ci: macOS confine leg + CONTRACTS.md exit-code contract#114
Merged
Conversation
Wave-0 items B1a + E11 from docs/ROADMAP-ADOPTION.md. - ci.yml: a macos-latest job running `pnpm dogfood:confine`, so the flagship --confine OS-sandbox enforcement path is CI-verified (the ubuntu matrix cannot exercise Seatbelt / sandbox-exec). Full unit suite intentionally not run there (a few tests are darwin-env sensitive); the dogfood is the enforcement contract. - docs/CONTRACTS.md: the exit-code table CI can depend on (sync --check = 2 on drift, up --frozen fail-closed = 1, ...), config/lock format versions, --json stability (only sync --json frozen), and semver-exempt ~/.mcpm internals. - cli-smoke.test.ts: end-to-end exit-code assertions backing the contract (sync --check drift = 2 with a no-drift positive control; up --frozen missing stack = 1).
The macOS CI leg (added in this PR) immediately caught a latent test-isolation bug: the tamper step removed pins.json to isolate the confine gate, but left the pins.json.integrity sidecar behind. The happy-path step just before it runs a real tools/list that TOFU-writes BOTH files off-thread, so on a (slower) CI runner the sidecar had landed -> readPins saw a sidecar with no matching file -> PINS-READ-ERROR fired first and masked the CONFINE hash-mismatch gate under test. Timing-dependent, which is why it passed locally. Now removes pins.json, its .integrity sidecar, and any stale .lock so readPins sees a clean first-run state.
…contracts # Conflicts: # CHANGELOG.md
m1ngshum
added a commit
that referenced
this pull request
Jul 3, 2026
…it) (#119) The macOS confine dogfood intermittently failed the tamper assertion with 'failed closed on pins, not confine — gate not isolated' (seen again on a docs-only PR #118, proving it's nondeterministic). #114 narrowed this by deleting the whole pins sidecar set before tampering, but couldn't beat the real cause: an async writer in another process. Root cause: driveHappy() resolved the instant the 3rd JSON-RPC response arrived and did child.kill() WITHOUT waiting for exit. The relay child's off-thread pins TOFU write (pins.json + .integrity, triggered by tools/list) was still in flight when control returned, so it landed AFTER the tamper step's rmSync — recreating a partial pins state, so the tampered run's readPins raised PINS-READ-ERROR and failed closed for an UNRELATED reason, masking the CONFINE gate under test. Fix: driveHappy() now resolves only on the child's 'exit' event (with a 2s SIGKILL escalation if SIGTERM stalls). Once the process is gone, no write from it can land after the delete, so the rmSync is final. Test-harness only — no product code; the confine enforcement path itself was always correct (secret read denied EPERM). Verified 3x locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wave 0 (credibility floor) — items B1a + E11 from
docs/ROADMAP-ADOPTION.md. Both are CI/contract hardening; no product-code change.B1a — macOS confine CI leg
Adds a
macos-latestjob toci.ymlthat runs the hermeticpnpm dogfood:confine. The--confineOS sandbox (Seatbelt /sandbox-exec) is macOS-only and the ubuntu matrix cannot exercise it — until now it was "verified locally, untested in CI" (a gapdocs/ROADMAP.mdcalls out twice). The full unit suite is intentionally not run on macOS (a couple of tests are darwin-env sensitive — real-keychain migrate count, chalk TTY detection); the dogfood is the enforcement contract that matters.E11 — CONTRACTS.md + exit-code smoke tests
docs/CONTRACTS.md— the stability promise for the0.xline: the exit codes CI can depend on (notablysync --check→2on drift,up --frozenfail-closed →1,upblocks regardless of--ci), the versionedmcpm.yaml(version: "1") /mcpm-lock.yaml(lockfileVersion: 1) formats, which--jsonshapes are stable (onlysync --jsonis frozen), and the semver-exempt~/.mcpminternals. It documents guarantees that already hold — nothing changes behaviourally.cli-smoke.test.ts— three end-to-end assertions backing the contract:sync --checkwith real cross-client drift exits2, a no-drift positive control exits0, andup --frozenwith a missing stack fails closed with1. Verified locally (10/10 smoke tests pass).Why
Enterprises automate against exit codes and need a written stability promise before they build CI gates on a
0.xtool; the macOS leg makes the flagship feature's "it works" claim CI-backed instead of trust-me.