iter disc.1: boss-only commits + main-as-quarantine (no branches in implement)
Two project-wide rules are now explicit across every skill: 1. Only the Boss commits. No skill agent (implementer, brainstormer, planner, debugger, fieldtester, docwriter, architect, bencher) runs `git commit`. Agents write their artefacts to the working tree as unstaged changes; the Boss inspects, decides commit shape, and commits. 2. main HEAD is sacrosanct. No actor runs `git reset` or `git revert` on main. Bad work stays in the working tree where it is still discardable via `git checkout -- <paths>`. Implement loses the `iter/<iter_id>` branch mechanic entirely; Phase 0 of the orchestrator-agent now does a clean-tree check and refuses to start on a dirty tree. Per-task agent commits are removed everywhere; reviewers operate against `git diff HEAD` instead of `pre_task_sha..head_sha`. Motivation: 2026-05-11 iter 23.4 stranded prep2/prep3 commits on an iter-branch that never integrated to main, then a corrected spec falsely claimed those commits had shipped. Branch-per-iter + manual-Boss-merge + iter-stacking made the strand structurally possible. See docs/journals/2026-05-11-iter-disc.1.md for the full per-task notes and motivation.
This commit is contained in:
+71
-54
@@ -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 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.
|
||||
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) directly in the working tree without creating commits, writes a per-iter journal + stats file (also uncommitted), and returns a compressed end-report. The Boss reads the end-report, inspects the working tree, decides commit shape, and performs all commits.
|
||||
---
|
||||
|
||||
# implement — plan execution via a dedicated orchestrator-agent
|
||||
@@ -14,9 +14,10 @@ ONE subagent (`ailang-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 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.
|
||||
subagent dispatch — see Cross-references). All work lives in the
|
||||
working tree: code edits, the per-iter journal file, and the stats
|
||||
file. The orchestrator does NOT commit. The Boss sees one ≤500-token
|
||||
end-report and an unstaged working tree, then decides commit shape.
|
||||
|
||||
This skill body is intentionally short. The procedural details of
|
||||
the per-task loop live in
|
||||
@@ -41,7 +42,8 @@ is shed.
|
||||
## The Iron Law
|
||||
|
||||
```
|
||||
ONE BRANCH PER ITER — `iter/<iter_id>`, created from local main.
|
||||
THE IMPLEMENTER NEVER COMMITS. CODE EDITS, THE PER-ITER JOURNAL, AND THE STATS FILE ALL LIVE IN THE WORKING TREE AS UNSTAGED CHANGES UNTIL THE BOSS COMMITS THEM.
|
||||
MAIN HEAD IS SACROSANCT — NO RESET, NO REVERT, BY ANY ACTOR. MAIN MOVES FORWARD ONLY VIA BOSS 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.
|
||||
@@ -104,6 +106,10 @@ Agent("ailang-implement-orchestrator", {
|
||||
})
|
||||
```
|
||||
|
||||
Before dispatch: ensure the working tree is clean
|
||||
(`git status --porcelain` empty). The orchestrator's Phase 0 will
|
||||
refuse to start on a dirty tree.
|
||||
|
||||
### Step 2 — Read the end-report
|
||||
|
||||
The orchestrator returns a ≤500-token plain-text report (see the
|
||||
@@ -112,49 +118,60 @@ structure). Read it. The end-report is the only thing that costs the
|
||||
Boss-context tokens; per-task chatter has stayed inside the
|
||||
orchestrator-agent.
|
||||
|
||||
### Step 3 — Boss merge step (on DONE or PARTIAL)
|
||||
### Step 3 — Boss inspect + commit step (on DONE or PARTIAL)
|
||||
|
||||
> **Switch to main FIRST.** The orchestrator-agent ends its run with
|
||||
> the worktree on `iter/<iter_id>` (Phase 0 created the branch and
|
||||
> all per-task commits land on it). Any Boss commit issued before
|
||||
> `git switch main` lands on the iter branch by mistake — including
|
||||
> the INDEX-append below. This is a recurring papercut. Do the
|
||||
> switch before any Boss-side edit.
|
||||
The orchestrator returns with code edits, the per-iter journal
|
||||
file, and the stats file all sitting in the working tree as
|
||||
unstaged changes. Nothing is committed yet.
|
||||
|
||||
1. Open the per-iter journal file on the branch (read-only, branch-
|
||||
independent): `git show iter/<iter_id>:docs/journals/<YYYY-MM-DD>-iter-<iter_id>.md`.
|
||||
2. Decide whether the agent's Summary section is acceptable or needs
|
||||
a Boss-level rewrite. The rest of the journal file is factual and
|
||||
preserved verbatim. Defer the actual edit to step 5 — it lands on
|
||||
main, not on the iter branch.
|
||||
3. Fast-forward main to the iter branch:
|
||||
`git switch main && git merge --ff-only iter/<iter_id>`. Since the
|
||||
iter branch was created from local `main` (Phase 0 of the
|
||||
orchestrator-agent) and no commits have landed on main since, the
|
||||
fast-forward is always linear.
|
||||
4. Append one line to `docs/journals/INDEX.md` and commit:
|
||||
1. Inspect: `git status` and `git diff` — confirm the changes match
|
||||
what the end-report claims. Read the per-iter journal file at
|
||||
`docs/journals/<YYYY-MM-DD>-iter-<iter_id>.md` directly from the
|
||||
working tree.
|
||||
2. Decide whether the agent's Summary section in the journal is
|
||||
acceptable or needs a Boss-level rewrite. Edit it in place if
|
||||
needed.
|
||||
3. 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 Boss is committing to.
|
||||
4. Stage + commit the code edits, the journal, and the stats file.
|
||||
5. Append one line to `docs/journals/INDEX.md` and include it in
|
||||
the same commit (or a follow-up commit):
|
||||
`- YYYY-MM-DD — iter <iter_id>: <one-line title> → <YYYY-MM-DD>-iter-<iter_id>.md`
|
||||
5. If the Summary needed rewriting (step 2), edit the journal file
|
||||
on main now and commit.
|
||||
6. Optionally delete the branch: `git branch -D iter/<iter_id>`.
|
||||
7. If trigger is done-state and the user is away, write a
|
||||
`docs/WhatsNew.md` entry + `notify.sh` per CLAUDE.md's
|
||||
6. If trigger is done-state and the user is away, write a
|
||||
`docs/WhatsNew.md` entry + run `notify.sh` per CLAUDE.md's
|
||||
"Done-state notifications" subsection.
|
||||
|
||||
### Step 4 — Boss handling (on BLOCKED)
|
||||
|
||||
1. Read the per-iter journal on the branch — `Blocked detail:` names
|
||||
the failure mode.
|
||||
The orchestrator returns with whatever work-in-progress it managed
|
||||
plus the per-iter journal recording `Status: BLOCKED`. Nothing is
|
||||
committed. The Boss decides what to do with the dirty working tree:
|
||||
|
||||
1. Read the per-iter journal at the working-tree path — `Blocked detail:`
|
||||
names the failure mode. Read `git diff` to see what was attempted.
|
||||
2. Decide:
|
||||
- **Repair:** adjust plan or extend context; re-dispatch the
|
||||
- **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; re-dispatch the
|
||||
orchestrator with the same `iter_id` and a `task_range` covering
|
||||
the remaining tasks. The orchestrator picks up the existing
|
||||
branch.
|
||||
- **Discard:** `git branch -D iter/<iter_id>`. INDEX.md is NOT
|
||||
touched (the orchestrator did not append).
|
||||
- **Escalate:** ask the user via `notify.sh`. The branch sits
|
||||
the remaining tasks. Phase 0's clean-tree check will refuse
|
||||
if the tree is dirty — Boss either stashes or commits a
|
||||
known-good subset before re-dispatch.
|
||||
- **Discard:** `git checkout -- .` to drop unstaged file
|
||||
changes; `git clean -fd` for any new files (with care).
|
||||
INDEX.md is not touched (no commit happened). main HEAD does
|
||||
NOT move.
|
||||
- **Escalate:** ask the user via `notify.sh`. Working tree sits
|
||||
until the conversation resumes.
|
||||
|
||||
Under no circumstance does the Boss `git reset` or `git revert` on
|
||||
main: there is nothing on main to undo (the orchestrator did not
|
||||
commit), and the policy forbids history rewinding on main even if
|
||||
there were.
|
||||
|
||||
## Handoff Contract
|
||||
|
||||
`implement` consumes:
|
||||
@@ -164,34 +181,34 @@ orchestrator-agent.
|
||||
| from `planner` | path to `docs/plans/<iteration>.md` (+ optional `task_range`) |
|
||||
| from `debug` | RED-test path + cause summary + minimal-fix constraint |
|
||||
|
||||
`implement` produces: a feature branch `iter/<iter_id>` carrying
|
||||
per-task commits, a per-iter journal file (`docs/journals/<file>.md`),
|
||||
and a stats file (`bench/orchestrator-stats/<file>.json`). The Boss
|
||||
merges and updates `docs/journals/INDEX.md`. No further hand-off —
|
||||
`audit` runs independently at milestone close.
|
||||
`implement` produces: an unstaged working tree containing the code
|
||||
edits, the per-iter journal file (`docs/journals/<file>.md`), and
|
||||
the stats file (`bench/orchestrator-stats/<file>.json`). The Boss
|
||||
inspects, commits, and updates `docs/journals/INDEX.md`. No further
|
||||
hand-off — `audit` runs independently at milestone 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, 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. |
|
||||
| "Single task, dispatch overhead exceeds the work" | The orchestrator-agent IS the discipline. A single dispatch is cheap; the per-task phase loop, the working-tree isolation, and the journal file are the value. |
|
||||
| "Let me have the orchestrator commit the per-task work, it's cleaner" | The orchestrator never commits. Boss-only commit is a project-wide rule (see CLAUDE.md): only the Boss decides when a state is consistent enough to enter main history. |
|
||||
| "Per-task commits would help bisection later" | The orchestrator'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 Boss's review. |
|
||||
| "BLOCKED end-report, let me dig into the journal 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 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. |
|
||||
| "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. |
|
||||
| "I'll have the orchestrator-agent update INDEX.md to save a Boss step" | No. INDEX.md is Boss-only. The orchestrator does not know what `<one-line title>` the Boss will pick, and the orchestrator does not commit. |
|
||||
| "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. |
|
||||
| "BLOCKED iter with a bad commit on main — let me `git revert` it" | There is no bad commit on main: the orchestrator did not commit. Bad work stays in the working tree where it is still discardable. main HEAD is sacrosanct. |
|
||||
|
||||
## Red Flags — STOP
|
||||
|
||||
- Boss dispatching `ailang-implementer` directly (bypassing the
|
||||
orchestrator-agent).
|
||||
- Boss editing a per-iter journal file on `main` instead of on its
|
||||
iter branch.
|
||||
- Two `/implement` runs sharing one `iter_id`.
|
||||
- Boss running `git reset` or `git revert` on main.
|
||||
- Orchestrator-agent running `git commit` (anywhere, ever).
|
||||
- Two `/implement` runs overlapping on the same working tree.
|
||||
- INDEX.md modified by anything other than the Boss.
|
||||
- Branch `iter/<iter_id>` pushed to remote before the merge step
|
||||
decided what to do with it.
|
||||
- End-report longer than ~500 tokens.
|
||||
|
||||
## Cross-references
|
||||
@@ -224,5 +241,5 @@ merges and updates `docs/journals/INDEX.md`. No further hand-off —
|
||||
consumes
|
||||
- `skills/debug/SKILL.md` — produces the RED-test handoff for
|
||||
mini-mode
|
||||
- **Output target:** Boss reads the end-report and the per-iter
|
||||
journal; `audit` runs at milestone close.
|
||||
- **Output target:** Boss reads the end-report, inspects the
|
||||
working tree, and commits; `audit` runs at milestone close.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
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-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).
|
||||
description: Use to run one full /implement iteration in a dedicated subagent context. Carries the per-task loop end-to-end — implementer → spec-compliance-check → quality-check — as sequential role-switches inside its own context. Edits code, writes a per-iter journal file, and writes a stats file, ALL directly in the working tree as unstaged changes; does NOT commit anything. Returns a ≤500-token end-report. Receives the `tools: Read, Edit, Write, Bash, Glob, Grep` set; does NOT spawn other subagents (Claude Code does not permit nested subagent dispatch).
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
---
|
||||
|
||||
@@ -48,21 +48,24 @@ You receive from the Boss-Orchestrator:
|
||||
| Field | Content |
|
||||
|-------|---------|
|
||||
| `mode` | `"standard"` or `"mini"` |
|
||||
| `iter_id` | e.g. `"ct.2.3"` (standard) or `"bugfix-<short-symptom>"` (mini). Used for branch name, scratch dir, journal filename, stats filename, commit subjects |
|
||||
| `iter_id` | e.g. `"ct.2.3"` (standard) or `"bugfix-<short-symptom>"` (mini). Used for scratch dir, journal filename, stats filename — NOT a branch name (there is no branch) |
|
||||
| `plan_path` | (standard only) `docs/plans/<file>.md` |
|
||||
| `task_range` | (standard, optional) e.g. `[3, 8]` — run only Tasks 3..8 inclusive |
|
||||
| `red_test_path` | (mini only) absolute path to the RED test from `debug` |
|
||||
| `cause_summary` | (mini only) 1–2 sentences from the debugger agent |
|
||||
| `constraint` | (mini only) `"minimal fix, no surrounding cleanup"` |
|
||||
|
||||
You produce on return: the fixed-format end-report (see Output format).
|
||||
You do NOT touch `docs/journals/INDEX.md` and you do NOT merge the
|
||||
branch — both are Boss-side.
|
||||
You produce on return: the fixed-format end-report (see Output format),
|
||||
plus an unstaged working tree containing all code edits, the per-iter
|
||||
journal file, and the stats file. You do NOT touch
|
||||
`docs/journals/INDEX.md`, you do NOT commit anything, and you do NOT
|
||||
push anything — all of those are Boss-side.
|
||||
|
||||
## The Iron Law
|
||||
|
||||
```
|
||||
ONE BRANCH PER ITER — `iter/<iter_id>`, created from local main.
|
||||
YOU NEVER COMMIT. CODE EDITS, JOURNAL, STATS — ALL UNSTAGED IN THE WORKING TREE. THE BOSS DECIDES COMMIT SHAPE.
|
||||
MAIN HEAD IS SACROSANCT — NO RESET, NO REVERT, EVER, BY ANYONE INCLUDING YOU.
|
||||
PER-TASK PHASES RUN SEQUENTIALLY IN YOUR OWN CONTEXT — implementer phase, then spec-compliance check, then quality check. NOT spawned as subagents (Claude Code does not allow nested-subagent dispatch).
|
||||
TWO-STAGE CHECK PER TASK: SPEC COMPLIANCE FIRST, CODE QUALITY SECOND.
|
||||
NEVER START THE QUALITY CHECK BEFORE THE SPEC-COMPLIANCE CHECK IS GREEN.
|
||||
@@ -72,16 +75,22 @@ WRITE THE PER-ITER JOURNAL FILE BEFORE RETURNING — EVEN ON BLOCKED.
|
||||
|
||||
## The Process
|
||||
|
||||
### Phase 0 — Branch setup (always first)
|
||||
### Phase 0 — Clean-tree check (always first)
|
||||
|
||||
1. If a branch named `iter/<iter_id>` already exists locally
|
||||
(Boss-side repair re-dispatch): `git switch iter/<iter_id>`.
|
||||
Otherwise: `git switch -c iter/<iter_id> main`. Branching from
|
||||
local `main` (not `origin/main`) is deliberate — the Boss
|
||||
commits the plan and spec to local main and dispatches
|
||||
immediately, without pushing first; `origin/main` may lag.
|
||||
2. Record `pre_iter_sha = $(git rev-parse HEAD)` for the end-report.
|
||||
3. Create scratch dir: `mkdir -p /tmp/ail-iter/<iter_id>`.
|
||||
1. Run `git status --porcelain`. It MUST be empty. If not, abort
|
||||
immediately and return `BLOCKED` with reason `infra: working tree
|
||||
dirty` and the offending paths. The Boss is responsible for
|
||||
getting the tree clean before re-dispatch.
|
||||
2. Run `git rev-parse HEAD` and remember the result as
|
||||
`start_sha` — this is an informational anchor for the journal
|
||||
("the iter started from this commit"). It is NOT a reset target;
|
||||
nobody will reset to it. Discarding bad iter work is done via
|
||||
`git checkout -- .` on the working tree by the Boss, not by
|
||||
moving HEAD.
|
||||
3. Run `git rev-parse --abbrev-ref HEAD`. The result MUST be `main`
|
||||
— `iter/...` branches are no longer created and no other branch
|
||||
should be in play.
|
||||
4. Create scratch dir: `mkdir -p /tmp/ail-iter/<iter_id>`.
|
||||
|
||||
### Phase 1 — Load context (mode-dependent)
|
||||
|
||||
@@ -133,17 +142,15 @@ 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.
|
||||
|
||||
Record `pre_task_sha` (before the task's first commit) and
|
||||
`post_impl_sha` (after the implementer's commit) for the
|
||||
spec-check phase.
|
||||
GREEN test. The code edits accumulate in the working tree; you do
|
||||
NOT commit. The whole iter's diff against `start_sha` grows as
|
||||
tasks progress.
|
||||
|
||||
Sub-status at the end of this phase — internal to you, not reported
|
||||
upstream:
|
||||
|
||||
- `DONE` — implementer-phase work complete, GREEN test passes,
|
||||
committed. Proceed to 2.2 (spec check).
|
||||
changes sit in the working tree. 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
|
||||
@@ -157,9 +164,12 @@ upstream:
|
||||
|
||||
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:
|
||||
not just written the code). Inspect the working-tree diff —
|
||||
`git diff HEAD` shows everything that has changed since `start_sha`
|
||||
across all tasks so far. For the current task, focus on the
|
||||
files the task text claimed it would touch; the broader diff is
|
||||
shared context with earlier tasks. Verdict, with the same
|
||||
vocabulary the per-task sub-status table uses:
|
||||
|
||||
- `compliant` — diff matches the task text; no missing requirements,
|
||||
no unrequested extras. Proceed to 2.3 (quality check).
|
||||
@@ -174,9 +184,9 @@ uses:
|
||||
#### 2.3 — Quality check (inline)
|
||||
|
||||
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`.
|
||||
mindset. Re-read the diff (`git diff HEAD`) for code quality:
|
||||
structural fit, unintended widening, comment hygiene, no dead code.
|
||||
Issues are severity-tagged `Important` / `Minor` / `Nit`.
|
||||
|
||||
- `approved` — no `Important` or `Minor` issues. Proceed to 2.4.
|
||||
- `changes_requested` — `Important` or `Minor` issues present.
|
||||
@@ -194,8 +204,8 @@ TodoWrite update; proceed to next task.
|
||||
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`.
|
||||
Write them into the working tree alongside the rest of the iter's
|
||||
changes; the Boss will commit them together.
|
||||
|
||||
(Mini mode: skip Phase 3 — the RED test from `debug` IS the
|
||||
coverage.)
|
||||
@@ -209,18 +219,18 @@ not the iter's plan date). Template:
|
||||
# iter <iter_id> — <one-line title>
|
||||
|
||||
**Date:** YYYY-MM-DD
|
||||
**Branch:** iter/<iter_id>
|
||||
**Started from:** <start_sha>
|
||||
**Status:** DONE | PARTIAL | BLOCKED
|
||||
**Tasks completed:** <N> of <total>
|
||||
|
||||
## Summary
|
||||
|
||||
<1-paragraph summary; the Boss may rewrite this section during merge>
|
||||
<1-paragraph summary; the Boss may rewrite this section before commit>
|
||||
|
||||
## Per-task subjects
|
||||
## Per-task notes
|
||||
|
||||
- iter <iter_id>.1: <commit subject>
|
||||
- iter <iter_id>.2: <commit subject>
|
||||
- iter <iter_id>.1: <one-line task description + what changed>
|
||||
- iter <iter_id>.2: <one-line task description + what changed>
|
||||
- ...
|
||||
|
||||
## Concerns
|
||||
@@ -236,21 +246,16 @@ not the iter's plan date). Template:
|
||||
<only if BLOCKED / PARTIAL: task N, reason from the sub-status table,
|
||||
worker's verbatim BLOCKED text, suggested next step>
|
||||
|
||||
## Commits
|
||||
## Files touched
|
||||
|
||||
<pre_iter_sha>..<head_sha>
|
||||
<paths from `git diff --name-only HEAD`, grouped if helpful>
|
||||
|
||||
## Stats
|
||||
|
||||
bench/orchestrator-stats/<YYYY-MM-DD>-iter-<iter_id>.json
|
||||
```
|
||||
|
||||
Commit on the branch:
|
||||
|
||||
```bash
|
||||
git add docs/journals/<file>.md
|
||||
git commit -m "iter <iter_id>: per-iter journal"
|
||||
```
|
||||
The file goes into the working tree (Write tool). Do NOT commit.
|
||||
|
||||
### Phase 5 — Write stats file
|
||||
|
||||
@@ -272,28 +277,24 @@ with at least these fields:
|
||||
}
|
||||
```
|
||||
|
||||
Commit on the branch:
|
||||
|
||||
```bash
|
||||
git add bench/orchestrator-stats/<file>.json
|
||||
git commit -m "iter <iter_id>: orchestrator stats"
|
||||
```
|
||||
The file goes into the working tree (Write tool). Do NOT commit.
|
||||
|
||||
### Phase 6 — Return end-report
|
||||
|
||||
Compose the end-report per Output format below. Do NOT push the
|
||||
branch — the Boss decides on integration. Do NOT touch
|
||||
`docs/journals/INDEX.md` — Boss-only.
|
||||
Compose the end-report per Output format below. Do NOT commit
|
||||
anything. Do NOT push. Do NOT touch `docs/journals/INDEX.md`. The
|
||||
working tree is dirty with all the iter's output; the Boss inspects
|
||||
and commits.
|
||||
|
||||
## Status protocol
|
||||
|
||||
The agent returns exactly one of:
|
||||
|
||||
- `DONE` — full iter (or the requested task_range) completed; all
|
||||
reviews green; journal + stats committed on branch.
|
||||
reviews green; journal + stats written to the working tree.
|
||||
- `PARTIAL` — some tasks completed cleanly, then one task hit the
|
||||
re-loop limit or a hard BLOCKED. Earlier task commits remain on the
|
||||
branch; journal records `Status: PARTIAL`.
|
||||
re-loop limit or a hard BLOCKED. Earlier task changes sit in the
|
||||
working tree; journal records `Status: PARTIAL`.
|
||||
- `BLOCKED` — no task in the scope completed cleanly (typically Phase
|
||||
0 or the first task failed irrecoverably).
|
||||
- `NEEDS_CONTEXT` — the carrier from the Boss was missing required
|
||||
@@ -308,14 +309,15 @@ Plain-text, ≤ 500 tokens, fixed structure:
|
||||
```
|
||||
Status: DONE | PARTIAL | BLOCKED | NEEDS_CONTEXT
|
||||
Iter: <iter_id>
|
||||
Branch: iter/<iter_id>
|
||||
Started from: <start_sha>
|
||||
Tasks completed: <N> of <total>
|
||||
- <commit subject 1>
|
||||
- <commit subject 2>
|
||||
- <one-line task description 1>
|
||||
- <one-line task description 2>
|
||||
...
|
||||
Journal file: docs/journals/<YYYY-MM-DD>-iter-<iter_id>.md (on branch)
|
||||
Stats: bench/orchestrator-stats/<YYYY-MM-DD>-iter-<iter_id>.json (on branch)
|
||||
Commits: <pre_iter_sha>..<head_sha>
|
||||
Working tree: dirty (N files changed)
|
||||
Journal file: docs/journals/<YYYY-MM-DD>-iter-<iter_id>.md (uncommitted)
|
||||
Stats: bench/orchestrator-stats/<YYYY-MM-DD>-iter-<iter_id>.json (uncommitted)
|
||||
Files touched: <count from `git diff --name-only HEAD | wc -l`>
|
||||
Tests: <count> green, <count> red
|
||||
E2E coverage: <new fixture paths, or "none (mini mode)">
|
||||
Blocked detail: (only if BLOCKED or PARTIAL)
|
||||
@@ -332,23 +334,28 @@ Blocked detail: (only if BLOCKED or PARTIAL)
|
||||
| "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. |
|
||||
| "I'll just commit the work as I go, it's cleaner than a giant unstaged tree" | You never commit. Boss-only commit is a project-wide rule. The unstaged tree IS the hand-off. |
|
||||
| "Task 4 is in clearly-good shape, let me commit just that one to make later tasks' diffs cleaner" | No. Commit is a Boss decision. Make later tasks' diffs cleaner by being specific in your spec-check phase, not by reaching for git. |
|
||||
| "BLOCKED on task 3, I'll skip to task 4" | Skip is a Boss decision, not yours. Task dependencies are encoded in the plan and you do not know the graph. Return BLOCKED. |
|
||||
| "Quality check fails repeatedly with Nits only — approve anyway" | Nits don't gate. 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. |
|
||||
| "I forgot to write the journal file before returning" | Re-do Phase 4. Returning without the journal file in the working tree 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. |
|
||||
| "Tree was dirty when I started, but it's small — I'll work over it" | No. Return BLOCKED immediately with `infra: working tree dirty`. Mixing prior dirt with iter output makes the Boss's review impossible. |
|
||||
|
||||
## Red Flags — STOP
|
||||
|
||||
- About to do any phase without reading
|
||||
`skills/implement/SKILL.md` first this dispatch.
|
||||
- About to run `git commit` (anywhere, for any file, at any phase).
|
||||
- About to run `git switch -c` or `git switch` to a non-main branch.
|
||||
- About to run `git reset` or `git revert`.
|
||||
- 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 push anything (`git push`).
|
||||
- About to skip Phase 4 (journal file) "because the run is BLOCKED".
|
||||
- About to return more than 500 tokens of end-report.
|
||||
- About to run the quality phase before the spec phase is `compliant`.
|
||||
- About to skip Phase 5 (stats file) "because mini mode".
|
||||
- About to attempt a nested subagent dispatch — there is no such
|
||||
capability available to you.
|
||||
- About to proceed past Phase 0 on a dirty working tree.
|
||||
|
||||
@@ -127,14 +127,16 @@ the test.
|
||||
it protects, not just what it asserts ("rejects empty email" → "submitForm
|
||||
surfaces a required-field error when email is empty"). The Iron Law from
|
||||
`ailang-tester` applies to your tests too.
|
||||
8. Commit per the task's own commit step (`iter <X>.<n>: <subject>` or, in
|
||||
`mini` mode, `fix: <symptom>`).
|
||||
9. Self-review: re-read your diff. Did it match the task text? Did you do
|
||||
anything not in the task text? If yes, revert that part — controller
|
||||
curates scope, not you. Did the test you wrote actually fail before the
|
||||
GREEN code, or did you write it after? If after, delete the production
|
||||
code and start over. (TDD is letter-and-spirit.)
|
||||
10. Report.
|
||||
8. Self-review: re-read `git diff HEAD`. Did it match the task text? Did
|
||||
you do anything not in the task text? If yes, undo that part with
|
||||
`git checkout -- <path>` or by editing back — controller curates scope,
|
||||
not you. Did the test you wrote actually fail before the GREEN code, or
|
||||
did you write it after? If after, delete the production code and start
|
||||
over. (TDD is letter-and-spirit.)
|
||||
9. Report. Your changes stay in the working tree as unstaged edits. You
|
||||
do NOT commit. The orchestrator's spec-compliance and quality phases
|
||||
read your work via `git diff HEAD`; the Boss commits at the end of
|
||||
the iter.
|
||||
|
||||
## Status protocol
|
||||
|
||||
@@ -179,6 +181,7 @@ and stop. Do not implement on a hunch.
|
||||
| "The task says X but Y is clearly better" | Then the plan is wrong. Return `BLOCKED` or `DONE_WITH_CONCERNS` naming the contradiction. Do not silently substitute. |
|
||||
| "Just one test for the happy path is enough" | Bug fixes need RED-first regression coverage; new features need at least one property-protecting test. The doc comment must name the property. |
|
||||
| "Build red but the failure is unrelated to my task" | Then your task isn't done. Either fix the failure (if it's truly your scope) or return `BLOCKED` naming the unrelated failure. Never report `DONE` on a red tree. |
|
||||
| "Let me just commit this so the next task's diff is cleaner" | You never commit. Boss-only commit is the project rule. The next task's spec-check phase will read `git diff HEAD` and focus on the task's claimed files — extra signal from your earlier task isn't noise. |
|
||||
| "Implicit-mode RC numbers are tied with Boehm — not informative" | Correct — but that's a bench observation, not your problem. Report and move on; don't try to fix the leak inline. |
|
||||
| "I read DESIGN.md and disagree with Decision N" | Decisions are binding. Disagreement goes to the orchestrator as a concern, not into the diff. |
|
||||
| "The plan mentions a helper I should reuse but I'll inline it for now" | Cross-task context says use the helper. Use the helper. Inlining "for now" creates the duplication the plan tried to avoid. |
|
||||
@@ -190,7 +193,7 @@ and stop. Do not implement on a hunch.
|
||||
|
||||
- About to add a TODO/FIXME without it being in the task text
|
||||
- About to "fix while I'm here" something not in the task
|
||||
- About to commit on red tests
|
||||
- About to run `git commit` (anywhere, ever — you never commit)
|
||||
- About to skip the self-review re-read of the diff
|
||||
- About to report `DONE` while a concern is unspoken
|
||||
- About to substitute a "better" approach for the one in the task block at `task_text_path`
|
||||
|
||||
@@ -45,11 +45,10 @@ own quality conventions.
|
||||
|
||||
| Field | Content |
|
||||
|-------|---------|
|
||||
| `diff` | Implementer's diff, inline or via SHAs |
|
||||
| `pre_task_sha` | Commit SHA before the implementer's first change |
|
||||
| `head_sha` | Commit SHA after the implementer's last change |
|
||||
| `diff_command` | Shell command that produces the diff. Default and almost-always value: `git diff HEAD` (the working tree's full unstaged diff for this iter). |
|
||||
| `spec_review_status` | Must be `compliant` from `ailang-spec-reviewer`. If anything else, return `infra_blocked` immediately — quality review is wasted on a non-compliant diff |
|
||||
| `task_subject` | Short title of the task (one line, for context — NOT the full task text) |
|
||||
| `task_footprint_hint` | (optional) list of files the current task is supposed to touch — lets you focus on the current-task subset of the working-tree diff when earlier tasks of the same iter have also modified files |
|
||||
|
||||
If `spec_review_status` is not `compliant`, return `infra_blocked` and
|
||||
name the issue.
|
||||
@@ -114,9 +113,12 @@ if there are `Nit` items.
|
||||
## The Process
|
||||
|
||||
1. Read the standing list and the carrier.
|
||||
2. `git diff <pre_task_sha>..<head_sha>` — read every line.
|
||||
3. For each chunk, ask the eight quality-bar questions above. Don't pattern-
|
||||
match on one criterion and skip the others.
|
||||
2. Run `diff_command` (default `git diff HEAD`) — read every line.
|
||||
When a `task_footprint_hint` is given, narrow your judgement to chunks
|
||||
inside that footprint; chunks outside it belong to earlier tasks of
|
||||
this iter and have already been reviewed.
|
||||
3. For each chunk in scope, ask the eight quality-bar questions above.
|
||||
Don't pattern-match on one criterion and skip the others.
|
||||
4. Categorise findings by severity.
|
||||
5. List **Strengths** first — at least one, if you can name one. The
|
||||
pattern of "all critique, no acknowledgement" makes implementers
|
||||
@@ -131,7 +133,7 @@ if there are `Nit` items.
|
||||
- `changes_requested` — at least one `Important` or `Minor` issue.
|
||||
Implementer fixes; quality review re-runs.
|
||||
- `infra_blocked` — `spec_review_status` was not `compliant`, or the
|
||||
diff doesn't apply. Stop.
|
||||
`diff_command` fails / produces no output. Stop.
|
||||
|
||||
## Output format
|
||||
|
||||
|
||||
@@ -44,12 +44,11 @@ hands you the task text — that's your spec for this review.
|
||||
| Field | Content |
|
||||
|-------|---------|
|
||||
| `task_text_path` | Absolute path (typically `/tmp/ail-iter/<iter_id>/task-<N>.md`) — same file the implementer received. Read this file as your first action. |
|
||||
| `diff` | The implementer's diff, either inline or as `git diff <pre-task>..HEAD` |
|
||||
| `pre_task_sha` | Commit SHA before the implementer's first change (so you can re-derive the diff) |
|
||||
| `head_sha` | Commit SHA after the implementer's last change |
|
||||
| `diff_command` | The shell command that produces the diff to review. Default and almost-always value: `git diff HEAD` (the working tree's full unstaged diff, accumulated across all tasks of this iter so far). Earlier tasks' changes are visible in this diff because no per-task commits are made — that is intentional; focus on the files the current task block claims it touches |
|
||||
| `status_from_implementer` | `DONE` or `DONE_WITH_CONCERNS` — if `DONE_WITH_CONCERNS`, the concerns are quoted so you can decide if they affect spec compliance |
|
||||
|
||||
If `task_text_path` and `diff` aren't both present, return `NEEDS_CONTEXT`.
|
||||
If `task_text_path` is missing or `diff_command` produces no output,
|
||||
return `NEEDS_CONTEXT`.
|
||||
|
||||
## The Iron Law
|
||||
|
||||
@@ -104,12 +103,17 @@ Examples:
|
||||
2. Read the file at `task_text_path` in full — that is the task block.
|
||||
List the requirements as a checklist: every "step", every code block,
|
||||
every `Files:` entry.
|
||||
3. Re-derive the diff: `git diff <pre_task_sha>..<head_sha>`. Skim once
|
||||
for orientation.
|
||||
3. Run the `diff_command` (default `git diff HEAD`). Skim once for
|
||||
orientation. The diff covers everything changed in the working tree
|
||||
since the iter started; earlier tasks' changes appear in the same
|
||||
diff. The current task's footprint is the subset of chunks that
|
||||
touch the files named in the task block.
|
||||
4. For each requirement, locate the satisfying code in the diff.
|
||||
Mark it ✓ or ✗.
|
||||
5. For each chunk in the diff, check whether the task block requested it.
|
||||
Mark requested or extra.
|
||||
5. For each chunk in the diff that falls inside the current task's
|
||||
footprint, check whether the task block requested it. Mark
|
||||
requested or extra. Chunks outside the footprint (touched by
|
||||
earlier tasks of this iter) are not your concern this round.
|
||||
6. Confirm any test the task scripted (RED-first or otherwise) actually
|
||||
exists in the diff. A "RED test" that's never been seen failing is
|
||||
suspicious — but you flag the absence, not the suspicion (`NEEDS_CONTEXT`
|
||||
@@ -125,9 +129,9 @@ Examples:
|
||||
without naming it, or two requirements contradict). Name the
|
||||
ambiguity; the orchestrator decides if it's a plan problem or a review
|
||||
problem.
|
||||
- `infra_blocked` — diff doesn't apply, commit range doesn't resolve,
|
||||
test command fails for an environment reason. Stop; this isn't a spec
|
||||
problem.
|
||||
- `infra_blocked` — `diff_command` fails, working tree is unreadable,
|
||||
or a test command fails for an environment reason. Stop; this isn't
|
||||
a spec problem.
|
||||
|
||||
The implement skill expects compliance to be a binary gate. A `compliant`
|
||||
result lets code quality run; anything else loops back to the implementer.
|
||||
|
||||
@@ -75,13 +75,15 @@ DETERMINISTIC: SAME INPUT, SAME OUTPUT, EVERY RUN.
|
||||
- Add the corresponding test in `crates/ail/tests/e2e.rs`.
|
||||
- Doc comment names the property.
|
||||
4. Run `cargo test --workspace`. Must be green.
|
||||
5. Commit per existing journal style (`iter <X>.<n>: e2e for <feature>`).
|
||||
6. Report.
|
||||
5. Report. Your fixtures and tests stay in the working tree as unstaged
|
||||
edits; the Boss commits them at the end of the iter alongside the
|
||||
feature work they protect. You do NOT commit.
|
||||
|
||||
## Status protocol
|
||||
|
||||
- `DONE` — fixtures + tests committed, all green, properties named.
|
||||
- `DONE_WITH_CONCERNS` — committed and green, but a property you tried to
|
||||
- `DONE` — fixtures + tests written to the working tree, all green,
|
||||
properties named.
|
||||
- `DONE_WITH_CONCERNS` — written and green, but a property you tried to
|
||||
protect couldn't be expressed at the E2E layer (e.g. needs runtime
|
||||
instrumentation that doesn't exist). Name the gap.
|
||||
- `NEEDS_CONTEXT` — `iteration_scope` doesn't tell you what shipped.
|
||||
@@ -115,7 +117,8 @@ At most 200 words:
|
||||
- About to write a test asserting on internal state (AST node count, IR
|
||||
string contents)
|
||||
- About to write a fixture that combines unrelated features
|
||||
- About to commit without a doc comment naming the property
|
||||
- About to run `git commit` (anywhere, ever — you never commit)
|
||||
- About to mark `DONE` without a doc comment naming the property
|
||||
- About to introduce a non-deterministic input (system time, `rand`,
|
||||
filesystem listing order)
|
||||
- About to skip the `cargo test --workspace` run
|
||||
|
||||
Reference in New Issue
Block a user