--- name: implement description: Use when an implementation plan exists under docs/plans and is ready to execute, OR when a debug/tdd RED-test is handed off for the GREEN side. Runs the `implement-loop` Workflow — a deterministic script that executes the per-task loop (implementer → spec-compliance → quality, each a separate agent call) and aggregates in code, writing edits, tests, and a stats file to the working tree without committing (and `BLOCKED.md` on PARTIAL/BLOCKED). The orchestrator reads the end-report, inspects the working tree, decides commit shape, and performs all commits. Also documents the `compiler-driven` light-edit arm. --- # implement — plan execution on the Workflow substrate > **Violating the letter of these rules is violating the spirit.** ## Overview Plan execution runs as the **`implement-loop` Workflow** (shipped at `workflows/implement-loop.js`, symlinked into `~/.claude/workflows/` by `install.sh`). The orchestrator invokes it through the Workflow tool; the script runs the entire per-task loop deterministically — for each task, implementer → spec-compliance → quality, **each a separate `agent()` call** dispatching the surviving phase agent-types (`implementer`, `spec-reviewer`, `quality-reviewer`, and `tester` for the E2E phase). The inter-phase re-loop, the aggregation, and the DONE/PARTIAL/BLOCKED verdict are code in the script, not natural-language reasoning between dispatches. This replaces the former `implement-orchestrator` agent, which carried the loop as inline role-switches inside one subagent context because Claude Code forbids nested-subagent dispatch. A Workflow orchestrates from the top level, so that workaround is retired: each phase is now a real, **independently-invokable** agent call, and the routing keys on the structured verdict each agent reports (which encodes the project's real build/test outcome). The four phase agents survive unchanged as the agent-types the script dispatches; only the dispatch/aggregation prose the orchestrator-agent carried is gone. All work lives in the working tree: code edits, the stats file, and — on PARTIAL/BLOCKED — `BLOCKED.md` at the repo root. The script **never commits** and never moves main HEAD. The orchestrator reads one end-report (the workflow's return value), inspects the unstaged tree, and decides commit shape. ## When to Use / Skipping Triggers: - A plan exists under `docs/plans` (standard mode → `implement-loop` with `mode: "standard"`). - A `debug` (RED test + cause) or `tdd` (RED executable-spec) handoff for the GREEN side (mini mode → `implement-loop` with `mode: "mini"`). **Never skipped when there is plan-driven or RED-handoff code to ship.** ### The compiler-driven arm (light path) A **behaviour-preserving type/signature edit at a definition site** — one the type checker enumerates across N sites, e.g. a carrier/newtype narrowing or a constructor rename propagated mechanically — does NOT go through the full per-task loop. It is the `compiler-driven` selector arm (see `../boss/SKILL.md` "Entry-path reflection"), routed here by a **positive** trigger matched on the edit's signature, not reached by elimination. Its executor is **observe-then-bounce**, shipped as `workflows/compiler-driven-edit.js`: 1. Make the edit; propagate it mechanically across the sites the build flags. Introduce no new behaviour; add or weaken no test. 2. **Run the project's real build + full suite.** This run — not an ex-ante guess that the change is "behaviour-preserving" — is the oracle. 3. **Done-signal: clean build AND suite green unchanged → the edits sit unstaged for the orchestrator to commit.** That conjunction is the whole gate; it keeps the light path light without letting a green-but-wrong change through. 4. **Bounce** otherwise — the change was not purely behaviour-preserving after all, so route up per the straddle rule: a site that forces a design decision → `specify`; a site that turns out to **encode new behaviour** pinnable as one assertion → `tdd`, RED-first; the suite not green-unchanged (a regression surfaced) → `debug`, RED-first. The fallible ex-ante guess becomes a cheap ex-post detection. A truly trivial mechanical edit (a one-line typo, a rename across a handful of files) the orchestrator MAY still do inline without running the workflow — but the **same done-signal binds**: clean build + suite green unchanged, or it bounces. No review-and-commit discipline is shed; the orchestrator still inspects and commits. **Hard gate — observed bugs never enter this arm.** An observed bug is `debug`'s job (RED-first), even when the fix is a one-line type edit. The selector places the observed-bug check *before* the type-edit arm for exactly this reason; "the fix is mechanical" must not reroute a regression around the RED-first gate. ## The Iron Law ``` THE LOOP NEVER COMMITS. CODE EDITS, TESTS, AND THE STATS FILE LIVE IN THE WORKING TREE AS UNSTAGED CHANGES UNTIL THE ORCHESTRATOR COMMITS THEM. MAIN HEAD IS SACROSANCT — NO RESET, NO REVERT, BY ANY ACTOR. MAIN MOVES FORWARD ONLY VIA ORCHESTRATOR COMMITS. PER-TASK PHASES ARE SEPARATE AGENT CALLS IN THE WORKFLOW SCRIPT — implementer, then spec-compliance, then quality. SPEC COMPLIANCE IS GATED BEFORE QUALITY. TASKS RUN SEQUENTIALLY; A BLOCKED TASK STOPS THE LOOP — NO SKIP-AHEAD (TASK ORDERING DEPENDENCIES ARE UNKNOWN). NEVER PUSH PAST `BLOCKED` BY HAND. ON `PARTIAL` OR `BLOCKED`, THE SCRIPT WRITES `BLOCKED.md` AT THE REPO ROOT — UNCOMMITTED BY CONVENTION. ON `DONE`, NO SEPARATE FILE. THE COMPILER-DRIVEN ARM COMMITS ONLY ON CLEAN BUILD + SUITE GREEN UNCHANGED; ELSE IT BOUNCES (specify for a design hole, tdd for discovered new behaviour, debug for a regression). ``` ## Per-task loop mechanics The script runs, per task: implementer phase, then spec-compliance, then quality — gated in that order. Each is a separate `agent()` call with a structured-output schema, so the script branches on a real verdict. The re-loop limit is **2 repair retries per failure-mode per task; the 3rd unresolved attempt escalates to `BLOCKED`**. A `non_compliant` / `changes_requested` verdict re-dispatches the `implementer` with the review findings as the repair brief; `unclear` task text → `spec-ambiguous` BLOCKED; a tooling failure → `infra` BLOCKED. This logic lives as the loops in `workflows/implement-loop.js` — the single source; it is deliberately not restated as prose elsewhere, so the two cannot drift. ## The Process — orchestrator side ### Step 1 — Run the `implement-loop` workflow Before invoking: ensure the working tree is clean (`git status --porcelain` empty). The workflow's preflight refuses to start on a dirty tree. For a standard iteration: ``` Workflow({ name: "implement-loop", args: { mode: "standard", iter_id: "", plan_path: "", task_range: [3, 8] // optional }}) ``` For a RED-first handoff from `debug` or `tdd` (mini mode): ``` Workflow({ name: "implement-loop", args: { mode: "mini", iter_id: "bugfix-", // tdd: "feat-" red_test_path: "", cause_summary: "<1-2 sentences from debugger>", // tdd: the desired-behaviour line constraint: "minimal fix, no surrounding cleanup" // tdd: "minimal feature, no surrounding scope" }}) ``` The carrier fields are defined authoritatively at the top of `workflows/implement-loop.js`. The load-bearing `iter_id` rule is there too: it names the scratch dir and the stats filename, NOT a branch (there is no branch). ### Step 2 — Read the end-report The workflow returns a small structured end-report (its return value): `status`, `iter_id`, `started_from`, `tasks_total` / `tasks_completed`, per-task summaries, concerns, E2E fixtures, the stats path, and — on PARTIAL/BLOCKED — the blocked detail. Per-task chatter stayed inside the workflow's agent contexts and never reached the orchestrator. Read the end-report; it is the per-task summary you build the commit body from. ### Step 3 — Orchestrator inspect + commit step (on DONE) The workflow returns with code edits and the stats file sitting in the working tree as unstaged changes. Nothing is committed yet, and there is no `BLOCKED.md` (DONE never writes one). 1. Inspect: `git status` and `git diff` — confirm the changes match what the end-report claims. The end-report is the per-task summary; use it as the basis for the commit body. 2. Decide commit shape — by default one cohesive commit for the whole iter; split into a few logical commits only if the diff genuinely covers multiple unrelated changes. Per-task commit splitting is NOT a goal; the iter is the unit of consistency the orchestrator is committing to. 3. Write the commit body. It carries everything a future reader needs that the diff itself does not: the *why*, the alternatives considered and rejected, the verification steps run, and any concerns that remain. Detail-fill comes from the end-report. 4. Stage + commit the code edits and the stats file. 5. If the trigger is done-state and the user is away, run the project's configured notification command per `../boss/SKILL.md` "Done-state notifications". ### Step 4 — Orchestrator handling (on PARTIAL or BLOCKED) The workflow returns with whatever work-in-progress it managed plus `BLOCKED.md` at the repo root carrying the diagnostic. Nothing is committed. The orchestrator decides what to do with the dirty working tree: 1. Read `BLOCKED.md` — `## What did not` names the failure mode and the blocked task's reason. Read `git diff` to see what was attempted. 2. Decide: - **Repair:** keep the working-tree changes in place (or `git stash` them if a clarifying read of clean main is needed first). Adjust plan or extend context; **delete `BLOCKED.md`** (`rm BLOCKED.md`) before re-running the workflow — its preflight clean-tree check counts the file as dirt. Either stash everything and re-run on a clean tree, or commit the known-good subset, then `rm BLOCKED.md`, then re-run. - **Discard:** `git checkout -- .` to drop unstaged file changes; `git clean -fd` / `rm BLOCKED.md` plus anything else new. main HEAD does NOT move. - **Escalate:** ask the user via the configured notification command. `BLOCKED.md` sits in the working tree until the conversation resumes. Under no circumstance does the orchestrator `git reset` or `git revert` on main: there is nothing on main to undo (the workflow did not commit), and the policy forbids history rewinding on main even if there were. ## Handoff Contract `implement` consumes: | Source | Carrier | |--------|---------| | from `planner` | path to plan under `docs/plans` (+ optional `task_range`) → `implement-loop` standard mode | | from `debug` / `tdd` | RED-test path + cause/spec summary + minimal-change constraint → `implement-loop` mini mode | | from the `compiler-driven` selector arm | a type/signature edit + its definition site → `compiler-driven-edit` workflow | `implement` produces: an unstaged working tree containing the code edits and the stats file; on PARTIAL/BLOCKED, also `BLOCKED.md` at the repo root. The orchestrator inspects, commits the code + stats (DONE) or repairs/discards (PARTIAL/BLOCKED). The `compiler-driven-edit` workflow produces an unstaged edit on `DONE`, or a `BOUNCE` verdict naming `specify` / `debug`. No further hand-off — `audit` runs independently at cycle close. ## Common Rationalisations | Excuse | Reality | |--------|---------| | "Single task, running a whole workflow exceeds the work" | The workflow IS the discipline. Invoking it is cheap; the gated per-task phases and the working-tree isolation are the value. For a genuinely trivial mechanical edit, the inline compiler-driven path exists — but its done-signal still binds. | | "Let me have the workflow commit the per-task work, it's cleaner" | The workflow never commits. Orchestrator-only commit is a project-wide rule: only the orchestrator decides when a state is consistent enough to enter main history. | | "Per-task commits would help bisection later" | The workflow's per-task phases are review gates, not bisection points. Iter-level commits are the bisection unit — and they only exist if the whole iter passes review. | | "BLOCKED end-report, let me dig into BLOCKED.md and continue myself" | Read the `## What did not` section first. The loop stopped at the re-loop limit for a reason. Continuing by hand undoes the discipline. | | "End-report says PARTIAL with 4/5 tasks DONE — close enough, commit them" | The 5th task may carry an invariant the earlier 4 silently depend on. Either re-run for the missing task or `git checkout -- .` and re-plan. | | "BLOCKED.md feels redundant — the end-report already has the detail" | The end-report dies when the chat scrolls; `BLOCKED.md` sits in the working tree across pauses and inspection rounds. It is the durable handoff. | | "The compiler-driven edit built fine, ship it without running the suite" | Clean build is half the done-signal. Suite-green-UNCHANGED is the other half — it is what catches a behaviour change the build can't see. No suite run, no commit. | | "The compiler-driven suite went red but the fix is one line — I'll just fix it here" | A red suite means the edit was not behaviour-preserving. That is an observed regression → bounce to `debug`, RED-first. Patching it inline reintroduces exactly the green-but-wrong path the bounce prevents. | | "Nested-subagent dispatch is back via workflows, so an agent can spawn agents" | No. The Workflow orchestrates from the TOP level; the agents it spawns still cannot spawn further agents. The platform constraint is unchanged — the workflow simply does not need nesting. | ## Red Flags — STOP - Orchestrator dispatching `implementer` directly outside the workflow (bypassing the gated loop). - Orchestrator running `git reset` or `git revert` on main. - The workflow (or any agent it spawns) running `git commit`. - Two `implement-loop` runs overlapping on the same working tree. - `BLOCKED.md` staged or committed by anyone. - A compiler-driven edit committed without a clean build AND an unchanged-green suite. - An observed bug routed to the compiler-driven arm instead of `debug`. ## Cross-references - **Workflows dispatched:** - `workflows/implement-loop.js` — the per-task loop (standard + mini). Single source for the carrier contract, the re-loop limit, the stats schema, the `BLOCKED.md` template, and the end-report shape. - `workflows/compiler-driven-edit.js` — the observe-then-bounce light path for a behaviour-preserving type/signature edit. - **Phase agent-types the workflow dispatches** (they survive the migration; the inline-role-switch orchestrator-agent does not): - `agents/implementer.md` — implementer phase (TDD discipline) - `agents/spec-reviewer.md` — spec-compliance phase - `agents/quality-reviewer.md` — quality phase - `agents/tester.md` — E2E coverage phase - **Selector that routes here:** `../boss/SKILL.md` "Entry-path reflection" — the `compiler-driven` arm names this executor, and this file names that arm. They are co-located on purpose: a future edit re-routing the light path back through the full loop changes both cross-references and is a visible regression. - **Why the substrate, not nested subagents.** Claude Code still forbids a subagent from spawning subagents. A Workflow script orchestrates from the top level, so the per-task phases run as its own agent calls without nesting — see `../docs/design.md` § Plugin layer. - **Input sources:** `../planner/SKILL.md` (plans), `../debug/SKILL.md` and `../tdd/SKILL.md` (RED-test handoff for mini mode). - **Output target:** orchestrator reads the end-report, inspects, and commits; `../audit` runs at cycle close.