Move enforcement-gate state from ana work status to ana doctor

`ana work status` unconditionally prints `Capture gate: <state>` as its first content line (`work.ts:348`). Every agent runs `work status`, but the gate's state **does not change how any agent behaves** — it's mechanically enforced at the action (`applyCaptureGate` → `process.exit(1)` at `ana artifact save build-report`, `artifact.ts:860`). The agent learns at the moment it matters and is told exactly what to do. Foreknowledge in `work status` is pure chrome.

verdict PASSscore 17 / 18findings 4 (0 risk · 1 debt · 3 obs)duration 58mrejection cycles 0shipped Jun 8, 2026surface cli

Pipeline timeline

Intent to proven code in 58m across Think, Plan, Build, and Verify.

Think
16m
Plan
7m
Build
10m
Verify
7m

Assertion ledger

18 claims, each independently verified. Showing 8 — show all →

IDSaysMatcher
A001Pipeline status no longer announces the capture-gate state to agentsverifiedok
A002The machine-readable pipeline status drops the capture-gate flagverifiedok
A003The machine-readable pipeline status drops the gate-active flagverifiedok
A004Pipeline status still works and reports the artifact branch after the gate state is removedverifiedfail
A005Project health now includes an enforcement viewverifiedok
A006Health shows the test-evidence gate as active when it is on and a test command existsverifiedok
A007Health distinctly flags a turned-on gate that cannot enforce because no test command is configuredverifiedok
A008Health shows the test-evidence gate as off when the flag is absentverifiedok

Findings 4 total

debtpackages/cli/src/commands/doctor.tsscope
assessEnforcement parse-failure fallback (all-off) is untested — every enforcement test uses createMinimalProject which always writes a valid ana.json, so the try/catch catch branch never runs
obspackages/cli/tests/commands/config.test.tsmonitor
config A016-A018 are absence-only assertions (not.toContain 'not a known ana.json field') — they would pass vacuously if the config-set validation path no-op'd; they do not positively confirm the field was written. Contract-aligned (matcher is not_contains) but fragile as regression guards
obspackages/cli/src/commands/doctor.tsacknowledge
assessEnforcement reads ana.json twice per doctor run — once via the raw inline parse and once inside isCaptureGateEnabled. Deliberate and documented in the spec (correctness-without-duplication on a cold human-invoked path); recorded so it is revisited if doctor ever becomes a hot path
obspackages/cli/src/commands/work.tsclosed
The work.ts double-read of ana.json (inline captureGate parse + isCaptureGateEnabled call in getWorkStatus) is removed by this build — getWorkStatus now reads ana.json once for lastScanAt only. Resolves the previously-recorded performance observation

Provenance

Who ran what, and what it cost. Recomputable estimates from the shared price table — subordinate to the verdict, never gating.

model claude-opus-4-8
sessionturnstoolsinoutcachecost
ana59246.3k32.6k1.4M$1.99
plan55296.3k23.9k1.2M$1.62
build144667.5k35.8k4.6M$3.78
verify84346.6k24.2k1.8M$1.95
TOTAL 4 sessions$9.33 (table 2026-06-14)
churn 6 files · +209/−48
completeness ✓ complete (plan 1/1 · build 1/1 · verify 1/1)

Integrity seal

scopesha256:f8fa04e72f275...
contractsha256:ef2bb3a014b8d...
plansha256:e8fe2e17a2a72...
specsha256:3253e6fb0ad55...
build-reportsha256:2700502226ce2...
build-datasha256:39868ab1ff86c...
verify-reportsha256:76bfc26463923...
verify-datasha256:73b06286f65e8...
audit cmd$ ana proof audit enforcement-state-in-doctor   → all hashes match