Files
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

445 lines
22 KiB
Markdown

# Pipeline
```
ENTRY PATHS — the selector cascade, walked top to bottom (see boss/SKILL.md)
bug observed ........... debug ........................ implement (mini) # RED-first; FIRST in the cascade
design fork ............ brainstorm -> specify -> plan -> implement
type/signature edit .... compiler-driven -> commit (clean build + suite green unchanged)
-> bounce: specify | tdd (a hole) | debug (suite red)
test-specifiable ....... tdd -> implement (mini) # RED executable-spec -> GREEN
settled prose design ... specify -> plan -> implement
(specify / tdd bounce to brainstorm on a design fork)
(per iteration loop)
|
[cycle close — a loop step, not a milestone close]
|
v
audit --(drift)--> plan + implement (tidy iteration)
--(ratify)-> --update-baseline + ratify paragraph in audit commit body
--(drift-clean)-+
|
[orchestrator: cycle complete? if surface-touch:]
v
fieldtest --(bug)------> debug -> implement (mini)
--(friction)-> brainstorm OR plan (tidy)
--(spec_gap)-> ratify OR tighten ledger
--(clean)----+
|
[orchestrator: surface stable across N cycles?]
v
docwriter
|
v
next cycle
```
## The methodology taxonomy
Development paths differ on two irreducible axes — the **first artefact
written**, and the **correctness oracle**. (Error-recovery is not a
third axis: whole-attempt discard is the plugin's universal containment,
not a per-path signature.) The top-level cut — ratified prose intent
before code (spec-driven) vs. machine / test / run oracles — is the hard
boundary; the paths cannot be centralised in one skill, only share the
implement executor as a primitive and the cycle-close `audit` tail.
| Path | First artefact | Oracle | Bounce-out when |
|------|----------------|--------|-----------------|
| **spec-driven** | ratified prose spec | human intent, judged at the document | (the deliberate heavy sink) |
| **tdd / debug** | a RED test | the assertion goes green | not test-specifiable → `brainstorm` |
| **compiler-driven** | a type / signature edit | clean build + suite green unchanged | a hole needs a decision → `specify` (or `tdd` if it is test-specifiable new behaviour); suite red → `debug` |
| **try-and-error** | throwaway code | an observed run | attempt budget exhausted |
`try-and-error` is **deferred** — listed for completeness, not yet a
live path. It is an exploration front-end terminating in a tdd-style
handoff, and its attempt tail is structurally unbounded (it can cost
more wall-clock than the spec-driven baseline it is meant to beat, and
its attempt-budget is a magic number the selector cannot derive). Out of
scope until it is given a bounded form.
## Cycle vs. milestone
These are two distinct axes, and conflating them is a bug.
- A **cycle** is one round in the pipeline graph above
(`brainstorm → specify → planner → implement → audit → [fieldtest]`).
A cycle close is an internal loop step.
- A **milestone** is a tracker container (Gitea milestone,
GitHub milestone, Linear project — whatever the project's
tracker calls a long-running work scope). A milestone spans
potentially many cycles and closes only when the work it
promised is **complete and functional** (see the gate below).
`audit` runs at cycle close and proves *drift-clean* — the code
matches the design ledger. It is blind to whether the work is
*functional* from a downstream consumer's point of view; that is
what `fieldtest` measures. So no `audit` result closes a
milestone, and neither does a `/boss` done-state.
## Milestone-close gate
A milestone may be closed in the tracker only when **both** legs
hold:
1. **Complete** — every cycle filed under the milestone is
`audit` drift-clean (or its drift explicitly ratified), and
the milestone container has no open iterations / issues left.
2. **Functional** — the **milestone fieldtest** has run its
curated end-to-end scenarios against the milestone's promise
and its status roll-up is `clean`: every scenario
demonstrably delivers what the milestone promised; no open
`bug` findings; `friction` / `spec_gap` findings resolved or
ratified into the design ledger. A `clean` roll-up is honoured
only with positive evidence the test actually ran — at least
2 examples in the working tree (`examples_added`). A milestone
fieldtest always runs **full tier** (the probe tier is
per-cycle only — `../fieldtest/SKILL.md` § Two tiers: probe
and full), so this floor is unconditional. A `clean`
with fewer, over a milestone that touched user-visible surface,
is itself a `spec_gap`, not a clean close (the agent owes the
same floor — `fieldtest/agents/fieldtester.md` "What you DO NOT
ship"; the gate verifies it rather than trusting the roll-up). The empty
report is valid only when no example was applicable.
The milestone fieldtest is the milestone-wide variant of the
`fieldtest` skill: the same fieldtester agent, a carrier scoped
to the milestone's promise rather than one cycle's surface. Its
scenarios are chosen top-down from what the milestone as a whole
promised, not assembled as the union of per-cycle axes.
A milestone whose entire scope is internal (no user-visible
surface) is exempt from the functional leg — the milestone
fieldtest is *not applicable* and the complete leg suffices.
This gate defines *when* a milestone is closeable. The actual
close stays a deliberate human / orchestrator act — the
tracker's own milestone-close action (on Gitea, `tea milestone
close`); no skill performs it automatically.
## Harvest sweep
A recognised batch shape for draining settled single-issue
backlog. When small, settled items accumulate on the tracker
(bundled fieldtest findings, absorbed leftovers, mechanical
one-offs), one full pipeline cycle per item is structurally
uneconomical; a harvest sweep drains them in one batch:
- the settled issue bodies stand in for spec and plan — each
item is already ratified and bite-sized, so `specify` and
`planner` are skipped by design (the exception is registered
in § Skip rules);
- the implementer works in sequential batches of 2-3 items —
direct `implementer` dispatches (the `implement-loop` carrier
needs a plan the sweep deliberately lacks), with no per-task
review pair; the whole-diff review below replaces it;
- the sweep closes with one **independent diff review over the
whole sweep** — an ad-hoc fresh-context reviewer over the
sweep's full diff, independent of the orchestrator and the
implementers (the per-task reviewer carriers do not fit a
whole-sweep diff) — then the mandatory `audit` close, and one
compact `fieldtest` under its normal skip rules (a
zero-surface sweep skips it).
The whole-diff review is **not removable**. Unlike a planned
cycle, where the task is the unit of review (`planner`'s
decomposition discipline), the sweep amortises review over the
batch — and in the consumer-project sweep this shape was
ratified from (recorded on issue #36), that one review caught
the only substantive error, which originated from orchestrator
+ fieldtest consensus, not from the implementers.
A sweep is orchestrator-decided at queue selection — a
judgement call like the `fieldtest` / `docwriter` dispatches,
not an arm of the selector cascade; the trigger is observed
accumulation of settled single-issue items.
## Cycle recon
Recon fan-out is budgeted **per cycle, not per phase**. The field
evidence behind the budget (issue #35, one bounded cycle): a broad
Explore-type sweep grounding `specify` (151k tokens) plus the
`plan-recon` dispatch grounding `planner` (99k tokens) overlapped
~40 % — two full recon passes over the same territory, the single
biggest obligatory per-cycle cost. This section is the single
source of the budget, reuse, and delta rules; the skills point
here and add only their own dispatch mechanics.
- **At most ONE full recon dispatch while a valid cycle recon
exists** — the **cycle recon**. It is a `plan-recon` dispatch
(`../planner/agents/plan-recon.md`) in the pre-spec carrier
form, normally fired at `specify` Step 1 when the work enters
code territory the orchestrator has not recently read; an
ad-hoc dispatch `brainstorm` fired earlier in the same cycle is
the cycle recon instead (subject to the coverage condition
below). One report serves every downstream consumer: the spec's
concrete code shapes and the plan's file-map. Normally that is
one full dispatch per cycle; a further full dispatch is
legitimate only via the fallback below.
- **Broad exploration sweeps are not recon.** No Explore-type
fan-out for spec, plan, or pre-dispatch grounding — grounding
fan-out goes through the one cycle-recon dispatch. This binds
the orchestrator in every mode, `/boss` included.
- **Reuse over re-dispatch.** A downstream phase reuses the
cycle-recon report while ALL of these hold:
- *Freshness* — no commit since the dispatch has touched the
paths the report maps (`git log <since-recon> -- <mapped
paths>` is empty; commits elsewhere — fixtures, tracker
side-effects — do not invalidate it). In a multi-iteration
cycle, iteration 1's commits to mapped paths invalidate the
report for iteration 2's planning.
- *Quotability* — the orchestrator can still quote the report's
Modify entries verbatim. A summarized memory of the report is
not the report. (The designed reuse window is the standard
same-session `specify``planner` handoff; across a session
break the fallback below applies.)
- *Coverage* (brainstorm-fired recons only) — the ratified
design's territory appears in the report's file-map or
existence-table rows, not merely as a one-line out-of-scope
acknowledgement. Missing territory is a delta below; a design
that pivoted wholly outside the mapped territory voids the
dispatch as cycle recon, and `specify` fires the cycle recon
afresh.
- **Delta dispatches do not count against the budget.** A delta
is a narrow re-dispatch whose `focus_hint` names the gap; its
bounded contract is **Delta dispatch** in
`../planner/agents/plan-recon.md`. Triggers:
- the spec names a path or symbol that appears in neither the
cycle recon's file-map nor its existence table;
- MANDATORY: the iteration scope is a signature / variant /
removal or content-pin-perturbing scope and the cycle recon
carries no compile-driven site set for it — `planner` MUST
delta-dispatch before planning that scope. (`specify` avoids
this delta by naming the anticipated change shape in
`recon_scope`, arming the compile-driven enumeration inside
the cycle recon itself.)
Two deltas in one planner run is the smell that the iteration
scope is too broad — re-read the spec.
- **A full re-dispatch is the bounded fallback, not a failure**:
no cycle recon exists (a direct tidy dispatch that skipped
`specify`; a session break), or a reuse condition failed. The
cost regression is capped at the pre-consolidation status quo —
one full dispatch.
## Phase descriptions
### brainstorm
Optional discovery front-end. Enumerates the cycle's load-bearing design
forks, then — instead of a serial interview — populates them with a parallel
swarm of grounded, genuinely-opposed `synthetic-user` stances and triages the
result: a fork the swarm settles on a *cited shared ground* was derivable and
is decided (the user vetoes); a fork it splits on, or agrees on with no citable
ground, is a direction fork the user settles. The orchestrator authors the 2-3
approaches from the populated space (never the swarm) and hands the ratified
design to `specify` (it writes no spec itself). A fire-check skips the swarm
when there are too few forks or the project is below a grounding floor
(greenfield, no ledger to cite against), falling back to a direct interview.
Skipped entirely when the design is already settled in the sources — that work
enters through `specify` directly. Under `/boss` the swarm runs autonomously:
convergent forks are decided and recorded on the reference issue, only a
divergent direction fork (or a sub-floor greenfield design) bounces to the
user.
### specify
Hard-gate before plan — the spec-production core and the carrier of the
"no plan without an approved spec" invariant. Takes a settled design
(directly from sources, or a ratified design handed over by
`brainstorm`), applies the feature-acceptance criterion, writes the
spec to `docs/specs` (an ephemeral active-cycle working file —
git-ignored, never committed, shell-`rm`'d at cycle close — see
`conventions.md` § Lifecycle), runs
the `grounding-check` gate, and takes sign-off — with review but no
interview. Under the bold stance it decides every load-bearing fork it
can *derive* an answer for and records the decision in the run's
reference issue; it bounces to `brainstorm` only when a fork hangs on a
pure user preference no source settles. Its code grounding comes from
the single cycle-recon dispatch (§ Cycle recon), never a broad
exploration sweep. A core node — the spec-production
gate before `planner` on every design path.
Outside `/boss` the sign-off is the user's. Under `/boss` the autonomous
signature is the **`grounding-check` `PASS`** itself: an independent
fresh-context agent's verdict against currently-green tests, not the
orchestrator's confidence. On `PASS` the orchestrator keeps the signed
spec as a git-ignored working file (never committed), records the
autonomous sign on the run's reference issue, fires the vetoable
auto-sign notify, and continues to `planner`; a no-override grounding
`BLOCK` / `INFRA_ERROR`
routes to the human sign-off pause. The former obligatory five-lens
`spec-skeptic` panel is **retired** (baseline tag `pre-autosign-rework`):
the judgement it applied now lives upstream in Step 1.5's bold-decide
stance, and `spec-skeptic` survives only as the optional ad-hoc
bias-breaker the orchestrator pulls when unsure whether its leaning on a
fork is judgement or bias. Editorial roughness the panel would have
caught is let through deliberately — cheap to patch inline downstream.
See `../specify/SKILL.md` Step 6 and `../boss/SKILL.md` §"Spec auto-sign".
### planner
Hard-gate before implement. Produces a placeholder-free,
bite-sized implementation plan in `docs/plans` (an ephemeral,
git-ignored working file, shell-`rm`'d alongside the spec at cycle
close — see `conventions.md` § Lifecycle) that the implement skill can
execute task-by-task. Its file-map normally comes from reusing the
cycle-recon report (§ Cycle recon); it dispatches `plan-recon` only
for that section's delta triggers, or in full when no valid cycle
recon exists.
### implement
Runs the `implement-loop` Workflow (`implement/workflows/implement-loop.js`),
a deterministic script that executes the per-task loop —
implementer → spec-compliance → quality, each a separate
`agent()` call — and aggregates the verdicts in code. A Workflow
orchestrates from the top level, so the per-task phases are real,
independently-invokable agent calls; this retired the former
`implement-orchestrator` agent's inline-role-switch workaround
(the four phase agents survive as the agent-types the script
dispatches). Writes code and tests directly in the working tree as
unstaged changes; never commits. The end-report carries the finished
stats.json and — on `PARTIAL`/`BLOCKED``BLOCKED.md` contents, which
the orchestrator writes (issue #29 retired the finalize dispatch that
only templated the script's own aggregate).
### compiler-driven
The lighter executor for a **behaviour-preserving type/signature
edit at a definition site** — the cascade arm between `debug` and
`tdd`. Runs the `compiler-driven-edit` Workflow
(`implement/workflows/compiler-driven-edit.js`): make the edit,
propagate it mechanically across the sites the build enumerates,
then let a real build + suite run settle the verdict —
**observe-then-bounce**. Clean build AND suite green *unchanged*
the edit is committed by the orchestrator; a hole that forces a
design decision → bounce to `specify` (or `tdd` if it turns out to be
test-specifiable new behaviour, per the straddle rule); the suite not
green-unchanged (a regression — the edit was not behaviour-preserving)
→ bounce to `debug`, RED-first. A truly trivial edit may run inline
without the
workflow, under the same done-signal. Never skips the
review-and-commit discipline; the orchestrator inspects and commits.
### audit
Runs at cycle close. Dispatches the architect agent (read-only
drift review against the design ledger) and the bencher agent
(regression diagnostics). Reports drift and regress. Once it is
drift-clean, the orchestrator discards every working-tree spec and plan
with a plain shell `rm` (nothing to `git rm` — they were never
committed); the cycle-close commit contains only code and ledger changes
(see `conventions.md` § Lifecycle).
### debug
Runs whenever a bug is observed. RED-first: produces a failing
test in the working tree before any fix is attempted. Hands off
the GREEN side to the implement skill in mini mode.
### tdd
A standard alternative entry, alongside `brainstorm → specify → planner`,
for work whose desired behaviour is test-specifiable — expressible
as one failing test. RED-first: the `tdd-author` agent turns a
description or issue into a single minimal, autonomous RED
executable-spec ("how it should work"), then hands the GREEN side
to `implement` in mini mode, exactly as a bug fix. When the
behaviour is not test-specifiable (a genuine design fork surfaces),
or two decomposition rounds fail, it bounces back to `brainstorm`.
When one iteration cannot reach GREEN, the headline test is carved
into a ladder of BLOCKER sub-tests, each its own RED→GREEN
mini-cycle. Distinct from the per-task TDD the implementer already
practices inside `implement`.
### fieldtest
Optional. Orchestrator-dispatched after the audit closes clean
on a cycle that touched user-visible surface. Picks 2-4 real-
world tasks within the cycle's scope (probe tier, for a
single-axis surface delta: 1-2 tasks on that axis — see
`../fieldtest/SKILL.md` § Two tiers: probe and full), implements them using
only the design ledger and public examples (never the language's
own implementation), runs the results, and writes a friction-
and-bug spec.
### docwriter
Optional. Orchestrator-dispatched after API surface has
stabilised across multiple cycles. Brings docstrings up to a
level where a newcomer can navigate the public API without
reading the design ledger first.
## Status protocol
Agents return one of these terminal states:
| State | Meaning |
|-------|---------|
| `DONE` | Task complete; no concerns. |
| `DONE_WITH_CONCERNS` | Task complete; flagged issues the orchestrator should weigh before committing. |
| `PARTIAL` | Task partially complete; the rest is blocked or out-of-scope. Writes `BLOCKED.md`. |
| `BLOCKED` | Task cannot proceed; explanation in report. Writes `BLOCKED.md`. |
| `NEEDS_CONTEXT` | Task cannot proceed without additional information from the orchestrator. |
Reviewer agents have role-specific states:
| Role | States |
|------|--------|
| spec-reviewer | `compliant` / `non_compliant` / `unclear` / `infra_blocked` |
| quality-reviewer | `approved` / `changes_requested` / `infra_blocked` |
## Skip rules
Skipping is codified per skill, not ad hoc. Each `SKILL.md`
documents what the skill skips and under what conditions:
- `specify` is never skipped at cycle start — it is the spec-production
gate before `planner`. `brainstorm` is the *optional* discovery stage
before it: skipped when the design is already settled in the sources
(the work enters through `specify` directly), run when a load-bearing
decision is still open. The one batch exception is the harvest sweep
(§ Harvest sweep): its settled issue bodies are the ratified spec
source, so no new spec is written.
- `planner` is never skipped at iteration start, except for the
side paths that carry no prose plan: the bug-driven
`debug → implement (mini)` path, the `compiler-driven` path
(whose "plan" is the type-checker's enumeration of edit sites),
and the harvest sweep (whose items are already bite-sized —
§ Harvest sweep).
- `implement` is the iteration body; not skippable.
- `audit` is mandatory at cycle close.
- `debug` is mandatory RED-first for any observable bug — first in
the selector cascade, so a mechanical-looking fix cannot bypass it.
- `tdd` is a standard alternative entry to `brainstorm` for
test-specifiable work; it bounces back to `brainstorm` on a
design fork. Always available — not opt-in.
- `compiler-driven` is the cascade arm for a behaviour-preserving
type/signature edit: it skips `specify` and `planner`, and its
done-signal (clean build + suite green unchanged) is the gate. It
bounces on a hole to `specify` (a design choice) or `tdd` (discovered
test-specifiable new behaviour), and to `debug` on a regression.
Always available — not opt-in.
- `fieldtest` and `docwriter` are optional and orchestrator-
dispatched.
If a skill's body says it must run and the orchestrator wants
to skip it, the orchestrator records the reason in the relevant
commit body — never as undocumented practice.
## Pipeline configuration
There is none. The phase set, the gates, and the conditional
dispatch shown above are fixed — the same for every project. All
phases (`brainstorm`, `specify`, `planner`, `implement`, `audit`,
`debug`, `tdd`, `fieldtest`, `docwriter`) are always available; which
ones run on a given iteration is the orchestrator's judgement per the
skip rules above, not a per-project setting. There is no behavioural
toggle either: spec auto-sign is always on under `/boss`. See
`conventions.md`.
If a project declares a glossary in its CLAUDE.md project facts, that
file is standing reading for every role — the canonical-nomenclature
source every skill and agent consults (see `glossary-convention.md`).