Field incident
Four lanes on one adopter workspace lost real work in a single day to spawns cut from a stale base. afx spawn branches the builder worktree from the shared checkout's LOCAL HEAD (verified: spawn-worktree.ts ~213 creates the worktree from the local branch with no git fetch on the normal path; only the fork/--branch path fetches). Confirmed instances, independently: a worktree cut 28 commits behind origin (the architect had verified the defect ON origin's branch and run a full pre-spawn checklist), 59 behind, and 141 behind (~20 hours; caught in plan phase after a 38-file inventory had to be re-verified against the merged tree). Two lanes were clean. Spawn reported [ok] in all cases.
Why a checklist is not the fix
The originating architect's checklist PASSED WHILE BEING WRONG: they asserted against origin/<branch> while the action consumed local HEAD. And "assert local==origin before every spawn" is a vigilance control on a shared resource with no signal — whoever fetches benefits everyone silently, whoever leaves the checkout stale poisons everyone silently, and nobody is told either way.
Design tension to respect (this repo's own workflow)
Branching from local HEAD is partly deliberate: approved specs/plans must be COMMITTED before spawning precisely so the builder (which branches from HEAD) can see them, including commits not yet pushed. So "always branch from origin" would break the commit-locally-then-spawn flow. The poison case is specifically the local base being BEHIND origin; being AHEAD (unpushed local commits) is legitimate.
Two asks (the second is cheaper and valuable even after the first lands)
- Guard on staleness: before cutting the worktree,
git fetch the base branch's remote ref and compute behind-count (git rev-list --count <base>..origin/<base>). Behind > 0 → refuse with the count and the remedy (or --force past it, mirroring the dirty-worktree guard — same guard class, same place). Ahead-only → proceed (legitimate unpushed work). Offline/fetch-failure → proceed with a loud UNKNOWN-staleness warning, never a silent pass (do not render unknown as determinate).
- Report the base regardless: replace bare
[ok] spawned with branched from <sha> (<base>, N behind / M ahead of origin/<base>). Even a correct base is something an architect wants to see; staleness becomes visible at spawn time with nobody remembering to run rev-list.
Audit instruments (from the reporting workspace, for docs/tests)
- Post-hoc check for an existing worktree:
git rev-list --count <builderHEAD>..origin/<base>.
- Spawn-time staleness forensics:
git reflog show origin/<base> --date=iso — commit dates lie (a branch authored days earlier and merged later carries old committer dates).
Field incident
Four lanes on one adopter workspace lost real work in a single day to spawns cut from a stale base.
afx spawnbranches the builder worktree from the shared checkout's LOCAL HEAD (verified:spawn-worktree.ts~213 creates the worktree from the local branch with nogit fetchon the normal path; only the fork/--branchpath fetches). Confirmed instances, independently: a worktree cut 28 commits behind origin (the architect had verified the defect ON origin's branch and run a full pre-spawn checklist), 59 behind, and 141 behind (~20 hours; caught in plan phase after a 38-file inventory had to be re-verified against the merged tree). Two lanes were clean. Spawn reported[ok]in all cases.Why a checklist is not the fix
The originating architect's checklist PASSED WHILE BEING WRONG: they asserted against
origin/<branch>while the action consumed local HEAD. And "assert local==origin before every spawn" is a vigilance control on a shared resource with no signal — whoever fetches benefits everyone silently, whoever leaves the checkout stale poisons everyone silently, and nobody is told either way.Design tension to respect (this repo's own workflow)
Branching from local HEAD is partly deliberate: approved specs/plans must be COMMITTED before spawning precisely so the builder (which branches from HEAD) can see them, including commits not yet pushed. So "always branch from origin" would break the commit-locally-then-spawn flow. The poison case is specifically the local base being BEHIND origin; being AHEAD (unpushed local commits) is legitimate.
Two asks (the second is cheaper and valuable even after the first lands)
git fetchthe base branch's remote ref and compute behind-count (git rev-list --count <base>..origin/<base>). Behind > 0 → refuse with the count and the remedy (or--forcepast it, mirroring the dirty-worktree guard — same guard class, same place). Ahead-only → proceed (legitimate unpushed work). Offline/fetch-failure → proceed with a loud UNKNOWN-staleness warning, never a silent pass (do not render unknown as determinate).[ok] spawnedwithbranched from <sha> (<base>, N behind / M ahead of origin/<base>). Even a correct base is something an architect wants to see; staleness becomes visible at spawn time with nobody remembering to run rev-list.Audit instruments (from the reporting workspace, for docs/tests)
git rev-list --count <builderHEAD>..origin/<base>.git reflog show origin/<base> --date=iso— commit dates lie (a branch authored days earlier and merged later carries old committer dates).