From c3a5abcf332aa1184d6473a635e5a4172ee8a716 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 19 Aug 2026 17:31:44 +0000 Subject: [PATCH] feat(writing-plans): add skeleton-first as a selectable plan shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- skills/writing-plans/SKILL.md | 24 ++++ skills/writing-plans/skeleton-first-plans.md | 131 +++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 skills/writing-plans/skeleton-first-plans.md diff --git a/skills/writing-plans/SKILL.md b/skills/writing-plans/SKILL.md index f74605bf..30bb519d 100644 --- a/skills/writing-plans/SKILL.md +++ b/skills/writing-plans/SKILL.md @@ -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. diff --git a/skills/writing-plans/skeleton-first-plans.md b/skills/writing-plans/skeleton-first-plans.md new file mode 100644 index 00000000..4cd49355 --- /dev/null +++ b/skills/writing-plans/skeleton-first-plans.md @@ -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. |