v2026.9.2
Fixed
- A signal-killed tool is no longer reported as a missing binary.
spawnCmdbound onlycodefrom Node'scloseevent, which fires with(code, signal)and exactly one non-null — so a process killed by a signal arrived asexitCode: null, the same value a spawn that never started produces, andvalidateToolreported both asE_EVIDENCE_TOOL_UNAVAILABLE("binary missing or spawn error"). Measured in the field: a 41-minute monorepo test suite, traced live in/procwith seven vitest workers executing, reported as a missing binary; three operators verifiednpmandpnpmresolved underenv -ibefore anyone questioned the message. NewE_EVIDENCE_TOOL_KILLEDnames the signal, the elapsed time, the execution root and the output captured before the kill (gh#1381) (provenance: T12182) - A killed tool run no longer poisons the evidence cache. That
exitCode: nullwas persisted as a well-formed entry and served on the next verify without spawning anything. Where the tool runs off a non-git root,headanddirtyFingerprintare null too — and both are cache-key components, so the key could never change and the wrong answer was permanent.runToolCachedno longer writes a null-exitCodeentry, andreadCacheEntryrefuses one, which retires the entries already written by<= 2026.9.1since those cannot rotate themselves out (gh#1380, gh#1387) (provenance: T12182)
Notes
The memory ceiling that produces the kill is not the defect and is unchanged. withMemoryLimit (T12116) runs test and build inside a systemd scope with MemorySwapMax=0; without it the failure mode is a throttle-and-thrash host freeze that logs nothing at all, which is strictly worse to diagnose than a clean kill. The new message reports the signal as measured and the ceiling as configured, side by side, and does not assert OOM — SIGKILL inside a bounded scope is also what an operator's own kill -9 produces.
@cleocode/cleo is also republished, but its only source change is three trailing // raw-cr-allowed markers plus explanatory comments in llm-login.ts — the executable text is byte-identical (gh#1355).
Repository-only changes in this release, with no effect on any published artifact: the CI aggregate now names which jobs failed versus which were cancelled (gh#1358); gate 18 scans every tracked vitest config rather than root plus packages/* (gh#1354); gates 18 and 20 are wired into a workflow, having been documented and bundled but executed by nothing (gh#1394); pnpm lint's second half runs in CI, having been wired to nothing for 92 days (gh#1355); and cleo init --yes, a flag that never existed, is gone from worktree-cleanup.yml (gh#1373).