Files
Skills/implement/SKILL.md
T
Brummel fc0e1d0d46 skills: cut blabla and redundancy from skill prose
Per-skill prose tightening from the same audit swarm; each finding
passed an adversarial second reviewer. No behavioural change.

- audit: drop garbled "Conventions require deferred audits to
  compound" sentence (says the opposite of intent; the preceding
  line already closes the loophole).
- brainstorm: drop forward-pointing meta-comment about the
  Rationalisations table.
- debug: drop third restatement that debugger.md is the single
  source for the carrier/handoff fields.
- docwriter: drop motivational opener; Overview starts at the
  waste argument.
- fieldtest: fold the 2-4-examples rationale into the dispatch
  sentence instead of restating the count a fourth time.
- implement: drop "known platform constraint at the time" aside.
- planner: cut the verbose anti-drift paragraph (which restated
  the very table it claimed not to) down to a cross-reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 13:21:25 +02:00

255 lines
13 KiB
Markdown

---
name: implement
description: Use when an implementation plan exists under paths.plan_dir and is ready to execute, OR when a debug RED-test is handed off for a bugfix. Dispatches the implement-orchestrator agent, which runs the entire per-task loop (implementer phase → spec-compliance check → quality check, as sequential role-switches in its own context) directly in the working tree without creating commits, writes a stats file (and on BLOCKED/PARTIAL also `BLOCKED.md`), and returns a compressed end-report. The orchestrator reads the end-report, inspects the working tree, decides commit shape, and performs all commits.
---
# implement — plan execution via a dedicated orchestrator-agent
> **Violating the letter of these rules is violating the spirit.**
## Overview
Plan execution is fully delegated. The orchestrator dispatches
ONE subagent (`implement-orchestrator`), which runs the entire
per-task loop in its own context: implementer phase → spec-
compliance check → quality check, per task, as sequential
role-switches inside the orchestrator-agent itself (Claude
Code does not permit nested subagent dispatch — see
Cross-references). All work lives in the working tree: code
edits and the stats file (and `BLOCKED.md` if the outcome is
PARTIAL/BLOCKED). The orchestrator-agent does NOT commit.
The orchestrator sees one ≤500-token end-report and an
unstaged working tree, then decides commit shape — the
end-report carries the per-task summary the orchestrator
uses to write the commit body.
This skill body is intentionally short. The procedural
details of the per-task loop live in
`agents/implement-orchestrator.md`. The **canonical
discipline** (Iron Law, sub-status table, common
rationalisations) lives in this file and is read by the
orchestrator-agent every dispatch.
## When to Use / Skipping
Triggers:
- A plan exists under `paths.plan_dir` (standard mode).
- A `debug` skill has produced a RED test + cause and is
handing off for the GREEN side (mini mode).
**Never skipped** when there is code to ship. Trivial
mechanical edits (one-line typo fix, schema rename across N
files) MAY be handled inline by the orchestrator without
dispatch, per the project's CLAUDE.md "trivial mechanical
edits" carve-out — but no review-and-commit discipline is
shed.
## The Iron Law
```
THE IMPLEMENTER NEVER COMMITS. CODE EDITS 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 RUN SEQUENTIALLY IN THE ORCHESTRATOR-AGENT'S OWN CONTEXT — implementer phase, then spec-compliance check, then quality check. Each phase is a deliberate role-switch, NOT a fresh subagent (nested-subagent dispatch is forbidden by Claude Code).
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.
ON `PARTIAL` OR `BLOCKED`, THE ORCHESTRATOR-AGENT WRITES `BLOCKED.md` AT THE REPO ROOT BEFORE RETURNING — UNCOMMITTED BY CONVENTION. ON `DONE`, NO SEPARATE FILE.
```
## Per-task sub-status mechanics
Each dispatch, the orchestrator-agent runs an internal per-task
loop over a sub-status vocabulary — `DONE`, `DONE_WITH_CONCERNS`,
`NEEDS_CONTEXT`, `non_compliant` / `changes_requested`, `BLOCKED`,
`unclear`, and tool/infra errors — bounded by a 2-retries-per-
failure-mode re-loop limit (the 3rd attempt escalates to
`BLOCKED`). These values are *internal* to the orchestrator-agent:
they describe the state of an inline role-phase, not a separate
subagent, and are not reported upstream.
The mapping of each value to its action (and the `BLOCKED` reasons
`context-exhausted` / `review-loop-exhausted` / `spec-ambiguous` /
`infra`) is defined authoritatively under **Per-task sub-status
vocabulary** in `agents/implement-orchestrator.md` — the file the
agent actually carries at runtime in its fresh context. That table
is the single source; it is deliberately not restated here, so the
two files cannot drift.
## The Process — orchestrator side
### Step 1 — Dispatch the orchestrator-agent
For a standard iteration:
```
Agent("implement-orchestrator", {
mode: "standard",
iter_id: "<iter_id>",
plan_path: "<path under paths.plan_dir>",
task_range: [3, 8]
})
```
For a debug-handoff (mini mode):
```
Agent("implement-orchestrator", {
mode: "mini",
iter_id: "bugfix-<short-symptom>",
red_test_path: "<absolute path>",
cause_summary: "<1-2 sentences from debugger>",
constraint: "minimal fix, no surrounding cleanup"
})
```
The blocks above show the call shape; each field's semantics
(including the load-bearing `iter_id` rule — it names the scratch
dir and stats filename, NOT a branch) are defined authoritatively
under **Carrier contract** in `agents/implement-orchestrator.md`.
That table is the single source for the field semantics; they are
deliberately not restated here, so the two files cannot drift.
Before dispatch: ensure the working tree is clean
(`git status --porcelain` empty). The orchestrator-agent's
Phase 0 will refuse to start on a dirty tree.
### Step 2 — Read the end-report
The orchestrator-agent returns a ≤500-token plain-text
report (see the agent's "Output format — end-report" section
for the fixed structure). Read it. The end-report is the
only thing that costs the orchestrator-context tokens;
per-task chatter has stayed inside the orchestrator-agent.
### Step 3 — Orchestrator inspect + commit step (on DONE)
The orchestrator-agent 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 that were considered and rejected, the
verification steps run, and any concerns that remain.
Detail-fill comes from the end-report — the per-task
chatter that stayed inside the orchestrator-agent does
not come back, by design.
4. Stage + commit the code edits and the stats file.
5. If trigger is done-state and the user is away, run the
project's configured notification command per
`../boss/SKILL.md` "Done-state notifications" subsection.
### Step 4 — Orchestrator handling (on PARTIAL or BLOCKED)
The orchestrator-agent 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 worker's verbatim reason. Read `git diff`
to see what was attempted.
2. Decide:
- **Repair:** keep the working-tree changes in place (or
stash them with `git stash` if a clarifying read of
clean main is needed first). Adjust plan or extend
context; **delete `BLOCKED.md`** (`rm BLOCKED.md`)
before re-dispatch — the orchestrator-agent's Phase 0
clean-tree check counts it as dirt. Either stash
everything and re-dispatch on a clean tree, or commit
the known-good subset, then `rm BLOCKED.md`, then
re-dispatch.
- **Discard:** `git checkout -- .` to drop unstaged file
changes; `git clean -fd BLOCKED.md` (or `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
orchestrator-agent 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 `paths.plan_dir` (+ optional `task_range`) |
| from `debug` | RED-test path + cause summary + minimal-fix constraint |
`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). No further hand-off — `audit` runs
independently at cycle close.
## Common Rationalisations
| Excuse | Reality |
|--------|---------|
| "Single task, dispatch overhead exceeds the work" | The orchestrator-agent IS the discipline. A single dispatch is cheap; the per-task phase loop and the working-tree isolation are the value. |
| "Let me have the orchestrator-agent commit the per-task work, it's cleaner" | The orchestrator-agent 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 orchestrator-agent'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 the orchestrator's review. |
| "BLOCKED end-report, let me dig into BLOCKED.md and continue myself" | Read the `## What did not` section first. The orchestrator-agent 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-dispatch for the missing task or `git checkout -- .` and re-plan. |
| "BLOCKED.md feels redundant — the end-report already has the blocked detail" | The end-report dies when the chat scrolls; `BLOCKED.md` sits in the working tree across pauses, mode-switches, and orchestrator-inspection rounds. It is the durable handoff. |
| "The per-task phases run inline anyway, just have the orchestrator dispatch the reviewer-agents instead and skip the orchestrator-agent" | That gives back fresh-per-phase context but loses the orchestrator-context offload — the per-task chatter goes back through the orchestrator. The orchestrator-agent exists precisely for the offload. If you want fresh-per-phase context AND offload, you want a capability Claude Code does not provide. |
| "BLOCKED iter with a bad commit on main — let me `git revert` it" | There is no bad commit on main: the orchestrator-agent did not commit. Bad work stays in the working tree where it is still discardable. main HEAD is sacrosanct. |
| "Re-dispatch refuses because `BLOCKED.md` is still in the tree — let me just commit it to clear the check" | No. `BLOCKED.md` is never committed. `rm BLOCKED.md` (or stash) before re-dispatch — the file's whole purpose is to live in the working tree, not on main. |
## Red Flags — STOP
- Orchestrator dispatching `implementer` directly (bypassing
the orchestrator-agent).
- Orchestrator running `git reset` or `git revert` on main.
- Orchestrator-agent running `git commit` (anywhere, ever).
- Two `/implement` runs overlapping on the same working tree.
- `BLOCKED.md` staged or committed by anyone.
- End-report longer than ~500 tokens.
## Cross-references
- **Agent dispatched:** `agents/implement-orchestrator.md`
carries the per-task loop inline; each phase is a
role-switch in the orchestrator-agent's own context. The
role-files below are *phase references* (the
orchestrator-agent reads them at each role-switch to
inhale the discipline) — they are NOT separately
dispatched subagents:
- `agents/implementer.md` — Phase 2.1 reference
(implementer mindset, TDD discipline)
- `agents/spec-reviewer.md` — Phase 2.2 reference
(spec-compliance mindset)
- `agents/quality-reviewer.md` — Phase 2.3 reference
(quality-review mindset)
- `agents/tester.md` — Phase 3 reference (E2E coverage
mindset)
- **Why inline phases, not nested subagents.** Claude Code
does not permit a subagent to spawn other subagents. The
orchestrator-agent cannot dispatch the role-agents above;
it adopts each role as a sequential phase in its own
context.
- **Input sources:**
- `../planner/SKILL.md` — produces the plan files this
skill consumes
- `../debug/SKILL.md` — produces the RED-test handoff for
mini-mode
- **Output target:** orchestrator reads the end-report,
inspects the working tree, and commits; `../audit` runs
at cycle close.