feat(sdd): execute skeleton-first plans with a wave dispatch plan

A plan whose header declares `Plan shape: skeleton-first` gets three
additions, each placed at the moment the controller already attends to:
the pre-flight scan ends with a dispatch plan grouping file-disjoint
tasks into waves; the never-parallel rule gains one exception with the
worktree integration protocol that makes it safe; each task completion
records a plan-check line so an amendment becomes the plan's text.

Every clause is gated on the declared plan shape. Plans without the
declaration execute exactly as before, including the unqualified
never-dispatch-in-parallel rule.
This commit is contained in:
Jesse Vincent
2026-08-19 17:32:31 +00:00
parent c3a5abcf33
commit ef0ca09658
+45 -1
View File
@@ -173,6 +173,14 @@ its own text agrees with itself — the tests it specifies against the code it
specifies, the files it creates against the files it later touches. "The scan
is clean" without those rows is not a scan you ran.
**When the plan's header declares `Plan shape: skeleton-first`,** the
table gets a final section: the DISPATCH PLAN — group the pending tasks
into waves. Tasks in the same wave are mutually file-disjoint and consume
no interface still under construction — dispatch each wave's implementers
concurrently, one worktree per task, and integrate before the next wave;
tasks that fail those conditions serialize. On a skeleton-first plan, a
scan without a dispatch plan is not a scan you ran.
Write the table to the ledger. Rule on everything you find before execution
begins — each finding against the plan text that mandates it — and record
each ruling in the ledger. If the scan is clean, proceed without comment.
@@ -259,7 +267,13 @@ and fix-round diffs need it.
know; (4) your resolution of any ambiguity you noticed in the brief;
(5) the report-file path and report contract. Exact values (numbers,
magic strings, signatures, test cases) appear only in the brief. Never
make a subagent read the whole plan file.
make a subagent read the whole plan file. When the brief is a contract
(goal, success criteria, interfaces) rather than written-out code, item
(3) also carries the elaboration the contract leaves to dispatch time:
the interfaces as actually built by completed tasks, environment facts
and discoveries from earlier reports, and any amendment rulings. There
the success criteria name the cases the tests must cover, and the
implementer designs its own code and tests within the contract.
- **Report file:** name the implementer's report file after the brief
(brief `…/task-N-brief.md` → report `…/task-N-report.md`) and put it in
the dispatch prompt. The implementer writes the full report there and
@@ -280,6 +294,26 @@ and fix-round diffs need it.
- Record the implementer's agent identity from the dispatch result —
fix-loop rounds 1-3 resume this agent.
- Never dispatch multiple implementation subagents in parallel (conflicts).
The one exception is a skeleton-first plan whose dispatch plan shows two
or more pending tasks mutually file-disjoint with none consuming an
interface still under construction. Dispatch those implementers
concurrently, each in its own worktree:
- Record the integration base commit in the ledger before the first
concurrent dispatch.
- Create one worktree per concurrent task off that base
(`git worktree add <repo-root>/.worktrees/task-<N> -b task-<N>
<base>`); each dispatch's `Work from:` is its own worktree, and its
BASE is that worktree's HEAD.
- Review each task's diff as usual when it reports. Integrate reviewed
branches in plan order: merge each into the integration branch
(`git merge --no-ff task-<N>`), and run that task's verification
commands after each merge.
- A merge conflict or post-merge verification failure is that task's
fix-loop round 1: rebase the task branch onto the current
integration head in its worktree, then resume its implementer
there. Never resolve conflicts yourself.
- Remove each worktree (`git worktree remove`) once its branch is
integrated, and record the integrated range in the ledger as usual.
Template: [implementer-prompt.md](implementer-prompt.md)
@@ -438,6 +472,16 @@ message as your other bookkeeping:
- `Task <N>: complete (commits <base7>..<head7>, <K> parked)` after a
tripped breaker
**On a skeleton-first plan,** write one plan-check line with the
completion line. Re-read the remaining tasks against what this task
actually established — interfaces as built, environment facts,
discoveries in the report — and append either `Plan holds` or
`Amendment: Task <M>: <what changes and why>` to the ledger. An
amendment is plan authority applied at the plan layer: from then on the
amended text IS the plan's text, and it rides into every affected task's
dispatch under item (3). Never dispatch a task whose brief a completed
task's report has already invalidated.
Then mark the todo complete and move on. Never move to the next task while
the review has open Critical/Important issues that are neither fixed nor
parked-with-ruling at the cap.