fe5ca8f8c0
Implements the three efficiency findings from the #310 pipeline measurement (refs #35): ~691k subagent tokens / ~3.5 h for a deliberately small cycle, with recon duplication as the single biggest obligatory per-cycle cost. 1. Cycle recon (pipeline.md § Cycle recon; specify, planner, brainstorm, boss, plan-recon): recon fan-out is budgeted per cycle, not per phase. One full plan-recon dispatch — normally specify Step 1, in a new pre-spec sources/recon_scope carrier form — serves both the spec's concrete code shapes and the plan's file-map. planner Step 2 becomes reuse-first (freshness / quotability / coverage conditions) with narrowly-bounded delta dispatches (new Delta dispatch contract in plan-recon.md); broad Explore-type grounding sweeps are banned in every mode. Field evidence: 151k (Explore) + 99k (plan-recon) with ~40 % overlap in one bounded cycle. 2. Fieldtest probe tier (fieldtest, fieldtester, pipeline.md, agent-template.md § model rule 2): a cycle whose user-visible delta is a single narrow axis dispatches the per-cycle fieldtest at tier: probe — 1-2 examples on exactly that axis, ~200-word report, explicit model:sonnet dispatch override (no dispatch-level effort override exists; frontmatter effort applies). Probe is a tier, not a skip; the milestone fieldtest always runs full tier on the frontmatter model, keeping the milestone-close gate's >=2-example floor unconditional. 3. Assumption economy (specify Step 3 + self-review item 6): grounding-check cost scales with the spec's assumption count, so specs state current-behaviour claims only where the change relies on them (the gate's own falsity test), demote context-only mentions to ledger citations, and keep iteration scope tight — fewer restatements, never fewer reliances. The gate itself is unchanged. Design reviewed pre-implementation (opus plan review); diff adversarially verified by a 3-lens review workflow (consistency, operability, cross-reference), confirmed findings folded in. refs #35
307 lines
12 KiB
Markdown
307 lines
12 KiB
Markdown
---
|
|
name: planner
|
|
description: Use when a cycle spec exists under docs/specs and a new iteration is starting. Produces a placeholder-free, bite-sized implementation plan under docs/plans that the implement skill can execute task-by-task. Hard-gate before any implementation work.
|
|
---
|
|
|
|
# planner — spec → executable plan
|
|
|
|
> **Violating the letter of these rules is violating the spirit.**
|
|
|
|
## Overview
|
|
|
|
A plan is the contract between design (spec) and execution
|
|
(`implement`). It commits the file structure, names every
|
|
file that will be created or modified, and decomposes work
|
|
into bites small enough that a subagent can execute one in
|
|
2-5 minutes without making judgement calls outside its remit.
|
|
|
|
Plans live under `docs/plans` with the fixed name shape
|
|
`slug.md` — a short kebab-case topic slug, no numeric prefix (see
|
|
`docs/conventions.md` § Naming). `docs/plans` is git-ignored via the
|
|
project's committed `docs/.gitignore`; on a direct tidy dispatch that
|
|
skipped `specify`, create that file first if it does not yet ignore
|
|
`plans/` (`docs/conventions.md` § File layout). The plan is a working
|
|
file, never committed. The header references the parent spec. The plan
|
|
decomposes work into tasks; each task is the unit of review
|
|
(spec-compliance and quality gates inside `implement`), not
|
|
the unit of commit. Commits are an orchestrator-only decision
|
|
taken at the end of the iter against the full working-tree
|
|
diff.
|
|
|
|
## When to Use / Skipping
|
|
|
|
Triggers:
|
|
|
|
- A spec under `docs/specs` for the active cycle is
|
|
approved.
|
|
- A new iteration within an active cycle is starting.
|
|
|
|
May be skipped when:
|
|
|
|
- The work is a bug fix where the RED test from `debug` IS
|
|
the plan (handoff goes straight to `implement` mini-mode).
|
|
- The work is a test-specifiable feature routed through `tdd`,
|
|
where the RED executable-spec IS the plan (handoff goes
|
|
straight to `implement` mini-mode). `tdd` skips the whole
|
|
design path — `brainstorm`, `specify`, and `planner`.
|
|
- The work is a trivial mechanical edit (per the project's
|
|
CLAUDE.md "trivial mechanical edits" carve-out).
|
|
- The work is a harvest sweep — settled single-issue backlog
|
|
drained as a batch. The settled issue bodies stand in for the
|
|
plan, and the per-task review pair is replaced by one
|
|
whole-sweep diff review. See `../docs/pipeline.md`
|
|
§ Harvest sweep.
|
|
|
|
**Never skipped** for a standard iteration within an active
|
|
cycle. "I know the cycle, plan from memory" is exactly the
|
|
failure mode this skill prevents.
|
|
|
|
## The Iron Law
|
|
|
|
```
|
|
NO PLACEHOLDERS — TBD, TODO, "implement later", "similar to Task N",
|
|
or "add appropriate error handling" are PLAN FAILURES.
|
|
EVERY STEP THAT CHANGES CODE INCLUDES THE CODE.
|
|
EVERY STEP THAT RUNS A COMMAND INCLUDES THE COMMAND AND EXPECTED OUTPUT.
|
|
```
|
|
|
|
Non-negotiable.
|
|
|
|
## The Process
|
|
|
|
### Step 1 — Read the parent spec
|
|
|
|
Read the spec under `docs/specs` in full. NOT from memory.
|
|
Even if the spec is recent and you wrote it yourself, re-read
|
|
it before planning.
|
|
|
|
The spec is the source of truth; the plan is the projection
|
|
of one iteration's worth of work onto a task list.
|
|
|
|
### Step 2 — Map file structure
|
|
|
|
The file-map normally already exists: the **cycle recon** report
|
|
(`../docs/pipeline.md` § Cycle recon), dispatched during `specify`
|
|
Step 1 or ad-hoc by `brainstorm`. Reuse it while that section's
|
|
reuse conditions — freshness, quotability, coverage — hold. Lift
|
|
the relevant entries
|
|
into the plan's "Files this plan creates or modifies" section; the
|
|
orchestrator may add or amend entries that recon missed.
|
|
|
|
Dispatch `plan-recon` only:
|
|
|
|
- as a **delta**, on the § Cycle recon delta triggers — a narrow
|
|
dispatch whose `focus_hint` names the gap, bounded by the
|
|
**Delta dispatch** contract in `agents/plan-recon.md`;
|
|
- in **full**, when no valid cycle recon exists (a direct tidy
|
|
dispatch that skipped `specify`, a session break, or a reuse
|
|
condition failed).
|
|
|
|
Either way the orchestrator does NOT do recon in-context: reuse
|
|
means reusing a prior *dispatch's* report, never the
|
|
orchestrator's own tree-walking.
|
|
|
|
Dispatch carrier: see the **Carrier contract** tables in
|
|
`agents/plan-recon.md` (single source for `spec_path`,
|
|
`iteration_scope`, `focus_hint`; the pre-spec `sources` form is
|
|
`specify`'s dispatch, not planner's).
|
|
|
|
Recon does NOT decide decomposition. Two *delta* dispatches in
|
|
one planner run is the smell that the iteration scope is too
|
|
broad — re-read the spec. A second *full* dispatch in a cycle
|
|
that already has a valid cycle recon is a § Cycle recon budget
|
|
violation, not a judgement call.
|
|
|
|
The plan's "Files this plan creates or modifies" section
|
|
keeps the same shape:
|
|
|
|
```markdown
|
|
**Files this plan creates or modifies:**
|
|
|
|
- Create: `<exact path>` — <one-line responsibility>
|
|
- Modify: `<exact path>:<line range if known>`
|
|
- Test: `<exact path>` — <one-line case description>
|
|
```
|
|
|
|
Files that change together stay in the same task. Files that
|
|
change independently get separate tasks.
|
|
|
|
### Step 3 — Write tasks, bite-sized
|
|
|
|
Each task is a logical unit of change (one feature, one fix,
|
|
one extension). Each task contains steps; each step is ONE
|
|
action that takes 2-5 minutes:
|
|
|
|
```markdown
|
|
### Task N: <Component Name>
|
|
|
|
**Files:**
|
|
- Create: `<exact path>`
|
|
- Modify: `<exact path>:<line range if known>`
|
|
- Test: `<exact path>`
|
|
|
|
- [ ] **Step 1: Write the failing test**
|
|
|
|
(exact test source code here)
|
|
|
|
- [ ] **Step 2: Run test to verify it fails**
|
|
|
|
Run: `<the project's test command (its CLAUDE.md project facts), scoped to this test>`
|
|
Expected: FAIL with "<exact expected message>"
|
|
|
|
- [ ] **Step 3: Write minimal implementation**
|
|
|
|
(exact implementation source code here)
|
|
|
|
- [ ] **Step 4: Run test to verify it passes**
|
|
|
|
Run: `<the same test command>`
|
|
Expected: PASS
|
|
```
|
|
|
|
No `git commit` step. Implement tasks leave their work in
|
|
the working tree; the orchestrator commits at the end of the
|
|
iter.
|
|
|
|
### Step 4 — Plan header
|
|
|
|
Every plan starts with this header:
|
|
|
|
```markdown
|
|
# <Iteration Title> — Implementation Plan
|
|
|
|
> **Parent spec:** `<path under docs/specs>`
|
|
>
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: use the
|
|
> `implement` skill to run this plan. Steps use `- [ ]`
|
|
> checkboxes for tracking.
|
|
|
|
**Goal:** <one sentence>
|
|
|
|
**Architecture:** <2-3 sentences>
|
|
|
|
**Tech Stack:** <key components touched>
|
|
|
|
---
|
|
```
|
|
|
|
### Step 5 — Self-review
|
|
|
|
Before handing the plan off, run this checklist inline:
|
|
|
|
1. **Spec coverage:** every spec section has a task that
|
|
implements it. If a section has no task, add one.
|
|
2. **Placeholder scan:** grep for "TBD", "TODO", "implement
|
|
later", "similar to Task", "add appropriate error
|
|
handling". Any hit is a plan failure to fix.
|
|
3. **Type consistency:** function names, type names, file
|
|
paths referenced across tasks must match.
|
|
`clearLayers()` in Task 3 and `clearFullLayers()` in
|
|
Task 7 is a bug.
|
|
4. **Step granularity:** every step is 2-5 minutes. If a
|
|
step is "implement the parser", split it.
|
|
5. **No commit steps:** task templates must not contain
|
|
`git commit` instructions. Implement tasks leave work in
|
|
the working tree.
|
|
6. **Pin/replacement substring contiguity:** when a task
|
|
ships a test asserting `contains("<substring>")` (or a
|
|
grep) AND another task's verbatim replacement body is
|
|
what must contain that substring, the substring must
|
|
appear *contiguously* in that replacement body — no
|
|
soft-wrap splitting it across two lines. Two
|
|
authoritative artefacts (exact pin vs. exact replacement)
|
|
that cannot both be applied literally is a plan defect,
|
|
not an implementer judgement call. This is a recurring
|
|
defect family — scrub it here, every plan that pairs a
|
|
presence-pin with a verbatim text edit.
|
|
7. **Compile-gate vs. deferred-caller ordering:** when a
|
|
task changes a function signature (or any change that
|
|
makes the whole compilation unit fail to compile until N
|
|
call sites are updated) AND that task ends with a
|
|
"0 errors" build gate, every caller the signature change
|
|
touches MUST be threaded *inside that same task* — not
|
|
deferred to a later task. A "0-errors" gate is
|
|
unsatisfiable while any caller is still unthreaded
|
|
(hard compile error), so a plan that defers a caller
|
|
(e.g. "the X call site is handled in Task 4") past an
|
|
earlier task's compile gate is internally contradictory:
|
|
the executor is forced to pull the deferred code forward
|
|
to satisfy the gate, silently resequencing the plan.
|
|
Either fold all caller-threading into the
|
|
signature-change task, or make the gate a *partial* build
|
|
of just the changed module with the workspace-wide build
|
|
deferred to the task that finishes threading. This is a
|
|
recurring defect family — scrub it here, every plan with
|
|
a signature-change task.
|
|
8. **Verification-command filter strings must resolve.**
|
|
Every literal test-filter / grep pattern / test-target
|
|
in a Run step is itself a load-bearing artefact: if its
|
|
filter substring matches **no** test (or its target file
|
|
does not exist), the step silently asserts nothing — a
|
|
green "0 ran" reads as success while proving the opposite
|
|
of the gate's intent. For every such command, either
|
|
(a) the filter substring must be one verified to match
|
|
≥1 real named test/line in the current tree (name it, do
|
|
not guess from the feature word), or (b) use the
|
|
unfiltered suite plus an explicit result-count assertion
|
|
so "nothing ran" cannot masquerade as "nothing
|
|
regressed". This is a recurring defect family — scrub
|
|
every Run step whose assertion lives in a filter string.
|
|
|
|
Fix issues inline.
|
|
|
|
### Step 6 — Hand off
|
|
|
|
The plan sits in the working tree as a git-ignored working file under
|
|
`docs/plans`. Hand off to `implement` with: path to the
|
|
plan file + optional task focus ("only Tasks 1-3 this run").
|
|
|
|
The plan is **never committed**. Like the spec, it is a git-ignored
|
|
active-cycle working file: present on disk for its own cycle and
|
|
shell-`rm`'d alongside the spec at cycle close by `audit` (see
|
|
`docs/conventions.md` § Lifecycle).
|
|
|
|
## Handoff Contract
|
|
|
|
| Direction | Carrier |
|
|
|-----------|---------|
|
|
| `specify` → `planner` | path to the spec under `docs/specs` + iteration scope ("this iteration covers spec section X+Y") |
|
|
| `planner` → `implement` | path to the plan under `docs/plans` + optional task-range focus |
|
|
| `planner` → `specify` (bounce) | spec contains placeholders or contradictions: name the offending section, request revision |
|
|
|
|
## Common Rationalisations
|
|
|
|
| Excuse | Reality |
|
|
|--------|---------|
|
|
| "TBD in step 4 lets me ship the plan tonight, fill in tomorrow" | Half-decided plans get re-litigated mid-iteration, costing more than the night's sleep saved. Make the decision tonight or close the laptop. |
|
|
| "Bundle Tasks 3 and 4, both small" | Tasks are the unit of review (spec-check + quality-check fire once per task). Bundling collapses two reviews into one and hides the smaller change inside the bigger one. If 3 and 4 are inseparable, they're one task — rewrite the decomposition. |
|
|
| "Spec is recent, I wrote it, plan from memory" | Memory diverges from disk. 15 minutes of re-reading is the cheapest insurance in the cycle. |
|
|
| "Step 5 'implement the parser' is fine, I'll detail it at execution time" | Then it's not a step, it's a wish. Steps are bite-sized OR the plan isn't done. |
|
|
| "Task 7 is similar to Task 4, just say so" | The executor may read tasks out of order. Repeat the code. |
|
|
| "The spec has a TBD too, I can pass it through" | Bounce back to `specify`. Plans inherit spec gaps; spec gaps are not plan placeholders. |
|
|
|
|
## Red Flags — STOP
|
|
|
|
- Any of: "TBD", "TODO", "fill in later", "similar to",
|
|
"add appropriate <X>" — fix or bounce.
|
|
- Steps that describe what to do without showing how
|
|
- Function/type/path names that don't match across tasks
|
|
- Step descriptions longer than the code they describe
|
|
- Header missing parent spec reference
|
|
- Self-review skipped because "the plan looks fine"
|
|
|
|
## Cross-references
|
|
|
|
- **Input source:** `../specify/SKILL.md` — produces the
|
|
spec this skill consumes (reached directly from settled
|
|
sources, or via the optional `../brainstorm` discovery stage).
|
|
- **Output target:** `../implement/SKILL.md` — runs the plan
|
|
task-by-task.
|
|
- **Agents dispatched:**
|
|
- `agents/plan-recon.md` — Step 2, file-structure mapping
|
|
(read-only). Normally reused from the cycle recon
|
|
(`../docs/pipeline.md` § Cycle recon); dispatched here only
|
|
for deltas, or in full when no valid cycle recon exists. The
|
|
file-map always comes from a dispatch's report; the
|
|
orchestrator does NOT do recon in-context.
|