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:
2026-05-11 22:44:43 +02:00
parent 841d65d88c
commit 51da9fab53
18 changed files with 552 additions and 248 deletions
@@ -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) 12 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.