Files
Skills/specify/SKILL.md
T
claude fe5ca8f8c0 feat(pipeline): consolidate cycle recon, add fieldtest probe tier, enforce assumption economy
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
2026-07-25 13:52:04 +02:00

35 KiB


name: specify description: Use when the design is already settled — a long in-context design discussion, an exhaustive tracker issue, or a ratified design handed over by brainstorm — and a spec must be produced from those sources with review but without an interview. The spec-production core: applies the feature-acceptance criterion, writes the spec under docs/specs, runs the parse and grounding-check gates, takes user sign-off, hands off to planner. Bounces to brainstorm the moment the sources do not resolve a load-bearing design decision. Co-equal third entry path alongside brainstorm and tdd.

specify — spec-production entry path

Violating the letter of these rules is violating the spirit.

Overview

specify is where a settled design becomes an approved spec. It takes given sources — a long in-context design discussion, an exhaustive tracker issue, settled design docs, or a ratified design narrative handed over by brainstorm — and produces the spec the planner consumes: with review, but without an interview.

It is the sole home of the spec-production gates: the feature-acceptance criterion, the write-spec step, the grounding-check hard-gate, and the sign-off gate. Whichever way design work enters — fresh through brainstorm's discovery, or directly from sources that already resolve the design — it passes through specify to become a spec. specify carries the universal invariant no plan without an approved spec.

specify is the producing half of a deliberate split. brainstorm owns deciding — discovery (a grounded synthetic-user swarm), approaches, ratification. specify owns producing — rendering that decision into the canonical artefact and clearing the gates. The split is the toolchain's deepest discipline applied one level up: tdd → implement and debug → implement split RED from GREEN across two dispatches so the spec stays honest; specify splits deciding from producing so the producing phase reads the decision as a source rather than making it inline.

specify is a core pipeline node: it is the gate before planner on every design path that is not a bug fix or a test-specifiable feature. The side paths that carry no fresh prose design — compiler-driven, the harvest sweep — bypass it (../docs/pipeline.md § Skip rules). Where tdd is one entry path among three (chosen when behaviour is test-specifiable), specify sits on every prose-design path — it is not bypassed for those.

When to Use / Skipping

Triggers:

  • The design is settled in the sources and a spec must be written: an exhaustive issue body, a long in-context design discussion, or a ratified design brainstorm just handed over.
  • A cycle-scope spec is missing for settled work and one is needed.

Use the named alternative instead for:

  • A genuine design fork — the sources do not resolve a load-bearing decision. Use brainstorm (its discovery is what resolves the fork). specify itself bounces here the moment it detects this (see The Iron Law and Step 1.5).
  • A test-specifiable feature — the RED executable-spec is the spec. Use tdd directly.
  • An observed bug — use debug directly (RED-first).
  • A tidy iteration — use audit directly.
  • A trivial mechanical edit — per the project's CLAUDE.md carve-out.
  • Settled single-issue backlog drained as a batch — the harvest sweep's issue bodies are the ratified spec source; no new spec is written. See ../docs/pipeline.md § Harvest sweep.

Skipping a gate is never permitted. The interview is brainstorm's, and its absence here is the whole point — but the production gates (criterion, grounding-check, sign-off) are non-negotiable regardless of how the work entered. "The issue looks exhaustive, skip the grounding-check" is the reactive-deference failure this skill must not reintroduce. (Under /boss the sign-off gate is the grounding-check PASS itself — see Step 6.)

The Iron Law

EVERY LOAD-BEARING DESIGN DECISION MUST BE RESOLVED BEFORE THE SPEC IS WRITTEN — BUT
  "RESOLVED" INCLUDES A FORK THE ORCHESTRATOR CAN DERIVE AN ANSWER FOR (FROM THE SOURCES,
  THE CODE, EXISTING-DESIGN CONSISTENCY, OR RISK). A DERIVABLE FORK -> DECIDE IT BOLDLY AND
  RECORD THE DECISION IN THE REFERENCE ISSUE. ONLY A FORK THAT HANGS ON PURE USER PREFERENCE
  WITH NO DERIVABLE BETTER -> STOP AND BOUNCE / PAUSE. DO NOT BOUNCE A FORK YOU CAN DECIDE.
THE PRODUCTION GATES — ACCEPTANCE CRITERION, GROUNDING-CHECK, SIGN-OFF —
  ARE NON-NEGOTIABLE REGARDLESS OF ENTRY PATH.
NO PLAN, SCAFFOLDING, OR DOWNSTREAM SKILL UNTIL THE SPEC IS APPROVED — BY THE USER, OR
  (UNDER /boss) BY A grounding-check PASS. MODEL SELF-CONFIDENCE ALONE IS NEVER APPROVAL;
  THE grounding-check IS AN INDEPENDENT FRESH-CONTEXT AGENT, NOT THE PRODUCER'S CONFIDENCE.

Every clause is non-negotiable. The precondition gate is what makes the no-interview path legitimate rather than merely convenient: it is the honest fork-check that tdd's "is this test-specifiable?" is for test work. Its bar is decidability, not pre-settlement: a fork the orchestrator can ground an answer for is resolved by deciding it; only a fork that turns on the user's own preference, with no derivable better, is the one that bounces.

The Process

Step 1 — Explore / re-ground context

Before producing anything, establish what the sources actually say:

  • Direct entry (from sources): read the sources in full — the tracker issue body, the in-context design discussion, any settled design docs. This IS the design input. Then git log -5 --format=full for the current state of the project.
  • Chain entry (from brainstorm): the ratified design narrative is already in-context. Re-ground lightly — fresh git log, the files the design touches — rather than re-deriving it.
  • If the project has a design ledger (its CLAUDE.md project facts), walk to the contracts the work touches. Note any status: aspirational source: its code is a target, not verified fact.

Grounding fan-out — the cycle recon. When the work enters code territory the orchestrator has not recently read, dispatch ../planner/agents/plan-recon.md once, in its pre-spec form — carrier fields (sources, recon_scope, optional focus_hint) defined authoritatively under its Pre-spec dispatch (cycle recon) heading. When the sources already settle the change shape (a signature change, a variant add / remove, a symbol removal, a content-pin perturbation), name it in recon_scope: that arms the compile-driven enumeration inside the cycle recon and saves planner a mandatory delta later. The returned file-map grounds Step 2's criterion evidence and Step 3's ## Concrete code shapes, and is reused downstream by planner — budget, reuse conditions, and delta triggers are defined once in ../docs/pipeline.md § Cycle recon. A brainstorm-fired dispatch that meets that section's coverage condition IS the cycle recon — do not dispatch again. Do NOT ground a spec with a broad Explore-type sweep (§ Cycle recon's ban; field evidence on issue #35: a 151k-token Explore sweep here, ~40 % duplicated by the later plan-recon).

Step 1.5 — Precondition gate (bounce-back)

Enumerate the load-bearing design decisions the spec must encode — the choices that, decided differently, would change what ships. For each, ask the honest question:

Can I derive an answer for this fork — from the sources, the code, consistency with the existing design, or relative risk — or does it turn on a preference only the user holds?

This is a decidability test, not a pre-settlement test, and the default is decide, not bounce:

  • Derivable fork → decide it boldly. If there is a groundable reason to prefer one option — it fits the existing design better, it is simpler, it carries less risk, the sources lean that way — the orchestrator decides it and proceeds. It does not bounce a fork it can actually answer. When unsure whether its own leaning is bias rather than judgement, it pulls one independent opinion — an ad-hoc spec-skeptic lens (see Step 6) — and weighs it; the lens informs the decision, it does not veto. Every derived decision is recorded in the reference issue (below) with its rationale.
  • Pure-preference fork → bounce / pause. Only when the fork turns on something the orchestrator cannot derive — roadmap order, product taste, two genuinely equivalent paths whose trade-off only the user can weigh — is it a real bounce. Then STOP and bounce to brainstorm (see The Bounce-Back), or under /boss route to the human sign-off pause. A guessed preference baked into a spec is the reactive-overreach this gate still prevents.

The old "genuine doubt is the fork signal → bounce" reflex is retired: doubt about whether you can derive an answer resolves to an honest attempt to derive it (with a bias-breaker if needed), not to a reflexive bounce. Being wrong on a derived call is allowed — the net is the user's veto and, under /boss, the rollback sandbox (../boss/SKILL.md § Direction freedom). What is not allowed is dressing a pure-preference guess as a derived decision.

Every /boss run carries a reference issue. The run is always anchored to a tracker issue — an existing one that seeded the cycle, or one the orchestrator creates when the work was settled in pure chat with no prior issue (the mechanic below). That issue is the run's decision log: as the orchestrator derives fork answers, it comments each one there, so the user can audit and veto after the fact and the orchestrator has a cross-run "issue memory". Because a /boss dead-end is recovered by hard-dropping the autonomous commits (no attempt branch survives), the issue's comment thread is also the only surviving trace of an abandoned attempt — which is the second reason it is mandatory, not optional.

A comment records one of two distinct things, and the distinction is load-bearing:

  • A user decision the conversation settled — minuted with provenance (the user's decision intent stated in English + explicit attribution + date; a verbatim quote only where the exact wording is load-bearing, and then translated — ../issue/SKILL.md rule 4). Legitimate: you are recording what the user chose.
  • A derived orchestrator decision — recorded with its rationale (why one option is groundably better). Legitimate under the new stance, but it must be labelled as what it is: a derived call, never disguised as a user decision. If you cannot state a rationale, the fork was not derivable — that is a pure-preference bounce, not a comment.

Reconciliation comment (lagging-issue case). A fork can be resolved — by a user decision in the discussion, or derived by the orchestrator — yet still be listed open by the tracker issue that seeded the cycle. When that holds, record the resolution as an auditable issue comment before writing the spec, via the project's issue-tracker comment command (tea comment <idx> for Gitea; a heredoc body per the issue skill's conventions). One comment, this shape:

## Design reconciliation (specify)
Spec: <spec-name>. The fork(s) below are still listed open on this
issue; this records their resolution.
- **Fork: <name>** → <decision>.
  Basis: <user decision intent in English + attribution, OR "derived:" +
  the groundable rationale>.

Basis: carries either provenance (user decision) or rationale (derived decision) — both are auditable, neither is a bare decision: X with no support. The comment is persistent and auditable (author + timestamp, in the forward queue) — which is exactly why it, and not your ephemeral confidence, is what the user reads to understand and veto a call made without them. Recording it keeps the forward queue honest in either run mode.

Gitea writes are pre-authorized (per ~/.claude/CLAUDE.md); post the comment without a confirmation prompt.

Issue-less in-context entry. If the cycle has no tracker issue — the design was settled in pure chat — there is no existing artefact to comment on, so create one: open a new tracker issue that records the resolved fork(s) under the same discipline as the reconciliation comment above. The body takes this shape:

## Design record (specify, issue-less in-context entry)
This issue seeds <one-line identity of the work>. The design was settled
in an in-context discussion with no prior tracker issue; this records it.
Load-bearing fork(s) resolved:
- **Fork: <name>** → <decision>.
  Basis: <user decision intent in English + attribution, OR "derived:" + rationale>.

The body names the work, not the spec file — the spec does not exist yet at Step 1.5 (its number is assigned only in Step 3). This new issue is the run's reference issue from here on: the orchestrator comments later derived decisions on it as the run proceeds, and a downstream ad-hoc spec-skeptic can read it via the project's issue show command if the orchestrator pulls one. A new issue is the right artefact where a provenance note inside the spec would be the wrong one — a note inside the spec is self-referential (the spec asserting its own sources settle it) and stays banned, but a separate issue is independent (author + timestamp, in the forward queue, readable without opening the spec).

Create it via the project's issue-create command (the issue skill's mechanics — tea issues create for Gitea), title and label per the project's vocabulary. Gitea writes are pre-authorized, so create it without a confirmation prompt. Capture the new issue's index the moment it is created — it is the run's reference issue, the target for every later decision comment.

Step 2 — Apply the project's feature-acceptance criterion

The project's CLAUDE.md declares the criterion a feature must satisfy to ship. Apply it now, prospectively. The typical shape is some combination of:

  • the project's intended audience naturally reaches for the feature,
  • the feature measurably improves correctness or removes redundancy,
  • the feature reintroduces no class of failure the project's core constraint exists to eliminate.

If the project declares no criterion, the default is "the feature solves a real user-facing problem and does not contradict a stated design commitment". The orchestrator applies the criterion; do not delegate it to the user.

The criterion is unjudgeable without concrete code. For any cycle with authoring or consumer surface, the spec MUST contain the actual program / invocation / configuration a user would write — and that example is the criterion's empirical evidence. A prose assertion ("a user naturally reaches for X") with no shown code is the unfalsifiable hand-wave the criterion exists to prevent: write the code the user would write, then judge whether it is what the criterion demands. For an infrastructure cycle with no user surface there is still concrete code: show the code the cycle delivers — frequently a test fixture whose correct behaviour is rejection — plus a minimal, honest slice of the north-star program the infrastructure serves. "No surface so no code to show" is the rationalisation to refuse.

Code lifted from an aspirational source is a hypothesis, not evidence. If the concrete code here is lifted from a design-models file (or any status: aspirational source, per Step 1), it carries no validation by default. Treat it as the spec's most suspect bytes: flag it as a target, not verified fact.

Step 3 — Write the spec

Path: under docs/specs, named slug.md per the fixed naming convention (see docs/conventions.md § Naming) — a short kebab-case topic slug, no numeric prefix. The directory is git-ignored via the project's committed docs/.gitignore; if that file does not yet ignore specs/, create it first (docs/conventions.md § File layout) so the spec can never be committable. The spec is created under docs/specs and never git add'd.

Structure:

# <Title> — Design Spec

**Date:** YYYY-MM-DD
**Status:** Draft — awaiting user spec review
**Authors:** orchestrator + Claude

## Goal
## Architecture
## Concrete code shapes
## Components
## Data flow
## Error handling
## Testing strategy
## Acceptance criteria

## Concrete code shapes is mandatory and leads with the user-facing program: the worked author example for a surface cycle (= the Step-2 empirical evidence), or — for a no-surface infra cycle — the code the cycle delivers (often a must-fail fixture) plus a minimal honest north-star slice. The before → after implementation shape (struct / signature / match-arm) for each load-bearing change follows as an explicitly secondary subsection, never first. Prose may explain code, never replace it. Exact bytes / line-numbers remain the planner's job — the spec owns the shape, shown.

Assumption economy — fewer restatements, never fewer reliances. Every assertion the spec makes about current codebase behaviour is a load-bearing-assumption candidate the Step-5 grounding-check must extract and ratify — the gate's cost scales with the count, and it BLOCKs an over-broad spec outright (agents/grounding-check.md). So: state a current-behaviour claim only where the change actually relies on it (the gate's test: its falsity would make the change fail or cost additional work), and render context-only mentions of existing mechanisms as a design-ledger contract citation instead of restating their behaviour. This trims restatements, never reliances: a mechanism the change builds on remains an assumption — explicit, or the implicit form the gate extracts anyway — and writing it as a bare citation does not exempt it; hiding a reliance is exactly the failure the gate exists to catch. The same economy applies to scope: a tightly-cut iteration makes fewer claims than a sprawling one (field evidence on issue #35: gate cost tracks the spec's assumption count near-linearly).

Step 4 — Self-review

Inline checklist (not a subagent dispatch):

  1. Placeholder scan: any "TBD", "TODO", incomplete sections, vague requirements? Fix.
  2. Internal consistency: sections must not contradict. Architecture must match component descriptions.
  3. Scope check: focused enough for one plan, or does it need sub-cycle decomposition?
  4. Ambiguity check: could any requirement be read two ways? Pick one and make it explicit.
  5. Concrete-code check: does ## Concrete code shapes exist and carry before → after code for every load-bearing change (plus the worked user-facing example for a surface cycle)? A load-bearing change described only in prose is a self-review failure to fix.
  6. Assumption economy: scan every claim about current codebase behaviour. The gate's own criterion decides which stay: a claim is a reliance iff its being false would make the proposed change fail or require additional work (agents/grounding-check.md § What "load-bearing assumption" means). Non-reliances are gate cost with no return — delete them, or demote them to a citation that carries no behaviour claim. Never demote a reliance: a bare citation does not ratify it, and the gate BLOCKs on it unratified (Step 3's restatements-vs-reliances line).

Fix issues inline.

Step 5 — Grounding-check (hard-gate)

Dispatch the read-only grounding-check agent. The agent reads the just-written spec with fresh context, extracts its load-bearing assumptions about current behaviour of the codebase, and for each searches the workspace for a currently-green test that ratifies it.

Dispatch carrier — the fields spec_path and iteration_scope, defined authoritatively under Carrier contract in agents/grounding-check.md (note spec_path is an absolute path). That table is the single source for those fields; it is deliberately not restated here, so the two files cannot drift.

The agent returns PASS / BLOCK / INFRA_ERROR. Interpretation:

Agent status Orchestrator action
PASS Proceed to Step 6. The report goes into the chat for the record.
BLOCK Present the report to the user. User either: (a) accepts discard → execute the failure-mode procedure below; or (b) overrides in free chat ("Test <path>::<name> ratifies that") → log the override note and proceed to Step 6.
INFRA_ERROR Abort. The spec stays as-is on disk; debug the workspace out-of-band and re-dispatch the agent.

Failure-mode procedure (no-override BLOCK):

  1. Delete the just-written spec file from the working tree (rm <spec_path> — a shell delete, NOT git rm; never committed).

  2. Open a backlog issue (via the project's issue-tracker create command) pointing forward to a future re-design. Include:

    • Title: one-line identity of the deferred work
    • Label: matching the project's vocabulary (feature / bug / idea; promote to BLOCKER if the unratified mechanism is on a core-functionality path)
    • Body: short description plus two structured lines:
      • depends on: <name of the unratified mechanism>
      • context: <why this is deferred>

    If the deferred work needs its own spec on resumption (multi-iteration, cross-subsystem), file it as a milestone container instead of a single issue.

  3. Tell the user the spec was retired and which backlog entry was filed. No commit is needed — the issue tracker is the live store.

After the failure-mode procedure runs, the session ENDS. There is no Step 6, no Step 7. The idea is parked until the dependency ships.

Re-dispatch on any post-PASS edit. The PASS report is bound to the exact bytes of the spec at dispatch time. Any subsequent edit — polish, a user-requested change, a wording tighten — invalidates the PASS report and requires a fresh dispatch of grounding-check before the Step-6 sign-off and commit. Step 5 is the last step that touches the spec file; nothing slips between it and the commit.

Step 6 — Sign-off gate

Outside /boss the signature is the user's; under /boss it is the Step-5 grounding-check PASS (the /boss subsection below).

The spec sits in the working tree as a git-ignored working file. Tell the user:

Spec written to <path> (git-ignored, never committed). Please review it and let me know if you want changes before we start the implementation plan.

Wait for the user's response. If they request changes, edit the file in place, re-run Step 4 AND re-dispatch Step 5 (the previous PASS report no longer covers the edited bytes), then return here. Only proceed after approval AND a fresh Step 5 PASS.

The spec is never committed: it is a git-ignored active-cycle working file that lives on disk only for its own cycle and is shell-rm'd at cycle close by audit (see docs/conventions.md § Lifecycle). The durable record of its design intent is the design ledger, lifted during audit — not the spec file.

In /boss (autonomous): specify is dispatched autonomously — it is bounded (no interview), so there is no user at this gate to take the signature. The signature comes from the Step-5 grounding-check PASS: an independent fresh-context agent's verdict against currently-green tests, not the producing orchestrator's confidence — and that is what the bold stance trusts in the user's place. There is no adversarial panel, no objective-gates-then-panel staging, no self-correction loop; those were retired in favour of decide-upstream + recover-downstream (baseline tag pre-autosign-rework).

  • On a Step-5 PASS: the spec is signed by the PASS — leave it as a git-ignored working file (never committed). Record the autonomous sign on the run's reference issue (a decision-log comment: which capability, that the grounding-check PASS was the signature, that no human signed), fire the auto-sign notify (see boss § Notifications — it names the capability in user terms and states the plan is proceeding and a reply vetoes), then proceed to Step 7. No pause.
  • On a Step-5 no-override BLOCK or INFRA_ERROR: there is no human to override it, so it routes to the human sign-off pause — a problem-state notify ("spec X needs your sign-off") — exactly as the Step-5 failure mode describes. A no-override grounding BLOCK is the one objective denial of an autonomous sign and is never signed over.

The judgement that used to live in the panel now lives upstream, in Step 1.5's bold-decide stance: a load-bearing fork is decided there (with an ad-hoc spec-skeptic bias-breaker if the orchestrator wants one) and recorded in the reference issue, or — if it is a pure-preference fork — bounced before the spec is ever written. By the time a spec reaches this gate the only thing left to verify is the objective one the grounding-check already verifies. Editorial defects the old panel would have caught (a clumsy worked example, a two-way-readable sentence) are allowed through deliberately: they are cheap to patch inline downstream, and catching them was never worth an obligatory five-juror panel on every spec.

Bias-breaker (optional, the orchestrator's call). When deciding a fork in Step 1.5 the orchestrator MAY dispatch the read-only spec-skeptic agent ad hoc — one lens, or a few, whichever fork it is unsure about — for an independent refutation to weigh against its own leaning. This is a tool it reaches for, not a gate it must clear: the lens returns a finding, the orchestrator decides. Carrier and lenses are defined in agents/spec-skeptic.md.

Auto-signed CODE commits are forward-only once ratified — with one /boss exception. The spec itself is never a commit (it is a git-ignored working file), so a later user veto is a forward correction: shell-rm (or edit) the git-ignored spec, and git revert / git checkout only the downstream code it produced. The /boss rollback sandbox is the exception: within an autonomous run the orchestrator may hard-reset its own unpushed autonomous code commits back toward (never below) the session anchor when it has run into a dead end — its own work only, and it shell-rms the git-ignored spec/plan of the abandoned line. See boss § Direction freedom for the exact boundary.

Step 7 — Hand off to planner

The terminal state of specify is invoking planner. NO other skill is invoked from specify. NO direct jump to implement.

Hand off carries:

  • path to the spec under docs/specs
  • iteration scope ("the first iteration covers section X+Y of the spec")

The Bounce-Back

specify returns to brainstorm whenever the precondition fails — a load-bearing fork turns on pure user preference the orchestrator cannot derive (Step 1.5), or a grounding-check BLOCK reveals an unratified mechanism the user does not override (Step 5 failure-mode routes to a re-design). A fork the orchestrator can derive an answer for is not a bounce — it is decided and recorded in the reference issue. On a precondition bounce:

  1. Nothing was written yet (the gate fires before Step 3), so there is no working-tree artefact to discard.
  2. Invoke brainstorm with the unresolved design question as the cycle request. From there the normal brainstorm → specify → planner path runs.

The bounce-back is not a failure of this skill; it is the skill correctly refusing to ratify a pure-preference guess into a spec — the same discipline tdd applies when behaviour is not test-specifiable. It is narrow by design: only the user's-call forks bounce, not every fork.

Handoff Contract

Direction Carrier
user / issue (design settled) → specify the sources: issue body, in-context design discussion, design docs
brainstormspecify ratified design narrative (approaches chosen, constraints, sections approved) — in-context; brainstorm writes no spec file
specifyplan-recon (Step 1, the cycle recon — skipped when a brainstorm-fired dispatch meets the coverage condition) sources + recon_scope + optional focus_hint; defined authoritatively under Pre-spec dispatch (cycle recon) in ../planner/agents/plan-recon.md
specifygrounding-check (Step 5) spec_path (absolute) + iteration_scope
specifyspec-skeptic bias-breaker (Step 1.5, optional, orchestrator's call) spec_path (absolute) + iteration_scope + one lens + seeding_issue (or none); dispatched ad hoc for a fork the orchestrator is deciding, never as a gate
specify → reference issue (Step 1.5) a derived-decision comment (rationale) or user-decision comment (provenance); a freshly created seeding issue if the cycle had none
specifyplanner (Step 7, on PASS or overridden BLOCK) path to spec + iteration scope
specifybrainstorm (precondition bounce, pure-preference fork) the unresolved design question as a cycle request; no spec written
specify → issue backlog (Step 5, no-override BLOCK) new issue naming the unratified dependency; spec file deleted from the working tree

Common Rationalisations

Excuse Reality
"The issue looks exhaustive — skip the grounding-check / criterion too" The interview is what specify skips, by design. The production gates are not the interview; they are what keeps the spec honest no matter how it entered. Skipping a gate because the sources look thorough is the exact reactive-deference failure this skill must not reintroduce.
"There's an open fork left — I should bounce to brainstorm to be safe" Only if it is a pure-preference fork. If you can derive an answer — sources, code, consistency, risk — decide it boldly, record the rationale in the reference issue, and proceed. Bouncing a fork you can actually decide is the reactive-deference reflex the new stance retired.
"I can derive an answer but I'm not 100% sure it's right — safer to bounce" Being wrong on a derived call is allowed: the net is the user's veto and the /boss rollback sandbox. If you're unsure your leaning is judgement not bias, pull one ad-hoc spec-skeptic lens and weigh it — then decide. Reserve the bounce for forks only the user's preference can settle.
"This is pure product taste but one option seems fine — I'll just pick it" A fork with no derivable better is the user's call; picking it is the pure-preference guess the gate still forbids. Bounce it, or under /boss route to the human sign-off pause. The line is derivable vs. preference, not small vs. large.
"The shape is clear from the prose, I don't need to paste the code" If it's clear, pasting it is free; if pasting it is hard, it wasn't clear. The acceptance criterion is unjudgeable without the worked code.
"Just polishing a wording after PASS, no need to re-dispatch" The grounding-check report attests to specific bytes. A polish edit changes the bytes; the attestation no longer covers them. Re-dispatch is cheap.
"It's in a model doc / the design ledger, so it's canonical" A models / RFC / proposal doc holds aspirational code — a target, not verified fact. Flag code lifted from a status: aspirational source as such; it is not ratified contract.
"Fewer assumptions = a cheaper grounding-check, so I'll phrase the reliances as vague citations" Economy cuts restatements, not reliances. A mechanism the change builds on stays a claim — vague phrasing merely converts it to the implicit form the gate extracts anyway, or worse, hides a false premise until a downstream iteration BLOCKs on it. Trim what the change does not rest on; never what it does.
"In /boss this spec looks solid — I'll sign and move on" Your sense that it looks solid is not the signature. Under /boss the signature is the Step-5 grounding-check PASS — an independent agent's verdict, not your confidence. Run the grounding-check; a no-override BLOCK routes to the human, never auto-signed over.
"A grounding BLOCK looks like a false alarm — I'll sign over it" With no human in the loop there is no override. A no-override grounding BLOCK is the one objective denial of an autonomous sign; it routes to the human sign-off pause. The whole point of trusting grounding-PASS as the signature is that you also honour its BLOCK.

Red Flags — STOP

  • A pure-preference fork silently picked instead of bounced — or its inverse: a derivable fork bounced to brainstorm instead of decided (the reactive-deference reflex the new stance retired)
  • A derived fork decision made but not recorded in the reference issue (no rationale comment, or no reference issue at all on a /boss run)
  • "The sources are thorough, skip a gate" thoughts (any flavour)
  • A load-bearing change described in prose with no before → after code block; a surface cycle with no worked user-facing example
  • Lifting code verbatim from a status: aspirational source without flagging it as a target, not verified fact
  • Editing the spec file after a Step 5 PASS without re-dispatching
  • (auto-sign) About to sign a spec in the user's place on confidence — rather than on the Step-5 grounding-check PASS that is the autonomous signature; or signing over a no-override grounding BLOCK / INFRA_ERROR instead of routing it to the human sign-off pause
  • (auto-sign) Treating the retired spec-skeptic panel as still a gate — re-introducing a unanimous five-juror pass as a sign precondition, rather than using spec-skeptic only as the optional Step-1.5 bias-breaker; or running any auto-sign path outside a /boss session (interactive runs take the user's signature directly)
  • Jumping straight from spec to implement (must go via planner)
  • Running an interview here (that is brainstorm's job — if the work needs one, bounce)
  • Grounding the spec with a broad Explore-type sweep — or a second full recon dispatch when a cycle recon already exists (../docs/pipeline.md § Cycle recon)

Cross-references

  • Output target: ../planner/SKILL.md — only valid next skill.
  • Discovery front-end / bounce-back target: ../brainstorm/SKILL.md — produces the ratified design specify consumes on the chain path, and reclaims the work when the sources do not resolve a design fork.
  • Sibling fast path: ../tdd/SKILL.md — the same bounce-to-brainstorm-on-fork discipline, for test-specifiable work; its RED executable-spec is the spec, so it skips both specify and planner.
  • Agent dispatched: agents/grounding-check.md — dispatched in Step 5 as a hard-gate. Reads the spec with fresh context and reports PASS / BLOCK / INFRA_ERROR.
  • Agent dispatched (optional bias-breaker): agents/spec-skeptic.md — an ad-hoc tool, not a gate. Under /boss, when the orchestrator is deciding a load-bearing fork in Step 1.5 and is unsure whether its leaning is judgement or bias, it MAY dispatch one (or a few) spec-skeptic lens(es) for an independent refutation to weigh. The lens returns a finding; the orchestrator decides. The former obligatory unanimous five-lens auto-sign panel is retired (baseline tag pre-autosign-rework); the autonomous signature is now the Step-5 grounding-check PASS.
  • Cycle recon (Step 1). ../planner/agents/plan-recon.md in its pre-spec form is the cycle's ONE full recon dispatch when the work enters code territory not recently read; its report also serves planner downstream. Budget, reuse conditions, and delta triggers: ../docs/pipeline.md § Cycle recon.
  • Project feature-acceptance criterion: declared in the project's CLAUDE.md. Applied prospectively in Step 2.