or.2: orchestrator-agent design correction — no nested subagent dispatch

Claude Code categorically forbids subagents from spawning other
subagents (code.claude.com/docs/en/sub-agents and the Agent SDK
subagents page). The `or.1` architecture (and `pr.1` that ran on
top of it) presumed a named-exception for `ailang-implement-
orchestrator` to dispatch implementer / spec-reviewer / quality-
reviewer / tester per task. That exception never existed at the
platform level; the `Agent` tool was silently dropped from the
orchestrator-agent's tool set at dispatch time.

Architecture revised, doc-only:

- Per-task phases (implementer → spec-compliance check → quality
  check) now run as sequential role-switches in the orchestrator-
  agent's own context, not as nested subagents.
- The four role-files (implementer / spec-reviewer / quality-
  reviewer / tester) become phase reference files the
  orchestrator-agent consults at role-switch boundaries.
- Boss-context offload preserved; fresh-per-phase context given
  up (the property that drove or.1's nested-dispatch design is
  not buildable in Claude Code).

Files touched:
- skills/implement/agents/ailang-implement-orchestrator.md
  (frontmatter, Iron Law, Phase 2/3 rewrite, rationalisations,
  red flags)
- skills/implement/SKILL.md (frontmatter, Iron Law, sub-status
  vocabulary note, cross-references)
- skills/README.md (Conventions: no more named exception; agent
  roster: role-files recast as phase references)
- docs/journals/INDEX.md (or.2 entry appended)
- docs/journals/2026-05-11-iter-or.2.md (new — full rationale)
- docs/roadmap.md (P1 tool-wiring item removed; resolved as
  categorically-not-fixable)
- docs/WhatsNew.md (user-facing correction entry appended)

No code changes; no bench impact; CLAUDE.md untouched (no stale
references to fix there).
This commit is contained in:
2026-05-11 13:01:38 +02:00
parent bd801b979c
commit 5c3bd9ab24
7 changed files with 340 additions and 97 deletions
+4
View File
@@ -22,3 +22,7 @@ The implement cycle no longer eats your context. From the next time we run it, t
## 2026-05-11 — plan-writing offload + first-run debrief
Plan-writing also offloads its read-heavy phase now — the part where I walk the codebase looking for the right files for a plan. Should feel lighter on the chat side from the next plan onwards. First real test of yesterday's per-task isolation refactor exposed a tool-wiring bug along the way: the Boss-context offload part works (you still see only an end-report at the end), but the per-task fresh-subagent isolation didn't actually fire — all tasks ended up running in one bigger context inside the orchestrator. Diagnosis is queued at the top of the next-up list. A small iter-branch setup wording bug got fixed in the same session. Audit clean, no benchmark regressions.
## 2026-05-11 — implement-cycle correction
Yesterday's note claimed the per-task review loop runs as separate fresh-context phases. That isn't possible — Claude Code does not allow a sub-helper to spawn further sub-helpers, full stop. The project's older "no helper calls another helper" convention turns out to have been a restatement of that platform rule all along, not a local design choice with a documented exception. So the architecture is corrected: the per-task loop still runs offloaded from your chat into one dedicated helper context (the part that does save your chat budget), but the review phases now run as sequential checkpoints inside that helper rather than as separate fresh contexts. The chat-side experience does not change. The fresh-per-phase isolation that the earlier note implied does not exist and never could; honestly scoped now.
+189
View File
@@ -0,0 +1,189 @@
# iter or.2 — orchestrator-agent design correction
**Date:** 2026-05-11
**Branch:** none (trivial-mechanical carve-out — doc-only revision, single commit on main)
**Status:** DONE
**Tasks completed:** N/A (doc revision, not a plan-driven iter)
## Summary
This entry corrects a factual error in the `or.1` architecture that
surfaced during the first real dispatch (pr.1, same day). The
revision lands as one direct-on-main commit because the change is
doc-only: no code, no tests, no behaviour shift in any compiler
crate. The Iron-Law mini-fix from earlier today (`origin/main`
`main`) is preserved unchanged — that fix remains correct.
### What was wrong
`or.1` and `pr.1` shipped the `ailang-implement-orchestrator` agent
with frontmatter `tools: Read, Edit, Write, Bash, Glob, Grep, Agent`
and an architecture that depended on the orchestrator-agent
spawning further subagents per task (implementer → spec-reviewer →
quality-reviewer → tester, each in fresh context). The architecture
was framed in `skills/README.md` as "agents do not call other
agents — one named exception" (the orchestrator-agent being the
exception).
The exception never existed in Claude Code. The platform forbids
**all** nested-subagent dispatch, categorically:
> "Subagents cannot spawn other subagents, so `Agent(agent_type)`
> has no effect in subagent definitions."
> — https://code.claude.com/docs/en/sub-agents
> "Subagents cannot spawn their own subagents. Don't include
> `Agent` in a subagent's `tools` array."
> — https://code.claude.com/docs/en/agent-sdk/subagents
The `Agent` tool was silently dropped from the orchestrator-agent's
tool set at dispatch time (no error, no warning). The pr.1 run
caught this empirically; the diagnosis closed the question today.
### Why the failure took the form it did
The Boss-Orchestrator (me) designed `or.1` on the false premise
that the project's house rule "agents do not call other agents"
was a local convention with a documented exception. In reality the
house rule was a *restatement of an external constraint* — and the
"named exception" was incompatible with the constraint itself.
This is a verification-of-capability failure: the architecture was
locked in before checking the platform docs for what subagents can
do. The right order is the other way around. (Memorised as a
feedback memory for future architecture decisions.)
### The corrected architecture
Same skill body, same skill triggers, same branch-and-merge
discipline, same Boss-side end-report contract. What changes is
*inside* the orchestrator-agent's run:
- Per-task phases (implementer → spec-compliance check → quality
check) run sequentially as **role-switches in the orchestrator-
agent's own context**, not as nested subagents.
- The `ailang-implementer.md` / `ailang-spec-reviewer.md` /
`ailang-quality-reviewer.md` / `ailang-tester.md` files now serve
as **phase reference files** — the orchestrator-agent consults
them at each role-switch to inhale the discipline of that role,
but does not dispatch them as separate subagents.
- The Boss-context offload property is preserved (the Boss still
sees only the ≤500-token end-report; per-task chatter stays
inside the orchestrator-agent's context).
- The fresh-per-phase context property — which was the design goal
that drove `or.1` to attempt nested dispatch — is **given up**.
Pure role-switching inside one context is a weaker discipline
than fresh-context-per-phase. The trade-off is named openly: the
cost is the loss of fresh-eyes review per phase; the benefit is
that the architecture is buildable in Claude Code at all.
- The pr.1 "degraded mode" was not actually degraded — it was the
only mode this agent can run in. The pr.1 journal's degraded-
mode caveat is preserved as-is (historical record of how the
constraint was discovered).
### Why option (A), not (B) or (C)
Three options were on the table:
- **(A)** Single-context inline phases (what landed) — preserves
Boss-context offload, gives up fresh-per-phase context.
- **(B)** Roll back to pre-or.1: Boss dispatches each per-task
subagent itself. Preserves fresh-per-phase context, gives up
Boss-context offload.
- **(C)** Hybrid: orchestrator-agent for setup / branch / journal,
Boss for per-task dispatches in between. Preserves both
theoretically but multiplies moving parts.
(A) was chosen because the Boss-context offload is the scarce
resource (user chat budget). Empirically, the pr.1 run with the
plan template's verbatim per-task content blocks made fresh-per-
phase context contribute little additional signal beyond a careful
single-context phase loop. The decision was made by the user
2026-05-11 after the diagnosis was presented; the rationale belongs
in the user's hands, not the agent's.
### Files changed
- `skills/implement/agents/ailang-implement-orchestrator.md`
frontmatter (`Agent` removed from tools, description rewritten),
Iron Law (sequential role-switches instead of fresh subagents),
Phase 2.1 / 2.2 / 2.3 rewritten as inline phases, Phase 3 likewise,
common rationalisations and red flags updated.
- `skills/implement/SKILL.md` — frontmatter description, Iron Law,
per-task sub-status mechanics note (vocabulary is preserved but
now describes inline role-phase status), one new
Common-Rationalisation row, Cross-references rewritten (role-files
recast as phase references, with a "Why inline phases" subsection
pointing here).
- `skills/README.md` — Conventions: "Agents do not call other
agents — one named exception" → "Agents do not call other agents"
(the exception is gone, with an explanation of why). Agent roster
rows for implementer / spec-reviewer / quality-reviewer / tester
recast as phase references for the orchestrator-agent.
- `docs/roadmap.md` — P1 entry "`Agent` tool wiring for the
dispatched orchestrator-agent" removed (resolved as
categorically-not-fixable).
- `docs/journals/INDEX.md` — this entry appended.
- `docs/WhatsNew.md` — user-facing correction entry appended.
### Files NOT changed (and why)
- `CLAUDE.md` — no stale references; the file does not encode the
named-exception story.
- `skills/implement/agents/ailang-implementer.md`,
`ailang-spec-reviewer.md`, `ailang-quality-reviewer.md`,
`ailang-tester.md` — these remain unchanged. Their content
(discipline, reading list, output format) is correct in the new
architecture; their *role* in the system has shifted from
"dispatched subagent" to "phase reference for the orchestrator-
agent". The shift is documented in the README roster row and the
SKILL.md Cross-references; no in-file edits are required for
correctness. A future cleanup iter may rewrite their frontmatter
to drop the "subagent" framing if it begins to mislead — for now
the cost of touching four files outweighs the marginal clarity
gain.
- `docs/specs/2026-05-11-implement-orchestrator-agent.md` and
`docs/specs/2026-05-11-plan-recon-subagent.md` — specs are
historical records of the design as conceived; they remain
accurate to that moment. Drift between spec and the corrected
architecture is acknowledged here, not by editing the specs.
## Concerns
None. The revision is deliberate and self-contained.
## Known debt
- **Phase reference files frame themselves as dispatched subagents.**
`ailang-implementer.md` and its three siblings still read like
files describing a subagent receiving a carrier from a dispatcher.
In the corrected architecture, the orchestrator-agent IS the
dispatcher and the worker for those phases. If the next
`/implement` run shows the orchestrator-agent confused by this
framing during phase reads, a follow-up cleanup iter rewrites
the four files. Not pre-emptive — wait for an empirical signal.
- **No verification ladder for the corrected design.** `or.1`'s
verification ladder (items 15 in
`docs/specs/2026-05-11-implement-orchestrator-agent.md`) was
written for the nested-dispatch architecture. Items 13
(Boss-side dispatch, branch creation, journal write) carry over
unchanged. Items 45 (intentional BLOCKED, intentional re-loop)
are weaker in the inline-phase world — re-loop is a same-context
retry, not a fresh-context re-dispatch — and a new ladder entry
for the inline phase-switch should be added the next time
`/implement` runs against a non-trivial plan. Tracked
informally; no ticket.
## Blocked detail
N/A — DONE.
## Commits
This entry's revision lands as a single trivial-mechanical commit
on `main` (no iter branch, no plan template). The commit subject is
`or.2: orchestrator-agent design correction — no nested subagent dispatch`.
## Stats
N/A — no orchestrator-agent dispatch (this is a doc-only revision
made directly by the Boss-Orchestrator).
+1
View File
@@ -8,3 +8,4 @@
- 2026-05-11 — iter or.1: orchestrator-refactor → 2026-05-11-iter-or.1.md
- 2026-05-11 — fieldtest canonical-type-names → 2026-05-11-fieldtest-canonical-type-names.md
- 2026-05-11 — iter pr.1: plan-recon subagent → 2026-05-11-iter-pr.1.md
- 2026-05-11 — iter or.2: orchestrator-agent design correction (no nested subagent dispatch) → 2026-05-11-iter-or.2.md
-16
View File
@@ -41,22 +41,6 @@ context. Pick the next milestone from P1.)_
## P1 — Next
- [ ] **\[todo\]** `Agent` tool wiring for the dispatched
orchestrator-agent — `skills/implement/agents/ailang-implement-orchestrator.md`
declares `tools: Read, Edit, Write, Bash, Glob, Grep, Agent`, but
the first real dispatch (pr.1) reported `Agent` was not in its
actual tool set, forcing degraded-mode execution (per-task
sub-loop did not run; all tasks executed inline in the
orchestrator's own context). Diagnosis needed before fix-scope
can be set: Claude Code restriction on nested-subagent dispatch?
Frontmatter parsing detail? Deferred-tool issue at the harness
layer? This blocks the or.1 design goal (Boss-context offload via
fresh-subagent-per-task isolation); Boss-context offload itself
still works because per-task detail collapses into one
end-report regardless.
- context: `docs/journals/2026-05-11-iter-pr.1.md` Boss-side
addendum + Audit close section.
- [ ] **\[milestone\]** Post-22 Prelude — ship `Show` / `Eq` / `Ord`
with the three total-orderable primitive instances (Int, Bool, Str);
rewire `print` through `Show.show`. Float gets `Show` but **not**
+15 -13
View File
@@ -53,11 +53,11 @@ are no orphan agents (an anti-pattern after the 2026-05-09 build-out).
| Agent | Path | Dispatched by skill |
|-------|------|---------------------|
| `ailang-plan-recon` | `planner/agents/` | `planner` (Step 2; read-only file-structure mapping); `brainstorm` (ad-hoc Step 1 in unfamiliar territory) |
| `ailang-implement-orchestrator` | `implement/agents/` | `implement` (the only agent with the `Agent` tool; runs the per-task loop) |
| `ailang-implementer` | `implement/agents/` | `implement` (Step 2.1; carries TDD as an independent layer) |
| `ailang-spec-reviewer` | `implement/agents/` | `implement` (Step 2.3; did the diff match the task text?) |
| `ailang-quality-reviewer`| `implement/agents/` | `implement` (Step 2.4; is the diff well-built? — only after spec is `compliant`) |
| `ailang-tester` | `implement/agents/` | `implement` (Step 3; E2E coverage) |
| `ailang-implement-orchestrator` | `implement/agents/` | `implement` (the dispatched agent; runs the entire per-task loop inline in its own context) |
| `ailang-implementer` | `implement/agents/` | phase reference for `ailang-implement-orchestrator` Phase 2.1 (implementer mindset, carries TDD as an independent layer); not dispatched as a separate subagent |
| `ailang-spec-reviewer` | `implement/agents/` | phase reference for `ailang-implement-orchestrator` Phase 2.2 (spec-compliance mindset); not dispatched as a separate subagent |
| `ailang-quality-reviewer`| `implement/agents/` | phase reference for `ailang-implement-orchestrator` Phase 2.3 (quality-review mindset); not dispatched as a separate subagent |
| `ailang-tester` | `implement/agents/` | phase reference for `ailang-implement-orchestrator` Phase 3 (E2E coverage); not dispatched as a separate subagent |
| `ailang-architect` | `audit/agents/` | `audit` (Step 1; drift review against DESIGN.md + spec) |
| `ailang-bencher` | `audit/agents/` | `audit` (regression diagnostics — hypothesis-driven) |
| `ailang-docwriter` | `audit/agents/` | `audit` (Step 3; rustdoc cleanup, optional) |
@@ -140,14 +140,16 @@ dispatch can find them by `subagent_type`:
- **No orphan agents.** Every agent lives under the skill that
dispatches it. If a recurring need does not fit any skill, raise
the question via a per-iter journal entry before adding the agent.
- **Agents do not call other agents — one named exception.** The
dirigierende skill composes (e.g. `audit` dispatches architect, then
bencher, then docwriter). The single exception is
`ailang-implement-orchestrator`, which runs the per-task implementer
→ spec-reviewer → quality-reviewer loop on its own; this exception
is documented in `skills/implement/SKILL.md` and exists to keep
per-iter chatter out of the Boss-context. No other agent gains the
`Agent` tool.
- **Agents do not call other agents.** The dispatching skill composes
(e.g. `audit` dispatches architect, then bencher, then docwriter).
No agent receives the `Agent` tool in its frontmatter — Claude Code
does not permit a subagent to spawn other subagents. The
`ailang-implement-orchestrator`, which historically was framed as a
named exception, runs its per-task phases as sequential
role-switches inside its own context (implementer phase → spec
check → quality check); see `skills/implement/SKILL.md` for the
mechanism and `docs/journals/2026-05-11-iter-or.2.md` for the
revision history.
- **Standing reading list stays in the agent file.** The skill provides
the carrier (task text, bug symptom, drift focus, hypothesis) on top
of the agent's standing reading list (CLAUDE.md, DESIGN.md, latest per-iter journals,
+46 -25
View File
@@ -1,6 +1,6 @@
---
name: implement
description: Use when an implementation plan exists in docs/plans/ and is ready to execute, OR when a debug RED-test is handed off for a bugfix. Dispatches the ailang-implement-orchestrator agent, which runs the entire per-task loop (implementer → spec-reviewer → quality-reviewer) on an isolated branch `iter/<iter_id>`, writes a per-iter journal + stats file, and returns a compressed end-report. The Boss reads the end-report, optionally rewrites the journal Summary section, appends one line to docs/journals/INDEX.md, and fast-forwards main to the iter branch.
description: Use when an implementation plan exists in docs/plans/ and is ready to execute, OR when a debug RED-test is handed off for a bugfix. Dispatches the ailang-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) on an isolated branch `iter/<iter_id>`, writes a per-iter journal + stats file, and returns a compressed end-report. The Boss reads the end-report, optionally rewrites the journal Summary section, appends one line to docs/journals/INDEX.md, and fast-forwards main to the iter branch.
---
# implement — plan execution via a dedicated orchestrator-agent
@@ -11,11 +11,12 @@ description: Use when an implementation plan exists in docs/plans/ and is ready
Plan execution is fully delegated. The Boss-Orchestrator dispatches
ONE subagent (`ailang-implement-orchestrator`), which runs the entire
per-task loop in its own context: implementer → spec-reviewer →
quality-reviewer, per task, with the Iron Law and re-loop limits
below. All commits land on a dedicated branch `iter/<iter_id>`.
The Boss sees one ≤500-token end-report and a per-iter journal file
on the branch.
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 commits land on a
dedicated branch `iter/<iter_id>`. The Boss sees one ≤500-token
end-report and a per-iter journal file on the branch.
This skill body is intentionally short. The procedural details of
the per-task loop live in
@@ -41,9 +42,9 @@ is shed.
```
ONE BRANCH PER ITER — `iter/<iter_id>`, created from local main.
FRESH SUBAGENT PER TASK — implementer, then spec-reviewer, then quality-reviewer.
TWO-STAGE REVIEW: SPEC COMPLIANCE FIRST, CODE QUALITY SECOND.
NEVER START QUALITY REVIEW BEFORE SPEC COMPLIANCE IS GREEN.
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.
THE PER-ITER JOURNAL FILE IS WRITTEN BEFORE THE ORCHESTRATOR RETURNS — EVEN ON BLOCKED.
```
@@ -51,18 +52,24 @@ THE PER-ITER JOURNAL FILE IS WRITTEN BEFORE THE ORCHESTRATOR RETURNS — EVEN ON
## Per-task sub-status mechanics
The orchestrator-agent reads and follows this table verbatim every
dispatch:
dispatch. Sub-status values are *internal* to the orchestrator-agent
— they describe the state of an inline role-phase, not the status
of a separate subagent. The vocabulary is preserved because it maps
1:1 to the phase reference files
(`ailang-implementer.md` / `ailang-spec-reviewer.md` /
`ailang-quality-reviewer.md`) the orchestrator-agent consults at
each role-switch.
| Sub-status | Orchestrator action |
|------------|---------------------|
| `DONE` | next task / next phase |
| `DONE_WITH_CONCERNS` | accumulate concern, next |
| `NEEDS_CONTEXT` (1st2nd) | re-dispatch with expanded carrier |
| `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 Boss, reason `context-exhausted` |
| `non_compliant` / `changes_requested` (1st2nd) | implementer re-dispatch with the reviewer's report as repair brief |
| `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 Boss, reason `review-loop-exhausted` |
| `BLOCKED` (worker) | stop → `BLOCKED` to Boss, reason verbatim |
| `unclear` (spec-reviewer) | stop → `BLOCKED` to Boss, reason `spec-ambiguous` |
| `BLOCKED` (implementer phase) | stop → `BLOCKED` to Boss, reason verbatim |
| `unclear` (spec-compliance phase) | stop → `BLOCKED` to Boss, reason `spec-ambiguous` |
| Tool / infra error | stop → `BLOCKED` to Boss, reason `infra` + raw error |
Re-loop limit: 2 retries per failure-mode per task. The 3rd is
@@ -158,12 +165,13 @@ merges and updates `docs/journals/INDEX.md`. No further hand-off —
| Excuse | Reality |
|--------|---------|
| "Single task, dispatch overhead exceeds the work" | The orchestrator-agent IS the discipline. A single dispatch is cheap; the per-task review loop, the branch isolation, and the journal file are the value. |
| "Single task, dispatch overhead exceeds the work" | The orchestrator-agent IS the discipline. A single dispatch is cheap; the per-task phase loop, the branch isolation, and the journal file are the value. |
| "I'll merge on main directly, no need for the iter branch" | The branch is what makes parallel `/implement` activity safe and makes "discard on BLOCKED" trivial. Skipping it puts you back in the pre-2026-05-11 coordination problems. |
| "BLOCKED end-report, let me dig into the branch and continue myself" | Read the `Blocked detail:` first. The orchestrator stopped at the re-loop limit for a reason. Continuing by hand undoes the discipline. |
| "End-report says PARTIAL with 4/5 DONE — close to enough" | The 5th task may carry an invariant the earlier 4 silently depend on. Either re-dispatch for the missing task or treat the iter as incomplete. |
| "Skip the INDEX line, the journal file is enough" | INDEX.md is the only thing that makes per-iter journals navigable. Without it, future agents have to ls the directory and parse filenames. |
| "I'll let the orchestrator-agent update INDEX.md" | No. INDEX.md is Boss-only. The orchestrator-agent does not know what `<one-line title>` the Boss will pick. |
| "The per-task phases run inline anyway, just have the Boss dispatch the reviewer-agents instead and skip the orchestrator-agent" | That gives back fresh-per-phase context but loses the Boss-context offload — the per-task chatter goes back through the Boss. 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. |
## Red Flags — STOP
@@ -181,11 +189,27 @@ merges and updates `docs/journals/INDEX.md`. No further hand-off —
- **Agent dispatched:**
`skills/implement/agents/ailang-implement-orchestrator.md`
carries the per-task loop, including dispatch of:
- `skills/implement/agents/ailang-implementer.md` (Phase 2.1)
- `skills/implement/agents/ailang-spec-reviewer.md` (Phase 2.3)
- `skills/implement/agents/ailang-quality-reviewer.md` (Phase 2.4)
- `skills/implement/agents/ailang-tester.md` (Phase 3)
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:
- `skills/implement/agents/ailang-implementer.md` — Phase 2.1
reference (implementer mindset, TDD discipline)
- `skills/implement/agents/ailang-spec-reviewer.md` — Phase 2.2
reference (spec-compliance mindset)
- `skills/implement/agents/ailang-quality-reviewer.md` — Phase
2.3 reference (quality-review mindset)
- `skills/implement/agents/ailang-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. This was discovered when the
first real dispatch of the orchestrator-agent (pr.1, 2026-05-11)
reported that the `Agent` tool was absent from its tool set even
though frontmatter declared it. The architecture has been revised
accordingly (see `docs/journals/2026-05-11-iter-or.2.md`).
- **Input sources:**
- `skills/planner/SKILL.md` — produces the plan files this skill
consumes
@@ -193,6 +217,3 @@ merges and updates `docs/journals/INDEX.md`. No further hand-off —
mini-mode
- **Output target:** Boss reads the end-report and the per-iter
journal; `audit` runs at milestone close.
- **Documented exception.** `ailang-implement-orchestrator` is the
named exception to "agents do not call other agents". See its file
frontmatter and Iron Law for the precise scope.
@@ -1,7 +1,7 @@
---
name: ailang-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-reviewer → quality-reviewer, with the canonical re-loop limits — on an isolated branch (`iter/<iter_id>`), writes a per-iter journal file, writes a stats file, returns a ≤500-token end-report. The named exception to "agents do not call other agents".
tools: Read, Edit, Write, Bash, Glob, Grep, Agent
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, on an isolated branch (`iter/<iter_id>`), writes a per-iter journal file, writes a stats file, 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
---
# ailang-implement-orchestrator — per-iter loop in isolated context
@@ -11,10 +11,13 @@ tools: Read, Edit, Write, Bash, Glob, Grep, Agent
## What this role is for
The Boss-Orchestrator's context grew by ~100k tokens per `/implement`
run before this role existed — plan loaded once, task text duplicated
between implementer and spec-reviewer dispatches, review re-loops
amortised against the Boss's context budget. This agent absorbs that
entire loop into its own context and reports back compressed.
run before this role existed — the Boss dispatched implementer +
spec-reviewer + quality-reviewer subagents itself per task, every
per-task chatter line travelled through the Boss's context, and
review re-loops amortised against the Boss'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 Boss needs
@@ -60,9 +63,9 @@ branch — both are Boss-side.
```
ONE BRANCH PER ITER — `iter/<iter_id>`, created from local main.
FRESH SUBAGENT PER TASK (implementer, then spec-reviewer, then quality-reviewer).
TWO-STAGE REVIEW PER TASK: SPEC COMPLIANCE FIRST, CODE QUALITY SECOND.
NEVER START QUALITY REVIEW BEFORE SPEC COMPLIANCE IS GREEN.
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 BOSS.
WRITE THE PER-ITER JOURNAL FILE BEFORE RETURNING — EVEN ON BLOCKED.
```
@@ -111,53 +114,88 @@ WRITE THE PER-ITER JOURNAL FILE BEFORE RETURNING — EVEN ON BLOCKED.
### Phase 2 — Per-task loop
For each task K in TodoWrite order (use TodoWrite to track tasks as
status changes — but TodoWrite items live in YOUR context, not the
status changes — TodoWrite items live in YOUR context, not the
Boss's):
#### 2.1 — Dispatch implementer
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:
`Agent("ailang-implementer", { task_text_path: "/tmp/ail-iter/<iter_id>/task-K.md", scene_set: ..., cross_task_context: ..., mode: ... })`.
- Implementer phase reference: `skills/implement/agents/ailang-implementer.md`
- Spec-compliance check reference: `skills/implement/agents/ailang-spec-reviewer.md`
- Quality check reference: `skills/implement/agents/ailang-quality-reviewer.md`
#### 2.2Handle implementer status
#### 2.1Implementer phase (inline)
Follow the per-task sub-status table in `skills/implement/SKILL.md`
verbatim. Re-loop limit: ≤ 2 retries with expanded context for
`NEEDS_CONTEXT`. 3rd → return `BLOCKED` to Boss (reason
`context-exhausted`).
Read `/tmp/ail-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 → commit on the branch with the task's commit subject.
#### 2.3 — Spec-compliance review
Record `pre_task_sha` (before the task's first commit) and
`post_impl_sha` (after the implementer's commit) for the
spec-check phase.
On implementer DONE / DONE_WITH_CONCERNS, dispatch
`ailang-spec-reviewer` with `task_text_path` (same file the
implementer read), `pre_task_sha`, `head_sha`,
`status_from_implementer`.
Sub-status at the end of this phase — internal to you, not reported
upstream:
`non_compliant`: re-dispatch the implementer with the reviewer's
report as repair brief. Re-loop limit: ≤ 2 retries. 3rd → return
`BLOCKED` (reason `review-loop-exhausted`).
- `DONE` — implementer-phase work complete, GREEN test passes,
committed. Proceed to 2.2 (spec check).
- `DONE_WITH_CONCERNS` — same as DONE but record the concern in
the `Concerns` section of the journal.
- `NEEDS_CONTEXT` — required information missing (carrier or
workspace). Re-attempt the phase with expanded context. Re-loop
limit: ≤ 2 retries. 3rd → return `BLOCKED` to Boss (reason
`context-exhausted`).
- `BLOCKED` — work cannot proceed (e.g. invariant violation, plan
contradiction). Return `BLOCKED` to Boss with the failure mode.
`unclear`: STOP. Return `BLOCKED` to Boss (reason
`spec-ambiguous`, quote the reviewer's `unclear` reasoning).
#### 2.2 — Spec-compliance check (inline)
#### 2.4 — Quality review
Switch to the spec-reviewer mindset. Re-read the task text at
`/tmp/ail-iter/<iter_id>/task-K.md` with fresh eyes (as if you had
not just written the code). Diff `pre_task_sha..post_impl_sha`.
Verdict, with the same vocabulary the per-task sub-status table
uses:
Only after spec is `compliant`. Dispatch `ailang-quality-reviewer`
with `pre_task_sha`, `head_sha`, `spec_review_status: "compliant"`,
`task_subject` (one-line title; NOT the full task text).
- `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 Boss (reason `spec-ambiguous`, quote
the ambiguity).
`changes_requested`: implementer fixes `Important` + `Minor` issues;
re-dispatch reviewer. Re-loop ≤ 2. 3rd → `BLOCKED`
(`review-loop-exhausted`).
#### 2.3 — Quality check (inline)
#### 2.5 — Task done
Only after 2.2 is `compliant`. Switch to the quality-reviewer
mindset. Re-read the diff 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)
Dispatch `ailang-tester` with `iteration_scope`, `coverage_gap` (if
known), `mode: "e2e_after_iter"`. Tester writes E2E fixtures and
commits them on the branch.
Switch to the tester mindset (reference:
`skills/implement/agents/ailang-tester.md`). Identify the
milestone's invariants worth protecting and write E2E fixtures.
Commit them on the branch with subject
`iter <iter_id>: E2E coverage`.
(Mini mode: skip Phase 3 — the RED test from `debug` IS the
coverage.)
@@ -291,22 +329,26 @@ Blocked detail: (only if BLOCKED or PARTIAL)
| Excuse | Reality |
|--------|---------|
| "Plan said dispatch a single big task, I'll just inline it" | Then the plan is wrong, or you misread it. Tasks are the unit of dispatch; refuse to inline. |
| "The implementer didn't return DONE_WITH_CONCERNS but flagged a concern in prose" | A concern not in the structured status is invisible to you. Re-dispatch asking for the structured status; do not act on prose hints. |
| "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 merge the branch myself, the Boss is busy" | Out of scope. Merge is Boss-only. Branch + journal + stats sit until the Boss reads the end-report. |
| "BLOCKED on task 3, I'll skip to task 4" | Skip is a Boss decision, not yours. Task dependencies are encoded in the plan and you do not know the graph. Return BLOCKED. |
| "Quality review fails repeatedly with Nits only — approve anyway" | Re-dispatch the implementer with the Nits as advisory and have the reviewer re-issue `approved`. Nits don't gate, but the reviewer's verdict does. |
| "Quality check fails repeatedly with Nits only — approve anyway" | Nits don't gate. Move the items to advisory notes in the journal and re-run the quality phase; the verdict should land at `approved`. |
| "I forgot to commit the journal file before returning" | Re-do Phase 4. Returning without the journal file committed is a bug, not a corner case. |
| "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. |
## Red Flags — STOP
- About to dispatch the implementer without reading
- About to do any phase without reading
`skills/implement/SKILL.md` first this dispatch.
- About to edit `docs/journals/INDEX.md`.
- About to push the branch to remote (any `git push`).
- About to merge into main / rebase main / fast-forward main.
- About to skip Phase 4 (journal file) "because the run is BLOCKED".
- About to return more than 500 tokens of end-report.
- About to dispatch the quality-reviewer before spec is `compliant`.
- 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.