diff --git a/docs/WhatsNew.md b/docs/WhatsNew.md index e065e96..7af6516 100644 --- a/docs/WhatsNew.md +++ b/docs/WhatsNew.md @@ -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. diff --git a/docs/journals/2026-05-11-iter-or.2.md b/docs/journals/2026-05-11-iter-or.2.md new file mode 100644 index 0000000..2fce834 --- /dev/null +++ b/docs/journals/2026-05-11-iter-or.2.md @@ -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 1–5 in + `docs/specs/2026-05-11-implement-orchestrator-agent.md`) was + written for the nested-dispatch architecture. Items 1–3 + (Boss-side dispatch, branch creation, journal write) carry over + unchanged. Items 4–5 (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). diff --git a/docs/journals/INDEX.md b/docs/journals/INDEX.md index 206b572..cb56c0b 100644 --- a/docs/journals/INDEX.md +++ b/docs/journals/INDEX.md @@ -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 diff --git a/docs/roadmap.md b/docs/roadmap.md index 91c7551..b044940 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -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** diff --git a/skills/README.md b/skills/README.md index 3dc8aaa..4d5abd7 100644 --- a/skills/README.md +++ b/skills/README.md @@ -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, diff --git a/skills/implement/SKILL.md b/skills/implement/SKILL.md index a936950..64a1ef1 100644 --- a/skills/implement/SKILL.md +++ b/skills/implement/SKILL.md @@ -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/`, 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/`, 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/`. -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/`. 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/`, 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` (1st–2nd) | re-dispatch with expanded carrier | +| `DONE` | next phase / next task | +| `DONE_WITH_CONCERNS` | accumulate concern, next phase | +| `NEEDS_CONTEXT` (1st–2nd) | re-attempt the phase with expanded context | | `NEEDS_CONTEXT` (3rd) | stop → `BLOCKED` to Boss, reason `context-exhausted` | -| `non_compliant` / `changes_requested` (1st–2nd) | implementer re-dispatch with the reviewer's report as repair brief | +| `non_compliant` / `changes_requested` (1st–2nd) | 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 `` 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. diff --git a/skills/implement/agents/ailang-implement-orchestrator.md b/skills/implement/agents/ailang-implement-orchestrator.md index 4d9052a..c2b19ce 100644 --- a/skills/implement/agents/ailang-implement-orchestrator.md +++ b/skills/implement/agents/ailang-implement-orchestrator.md @@ -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/`), 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/`), 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/`, 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//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.2 — Handle implementer status +#### 2.1 — Implementer 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//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//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 : 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.