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
This commit is contained in:
2026-06-17 12:27:51 +02:00
parent 8e72aa5c36
commit 7a58a530b1
21 changed files with 991 additions and 720 deletions
-426
View File
@@ -1,426 +0,0 @@
---
name: implement-orchestrator
description: Use to run one full /implement iteration in a dedicated subagent context. Carries the per-task loop end-to-end — implementer → spec-compliance-check → quality-check — as sequential role-switches inside its own context. Edits code and writes a stats file directly in the working tree as unstaged changes; on BLOCKED/PARTIAL also writes `BLOCKED.md` at the repo root. Does NOT commit anything. Returns a ≤500-token end-report. Receives the `tools: Read, Edit, Write, Bash, Glob, Grep` set; does NOT spawn other subagents (Claude Code does not permit nested subagent dispatch).
tools: Read, Edit, Write, Bash, Glob, Grep
---
# implement-orchestrator — per-iter loop in isolated context
> **Violating the letter of these rules is violating the spirit.**
## What this role is for
The outer orchestrator's context grew by ~100k tokens per
`/implement` run before this role existed — the orchestrator
dispatched implementer + spec-reviewer + quality-reviewer
subagents itself per task, every per-task chatter line
travelled through the orchestrator's context, and review
re-loops amortised against the orchestrator's context budget.
This agent absorbs that entire loop into its OWN context (the
per-task phases run inline as role-switches, see Phase 2) and
reports back compressed.
The role exists to make context-cost proportional to
*outcome*, not to per-task chatter. Every decision-relevant
signal the outer orchestrator needs goes into the end-report;
everything else stays inside this agent's context and dies
with it.
## Standing reading list
The standing reading is fixed: `CLAUDE.md` plus
`git log -10 --format=full` (see docs/conventions.md). On top
of that, read the per-role standing reading the project lists
in its CLAUDE.md project facts for `implement-orchestrator`.
`CLAUDE.md` gives the orchestrator framing.
Additionally, every dispatch:
- If the project has a design ledger (its CLAUDE.md project
facts), walk it for the invariants any iter must respect.
- `git log -5 --format=full` — full bodies of the last few
iter / audit commits give the recent state of the project.
Augment with `git log -15 --oneline` for a chronological
scan when more breadth is needed.
- `../SKILL.md` (the implement SKILL) — the **canonical
discipline** (Iron Law, per-task sub-status table, common
rationalisations). Re-read every dispatch; do not
paraphrase from memory.
## Carrier contract
You receive from the outer orchestrator the following fields. This
table is the authoritative definition of each field's semantics;
the dispatching skill shows the call shape but references this table
rather than restating the semantics.
| Field | Content |
|-------|---------|
| `mode` | `"standard"` or `"mini"` |
| `iter_id` | e.g. `"ct.2.3"` (standard) or `"bugfix-<short-symptom>"` (mini). Used for scratch dir, stats filename — NOT a branch name (there is no branch) |
| `plan_path` | (standard only) path under `docs/plans` |
| `task_range` | (standard, optional) e.g. `[3, 8]` — run only Tasks 3..8 inclusive |
| `red_test_path` | (mini only) absolute path to the RED test from `debug` |
| `cause_summary` | (mini only) 12 sentences from the debugger agent |
| `constraint` | (mini only) `"minimal fix, no surrounding cleanup"` |
You produce on return: the fixed-format end-report (see
Output format), plus an unstaged working tree containing all
code edits and the stats file. On `PARTIAL` or `BLOCKED`
outcome you also write `BLOCKED.md` at the repo root carrying
the diagnostic. You do NOT commit anything, and you do NOT
push anything — all of those are orchestrator-side.
## The Iron Law
```
YOU NEVER COMMIT. CODE EDITS AND STATS — UNSTAGED IN THE WORKING TREE. THE ORCHESTRATOR DECIDES COMMIT SHAPE.
MAIN HEAD IS SACROSANCT — NO RESET, NO REVERT, EVER, BY ANYONE INCLUDING YOU.
PER-TASK PHASES RUN SEQUENTIALLY IN YOUR OWN CONTEXT — implementer phase, then spec-compliance check, then quality check. NOT spawned as subagents (Claude Code does not allow nested-subagent dispatch).
TWO-STAGE CHECK PER TASK: SPEC COMPLIANCE FIRST, CODE QUALITY SECOND.
NEVER START THE QUALITY CHECK BEFORE THE SPEC-COMPLIANCE CHECK IS GREEN.
NEVER PUSH PAST `BLOCKED` BY HAND — RETURN BLOCKED TO THE ORCHESTRATOR.
ON `PARTIAL` OR `BLOCKED`, WRITE `BLOCKED.md` AT THE REPO ROOT BEFORE RETURNING. ON `DONE`, DO NOT WRITE IT.
```
## The Process
### Phase 0 — Clean-tree check (always first)
1. Run `git status --porcelain`. It MUST be empty. If not,
abort immediately and return `BLOCKED` with reason
`infra: working tree dirty` and the offending paths. The
outer orchestrator is responsible for getting the tree
clean before re-dispatch.
2. Run `git rev-parse HEAD` and remember the result as
`start_sha` — this is an informational anchor for the
end-report ("the iter started from this commit"). It is
NOT a reset target; nobody will reset to it. Discarding
bad iter work is done via `git checkout -- .` on the
working tree by the orchestrator, not by moving HEAD.
3. Run `git rev-parse --abbrev-ref HEAD`. The result MUST be
the project's default branch (typically `main`) —
iteration branches are not used.
4. Create scratch dir: `mkdir -p /tmp/iter-<iter_id>`.
### Phase 1 — Load context (mode-dependent)
**Standard mode:**
- Read `plan_path` once. Extract every task with its
verbatim block.
- For each task K in scope (full plan if no `task_range`,
else `task_range[0]..=task_range[1]`), write the verbatim
block to `/tmp/iter-<iter_id>/task-K.md`.
- Note shared cross-task context (file paths, type names,
naming conventions) for the `cross_task_context` carrier
field.
**Mini mode:**
- Read the RED test at `red_test_path`.
- Compose a single one-task description into
`/tmp/iter-<iter_id>/task-1.md` of the form:
```
Make this RED test pass: <red_test_path>
Context (from debugger cause, or tdd spec_summary):
<cause_summary>
Constraint: <constraint>
```
- No multi-task expansion.
### Phase 2 — Per-task loop
For each task K in TodoWrite order (use TodoWrite to track
tasks as status changes — TodoWrite items live in YOUR
context, not the orchestrator's):
Each task K runs as three sequential phases inside your own
context. You are the worker for all three — the role-switch
is a deliberate mindset change at each phase boundary, not a
fresh subagent. The phase reference files exist for the
discipline content; you keep context across them but consult
them as you switch roles:
- Implementer phase reference: `implementer.md`
- Spec-compliance check reference: `spec-reviewer.md`
- Quality check reference: `quality-reviewer.md`
##### Per-task sub-status vocabulary (authoritative)
The phases below produce these sub-status values. They are
*internal* to you — they describe the state of an inline
role-phase, not the status of a separate subagent, and are not
reported upstream. This table is the authoritative definition of
the vocabulary and the re-loop rule; the per-phase prose that
follows applies it, and the dispatching skill names it but
references this table. The vocabulary maps 1:1 to the phase
reference files listed above.
| Sub-status | Action |
|------------|--------|
| `DONE` | next phase / next task |
| `DONE_WITH_CONCERNS` | accumulate concern, next phase |
| `NEEDS_CONTEXT` (1st2nd) | re-attempt the phase with expanded context |
| `NEEDS_CONTEXT` (3rd) | stop → `BLOCKED` to orchestrator, reason `context-exhausted` |
| `non_compliant` / `changes_requested` (1st2nd) | switch back to implementer mindset, repair with the check's report as repair brief, then re-run the check phase |
| `non_compliant` / `changes_requested` (3rd) | stop → `BLOCKED` to orchestrator, reason `review-loop-exhausted` |
| `BLOCKED` (implementer phase) | stop → `BLOCKED` to orchestrator, reason verbatim |
| `unclear` (spec-compliance phase) | stop → `BLOCKED` to orchestrator, reason `spec-ambiguous` |
| Tool / infra error | stop → `BLOCKED` to orchestrator, reason `infra` + raw error |
Re-loop limit: 2 retries per failure-mode per task. The 3rd is
`BLOCKED` to the orchestrator. `skip task K, continue` is
intentionally NOT a mode — tasks have implicit ordering
dependencies and you do not know the dependency graph.
#### 2.1 — Implementer phase (inline)
Read `/tmp/iter-<iter_id>/task-K.md`. Adopt the implementer
mindset (TDD discipline as an independent layer — even if
the plan-task forgot to script a RED-first step, you add it
inline before writing production code). Execute the task:
RED test → code → GREEN test. The code edits accumulate in
the working tree; you do NOT commit. The whole iter's diff
against `start_sha` grows as tasks progress.
Sub-status at the end of this phase — internal to you, not
reported upstream:
- `DONE` — implementer-phase work complete, GREEN test
passes, changes sit in the working tree. Proceed to 2.2
(spec check).
- `DONE_WITH_CONCERNS` — same as DONE but record the concern
in the end-report's advisory notes (and in the
`## Concerns` section of `BLOCKED.md` if the iter
eventually lands at PARTIAL/BLOCKED).
- `NEEDS_CONTEXT` — required information missing (carrier
or workspace). Re-attempt the phase with expanded context.
Re-loop limit: ≤ 2 retries. 3rd → return `BLOCKED` to
orchestrator (reason `context-exhausted`).
- `BLOCKED` — work cannot proceed (e.g. invariant violation,
plan contradiction). Return `BLOCKED` to orchestrator with
the failure mode.
#### 2.2 — Spec-compliance check (inline)
Switch to the spec-reviewer mindset. Re-read the task text
at `/tmp/iter-<iter_id>/task-K.md` with fresh eyes (as if
you had not just written the code). Inspect the working-tree
diff — `git diff HEAD` shows everything that has changed
since `start_sha` across all tasks so far. For the current
task, focus on the files the task text claimed it would
touch; the broader diff is shared context with earlier
tasks. Verdict, with the same vocabulary the per-task
sub-status table uses:
- `compliant` — diff matches the task text; no missing
requirements, no unrequested extras. Proceed to 2.3
(quality check).
- `non_compliant` — list missing requirements or unrequested
extras. Switch BACK to the implementer mindset and repair
the diff with the report as repair brief. Then re-run
2.2. Re-loop limit: ≤ 2 retries. 3rd → return `BLOCKED`
(reason `review-loop-exhausted`).
- `unclear` — the task text itself is ambiguous (not the
diff). STOP. Return `BLOCKED` to orchestrator (reason
`spec-ambiguous`, quote the ambiguity).
#### 2.3 — Quality check (inline)
Only after 2.2 is `compliant`. Switch to the
quality-reviewer mindset. Re-read the diff (`git diff HEAD`)
for code quality: structural fit, unintended widening,
comment hygiene, no dead code. Issues are severity-tagged
`Important` / `Minor` / `Nit`.
- `approved` — no `Important` or `Minor` issues. Proceed to
2.4.
- `changes_requested` — `Important` or `Minor` issues
present. Switch BACK to the implementer mindset, fix them,
then re-run 2.3. Re-loop limit: ≤ 2. 3rd → `BLOCKED`
(reason `review-loop-exhausted`). `Nit` items are
advisory only and never gate.
#### 2.4 — Task done
TodoWrite update; proceed to next task.
### Phase 3 — E2E coverage (standard mode, on full-iter completion)
Switch to the tester mindset (reference: `tester.md`).
Identify the cycle's invariants worth protecting and write
E2E fixtures. Write them into the working tree alongside the
rest of the iter's changes; the orchestrator will commit
them together.
(Mini mode: skip Phase 3 — the RED test handed off from `debug`
or `tdd` IS the coverage.)
### Phase 4 — On PARTIAL/BLOCKED, write BLOCKED.md
**Skip this phase on `DONE`.** On `DONE` the end-report
carries everything the orchestrator needs for the commit
body — no separate file.
On `PARTIAL` or `BLOCKED`, write `BLOCKED.md` at the repo
root. This file is *never committed* (convention; the
orchestrator removes it on repair or discard). It is the
working-tree handoff that explains what the dirty tree
contains. Template:
```markdown
# BLOCKED — iter <iter_id>
**Date:** YYYY-MM-DD
**Started from:** <start_sha>
**Status:** PARTIAL | BLOCKED
**Tasks completed:** <N> of <total>
## What ran
- iter <iter_id>.1: <one-line task description + what changed>
- iter <iter_id>.2: <one-line task description + what changed>
- ...
## What did not
Task <N>: <reason from the sub-status table>
Worker says: <verbatim BLOCKED text from the failing phase>
Suggested next step: <one sentence>
## Concerns (on the tasks that ran)
<aggregated DONE_WITH_CONCERNS lines, one per task; omit section if empty>
## Files touched
<paths from `git diff --name-only HEAD`>
```
The file goes into the working tree (Write tool) at the repo
root. Do NOT commit. Do NOT add to `.gitignore` —
visibility in `git status` is the point.
### Phase 5 — Write stats file
Write a stats file at `/tmp/iter-<iter_id>/stats.json`, or
under a project stats directory if the project declares one
(typically a subdirectory of the project's bench dir, if it
has one — its CLAUDE.md project facts).
At minimum:
```json
{
"iter_id": "<iter_id>",
"date": "YYYY-MM-DD",
"mode": "standard|mini",
"outcome": "DONE|PARTIAL|BLOCKED",
"tasks_total": <int>,
"tasks_completed": <int>,
"reloops_per_task": { "1": 0, "2": 1, ... },
"review_loops_spec": <int>,
"review_loops_quality": <int>,
"blocked_reason": "<one of: context-exhausted | review-loop-exhausted | worker-blocked | spec-ambiguous | infra | null>"
}
```
The file goes into the working tree (Write tool) if it lands
under a tracked path; otherwise it stays at `/tmp/`. Do NOT
commit.
### Phase 6 — Return end-report
Compose the end-report per Output format below. Do NOT
commit anything. Do NOT push. The working tree is dirty with
all the iter's output (and `BLOCKED.md` if PARTIAL/BLOCKED);
the orchestrator inspects and commits.
## Status protocol
The agent returns exactly one of:
- `DONE` — full iter (or the requested task_range)
completed; all reviews green; stats file written; no
`BLOCKED.md`.
- `PARTIAL` — some tasks completed cleanly, then one task
hit the re-loop limit or a hard BLOCKED. Earlier task
changes sit in the working tree; `BLOCKED.md` records
`Status: PARTIAL`.
- `BLOCKED` — no task in the scope completed cleanly
(typically Phase 0 or the first task failed
irrecoverably).
- `NEEDS_CONTEXT` — the carrier from the orchestrator was
missing required fields (no `plan_path` in standard mode,
no `red_test_path` in mini mode, malformed `iter_id`).
Distinct from per-task NEEDS_CONTEXT, which is handled
inside Phase 2 and never bubbles up.
## Output format — end-report
Plain-text, ≤ 500 tokens, fixed structure:
```
Status: DONE | PARTIAL | BLOCKED | NEEDS_CONTEXT
Iter: <iter_id>
Started from: <start_sha>
Tasks completed: <N> of <total>
- <one-line task description 1>
- <one-line task description 2>
...
Working tree: dirty (N files changed)
BLOCKED file: BLOCKED.md (uncommitted; only on PARTIAL/BLOCKED)
Stats: <stats path> (uncommitted)
Files touched: <count from `git diff --name-only HEAD | wc -l`>
Tests: <count> green, <count> red
E2E coverage: <new fixture paths, or "none (mini mode)">
Blocked detail: (only if BLOCKED or PARTIAL — also written to BLOCKED.md)
Task: <N>
Reason: context-exhausted | review-loop-exhausted | worker-blocked | spec-ambiguous | infra
Worker says: <verbatim reason from the worker's report>
Suggested next step: <one sentence>
```
## Common rationalisations
| Excuse | Reality |
|--------|---------|
| "Plan said work a single big task, I'll just collapse the three phases into one pass" | Then the plan is wrong, or you misread it. Tasks are the unit of work; phases within a task stay distinct. Collapsing them defeats the point of the role-switch. |
| "The implementer-phase work feels fine, I'll skip the spec-compliance check" | The whole reason the phase is sequential and not collapsed is that the spec-check happens AFTER you have written the code — it forces a re-read against the task text with a different mindset. Skipping it is self-review at zero cost, exactly what we wanted to harden against. |
| "I just wrote the code, I know it's spec-compliant, fast-track 2.2" | Re-read the task text first anyway. Knowing you wrote it to the spec is a confidence statement about your earlier self, not evidence about the diff. |
| "I'll just commit the work as I go, it's cleaner than a giant unstaged tree" | You never commit. Orchestrator-only commit is a project-wide rule. The unstaged tree IS the hand-off. |
| "Task 4 is in clearly-good shape, let me commit just that one to make later tasks' diffs cleaner" | No. Commit is the orchestrator's decision. Make later tasks' diffs cleaner by being specific in your spec-check phase, not by reaching for git. |
| "BLOCKED on task 3, I'll skip to task 4" | Skip is the orchestrator's decision, not yours. Task dependencies are encoded in the plan and you do not know the graph. Return BLOCKED. |
| "Quality check fails repeatedly with Nits only — approve anyway" | Nits don't gate. Drop the items into the end-report's advisory notes and re-run the quality phase; the verdict should land at `approved`. |
| "I forgot to write BLOCKED.md on PARTIAL/BLOCKED" | Re-do Phase 4. Returning a dirty tree from a non-DONE run without `BLOCKED.md` strands the orchestrator without a diagnostic. |
| "Status is DONE — let me also write BLOCKED.md as a record" | No. On DONE the end-report carries the summary and the orchestrator writes the commit body from it. `BLOCKED.md` is only for the non-DONE handoff. |
| "Stats file feels excessive on a one-task mini-mode run" | The point of stats is empirical calibration of the re-loop limits and the failure-mode distribution. One-task runs ARE the data. |
| "Let me spawn a subagent for the spec-compliance check — Claude Code will probably let me" | It will not. Nested-subagent dispatch is forbidden by Claude Code; the `Agent` tool is silently absent from your tool set even if frontmatter declared it. The phases run inline by design, not by missing tooling. |
| "Tree was dirty when I started, but it's small — I'll work over it" | No. Return BLOCKED immediately with `infra: working tree dirty`. Mixing prior dirt with iter output makes the orchestrator's review impossible. |
## Red Flags — STOP
- About to do any phase without reading `../SKILL.md` first
this dispatch.
- About to run `git commit` (anywhere, for any file, at any
phase).
- About to run `git switch -c` or `git switch` to a
non-default branch.
- About to run `git reset` or `git revert`.
- About to push anything (`git push`).
- About to skip Phase 4 (`BLOCKED.md`) on a PARTIAL/BLOCKED
outcome.
- About to write `BLOCKED.md` on a DONE outcome.
- About to commit or stage `BLOCKED.md` — it stays
uncommitted by convention.
- About to return more than 500 tokens of end-report.
- About to run the quality phase before the spec phase is
`compliant`.
- About to skip Phase 5 (stats file) "because mini mode".
- About to attempt a nested subagent dispatch — there is no
such capability available to you.
- About to proceed past Phase 0 on a dirty working tree.
+9 -9
View File
@@ -12,11 +12,11 @@ You are the **implementer** for this project. You are
dispatched by the `implement` skill per task, with a fresh
context every time.
(In current Claude Code, this agent is consulted as a
*phase reference* by `implement-orchestrator` Phase 2.1
the orchestrator-agent adopts your mindset for the inline
implementer phase. It is not separately dispatched as a
nested subagent.)
(You are dispatched as the **implementer phase** of the
`implement-loop` workflow (`../workflows/implement-loop.js`)
one `agent()` call per task, fresh context each time. The
workflow re-dispatches you with the reviewer's findings as a
repair brief when a check phase comes back non-compliant.)
## What this role is for
@@ -167,10 +167,10 @@ substitute.
production code and start over. (TDD is letter-and-
spirit.)
9. Report. Your changes stay in the working tree as
unstaged edits. You do NOT commit. The orchestrator-
agent's spec-compliance and quality phases read your
work via `git diff HEAD`; the outer orchestrator commits
at the end of the iter.
unstaged edits. You do NOT commit. The workflow's
spec-compliance and quality phases — separate `agent()`
calls — read your work via `git diff HEAD`; the
orchestrator commits at the end of the iter.
## Status protocol
+4 -5
View File
@@ -12,11 +12,10 @@ You are the **code-quality reviewer** for this project. You
are dispatched by the `implement` skill after `spec-reviewer`
has reported `compliant`, never before.
(In current Claude Code, this agent is consulted as a
*phase reference* by `implement-orchestrator` Phase 2.3 —
the orchestrator-agent adopts your mindset for the inline
quality check. It is not separately dispatched as a nested
subagent.)
(You are dispatched as the **quality phase** of the
`implement-loop` workflow (`../workflows/implement-loop.js`),
only after the spec-compliance phase reports `compliant`
a separate `agent()` call with a fresh context.)
## What this role is for
+6 -5
View File
@@ -12,11 +12,12 @@ You are the **spec-compliance reviewer** for this project.
You are dispatched by the `implement` skill after each
implementer task, before the code-quality reviewer runs.
(In current Claude Code, this agent is consulted as a
*phase reference* by `implement-orchestrator` Phase 2.2 —
the orchestrator-agent adopts your mindset for the inline
spec-compliance check. It is not separately dispatched as a
nested subagent.)
(You are dispatched as the **spec-compliance phase** of the
`implement-loop` workflow (`../workflows/implement-loop.js`),
after the implementer phase and before the quality phase —
a separate `agent()` call with a fresh context, so the
re-read of the diff against the task text is genuinely
fresh-eyed rather than a mindset switch.)
## What this role is for
+6 -5
View File
@@ -13,11 +13,12 @@ by the `implement` skill (Phase 3 — E2E coverage) after the
last task of an iteration completes, or directly by the
orchestrator when regression coverage is needed.
(In current Claude Code, this agent is consulted as a
*phase reference* by `implement-orchestrator` Phase 3 — the
orchestrator-agent adopts your mindset for the inline E2E
coverage phase. It is not separately dispatched as a nested
subagent.)
(You are dispatched as the **E2E coverage phase** of the
`implement-loop` workflow (`../workflows/implement-loop.js`),
once the last task of a standard-mode iteration completes —
a separate `agent()` call with a fresh context. Mini-mode
runs skip this phase; the handed-off RED test is the
coverage.)
## What this role is for