Instrument MCP production synchronization in Loom models
Problem
MCP Loom verification used test-only atomic traits and had no negative controls. It also discarded worker results, so removing the final cancellation check passed. Moving tests behind cfg(loom) left routine qualification unable to run them.
Design
Route production cancellation and codec-bound atomics and Arc ownership through one crate-local cfg(loom) shim. The focused mcp-loom target compiles the production cancellation and codec source with instrumented ownership and atomics. Dependency runtimes remain outside these models.
The cancellation model retains the original cancellation/completion race and adds a controlled window: registration starts, the parent publishes cancellation, then the callback returns success. The model requires a cancelled result and released worker/connection ownership. Its negative controls omit the cancellation guard or the final check separately. The codec model runs the production encoder/decoder through catalog-to-tool handoff and detects omitted bound publication. Three positive cases and three detectable broken variants run exhaustively with two threads and no preemption/permutation truncation.
scripts/qualify-mcp-loom.mjs builds only the instrumented test target, locates its Cargo-reported executable and runs it directly. It rejects build/artifact failures, nonzero test status, zero execution, ignored tests and filtered tests. The qualification gate invokes this checked-in runner before nextest; the fixture exercises that dispatch. Runner unit tests cover zero/skipped/filtered execution and failed or ambiguous builds. The policy lane explicitly runs qualify-mcp-loom.test.mjs; the test asserts its own policy-lane registration.
Deletions
Remove CancelFlag/ByteLimit traits, generic sync substitutions and test-only atomic implementations. The codec fuzzer shares the production shim. No new production locks, channels or protocol. Full PR: +269/-96, net +173 lines. This review fix: +146/-10, net +136, predominantly model and qualification verification.
Decisions
- #572 merged before this correction. Start from origin/main at fd91afbaace3, then merge origin/main at 7f5aa0cdf533 with signed merge d633da34ad0b. Preserve both MCP-model and goal-files test declarations when resolving their Cargo conflict. Main advanced during validation; signed merge 1b8544050666 also includes origin/main 1013468ab8c5, preserving both notification features and Loom lint configuration in the fuzz manifest. #590 remains separate.
- cfg(loom) selects loom::sync::{Arc, atomic}; ordinary builds use std. Release/Acquire publication is unchanged. No new mutex or lock order.
- Production run always enables its private constant completion-check branch; only the model's deliberate mutant disables it. Both variants execute the same registration/check implementation.
- cargo rustc applies --cfg loom only to the model target. No global RUSTFLAGS change or dependency-runtime instrumentation claim.
- The CI gate forwards its existing --all-features closure to the runner. Focused lane validation uses the same hooks,mcp-stdio,mcp-http native closure and default features for both the compile gate and checked-in runner. No parallelism caps or incremental overrides.
Tests run
Signed head: 1caa646f61737c46689a7e8753a4ef42290805e9. All builds and execution through Q:/lanes/bs.ps1, warm target and incremental defaults.
- cargo test --no-run -p acyclic-harness --lib --features hooks,mcp-stdio,mcp-http: passed, default features included; 24.89 s compilation at the final merged head.
- Built native MCP suite directly: 50/50, 0.41 s wall. Existing registration deadlines, stable revisions, independent tool I/O bounds and shrinking properties pass.
- node scripts/qualify-mcp-loom.mjs: passed; runs the instrumented Cargo command from checked-in code, then its built binary. 6/6 tests, including missing-final-check detection; model runtime under 0.01 s, runner plus incremental model build 0.38 s wall at the final merged head.
- node --test scripts/qualify-mcp-loom.test.mjs scripts/test-plan-qualification-gate.mjs: 4/4, 0.46 s wall.
- bash scripts/test-qualify-ci-preflight.sh: passed, 4.41 s wall; exercises gate dispatch and model-artifact execution using the shared offline fixture.
- Unchanged codec source/parser verification from the initial correction: ASan fuzz build 2.26 s; 512 runs from checked-in seeds with 4096-byte/3-second bounds, 0.52 s wall. Existing shrinking codec round-trip and atomic-rejection properties pass in the native MCP suite.
- rustfmt --check and git diff --check pass. All execution suites are below 10 seconds; no sleeps or polling added.
Final gate log: /home/var/log/buildbox/2026-10-15T231234013Z-3314750.log (rc=0); includes a locked Cargo metadata check of the merged fuzz manifest. Unchanged runner/qualification fixture results: /home/var/log/buildbox/2026-10-15T230907736Z-3278155.log (rc=0). Earlier codec fuzz log: /home/var/log/buildbox/2026-10-15T225505264Z-3177258.log (rc=0).
Policy registration validation at the final signed head: attempted bash scripts/qualify-ci.sh policy once via bs.ps1. Static release checks passed, then the existing compatibility gate failed with stream descriptorDigest mismatch before reaching Node test commands (5.96 s). Focused runner tests passed 3/3 in 0.07 s; touched-feature/default compile check passed from warm artifacts in 0.33 s. Policy lane is not claimed green. No compatibility digest or unrelated gate was changed. Log: /home/var/log/buildbox/2026-10-15T232045038Z-3362927.log.