7a58a530b1
The selector forced every task through the heaviest methodology's
critical path: a behaviour-preserving, type-enumerable change paid the
same specify -> planner -> implement front-half as a novel feature,
because it was neither new behaviour (tdd) nor an observed bug (debug)
and so fell to specify by elimination. Two coupled defects — a selector
with no verification axis, and an all-or-nothing executor — kept the
existing lighter path unreachable and uneconomical. This fixes both.
Part A — verification-keyed selector (boss/SKILL.md):
- Replace the three-way "design line" with an ordered cascade that adds
a verification/enumeration axis ahead of the settled-vs-fork question.
Each lighter arm carries a positive trigger matched by signature, not
reached by elimination.
- New `compiler-driven` arm: a type/signature edit at a definition site
that propagates mechanically. Observe-then-bounce — make the edit,
build, run the suite; clean build AND suite green unchanged commits;
a hole bounces up (specify for a design choice, tdd for discovered
test-specifiable new behaviour); a regression bounces to debug.
- The observed-bug RED-first gate is first in the cascade, so a
mechanical-looking fix cannot bypass it.
- The straddle rule ("add an enum variant") is codified as a rule:
mechanical/forwarding -> compiler-driven; encodes new behaviour ->
tdd/spec; doubt routes up.
- The executor is the elevated inline carve-out plus a shipped workflow,
not a heavy new skill ("the largest concrete win is small").
Part B — Workflow substrate (implement/workflows/):
- implement-loop.js: the per-task loop as a deterministic script. Each
phase (implementer -> spec-compliance -> quality, + tester for E2E) is
a separate top-level agent() call, so a single phase is independently
invokable and inter-phase aggregation/re-loop is code. Retires the
implement-orchestrator agent's inline-role-switch workaround (the four
phase agents survive as the agent-types the script dispatches).
- compiler-driven-edit.js: the observe-then-bounce loop.
- install.sh / uninstall.sh symlink shipped workflows into
~/.claude/workflows/.
- specify and brainstorm stay prose + interactive (human-intent oracle);
only the autonomous/mechanical loops moved. try-and-error is deferred.
Docs (pipeline taxonomy, design, agent-template, migration, README) and
all selector<->executor cross-references updated; the arm and its
executor are co-located so a future re-route through the full loop is a
visible regression.
Verified by an adversarial multi-agent pass: PASS on all six acceptance
criteria; two coherence concerns fixed. The shipped scripts are
syntax-validated but exercised only in a downstream target project (the
skills repo is not itself a pipeline target).
closes #7
567 lines
32 KiB
Markdown
567 lines
32 KiB
Markdown
---
|
|
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 user-review 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* — interview, 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.
|
|
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.
|
|
|
|
**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, user-review) 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.
|
|
|
|
## The Iron Law
|
|
|
|
```
|
|
THE SOURCES MUST RESOLVE EVERY LOAD-BEARING DESIGN DECISION BEFORE THE SPEC IS WRITTEN.
|
|
IF WRITING THE SPEC FORCES A CHOICE BETWEEN PLAUSIBLE DESIGNS THE SOURCES DO NOT RESOLVE,
|
|
STOP AND BOUNCE TO brainstorm. DO NOT SILENTLY PICK ONE.
|
|
THE PRODUCTION GATES — ACCEPTANCE CRITERION, GROUNDING-CHECK, USER-REVIEW —
|
|
ARE NON-NEGOTIABLE REGARDLESS OF ENTRY PATH.
|
|
NO PLAN, SCAFFOLDING, OR DOWNSTREAM SKILL UNTIL THE SPEC IS APPROVED — BY THE USER, OR
|
|
(ONLY UNDER /boss WITH spec_auto_sign ENABLED) BY THE AUTO-SIGN GATE: ALL OBJECTIVE GATES GREEN
|
|
AND A UNANIMOUS ADVERSARIAL spec-skeptic PANEL. MODEL SELF-CONFIDENCE ALONE IS NEVER APPROVAL.
|
|
```
|
|
|
|
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.
|
|
|
|
## 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.
|
|
|
|
### 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:
|
|
|
|
> Do the sources **resolve** this, or am I about to **pick** it
|
|
> myself?
|
|
|
|
If every load-bearing decision is resolved by the sources, proceed to
|
|
Step 2. If even one is unresolved — the sources leave a genuine fork
|
|
between plausible designs with real trade-offs — **STOP and bounce to
|
|
`brainstorm`** (see Error handling / The Bounce-Back). Do not silently
|
|
pick one and bake it into the spec; a guessed design ratified into a
|
|
spec is harder to dislodge than an open question, and it is exactly
|
|
the reactive-deference failure the gate exists to prevent.
|
|
|
|
Genuine doubt about whether the sources resolve a decision *is itself*
|
|
the fork signal — it resolves to a bounce, not to a guess.
|
|
|
|
**Reconciliation comment (lagging-issue case).** A load-bearing fork can
|
|
be resolved by the in-context design discussion yet still be listed
|
|
*open* by the tracker issue that seeded the cycle — the issue lags the
|
|
conversation. When that holds (entry is in-context **and** a tracker
|
|
issue still carries a now-resolved fork as open), 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
|
|
exact shape:
|
|
|
|
```
|
|
## Design reconciliation (specify, in-context entry)
|
|
Spec: <spec-name>. The fork(s) below are still listed open on this
|
|
issue; they were resolved in the in-context design discussion.
|
|
- **Fork: <name>** → <decision>.
|
|
Provenance: <verbatim user statement, or explicit attribution + date>.
|
|
```
|
|
|
|
The comment must carry **provenance**, and the distinction is
|
|
load-bearing: it is the *record of a user decision* (legitimate — the
|
|
user settled the fork in discussion, you are minuting it), never a *new
|
|
orchestrator decision* dressed as settled (illegitimate). A bare
|
|
`decision: B` with no provenance is the latter. If you cannot point to a
|
|
real user statement, that is the signal that *you* picked the fork, not
|
|
the user — which is a Step-1.5 bounce, not a comment. The comment is
|
|
*persistent and auditable* (author + timestamp, in the forward queue) —
|
|
which is exactly why it, and not your ephemeral confidence, is what a
|
|
downstream `scope-fork` juror reads to confirm the fork is settled (see
|
|
Step 6). Recording it keeps the forward queue honest in either run mode;
|
|
under auto-sign it is *load-bearing* — without it the `scope-fork` juror
|
|
sees only the stale issue body and (correctly) blocks.
|
|
|
|
Provenance enforcement is not yours to self-certify: you *write* the
|
|
comment, the adversarial `scope-fork` juror *checks* it carries
|
|
provenance (Step 6). Writing a provenance-less comment does not buy a
|
|
pass — the re-dispatched juror blocks on it.
|
|
|
|
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) with provenance, 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>.
|
|
Provenance: <verbatim user statement, or explicit attribution + date>.
|
|
```
|
|
|
|
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 cycle's seeding issue from here on: the `scope-fork` juror reads
|
|
it via the project's issue show command — its index handed to the juror
|
|
in the Step-6 carrier (the `seeding_issue` field, below) — exactly as it
|
|
reads any seeding issue. A *new issue* is the right artefact where a spec-note
|
|
is the wrong one — a provenance 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, juror-readable without opening the spec), as
|
|
auditable as a reconciliation comment. Creating it is what makes
|
|
auto-sign *reachable* here, instead of the old unconditional fall-back
|
|
to the human sign-off.
|
|
|
|
The provenance gate is unchanged and load-bearing: the new issue records
|
|
*user* decisions, never fresh orchestrator ones. No real user statement
|
|
for a fork means *you* picked it — a Step-1.5 bounce, not an issue to
|
|
manufacture. You *write* the issue; the adversarial `scope-fork` juror
|
|
*checks* the provenance, and a provenance-less body buys no pass.
|
|
|
|
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 as in the Step-5 failure-mode procedure. Gitea
|
|
writes are pre-authorized, so create it without a confirmation prompt.
|
|
**Capture the new issue's index** the moment it is created and carry it
|
|
into the Step-6 panel as the `seeding_issue` field — it is the only way
|
|
the `scope-fork` juror knows which issue to read. An issue created but
|
|
never handed to the panel is invisible to the juror, which leaves the
|
|
fork looking picked and the creation pointless.
|
|
|
|
### 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 per the fixed naming convention —
|
|
`NNNN-slug.md`, 4-digit per-directory counter (see
|
|
`docs/conventions.md`). Determine the next free number by scanning the
|
|
directory.
|
|
|
|
Structure:
|
|
|
|
```markdown
|
|
# <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.
|
|
|
|
### 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.
|
|
|
|
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 — User-review gate
|
|
|
|
The spec sits in the working tree as an unstaged file. Tell the user:
|
|
|
|
> Spec written to `<path>` (uncommitted). Please review it and let me
|
|
> know if you want changes before we start the implementation plan.
|
|
> The orchestrator will commit it once you approve.
|
|
|
|
Wait for the user's response. If they request changes, edit the file
|
|
in place (still uncommitted), **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 orchestrator commits the approved spec after sign-off (suggested
|
|
commit subject: `spec: <cycle> <topic>`). The skill does not perform
|
|
the commit itself.
|
|
|
|
**In `/boss` (autonomous):** `specify` is dispatched autonomously —
|
|
it is bounded (no interview). It runs the criterion, parse, and
|
|
grounding-check gates without a checkpoint. What happens at *this*
|
|
gate then depends on whether the project enables spec auto-sign (its
|
|
CLAUDE.md project facts):
|
|
|
|
- **Slot absent or `false` (default):** `specify` **pauses here** as a
|
|
problem-state notify ("spec X ready, please sign off") and waits for
|
|
the user. This is the final sign-off pause, not a pre-dispatch
|
|
checkpoint — the distinction from `brainstorm`, which `/boss` bounces
|
|
*before* dispatch. This is the conservative default; the user's
|
|
signature is mandatory.
|
|
|
|
- **Slot `true`:** the orchestrator MAY sign in the user's place, but
|
|
only through the **auto-sign gate** below. The gate exists because
|
|
the orchestrator that wrote the spec is the worst-placed party to
|
|
judge it — so the gate is built to *not* rely on the orchestrator's
|
|
own confidence. Run it in two stages:
|
|
|
|
1. **Objective gates (all must already hold — these are facts, not
|
|
judgements):**
|
|
- Step 1.5 precondition gate passed cleanly — no load-bearing
|
|
fork was silently picked (if one had been, `specify` would have
|
|
bounced, so reaching here is the evidence; do not re-decide it).
|
|
- Step 4 self-review clean, **including the placeholder scan** (no
|
|
`TBD` / `TODO` / incomplete section).
|
|
- Step 5 `grounding-check` returned **`PASS`** — *not* an
|
|
overridden `BLOCK`. An override needs a human; with no human in
|
|
the loop a `BLOCK` can never be overridden, so any non-`PASS`
|
|
grounding result denies auto-sign outright.
|
|
|
|
If any objective gate is not green, **do not run the panel** —
|
|
fall straight to the human sign-off pause (the default-slot
|
|
behaviour above), carrying the failing gate in the notify.
|
|
|
|
2. **Adversarial panel (unanimous-or-nothing):** dispatch the
|
|
read-only `spec-skeptic` agent **five times in parallel**, once
|
|
per lens — `criterion`, `grounding`, `scope-fork`, `ambiguity`,
|
|
`plan-readiness`. Carrier per dispatch: `spec_path` (absolute),
|
|
`iteration_scope`, the single `lens`, and `seeding_issue` — the
|
|
index of the cycle's seeding issue (the lagging issue reconciled in
|
|
Step 1.5, the issue Step 1.5 created for an otherwise issue-less
|
|
cycle, or `none` if the cycle has neither) for the `scope-fork`
|
|
juror to read; the other four lenses ignore it. Each juror tries to
|
|
*refute* the spec along its lens and returns `SOUND` / `BLOCK` /
|
|
`INFRA_ERROR`. Auto-sign requires a **unanimous `SOUND`** — that
|
|
never changes. What the partition below adds is a bounded path to
|
|
*reach* that unanimity for defects the orchestrator can repair
|
|
without judging the spec.
|
|
|
|
The five lenses split by what a `BLOCK` actually means:
|
|
|
|
| Lens class | Lenses | A `BLOCK` means |
|
|
|------------|--------|-----------------|
|
|
| **Editorial** | `criterion`, `ambiguity`, `plan-readiness` | The spec is under-*articulated*: missing worked evidence, a requirement readable two ways, scope too broad for one plan. Repairable by editing the prose without settling any new design or fact. A `criterion` repair may only *supply or sharpen the worked evidence the criterion already demands* (paste the concrete before → after / user-facing code the spec implied) — it may **not** soften what the criterion requires or re-judge acceptance, and if the missing evidence cannot be shown without picking an un-settled design, that is a `scope-fork` in disguise: leave it, and the re-dispatched `scope-fork` juror escalates it. |
|
|
| **Design** | `scope-fork`, `grounding` | The *ground is not settled*: the sources do not resolve a load-bearing fork, or a load-bearing assumption is not ratified by a green test. The orchestrator may **never** settle these in the user's place. |
|
|
|
|
Resolve the panel against that split, in a bounded loop
|
|
(`round` starts at `0`):
|
|
|
|
| Panel outcome this round | Orchestrator action |
|
|
|--------------------------|---------------------|
|
|
| All five `SOUND` | **Auto-sign.** Commit the spec yourself (subject `spec: <cycle> <topic> (boss-signed)`), send the informational auto-sign notify (see `boss` § Notifications — names the capability in user terms and states the plan is proceeding and a reply vetoes), then proceed to Step 7. No pause. |
|
|
| Any `INFRA_ERROR` | **Escalate.** Fall back to the human sign-off pause; the notify carries the failing dispatch. |
|
|
| Any **design**-lens (`scope-fork` / `grounding`) `BLOCK` | **Escalate.** No self-correction — this is exactly the judgement the gate refuses to make for the user. Fall back to the human sign-off pause, carrying *all* lens findings this round. |
|
|
| Only **editorial**-lens `BLOCK`(s), and `round == 2` | **Escalate.** The self-correction budget is spent. Fall back to the human sign-off pause, carrying the findings *and* the per-round correction history. |
|
|
| Only **editorial**-lens `BLOCK`(s), and `round < 2` | **Self-correct.** Edit the spec in place to address each editorial finding (each names its `§section` / offending text / defect). Then **re-run Step 4 self-review and re-dispatch Step 5 `grounding-check`** — the edit invalidated the prior `PASS` (see "Re-dispatch on any post-PASS edit"); if `grounding-check` does not return `PASS`, escalate. Increment `round` and re-dispatch all five lenses from the top of this table. |
|
|
|
|
**Re-loop limit: ≤ 2 self-correction rounds. The 3rd unresolved
|
|
editorial `BLOCK` escalates** — same shape as the per-task re-loop
|
|
limit in the implement loop (`../implement/workflows/implement-loop.js`).
|
|
|
|
Three properties keep this loop honest, not a way to grind the panel
|
|
into submission:
|
|
|
|
- **The panel stays the sole arbiter.** The orchestrator never judges
|
|
the spec; it only edits in response to a juror's finding, and a
|
|
fresh panel re-adjudicates. "The spec looks good to me" still never
|
|
signs.
|
|
- **Re-dispatch is all five lenses, every round.** This is the
|
|
backstop. If an editorial repair silently *launders* an unsourced
|
|
design decision into the spec (resolving an ambiguity by picking an
|
|
un-settled fork), the re-run `scope-fork` / `grounding` jurors now
|
|
`BLOCK` on it — and a design `BLOCK` escalates. The only thing the
|
|
loop can converge to autonomously is a spec whose every lens is
|
|
`SOUND` *and* whose only repairs were editorial.
|
|
- **Escalation is the panel doing its job**, not a failure — it routes
|
|
the spec to the human who was going to review it anyway, the moment
|
|
a real design question surfaces or the budget runs out.
|
|
|
|
**Auto-sign commits on `main` are forward-only like every other
|
|
commit.** A later user veto is a forward correction (revert / revised
|
|
spec / `git checkout` of downstream working-tree work), never a
|
|
history rewind — same discipline as any other orchestrator call (see
|
|
`boss` § Direction freedom).
|
|
|
|
### 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 — the
|
|
sources do not resolve a load-bearing design decision (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). 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 an un-chosen design into a spec — the same
|
|
discipline `tdd` applies when behaviour is not test-specifiable.
|
|
|
|
## Handoff Contract
|
|
|
|
| Direction | Carrier |
|
|
|-----------|---------|
|
|
| user / issue (design settled) → `specify` | the sources: issue body, in-context design discussion, design docs |
|
|
| `brainstorm` → `specify` | ratified design narrative (approaches chosen, constraints, sections approved) — in-context; brainstorm writes no spec file |
|
|
| `specify` → `grounding-check` (Step 5) | `spec_path` (absolute) + `iteration_scope` |
|
|
| `specify` → `spec-skeptic` panel (Step 6, `/boss` + `spec_auto_sign` only) | `spec_path` (absolute) + `iteration_scope` + one `lens` per dispatch (five in parallel) + `seeding_issue` (index for the `scope-fork` juror to read, or `none`) |
|
|
| `specify` → `planner` (Step 7, on PASS or overridden BLOCK) | path to spec + iteration scope |
|
|
| `specify` → `brainstorm` (precondition bounce) | 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 a small open fork but the sources mostly decide it — I'll pick the rest" | "Mostly decided" with one real fork left is an unresolved design, and a guessed design baked into a spec is harder to dislodge than an open question. That is the bounce-back trigger — stop and go to `brainstorm`. |
|
|
| "Genuine doubt whether the sources resolve this — but bouncing feels like overkill" | Doubt about whether the sources resolve a decision *is* the fork signal. It resolves to a bounce, not a guess. The bounce is cheap (nothing is written yet); a wrong guess in a ratified spec is not. |
|
|
| "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. |
|
|
| "In `/boss` with auto-sign on, this spec looks solid — I'll sign and move on" | Your sense that it looks solid is the exact signal the auto-sign gate refuses to trust. Signing requires all objective gates green AND a unanimous `spec-skeptic` panel. If you find yourself wanting to sign on confidence, that is the cue to run the gate, not to skip it. |
|
|
| "One lens blocked on something minor — I'll sign anyway since the rest passed" | The panel is unanimous-or-nothing by design. You never *sign over* a `BLOCK`. An editorial `BLOCK` you may *repair* (within the ≤ 2-round budget, with a full re-panel after); a design `BLOCK` routes to the human. Neither is overruling a juror — that is the whole point of replacing your eye with five independent ones. |
|
|
|
|
## Red Flags — STOP
|
|
|
|
- An unresolved design fork silently picked instead of bounced (any flavour)
|
|
- "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 —
|
|
without all objective gates green AND a unanimous `spec-skeptic`
|
|
panel; signing over any `BLOCK`; self-correcting a *design*-lens
|
|
(`scope-fork` / `grounding`) `BLOCK` instead of escalating; or
|
|
re-dispatching only the blocked lens rather than all five, or past
|
|
the 2-round self-correction budget
|
|
- (auto-sign) Running the panel before the objective gates are green,
|
|
or running it at all when `spec_auto_sign` is not enabled
|
|
- 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)
|
|
|
|
## 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 (auto-sign only):** `agents/spec-skeptic.md` —
|
|
dispatched in Step 6 five times in parallel (one per lens) ONLY under
|
|
a `/boss` session with spec auto-sign enabled (the project's CLAUDE.md
|
|
project facts). Each
|
|
juror tries to refute the spec along its lens; a unanimous `SOUND` is
|
|
what lets the orchestrator sign in the user's place. An editorial-lens
|
|
`BLOCK` (`criterion` / `ambiguity` / `plan-readiness`) is self-
|
|
corrected in a bounded loop (≤ 2 rounds, full re-panel each round); a
|
|
design-lens `BLOCK` (`scope-fork` / `grounding`), an `INFRA_ERROR`, or
|
|
an exhausted budget falls back to the human sign-off pause.
|
|
- **Ad-hoc dispatch.** The orchestrator MAY also ad-hoc dispatch
|
|
`../planner/agents/plan-recon.md` during Step 1 when the work enters
|
|
code territory not recently read; discretionary, not part of the
|
|
standard process.
|
|
- **Project feature-acceptance criterion:** declared in the project's
|
|
`CLAUDE.md`. Applied prospectively in Step 2.
|