Repository navigation
1.3.0 was never tagged, so its changes ship here. Everything below is what a 1.2.1 user gets by upgrading.
The claim follows the process, not a clock
A claim is live while its job has no exit.json and either a heartbeat exists or its recorded pid can still be probed as running. The old rule treated a missing heartbeat as a dead job — exactly the window in which a crashed supervisor's orphaned executor is still editing the claimed paths. A pid that cannot be probed falls back to the old heuristic, so the lock cannot wedge forever.
The lock fails closed
A dispatch.lock that exists but cannot be parsed is refused rather than read as "no claims". Coercing a damaged lock to empty admitted every job and then rewrote the file with only the new claim, discarding live holds with no message.
jobs is a read command
It lists live claims (paths, pid, liveness, age) and recent history, prunes and releases nothing, and exits 0 even when the lock is damaged — the damage is reported in lock_warning, because a read command should still be able to show you what is wrong.
Output is bounded
stdout.jsonl plus stderr.log are capped at 64 MiB (WB_EXEC_LOG_CAP overrides). Crossing the cap kills the child and records the cap in blockers, so a truncated transcript is never read as a finished run.
Results carry protocol
A plain integer envelope version, so a host can tell which shape it is reading instead of failing deep inside its own logic after an upgrade.
Desktop hardening, merged in
- The CLI is probed before any claim is taken: a missing executor leaves no live lock.
- An explicit
WB_CLIis authoritative; a broken one fails instead of silently falling back to another installation. - A worktree that cannot be created aborts the dispatch instead of editing the source tree in place.
- A crash in dispatch or the supervisor still writes
exit.jsonandresult.json, so the job is collectable asfailed. - The prompt is delivered on a writer thread, so a child that never reads stdin cannot block timeout or cancel.
- Task packages are read as
utf-8-sig; Windows PowerShell writes a BOM. owned_pathsis resolved against--cwd; an entry that escapes it, or the repository root itself, is refused.- Changed paths come from
git diff -z --name-status, so names with spaces, quotes or CJK characters survive intact.
Behaviour change worth knowing
An empty owned_paths is now enforced as additions-only. Editing or deleting an existing file is reported in violations and raises needs_human. Previously it produced no violations at all, which contradicted both the README and protocol.md. A task that used to run quietly can now come back as needing a human — correct, but not a patch-level change.
Figures
Figure 1 is redrawn to match this release, and the two defects it already had — the Isolation and Artifacts panel titles covered by nodes — are gone. The pipeline is reproducible: docs/figures/check_layout.py measures real font extents and fails on text that overflows, nodes on a panel border, colliding nodes, or edges that end in mid-air; docs/figures/build.py renders and then downscales to 1280 px, a step that used to be manual.
Verification
75 tests, fully offline, passing in a clean environment and with WB_SUBAGENT=1. Python 3.10+, standard library only.