diff --git a/CLAUDE.md b/CLAUDE.md index bf135e0..c10e984 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,6 +77,34 @@ See @skills/README.md for the skill + agent roster. outcome. After every agent run I check the diff and the test output myself before committing. +### Commit discipline and main-branch sanctity + +Two project-wide rules govern who touches git history and how: + +- **Only the Boss (me) commits.** No skill agent — implementer, + brainstormer, planner, debugger, fieldtester, docwriter, + architect, bencher — runs `git commit`. Every agent writes its + output (spec, plan, code, tests, fixtures, rustdoc edits, RED + tests, journal files, stats, updated baselines) into the working + tree as unstaged changes. I inspect the result with + `git status` / `git diff`, decide commit shape (often one + cohesive iter-level commit; sometimes a few logical commits when + the changes genuinely cover separate concerns), and commit. + Per-task or per-phase commits are not a goal in themselves. +- **main HEAD is sacrosanct.** Nobody (including me) runs + `git reset` or `git revert` on main. main moves forward only via + my commits. The consequence is the working-tree-as-quarantine + discipline: nothing half-baked enters main, because nothing can + be taken back off. If a dispatched agent's output is wrong, I + discard it via `git checkout -- ` or `git stash` on the + working tree — main HEAD does not move. If something wrong does + land on main, the remedy is a forward-fix commit, never a rewind. + +These rules supersede earlier mechanics that involved per-iter +branches and per-task agent commits. See `skills/README.md` +"Conventions" for the same rules in skill-system form, and the +2026-05-11 journal for the failure mode that motivated the change. + ### Authority over `skills/` and the agent roster I am free to add, edit, retire, or replace skill or agent definitions @@ -142,15 +170,17 @@ applied as a gate by `skills/brainstorm/SKILL.md` during spec writing. ### Direction freedom I have authority to choose the next iteration, refactor, or feature -without asking. Wrong calls are recoverable: every commit is -reachable via git, branches and tags exist for sharper rollback -points (`pre-rc` is one such), and reverting one or several commits -is cheap. +without asking. Wrong calls are contained, not recovered: only the +Boss commits, and only when the working-tree state is consistent — +so bad work doesn't reach main in the first place. If a dispatched +agent's output is wrong, the remedy is `git checkout -- ` on +the working tree (Boss-side), never a rewind of main HEAD. main is +forward-only. The cost of asking "what should I do next" — context-switch for -the user, latency on my side — exceeds the expected cost of an -occasional rollback. So when the queue is non-empty and the path -is clear, just pick and proceed. +the user, latency on my side — exceeds the expected cost of +discarding a bad working-tree state. So when the queue is non-empty +and the path is clear, just pick and proceed. Bounce back to the user only when: diff --git a/docs/journals/2026-05-11-iter-disc.1.md b/docs/journals/2026-05-11-iter-disc.1.md new file mode 100644 index 0000000..349856b --- /dev/null +++ b/docs/journals/2026-05-11-iter-disc.1.md @@ -0,0 +1,190 @@ +# iter disc.1 — boss-only commits and main-as-quarantine + +**Date:** 2026-05-11 +**Started from:** 841d65d +**Status:** DONE +**Tasks completed:** 10 of 10 (Boss-direct implementation; no orchestrator dispatch) + +## Summary + +Skill-system-wide discipline update. Two project-wide rules are now +explicit: + +1. **Only the Boss commits.** No skill agent — implementer, + brainstormer, planner, debugger, fieldtester, docwriter, + architect, bencher — performs `git commit`. Agents write all + their artefacts into the working tree as unstaged changes; the + Boss inspects, decides commit shape (typically one cohesive iter + commit, occasionally a few logical commits), and commits. +2. **main HEAD is sacrosanct.** No actor — Boss or agent — runs + `git reset` or `git revert` on main. Bad work stays in the + working tree where it is still discardable via + `git checkout -- `; main moves forward only via Boss + commits. + +The two rules together force a working-tree-as-quarantine +discipline: nothing half-baked enters main, because nothing can +be taken back off main. The implement skill loses its +`iter/` branch-per-iter mechanic entirely; per-task agent +commits are also gone — Phase 4 of the orchestrator-agent now +writes the per-iter journal and the stats file into the working +tree (Write tool) but does not commit them. + +## Per-task notes + +- disc.1.1: `skills/implement/SKILL.md` — Iron Law rewritten + ("IMPLEMENTER NEVER COMMITS" replaces "ONE BRANCH PER ITER"; + "MAIN HEAD IS SACROSANCT" added). Step 3 "Boss merge step" + renamed and rewritten as "Boss inspect + commit step" (no + fast-forward; Boss reads `git status` / `git diff`, decides + commit shape, commits). Step 4 (BLOCKED) rewritten: Working-Tree + inspect, Repair re-dispatch or Discard via + `git checkout -- .`, no branch deletion. Description, Overview, + Rationalisations, Red Flags updated. +- disc.1.2: `skills/implement/agents/ailang-implement-orchestrator.md` + rewritten — Phase 0 is now a clean-tree check + (`git status --porcelain` must be empty), records + `start_sha` informationally (not as reset target), refuses to + proceed on a dirty tree. All `git commit` invocations removed. + Phase 4 (journal) and Phase 5 (stats) write to the working tree + via the Write tool, no commit. End-report Branch-field replaced + by `Working tree: dirty (N files)` and `(uncommitted)` markers + on file paths. +- disc.1.3: `skills/implement/agents/ailang-implementer.md`, + `ailang-tester.md` — commit steps in The Process removed. + Red-Flag "commit on red tests" replaced by the broader "never + commits, ever". Self-review now operates on `git diff HEAD` + with `git checkout -- ` for undo. +- disc.1.4: `skills/implement/agents/ailang-spec-reviewer.md`, + `ailang-quality-reviewer.md` — Carrier fields `pre_task_sha` / + `head_sha` replaced by `diff_command` (default `git diff HEAD`). + The full working-tree diff accumulates across tasks; reviewers + focus on the current task's footprint via the task block's file + list (or an optional `task_footprint_hint`). +- disc.1.5: `skills/brainstorm/SKILL.md` — Step 8 spec-commit + block removed; brainstorm writes the spec, user reviews, Boss + commits. The Step-7.5 retire-on-BLOCK procedure was rewritten + too: it now deletes the working-tree spec file (Bash `rm`, not + `git rm`, since the file was never committed) and appends a + roadmap entry; Boss commits the roadmap edit. +- disc.1.6: `skills/planner/SKILL.md` — Step 6 plan-commit + block removed; planner writes the plan, hand-off carries the + filepath, Boss commits. Plan-template tasks lose their + per-task "Step 5: Commit" — tasks are now 4 steps (write-failing- + test, verify-fail, write-impl, verify-pass) and leave work in + the working tree for the iter-level Boss commit. The "Bundle + Tasks 3 and 4" rationalisation reframed: tasks are units of + review, not units of commit. +- disc.1.7: `skills/debug/SKILL.md`, `skills/debug/agents/ailang-debugger.md` + — debugger writes the RED test to the working tree (uncommitted) + and hands off. The Boss chooses between two flows for + implement-mini: commit the RED separately for an audit-trail + before dispatching mini-mode (clean-tree mini gets the RED via + HEAD diff), or commit RED+GREEN together at the end (Boss + decides before dispatching). +- disc.1.8: `skills/fieldtest/SKILL.md`, + `skills/fieldtest/agents/ailang-fieldtester.md` — Phase 5 + commit block removed; fieldtester writes `.ailx` files, + `.ail.json` files, and the spec to the working tree; Boss + commits with the suggested subject + `fieldtest: examples, findings`. +- disc.1.9: `skills/docwriter/agents/ailang-docwriter.md` — + Iron Law extended with "YOU NEVER COMMIT"; Red-Flag added. + `skills/audit/SKILL.md` — Step 4 reframed to name the Boss as + the actor who commits tidy fixes / ratify baselines / clean + closes. Other audit-agent files (architect, bencher) had no + commit invocations and are unchanged in this dispatch. +- disc.1.10: `skills/README.md` — Conventions section gained + two new bullets ("Only the Boss commits", "main HEAD is + sacrosanct"). Skill-table Output column updated for implement, + docwriter, fieldtest, debug to say "uncommitted in the working + tree". `CLAUDE.md` Direction-freedom subsection rewritten + (recovery is no longer about reverting commits; it is about + discarding bad working-tree state). New + "Commit discipline and main-branch sanctity" subsection added, + stating both rules in CLAUDE.md form. + +## Concerns + +(empty) + +## Known debt + +- Three historical files describe the obsolete branch-per-iter + discipline: `docs/specs/2026-05-11-implement-orchestrator-agent.md`, + `docs/journals/2026-05-11-iter-pr.1.md`, + `docs/plans/2026-05-11-orchestrator-refactor.md`. They are + zeitliche records and are left intact; this journal entry is the + forward-pointer that supersedes them. A future tidy iter could + add "Superseded by" banners, but the journal-archive convention is + append-only history. +- The implement orchestrator's Phase 0 refuses to run on a dirty + tree. The first real dispatch under the new discipline may + surface friction around this (e.g. Boss prepared scratch files + before dispatch). Capture in that iter's journal. + +## Blocked detail + +(none — DONE) + +## Files touched + +- `CLAUDE.md` +- `skills/README.md` +- `skills/audit/SKILL.md` +- `skills/brainstorm/SKILL.md` +- `skills/debug/SKILL.md` +- `skills/debug/agents/ailang-debugger.md` +- `skills/docwriter/agents/ailang-docwriter.md` +- `skills/fieldtest/SKILL.md` +- `skills/fieldtest/agents/ailang-fieldtester.md` +- `skills/implement/SKILL.md` +- `skills/implement/agents/ailang-implement-orchestrator.md` +- `skills/implement/agents/ailang-implementer.md` +- `skills/implement/agents/ailang-quality-reviewer.md` +- `skills/implement/agents/ailang-spec-reviewer.md` +- `skills/implement/agents/ailang-tester.md` +- `skills/planner/SKILL.md` +- `docs/journals/2026-05-11-iter-disc.1.md` (this file) +- `docs/journals/INDEX.md` + +## Motivation + +On 2026-05-11 iter 23.4 (eq/ord prelude — Free-Fns) BLOCKED three +times. A retrospective brainstorm produced a corrected spec; the +implement-orchestrator was dispatched on the revised plan and +immediately BLOCKED at Phase 0 with a branch-state mismatch: an +existing `iter/23.4` branch carried prep2 + prep3 commits that +the spec falsely claimed lived on main. They had never been +fast-forwarded; they were stranded on the iter-branch when the +iter was abandoned. The grounding-check agent had passed the +spec because it verified main-behaviour-via-green-tests, not +git-reachability of named commit SHAs. + +The user identified the structural root cause: branch-per-iter +plus manual Boss-merge plus iter-stacking allows work to strand +on a branch that nobody integrates. The discipline correction is +this iter: + +- Drop the branch mechanic in implement entirely. +- Centralise commit authority on the Boss across every skill. +- Make main forward-only by policy: no reset, no revert, by + anyone. + +Per-task agent commits were eh too many (user phrasing: "es wird +eh viel zu viel commitet") — the new policy eliminates them as +a side-effect. + +## Forward pointer + +Step 5 of the 2026-05-11 recovery plan: re-attempt the eq/ord +prelude mono-pass unification (iter 23.4 in the corrected spec +`docs/specs/2026-05-11-23-eq-ord-prelude.md`), now under the +discipline this iter installs. A fresh plan is written first; +the implement-orchestrator is dispatched against it; the Boss +inspects + commits at the end. No branches, no agent commits. + +## Stats + +None — this iter was Boss-direct implementation (no orchestrator +dispatch; no stats file written). diff --git a/docs/journals/INDEX.md b/docs/journals/INDEX.md index 56a6d2a..8f6ae86 100644 --- a/docs/journals/INDEX.md +++ b/docs/journals/INDEX.md @@ -12,3 +12,4 @@ - 2026-05-11 — iter cadence: audit/fieldtest/docwriter cadence restructure → 2026-05-11-iter-cadence.md - 2026-05-11 — iter 23.4-prep: checker prerequisites for prelude free fns → 2026-05-11-iter-23.4-prep.md - 2026-05-11 — iter gc.1: grounding-check agent + brainstorm Step 7.5 → 2026-05-11-iter-gc.1.md +- 2026-05-11 — iter disc.1: boss-only commits + main-as-quarantine (no branches in implement) → 2026-05-11-iter-disc.1.md diff --git a/skills/README.md b/skills/README.md index 9f7b659..fbb9651 100644 --- a/skills/README.md +++ b/skills/README.md @@ -16,11 +16,11 @@ The system was bootstrapped on 2026-05-09. See |-------|---------|--------|------------| | [`brainstorm`](brainstorm/SKILL.md) | New milestone starting | `docs/specs/.md` | Hard-gate before plan | | [`planner`](planner/SKILL.md) | New iteration within an open milestone | `docs/plans/.md` | Hard-gate before implement | -| [`implement`](implement/SKILL.md) | Plan exists | Code + tests + per-task commits + per-iter journal entry | Standard iteration path | +| [`implement`](implement/SKILL.md) | Plan exists | Code + tests + per-iter journal entry, all uncommitted in the working tree | Standard iteration path | | [`audit`](audit/SKILL.md) | Milestone closing OR baseline drift suspected | Drift report + bench-regression report | **Mandatory** at milestone close | -| [`docwriter`](docwriter/SKILL.md) | API surface stabilized; rustdoc lag suspected | rustdoc updates in `///` and `//!` | No — Boss-dispatched only | -| [`fieldtest`](fieldtest/SKILL.md) | Boss-dispatched post-audit field test on a milestone that touched user-visible surface | 2-4 `.ailx` example fixtures + `docs/specs/-fieldtest-.md` | No — Boss-dispatched only | -| [`debug`](debug/SKILL.md) | Bug encountered (failing test, segfault, wrong stdout) | RED-test commit + cause analysis | **Mandatory RED-first** for any bug | +| [`docwriter`](docwriter/SKILL.md) | API surface stabilized; rustdoc lag suspected | rustdoc updates in `///` and `//!`, uncommitted in the working tree | No — Boss-dispatched only | +| [`fieldtest`](fieldtest/SKILL.md) | Boss-dispatched post-audit field test on a milestone that touched user-visible surface | 2-4 `.ailx` example fixtures + `docs/specs/-fieldtest-.md`, all uncommitted in the working tree | No — Boss-dispatched only | +| [`debug`](debug/SKILL.md) | Bug encountered (failing test, segfault, wrong stdout) | RED-test in the working tree (uncommitted) + cause analysis | **Mandatory RED-first** for any bug | ## Pipeline @@ -152,6 +152,20 @@ dispatch can find them by `subagent_type`: ## Conventions +- **Only the Boss commits.** No skill agent — implementer, + brainstormer, planner, debugger, fieldtester, docwriter, + architect, bencher — performs `git commit`. Agents write their + artefacts (spec, plan, code, tests, fixtures, rustdoc edits, RED + tests, journal files, stats files, updated baselines) to the + working tree as unstaged changes. The Boss inspects with + `git status` / `git diff` and commits when there is something + consistent to commit. Per-task or per-phase commits are not a + goal; the iter (or the cohesive change) is the unit of commit. +- **main HEAD is sacrosanct.** No actor (Boss or agent) runs + `git reset` or `git revert` on main. main moves forward only via + Boss commits; bad work stays in the working tree where it is + still discardable via `git checkout -- ` (Boss-side, not + on main HEAD). - **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. diff --git a/skills/audit/SKILL.md b/skills/audit/SKILL.md index 1f35207..e8e9f43 100644 --- a/skills/audit/SKILL.md +++ b/skills/audit/SKILL.md @@ -82,12 +82,17 @@ the orchestrator (me). Each item is one of: The orchestrator picks per item: - **fix path:** dispatch `planner` + `implement` for a tidy iteration. - Commit pattern: `iter .tidy: `. -- **ratify path:** `--update-baseline` + JOURNAL entry. The entry - names the iter that moved the metric and the language reason - (semantic cost, intentional trade-off). + The implement skill leaves the fix in the working tree; the Boss + commits per the iter's pattern (suggested subject: + `iter .tidy: `). +- **ratify path:** run `--update-baseline` on the firing script, then + write a JOURNAL entry naming the iter that moved the metric and + the language reason (semantic cost, intentional trade-off). Both + artefacts (the updated baseline JSON and the JOURNAL entry) sit in + the working tree; the Boss commits them together. - **carry-on path:** no commit needed; JOURNAL closes the milestone - with `Milestone- tidy (clean)`. + with `Milestone- tidy (clean)` — that JOURNAL entry is itself a + Boss-committed working-tree edit. ## Handoff Contract diff --git a/skills/brainstorm/SKILL.md b/skills/brainstorm/SKILL.md index 7afe571..de19fbb 100644 --- a/skills/brainstorm/SKILL.md +++ b/skills/brainstorm/SKILL.md @@ -175,37 +175,43 @@ interpretation: **Failure-mode procedure (no-override `BLOCK`):** -```bash -git rm docs/specs/.md -# Append a roadmap entry pointing forward to a future re-brainstorm: -# - [ ] **[]** -# - context: -# - depends on: -$EDITOR docs/roadmap.md # add the entry under the appropriate priority bucket -git add docs/roadmap.md -git commit -m "spec: retire — depends on " -``` +1. Delete the just-written spec file from the working tree + (`rm docs/specs/.md` — a Bash-level delete on the + working tree, NOT `git rm`; the file was never committed). +2. Append a roadmap entry to `docs/roadmap.md` pointing forward to a + future re-brainstorm, under the appropriate priority bucket: + + ```markdown + - [ ] **[]** + - context: + - depends on: + ``` + +3. Tell the user the spec was retired and which roadmap entry was + added. The user / Boss commits the roadmap edit (suggested + commit subject: `spec: retire — depends on + `). After the failure-mode procedure runs, the brainstorm session ENDS. There is no Step 8, no Step 9. The idea is parked until the dependency ships, at which point a fresh brainstorm session re-derives the spec from scratch. -### Step 8 — Commit + user-review gate +### Step 8 — User-review gate -```bash -git add docs/specs/.md -git commit -m "spec: " -``` +The spec sits in the working tree as an unstaged file. Tell the user: -Tell the user: +> Spec written to `` (uncommitted). Please review it and let +> me know if you want changes before we start the implementation +> plan. The Boss will commit it once you approve. -> Spec written and committed to ``. Please review it and -> let me know if you want to make any changes before we start the -> implementation plan. +Wait for the user's response. If they request changes, edit the +file in place (still uncommitted) and re-run Step 7. Only proceed +to the next step after approval. -Wait for the user's response. If they request changes, make them -and re-run Step 7. Only proceed to the next step after approval. +The Boss commits the approved spec after the user signs off +(suggested commit subject: `spec: `). The +brainstorm skill does not perform the commit itself. ### Step 9 — Hand off to `planner` @@ -224,7 +230,7 @@ Hand off carries: | user → `brainstorm` | new milestone request | | `brainstorm` → `ailang-grounding-check` (Step 7.5) | `spec_path` + `iteration_scope` | | `brainstorm` → `planner` (Step 9, on PASS or overridden BLOCK) | path to spec + iteration scope | -| `brainstorm` → roadmap (Step 7.5, on no-override BLOCK) | `depends on:` entry, spec deleted | +| `brainstorm` → roadmap (Step 7.5, on no-override BLOCK) | `depends on:` entry added to `docs/roadmap.md` in the working tree, spec file deleted from the working tree; Boss commits the roadmap edit | ## Common Rationalisations diff --git a/skills/debug/SKILL.md b/skills/debug/SKILL.md index 92df54b..bd467e8 100644 --- a/skills/debug/SKILL.md +++ b/skills/debug/SKILL.md @@ -1,6 +1,6 @@ --- name: debug -description: Use when a bug surfaces — failing test, segfault, wrong stdout, panic, or any observable misbehaviour. Bug fixes are RED-first TDD; no fix is attempted before the failing test is committed. Mandatory for any bug, including ones that look trivial. +description: Use when a bug surfaces — failing test, segfault, wrong stdout, panic, or any observable misbehaviour. Bug fixes are RED-first TDD; no fix is attempted before the failing test exists in the working tree. Mandatory for any bug, including ones that look trivial. --- # debug — RED-first bug diagnoser @@ -57,10 +57,17 @@ Dispatch `ailang-debugger` with: | `repro_known` | One-line repro if known, otherwise the agent finds one | | `recent_iter` | Iteration that last touched the suspected area (often `git log` tail) | -The agent commits the RED test as `test: red for ` and reports -the handoff carrier for `implement` mini-mode. The agent does NOT write -the fix — splitting RED (this skill) and GREEN (`implement` mini-mode) -across two dispatches keeps the diagnosis honest. +The agent writes the RED test to the working tree (uncommitted) and +reports the handoff carrier for `implement` mini-mode. The agent does +NOT commit anything, and does NOT write the fix — splitting RED (this +skill) and GREEN (`implement` mini-mode) across two dispatches keeps +the diagnosis honest. The Boss decides whether to commit the RED test +as a separate audit-trail commit before dispatching `implement` mini- +mode, or to hand the dirty working tree directly to mini-mode (the +mini-mode orchestrator's Phase-0 clean-tree check will refuse the +latter — so for an audit-trail-preserving flow the Boss commits the +RED test first; for a streamlined-fix flow the Boss commits the +combined RED+GREEN at the end of mini-mode). ## Handoff Contract @@ -82,7 +89,8 @@ scope for the bug-fix iteration and gets queued for a separate one. Common Rationalisations table, and the Red Flags list. The orchestrator does not execute these phases directly. - **Hand-off target:** `skills/implement/SKILL.md` — runs the GREEN - side after the RED test is committed. + side after the Boss has decided whether to commit the RED test + separately or as part of the final fix commit. - **Project source:** former CLAUDE.md "Bug fixes — TDD, always" section is now superseded by this file; CLAUDE.md keeps a one-line pointer. diff --git a/skills/debug/agents/ailang-debugger.md b/skills/debug/agents/ailang-debugger.md index aa89f34..14756c1 100644 --- a/skills/debug/agents/ailang-debugger.md +++ b/skills/debug/agents/ailang-debugger.md @@ -14,11 +14,14 @@ segfault, wrong stdout, panic, observable misbehaviour. ## What this role is for -Bug diagnosis is RED-first. Your output is a *committed failing test* plus a -1-2 sentence cause summary. The fix itself is `skills/implement`'s job, run -in mini-mode. Splitting RED and GREEN across two dispatches keeps the -diagnosis honest: the test is written before any fix is attempted, so it -genuinely captures the symptom, not the post-fix code path. +Bug diagnosis is RED-first. Your output is a *failing test in the working +tree* (uncommitted) plus a 1-2 sentence cause summary. The fix itself is +`skills/implement`'s job, run in mini-mode. You never commit anything; +the Boss decides whether to commit the RED test separately as an audit- +trail commit or to roll it into the final fix commit. Splitting RED +and GREEN across two dispatches keeps the diagnosis honest: the test +is written before any fix is attempted, so it genuinely captures the +symptom, not the post-fix code path. ## Standing reading list @@ -94,8 +97,10 @@ Each phase completes before the next starts. - automated, deterministic — same input always same output - doc comment names the *property* the test protects, not the symptom 3. Run the test. Confirm it fails with the symptom the carrier described. -4. Commit the failing test as a separate commit: - `git commit -m "test: red for "`. +4. Leave the failing test in the working tree as an unstaged change. + You do NOT commit. The Boss decides commit shape; the suggested + subject if the Boss elects to commit the RED separately is + `test: red for `. ### Phase 4 — Hand off @@ -120,9 +125,10 @@ orchestrator escalates. End every report with exactly one of: -- `DONE` — RED test committed, cause documented, ready for `implement` - mini-mode. Provide the handoff carrier (see Output format). -- `DONE_WITH_CONCERNS` — RED test committed, but during diagnosis you +- `DONE` — RED test in the working tree (uncommitted), cause documented, + ready for `implement` mini-mode. Provide the handoff carrier (see + Output format). +- `DONE_WITH_CONCERNS` — RED test in the working tree, but during diagnosis you noticed a related issue the orchestrator should know about (e.g. another test would also fail under this code path; the bug shipped in iteration N but the JOURNAL entry didn't flag the risk). @@ -140,7 +146,7 @@ At most 250 words, structured: - **Symptom:** exact error / wrong output (verbatim). - **Repro:** the one-line command. - **Cause:** file + function + why (1-2 sentences). -- **RED test:** path to the new test + commit SHA. +- **RED test:** path to the new test in the working tree (uncommitted). - **Handoff carrier for `implement` mini-mode:** - `red_test_path`: absolute path - `cause_summary`: 1-2 sentences @@ -164,7 +170,7 @@ At most 250 words, structured: | "I'll write the fix and the test together" | Test-after proves nothing about whether the test would have caught the pre-fix bug. RED before GREEN — always. | | "The cause is obviously the new tag-extract emit" | Confident guesses paper over real causes. Phase 1 is data-flow tracing, not guessing. | | "Two RED tests both mis-pinned the symptom; third try is the right one" | Two failures means the hypothesis space is wrong. Phase 4.5 fires now, not after the third try. | -| "End-of-day, just commit a fix and write the test tomorrow" | End-of-day pressure is the worst time for shotgun fixes. Clean tree + open bug > three speculative half-fixes. | +| "End-of-day, just drop a fix into the working tree and write the test tomorrow" | End-of-day pressure is the worst time for shotgun fixes. Clean tree + open bug > three speculative half-fixes. Diagnosis is RED-first; the fix is a separate dispatch. | | "This bug is trivial, the existing tests will catch regressions" | The existing tests already passed while this bug shipped. By definition they don't cover it. | | "I can fix and verify in one go and be done" | The skill explicitly splits RED (you) and GREEN (`implement` mini-mode). Don't collapse them; the split is the whole point. | @@ -177,4 +183,4 @@ At most 250 words, structured: - "Pattern says X but I'll adapt it differently" - *"One more hypothesis"* (when ≥ 2 already failed) - About to apply ANY edit outside the new test file -- About to commit a fix in this dispatch +- About to run `git commit` (anywhere, ever — you never commit) diff --git a/skills/docwriter/agents/ailang-docwriter.md b/skills/docwriter/agents/ailang-docwriter.md index 0bcdf72..bcc1733 100644 --- a/skills/docwriter/agents/ailang-docwriter.md +++ b/skills/docwriter/agents/ailang-docwriter.md @@ -56,6 +56,7 @@ If `crate_scope` is empty, return `NEEDS_CONTEXT`. NO API CHANGES. NO RENAMES. NO NEW PUB EXPORTS. NO EDITS IN docs/. RUSTDOC ONLY. FINDINGS GET REPORTED, NOT FIXED. EVERY pub ITEM YOU TOUCH MUST EITHER BE DOCUMENTED OR THE WARNING CLEARED. +YOU NEVER COMMIT. RUSTDOC EDITS LIVE IN THE WORKING TREE; THE BOSS COMMITS. ``` ## Documentation rules (binding) @@ -142,5 +143,6 @@ At most 200 words, structured: - About to edit `docs/DESIGN.md` or any file under `docs/journals/` / `docs/journal-archive.md` - About to write a doc comment that contradicts the function body - About to skip the `cargo doc --no-deps` re-run after edits +- About to run `git commit` (anywhere, ever — you never commit) - About to report `DONE` while one of the three verification commands is red diff --git a/skills/fieldtest/SKILL.md b/skills/fieldtest/SKILL.md index fe45e6f..260c4a6 100644 --- a/skills/fieldtest/SKILL.md +++ b/skills/fieldtest/SKILL.md @@ -80,9 +80,10 @@ agent compiler-internal hints in the carrier. Dispatch `ailang-fieldtester` with the carrier from the Handoff Contract below. The agent picks 2-4 examples (one per axis the milestone touched), implements them in `.ailx`, runs them through the -public `ail` CLI, classifies findings, writes the spec, and commits -both fixtures and spec in one commit -(`fieldtest: examples, findings`). +public `ail` CLI, classifies findings, and writes the spec. All +artefacts (fixtures + spec) stay in the working tree as unstaged +changes; the Boss commits them after reviewing the report (suggested +commit subject: `fieldtest: examples, findings`). Two to four examples is the right size. One is too few (no signal on variation); five is too many for one report to stay readable. diff --git a/skills/fieldtest/agents/ailang-fieldtester.md b/skills/fieldtest/agents/ailang-fieldtester.md index 11b5353..84e4c89 100644 --- a/skills/fieldtest/agents/ailang-fieldtester.md +++ b/skills/fieldtest/agents/ailang-fieldtester.md @@ -161,15 +161,14 @@ Each finding is exactly one of: Borderline items get split into two findings (one per class), not merged. -### Phase 5 — Write the spec, commit, hand back +### Phase 5 — Write the spec, hand back Write `docs/specs/-fieldtest-.md` using the -spec structure below. Then: - -```bash -git add examples/fieldtest/*.ail* docs/specs/*-fieldtest-*.md -git commit -m "fieldtest: examples, findings" -``` +spec structure below. Leave all artefacts (the `.ailx` files, the +`.ail.json` files, and the spec file) in the working tree as +unstaged changes. You do NOT commit — the Boss commits after +reading the end-report (suggested commit subject: +`fieldtest: examples, findings`). Report `DONE` with the carrier (see Output format). @@ -211,10 +210,11 @@ A short table mapping finding → action (`debug` / `planner` / `ratify` / End every report with exactly one of: -- `DONE` — examples committed, spec committed, findings classified, - recommendations stated. The orchestrator dispatches the follow-ups - (debug for bugs, plan/brainstorm for friction/spec_gap). -- `DONE_WITH_CONCERNS` — examples and spec committed, but during the +- `DONE` — examples written to the working tree, spec written to the + working tree, findings classified, recommendations stated. The + orchestrator dispatches the follow-ups (debug for bugs, + plan/brainstorm for friction/spec_gap) after committing. +- `DONE_WITH_CONCERNS` — examples and spec written, but during the run you noticed something orthogonal worth flagging (e.g. a separate per-iter journal entry's claim is contradicted by what you saw, but only as a side observation). @@ -240,8 +240,9 @@ At most 350 words, structured: `working → carry-on`. - **Concerns / blockers:** if applicable. -The full text of the spec is in the committed file; do NOT reproduce -it in the report. The orchestrator reads the file. +The full text of the spec is in the spec file in the working tree; +do NOT reproduce it in the report. The orchestrator reads the file +before committing. ## What you DO NOT ship @@ -254,10 +255,11 @@ it in the report. The orchestrator reads the file. - A `friction` finding without a 1-line recommendation. Every finding is actionable or it isn't a finding. - An "all-clean" report on a milestone that touched user-visible - surface without at least 2 examples committed. The empty report is - a valid status only if no examples were applicable — and that - itself is a `spec_gap` finding ("milestone shipped surface X but - no real-world task naturally exercises it" is itself the finding). + surface without at least 2 examples in the working tree. The empty + report is a valid status only if no examples were applicable — and + that itself is a `spec_gap` finding ("milestone shipped surface X + but no real-world task naturally exercises it" is itself the + finding). ## Common Rationalisations @@ -283,7 +285,8 @@ it in the report. The orchestrator reads the file. - About to silently shrink an example to make it compile - About to merge a `bug` and a `friction` into one finding - About to attempt a fix in this dispatch -- About to write the report without committing the examples first +- About to run `git commit` (anywhere, ever — you never commit) +- About to write the report without writing the examples to the working tree first - About to claim "all working" without recording what was reached for and what was easy (a `working` finding still requires a paragraph) diff --git a/skills/implement/SKILL.md b/skills/implement/SKILL.md index cd1c0e3..e861ecb 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 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. +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/`. 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/`, 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/` (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/:docs/journals/-iter-.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/`. 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/-iter-.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-.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/`. -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/`. 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/.md` (+ optional `task_range`) | | from `debug` | RED-test path + cause summary + minimal-fix constraint | -`implement` produces: a feature branch `iter/` carrying -per-task commits, a per-iter journal file (`docs/journals/.md`), -and a stats file (`bench/orchestrator-stats/.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/.md`), and +the stats file (`bench/orchestrator-stats/.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 `` 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 `` 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/` 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. diff --git a/skills/implement/agents/ailang-implement-orchestrator.md b/skills/implement/agents/ailang-implement-orchestrator.md index c2b19ce..d4c89e0 100644 --- a/skills/implement/agents/ailang-implement-orchestrator.md +++ b/skills/implement/agents/ailang-implement-orchestrator.md @@ -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/`), 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-"` (mini). Used for branch name, scratch dir, journal filename, stats filename, commit subjects | +| `iter_id` | e.g. `"ct.2.3"` (standard) or `"bugfix-"` (mini). Used for scratch dir, journal filename, stats filename — NOT a branch name (there is no branch) | | `plan_path` | (standard only) `docs/plans/.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/`, 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/` already exists locally - (Boss-side repair re-dispatch): `git switch iter/`. - Otherwise: `git switch -c iter/ 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/`. +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/`. ### Phase 1 — Load context (mode-dependent) @@ -133,17 +142,15 @@ 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. - -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//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 : 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 **Date:** YYYY-MM-DD -**Branch:** iter/ +**Started from:** **Status:** DONE | PARTIAL | BLOCKED **Tasks completed:** of ## 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 .1: -- iter .2: +- iter .1: +- iter .2: - ... ## Concerns @@ -236,21 +246,16 @@ not the iter's plan date). Template: -## Commits +## Files touched -.. + ## Stats bench/orchestrator-stats/-iter-.json ``` -Commit on the branch: - -```bash -git add docs/journals/.md -git commit -m "iter : 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/.json -git commit -m "iter : 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: -Branch: iter/ +Started from: Tasks completed: of - - - - + - + - ... -Journal file: docs/journals/-iter-.md (on branch) -Stats: bench/orchestrator-stats/-iter-.json (on branch) -Commits: .. +Working tree: dirty (N files changed) +Journal file: docs/journals/-iter-.md (uncommitted) +Stats: bench/orchestrator-stats/-iter-.json (uncommitted) +Files touched: Tests: green, red E2E coverage: 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. diff --git a/skills/implement/agents/ailang-implementer.md b/skills/implement/agents/ailang-implementer.md index 816bf22..18dede9 100644 --- a/skills/implement/agents/ailang-implementer.md +++ b/skills/implement/agents/ailang-implementer.md @@ -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 .: ` or, in - `mini` mode, `fix: `). -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 -- ` 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` diff --git a/skills/implement/agents/ailang-quality-reviewer.md b/skills/implement/agents/ailang-quality-reviewer.md index 70b9be3..ca51222 100644 --- a/skills/implement/agents/ailang-quality-reviewer.md +++ b/skills/implement/agents/ailang-quality-reviewer.md @@ -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 ..` — 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 diff --git a/skills/implement/agents/ailang-spec-reviewer.md b/skills/implement/agents/ailang-spec-reviewer.md index 5b26040..88219b8 100644 --- a/skills/implement/agents/ailang-spec-reviewer.md +++ b/skills/implement/agents/ailang-spec-reviewer.md @@ -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//task-.md`) — same file the implementer received. Read this file as your first action. | -| `diff` | The implementer's diff, either inline or as `git diff ..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 ..`. 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. diff --git a/skills/implement/agents/ailang-tester.md b/skills/implement/agents/ailang-tester.md index fb8b7b8..39f5a22 100644 --- a/skills/implement/agents/ailang-tester.md +++ b/skills/implement/agents/ailang-tester.md @@ -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 .: e2e for `). -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 diff --git a/skills/planner/SKILL.md b/skills/planner/SKILL.md index 5b83b13..266b82a 100644 --- a/skills/planner/SKILL.md +++ b/skills/planner/SKILL.md @@ -15,9 +15,12 @@ that will be created or modified, and decomposes work into bites small enough that a subagent can execute one in 2-5 minutes without making judgement calls outside its remit. -Plans live at `docs/plans/.md`, the header -references the parent spec, and the commit-per-task pattern -matches the existing JOURNAL style. +Plans live at `docs/plans/.md` and the header references +the parent spec. The plan decomposes work into tasks; each task is +the unit of review (spec-compliance and quality gates inside +`implement`), not the unit of commit. Commits are a Boss-only +decision taken at the end of the iter against the full working-tree +diff. ## When to Use / Skipping @@ -133,15 +136,11 @@ fn function(input: T) -> U { Run: `cargo test --workspace -p test_` Expected: PASS - -- [ ] **Step 5: Commit** - -```bash -git add -git commit -m "iter .: " -``` ``` +No `git commit` step. Implement tasks leave their work in the +working tree; the Boss commits at the end of the iter. + ### Step 4 — Plan header Every plan starts with this header: @@ -165,7 +164,7 @@ Every plan starts with this header: ### Step 5 — Self-review -Before committing the plan, run this checklist inline: +Before handing the plan off, run this checklist inline: 1. **Spec coverage:** every spec section has a task that implements it. If a section has no task, add one. @@ -177,18 +176,21 @@ Before committing the plan, run this checklist inline: and `clearFullLayers()` in Task 7 is a bug. 4. **Step granularity:** every step is 2-5 minutes. If a step is "implement the parser", split it. +5. **No commit steps:** task templates must not contain + `git commit` instructions. Implement tasks leave work in the + working tree. -Fix issues inline. No need to re-review — fix and commit. +Fix issues inline. -### Step 6 — Commit and hand off +### Step 6 — Hand off -```bash -git add docs/plans/.md -git commit -m "plan: " -``` +The plan sits in the working tree as an unstaged file at +`docs/plans/.md`. Hand off to `implement` with: path to +the plan file + optional task focus ("only Tasks 1-3 this run"). -Hand off to `implement` with: path to the plan file + optional -task focus ("only Tasks 1-3 this run"). +The Boss commits the plan when handing it forward (suggested +commit subject: `plan: `). The planner skill +does not perform the commit itself. ## Handoff Contract @@ -203,7 +205,7 @@ task focus ("only Tasks 1-3 this run"). | Excuse | Reality | |--------|---------| | "TBD in step 4 lets me ship the plan tonight, fill in tomorrow" | Half-decided plans get re-litigated mid-iteration, costing more than the night's sleep saved. Make the decision tonight or close the laptop. | -| "Bundle Tasks 3 and 4, both small, single commit" | The red-green-refactor cycle is the unit of verification. Bundled commits make bisection lie. If 3 and 4 are inseparable, they're one task — rewrite the decomposition. | +| "Bundle Tasks 3 and 4, both small" | Tasks are the unit of review (spec-check + quality-check fire once per task). Bundling collapses two reviews into one and hides the smaller change inside the bigger one. If 3 and 4 are inseparable, they're one task — rewrite the decomposition. | | "Spec is recent, I wrote it, plan from memory" | Memory diverges from disk. 15 minutes of re-reading is the cheapest insurance in the cycle. | | "Step 5 'implement the parser' is fine, I'll detail it at execution time" | Then it's not a step, it's a wish. Steps are bite-sized OR the plan isn't done. | | "Task 7 is similar to Task 4, just say so" | The executor may read tasks out of order. Repeat the code. |