Route every .stories/ write through skills/story-lifecycle/scripts/ledger.js:
- exclusive per-ledger lock; a second writer waits, then exits 3 without writing
- story IDs reserved with exclusive-create markers in the git common dir, so
concurrent agents and worktrees of one clone never share an ID
- journaled batches: stage, journal, rename; derived epic/sprint tables are
regenerated inside the batch; an interrupted batch is rolled back by the
next write command or `recover`; `status` reports it only when no live
writer holds the lock
Bound the ledger to an opt-in planning projection that is never canonical
ECC Task/Evidence/Completion/Integration state, and state that .stories/
follows the checkout.
tests/docs/story-lifecycle-ledger.test.js exercises create, concurrent
create, concurrent cross-worktree allocation, lock contention, overwrite
refusal, interrupted-batch recovery, sprint planning, status drift and
reconcile, and path confinement. Also refresh the skill-triggers manifest
digest for 294 skills.
Address maintainer review on #2311:
- story file is the single authoritative status record; epic/sprint
tables are derived and reconciled; todo → in-progress → review → done
with done gated on confirmed merge to main
- implement lane: tdd-workflow first, language reviewer +
verification-loop before a story reaches review
- naming/path contract (slug, story-id, sprint validation), resolved-path
confinement under .stories/, untrusted-content handling, no silent
overwrites, harness-native file operations (no POSIX-only shell)
- documented boundary and handoff to issue-backed epic-* coordination
- replaced references that do not resolve on main; added
tests/docs/story-lifecycle-skill.test.js contract test