Dispatch Lifecycle Safety — cumulative execution record
One anchor per landed node. Each entry records the commit, the gate measure as executed, the tests, and anything negative found on the way. The evergreen plan holds the design; this record holds what actually happened.
Dispatch guards (member-collision refusal, transactional rollback)
Commit c193f19559caee1c5249614e02b85fe50c24de10 (2026-08-16, worker codex-b,
509 s, 144 insertions / 3 deletions over reckon/crew.py,
tests/test_crew.py; merged as ff5bd3c).
- Member-collision guard.
dispatch()now raisesMemberInFlight— carrying the member id and the existing run id — before any worktree is created, when the requested roster member already holds a pointer in a non-terminal phase. Terminal phases (complete,failed,stopped) do not trigger the guard. Measure: the double-dispatch scenario refuses and names the in-flight run instead of silently orphaning the second node. - Transactional rollback. Run-directory creation moved inside the dispatch rollback scope; a post-spawn failure signals the spawned process group before removing the worktree. Measure: an injected post-spawn pointer-write failure left 0 running processes, 0 run directories, 0 pointers and 0 worktrees.
Tests: 2 focused regressions added; full suite 1867 passed, 0 failed (91 s) in the
worker's tree. Log:
~/.config/reckon/crew/runs/r-20260816T204727513038-dispatch-guards/full-suite-final.log.
Observe truth (stopped-phase preservation, pid identity, honest live view)
Commit 421be971e70b2371eb6331d0b396ba68cd78928d (2026-08-16, worker codex-b,
367 s, 197 insertions / 22 deletions over reckon/crew.py,
tests/test_crew.py; fast-forwarded).
- Phase truth. stop → observe → recover round-trips as
stopped(phase and classification, count 1); in-harnessblockedandfailedmanifests retain their recorded status instead of classifying ascompleteby mere existence. - Signal safety. Dispatch and resumption record process start ticks;
killpgrefuses a changed pid identity before signalling;process_alivereturns false onPermissionErrorinstead of treating not-ours as alive. - Honest live view. Live-pointer classification re-checks every present
pid: a killed worker with a stale
process_alive=trueflag reportsfalseand classifiesabandonedwith no intervening observe.
Tests: 6 added (7 focused cases); full suite 1881 passed, 0 failed (69 s). Log:
~/.config/reckon/crew/runs/r-20260816T211233341959-observe-truth/full-suite.log.
Resume correctness (stream preservation, refuse-while-alive, timestamp guards)
Commit 9cc6fff7973aa13b5ee1205a0b399af92a517272 (2026-08-16, worker codex-b,
368 s, 139 insertions / 13 deletions over reckon/_backends.py,
reckon/crew.py, reckon/ledger.py and three test files;
fast-forwarded).
- Resume stream handling.
record_resumptionpreserves the pointer's originalstream.jsonlpath; crew completion and ledger repair both order streams asstream.jsonl,resume-1,resume-2, …resume-10numerically, and the full stream set is measured at completion. Resume refuses while the previous process is alive. - Timestamp guards. Millisecond and out-of-range reset epochs produce a
null reading instead of raising through observe, complete, recover or the budget probe;
a naive
complete --completed-atis stored as UTC and yields a non-null worker duration, matching the guard inledger._worker_seconds. Both demonstrated crashes are regression tests.
Tests: 5 added; full suite 1886 passed, 0 failed (74 s). Log:
~/.config/reckon/crew/runs/r-20260816T212015471178-resume-correctness/full-suite.log.