Skip to content

v0.2.3

Choose a tag to compare

@coo1white coo1white released this 10 Jul 07:00
· 509 commits to main since this release

CW is now safe to run from many concurrent processes — state.json, the scheduler policy file, and the trust-audit log no longer lose updates or double-mint queue ids under a race, a Ctrl-C/SIGTERM mid-drive stops cleanly and resumes to completion, and a stuck agent times out and is SIGKILLed instead of hanging.

  • Capability: A many-process safety release. Ten verified concurrency/robustness bugs are fixed: state.json, the sched policy file, and the trust-audit log no longer lose updates under concurrent writers; withFileLock's stale-lock steal is race-free end to end (pid-liveness gate, single-winner link(2) acquire, and a serialized steal guard — each step forced by a real CI failure); two processes can no longer mint the same queue id and break through maxConcurrent; a chained trust-audit event with a dropped prevEventHash now fails closed; a stuck agent is SIGKILLed and reported as a real timeout instead of "failed to spawn"; an escape-heavy batch job fails alone instead of ENOBUFSing every sibling; and cw <verb> --json | head -1 exits quietly instead of an unhandled EPIPE crash. CLI polish: cw completion <bash|zsh|fish>, a documented --quiet flag, --json in top-level help, grouped "More commands", a cw doctor onramp pointer, a friendlier bare cw quickstart, and structured workbench panels with a light theme. Security/CI: ed25519-signed release verdicts, CodeQL + gitleaks scanning, SHA-pinned workflow actions, and labeled stored text in MCP results.
  • Implementation: The lock work is concentrated in shell/fs-atomic.ts — acquire by hard-linking a per-attempt temp file onto the lock path, steal only while holding a single-winner <lock>.steal guard with the verdict pinned to the judged inode+mtime. Every queue/policy mutator in scheduling-io.ts / run-registry-io.ts now runs its whole read-modify-write inside withFileLock, and queue ids are checked against the queue's own current entries under that same lock. The agent backend passes killSignal: "SIGKILL" and classifies ETIMEDOUT honestly; the batch child caps the SERIALIZED NDJSON line (33MB), not just raw stdout; one process-level stdout/stderr 'error' listener in cli/entry.ts handles EPIPE for every writer.
  • Tests: conformance 106/106, unit 160/160, full smoke suite green with 91.6% line coverage (floor 80%). The lock fixes were measured, not argued: an artificial-load stress rig (24 processes, 6-core load) reproduced each residual race red before its fix and ran 60/60 trials clean after.
  • Risk: Low to moderate — the fixes are fail-closed guards and lock serialization on existing surfaces; no schema, exit code, or --json shape changed, and the new CLI surfaces are additive. Zero new runtime dependencies.

Provenance & audit

Released through the gated flow: deterministic gate → independent release-reviewer (verdict above) → provenance-attested npm publish.