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.
+12 -9
View File
@@ -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
+15 -11
View File
@@ -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.
+8 -5
View File
@@ -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