Compare commits

...

3 Commits

Author SHA1 Message Date
Jesse Vincent a56a34365a feat(sdd): follow a task's declared implementation tier at dispatch
The skeleton-first task template carries a Tier field the planner marks
deliberately. Model Selection now follows it instead of re-deciding at
dispatch, the implementer template's model slot reads it at fill time, and
an explicit mechanical ruling overrides the mid-tier contract floor —
the planner has already ruled the deliverable fully specified.

Task templates without a Tier field are unaffected: every route falls
through to the existing Model Selection guidance.
2026-08-19 17:32:55 +00:00
Jesse Vincent ef0ca09658 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.
2026-08-19 17:32:31 +00:00
Jesse Vincent c3a5abcf33 feat(writing-plans): add skeleton-first as a selectable plan shape
Adds a plan-shape router in the idiom of brainstorming's Three Paths:
classify the shape, announce it so the human partner can override, and
default to task-by-task on doubt. The alternative shape's full text —
skeleton ordering, task contracts instead of written-out code, the
contract task template, and its plan-failure list — lives in a sibling
reference file, so the default shape's guidance is unchanged.

Skeleton-first is a trade, not an upgrade: it buys an earlier running
end-to-end slice and pays for it in total wall clock.
2026-08-19 17:31:44 +00:00
4 changed files with 213 additions and 4 deletions
+53 -2
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.
@@ -187,6 +195,10 @@ Use the least powerful model that can handle each role to conserve cost and incr
**Mechanical implementation tasks** (isolated functions, clear specs, 1-2 files): use a fast, cheap model. Most implementation tasks are mechanical when the plan is well-specified.
When a task carries a **Tier:** field, follow it — the planner already
ruled: mechanical → the cheapest available model; judgment → a standard
model. Do not re-litigate the tier at dispatch.
**Integration and judgment tasks** (multi-file coordination, pattern matching, debugging): use a standard model.
**Architecture and design tasks**: use the most capable available model.
@@ -208,7 +220,10 @@ most expensive — which silently defeats this section.
**Turn count beats token price.** Wall-clock and context cost scale with how
many turns a subagent takes, and the cheapest models routinely take 2-3× the
turns on multi-step work — costing more overall. Use a mid-tier model as the
floor for reviewers and for implementers working from prose descriptions.
floor for reviewers and for implementers working from task contracts or
prose descriptions — unless the task's Tier line says mechanical: the
planner has already ruled the deliverable fully specified, so treat a
mechanical-tier contract like spelled-out content.
When the task's plan text contains the complete code to write, the
implementation is transcription plus testing: use the cheapest tier for
that implementer. Single-file mechanical fixes also take the cheapest tier.
@@ -259,7 +274,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 +301,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 +479,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.
@@ -5,8 +5,11 @@ Use this template when dispatching an implementer subagent.
```
Subagent (general-purpose):
description: "Implement Task N: [task name]"
model: [MODEL — REQUIRED: choose per SKILL.md Model Selection; an omitted
model silently inherits the session's most expensive one]
model: [MODEL — REQUIRED: when the brief carries a Tier line, set from it:
mechanical → the cheapest model the subagent tool offers; judgment →
a standard mid-tier model. Otherwise choose per SKILL.md Model
Selection. An omitted model silently inherits the session's most
expensive one]
prompt: |
You are implementing Task N: [task name]
+24
View File
@@ -22,6 +22,30 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
If the spec covers multiple independent subsystems, it should have been broken into sub-project specs during brainstorming. If it wasn't, suggest breaking this into separate plans — one per subsystem. Each plan should produce working, testable software on its own.
## Two Plan Shapes
Before mapping files, classify the plan's shape and say the
classification out loud — "this composes three subsystems, so I'll plan
it skeleton-first" — so your human partner can override it:
- **Task-by-task (default)** — tasks build the feature a component at a
time, each step carrying the actual content the engineer needs. Use it
for changes to code that already exists, for a spec that touches one
subsystem, and whenever the alternative's conditions do not clearly
hold. The rest of this skill describes this shape.
- **Skeleton-first (alternative)** — Task 1 is the thinnest end-to-end
slice through every subsystem the spec composes; later tasks widen it
one component at a time, each from a contract rather than written-out
code. Use it when the spec composes more than one subsystem AND a
running end-to-end slice early is worth a longer total build. Read
[skeleton-first-plans.md](skeleton-first-plans.md) before writing one
— it adds one line to the plan header and replaces this skill's task
granularity, task template, and plan-failure list.
When in doubt, plan task-by-task. Skeleton-first buys an earlier running
system and pays for it in total wall clock; it is a trade, not an
upgrade.
## File Structure
Before defining tasks, map out which files will be created or modified and what each one is responsible for. This is where decomposition decisions get locked in.
@@ -0,0 +1,131 @@
# Skeleton-First Plans
The alternative plan shape from writing-plans' Two Plan Shapes router.
Each section below replaces the same-named section of
[SKILL.md](SKILL.md); everything SKILL.md says that is not named here
still binds — Scope Check, File Structure, Task Right-Sizing, the plan
header, Self-Review, and the Execution Handoff.
## Overview
Write a plan that carries the decisions, not the keystrokes:
decomposition, file structure, interfaces, constraints, and a precise
contract per task. Assume the engineer is skilled and designs their own
code and tests from a precise contract, but knows nothing about our
codebase, toolset, or problem domain — every name, path, constraint, and
behavior they must match is stated explicitly. DRY. YAGNI. TDD.
Frequent commits.
## When This Shape Fits
Use it when the spec composes more than one subsystem and a running
end-to-end slice early is worth a longer total build: the value arrives
as soon as real input reaches real output, and every later task widens
something that already runs.
Do not use it for a change to one subsystem, or when the whole point is
to land the finished thing as fast as possible. This shape spends its
first task on a slice that does almost nothing, and it spends planning
effort on contracts and interfaces the task-by-task shape gets for free
by writing the code out.
## Plan Document Header
The header is SKILL.md's, plus one line directly under the **Goal:**
line, which is how executors know which shape they are running:
```markdown
**Plan shape:** skeleton-first
```
## Walking Skeleton First
Task 1 builds the thinnest end-to-end slice through every subsystem the
spec composes — real input to real output — before any task deepens a
single layer; later tasks widen the skeleton.
The test of a skeleton is that it runs. A first task that builds the
data loader, the schema, or the config layer is a foundation, not a
skeleton: nothing runs until something above it exists. A skeleton
reaches the output — thinly, with one real case — through every
subsystem the spec names.
## Task Contracts, Not Task Scripts
A task states WHAT must exist when it is done, precisely enough that a
skilled engineer can build it without asking you anything, without
prescribing HOW:
- **Goal:** one short paragraph naming the deliverable and its role in
the feature.
- **Success criteria:** concrete, checkable behaviors — exact commands
to run and what they must show, the cases tests must cover (including
failure cases), constraints that bind the implementation.
- **Notes:** what the engineer needs and cannot discover alone — spec
sections to read, files worth reading first, known pitfalls.
The Interfaces block carries the exact names, signatures, and types;
the success criteria carry the behaviors; the engineer supplies the
code and the test design. TDD and frequent commits remain required.
## Task Structure
````markdown
### Task N: [Component Name]
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
**Interfaces:**
- Consumes: [what this task uses from earlier tasks — exact signatures]
- Produces: [what later tasks rely on — exact function names, parameter
and return types. A task's implementer sees only their own task; this
block is how they learn the names and types neighboring tasks use.]
**Goal:** [one paragraph — the deliverable and its role in the feature]
**Success criteria:**
- Run: `pytest tests/exact/path/to/test.py -v` — all tests pass; tests
cover [the specific behaviors and failure cases, named concretely]
- [observable behavior the deliverable must exhibit, with the exact
command or input/output that demonstrates it]
- [constraint that binds the implementation, copied from the spec]
**Notes:** [spec sections to read; files to read first; known pitfalls]
**Tier:** mechanical | judgment. Mechanical = the deliverable is fully
specified by Files + Interfaces + success criteria above (most tasks in
a well-specified plan are mechanical); judgment = multi-file
coordination, debugging, or real design latitude remains. The
implementer's model follows this field — mark it deliberately.
**Commit:** one commit ending the task; message named here.
````
## No Vague Contracts
Every contract must be checkable by someone who did not write it. These
are **plan failures** — never write them:
- "TBD", "TODO", "implement later", "fill in details"
- Goals naming activity instead of a deliverable ("improve error handling")
- Success criteria with no observable check ("works correctly", "handles edge cases")
- Interfaces blocks omitting a name, signature, or type another task consumes
- "Similar to Task N" (state this task's own contract in full — the engineer may be reading tasks out of order)
- References to types, functions, or methods not defined in any task's Interfaces block
## Self-Review
Run SKILL.md's Self-Review checklist, reading step 2 against "No Vague
Contracts" above rather than "No Placeholders".
## Red Flags
| Thought | Reality |
|---------|---------|
| "Task 1 is the data loader — that's the foundation" | A foundation is a layer. The skeleton runs real input to real output through every subsystem the spec names, thinly. |
| "The skeleton can return a hardcoded value for now" | It may be thin, but the path must be real: real input, real wiring, real output. A hardcoded response tests nothing end to end. |
| "A contract without the code is vague" | Vague is an uncheckable success criterion. Exact names, exact commands, exact expected output — no code. |
| "I'll write the test code into the task to be safe" | The success criteria name the cases; the implementer designs the tests. Written-out tests are the task-by-task shape. |
| "Skeleton-first is the better shape, so I'll use it here" | It costs total wall clock. Without more than one subsystem and a reason to want an early running slice, plan task-by-task. |