Keep the approval-identity test seam beside its only reader
Summary
Main's (7c05f9cdc) harness unit tests don't compile under --features filesystem, the plain native build without hooks. The error is E0433: cannot find hooks in crate, at runtime/tools.rs:217.
- Breaking commit: #982 (32a9ae569). It added an approval-identity negative-control switch to
crate::hooks::mcp_identity_tests. It also read that switch fromruntime::tools::tool_approval_bindingundercfg(all(test, not(wasm32))).hooksonly exists withfeature = "hooks", so every test build withouthooksstopped compiling. - Why the gate missed it: every native harness test suite in the gate runs with
--all-features, which always turnshookson. No gate step compiled the unit tests with an optional native feature switched off.
Fix
- The
SUBSTITUTE_APPROVAL_NAMEseam now lives next to its only reader, inruntime/tools.rs, under the samecfgas that reader. It therefore exists in every build that compiles the read. hooks::mcp_identity_testsrefers to it ascrate::runtime::SUBSTITUTE_APPROVAL_NAME.- The gate lane now runs
cargo check --locked -p acyclic-harness --features filesystem --lib --tests. test-plan-qualification.mjsasserts that the gate branch keeps that step.
Guarantee
- Class: a test-only seam whose owner sits behind a narrower
cfgthan its reader. The result is unit-test builds that fail to compile under feature sets the all-features gate never builds. - Structural fix: the seam is defined under exactly the
cfgof its reader, so it can't be missing where it's read. The gate now builds the unit-test closure without the optional native features. With onlyfilesystemon, the step catches any future seam that crosses thehooks, MCP, search, objects, machines, grpc or tui feature gates, not just this one. - Exhaustive proof:
- Under
--features filesystem --lib --tests, this branch compiles (bbBUILD_SLOT_TREEe6d5c6fdb on 7c05f9cdc, rc=0). - Negative control: the same command on unfixed main 7c05f9cdc fails with
E0433 cannot find hooks in crateatruntime/tools.rs:217(rc=101). - Under
--all-features,hooks::mcp_identity_testspasses, includingnegative_control_detects_approval_identity_substitution. So the seam still drives the approval-identity mutant through the moved switch. - CI-plan negative control: dropping
--testsfrom the new gate step makesnode scripts/test-plan-qualification.mjsfail. Restoring it passes 23/23.
- Under
- Entry points: there was one reader of the seam,
tool_approval_binding, and one writer,negative_control_detects_approval_identity_substitution. Both changed.SUBSTITUTE_HOOK_NAMEhas its reader and owner both underhooks, so it is unaffected. - Gaps: none.
Gate once
I ran cargo test --locked -p acyclic-harness -p acyclic-harness-providers --all-features --no-fail-fast once on head 321d201ad, which is main 7c05f9cdc plus this change. Then I compared it against the newest main gate, ws-4b9c84541:
- This branch: 19 failures.
- Main gate: 70 failures.
- Failures not in the main list: two. Both are known races on main that the children lane owns, and neither touches the moved seam:
work_tests::preparation_status_preserves_bytes_and_errors_without_loading_its_reportfails withConflict("workspace generation changed"). This is the #821 directory-record batch-observation race; the fix is in flight on hf/main-green-kind-only-lookups.work_tests::replay_admission_preserves_results_and_errors_with_zero_workspace_workfails because concurrent tests' work kinds leak into the trace. #1021 covers this.
Separately observed, not in scope
The plain --features filesystem lib (non-test) build has 10 pre-existing dead-code warnings, for example in task_volume/child_queries.rs:5, task_volume/files.rs:86 and durable_host/observations.rs:7. That's why the new gate step doesn't use -Dwarnings. I'm reporting it to the coordinator as a separate root cause.
🤖 Generated with Claude Code