Commit Graph

5 Commits

Author SHA1 Message Date
Brummel 6bfec9655c feat(agents): pin explicit model on every agent and workflow call
Agents and workflows previously carried no model field, so every
dispatch inherited the session model — including fable, which is
banned for all plugin agents and workflows by owner decree. Every
dispatch now pins opus or sonnet explicitly.

- opus (low-volume judgment gates whose misses silently poison
  downstream work): architect, bencher, debugger, fieldtester,
  grounding-check, plan-recon, quality-reviewer, spec-skeptic,
  tdd-author
- sonnet (mechanical scope, in-loop or fanned out): docwriter,
  glossary-extractor, implementer, spec-reviewer, synthetic-user,
  tester
- workflows: all 13 agent() call sites pin a model — sonnet
  everywhere except the quality-reviewer gate in implement-loop,
  the loop's last correctness check (spec-reviewer only gates
  task-text correspondence; real-bug finding is the documented
  opus strength)
- docs/agent-template.md: model is now a mandatory frontmatter
  field, with the assignment rule and the fable ban recorded
2026-07-02 12:14:36 +02:00
Brummel d6c4faa3c0 fix(implement-loop): require positive edit evidence before DONE
The #11 vacuous-green shape on the main path: `outcome = DONE` was set
purely from the absence of a BLOCKED task, with no check that the
iteration actually wrote anything. `files_touched` was even computed by
the finalize agent but never asserted > 0, `e2e.status` was never read,
and in mini mode the handed-off RED test was never independently re-run
(GREEN was asserted from the implementer's self-report, never observed).

Add a positive-evidence precondition on DONE, taken from git ground
truth — never a self-report, which must not be able to fail a run that
actually did the work:

- Standard mode: a dedicated `tree-check` agent runs `git status
  --porcelain | wc -l` after the per-task loop but BEFORE E2E/finalize.
  Zero (or a non-returning agent) downgrades DONE to BLOCKED. `git
  status --porcelain` (not `git diff HEAD`) so a brand-new untracked
  file — the implementer leaves edits unstaged — still counts; running
  pre-E2E/finalize keeps fixtures and the stats/BLOCKED.md artefacts
  from inflating it.
- Mini mode: an independent `mini-verify` agent re-runs the RED test by
  name and the suite and checks the tree is dirty; a still-red test, a
  regression, or a clean tree is BLOCKED (route back to debug).
- Per-task `applied_changes` (OR-ed across the initial dispatch and
  every repair) feeds only a neutral concern, never the outcome.
- `e2e.status` is now read: a non-DONE status or a zero-fixture run
  surfaces as a concern.

A clean-tree no-op is BLOCKED with no BLOCKED.md (nothing to clean up);
the status + reason ride the end-report. SKILL.md documents the
precondition, the no-BLOCKED.md carve-out, and the Step-4 handling.

closes #12
2026-06-27 14:26:58 +02:00
Brummel 89cc4bb9a8 fix(compiler-driven-edit): require positive edit evidence before DONE
The done-signal `build_clean && suite_green_unchanged` was vacuously
true on a clean working tree, so a no-op edit (the edit agent touched
nothing and reported sites: 0) read as DONE. An orchestrator trusting
that verdict would "commit the unstaged changes" — committing nothing
under a DONE banner.

Add positive evidence that an edit actually landed, checked at two
independent points:

- Phase 1 (cheap, pre-suite): the edit agent reports `applied_changes`
  as ground truth from `git status --porcelain` / `git diff HEAD`. No
  hole + clean tree -> distinct BLOCKED (kind: no-op-edit), skipping a
  pointless suite run against an empty tree.
- Phase 3 (authoritative backstop): DONE now also requires the verify
  agent's independent `working_tree_dirty` observation. The verify
  agent never sees the edit agent's self-report, so a false
  applied_changes is still caught. A green build+suite over a clean
  tree routes to the same BLOCKED, not to debug (a clean tree is no
  regression — nothing to reproduce RED-first).

The precondition keys on tree-dirty, not sites > 0: a legitimate
behaviour-preserving edit can touch only the definition site (sites: 0)
and still dirty the tree. Also fix the DONE note to report a legitimate
sites: 0 as 0 rather than coercing it to null.

closes #11
2026-06-27 13:12:24 +02:00
Brummel 52db1abe10 fix(implement-loop): hold plan-contradicting quality findings instead of oscillating to a false BLOCKED
The per-task quality re-loop treated every `changes_requested` as
"deviate to satisfy", and the quality-repair dispatch was not even
given the task text. When a finding's only remedy contradicted a
plan-prescribed name/signature, the implementer renamed off-plan, the
next review flagged "diverges from plan", and the loop oscillated
name-misleads <-> diverges-from-plan until the retry cap, emitting a
false BLOCKED on code that was green the whole time.

Fix (issue's option 2 — the plan knowledge lives with the implementer,
which holds the task text; the quality-reviewer is deliberately blind
to it, so option 1 would have breached that separation):

- The quality-repair dispatch now receives the task text and a HOLD
  CLAUSE. A cosmetic finding (plan kept => build+tests green) is KEPT
  and recorded in a new `held` field; the loop surfaces it as a concern
  instead of chasing a deviation. A finding the implementer judges
  correctness-breaking escalates to BLOCKED, never a silent hold.
- The hold is keyed on two structural signals, never on a self-reported
  status enum (which the implementer contract overloads): the `held`
  array, and a no-op backstop over a required `diff_fingerprint` (a
  changes_requested verdict over an already-seen diff-state means the
  repair was a no-op or cycled back — re-running quality is futile).
  Fingerprints are tracked in a Set so A-B-A edit-then-revert is caught.
- A no-op-backstop concern is labelled neutrally (a byte-identical diff
  cannot tell a principled plan-hold from an ignored bug); implement
  SKILL.md Step 3 now routes a held/unresolved quality finding to
  orchestrator hand-verification before committing, even under /boss.

The held/no-op partition is the implementer's judgement, not enforced
in code — the residual fail-open is bounded to cosmetic-on-green
findings and disclosed, with the orchestrator's Step-3 inspection as
the backstop, the same trust placed in its other self-reports. Verified
across three rounds of adversarial review (held-the-plan paths, fail-
open laundering, schema/Set mechanics) — all closed.

closes #10
2026-06-22 20:11:06 +02:00
Brummel 7a58a530b1 feat(pipeline): route to the lightest correct methodology; move execution loops onto the Workflow substrate
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
2026-06-17 12:27:51 +02:00