Skip to content

test(winds): add deterministic T059 negative fixtures - #41

Merged
TheHalfMoon merged 1 commit into
mainfrom
test/003-t059-negative-fixtures
Aug 17, 2026
Merged

test(winds): add deterministic T059 negative fixtures#41
TheHalfMoon merged 1 commit into
mainfrom
test/003-t059-negative-fixtures

Conversation

@TheHalfMoon

@TheHalfMoon TheHalfMoon commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Spec 003 / T059

Adds the deterministic negative-fixture acceptance suite required by T059 on top of canonical main:

ef985b11f67241ae45c623c89ccd03eb18441a0f

Final exact candidate head:

d39549d3190a4e069d3313df2563f86ba999b78b

Scope

Tests only. The final tree changes exactly:

  • src/t059_negative_tests.rs — dedicated T059 negative acceptance suite
  • src/git.rs — three-line #[cfg(test)] module wiring only

No production runtime behavior, dependency, migration, workflow, schema, CLI, protocol, daemon, persistent-session, plugin/provider, MCP/ACP/A2A, Agent Fleet, Herdr/Pi, sandbox, or verification-authority behavior changes.

T059 fixture map

The suite explicitly exercises:

  1. missing / non-Git / bare workspace rejection before registration;
  2. invalid and broken symlinked-workspace rejection without registration;
  3. successful local credential-bearing file:// clone proving returned and SQLite-persisted remote identity strips user-info credentials without external network access;
  4. clone failure before workspace registration;
  5. disappearing shell executable rejected by launch-time validation;
  6. deterministic terminal start/exec failure after launch validation using an executable with an unavailable interpreter: the PTY backend may create the session successfully, but the failure must become an observed non-zero final exit, remain final on repeated observation, and never execute the script body;
  7. immediate terminal exit observed once and retained as final truth;
  8. 1 MiB output fully observed while transcript retention remains bounded to a 4 KiB per-session quota and 64 KiB total logical quota;
  9. .envrc, .mise.toml, and devcontainer manifest inventory proving no auto-execution and no manifest secret-value serialization.

Boundary to T060

This PR does not start T060. It does not introduce input/resize/exit races, SQLite fault injection, stale-PID/reuse fixtures, shell-hook spoofing, ownership-loss injection, or a generic fault-injection seam. A synthetic PTY allocator merely to force openpty failure is intentionally not introduced; the real child start/exec failure boundary is tested through the accepted backend semantics instead.

Exact-head acceptance evidence

On d39549d3190a4e069d3313df2563f86ba999b78b:

  • quality #370 — PASS on Ubuntu/macOS, including format, Clippy, and full tests;
  • windows-terminal #138 — PASS on official windows-latest; attempt 1 failed before checkout/project execution because GitHub codeload returned HTTP 503/429 while downloading the pinned Rust action, and only that failed job was rerun successfully on the unchanged exact head;
  • release-candidate #206 — PASS;
  • SC-001 controlled 100-cycle soak — PASS;
  • Linux x86_64 release build/bundle/artifact — PASS;
  • macOS arm64 release build/bundle/artifact — PASS;
  • exact-head correctness/safety/authority review — PASS;
  • exact-head Ponytail v4.9.0 simplicity review — PASS;
  • independent CodeRabbit exact-head review — COMPLETED / SUCCESS at 2026-08-17T15:03:30Z after the PR was Ready; this is distinct from the earlier draft-time status that explicitly said review skipped;
  • unresolved inline review threads — 0.

Qodo /review was additionally requested and acknowledged with an eyes reaction, but is not counted as acceptance evidence because no completed persistent result is currently available through the connector.

T059 remains unchecked in tasks.md until this accepted PR is merged with exact-head/unchanged-main guards and post-merge evidence is proven. T060+ remains not started.

Summary by CodeRabbit

  • Tests
    • Added comprehensive validation coverage for invalid workspaces, symbolic links, failed clones, and credential handling.
    • Added safety checks for unavailable shells and interpreters, terminal exit behavior, and session-history retention.
    • Verified large command output is fully observed while storage remains bounded.
    • Added checks ensuring environment inventories are collected without executing content or persisting secrets.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fe962211-ffa5-4e82-bbdf-b5a5372202a0

📥 Commits

Reviewing files that changed from the base of the PR and between ef985b1 and d39549d.

📒 Files selected for processing (2)
  • src/git.rs
  • src/t059_negative_tests.rs

📝 Walkthrough

Walkthrough

Added a test-only module with isolated fixtures and negative tests for workspace validation, Git cloning, shell and terminal failures, terminal-history retention, and environment-manifest inventory.

Changes

Negative behavior tests

Layer / File(s) Summary
Workspace and Git validation
src/git.rs, src/t059_negative_tests.rs
Registers the test module. Tests reject invalid workspace paths and symlinks before database registration. Clone tests verify sanitized remote identities and cleanup after failure.
Process and terminal failures
src/t059_negative_tests.rs
Tests unavailable executables, missing interpreters, startup failures, immediate exits, and stable final exit observations.
History and environment inventory
src/t059_negative_tests.rs
Tests bounded transcript retention while observing all output. Tests inventory manifests in sorted order without execution or secret persistence.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/003-t059-negative-fixtures

Comment @coderabbitai help to get the list of available commands.

@TheHalfMoon
TheHalfMoon force-pushed the test/003-t059-negative-fixtures branch from 3c2c551 to 9de6ffb Compare August 17, 2026 14:53
@TheHalfMoon
TheHalfMoon force-pushed the test/003-t059-negative-fixtures branch from cface77 to d39549d Compare August 17, 2026 14:56

@TheHalfMoon TheHalfMoon left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T059 exact-head correctness / safety / authority review — PASS

Reviewed exact head d39549d3190a4e069d3313df2563f86ba999b78b against canonical base ef985b11f67241ae45c623c89ccd03eb18441a0f and active Spec 003 / T059 only.

PASS rationale:

  • the final diff is tests-only: one dedicated T059 acceptance module plus #[cfg(test)] wiring; no production runtime or verification-authority behavior changes;
  • missing, non-Git, bare, invalid-symlink, and broken-symlink workspace fixtures fail before persistent workspace registration;
  • credential-bearing clone coverage uses a local file:// remote, requires successful cloning, and checks both returned and SQLite-persisted remote identity for user-info removal without external network dependence;
  • clone failure remains explicit and does not fabricate workspace registration;
  • disappearing shell executable is revalidated at launch time rather than trusting discovery-time identity;
  • the unavailable-interpreter fixture reflects the actual PTY backend boundary: launch validation succeeds, PTY/session creation may succeed, but the child exec/start failure must become an observed non-zero final exit, must stay final on repeated observation, and must not execute the script body; no false-success or falsely-live claim is accepted;
  • the separate immediate-exit fixture proves a normal explicit exit remains a single stable final result;
  • the large-output fixture consumes 1 MiB while retaining only the configured 4 KiB transcript and proving total transcript+manifest storage remains inside the configured 64 KiB quota with truthful complete/truncated metadata;
  • manifest inventory proves .envrc, .mise.toml, and devcontainer contents are not executed or serialized as secret values;
  • temp cleanup is ownership-scoped to a canonical system-temp descendant with a Winds-owned prefix;
  • Windows all-target compile/Clippy and the existing ConPTY/WSL/ledger/command suites remain green; Unix-only fixtures are explicitly cfg-gated;
  • no T060 race/fault injection, stale-PID simulation, SQLite fault injection, shell-marker spoofing, daemon/protocol/Fleet, or new security claim is introduced.

Deterministic exact-head evidence observed: quality #370 PASS, windows-terminal #138 PASS after an infrastructure-only initial codeload 503/429 retry on the unchanged head, and release-candidate #206 PASS including SC-001 100-cycle soak plus Linux/macOS release builds/artifacts.

No correctness, safety, authority, data-loss, or active-scope blocker found on this exact head.

@TheHalfMoon TheHalfMoon left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T059 exact-head Ponytail v4.9.0 simplicity review — PASS

Reviewed exact head d39549d3190a4e069d3313df2563f86ba999b78b for unnecessary implementation, abstraction, dependency, and future-scope leakage.

PASS rationale:

  • no production code path, dependency, schema, migration, workflow, CLI, service, protocol, plugin/provider, daemon, renderer, or runtime abstraction was added;
  • the suite reuses the already-accepted workspace, clone, shell-profile, PTY, history, and inventory seams directly rather than creating a new test framework;
  • one dedicated test module keeps T059 acceptance evidence coherent, while git.rs adds only #[cfg(test)] wiring;
  • the credential clone fixture is fully local and reuses system Git instead of introducing a mock transport/server;
  • the PTY start-failure fixture deliberately avoids a synthetic PTY allocator/fault-injection interface. It tests the real unavailable-interpreter start/exec boundary and accepts the backend's truthful immediate non-zero exit semantics rather than modifying production behavior to satisfy a test assumption;
  • generic allocator failure injection, concurrency races, SQLite failure injection, stale-PID simulation, and shell-hook spoof infrastructure are correctly left to T060 where the spec actually requires those fault surfaces;
  • existing tests are not duplicated wholesale: the T059 suite adds explicit cross-slice acceptance assertions, including persisted clone sanitization and bounded 1 MiB transcript behavior, while remaining tests-only;
  • platform-specific imports/helpers are cfg-gated only where necessary for Windows all-target compilation.

No justified simplification removes meaningful T059 evidence. No over-engineering blocker found on this exact head.

@TheHalfMoon
TheHalfMoon marked this pull request as ready for review August 17, 2026 15:02

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Please perform a fresh review of exact head d39549d3190a4e069d3313df2563f86ba999b78b for Spec 003 / T059 only.

Focus on deterministic fixture correctness, false-positive/false-success assertions, test cleanup/data safety, cross-platform compile assumptions, credential sanitization verification, PTY start/exec-failure truth, bounded-output assertions, and accidental T060+ scope leakage. The diff is tests-only and must not be treated as authorization for production runtime changes.

Copy link
Copy Markdown
Owner Author

/review

Review exact head d39549d3190a4e069d3313df2563f86ba999b78b for Spec 003 / T059 only. Please treat the diff as tests-only. Check fixture determinism, platform assumptions, safety of temp cleanup, credential-bearing clone sanitization assertions, PTY start/exec-failure semantics, bounded transcript assertions, and T060+ scope leakage.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add deterministic T059 negative-fixture acceptance tests

🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add a dedicated T059 negative acceptance suite covering workspace, clone, terminal, and inventory
 failures.
• Verify credential-bearing clone URLs are sanitized before persisting remote identity.
• Assert terminal exit/retention semantics and manifest inventory never auto-executes or serializes
 secrets.
Diagram

graph TD
  T["src/t059_negative_tests.rs"] --> W["workspace open/inspect"] --> DB[("winds.db")]
  T --> C["clone+register"] --> DB
  T --> Term["TerminalSession"]
  T --> Hist["SessionHistoryRecorder"] --> DB
  T --> Inv["env inventory"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move acceptance coverage to external integration tests (tests/ harness)
  • ➕ Exercises the crate as a black box (closer to real usage)
  • ➕ Avoids adding test-only module wiring in src/git.rs
  • ➖ Harder to reach internal APIs needed for deterministic fixtures without exposing more public surface
  • ➖ More brittle around platform differences (especially PTY/terminal paths)
2. Use tempfile::TempDir for deterministic cleanup
  • ➕ Less custom cleanup logic; clearer lifecycle management
  • ➕ Lower risk of accidental temp-dir removal edge cases
  • ➖ Adds/leans on an additional dev-dependency (if not already present)
  • ➖ Current cleanup already scopes to a strict prefix + canonical temp-dir check
3. Parameterize fixtures via a small internal test harness (table-driven tests)
  • ➕ Reduces repetition across workspace/clone/terminal negative cases
  • ➕ Easier to add future T06x cases consistently
  • ➖ May obscure the intent of each spec item vs. explicit named tests
  • ➖ Upfront refactor cost for mostly one-off acceptance scenarios

Recommendation: Current approach (in-crate, deterministic tests with explicit named cases) is appropriate because it can directly exercise internal workspace/terminal/history invariants without widening the public API. The small test-only module wiring in src/git.rs is a reasonable tradeoff for deterministic coverage. If the suite grows further (e.g., into T060), consider extracting a small table-driven harness to reduce repetition.

Files changed (2) +438 / -0

Tests (2) +438 / -0
git.rsWire in T059 negative test module under cfg(test) +3/-0

Wire in T059 negative test module under cfg(test)

• Adds a test-only module include for the new T059 negative-fixture suite. Production runtime behavior is unchanged because the module is only compiled in test builds.

src/git.rs

t059_negative_tests.rsAdd deterministic T059 negative acceptance fixtures +435/-0

Add deterministic T059 negative acceptance fixtures

• Introduces a dedicated test suite covering invalid/bare workspace rejection, symlinked workspace failure, clone failure non-registration, and credential stripping before persisting remote identity. Adds Unix-only terminal and history retention tests to assert final exit semantics and bounded transcript retention. Verifies environment manifest inventory detects known files without auto-executing them or serializing secret values.

src/t059_negative_tests.rs

@TheHalfMoon
TheHalfMoon merged commit 64b1a2e into main Aug 17, 2026
10 of 11 checks passed
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected='d39549d3190a4e069d3313df2563f86ba999b78b'
actual="$(git rev-parse HEAD)"
printf 'HEAD=%s\nEXPECTED=%s\n' "$actual" "$expected"
git status --short
git diff --name-status "${expected}^" "$expected"
git diff --stat "${expected}^" "$expected"
git diff --check "${expected}^" "$expected"
git diff --no-ext-diff --unified=80 "${expected}^" "$expected" -- src/t059_negative_tests.rs src/git.rs

printf '\n== Outline: T059 tests ==\n'
ast-grep outline src/t059_negative_tests.rs --items all --view expanded || true
printf '\n== Outline: git module ==\n'
ast-grep outline src/git.rs --items all --view expanded || true

printf '\n== Relevant declarations and test hooks ==\n'
rg -n -C 5 --glob '*.rs' \
  'pub\s+(async\s+)?fn\s+(register|launch|start|exec|observe|transcript|remote)|fn\s+(register|launch|start|exec|observe|transcript|remote)|cfg\(test\)|t059_negative_tests' \
  src

Length of output: 53999


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Package and target configuration =='
fd -a -t f '^(Cargo\.toml|rust-toolchain.*|AGENTS\.md)$' . -x sh -c 'echo "--- $1"; sed -n "1,260p" "$1"' sh {} \;

printf '%s\n' '== Terminal session lifecycle =='
sed -n '45,230p' src/terminal.rs
printf '%s\n' '== Terminal Unix backend and exit handling =='
rg -n -C 8 --glob '*.rs' \
  'fn (wait|try_wait|start_command|spawn)|impl TerminalSession|final_exit|exec|openpty|forkpty|waitpid' \
  src/terminal.rs src

printf '%s\n' '== Shell profile discovery and launch validation =='
sed -n '1,285p' src/shell_profiles.rs

printf '%s\n' '== Clone sanitization and registration order =='
sed -n '1,270p' src/workspace_clone.rs
printf '%s\n' '== Workspace registration validation =='
sed -n '1,260p' src/workspace.rs

printf '%s\n' '== History reader, persistence, and quota accounting =='
rg -n -C 10 --glob '*.rs' \
  'struct SessionHistoryRecorder|fn (wrap_output_reader|persist|local_bounded|history_logical_bytes|prune_for_write)|transcript_(observed|retained|capture_complete|truncated)|TOTAL|quota' \
  src/command/history.rs

printf '%s\n' '== Environment inventory behavior =='
sed -n '1,235p' src/workspace_inventory.rs

Length of output: 105836


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Manifest and target configuration files =='
fd -a -t f -g 'Cargo.toml' -g 'rust-toolchain*' -g 'AGENTS.md' . \
  -x sh -c 'echo "--- $1"; cat "$1"' sh {} \;

printf '%s\n' '== Exact new-test lines =='
nl -ba src/t059_negative_tests.rs | sed -n '1,460p'

printf '%s\n' '== Exact terminal session methods =='
nl -ba src/terminal.rs | sed -n '45,190p'
rg -n -A 70 -B 15 'pub fn wait\(|pub fn try_wait\(|fn wait\(|fn try_wait\(' src/terminal.rs

printf '%s\n' '== Platform-specific terminal backend boundaries =='
rg -n -A 100 -B 15 \
  'cfg\(unix\)|cfg\(windows\)|fn start_command|spawn|exec|forkpty|openpty|waitpid' \
  src/terminal.rs

printf '%s\n' '== New-test cfg/import consistency =='
rg -n '^\s*#\[cfg|^use |TerminalSession|SessionHistory|Connection|symlink|initialize_repo|create_executable' \
  src/t059_negative_tests.rs

printf '%s\n' '== Test module compilation topology =='
rg -n -C 3 'mod git|mod command|mod store|mod domain|mod execution|cfg\(test\)' src/lib.rs src/main.rs 2>/dev/null || true

printf '%s\n' '== Diff scope excludes production and T060 fault seams =='
git diff --no-ext-diff --name-only d39549d3190a4e069d3313df2563f86ba999b78b^ d39549d3190a4e069d3313df2563f86ba999b78b
git diff --no-ext-diff d39549d3190a4e069d3313df2563f86ba999b78b^ d39549d3190a4e069d3313df2563f86ba999b78b \
  | rg -n -i 'fault.inject|openpty|allocator|resize|stale.pid|reuse|ownership.loss|race|daemon|ipc|protocol|plugin|mcp|a2a|acp|sandbox' || true

Length of output: 2604


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Configuration files =='
for file in Cargo.toml rust-toolchain rust-toolchain.toml AGENTS.md; do
  if [ -f "$file" ]; then
    printf '%s\n' "--- $file"
    sed -n '1,320p' "$file"
  fi
done

printf '%s\n' '== Exact T059 test source with line numbers =='
awk '{printf "%6d  %s\n", NR, $0}' src/t059_negative_tests.rs

printf '%s\n' '== Terminal session lifecycle with line numbers =='
awk 'NR >= 45 && NR <= 240 {printf "%6d  %s\n", NR, $0}' src/terminal.rs
printf '%s\n' '== wait / try_wait definitions =='
rg -n -A 80 -B 12 'pub fn (wait|try_wait)\(' src/terminal.rs

printf '%s\n' '== Unix and Windows terminal backend sections =='
rg -n -A 130 -B 10 \
  '#\[cfg\((unix|windows)\)\]|fn start_command|forkpty|openpty|waitpid|exec' \
  src/terminal.rs

printf '%s\n' '== Root module topology =='
sed -n '1,240p' src/main.rs
printf '%s\n' '== New test cfg markers and platform-sensitive symbols =='
rg -n -C 2 \
  '#\[cfg|TerminalSession|SessionHistory|Connection|symlink|initialize_repo|create_executable' \
  src/t059_negative_tests.rs

printf '%s\n' '== Exact diff scope and T060 keyword scan =='
git diff --no-ext-diff --name-only d39549d3190a4e069d3313df2563f86ba999b78b^ d39549d3190a4e069d3313df2563f86ba999b78b
git diff --no-ext-diff d39549d3190a4e069d3313df2563f86ba999b78b^ d39549d3190a4e069d3313df2563f86ba999b78b \
  | rg -n -i 'fault.inject|allocator|resize|stale.pid|pid.reuse|ownership.loss|race|daemon|ipc|protocol|plugin|mcp|a2a|acp|sandbox' || true

Length of output: 68655


@TheHalfMoon Fresh review complete for exact head d39549d3190a4e069d3313df2563f86ba999b78b.

I found no blocking findings in the T059-only diff.

  • The diff is limited to src/t059_negative_tests.rs and test-only wiring in src/git.rs.
  • Unix-only fixtures and imports use #[cfg(unix)]. The remaining Git fixtures are platform-neutral.
  • The credential fixture verifies both the returned identity and the persisted SQLite remote_identity. It checks that user-info credentials are absent.
  • The PTY fixtures validate a non-zero final exit for the unavailable-interpreter case. They also verify cached final-exit truth through try_wait().
  • The bounded-output fixture verifies 1 MiB observed output, 4 KiB retained transcript data, truncation metadata, and a 64 KiB logical persistence bound.
  • The temporary-root cleanup requires a canonical path below the system temporary directory and an owned winds-t059- name before recursive removal.
  • I found no T060+ fault injection or production runtime scope leakage.

I used the repository workflow guidance that requires deterministic checks and a correctness/safety review. The sandbox did not execute repository code, so this result is a static review. The supplied exact-head CI evidence remains necessary for runtime validation.


🧠 Learnings used
Learnt from: CR
Repo: TheHalfMoon/Winds PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-16T04:36:23.042Z
Learning: 4. Run deterministic checks before requesting review.

Learnt from: CR
Repo: TheHalfMoon/Winds PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-16T04:36:23.042Z
Learning: 5. Run a correctness/safety review.

Learnt from: CR
Repo: TheHalfMoon/Winds PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-16T04:36:23.043Z
Learning: For 0.1 do not introduce a daemon, IPC/public runtime protocol, terminal emulator, generic runtime abstraction, Graphify/code graph, Jujutsu dependency, plugin system, MCP/A2A, port broker, service orchestration, broad sandbox framework, or AI reviewer in product code unless the active spec is explicitly amended first.
⚠️ Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant