Files
Skills/planner/SKILL.md
T
Brummel f7758818ab audit(specify): close cycle — repair planner, grounding-check, schema drift
Architect drift review (cycle 9e8b9ec..HEAD) returned drift_found. Three
cycle-introduced items, all repaired here as tidy edits:

- planner/SKILL.md: the cycle never touched it (recon never scoped it,
  the feat commit body's "every pipeline rendering agrees" over-claimed).
  Its Handoff Contract still named `brainstorm → planner` and the bounce
  `planner → brainstorm`; the Input-source cross-ref and two
  rationalisation rows still pointed at brainstorm as the spec producer.
  All repointed to specify (specify produces and owns the spec; brainstorm
  is the optional discovery stage upstream of it). The skip rule now lists
  specify in the design path tdd bypasses.
- specify/agents/grounding-check.md: the agent move left one stale pair —
  "self-review (Step 7) and user-approval (Step 8)" were brainstorm's old
  numbers; in specify they are Step 4 and Step 6.
- profile-schema + template: the `optional: true` per-phase key I
  introduced in the plan was undocumented AND rested on a semantic error —
  `brainstorm: { gates: [specify] }` reads as "specify cannot start until
  brainstorm has run", which is false (specify enters directly from
  sources). Corrected to `brainstorm: {}` (an active phase with no hard
  gate of its own, like implement); specify keeps `gates: [planner]` as
  the one real hard gate. The optional key is gone; brainstorm's
  optionality lives in the skip rules and SKILL prose, where it belongs.

Why these escaped the cycle's own grep suite: the consistency greps used
`brainstorm *-> *planner`, which does not match the real renderings
`` `brainstorm` -> `planner` `` (backticks between the words). The same
filter-string blind spot recurred twice this session; the verification
greps here tolerate optional backticks.

Pre-existing debt (NOT cycle-introduced), filed as backlog Brummel/Skills
issue #5 rather than fixed here: docs/migration.md's layout tree and
README's migration-status both predate tdd/glossary/pseudo/issue/
postmortem and misdescribe the roster.

Verdict: cycle drift-clean after these repairs (carry-on). No regression
gate (prose repo, no scripts). Not a milestone close.
2026-06-04 23:25:03 +02:00

12 KiB

name, description
name description
planner Use when a cycle spec exists under paths.spec_dir and a new iteration is starting. Produces a placeholder-free, bite-sized implementation plan under paths.plan_dir 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 the project's paths.plan_dir with a name shape governed by the project's naming.policy (see profile schema). 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 paths.spec_dir 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).

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 paths.spec_dir 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

Dispatch plan-recon with the spec path and iteration scope. Read the returned file-map. 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 carrier: see the Carrier contract table in agents/plan-recon.md (single source for spec_path, iteration_scope, focus_hint).

Recon does NOT decide decomposition. Two recon dispatches per planner run is unusual but legitimate (e.g. one for the main spec sections, one with a sharper focus_hint for a tricky subsystem). Three or more is a smell — re-read the spec; the iteration scope is probably too broad.

The plan's "Files this plan creates or modifies" section keeps the same shape:

**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:

### 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 from commands.test, 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:

# <Iteration Title> — Implementation Plan

> **Parent spec:** `<path under paths.spec_dir>`
>
> **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.
  9. Parse-the-bytes-you-inline gate. Every verbatim code body the plan inlines into a task step must be run through the spec_validation gate defined in docs/profile-schema.md (which owns the parser-invocation protocol, the noted no-parser skip, the malformed-entry failure, and the no-op when the profile declares no spec_validation) before hand-off. The target is the surface-language snippets the plan lifts verbatim (example programs, fixtures); the project's source-language test / implementation bodies are NOT the target — the implement compile gate catches those. A parse failure is a plan failure — the plan would hand the implementer bytes that do not parse, the last defensive line before dispatch — fix the plan, do not hand off. The parse-trace goes into the planner's self-review activity (the session) as the attestation the gate fired.

Fix issues inline.

Step 6 — Hand off

The plan sits in the working tree as an unstaged file under paths.plan_dir. Hand off to implement with: path to the plan file + optional task focus ("only Tasks 1-3 this run").

The orchestrator commits the plan when handing it forward (suggested commit subject: plan: <iteration> <subject>). The planner skill does not perform the commit itself.

Handoff Contract

Direction Carrier
specifyplanner path to the spec under paths.spec_dir + iteration scope ("this iteration covers spec section X+Y")
plannerimplement path to the plan under paths.plan_dir + optional task-range focus
plannerspecify (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.
"The example program came straight from the spec, it must be valid" The spec's code blocks are hypotheses, not verified bytes — specify's parse gate can be skipped and a post-spec edit can break them. Re-parse every surface-language body you inline; this is the last line before the implementer hits it (issue #1 Fix 4).

Red Flags — STOP

  • Any of: "TBD", "TODO", "fill in later", "similar to", "add appropriate " — 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"
  • A task step inlining a surface-language code body whose fence label has a configured spec_validation parser, handed off without a parse-trace in the planner session

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). Mandatory; the orchestrator does NOT do recon in-context.