diff --git a/.cortexkit/WORKER.md b/.cortexkit/WORKER.md index ab2bac7be6..583e23be61 100644 --- a/.cortexkit/WORKER.md +++ b/.cortexkit/WORKER.md @@ -6,17 +6,20 @@ A check that prints nothing and exits 0 is not a pass unless this guide says tha ## Rust (`crates/aft`, package `agent-file-tools`) +Integration suites require `--features test-hooks` explicitly. Lib-only tests do +not need it; production and release builds must never enable it. + | Gate | Command | Proof it ran | |---|---|---| | Format | `cargo fmt --all -- --check` | Silent on success. Show `cargo fmt --version` and exit 0. | -| Windows compile | `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu` | `Finished` line. Compile-only: it cannot catch Windows runtime failures. | +| Windows compile | `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu --features test-hooks` | `Finished` line. Compile-only: it cannot catch Windows runtime failures. | | Unit (lib) | `cargo test -p agent-file-tools --lib -- ` | `test result: ok. N passed` with N > 0. A filter that matches nothing reports `0 passed`, which is not a pass. | | Binary tests | `cargo test -p agent-file-tools --bin aft -- ` | Same as above. Shared infrastructure (locks, leases, capability gates, path identity) breaks fixtures here too. | -| Integration | `cargo test -p agent-file-tools --test integration -- ` | Same as above. | +| Integration | `cargo test --features test-hooks -p agent-file-tools --test integration -- ` | Same as above. | | Windows native tests | `bash scripts/windows-gate.sh --filter ` or `cargo test -p agent-file-tools --lib -- ` | Run with `runon: "windows"`. The Windows job snapshots tracked and untracked files, but not ignored files. A gate filter that runs zero tests fails. | -| Other test targets | `--test engine`, `--test list_envelope`, `--test rest`, `--test semantic`, `--test alert`, `--test watcher_integration` | Same as above. | +| Other test targets | `--test engine`, `--test list_envelope`, `--test rest`, `--test semantic`, `--test alert`, `--test watcher_integration`, with `--features test-hooks` | Same as above. | | Real rust-analyzer | prefix with `AFT_TEST_REQUIRE_RUST_ANALYZER=1` | Without it, real-server tests skip silently. | -| Full suite | `cargo test -p agent-file-tools`, or `scripts/rust-test-gate.sh` | The gate prints `GATE PASSED` / `GATE FAILED` as its last line. | +| Full suite | `cargo test --features test-hooks -p agent-file-tools`, or `scripts/rust-test-gate.sh` | The gate prints `GATE PASSED` / `GATE FAILED` as its last line. | ### Build server jobs (`runon`) @@ -27,10 +30,10 @@ A check that prints nothing and exits 0 is not a pass unless this guide says tha - **Build a scratch copy of the source with its own target folder.** Linux jobs share the checkout's warm build folder (`CARGO_TARGET_DIR=/run/motor/target`). A copy built there, for example a red-first proof under `$TMPDIR`, leaves its outputs where later jobs in the real checkout reuse them as current, so a gate can pass on old code. Give the copy `CARGO_TARGET_DIR=$TMPDIR/copy-target` or `--target-dir`. If it already happened, `cargo clean -p ` repairs it. Mandatory when you touch them: -- A list-cutting site (`.take(`, `truncate(`, a cap): register it, then run `cargo test -p agent-file-tools --test list_envelope`. -- A new file under the search engine: register its owner, then run `cargo test -p agent-file-tools --test engine`. +- A list-cutting site (`.take(`, `truncate(`, a cap): register it, then run `cargo test --features test-hooks -p agent-file-tools --test list_envelope`. +- A new file under the search engine: register its owner, then run `cargo test --features test-hooks -p agent-file-tools --test engine`. - An agent tool argument: regenerate with `bun run --cwd packages/opencode-plugin build:tool-schemas`. The committed `crates/aft/src/subc_tool_schemas.json` must match byte for byte. -- Config keys or the resolver: run `bun scripts/capture-config-parity.ts` (zero diff), then `cargo test -p agent-file-tools --test integration config_parity`. +- Config keys or the resolver: run `bun scripts/capture-config-parity.ts` (zero diff), then `cargo test --features test-hooks -p agent-file-tools --test integration config_parity`. - Search ranking or routing files (the `RANKING_FENCE_PREFIXES` in `benchmarks/aft-search/search_quality_lib.py`): say so in your report. The train needs a search-quality descriptor, and ranking changes need benchmark evidence. ## TypeScript (`packages/*`) diff --git a/.github/actions/storm-suite/action.yml b/.github/actions/storm-suite/action.yml index 3a61b7a7c9..01ee41f0a4 100644 --- a/.github/actions/storm-suite/action.yml +++ b/.github/actions/storm-suite/action.yml @@ -5,17 +5,17 @@ runs: steps: - name: Build calibrated storm harness with compiler timings shell: bash - run: cargo test --profile ci-storm --locked -p agent-file-tools --test integration --no-run --timings + run: cargo test --features test-hooks --profile ci-storm --locked -p agent-file-tools --test integration --no-run --timings - name: Require every calibrated storm case shell: bash run: | - cargo nextest list --profile default --cargo-profile ci-storm --locked -p agent-file-tools --test integration -E 'test(subc_storm)' -T json > target/storm-inventory.json + cargo nextest list --features test-hooks --profile default --cargo-profile ci-storm --locked -p agent-file-tools --test integration -E 'test(subc_storm)' -T json > target/storm-inventory.json python3 scripts/ci-storm-inventory.py --check-inventory target/storm-inventory.json - name: Run all calibrated storm tests shell: bash - run: cargo nextest run --no-fail-fast --profile default --cargo-profile ci-storm --locked -p agent-file-tools --test integration -E 'test(subc_storm)' + run: cargo nextest run --no-fail-fast --features test-hooks --profile default --cargo-profile ci-storm --locked -p agent-file-tools --test integration -E 'test(subc_storm)' - name: Retain storm compiler timings and inventory if: always() diff --git a/.github/workflows/_unit-suite.yml b/.github/workflows/_unit-suite.yml index 65c0faf43a..5951d317cd 100644 --- a/.github/workflows/_unit-suite.yml +++ b/.github/workflows/_unit-suite.yml @@ -79,7 +79,7 @@ jobs: - uses: ./.github/actions/setup-nextest - name: Build nextest archive (Linux Rust suite) - run: cargo nextest archive --workspace -E '(kind(lib) | kind(bin) | kind(test)) - binary(=watcher_integration)' --archive-file "$LINUX_NEXTEST_ARCHIVE" + run: cargo nextest archive --features test-hooks --workspace -E '(kind(lib) | kind(bin) | kind(test)) - binary(=watcher_integration)' --archive-file "$LINUX_NEXTEST_ARCHIVE" env: LINUX_NEXTEST_ARCHIVE: ${{ runner.temp }}/linux-nextest.tar.zst @@ -468,17 +468,17 @@ jobs: run: cargo build -p agent-file-tools --bin aft - name: Run worker broker host policy and rendered socket rule regressions run: | - cargo test -p agent-file-tools --lib -- gh_shim --test-threads=1 - binary_listing="$(cargo test -p agent-file-tools --bin aft -- --list)" + cargo test -p agent-file-tools --features test-hooks --lib -- gh_shim --test-threads=1 + binary_listing="$(cargo test -p agent-file-tools --features test-hooks --bin aft -- --list)" [[ "$binary_listing" == *"gh_shim_broker_seatbelt_root_uses_the_shared_namespace_definition: test"* ]] - cargo test -p agent-file-tools --bin aft -- gh_shim_broker_seatbelt_root_uses_the_shared_namespace_definition --test-threads=1 + cargo test -p agent-file-tools --features test-hooks --bin aft -- gh_shim_broker_seatbelt_root_uses_the_shared_namespace_definition --test-threads=1 - name: Require worker-read test inventory and run the native gate shell: bash run: | set -euo pipefail unset AFT_TEST_AFT_BINARY NEXTEST_BIN_EXE_aft CARGO_BIN_EXE_aft cargo --version - listing="$(cargo test -p agent-file-tools --test worker_jail -- --list)" + listing="$(cargo test --features test-hooks -p agent-file-tools --test worker_jail -- --list)" printf '%s\n' "$listing" for test in \ gh_shim_router_host_read_uses_served_catalog_arguments \ @@ -498,16 +498,16 @@ jobs: worker_jail_temp_denies_other_task_directory; do [[ "$listing" == *"$test: test"* ]] || { printf 'missing native test: %s\n' "$test" >&2; exit 1; } done - cargo test -p agent-file-tools --test worker_jail -- gh_shim_router_host --test-threads=1 --nocapture - cargo test -p agent-file-tools --test worker_jail -- worker_gh_read --test-threads=1 --nocapture - cargo test -p agent-file-tools --test worker_jail -- worker_jail_temp_denies_other_task_directory --exact --test-threads=1 --nocapture - probe_listing="$(cargo test -p agent-file-tools --test sandbox_launch_probe -- --list)" + cargo test --features test-hooks -p agent-file-tools --test worker_jail -- gh_shim_router_host --test-threads=1 --nocapture + cargo test --features test-hooks -p agent-file-tools --test worker_jail -- worker_gh_read --test-threads=1 --nocapture + cargo test --features test-hooks -p agent-file-tools --test worker_jail -- worker_jail_temp_denies_other_task_directory --exact --test-threads=1 --nocapture + probe_listing="$(cargo test --features test-hooks -p agent-file-tools --test sandbox_launch_probe -- --list)" [[ "$probe_listing" == *"launcher_closes_late_inherited_listener_above_marker_slots: test"* ]] [[ "$probe_listing" == *"launcher_fd_probe_required_mode_cannot_silently_skip: test"* ]] [[ "$probe_listing" == *"launcher_failure_marker_cannot_be_forged_by_jailed_exec: test"* ]] - cargo test -p agent-file-tools --test sandbox_launch_probe -- launcher_closes_late_inherited_listener_above_marker_slots --exact --test-threads=1 --nocapture - cargo test -p agent-file-tools --test sandbox_launch_probe -- launcher_fd_probe_required_mode_cannot_silently_skip --exact --test-threads=1 --nocapture - cargo test -p agent-file-tools --test sandbox_launch_probe -- launcher_failure_marker_cannot_be_forged_by_jailed_exec --exact --test-threads=1 --nocapture + cargo test --features test-hooks -p agent-file-tools --test sandbox_launch_probe -- launcher_closes_late_inherited_listener_above_marker_slots --exact --test-threads=1 --nocapture + cargo test --features test-hooks -p agent-file-tools --test sandbox_launch_probe -- launcher_fd_probe_required_mode_cannot_silently_skip --exact --test-threads=1 --nocapture + cargo test --features test-hooks -p agent-file-tools --test sandbox_launch_probe -- launcher_failure_marker_cannot_be_forged_by_jailed_exec --exact --test-threads=1 --nocapture # --------------------------------------------------------------------------- # Real-kernel Landlock probes. This stays separate from the general unit lane @@ -533,7 +533,7 @@ jobs: run: cargo build -p agent-file-tools --bin aft - name: Run sandbox launch probes - run: cargo test -p agent-file-tools --test sandbox_launch_probe -- --test-threads=1 --nocapture + run: cargo test --features test-hooks -p agent-file-tools --test sandbox_launch_probe -- --test-threads=1 --nocapture env: AFT_REQUIRE_LANDLOCK: "1" @@ -543,7 +543,7 @@ jobs: set -euo pipefail cargo --version test_name="bash_reply_timing_contract_test::subc_promoted_foreground_is_killed_at_its_timeout" - if ! listing="$(cargo test --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --list 2>&1)"; then + if ! listing="$(cargo test --features test-hooks --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --list 2>&1)"; then printf '%s\n' "$listing" >&2 exit 1 fi @@ -552,7 +552,7 @@ jobs: printf 'expected test missing from integration inventory: %s\n' "$test_name" >&2 exit 1 fi - cargo test --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --exact + cargo test --features test-hooks --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --exact # --------------------------------------------------------------------------- # Release-calibrated storm latency on a dedicated free Linux runner. The @@ -653,8 +653,12 @@ jobs: cache-on-failure: true save-if: ${{ github.ref == 'refs/heads/main' }} + # Library and binaries as shipped (no test hooks), then every target + # with the hooks the test suites need. - name: Cargo check (locked, MSRV floor) - run: cargo check --workspace --all-targets --locked + run: | + cargo check --workspace --lib --bins --locked + cargo check --workspace --all-targets --features test-hooks --locked # --------------------------------------------------------------------------- # Rust + plugin tests on macOS @@ -778,7 +782,7 @@ jobs: started=$SECONDS trap 'printf "### macOS libtest archive\n\nRunner: macos-26 (%s)\n\nBuild duration: %ss\n" "$RUNNER_NAME" "$((SECONDS - started))" >> "$GITHUB_STEP_SUMMARY"' EXIT # Native time reports resident-memory and paging counters for the build. - /usr/bin/time -l cargo nextest archive --workspace --lib --test sandbox_launch_probe -E 'kind(lib)' --config "$LIBTEST_CARGO_CONFIG" --timings --archive-file "$MACOS_LIBTEST_ARCHIVE" + /usr/bin/time -l cargo nextest archive --features test-hooks --workspace --lib --test sandbox_launch_probe -E 'kind(lib)' --config "$LIBTEST_CARGO_CONFIG" --timings --archive-file "$MACOS_LIBTEST_ARCHIVE" env: MACOS_LIBTEST_ARCHIVE: ${{ runner.temp }}/macos-libtest-nextest.tar.zst @@ -793,10 +797,10 @@ jobs: if-no-files-found: error - name: Run the serial backtrace probe with local debug objects - run: cargo test -p agent-file-tools --lib panic_hook_preserves_default_backtrace_behavior_and_persists --config "$LIBTEST_CARGO_CONFIG" + run: cargo test -p agent-file-tools --features test-hooks --lib panic_hook_preserves_default_backtrace_behavior_and_persists --config "$LIBTEST_CARGO_CONFIG" - name: Capture lib source inventory - run: cargo nextest list --workspace --lib --profile gate -T json --cargo-quiet --config "$LIBTEST_CARGO_CONFIG" > "$RUNNER_TEMP/macos-libtest-inventory.json" + run: cargo nextest list --workspace --lib --features test-hooks --profile gate -T json --cargo-quiet --config "$LIBTEST_CARGO_CONFIG" > "$RUNNER_TEMP/macos-libtest-inventory.json" - name: Report macOS libtest archive size run: | @@ -847,12 +851,12 @@ jobs: - name: Build nextest archive (macOS bin tests) # Keep the real CLI alongside the binary test harness without compiling # the unrelated library harnesses and integration suite. - run: cargo nextest archive --workspace --bins --test sandbox_launch_probe -E 'kind(bin)' --archive-file "$MACOS_BIN_ARCHIVE" + run: cargo nextest archive --features test-hooks --workspace --bins --test sandbox_launch_probe -E 'kind(bin)' --archive-file "$MACOS_BIN_ARCHIVE" env: MACOS_BIN_ARCHIVE: ${{ runner.temp }}/macos-bin-nextest.tar.zst - name: Capture bin source inventory - run: cargo nextest list --workspace --bins --profile gate -T json --cargo-quiet > "$RUNNER_TEMP/macos-bin-inventory.json" + run: cargo nextest list --workspace --bins --features test-hooks --profile gate -T json --cargo-quiet > "$RUNNER_TEMP/macos-bin-inventory.json" - name: Report macOS bin archive size run: | @@ -1110,7 +1114,7 @@ jobs: - uses: ./.github/actions/setup-nextest - name: Capture watcher inventory for the split proof - run: cargo test -p agent-file-tools --features test-timing-hooks --test watcher_integration -- --list > "$RUNNER_TEMP/macos-watcher-inventory.txt" 2>&1 + run: cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test watcher_integration -- --list > "$RUNNER_TEMP/macos-watcher-inventory.txt" 2>&1 env: CARGO_TERM_COLOR: never @@ -1218,7 +1222,7 @@ jobs: set -euo pipefail cargo --version test_name="bash_reply_timing_contract_test::subc_promoted_foreground_is_killed_at_its_timeout" - if ! listing="$(cargo test --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --list 2>&1)"; then + if ! listing="$(cargo test --features test-hooks --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --list 2>&1)"; then printf '%s\n' "$listing" >&2 exit 1 fi @@ -1227,7 +1231,7 @@ jobs: printf 'expected test missing from integration inventory: %s\n' "$test_name" >&2 exit 1 fi - cargo test --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --exact + cargo test --features test-hooks --locked -p agent-file-tools --features test-timing-hooks --test integration "$test_name" -- --exact - name: Fetch pinned subc-core id: subc_core @@ -1288,7 +1292,7 @@ jobs: - uses: ./.github/actions/setup-nextest - name: Build nextest archive (Windows Rust suite) - run: cargo nextest archive --workspace -E "(kind(lib) | kind(bin) | kind(test)) - binary(=watcher_integration)" --archive-file "$env:WINDOWS_NEXTEST_ARCHIVE" + run: cargo nextest archive --features test-hooks --workspace -E "(kind(lib) | kind(bin) | kind(test)) - binary(=watcher_integration)" --archive-file "$env:WINDOWS_NEXTEST_ARCHIVE" shell: pwsh env: WINDOWS_NEXTEST_ARCHIVE: ${{ runner.temp }}/windows-nextest.tar.zst @@ -1530,14 +1534,21 @@ jobs: cache-on-failure: true save-if: ${{ github.ref == 'refs/heads/main' }} + # Library and binaries as shipped (no test hooks), then every target + # with the hooks the test suites need. pwsh doesn't stop on a failing + # native command, so each one checks its own exit code. - name: Cargo check (deny warnings) - run: cargo check --workspace --all-targets + run: | + cargo check --workspace --lib --bins + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + cargo check --workspace --all-targets --features test-hooks + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } shell: pwsh env: RUSTFLAGS: "-D warnings" - name: Check feature-enabled provider conformance (deny warnings) - run: cargo check -p agent-file-tools --features test-timing-hooks --test rest + run: cargo check -p agent-file-tools --features test-hooks --features test-timing-hooks --test rest shell: pwsh env: RUSTFLAGS: "-D warnings" diff --git a/.github/workflows/cost-gate.yml b/.github/workflows/cost-gate.yml index 5c78a1a7ec..e6efee65cd 100644 --- a/.github/workflows/cost-gate.yml +++ b/.github/workflows/cost-gate.yml @@ -58,7 +58,7 @@ jobs: - name: Run original stress volumes shell: bash run: >- - cargo test -p agent-file-tools --lib -- + cargo test -p agent-file-tools --features test-hooks --lib -- views_incremental_random_sequences_equal_full_rebuild tool_result_fixtures_release_descriptors bash_changed_files_flush_native_no_false_complete_during_50k_activity diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2913e6f11..ff34185c20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,3 +30,11 @@ Typo-class fixes do not need an issue. Open the PR; a maintainer applies the ## Before you push Run `bun run format` and `cargo fmt`. CI rejects unformatted code. + +## Rust test hooks + +Pass `--features test-hooks` when building or running integration tests, including +`cargo test --features test-hooks -p agent-file-tools`. The integration and rest +harnesses fail at compile time without it rather than silently skipping tests. +Lib-only tests (`cargo test -p agent-file-tools --lib`) do not need the feature. +Never enable `test-hooks` for a production or release build. diff --git a/Cargo.lock b/Cargo.lock index ea451463b5..1033735d27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,6 @@ version = "0.63.4" dependencies = [ "aft-secret-rules", "aft-tokenizer", - "agent-file-tools", "apollo-parser", "ast-grep-core", "async-compression", diff --git a/benchmarks/aft-search/slice-descriptors/land-test-hooks-feature.json b/benchmarks/aft-search/slice-descriptors/land-test-hooks-feature.json new file mode 100644 index 0000000000..ebd574711e --- /dev/null +++ b/benchmarks/aft-search/slice-descriptors/land-test-hooks-feature.json @@ -0,0 +1,8 @@ +{ + "targeted_mechanism": "none", + "kind": "harness", + "slice_class": "non_ranking", + "fixtures": [ + "harness-goldens" + ] +} diff --git a/crates/aft/Cargo.toml b/crates/aft/Cargo.toml index 605ac6391b..dbf24bfbe2 100644 --- a/crates/aft/Cargo.toml +++ b/crates/aft/Cargo.toml @@ -110,10 +110,9 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(aft_views_lazy_benchmark)' test-scope-owner = [] # Explicit opt-in for cross-process timing controls used by integration tests. test-timing-hooks = [] -# In-process integration fixtures need the real binary for native re-exec. -test-sandbox-launcher = [] -# Deterministic producer inputs for real-wire conformance fixtures, never production. -test-conformance-result-inputs = [] +# Opt-in integration hooks for native re-exec and deterministic conformance inputs; +# never enable these hooks in production builds. +test-hooks = [] # Compiles the test-only secret vault (V5). Nothing in the product reads it: # a release profile must never enable it, and # `scripts/check-secret-test-fake.sh` fails CI when one does. @@ -299,8 +298,6 @@ windows-sys = { version = "0.61", features = [ ] } [dev-dependencies] -# Enable the launcher seam only in test builds, not ordinary aft binaries. -agent-file-tools = { path = ".", features = ["test-sandbox-launcher", "test-conformance-result-inputs"] } graphql-parser = "0.4.1" cortexkit-role-tool-provider-conformance = "=0.15.4" cortexkit-role-tool-provider = { version = "=0.15.4", features = ["test-vectors"] } diff --git a/crates/aft/src/commands/status.rs b/crates/aft/src/commands/status.rs index 3b96057c96..9180096589 100644 --- a/crates/aft/src/commands/status.rs +++ b/crates/aft/src/commands/status.rs @@ -108,7 +108,7 @@ pub fn handle_status(req: &RawRequest, ctx: &AppContext) -> Response { } // Integration fixtures pin only the unpredictable producer input. Formatting // and legacy/result-body serialization below the handler remain unchanged. - #[cfg(feature = "test-conformance-result-inputs")] + #[cfg(feature = "test-hooks")] if let Ok(input) = std::env::var("AFT_TEST_CONFORMANCE_STATUS_SNAPSHOT") { snapshot = serde_json::from_str(&input).expect("conformance status snapshot is JSON"); } diff --git a/crates/aft/src/sandbox_spawn.rs b/crates/aft/src/sandbox_spawn.rs index fcf2362026..81da4bb26b 100644 --- a/crates/aft/src/sandbox_spawn.rs +++ b/crates/aft/src/sandbox_spawn.rs @@ -753,7 +753,7 @@ pub struct SandboxSpawnObservation { static TEST_OBSERVATIONS: OnceLock>>> = OnceLock::new(); -#[cfg(all(unix, any(test, feature = "test-sandbox-launcher")))] +#[cfg(all(unix, any(test, feature = "test-hooks")))] static TEST_LAUNCHERS: OnceLock>> = OnceLock::new(); thread_local! { @@ -5621,7 +5621,7 @@ fn observation_key(project_root: &Path) -> PathBuf { #[cfg(unix)] fn native_launcher_path(ctx: &AppContext) -> std::io::Result { - #[cfg(any(test, feature = "test-sandbox-launcher"))] + #[cfg(any(test, feature = "test-hooks"))] if let Some(launchers) = TEST_LAUNCHERS.get() { if let Some(root) = ctx.config().project_root.as_deref() { if let Some(path) = launchers @@ -5640,7 +5640,7 @@ fn native_launcher_path(ctx: &AppContext) -> std::io::Result { /// Use the real aft executable for an in-process integration fixture. The test /// harness cannot re-exec itself as `aft sandbox-launch`; it only accepts libtest /// arguments. Only executable selection changes, not the native sandbox policy. -#[cfg(all(unix, any(test, feature = "test-sandbox-launcher")))] +#[cfg(all(unix, any(test, feature = "test-hooks")))] #[doc(hidden)] pub fn install_sandbox_launcher_for_test(project_root: &Path, launcher_path: PathBuf) -> impl Drop { struct LauncherScope(PathBuf, Option); diff --git a/crates/aft/src/subc/mod.rs b/crates/aft/src/subc/mod.rs index 501c593f54..16be2c006e 100644 --- a/crates/aft/src/subc/mod.rs +++ b/crates/aft/src/subc/mod.rs @@ -11575,7 +11575,7 @@ async fn handle_tool_call_with_capabilities( // Pin the response ID only for the fixture's exact probe inputs. Other // calls and frame correlation keep their ordinary identities; all native // handlers, formatters and wire rendering still run unchanged. - #[cfg(feature = "test-conformance-result-inputs")] + #[cfg(feature = "test-hooks")] let request_id = if std::env::var("AFT_TEST_CONFORMANCE_RESPONSE_ID") .ok() .and_then(|input| serde_json::from_str::(&input).ok()) diff --git a/crates/aft/src/subc/push.rs b/crates/aft/src/subc/push.rs index b0b6c92b3f..411c4564d0 100644 --- a/crates/aft/src/subc/push.rs +++ b/crates/aft/src/subc/push.rs @@ -1912,7 +1912,10 @@ mod tests { Instant::now() + Duration::from_secs(10), ); } - let done = tokio::time::timeout(Duration::from_secs(10), done_rx.recv()) + // Both waits below return as soon as their frame arrives. The 30 s + // bounds are for loaded Windows CI runners, where spawning the shell + // and its completion frame has taken over 10 s. + let done = tokio::time::timeout(Duration::from_secs(30), done_rx.recv()) .await .unwrap() .unwrap(); @@ -1923,7 +1926,7 @@ mod tests { .expect("background task id") .to_string(); let completion = loop { - let frame = tokio::time::timeout(Duration::from_secs(10), notice_rx.recv()) + let frame = tokio::time::timeout(Duration::from_secs(30), notice_rx.recv()) .await .unwrap() .expect("background completion"); diff --git a/crates/aft/src/subc/wire.rs b/crates/aft/src/subc/wire.rs index 3be48d91b1..f1f95d9365 100644 --- a/crates/aft/src/subc/wire.rs +++ b/crates/aft/src/subc/wire.rs @@ -1025,9 +1025,9 @@ fn serialize_tool_response_body_with_text( let response_id = data.and_then(|data| data.get("id")); // Early orchestration errors have no native dispatch. Pin only their // outgoing ID too; the remaining legacy/result body is serialized normally. - #[cfg(feature = "test-conformance-result-inputs")] + #[cfg(feature = "test-hooks")] let fixture_id = serde_json::json!("conformance-result-probe"); - #[cfg(feature = "test-conformance-result-inputs")] + #[cfg(feature = "test-hooks")] let response_id = if std::env::var_os("AFT_TEST_CONFORMANCE_RESPONSE_ID").is_some() { Some(&fixture_id) } else { diff --git a/crates/aft/tests/fixtures/agent_data/agent-sessions-v1/README.md b/crates/aft/tests/fixtures/agent_data/agent-sessions-v1/README.md index 7d2d044f7f..d894b0d463 100644 --- a/crates/aft/tests/fixtures/agent_data/agent-sessions-v1/README.md +++ b/crates/aft/tests/fixtures/agent_data/agent-sessions-v1/README.md @@ -211,9 +211,9 @@ a backfill makes the data local. From the repository root, generate the vector files with: ```sh -ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --locked session_records_match_published_files -- --nocapture -ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --locked session_lifecycle_records_match_published_files -- --nocapture -ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --locked session_rekey_records_match_published_files -- --nocapture +ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --features test-hooks --locked session_records_match_published_files -- --nocapture +ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --features test-hooks --locked session_lifecycle_records_match_published_files -- --nocapture +ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --features test-hooks --locked session_rekey_records_match_published_files -- --nocapture ``` Refresh their hashes from the repository root with: diff --git a/crates/aft/tests/fixtures/agent_data/project-resolve-v1/README.md b/crates/aft/tests/fixtures/agent_data/project-resolve-v1/README.md index 19c8ce386f..dca8913373 100644 --- a/crates/aft/tests/fixtures/agent_data/project-resolve-v1/README.md +++ b/crates/aft/tests/fixtures/agent_data/project-resolve-v1/README.md @@ -67,7 +67,7 @@ The implicit path id `pj-implicit1-30f9d5fcd6aa4ef2` demonstrates the derivation From the repository root, regenerate the vector files from the real handler with: ```sh -ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --locked project_resolve_ -- --nocapture +ENTO_WRITE_SERVED_VECTORS=1 cargo test --workspace --all-targets --features test-hooks --locked project_resolve_ -- --nocapture ``` Refresh the `project-resolve-v1` manifest from the repository root with: @@ -87,5 +87,5 @@ PY Without `ENTO_WRITE_SERVED_VECTORS=1`, the non-ignored `served_vectors::project_resolve_v1_records_match_published_files` and `served_vectors::project_resolve_remote_v1_records_match_published_file` tests regenerate all five files from entorhinal's real request handling and compare each file byte for byte. Both tests also run under nextest: ```sh -cargo nextest run --workspace --all-targets --locked -E 'test(served_vectors::project_resolve_)' +cargo nextest run --workspace --all-targets --features test-hooks --locked -E 'test(served_vectors::project_resolve_)' ``` diff --git a/crates/aft/tests/fixtures/tool_provider_legacy_replies.json b/crates/aft/tests/fixtures/tool_provider_legacy_replies.json index 6ab8234f29..596605e141 100644 --- a/crates/aft/tests/fixtures/tool_provider_legacy_replies.json +++ b/crates/aft/tests/fixtures/tool_provider_legacy_replies.json @@ -8,7 +8,7 @@ }, "binary_sha256": "d4481e723c9ecd4b3844c583fa61a892b2b1e65b62f55d65e1bb74198d5a424a", "rustc": "rustc 1.99.0 (b940084d7 2026-09-28)", - "profile": "debug, test-conformance-result-inputs", + "profile": "debug, test-hooks", "normalization": "only the disposable project root is replaced with {PROJECT}; status snapshot and response id are fixed producer inputs", "fixture_project_sha256": "76855e7de25ca208e6d1a449ff591bf5898ec8822021c651aea67fad50e0f58f", "status_snapshot": { diff --git a/crates/aft/tests/integration/main.rs b/crates/aft/tests/integration/main.rs index 446a7dffcb..44a0b97bf1 100644 --- a/crates/aft/tests/integration/main.rs +++ b/crates/aft/tests/integration/main.rs @@ -1,3 +1,6 @@ +#[cfg(not(feature = "test-hooks"))] +compile_error!("the integration test suite requires --features test-hooks"); + #[path = "../helpers/context_storage.rs"] mod context_storage; mod context_storage_test; diff --git a/crates/aft/tests/rest/main.rs b/crates/aft/tests/rest/main.rs index 2b6853cb36..ef887adc53 100644 --- a/crates/aft/tests/rest/main.rs +++ b/crates/aft/tests/rest/main.rs @@ -1,3 +1,6 @@ +#[cfg(not(feature = "test-hooks"))] +compile_error!("the rest test suite requires --features test-hooks"); + // Import `test_helpers` from `callgraph_store_test` rather than compiling a #[path = "../helpers/context_storage.rs"] mod context_storage; diff --git a/crates/aft/tests/tool_provider_conformance.rs b/crates/aft/tests/tool_provider_conformance.rs index cfad784f65..5a437892d2 100644 --- a/crates/aft/tests/tool_provider_conformance.rs +++ b/crates/aft/tests/tool_provider_conformance.rs @@ -3758,7 +3758,7 @@ async fn regenerate_pre_flip_legacy_replies() { let body: Value = serde_json::from_slice(&frame.body).unwrap(); assert_eq!( body["structuredContent"]["id"], "conformance-result-probe", - "build the fixture binary with test-conformance-result-inputs" + "build the fixture binary with test-hooks" ); let mut snapshot = body["structuredContent"].clone(); for key in ["id", "success", "text"] { @@ -3774,7 +3774,7 @@ async fn regenerate_pre_flip_legacy_replies() { }, "binary_sha256":format!("{:x}", Sha256::digest(std::fs::read(aft_binary::aft_binary()).unwrap())), "rustc":String::from_utf8(Command::new("rustc").arg("--version").output().unwrap().stdout).unwrap().trim(), - "profile":"debug, test-conformance-result-inputs", + "profile":"debug, test-hooks", "normalization":"only the disposable project root is replaced with {PROJECT}; status snapshot and response id are fixed producer inputs", "fixture_project_sha256":format!("{:x}", Sha256::digest(std::fs::read(root.path().join("project/.cortexkit/aft.jsonc")).unwrap())), "status_snapshot":fixed_status_values(snapshot), diff --git a/docs/design/durability-per-store.md b/docs/design/durability-per-store.md index 297abad4a4..b2ab5ab859 100644 --- a/docs/design/durability-per-store.md +++ b/docs/design/durability-per-store.md @@ -124,7 +124,7 @@ tests: Rerun: ``` -AFT_DURABILITY_CENSUS_OUT=/tmp/census cargo test -p agent-file-tools --test integration -- \ +AFT_DURABILITY_CENSUS_OUT=/tmp/census cargo test --features test-hooks -p agent-file-tools --test integration -- \ durability_census --ignored --nocapture --test-threads=1 ``` diff --git a/docs/development-storage.md b/docs/development-storage.md index f5fd8c75bf..6947a096ea 100644 --- a/docs/development-storage.md +++ b/docs/development-storage.md @@ -17,7 +17,8 @@ lookup, rather than panicking or permitting the write. Symlink aliases and not-yet-created descendants are checked against every protected root. Debug assertions identify the builds that tests and development rigs normally -run: plain `cargo test` and the `target/debug/aft` children spawned by Bun tests. +run: `cargo test --features test-hooks` and the `target/debug/aft` children spawned +by Bun tests. Those builds cannot write the account's production store by default. The fence uses `cfg!(debug_assertions)` directly; it does not require a release-card feature, a compile-time environment marker, or a packaging-specific build path. diff --git a/docs/diagnostics/search-prose-views.md b/docs/diagnostics/search-prose-views.md index 67bddf85ff..79825f5995 100644 --- a/docs/diagnostics/search-prose-views.md +++ b/docs/diagnostics/search-prose-views.md @@ -253,7 +253,7 @@ The continuation's required gates pass on Rust/cargo 1.99.0 and Python 3.9.6: 116 tests (one Windows-only case skipped). - `cargo test -p agent-file-tools --lib -- semantic_search migration views`: 503 passed, 12 ignored; child fixtures also passed. -- `cargo test -p agent-file-tools --test integration per_checkout_semantic_runtime`: +- `cargo test --features test-hooks -p agent-file-tools --test integration per_checkout_semantic_runtime`: six passed. - `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu`: finished successfully (compile-only, not Windows runtime execution). diff --git a/docs/investigations/bash-sandbox-compression-perf.md b/docs/investigations/bash-sandbox-compression-perf.md index 024b4cbfd0..cec66bc1c6 100644 --- a/docs/investigations/bash-sandbox-compression-perf.md +++ b/docs/investigations/bash-sandbox-compression-perf.md @@ -139,8 +139,8 @@ Tool versions: `cargo 1.99.0 (5f94df478 2026-08-27)`, | --- | --- | | `cargo test -p agent-file-tools --lib -- bash_background::` | 140 passed, 0 failed. | | `cargo test -p agent-file-tools --lib -- sandbox_` | 40 passed, 0 failed (includes 5 profile tests). | -| `cargo test -p agent-file-tools --test integration -- bash` | 326 passed, 0 failed, 1 ignored. | -| `cargo test -p agent-file-tools --test integration -- sandbox` | 6 passed, 0 failed. | +| `cargo test --features test-hooks -p agent-file-tools --test integration -- bash` | 326 passed, 0 failed, 1 ignored. | +| `cargo test --features test-hooks -p agent-file-tools --test integration -- sandbox` | 6 passed, 0 failed. | | `cargo test -p agent-file-tools --bin aft -- sandbox` | 8 passed, 0 failed. | | `cargo fmt --all -- --check` | Exit 0; silent-success gate. | | `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu` | `Finished` successfully; compile-only, not Windows runtime evidence. | diff --git a/docs/investigations/build-breaker-windows-ci-flake-2026-08-30.md b/docs/investigations/build-breaker-windows-ci-flake-2026-08-30.md index 064972add9..cdce4adaf5 100644 --- a/docs/investigations/build-breaker-windows-ci-flake-2026-08-30.md +++ b/docs/investigations/build-breaker-windows-ci-flake-2026-08-30.md @@ -46,6 +46,6 @@ Mutation control replaced health's injected snapshot timestamp with the live wal - `cargo test -p agent-file-tools --lib build_breaker::tests::durable_trip_agrees_across_navigation_inspect_and_health_snapshots -- --exact --nocapture` passed after the deterministic rewrite; the red-first and live-clock mutation controls both failed at the intended health assertions before restoration. - `cargo test -p agent-file-tools --lib --quiet` passed all 2,875 selected unit tests (17 ignored). - The full integration suite passed 1,618 tests and hit 19 pre-existing `callgraph_test` failures: this linked Mason worktree is correctly borrow-only, while those fixtures require creating a callgraph store. Re-running with the baseline module excluded passed all 1,584 selected tests (11 ignored). -- `cargo test -p agent-file-tools --test watcher_integration --quiet -- --test-threads=1` passed all 18 tests. +- `cargo test --features test-hooks -p agent-file-tools --test watcher_integration --quiet -- --test-threads=1` passed all 18 tests. - `cargo check --workspace --all-targets --target x86_64-pc-windows-gnu` passed. - `cargo fmt --all -- --check` passed. diff --git a/docs/investigations/callgraph-extraction-work-2026-10.md b/docs/investigations/callgraph-extraction-work-2026-10.md index 0ba3c74d24..020b7809b6 100644 --- a/docs/investigations/callgraph-extraction-work-2026-10.md +++ b/docs/investigations/callgraph-extraction-work-2026-10.md @@ -140,7 +140,7 @@ listed below; Cargo commands used three-hour timeouts and were run sequentially. | `cargo test -p agent-file-tools --lib callgraph -- --test-threads=1` | 340 passed, 0 failed, 5 ignored | | `cargo test -p agent-file-tools --lib views:: -- --test-threads=1` | 159 passed, 0 failed, 6 ignored | | `cargo test -p agent-file-tools --bin aft -- callgraph` | 6 passed, 0 failed | -| `cargo test -p agent-file-tools --test rest -- callgraph` | 83 passed, 0 failed, 6 ignored | +| `cargo test --features test-hooks -p agent-file-tools --test rest -- callgraph` | 83 passed, 0 failed, 6 ignored | | `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu` | Finished successfully, including test targets; compile-only, not Windows runtime verification | | `cargo fmt --all -- --check` | Passed, silent success | diff --git a/docs/investigations/callgraph-large-refresh-2026-09.md b/docs/investigations/callgraph-large-refresh-2026-09.md index 15d5857309..c85e2dadd2 100644 --- a/docs/investigations/callgraph-large-refresh-2026-09.md +++ b/docs/investigations/callgraph-large-refresh-2026-09.md @@ -118,7 +118,7 @@ was only read by `git clone` and `git reflog`. git clone --no-hardlinks ~/Work/OSS/oh-my-pi /private/tmp/lrb/omp cp docs/investigations/scripts/callgraph-large-refresh-bench.rs \ crates/aft/tests/callgraph_large_refresh_bench.rs -cargo test --profile stage -p agent-file-tools \ +cargo test --features test-hooks --profile stage -p agent-file-tools \ --test callgraph_large_refresh_bench --no-run ``` diff --git a/docs/investigations/callgraph-refresh-lazy-index-2026-09.md b/docs/investigations/callgraph-refresh-lazy-index-2026-09.md index f00ffb5657..b4ace6be47 100644 --- a/docs/investigations/callgraph-refresh-lazy-index-2026-09.md +++ b/docs/investigations/callgraph-refresh-lazy-index-2026-09.md @@ -67,7 +67,7 @@ Reading the table: git clone --no-hardlinks ~/Work/OSS/oh-my-pi .tmp/omp && git -C .tmp/omp checkout e1a86ce4f9 cp docs/investigations/scripts/callgraph-large-refresh-bench.rs \ crates/aft/tests/callgraph_large_refresh_bench.rs -CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test --profile stage -p agent-file-tools \ +CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test --features test-hooks --profile stage -p agent-file-tools \ --test callgraph_large_refresh_bench --no-run ``` diff --git a/docs/investigations/callgraph-refresh-write-amplification-2026-09.md b/docs/investigations/callgraph-refresh-write-amplification-2026-09.md index 32b948bb3b..5fb39bf14a 100644 --- a/docs/investigations/callgraph-refresh-write-amplification-2026-09.md +++ b/docs/investigations/callgraph-refresh-write-amplification-2026-09.md @@ -36,7 +36,7 @@ Run the optimized probe with: AFT_CALLGRAPH_REFRESH_STORE="$HOME/.local/share/cortexkit/aft/callgraph/90ff783f3f4c5cf2" \ AFT_CALLGRAPH_REFRESH_ROOT="$PWD" \ AFT_CALLGRAPH_REFRESH_FILE="crates/aft/tests/engine_comparator_test.rs" \ -cargo test -p agent-file-tools --test callgraph_refresh_bench \ +cargo test --features test-hooks -p agent-file-tools --test callgraph_refresh_bench \ bench_refresh_files_on_store_copy -- --ignored --nocapture ``` diff --git a/docs/investigations/ci-flaky-tests.md b/docs/investigations/ci-flaky-tests.md index 8d59a9f9a9..b2907f8f4f 100644 --- a/docs/investigations/ci-flaky-tests.md +++ b/docs/investigations/ci-flaky-tests.md @@ -458,7 +458,7 @@ behavior, ranking files, package manifests or generated schemas. Original CI-history limitations and other deferred follow-ups remain explicit above. Final correction gates after stress-helper removal and comment cleanup: -`cargo test -p agent-file-tools --features test-timing-hooks --test integration -- +`cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- status_answers_while_another_process_holds_the_write_lock subc_drain_exits_with_many_live_lsp_servers_in_one_deadline --test-threads 4 --nocapture`: **2 passed, 0 failed**. `cargo check -p agent-file-tools --lib diff --git a/docs/investigations/cpu-hunt-2026-09.md b/docs/investigations/cpu-hunt-2026-09.md index 7e44acaeff..5e284b52be 100644 --- a/docs/investigations/cpu-hunt-2026-09.md +++ b/docs/investigations/cpu-hunt-2026-09.md @@ -122,7 +122,7 @@ Reproduce the graph measurements: AFT_CALLGRAPH_REFRESH_STORE=/path/to/source-or-copied/root-key-directory \ AFT_CALLGRAPH_REFRESH_ROOT="$PWD" \ AFT_CALLGRAPH_REFRESH_FILE=crates/aft/tests/engine_comparator_test.rs \ -cargo test -p agent-file-tools --test callgraph_refresh_bench \ +cargo test --features test-hooks -p agent-file-tools --test callgraph_refresh_bench \ bench_refresh_files_on_store_copy -- --ignored --nocapture ``` @@ -166,8 +166,8 @@ Tool response rendering and the parity fixture are unchanged. Health diagnostics ## Gates - `cargo test -p agent-file-tools --lib`: **3,147 passed, 19 ignored** after the bind fix. Subsequent full-suite reruns after CPU-only benchmark instrumentation exposed unrelated environment/test-order failures: the live default database advanced to schema 10 while this source supports 9 (`standing_roots::tests::daemon_startup_empty_pass_marks_existing_snapshot_strict_on_first_configured_pass`). Rerunning with `XDG_DATA_HOME` inside the worktree avoids that live database; one default-parallel run then failed a semantic HTTP transient-classification test and two configure-tail timeout tests. A four-thread full run passed 3,146 tests and failed only `commands::configure::tests::cold_configure_starts_callgraph_before_semantic`; that test passed when rerun alone under the same isolated storage. These are recorded rather than weakening those tests or modifying the operator database. -- `cargo test -p agent-file-tools --test integration subc_`: **117 passed, 5 ignored** (bridge, storm, detach and other matching subc integration coverage). -- `cargo test -p agent-file-tools --test integration tool_call_parity_test`: **12 passed**. +- `cargo test --features test-hooks -p agent-file-tools --test integration subc_`: **117 passed, 5 ignored** (bridge, storm, detach and other matching subc integration coverage). +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test`: **12 passed**. - `git diff --exit-code 427895e45278924df01fee8353fb36806ec2c1ae -- crates/aft/tests/integration/tool_call_parity_test.rs`: **byte-identical source**. - `RUSTFLAGS='-D warnings' cargo check -p agent-file-tools --all-targets`: passed. - `RUSTFLAGS='-D warnings' cargo check -p agent-file-tools --target x86_64-pc-windows-gnu --all-targets`: passed. @@ -242,8 +242,8 @@ A separate run of the copied-store probe against the same mutation also failed e ### Final gates for the projection fix - Full library with isolated default storage and serial test execution: `XDG_DATA_HOME=... cargo test -p agent-file-tools --lib -- --test-threads=1` — **3,149 passed, 20 ignored**. This avoids the default-database schema mismatch and the parallel/order failures described above, without changing tests. -- `cargo test -p agent-file-tools --test integration callgraph`: initially **67 passed, 10 failed** because in-repository fixtures inherited this checkout's read-only worktree identity; the diagnostic error explicitly said the persisted store was unavailable in a read-only worktree. With `GIT_CEILING_DIRECTORIES="$PWD/crates/aft/tests/fixtures"` and isolated default storage, the same suite passed **77 tests**. This fences only fixture ancestor discovery; no parent checkout or daemon is warmed to make the test pass. -- `cargo test -p agent-file-tools --test integration inspect`: **222 passed, 5 ignored**. -- `cargo test -p agent-file-tools --test integration tool_call_parity_test`: **12 passed**; parity source remains byte-identical to the task base. +- `cargo test --features test-hooks -p agent-file-tools --test integration callgraph`: initially **67 passed, 10 failed** because in-repository fixtures inherited this checkout's read-only worktree identity; the diagnostic error explicitly said the persisted store was unavailable in a read-only worktree. With `GIT_CEILING_DIRECTORIES="$PWD/crates/aft/tests/fixtures"` and isolated default storage, the same suite passed **77 tests**. This fences only fixture ancestor discovery; no parent checkout or daemon is warmed to make the test pass. +- `cargo test --features test-hooks -p agent-file-tools --test integration inspect`: **222 passed, 5 ignored**. +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test`: **12 passed**; parity source remains byte-identical to the task base. - Native and `--target x86_64-pc-windows-gnu` **all-target** Cargo checks with `RUSTFLAGS='-D warnings'`: passed after the final code edits. - Comment clarity review: no flagged changed comments. Formatter and diff whitespace checks: passed. diff --git a/docs/investigations/daemon-unexplained-writes-2026-09.md b/docs/investigations/daemon-unexplained-writes-2026-09.md index 72d83ff9ff..04b5a3137d 100644 --- a/docs/investigations/daemon-unexplained-writes-2026-09.md +++ b/docs/investigations/daemon-unexplained-writes-2026-09.md @@ -129,10 +129,10 @@ python3 docs/investigations/scripts/daemon-unexplained-writes.py \ --output-dir /tmp/aft-isolated-write-run # INPUT contains OFFLINE SQLite-backup snapshots, never live databases. -AFT_WRITE_PROBE_DIR="$INPUT" cargo test -p agent-file-tools \ +AFT_WRITE_PROBE_DIR="$INPUT" cargo test --features test-hooks -p agent-file-tools \ --test daemon_unexplained_writes_probe offline_database_read_writes \ -- --ignored --nocapture --test-threads=1 -AFT_WRITE_PROBE_DIR="$INPUT" cargo test -p agent-file-tools \ +AFT_WRITE_PROBE_DIR="$INPUT" cargo test --features test-hooks -p agent-file-tools \ --test daemon_unexplained_writes_probe offline_sparse_callgraph_writes \ -- --ignored --nocapture --test-threads=1 ``` @@ -179,7 +179,7 @@ For the actual refresh control, prepare a disposable `prefrontal-root` clone **i ```sh AFT_STORAGE_DIR="$INPUT/storage" AFT_WRITE_PROBE_DIR="$INPUT" \ - cargo test -p agent-file-tools --test daemon_unexplained_writes_probe \ + cargo test --features test-hooks -p agent-file-tools --test daemon_unexplained_writes_probe \ offline_production_callgraph_refresh -- --ignored --nocapture --test-threads=1 # Add AFT_WRITE_PROBE_DELETE=1 for the deletion variant. ``` diff --git a/docs/investigations/database-open-contention.md b/docs/investigations/database-open-contention.md index 09f5a024f6..c799321ea9 100644 --- a/docs/investigations/database-open-contention.md +++ b/docs/investigations/database-open-contention.md @@ -33,7 +33,7 @@ The macOS repetition gate passed **100/100 runs** again after adding the short p ```sh for i in $(seq 1 100); do echo "concurrent run $i/100" - CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test -q \ + CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test --features test-hooks -q \ -p agent-file-tools --test integration \ state_commands_test::db_set_host_state_concurrent_insert -- --exact || exit $? done diff --git a/docs/investigations/disk-write-hunt-2026-09.md b/docs/investigations/disk-write-hunt-2026-09.md index 8aca4754c6..9d2774c8fb 100644 --- a/docs/investigations/disk-write-hunt-2026-09.md +++ b/docs/investigations/disk-write-hunt-2026-09.md @@ -178,8 +178,8 @@ USE TEMP B-TREE FOR ORDER BY ## Verification for the retention commit - `cargo test -p agent-file-tools --lib`: 3,149 passed, 21 ignored. -- `cargo test -p agent-file-tools --test integration`: 1,708 passed, 12 ignored, 11 failed. Ten callgraph tests require a writable checkout/store and fail with `callgraph_unavailable` here; all ten reproduced after restoring the implementation files to the unchanged base, in a 53-test callgraph run (43 passed). The eleventh, `standalone_ndjson_polls_cold_navigation_off_the_input_loop`, passed when rerun alone on the fixed code (parallel-suite deadline sensitivity). -- `cargo test -p agent-file-tools --test integration tool_call_parity_test`: all 12 passed, including byte-envelope parity. +- `cargo test --features test-hooks -p agent-file-tools --test integration`: 1,708 passed, 12 ignored, 11 failed. Ten callgraph tests require a writable checkout/store and fail with `callgraph_unavailable` here; all ten reproduced after restoring the implementation files to the unchanged base, in a 53-test callgraph run (43 passed). The eleventh, `standalone_ndjson_polls_cold_navigation_off_the_input_loop`, passed when rerun alone on the fixed code (parallel-suite deadline sensitivity). +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test`: all 12 passed, including byte-envelope parity. - `RUSTFLAGS='-D warnings' cargo check -p agent-file-tools --all-targets`: passed. - `RUSTFLAGS='-D warnings' cargo check -p agent-file-tools --target x86_64-pc-windows-gnu --all-targets`: passed. - Both ignored measurement probes passed. Scoped AFT inspection completed but had no authoritative Rust diagnostics; Cargo checks, not the diagnostic summary, are the compile gate. @@ -207,9 +207,9 @@ Applied diff: `crates/aft/src/db/bash_tasks.rs | 3 ++-`; restored diff: empty. T Verification after restoration: - Full `cargo test -p agent-file-tools --lib`: 3,150 passed, 21 ignored. -- `cargo test -p agent-file-tools --test integration bash`: 271 passed. -- `cargo test -p agent-file-tools --test integration db_read_fallback_test`: 12 passed. -- `cargo test -p agent-file-tools --test integration tool_call_parity_test`: 12 passed. +- `cargo test --features test-hooks -p agent-file-tools --test integration bash`: 271 passed. +- `cargo test --features test-hooks -p agent-file-tools --test integration db_read_fallback_test`: 12 passed. +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test`: 12 passed. - Native and `--target x86_64-pc-windows-gnu` `cargo check -p agent-file-tools --all-targets` with `RUSTFLAGS='-D warnings'`: both passed. - Full integration was not rerun for this narrow read change; its unchanged callgraph-worktree failures and isolated LSP deadline rerun are documented above. No failing baseline test was rewritten. diff --git a/docs/investigations/fsevents-overflow-churn.md b/docs/investigations/fsevents-overflow-churn.md index 7941e238e2..bcfa79d51d 100644 --- a/docs/investigations/fsevents-overflow-churn.md +++ b/docs/investigations/fsevents-overflow-churn.md @@ -199,8 +199,8 @@ an empty unstaged diff. No existing test was rewritten to accept changed behavio All Cargo test commands used the temporary HOME/XDG setup described above. * `cargo test -p agent-file-tools --lib -- watcher`: 100 passed, 8 ignored. -* `cargo test -p agent-file-tools --test integration -- watcher`: 22 passed. -* `cargo test -p agent-file-tools --test watcher_integration`: 29 passed on macOS, +* `cargo test --features test-hooks -p agent-file-tools --test integration -- watcher`: 22 passed. +* `cargo test --features test-hooks -p agent-file-tools --test watcher_integration`: 29 passed on macOS, including config live reload, Git branch switching, and ignored-event floods. * `cargo test -p agent-file-tools --lib -- config_live --test-threads=1`: 33 passed, including replacement directories and late directory creation. diff --git a/docs/investigations/gh-shim-wire-goldens/README.md b/docs/investigations/gh-shim-wire-goldens/README.md index f642d39340..749e494467 100644 --- a/docs/investigations/gh-shim-wire-goldens/README.md +++ b/docs/investigations/gh-shim-wire-goldens/README.md @@ -48,7 +48,7 @@ rewritten): ```sh AFT_GH_SHIM_WIRE_GOLDENS_REGEN=1 CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= \ - cargo test -p agent-file-tools --test gh_shim_wire_goldens_test -- --test-threads=1 + cargo test --features test-hooks -p agent-file-tools --test gh_shim_wire_goldens_test -- --test-threads=1 ``` Without the variable the same test compares instead: each captured request diff --git a/docs/investigations/inspect-rust-cancelled-pull.md b/docs/investigations/inspect-rust-cancelled-pull.md index 2587d76ceb..0c875f42f6 100644 --- a/docs/investigations/inspect-rust-cancelled-pull.md +++ b/docs/investigations/inspect-rust-cancelled-pull.md @@ -17,7 +17,7 @@ workspace just because its compiler check later finishes. The unchanged settle logic was exercised with: ```sh -AFT_TEST_REQUIRE_RUST_ANALYZER=1 cargo test -p agent-file-tools --test integration scoped_rust_inspect_reports_a_removed_field_after_an_outside_edit_with_real_rust_analyzer -- --nocapture +AFT_TEST_REQUIRE_RUST_ANALYZER=1 cargo test --features test-hooks -p agent-file-tools --test integration scoped_rust_inspect_reports_a_removed_field_after_an_outside_edit_with_real_rust_analyzer -- --nocapture ``` Temporary instrumentation printed the reader's LSP responses, progress and diff --git a/docs/investigations/inspect-tier2-worktrees-cold.md b/docs/investigations/inspect-tier2-worktrees-cold.md index e08b06e96f..825f16906a 100644 --- a/docs/investigations/inspect-tier2-worktrees-cold.md +++ b/docs/investigations/inspect-tier2-worktrees-cold.md @@ -122,7 +122,7 @@ Tool versions: Cargo 1.99.0, rustc 1.99.0, rust-analyzer 1.99.0 (all the install 2026-09-28 toolchain). The isolated samples required the real server with: ```text -AFT_TEST_REQUIRE_RUST_ANALYZER=1 cargo test -p agent-file-tools --test integration scoped_rust_inspect_reports_a_removed_field_after_an_outside_edit_with_real_rust_analyzer +AFT_TEST_REQUIRE_RUST_ANALYZER=1 cargo test --features test-hooks -p agent-file-tools --test integration scoped_rust_inspect_reports_a_removed_field_after_an_outside_edit_with_real_rust_analyzer ``` Unchanged base `205903927a5cc717199cb6c8085560e5070f8265`: **12 invocations, diff --git a/docs/investigations/linux-inspect-lsp-lifetime.md b/docs/investigations/linux-inspect-lsp-lifetime.md index 926aa774ed..cefcb2265c 100644 --- a/docs/investigations/linux-inspect-lsp-lifetime.md +++ b/docs/investigations/linux-inspect-lsp-lifetime.md @@ -5,9 +5,9 @@ Reproduced in Ubuntu 24.04, Linux x86_64 under OrbStack on an arm64 host, with the task worktree mounted at `/work` and isolated Cargo and target volumes. The container uses Rust 1.98.1 and the native C build dependencies described in [the Linux search-readiness investigation](linux-search-readiness.md); Python 3 is also required by the protocol-server fixtures in the broader LSP suite. All builds ran with `CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER=`. ```sh -cargo test -p agent-file-tools --test integration inspect_command_test::a_typescript_file_still_starts_typescript -- --nocapture -cargo test -p agent-file-tools --test integration inspect_command_test::blocking_inspect_returns_before_the_configured_request_deadline -- --nocapture -cargo test -p agent-file-tools --test integration inspect_command_test::blocking_inspect_indexing_gap_names_elapsed_wait_and_retry -- --nocapture +cargo test --features test-hooks -p agent-file-tools --test integration inspect_command_test::a_typescript_file_still_starts_typescript -- --nocapture +cargo test --features test-hooks -p agent-file-tools --test integration inspect_command_test::blocking_inspect_returns_before_the_configured_request_deadline -- --nocapture +cargo test --features test-hooks -p agent-file-tools --test integration inspect_command_test::blocking_inspect_indexing_gap_names_elapsed_wait_and_retry -- --nocapture ``` At train 235 tip `a32b4e53ff666cd7e84e5e64241ff25888ecb93d`, `a_typescript_file_still_starts_typescript` failed four consecutive runs. Three failed the unscoped assertion (expected active Rust and TypeScript servers); one already failed the scoped assertion (expected an active TypeScript server). Both blocking deadline tests also failed at their reported assertions. CPU load was unnecessary. All three passed on main/train 234, `17f2c807c9f5df1b55e40b4efce3bd54e3262ecc`. @@ -42,8 +42,8 @@ Linux LSP process creation is dispatched onto one process-lifetime spawning thre On the fixed Linux build: - New lifecycle regression: passed (and failed with `BrokenPipe` on the old implementation). -- `cargo test -p agent-file-tools --test integration inspect_command_test:: -- --nocapture`: 72 passed, 4 ignored, including all three original failures. -- `cargo test -p agent-file-tools --test integration lsp_manager_test:: -- --nocapture`: 26 passed, including delayed initialization, initialize timeout/retry, graceful shutdown, and forced group cleanup. +- `cargo test --features test-hooks -p agent-file-tools --test integration inspect_command_test:: -- --nocapture`: 72 passed, 4 ignored, including all three original failures. +- `cargo test --features test-hooks -p agent-file-tools --test integration lsp_manager_test:: -- --nocapture`: 26 passed, including delayed initialization, initialize timeout/retry, graceful shutdown, and forced group cleanup. - `cargo test -p agent-file-tools --lib lsp::client:: -- --nocapture`: 14 passed. - `cargo test -p agent-file-tools --lib lsp::child_registry:: -- --nocapture`: 13 passed. - `cargo check -p agent-file-tools --tests`: passed. diff --git a/docs/investigations/linux-search-readiness.md b/docs/investigations/linux-search-readiness.md index e339d782b4..08f1cc92fa 100644 --- a/docs/investigations/linux-search-readiness.md +++ b/docs/investigations/linux-search-readiness.md @@ -72,7 +72,7 @@ The same search-admission mechanism cannot account for a module that stops answe ## Verification results - Fixed Linux debug binary: unchanged semantic-search e2e file passed all 4 tests (11 assertions). -- `cargo test -p agent-file-tools --test search_b2_readiness`: all 13 passed, including after mutation restoration. Isolated post-restore runs of the real-handler regression and `building_indexes_refuse_with_each_lanes_status_instead_of_walking` also passed. +- `cargo test --features test-hooks -p agent-file-tools --test search_b2_readiness`: all 13 passed, including after mutation restoration. Isolated post-restore runs of the real-handler regression and `building_indexes_refuse_with_each_lanes_status_instead_of_walking` also passed. - `cargo test -p agent-file-tools --lib commands::semantic_search::tests`: 87 passed, 1 failed the unrelated 200 ms wall-clock assertion in `blackholed_backend_never_blocks_status_or_search` under x86_64 emulation. It took 209.6 ms for status in the suite and 203.3 ms for search on an isolated retry. That fixture already has a ready lexical index, so the changed admission condition takes the same branch as before. The test was not relaxed. - Both new regressions failed against the old implementation; the real-handler test reproduced the same empty result and contradictory readiness metadata as the Linux e2e failure. - Controlled mutation restored the symbol-only shortcut in `readiness.rs`: `ready_symbols_wait_for_trigram_before_selecting_lexical_plan` alone failed, and the other 12 readiness tests passed. The staged fix was restored afterward with an empty unstaged diff. diff --git a/docs/investigations/path-resolution-audit-2026-09.md b/docs/investigations/path-resolution-audit-2026-09.md index ae65d4d12a..2617813928 100644 --- a/docs/investigations/path-resolution-audit-2026-09.md +++ b/docs/investigations/path-resolution-audit-2026-09.md @@ -140,7 +140,7 @@ The placeholders are replaced with captured test names and output before commit. The required bare command was run after the audit changes: ```text -cargo test -p agent-file-tools --test integration +cargo test --features test-hooks -p agent-file-tools --test integration test result: FAILED. 1682 passed; 20 failed; 12 ignored; 0 measured; 0 filtered out; finished in 195.69s ``` @@ -154,4 +154,4 @@ Status-related failures exposed assertions that still treated unavailable diagno The only remaining failures are 19 callgraph tests that target fixtures inside this linked task worktree and receive the worktree read-only `callgraph_unavailable` response. Positive control: `callgraph_unknown_symbol_error` reproduces that environmental limitation in isolation. -No parity fixture moved. `cargo test -p agent-file-tools --test integration tool_call_parity_test` passed all 12 tests exercising the 69 pinned fixtures: `12 passed; 0 failed; 1702 filtered out`. +No parity fixture moved. `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test` passed all 12 tests exercising the 69 pinned fixtures: `12 passed; 0 failed; 1702 filtered out`. diff --git a/docs/investigations/perf-audit-2-callgraph.md b/docs/investigations/perf-audit-2-callgraph.md index fbfdc8c691..123a4c8221 100644 --- a/docs/investigations/perf-audit-2-callgraph.md +++ b/docs/investigations/perf-audit-2-callgraph.md @@ -217,7 +217,7 @@ or lockfile was changed. | `cargo test -p agent-file-tools --bin aft -- callgraph` | 6 passed, 0 failed | | `cargo fmt --all -- --check` | exit 0, silent success; version shown above | | `cargo test -p agent-file-tools --lib callgraph -- --test-threads=1` | 350 passed, 4 failed, 6 ignored; baseline with isolated storage has the **same four failures**, 346 passed, 5 ignored | -| `cargo test -p agent-file-tools --test rest -- callgraph` | 75 passed, 8 failed, 6 ignored; isolated-storage baseline has the **same eight failures**, 75 passed, 6 ignored | +| `cargo test --features test-hooks -p agent-file-tools --test rest -- callgraph` | 75 passed, 8 failed, 6 ignored; isolated-storage baseline has the **same eight failures**, 75 passed, 6 ignored | | Scoped `aft_inspect` | partial rust-analyzer warm-up diagnostics; package compilation/tests are the authoritative compiler checks | The four broad-lib failures are diff --git a/docs/investigations/perf-audit-2-edit.md b/docs/investigations/perf-audit-2-edit.md index ae2d8c2a34..cf7c0f29f3 100644 --- a/docs/investigations/perf-audit-2-edit.md +++ b/docs/investigations/perf-audit-2-edit.md @@ -105,7 +105,7 @@ Run the real-compiler tests explicitly after `bun install`, under a throwaway the real `CARGO_HOME` and `RUSTUP_HOME` retained and `AFT_STORAGE_DIR` unset: ``` -cargo test -p agent-file-tools --test integration -- multi_file_full_validation --ignored --nocapture +cargo test --features test-hooks -p agent-file-tools --test integration -- multi_file_full_validation --ignored --nocapture ``` The four `multi_file_full_validation_ci_*` twins run normally on Linux and macOS @@ -121,7 +121,7 @@ conditional on an ignored test being selected. Summary nouns use singular forms for one error, one touched file and one unchecked file. ``` -cargo test -p agent-file-tools --test integration -- multi_file_full_validation_ci_ +cargo test --features test-hooks -p agent-file-tools --test integration -- multi_file_full_validation_ci_ ``` The CI-coverage revision adds a six-case summary test for zero, one and multiple diff --git a/docs/investigations/perf-audit-2-views-blob-store-gc.md b/docs/investigations/perf-audit-2-views-blob-store-gc.md index 10df5e2fa7..51e18c83d8 100644 --- a/docs/investigations/perf-audit-2-views-blob-store-gc.md +++ b/docs/investigations/perf-audit-2-views-blob-store-gc.md @@ -238,7 +238,7 @@ Tool versions: `cargo 1.99.0 (5f94df478 2026-08-27)`, - `cargo test -p agent-file-tools --bin aft`: 121 passed, 0 failed. The initial `view_publication` filter matched 0 tests and is **not** counted as a pass; it was replaced with the full binary suite. -- `cargo test -p agent-file-tools --test integration per_checkout`: 81 passed, +- `cargo test --features test-hooks -p agent-file-tools --test integration per_checkout`: 81 passed, 5 ignored child-process entrypoints, 0 failed. - Windows cross-check skipped at the parent's instruction; the train owns it. - Scoped diagnostics inspections returned PARTIAL while rust-analyzer was diff --git a/docs/investigations/pi-standalone-startup-399.md b/docs/investigations/pi-standalone-startup-399.md index 3f87cf21ca..e4848db1d8 100644 --- a/docs/investigations/pi-standalone-startup-399.md +++ b/docs/investigations/pi-standalone-startup-399.md @@ -104,10 +104,10 @@ waiting for a legacy build. Commands: ``` -cargo test -p agent-file-tools --features test-timing-hooks --test integration standalone_ -- --nocapture +cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration standalone_ -- --nocapture cargo test -p agent-file-tools --lib commands::configure::tests:: -- --test-threads=4 cargo test -p agent-file-tools --lib -- commands::configure::tests:: context::callgraph_store_for_ops_tests:: runtime_drain::tests:: views::semantic_runtime:: -cargo test -p agent-file-tools --features test-timing-hooks --test integration -- per_checkout_9:: standalone_search_deferred_test:: +cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- per_checkout_9:: standalone_search_deferred_test:: bun run --cwd packages/aft-bridge build bun run --cwd packages/aft-bridge typecheck bun run --cwd packages/pi-plugin typecheck diff --git a/docs/investigations/release-storm-readiness-health-budget-2026-10-07.md b/docs/investigations/release-storm-readiness-health-budget-2026-10-07.md index 2875eca0af..f89aa5c7e9 100644 --- a/docs/investigations/release-storm-readiness-health-budget-2026-10-07.md +++ b/docs/investigations/release-storm-readiness-health-budget-2026-10-07.md @@ -50,7 +50,7 @@ There were 320 successful readiness health replies and **zero** `stall watchdog: Each revision below was checked out in the isolated worker worktree and tested on Linux with: ```sh -cargo nextest run --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm_rebinds_stay_live_under_build_and_tool_traffic)' +cargo nextest run --features test-hooks --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm_rebinds_stay_live_under_build_and_tool_traffic)' ``` | Revision | Result | @@ -73,7 +73,7 @@ The readiness barrier (`subc_storm_test.rs:2843–2872`) still polls health over Ran the exact release-storm workflow command five consecutive times: ```sh -cargo nextest run --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm)' +cargo nextest run --features test-hooks --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm)' ``` Each run passed all **18** tests (the existing 15 plus three predicate regressions), without retries. The formerly failing test took 11.282, 11.331, 11.340, 11.306 and 11.407 seconds respectively. diff --git a/docs/investigations/semantic-shared-overlays-2026-09.md b/docs/investigations/semantic-shared-overlays-2026-09.md index bf7aad53bd..5f72c788c5 100644 --- a/docs/investigations/semantic-shared-overlays-2026-09.md +++ b/docs/investigations/semantic-shared-overlays-2026-09.md @@ -97,7 +97,7 @@ in the temporary source. The final applied diff was nonempty (2 files, 314 insertions, 553 deletions). Running ```sh -CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test --locked \ +CARGO_BUILD_RUSTC_WRAPPER= RUSTC_WRAPPER= cargo test --features test-hooks --locked \ -p agent-file-tools --lib shared_overlay_equivalence_and_sharing -j 2 ``` diff --git a/docs/investigations/subc-bridge-windows-reliability.md b/docs/investigations/subc-bridge-windows-reliability.md index 86f85bc9b5..5c80d2155b 100644 --- a/docs/investigations/subc-bridge-windows-reliability.md +++ b/docs/investigations/subc-bridge-windows-reliability.md @@ -245,7 +245,7 @@ Unrelated failures, individually: Linux: `cargo test -p agent-file-tools --lib subc::` passed 338 tests (7 existing ignores). That combined run lost remote monitoring during integration; its integration outcome is recorded as unknown, not passed. The reviewer authorized -one fresh read-only integration run; `cargo test -p agent-file-tools --test +one fresh read-only integration run; `cargo test --features test-hooks -p agent-file-tools --test integration subc_bridge_test::` then passed 101 tests (2 existing ignores), in 167.83 seconds. The final drain slice passed 7 tests. Rustfmt 1.10.0-stable `cargo fmt --all -- --check` passed. Final scoped rust-analyzer diagnostics were diff --git a/docs/investigations/subc-control-stall-2026-10-09.md b/docs/investigations/subc-control-stall-2026-10-09.md index 92d530baef..8c624bb00b 100644 --- a/docs/investigations/subc-control-stall-2026-10-09.md +++ b/docs/investigations/subc-control-stall-2026-10-09.md @@ -256,7 +256,7 @@ Tools: `cargo 1.99.0 (5f94df478 2026-08-27)`, | `cargo test -p agent-file-tools --lib -- lock_diagnostics::` | 1 passed, 0 failed. | | `cargo test -p agent-file-tools --lib -- executor::` | 109 passed, 2 ignored, 0 failed. | | `cargo test -p agent-file-tools --bin aft --` | 122 passed, 0 failed. | -| `cargo test -p agent-file-tools --test integration -- subc_` | 171 passed, 5 ignored, 0 failed. | +| `cargo test --features test-hooks -p agent-file-tools --test integration -- subc_` | 171 passed, 5 ignored, 0 failed. | | `RUSTFLAGS="-D warnings -A deprecated" cargo check -p agent-file-tools --tests --target x86_64-pc-windows-gnu` | Finished dev profile; compile-only, not Windows runtime coverage. | | Scoped AFT diagnostics | Authoritative diagnostics for 5/5 inspected files: 0 errors/warnings. Overall inspection remains PARTIAL because the checkout call-graph analysis is unavailable. | diff --git a/docs/investigations/subc-egress-hol-2026-07-14.md b/docs/investigations/subc-egress-hol-2026-07-14.md index ccae71d320..9eb0b8ebc1 100644 --- a/docs/investigations/subc-egress-hol-2026-07-14.md +++ b/docs/investigations/subc-egress-hol-2026-07-14.md @@ -97,7 +97,7 @@ measurement lock contained `bg_1d44c6cd F-3 rerun` for every final-code run and was removed afterward. The release-profile command was: ```text -cargo test --release -p agent-file-tools --test integration \ +cargo test --features test-hooks --release -p agent-file-tools --test integration \ subc_egress_hol_measurement -- --ignored --nocapture ``` diff --git a/docs/investigations/subc-promote-error-follow-up.md b/docs/investigations/subc-promote-error-follow-up.md index 18ff592b66..a83d79ca80 100644 --- a/docs/investigations/subc-promote-error-follow-up.md +++ b/docs/investigations/subc-promote-error-follow-up.md @@ -9,7 +9,7 @@ is an Actions run identifier, not a Git ref. The reported assertion was reproduced before editing with: ```sh -AFT_TEST_SUBC_BASH_PROMOTE_DELAY_MS=3000 cargo test -p agent-file-tools --test integration subc_bridge_bash_promote_failure_is_normal_tool_error +AFT_TEST_SUBC_BASH_PROMOTE_DELAY_MS=3000 cargo test --features test-hooks -p agent-file-tools --test integration subc_bridge_bash_promote_failure_is_normal_tool_error ``` It failed at `tool_result_is_error(&frame)`, followed by `ConnectionLost`. diff --git a/docs/investigations/train-343-verification.md b/docs/investigations/train-343-verification.md index 4be8631dba..c24aa7d567 100644 --- a/docs/investigations/train-343-verification.md +++ b/docs/investigations/train-343-verification.md @@ -88,13 +88,13 @@ Tools: cargo 1.99.0 (`5f94df478`); rustc 1.99.0 (`b940084d7`); rustfmt 1.10.0-st | Integration `bash_background` / `bash_watch` | 88 / 20 pass | | Integration `db_` / `migration` / `inspect` / `semantic` | 52 / 10 / 282 / 68 pass; inspect 6 ignored, semantic 4 ignored | | Integration `callgraph` | 96 pass / 10 known linked-worktree failures / 2 ignored | -| `cargo test -p agent-file-tools --test semantic -- --test-threads 4` | 52 pass / 3 ignored | +| `cargo test --features test-hooks -p agent-file-tools --test semantic -- --test-threads 4` | 52 pass / 3 ignored | | Rest `callgraph` after explicit pins | 85 pass / 6 ignored | | Feature-enabled rest `tool_provider_conformance` | 19 pass; Prepared/Authorized crash hooks actually ran | | Rest `tool_provider_subc_e2e` | NOT a pass: 0 pass / 1 ignored; requires a real ck-subc 0.29+ daemon and AFT_E2E_SUBC_BIN | | `cargo test -p agent-file-tools --bin aft -- --test-threads 4` | 121 pass | | Mandatory real analyzer restart test with `AFT_TEST_REQUIRE_RUST_ANALYZER=1` | 1 pass, not a silently skipped server test | -| `cargo test -p agent-file-tools --test list_envelope -- --test-threads 4` | 175 pass | +| `cargo test --features test-hooks -p agent-file-tools --test list_envelope -- --test-threads 4` | 175 pass | | `python3 benchmarks/aft-search/run_search_quality.py --self-test` | Goldens OK; 123 unittest cases / 1 platform skip | | Bridge build, typecheck, unit | `bun run --cwd packages/aft-bridge build`, `typecheck`: exit 0; `test:unit`: 797 pass / 0 fail / 3 skip across 67 files | | `bun run lint` | Checked 699 files, exit 0 | diff --git a/docs/investigations/train-345-baseline-comparison.md b/docs/investigations/train-345-baseline-comparison.md index 21fe44d1ae..5096256def 100644 --- a/docs/investigations/train-345-baseline-comparison.md +++ b/docs/investigations/train-345-baseline-comparison.md @@ -8,7 +8,7 @@ Compared **main `d286c3d3000bbd0d52b0a2f45043de332078b1c9`** with the original a All 40 previously reported failing Rust tests ran individually with exact-name selection on **ck-motor**, using the same command structure, toolchain, sandbox, serial execution (`RUST_TEST_THREADS=1`), and fresh disposable HOME/XDG namespaces. Every selected case executed exactly one test: there were no absent tests, zero-match passes, or skipped cases. -Commands were `cargo test -p agent-file-tools --lib -- --exact --nocapture` or `cargo test -p agent-file-tools --test -- --exact --nocapture`. Every remote shell command started with `[ "$(uname)" = Linux ] || exit 99`. +Commands were `cargo test -p agent-file-tools --lib -- --exact --nocapture` or `cargo test --features test-hooks -p agent-file-tools --test -- --exact --nocapture`. Every remote shell command started with `[ "$(uname)" = Linux ] || exit 99`. HOME and XDG_DATA/CONFIG/STATE/CACHE_HOME were created with `mkdir -p` under a fresh `/motor-home/aft-train345-ci.*` directory, outside the checkout and outside the runner's ordinary temporary-directory exemption. This reproduces CI's non-temp HOME classification without opening the real account database. `AFT_STORAGE_DIR` and `AFT_ALLOW_PRODUCTION_MIGRATION` were unset; existing CARGO_HOME/RUSTUP_HOME were retained for the toolchain. A new namespace was used for each revision so baseline writes could not seed the train's state. diff --git a/docs/investigations/train-345-verification.md b/docs/investigations/train-345-verification.md index b534b0e397..6eef59bfd3 100644 --- a/docs/investigations/train-345-verification.md +++ b/docs/investigations/train-345-verification.md @@ -66,14 +66,14 @@ Rust commands ran on Linux via `runon: "linux"`, each starting with `[ "$(uname) | `cargo check --target x86_64-pc-windows-gnu --tests -p agent-file-tools` | Unavailable: remote target is not installed; E0463 cannot find `core`/`std`. No Windows compile pass claimed. | | `cargo test -p agent-file-tools --lib` | 5415 passed, 18 failed, 48 ignored (5481 total). | | `cargo test -p agent-file-tools --bin aft` | 120 passed, 0 failed. | -| `cargo test -p agent-file-tools --test integration` | Initial run: 2193 passed, 19 failed, 28 ignored (2240 total). Two contract mismatches corrected as described above; only impacted tests rerun. | -| `cargo test -p agent-file-tools --test rest` | Initial E0063 corrected; subsequent full run: 247 passed, 3 failed, 6 ignored (256 total). | -| `cargo test -p agent-file-tools --test semantic` | 52 passed, 0 failed, 2 ignored. | -| `cargo test -p agent-file-tools --test list_envelope` | 175 passed, 0 failed. | -| `cargo test -p agent-file-tools --test integration config_parity` | 1 passed, verifies the parity fixture corpus. | -| `cargo test -p agent-file-tools --test integration rust_complex_use_lists_survive_edits_and_compile` | Final restored run: 1 passed. | -| `cargo test -p agent-file-tools --test integration embed_counts_views_and_sessions_share_identical_content` | Final restored run: 1 passed. | -| `cargo test -p agent-file-tools --test rest status_counts_inspect_seams` | 4 passed. | +| `cargo test --features test-hooks -p agent-file-tools --test integration` | Initial run: 2193 passed, 19 failed, 28 ignored (2240 total). Two contract mismatches corrected as described above; only impacted tests rerun. | +| `cargo test --features test-hooks -p agent-file-tools --test rest` | Initial E0063 corrected; subsequent full run: 247 passed, 3 failed, 6 ignored (256 total). | +| `cargo test --features test-hooks -p agent-file-tools --test semantic` | 52 passed, 0 failed, 2 ignored. | +| `cargo test --features test-hooks -p agent-file-tools --test list_envelope` | 175 passed, 0 failed. | +| `cargo test --features test-hooks -p agent-file-tools --test integration config_parity` | 1 passed, verifies the parity fixture corpus. | +| `cargo test --features test-hooks -p agent-file-tools --test integration rust_complex_use_lists_survive_edits_and_compile` | Final restored run: 1 passed. | +| `cargo test --features test-hooks -p agent-file-tools --test integration embed_counts_views_and_sessions_share_identical_content` | Final restored run: 1 passed. | +| `cargo test --features test-hooks -p agent-file-tools --test rest status_counts_inspect_seams` | 4 passed. | | `cargo test -p agent-file-tools --lib category_off_helper_preserves_active_and_retired_categories` | 1 passed; also passed in the full lib run. | | `cargo test -p agent-file-tools --lib disabled_inspect_category_starts_zero_jobs` | 1 passed; also passed in the full lib run. | diff --git a/docs/investigations/typescript-fresh-worktree.md b/docs/investigations/typescript-fresh-worktree.md index 101b1e87b0..399851228e 100644 --- a/docs/investigations/typescript-fresh-worktree.md +++ b/docs/investigations/typescript-fresh-worktree.md @@ -64,7 +64,7 @@ bun test packages/opencode-plugin/src/__tests__/lsp-auto-install.test.ts package bun run --cwd packages/opencode-plugin typecheck bun run --cwd packages/pi-plugin typecheck cargo test -p agent-file-tools --lib typescript_worktree_tests -AFT_TEST_LSP_BIN_DIR=/absolute/cache/node_modules/.bin cargo test -p agent-file-tools --test lsp_fresh_worktree_test -- --nocapture +AFT_TEST_LSP_BIN_DIR=/absolute/cache/node_modules/.bin cargo test --features test-hooks -p agent-file-tools --test lsp_fresh_worktree_test -- --nocapture ``` The opt-in real-server test requires Node and a bin directory with diff --git a/docs/investigations/views-lazy-read-benchmark-2026-09.md b/docs/investigations/views-lazy-read-benchmark-2026-09.md index e150500a6d..5efb1281da 100644 --- a/docs/investigations/views-lazy-read-benchmark-2026-09.md +++ b/docs/investigations/views-lazy-read-benchmark-2026-09.md @@ -24,7 +24,7 @@ AFT_HUNT_ROOT=/Users/ufukaltinok/Work/OSS/opencode \ AFT_HUNT_STORAGE=/Users/ufukaltinok/.cache/aft-views-soak/0f3900af641f5248/views-on-storage \ AFT_LAZY_READ_REPORT="$PWD/target/views-lazy-read-report.json" \ RUSTFLAGS='--cfg aft_views_lazy_benchmark' \ -cargo test -p agent-file-tools --test views_lazy_navigation_profile \ +cargo test --features test-hooks -p agent-file-tools --test views_lazy_navigation_profile \ --release -- --ignored --nocapture ``` diff --git a/docs/investigations/views-perf-hunt-2026-09-16.md b/docs/investigations/views-perf-hunt-2026-09-16.md index 416dc8a574..3016a70c35 100644 --- a/docs/investigations/views-perf-hunt-2026-09-16.md +++ b/docs/investigations/views-perf-hunt-2026-09-16.md @@ -181,8 +181,8 @@ Verification completed before the drill: - `RUSTFLAGS='-D warnings' cargo check -p agent-file-tools --lib --bin aft -j 4`: passed. - The three ownership/migration/navigation unit tests above: passed after implementation and after mutation restore. -- `cargo test -p agent-file-tools --test watcher_integration branch_switch`: 2 passed. -- `cargo test -p agent-file-tools --test integration tool_call_matches_direct_spine_envelopes`: passed (the 69-fixture parity matrix). +- `cargo test --features test-hooks -p agent-file-tools --test watcher_integration branch_switch`: 2 passed. +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_matches_direct_spine_envelopes`: passed (the 69-fixture parity matrix). ### Fresh-storage views-on drill diff --git a/docs/investigations/views-soak-2026-09/materialization-in-situ-2026-09-16.md b/docs/investigations/views-soak-2026-09/materialization-in-situ-2026-09-16.md index 56d2b5b53b..1889906a36 100644 --- a/docs/investigations/views-soak-2026-09/materialization-in-situ-2026-09-16.md +++ b/docs/investigations/views-soak-2026-09/materialization-in-situ-2026-09-16.md @@ -120,11 +120,11 @@ checkpoint omission rather than just a matching path or a no-op publication. ### Gates -- `cargo test -p agent-file-tools --test view_assembly_wiring_test`: unavailable +- `cargo test --features test-hooks -p agent-file-tools --test view_assembly_wiring_test`: unavailable in this base; the file is a module of the `integration` target. - Equivalent integration module: 6 passed. Publication/CAS, migration, schema, pins/GC, and staging selected integration modules: 44 passed. -- `cargo test -p agent-file-tools --test watcher_integration branch_switch`: +- `cargo test --features test-hooks -p agent-file-tools --test watcher_integration branch_switch`: 2 passed (134.18 s). This real-watcher matrix is intentionally registered in the serial watcher binary, not the parallel integration binary. An accidental duplicate registration in integration/main.rs was reverted before committing. @@ -313,7 +313,7 @@ acceptance. It provides a measured bucket answer and two proven lifecycle fixes. that this is the separately named 69-fixture parity gate). - The selected publication/CAS/migration/schema/pins/staging/assembly integration command above: 44 passed on final product code. -- `cargo test -p agent-file-tools --test watcher_integration branch_switch`: +- `cargo test --features test-hooks -p agent-file-tools --test watcher_integration branch_switch`: 2 passed on final code (126.84 s), including the return-leg embedding/put checks. - Both compiler deny-warnings targets and release build passed on final code. - Final offline paired replay passed full cold-row parity. @@ -574,10 +574,10 @@ reader changes, or legacy-plane retirement is included in this delivery. ### Final verification -- `cargo test -p agent-file-tools --test integration tool_call_parity_test`: +- `cargo test --features test-hooks -p agent-file-tools --test integration tool_call_parity_test`: 12 passed, including the owner-confirmed 69-fixture `tool_call_matches_direct_spine_envelopes` matrix, with default views-off. -- `cargo test -p agent-file-tools --test watcher_integration branch_switch`: +- `cargo test --features test-hooks -p agent-file-tools --test watcher_integration branch_switch`: 2 passed (134.20 s), including views-on round-trip reuse and the branch matrix. - `cargo test --release -p agent-file-tools --lib -- views::materialization::tests callgraph_store::join::`: 46 passed, 2 ignored, on final test-control code. diff --git a/docs/investigations/views-storage-growth-2026-10.md b/docs/investigations/views-storage-growth-2026-10.md index 48cc384102..8b108762a8 100644 --- a/docs/investigations/views-storage-growth-2026-10.md +++ b/docs/investigations/views-storage-growth-2026-10.md @@ -255,7 +255,7 @@ proof. No mutant remains. Final Linux gates on rustc 1.99.0 / cargo 1.99.0: - `cargo fmt --all -- --check`: exit 0 (rustfmt 1.10.0-stable). - `cargo check -p agent-file-tools --tests`: `Finished dev`, passed. -- `cargo test -p agent-file-tools --test integration -- view_assembly_wiring_test`: +- `cargo test --features test-hooks -p agent-file-tools --test integration -- view_assembly_wiring_test`: 9 passed, 1 existing full-checkout profiling test ignored. - `cargo test -p agent-file-tools --lib -- executor::view_publication::tests`: 15 passed. @@ -664,9 +664,9 @@ modified by this implementation or its censuses. Policy-update final Rust verification on Linux (rustc/cargo 1.99.0, rustfmt 1.10.0-stable): formatting and package-with-tests checking passed; `cargo test -p agent-file-tools --lib -- storage_retention` passed **35 tests**; -`cargo test -p agent-file-tools --test integration -- per_checkout_registry` +`cargo test --features test-hooks -p agent-file-tools --test integration -- per_checkout_registry` passed **16 tests** (one child fixture ignored in the parent run); -`cargo test -p agent-file-tools --test integration -- pins_gc_test` passed +`cargo test --features test-hooks -p agent-file-tools --test integration -- pins_gc_test` passed **4 tests**. Commands used the Linux guard and isolated HOME/XDG storage. Scoped inspection remained partial; the successful package check is authoritative. The pre-existing unavailable MinGW compiler still prevents claiming a Windows diff --git a/docs/investigations/windows-ci-flake-family-census-2026-08-29.md b/docs/investigations/windows-ci-flake-family-census-2026-08-29.md index b009b852eb..d2cca30b83 100644 --- a/docs/investigations/windows-ci-flake-family-census-2026-08-29.md +++ b/docs/investigations/windows-ci-flake-family-census-2026-08-29.md @@ -45,7 +45,7 @@ Deterministic contention used one inspect worker plus the existing 300 ms Tier-2 ```text AFT_INSPECT_POOL_THREADS=1 AFT_TEST_TIER2_REUSE_DELAY_MS=300 \ - cargo test -p agent-file-tools --test integration \ + cargo test --features test-hooks -p agent-file-tools --test integration \ inspect_tier2_scheduler_test::linked_worktree_explicit_inspect_keeps_parent_aggregates_byte_identical \ -- --exact --nocapture ``` diff --git a/docs/investigations/windows-watcher-overflow-2026-09.md b/docs/investigations/windows-watcher-overflow-2026-09.md index d25f63f66e..9f108ee3a3 100644 --- a/docs/investigations/windows-watcher-overflow-2026-09.md +++ b/docs/investigations/windows-watcher-overflow-2026-09.md @@ -49,7 +49,7 @@ test result: ok. 2 passed; 0 failed The overflow test holds the completion consumer while 5,000 files are created with the test-only 256-byte buffer, then routes the native overflow through the production filter. It receives exactly one `RescanRequired(BufferOverflow)`. Replacing the buffer-overflow mapping with `Unknown` under the `NON-VACUITY BREAK` mutation made that exact test fail alone (`0 passed; 1 failed`); restoring the file returned the diff stat to empty. ```text -cargo nextest run -p agent-file-tools --test watcher_integration --no-fail-fast +cargo nextest run --features test-hooks -p agent-file-tools --test watcher_integration --no-fail-fast Starting 23 tests across 1 binary Summary [113.705s] 23 tests run: 23 passed (1 slow), 0 skipped ``` diff --git a/docs/performance-producer-bounds.md b/docs/performance-producer-bounds.md index acfc1c9c3c..ba345b3bbb 100644 --- a/docs/performance-producer-bounds.md +++ b/docs/performance-producer-bounds.md @@ -52,8 +52,8 @@ PERF-31 now bounds both `CallGraphStore::call_tree` and the distinct command-ada - `cargo check -p agent-file-tools --locked`: passed after each Rust area. - `cargo check -p agent-file-tools --tests --locked`: passed, including library test compilation. This caught and prompted restoration of a test-only forward-call helper. -- Final combined `cargo test -p agent-file-tools --test engine_anchored_test --test engine_fallback_test --test engine_exact_test --test engine_trailer_contract_test --test read_producer_bounds_test --test outline_producer_bounds_test -- --nocapture`: 53 passed. -- `cargo test -p agent-file-tools --test callgraph_store_test -- --nocapture`: 38 passed, 1 ignored. Existing live poisoned-DB-copy test self-skipped because that optional fixture was absent. +- Final combined `cargo test --features test-hooks -p agent-file-tools --test engine_anchored_test --test engine_fallback_test --test engine_exact_test --test engine_trailer_contract_test --test read_producer_bounds_test --test outline_producer_bounds_test -- --nocapture`: 53 passed. +- `cargo test --features test-hooks -p agent-file-tools --test callgraph_store_test -- --nocapture`: 38 passed, 1 ignored. Existing live poisoned-DB-copy test self-skipped because that optional fixture was absent. - Bridge producer, durable-log, and transport tests: 36 passed; package `typecheck` and `build` passed. No manifests or lockfiles changed; no install required. - Separate safe mutations disabled the stderr fragment cap and durable queue cap. Each named corresponding producer regression alone reddened while its sibling remained green. Both mutations were staged-safe and restored, with empty unstaged diffs afterward. - AFT inspect timed out twice at LSP quiescence, including a single-file diagnostic scope. Cargo checks are the authoritative diagnostic evidence. diff --git a/docs/test-executable-consolidation.md b/docs/test-executable-consolidation.md index 28d89e1280..31872434c8 100644 --- a/docs/test-executable-consolidation.md +++ b/docs/test-executable-consolidation.md @@ -49,12 +49,12 @@ Cargo registry/toolchain and machine were shared with other workers. | Measurement | Before | After | | --- | ---: | ---: | -| `cargo test -p agent-file-tools --no-run` test executables | 81 | 16 | +| `cargo test --features test-hooks -p agent-file-tools --no-run` test executables | 81 | 16 | | Integration test executables within that count | 77 | 12 | | Cold `--no-run` wall time | 440.18 s | 1076.11 s | | Cold build user CPU time | 381.10 s | 317.64 s | | Cold build system CPU time | 80.24 s | 107.21 s | -| `cargo nextest list -p agent-file-tools` test count | 7305 | 7305 | +| `cargo nextest list --features test-hooks -p agent-file-tools` test count | 7305 | 7305 | | Ignored tests in that inventory | 84 | 84 | The executable count falls by 65 (80.2%). These wall-time samples are not a @@ -86,7 +86,7 @@ which prefers `AFT_TEST_AFT_BINARY`, then nextest's `NEXTEST_BIN_EXE_aft`, then Cargo's build-time path, so it keeps working from a relocated nextest archive. Pointing `AFT_TEST_AFT_BINARY` at a missing file makes its tests fail at launch, which shows the folded module goes through that helper. -`cargo nextest list -p agent-file-tools --run-ignored all`: 82 to 16 test +`cargo nextest list --features test-hooks -p agent-file-tools --run-ignored all`: 82 to 16 test executables, 7541 tests and 89 ignored before and after, and the sorted multiset of (source, test name, ignore flag) is identical once the folded module prefix is accounted for. diff --git a/scripts/ally-gate.sh b/scripts/ally-gate.sh index ef25bce9fd..0370618f71 100755 --- a/scripts/ally-gate.sh +++ b/scripts/ally-gate.sh @@ -33,7 +33,7 @@ echo "== nextest on ally: $FILTER" # Bare runner over ssh; ssh propagates the remote exit code, which is this # script's verdict. No pipes between the runner and the gate (rule 8231). ssh -o BatchMode=yes "$ALLY" \ - "cd ~/aft && git fetch origin ally-gate && git reset --hard FETCH_HEAD && cargo nextest run -p agent-file-tools -E \"$FILTER\" --no-fail-fast" + "cd ~/aft && git fetch origin ally-gate && git reset --hard FETCH_HEAD && cargo nextest run --features test-hooks -p agent-file-tools -E \"$FILTER\" --no-fail-fast" rc=$? echo "ALLY_GATE_RC=$rc" exit $rc diff --git a/scripts/check-secret-test-fake.sh b/scripts/check-secret-test-fake.sh index 92be6fa2d3..add226386a 100755 --- a/scripts/check-secret-test-fake.sh +++ b/scripts/check-secret-test-fake.sh @@ -1,12 +1,11 @@ #!/usr/bin/env bash -# V5: a release build must never compile the test-only secret vault. +# A release build must never compile the test-only secret vault or fixture hooks. # # The feature `secret-test-fake` compiles a vault that hands out key material on # request. If a shipped build enabled it, a released binary could substitute -# fake keys. Cargo profiles cannot turn crate features on, so this guard checks -# the two places a build graph can: a feature that already requires -# `secret-test-fake` (which a profile would pick up through `--features`), and a -# dependency edge that requests it on behalf of another crate. +# fake keys. The fixture hooks allow test inputs and executable overrides. +# Cargo profiles cannot enable crate features, so this guard checks default +# feature sets and dependency edges that could enable either test-only feature. # # It reads the workspace manifests directly. `cargo metadata` would need the # network on a clean runner, and this check must run before any build artifact @@ -16,7 +15,6 @@ set -euo pipefail repo_root="$(git rev-parse --show-toplevel)" cd "$repo_root" -feature="secret-test-fake" status=0 fail() { @@ -35,14 +33,15 @@ dependency_lines() { ' "$manifest" } -# The feature block of the crate that owns the fake: `secret-test-fake` must -# stay a standalone, opt-in switch with no `default` path to it. +# Both test-only features must stay standalone opt-in switches, with no default +# or dependency edge enabling them in a production build. +for feature in secret-test-fake test-hooks; do fake_owner="./crates/aft/Cargo.toml" if [[ ! -f "$fake_owner" ]]; then - fail "$fake_owner is missing, so the fake cannot be checked" + fail "$fake_owner is missing, so $feature cannot be checked" else if ! grep -Eq "^[[:space:]]*$feature[[:space:]]*=[[:space:]]*\[[[:space:]]*\][[:space:]]*$" "$fake_owner"; then - fail "$fake_owner must declare $feature = [] with no other feature behind the fake" + fail "$fake_owner must declare $feature = [] as a standalone opt-in feature" fi # A `default` line that names the fake turns it on for every ordinary build. while IFS= read -r default_line; do @@ -79,9 +78,10 @@ while IFS= read -r manifest; do fi done < <(dependency_lines "$manifest" | grep -E 'agent-file-tools' || true) done < <(find . -name Cargo.toml -not -path './target/*' -not -path './node_modules/*' | sort) +done if [[ "$status" -ne 0 ]]; then printf 'secret-test-fake guard: FAILED\n' >&2 exit 1 fi -printf 'secret-test-fake guard: ok (%d manifests, %s stays opt-in)\n' "$checked" "$feature" +printf 'secret-test-fake guard: ok (%d manifests, secret-test-fake and test-hooks stay opt-in)\n' "$checked" diff --git a/scripts/check-secret-test-fake.test.sh b/scripts/check-secret-test-fake.test.sh index f36802a188..e69a95b490 100755 --- a/scripts/check-secret-test-fake.test.sh +++ b/scripts/check-secret-test-fake.test.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Proves `scripts/check-secret-test-fake.sh` fails when the fake would ship. +# Proves the release guard fails when either test-only feature would ship. # # Runs the guard against a throwaway copy of the workspace manifests, with one # change each time: a dependency edge that requests the feature, a `default` @@ -50,24 +50,28 @@ clean="$work/clean" copy_manifests "$clean" expect_ok "the committed manifests" "$clean" -# 1. A dependency edge in another crate requests the fake. +# Check both features independently so protecting the fake cannot mask a missing +# fixture-hook guard. +for feature in secret-test-fake test-hooks; do +# 1. A dependency edge in another crate requests the feature. edge="$work/edge" copy_manifests "$edge" -printf '\n[dev-dependencies]\nagent-file-tools = { path = "../aft", features = ["secret-test-fake"] }\n' \ +printf '\n[dev-dependencies]\nagent-file-tools = { path = "../aft", features = ["%s"] }\n' "$feature" \ >>"$edge/crates/aft-tokenizer/Cargo.toml" -expect_fail "a dependency edge requesting the fake" "$edge" +expect_fail "a dependency edge requesting $feature" "$edge" -# 2. A default feature set names the fake. +# 2. A default feature set names the test-only feature. default="$work/default" copy_manifests "$default" -perl -0pi -e 's/\[features\]\n/[features]\ndefault = ["secret-test-fake"]\n/' \ +FEATURE="$feature" perl -0pi -e 's/\[features\]\n/[features]\ndefault = ["$ENV{FEATURE}"]\n/' \ "$default/crates/aft/Cargo.toml" -expect_fail "a default feature naming the fake" "$default" +expect_fail "a default feature naming $feature" "$default" # 3. Another crate declares its own feature of the same name. impostor="$work/impostor" copy_manifests "$impostor" -printf '\n[features]\nsecret-test-fake = []\n' >>"$impostor/crates/aft-tokenizer/Cargo.toml" -expect_fail "an impostor feature in another crate" "$impostor" +printf '\n[features]\n%s = []\n' "$feature" >>"$impostor/crates/aft-tokenizer/Cargo.toml" +expect_fail "an impostor $feature in another crate" "$impostor" +done -printf 'secret-test-fake guard self-test: ok (1 pass, 3 failures)\n' +printf 'secret-test-fake guard self-test: ok (1 pass, 6 failures)\n' diff --git a/scripts/ci-macos-integration-archive.py b/scripts/ci-macos-integration-archive.py index 2376fc153c..2826d0fec6 100644 --- a/scripts/ci-macos-integration-archive.py +++ b/scripts/ci-macos-integration-archive.py @@ -30,7 +30,7 @@ def integration_targets(metadata: dict) -> list[str]: def command(metadata: dict, mode: str, archive_file: str | None = None) -> list[str]: # A nextest filterset selects archive/list contents only: cargo still builds # every default test target unless explicit Cargo target selectors are used. - args = ["cargo", "nextest", mode, "--workspace"] + args = ["cargo", "nextest", mode, "--workspace", "--features", "test-hooks"] for name in integration_targets(metadata): args.extend(["--test", name]) args.extend(["-E", FILTER]) diff --git a/scripts/flake-hunt.sh b/scripts/flake-hunt.sh index 6f978c546c..6ad8597c15 100755 --- a/scripts/flake-hunt.sh +++ b/scripts/flake-hunt.sh @@ -178,6 +178,7 @@ for (( iteration = 1; iteration <= iterations; iteration++ )); do nextest_cmd=( cargo nextest run + --features test-hooks -p "$package" --no-fail-fast --failure-output immediate-final diff --git a/scripts/lib/test_ci_macos_integration_archive.py b/scripts/lib/test_ci_macos_integration_archive.py index c9bb79be14..9b3dd192c8 100644 --- a/scripts/lib/test_ci_macos_integration_archive.py +++ b/scripts/lib/test_ci_macos_integration_archive.py @@ -42,6 +42,7 @@ def test_archive_and_source_inventory_use_explicit_cargo_test_targets(self): self.assertNotIn("--tests", args) self.assertNotIn("--all-targets", args) self.assertIn("--workspace", args) + self.assertEqual(args[args.index("--features") + 1], "test-hooks") self.assertIn(plan.FILTER, args) def test_future_integration_targets_are_not_silently_dropped(self): diff --git a/scripts/lib/test_ci_storm_inventory.py b/scripts/lib/test_ci_storm_inventory.py index 2f76cab0f4..60dbaeb881 100644 --- a/scripts/lib/test_ci_storm_inventory.py +++ b/scripts/lib/test_ci_storm_inventory.py @@ -63,7 +63,8 @@ def test_both_lto_options_run_the_same_normal_inventory(self): self.assertIn("--profile default --cargo-profile ci-storm", commands) self.assertIn("test(subc_storm)", commands) self.assertIn("--check-inventory", commands) - self.assertNotIn("--features", commands) + self.assertEqual(commands.count("--features test-hooks"), 3) + self.assertNotIn("test-timing-hooks", commands) if __name__ == "__main__": diff --git a/scripts/lib/test_windows_gate.sh b/scripts/lib/test_windows_gate.sh index 9676b36bf8..c24e949a16 100644 --- a/scripts/lib/test_windows_gate.sh +++ b/scripts/lib/test_windows_gate.sh @@ -74,8 +74,10 @@ esac SH chmod +x "$temp/uname" "$temp/git" output=$(PATH="$temp:$PATH" bash "$script" --plan 2>&1) + [[ "$output" == *'--lib search_index::'* && "$output" != *'--features test-hooks'* ]] || fail "${FUNCNAME[0]}" + output=$(PATH="$temp:$PATH" bash "$script" --plan --test-target integration --features test-timing-hooks 2>&1) + [[ "$output" == *'--test integration --features test-hooks --features test-timing-hooks'* ]] || fail "${FUNCNAME[0]} integration hooks" rm -rf "$temp" - [[ "$output" == *'--lib search_index::'* ]] || fail "${FUNCNAME[0]}" printf 'PASS: %s\n' "${FUNCNAME[0]}" } diff --git a/scripts/lib/test_workflow_gates.py b/scripts/lib/test_workflow_gates.py index 768458fa23..df0a6eb7f2 100644 --- a/scripts/lib/test_workflow_gates.py +++ b/scripts/lib/test_workflow_gates.py @@ -906,7 +906,7 @@ def test_bash_timeout_contract_reuses_the_macos_conformance_build(self) -> None: self.assertIn('"$test_name" -- --exact', timeout_step) self.assertIn("expected test missing from integration inventory", timeout_step) self.assertIn( - "cargo test -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation", + "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation", GATE_TEXT, ) @@ -972,7 +972,7 @@ def test_macos_libtest_downloads_verify_before_extract(self) -> None: self.assertLess(steps.index(download), consumer) def test_macos_backtrace_probe_runs_once_in_archive_builder_not_shards(self) -> None: - probe = "cargo test -p agent-file-tools --lib panic_hook_preserves_default_backtrace_behavior_and_persists" + probe = "cargo test -p agent-file-tools --features test-hooks --lib panic_hook_preserves_default_backtrace_behavior_and_persists" archive = workflow_job("unit-macos-libtest-archive") shard = workflow_job("unit-macos-libtest-shard") diff --git a/scripts/rust-test-gate.sh b/scripts/rust-test-gate.sh index 4d8d73c917..25e4a93845 100755 --- a/scripts/rust-test-gate.sh +++ b/scripts/rust-test-gate.sh @@ -349,7 +349,7 @@ warm_macos_test_binaries() { # field in the build JSON — not the incremental fragments under deps/). $@ = # the cargo build arguments that define the profile and scope. local bins - bins="$(cargo test "$@" --no-run --message-format=json 2>/dev/null | python3 -c " + bins="$(cargo test --features test-hooks "$@" --no-run --message-format=json 2>/dev/null | python3 -c " import sys, json seen = set() for line in sys.stdin: @@ -393,7 +393,7 @@ if [[ "$runner" == "cargo" ]]; then run_phase "warm macOS Gatekeeper assessment: sign + exec debug test binaries and target/debug/aft" \ warm_macos_test_binaries --workspace fi - run_phase "cargo test --workspace --quiet" gate_cargo test --workspace --quiet + run_phase "cargo test --features test-hooks --workspace --quiet" gate_cargo test --features test-hooks --workspace --quiet finish_gate exit 0 fi @@ -429,7 +429,7 @@ extract_nextest_archive_for_prewarm() { --no-pager >/dev/null } -# `cargo test --workspace -- --list` currently reports zero doctests for both +# `cargo test --features test-hooks --workspace -- --list` currently reports zero doctests for both # workspace crates (`aft` and `aft_tokenizer`), so the split gate omits # `cargo test --workspace --doc` until doctests actually exist. # @@ -525,8 +525,8 @@ if phase_enabled lib; then && [[ -n "${AFT_NEXTEST_ARCHIVE_FILE:-}" && "$(uname)" != "Darwin" ]]; then # Windows needs its local PDB for the child backtrace; the macOS archive job # runs this probe before upload while its linked debug objects are present. - run_phase "cargo test -p agent-file-tools --lib panic_hook_preserves_default_backtrace_behavior_and_persists --quiet (serial: child backtrace needs the local PDB)" \ - gate_cargo test -p agent-file-tools --lib panic_hook_preserves_default_backtrace_behavior_and_persists --quiet + run_phase "cargo test -p agent-file-tools --features test-hooks --lib panic_hook_preserves_default_backtrace_behavior_and_persists --quiet (serial: child backtrace needs the local PDB)" \ + gate_cargo test -p agent-file-tools --features test-hooks --lib panic_hook_preserves_default_backtrace_behavior_and_persists --quiet fi # When lib-shard is selected, the archive-backed command below owns the rest @@ -608,8 +608,8 @@ if phase_enabled nextest; then nextest_label="cargo nextest run --archive-file $AFT_NEXTEST_ARCHIVE_FILE -E kind(test) - binary(=watcher_integration)" nextest_args+=(--archive-file "$AFT_NEXTEST_ARCHIVE_FILE") else - nextest_label="cargo nextest run --workspace -E kind(test) - binary(=watcher_integration)" - nextest_args+=(--workspace) + nextest_label="cargo nextest run --features test-hooks --workspace -E kind(test) - binary(=watcher_integration)" + nextest_args+=(--workspace --features test-hooks) fi nextest_args+=(-E 'kind(test) - binary(=watcher_integration)') if [[ -n "${AFT_NEXTEST_PARTITION:-}" ]]; then @@ -622,21 +622,21 @@ fi if phase_enabled watcher; then # test-timing-hooks compiles in the test-only gates the linked-worktree # semantic quiet-window test holds; without the feature that test is not built. - run_phase "cargo test -p agent-file-tools --features test-timing-hooks --test watcher_integration --quiet -- --test-threads=1" \ - gate_cargo test -p agent-file-tools --features test-timing-hooks --test watcher_integration --quiet -- --test-threads=1 + run_phase "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test watcher_integration --quiet -- --test-threads=1" \ + gate_cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test watcher_integration --quiet -- --test-threads=1 fi if phase_enabled conformance; then - run_phase "cargo test -p agent-file-tools --features test-timing-hooks --test rest -- scope_end_kill" \ - gate_cargo test -p agent-file-tools --features test-timing-hooks --test rest -- scope_end_kill - run_phase "cargo test -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation" \ - gate_cargo test -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation - run_phase "cargo test -p agent-file-tools --features test-timing-hooks --test rest -- tool_provider_conformance" \ - gate_cargo test -p agent-file-tools --features test-timing-hooks --test rest -- tool_provider_conformance + run_phase "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test rest -- scope_end_kill" \ + gate_cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test rest -- scope_end_kill + run_phase "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation" \ + gate_cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- scope_revocation + run_phase "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test rest -- tool_provider_conformance" \ + gate_cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test rest -- tool_provider_conformance # Keep promotion failure, deadline handoff, and elicitation TTL coverage in # the hook-enabled phase; ordinary production builds cannot inject them. - run_phase "cargo test -p agent-file-tools --features test-timing-hooks --test integration -- subc_bridge_bash_promote subc_bridge_bash_started_promotion subc_bridge_bash_late_promote subc_bridge_untrusted_bash_elicitation_ttl" \ - gate_cargo test -p agent-file-tools --features test-timing-hooks --test integration -- subc_bridge_bash_promote subc_bridge_bash_started_promotion subc_bridge_bash_late_promote subc_bridge_untrusted_bash_elicitation_ttl + run_phase "cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- subc_bridge_bash_promote subc_bridge_bash_started_promotion subc_bridge_bash_late_promote subc_bridge_untrusted_bash_elicitation_ttl" \ + gate_cargo test --features test-hooks -p agent-file-tools --features test-timing-hooks --test integration -- subc_bridge_bash_promote subc_bridge_bash_started_promotion subc_bridge_bash_late_promote subc_bridge_untrusted_bash_elicitation_ttl fi # The main subc storm test asserts production-calibrated absolute latencies @@ -653,8 +653,8 @@ if phase_enabled storm; then else # Storm is intentionally on the retry-free default nextest profile: a retry # would hide a real latency regression behind a second warm attempt. - run_phase "cargo nextest run --profile default --cargo-profile release -E 'test(subc_storm)' (release-calibrated latency bounds)" \ - gate_cargo nextest run --profile default --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm)' + run_phase "cargo nextest run --features test-hooks --profile default --cargo-profile release -E 'test(subc_storm)' (release-calibrated latency bounds)" \ + gate_cargo nextest run --features test-hooks --profile default --cargo-profile release -p agent-file-tools --test integration -E 'test(subc_storm)' fi fi diff --git a/scripts/rust-test-inventory-proof.py b/scripts/rust-test-inventory-proof.py index f16272996f..b6f15a91a4 100755 --- a/scripts/rust-test-inventory-proof.py +++ b/scripts/rust-test-inventory-proof.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 """Prove that every Rust test lands in exactly one split-gate bucket. -By default, this script captures the current workspace inventory from `cargo test +By default, this script captures the current workspace inventory from `cargo test --features test-hooks --workspace -- --list`, then compares it against the split buckets used by `scripts/rust-test-gate.sh`: -* `cargo nextest list --workspace --lib --bins` -* `cargo nextest list --workspace -E 'kind(test) - binary(=watcher_integration)'` -* `cargo test -p agent-file-tools --test watcher_integration` +* `cargo nextest list --features test-hooks --workspace --lib --bins` +* `cargo nextest list --features test-hooks --workspace -E 'kind(test) - binary(=watcher_integration)'` +* `cargo test --features test-hooks -p agent-file-tools --test watcher_integration` When `AFT_NEXTEST_ARCHIVE_FILE` is set, the archived test inventory is also compared by test identity with the non-watcher nextest bucket. macOS can provide @@ -624,7 +624,7 @@ def archive_command(archive_path: str) -> list[str]: sys.exit(0) -baseline_output = run_command(["cargo", "test", "--workspace", "--", "--list"]) +baseline_output = run_command(["cargo", "test", "--workspace", "--features", "test-hooks", "--", "--list"]) baseline_entries = parse_cargo_list(baseline_output) unit_bin_command = [ @@ -633,6 +633,10 @@ def archive_command(archive_path: str) -> list[str]: "list", "--profile", "gate", + # The same features the CI archive builds with, so listing reuses its + # compiled library instead of building a second copy without the hooks. + "--features", + "test-hooks", "--workspace", "--lib", "--bins", @@ -677,13 +681,17 @@ def archive_command(archive_path: str) -> list[str]: doc_baseline_entries = [entry for entry in baseline_entries if entry.kind == "doc"] doc_entries: list[CargoEntry] = [] if doc_baseline_entries: - doc_output = run_command(["cargo", "test", "--workspace", "--doc", "--", "--list"]) + doc_output = run_command( + ["cargo", "test", "--workspace", "--features", "test-hooks", "--doc", "--", "--list"] + ) doc_entries = [entry for entry in parse_cargo_list(doc_output) if entry.kind == "doc"] nextest_command = [ "cargo", "nextest", "list", + "--features", + "test-hooks", "--profile", "gate", "--workspace", @@ -722,6 +730,8 @@ def archive_command(archive_path: str) -> list[str]: watcher_output = run_command([ "cargo", "test", + "--features", + "test-hooks", "-p", "agent-file-tools", "--test", diff --git a/scripts/windows-gate.sh b/scripts/windows-gate.sh index 770a13fe03..0c2c2667fa 100755 --- a/scripts/windows-gate.sh +++ b/scripts/windows-gate.sh @@ -177,6 +177,7 @@ print_job() { local kind=$1 target=$2 test_filter=$3 local -a args=(test --locked -j 4 -p agent-file-tools "--$kind") [[ -z "$target" ]] || args+=("$target") + [[ "$kind" != test ]] || args+=(--features test-hooks) [[ -z "$features" ]] || args+=(--features "$features") [[ -z "$test_filter" ]] || args+=("$test_filter") args+=(-- --test-threads 4) @@ -239,6 +240,7 @@ run_job() { local kind=$1 target=$2 test_filter=$3 label=$4 remaining output code local -a args=(test --locked -j 4 -p agent-file-tools "--$kind") [[ -z "$target" ]] || args+=("$target") + [[ "$kind" != test ]] || args+=(--features test-hooks) [[ -z "$features" ]] || args+=(--features "$features") [[ -z "$test_filter" ]] || args+=("$test_filter") args+=(-- --test-threads 4)