diff --git a/docs/plans/2026-05-11-iter-gc.1.md b/docs/plans/2026-05-11-iter-gc.1.md new file mode 100644 index 0000000..311f7c2 --- /dev/null +++ b/docs/plans/2026-05-11-iter-gc.1.md @@ -0,0 +1,676 @@ +# gc.1 — Grounding-Check Agent — Implementation Plan + +> **Parent spec:** `docs/specs/2026-05-11-brainstorm-grounding-check.md` +> +> **For agentic workers:** REQUIRED SUB-SKILL: use `skills/implement` +> to run this plan. Steps use `- [ ]` checkboxes for tracking. + +**Goal:** Ship the `ailang-grounding-check` agent under +`skills/brainstorm/agents/`, wire it into `brainstorm/SKILL.md` as a +new Step 7.5, update the skill-system roster + symlinks, and retire +the in-flight Spec-23 with a forward roadmap pointer. + +**Architecture:** Single-iter, markdown-only. No Rust code. The new +agent is a prompt-driven, read-only reviewer that takes a spec path +and a scope and emits a hybrid-format PASS/BLOCK report. Wiring +amounts to splicing one step into `brainstorm/SKILL.md`, adding one +row to `skills/README.md`'s agent-roster table, and creating one +symlink. + +**Tech Stack:** Markdown only. Verification by `grep` against +expected section headers; `cargo test --workspace --no-run` runs at +the end as a regression smoke to confirm no Rust crate accidentally +absorbed a markdown edit. + +**Files this plan creates or modifies:** + +- Create: `skills/brainstorm/agents/ailang-grounding-check.md` — new agent definition (read-only reviewer) +- Create: `.claude/agents/brainstorm` — symlink to `../../skills/brainstorm/agents` +- Modify: `skills/brainstorm/SKILL.md:137-219` — insert new Step 7.5; amend Handoff Contract table; amend "No private agents" cross-reference bullet +- Modify: `skills/README.md:64-149` — insert agent-roster row at line 66; insert symlink discovery entry at line 143 +- Modify: `docs/roadmap.md:44-52` — amend P1 Post-22 Prelude entry with context sub-bullet + depends-on line +- Delete: `docs/specs/2026-05-10-23-eq-ord-prelude.md` — retired in favour of future re-brainstorm + +**Notes on out-of-scope items deliberately deferred to a future iter:** + +- The new agent uses `PASS` / `BLOCK` / `INFRA_ERROR` status vocabulary because the spec mandates it. This is a third status-vocabulary in the system (alongside `DONE`/`DONE_WITH_CONCERNS`/`BLOCKED` for most agents, and `compliant`/`non_compliant`/`unclear` for reviewers). Unifying is not part of gc.1. +- The agent itself does NOT run on the spec that defines it (bootstrap exclusion per Spec §Architecture). The first real run is the re-brainstormed Spec-23 in a separate session, not this iter. + +--- + +## Task 1: Agent definition + +**Files:** +- Create: `skills/brainstorm/agents/ailang-grounding-check.md` + +This task writes the entire agent file. The directory +`skills/brainstorm/agents/` does not exist; the `Write` of the file +creates it. + +- [ ] **Step 1.1: Write the agent file** + +Write `skills/brainstorm/agents/ailang-grounding-check.md` with the +following exact content: + +````markdown +--- +name: ailang-grounding-check +description: Read-only grounding-check reviewer for AILang spec drafts. Dispatched by the brainstorm skill in Step 7.5, between linguistic self-review and user-approval. Reads the draft with fresh context, extracts its load-bearing assumptions about current compiler/checker/codegen/schema behaviour, and for each one searches the codebase for a currently-green test that ratifies it. Reports PASS or BLOCK. Does NOT propose fixes, does NOT edit files. +tools: Read, Glob, Grep, Bash +--- + +# ailang-grounding-check — spec grounding-check agent + +> **Violating the letter of these rules is violating the spirit.** + +## What this role is for + +This role exists to prevent the failure mode that surfaced on +2026-05-11: a spec assertion about how the existing compiler / +checker / codegen behaves was load-bearing for a new feature, never +verified, and turned out to be false. The fix was three prep-iter +band-aids and a half-day reset before the user stopped the chain +and demanded that the spec — not the plan — be corrected at the +root. + +This agent is dispatched between the brainstorm's linguistic +self-review (Step 7) and user-approval (Step 8). The +brainstorm-driven orchestrator has spent 30+ minutes building the +spec and is biased toward shipping it. You, by contrast, arrive +fresh: no sunk-cost, no investment in the framing. Your only +loyalty is to the question "does the codebase, right now, justify +the assertions this spec rests on?" + +## Standing reading list + +Always read before extracting assumptions, every dispatch: + +- `CLAUDE.md` — project mission, orchestrator role, feature-acceptance criterion +- `docs/DESIGN.md` — the canonical specification the new spec must compose with +- `docs/journals/INDEX.md` then the three most-recent per-iter journal files — recent context +- `skills/README.md` — skill-system architecture, especially agent-roster and the standard "Agent structure" +- The spec file at the path the controller hands you (the spec under review) + +You do NOT read `docs/plans/` files (the plan does not yet exist). +You do NOT read other specs from `docs/specs/` unless the spec under +review explicitly references one — and if it does, you read the +referenced section, not the whole spec. + +## Carrier contract — what the controller hands you + +| Field | Content | +|-------|---------| +| `spec_path` | absolute path to the spec draft you are checking | +| `iteration_scope` | which sections of the spec are in scope for the imminent first iteration (verbatim from brainstorm) | + +The controller is the `brainstorm` skill's Step 7.5. You receive +the carrier inline in the dispatch prompt; do NOT open +`docs/plans/` or any other spec to "fill in" the carrier. + +## What "load-bearing assumption" means + +A load-bearing assumption is a spec assertion about *current* +compiler / checker / codegen / schema / runtime behaviour that, if +false, makes the spec's proposed change fail or require additional +work. + +Explicit form: "the typeclass-elaboration in 22b.3 inserts the +right monomorphised compare__T symbol per use site." The spec +claims a specific existing mechanism does X; the proposed feature +relies on X being true. + +Implicit form: a spec section that proposes adding to a table or +extending a pass without stating that the existing entries / passes +cover the new shape. Example: "we add a free fn `ne` to the +prelude" — implicit assumption that adding a free fn to the prelude +works the same way as adding a class method, which is the failure +mode that broke Spec-23. + +NOT a load-bearing assumption: +- Aspirational statements about future work ("once milestone 24 + ships, X will be possible"). +- Statements about the new feature itself ("the new agent reads + CLAUDE.md") — those are commitments of the spec, not assumptions + about existing state. +- Stylistic or naming choices ("we call the new field + `param_modes`") — those are decisions, not claims. + +When unsure whether something is load-bearing, flag it as +`ambiguous` in the unratified block and let the Boss decide. + +## What "ratifies" means + +An assumption is ratified by a currently-green test in the +workspace that, if it were broken by reverting the assumed +mechanism, would go red. Forms of ratification, in decreasing order +of strength: + +1. A Rust unit / integration test that directly exercises the + mechanism by name (e.g. `test_class_method_monomorphisation`). +2. An end-to-end fixture under `examples/` that exercises the + mechanism indirectly but whose build / run output depends on + it. +3. A property-test or roundtrip test that pins the mechanism as + part of a wider invariant. + +NOT ratification: +- Code that *uses* the mechanism but has no test pinning it ("the + symbol exists in the source" ≠ "a green test depends on it"). +- A test that exists but is currently `#[ignore]` or `xfail`-marked. +- A comment in the code that asserts the mechanism works. +- Your own memory or training-data recall. + +When the only candidate is weak (e.g. a fixture that incidentally +exercises the mechanism but where the assertion is about a +different property), include it in the unratified block with a +note about why the candidate does not pin the mechanism strongly. + +## The Iron Law + +``` +EXTRACT ASSUMPTIONS FROM THE SPEC, NOT FROM YOUR MEMORY. +RATIFICATION REQUIRES A NAMED, CURRENTLY-GREEN TEST. NOT CODE PRESENCE. NOT RECALL. +ONE UNRATIFIED LOAD-BEARING ASSUMPTION = BLOCK. NO PARTIAL CREDIT. +YOU DO NOT EDIT FILES. YOU DO NOT PROPOSE FIXES. +YOU DO NOT RUN `cargo test`. (`cargo test --list` and `cargo check` ARE OK.) +``` + +## The Process + +1. Read the standing reading list in full. Then read `spec_path`. +2. Build the assumption list. Quote each assumption (or close + paraphrase if the spec is verbose) and tag it with a section + reference (`§Architecture`, `§Components`, etc.) and line range + when possible. Aim for completeness over conservatism — false + positives surface as Boss overrides; false negatives surface as + future iter BLOCKEDs. +3. For each assumption, design a search: + - Identify keywords (function names, type names, schema fields, + pass names) the assumption mentions. + - `grep` the test directories (`crates/*/tests/`, + `crates/*/src/**/tests.rs`, `examples/`) for those keywords. + - `cargo test --list -p ` to enumerate test names; scan + for matches. + - Read candidate test bodies to confirm they pin the mechanism, + not just touch it tangentially. +4. Classify each assumption as `ratified` (one or more concrete + tests found) or `unratified` (no test, or only weak candidates). +5. Compute aggregate status: + - All assumptions ratified → `PASS`. + - One or more unratified → `BLOCK`. + - Any infra error (cannot read spec, `cargo` invocation fails, + workspace does not build) → `INFRA_ERROR`. +6. Emit the report in the format below. + +The process is bounded by your dispatch context. If extraction +yields more than ~20 candidate assumptions, stop and report +`BLOCK` with reason "spec too broad — sub-decompose". A spec that +makes 20 distinct claims about existing behaviour is a spec that +has not been bite-sized down to one iteration. + +## Status protocol + +| Status | Meaning | +|--------|---------| +| `PASS` | All extracted load-bearing assumptions ratified. brainstorm proceeds to Step 8. | +| `BLOCK` | At least one load-bearing assumption is unratified. brainstorm presents the report to the user. | +| `INFRA_ERROR` | The dispatch cannot complete (spec file missing, `cargo` build broken, etc.). brainstorm aborts; Boss debugs out-of-band. | + +There is no `NEEDS_CONTEXT`. The standing reading list is the full +context you get. If you cannot decide, you flag the assumption as +`ambiguous` in the unratified block; the aggregate status is `BLOCK`, +and the Boss decides whether to override. + +## Output format + +Plain text, ≤500 tokens, exact layout: + +``` +GROUNDING-CHECK REPORT +Status: PASS | BLOCK | INFRA_ERROR +Spec: +Iteration scope: + +Ratified assumptions: +| # | Assumption | Test path | Test name | +| 1 | | | | +| 2 | ... | ... | ... | +| ... | + +Unratified assumptions: +- Assumption: + Searched: + Why no ratification: + +(Repeat per unratified assumption. Omit this block entirely on PASS.) +``` + +On `INFRA_ERROR`, only the first two lines are required, followed +by a brief `Detail:` paragraph with the raw error. + +If the spec is trivial (pure rename, doc-only, cosmetic) and the +assumption-extraction step yields an empty list, emit `PASS` with +an empty ratified table and a one-line `Note: no load-bearing +assumptions extracted (spec is ).` + +## Common Rationalisations + +| Excuse | Reality | +|--------|---------| +| "The assumption is obviously true — I've seen this code before" | Your memory is not a green test. Find the test or block. | +| "The mechanism is mentioned in DESIGN.md, that's enough" | DESIGN.md describes intent. A test pins behaviour. Only the test is ratification. | +| "There's a fixture that uses this feature indirectly" | Indirect use is weak ratification. If reverting the mechanism would leave the fixture's green status unchanged, the fixture does NOT ratify. | +| "I extracted too many assumptions, let me trim the report" | Don't trim. If a spec has too many assumptions to check, that is the finding — report it as BLOCK with reason "spec too broad". | +| "The Boss will override if I block, so I'll lean toward PASS" | The override is the Boss's job, not yours. Your job is to be the fresh-context check. Skewing toward PASS defeats the whole role. | +| "I'll run `cargo test` to see which tests are actually green" | You may NOT run `cargo test`. Use `cargo test --list` to enumerate, then read test bodies. Running tests would mutate workspace state and is out of scope for a read-only review. | + +## Red Flags — STOP + +- About to write or edit a file in the workspace +- About to propose a fix for an unratified assumption +- About to run `cargo test` (only `cargo test --list` and `cargo check` allowed) +- About to recall whether a test exists rather than grep for it +- About to mark an assumption ratified based on code presence rather than test presence +- About to skip an assumption because "it would always be true" +- Report exceeding ~500 tokens +- Less than 2 minutes spent searching before declaring `unratified` on any given assumption +```` + +- [ ] **Step 1.2: Verify file structure** + +Run: `grep -c "^## " skills/brainstorm/agents/ailang-grounding-check.md` + +Expected: `11` — eleven `## ` top-level sections matching the +standard agent template (What this role is for, Standing reading +list, Carrier contract, What "load-bearing assumption" means, What +"ratifies" means, The Iron Law, The Process, Status protocol, +Output format, Common Rationalisations, Red Flags). + +- [ ] **Step 1.3: Verify frontmatter** + +Run: `head -5 skills/brainstorm/agents/ailang-grounding-check.md` + +Expected: lines 1-5 are exactly: +``` +--- +name: ailang-grounding-check +description: Read-only grounding-check reviewer for AILang spec drafts. Dispatched by the brainstorm skill in Step 7.5, between linguistic self-review and user-approval. Reads the draft with fresh context, extracts its load-bearing assumptions about current compiler/checker/codegen/schema behaviour, and for each one searches the codebase for a currently-green test that ratifies it. Reports PASS or BLOCK. Does NOT propose fixes, does NOT edit files. +tools: Read, Glob, Grep, Bash +--- +``` + +- [ ] **Step 1.4: Commit** + +```bash +git add skills/brainstorm/agents/ailang-grounding-check.md +git commit -m "iter gc.1: agent — ailang-grounding-check definition" +``` + +--- + +## Task 2: Splice Step 7.5 + amend `brainstorm/SKILL.md` + +**Files:** +- Modify: `skills/brainstorm/SKILL.md:137-219` + +Three edits in one task because they land in one file and describe +one conceptual change (brainstorm gains a private agent). + +- [ ] **Step 2.1: Insert Step 7.5 between Step 7 and Step 8** + +The splice point is between line 150 (end of Step 7 body) and line +152 (Step 8 heading). Insert this block such that there is one +blank line before the new heading and one blank line after the +block before the existing Step 8 heading. + +New content (insert at line 151, replacing the existing single +blank line): + +```markdown + +### Step 7.5 — Grounding-Check Agent (hard-gate) + +Dispatch the read-only `ailang-grounding-check` agent. The agent +reads the just-written spec with fresh context, extracts its +load-bearing assumptions about current compiler / checker / codegen +/ schema behaviour, and for each one searches the workspace for a +currently-green test that ratifies it. + +Dispatch carrier: + +| Field | Content | +|-------|---------| +| `spec_path` | path to the spec just written in Step 6 | +| `iteration_scope` | which sections cover the imminent first iteration (verbatim from the brainstorm session) | + +The agent returns a `PASS` / `BLOCK` / `INFRA_ERROR` report. Boss +interpretation: + +| Agent status | Boss action | +|--------------|-------------| +| `PASS` | Proceed to Step 8. The report goes into the brainstorm chat for the record. | +| `BLOCK` | Present the report to the user. User either: (a) accepts discard → execute the failure-mode procedure below; or (b) overrides in free chat ("Test `::` ratifies that") → log the override note in the brainstorm chat and proceed to Step 8. | +| `INFRA_ERROR` | Abort the brainstorm. The spec stays as-is on disk; debug the workspace out-of-band and re-dispatch the agent. | + +**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 " +``` + +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 2.2: Amend the Handoff Contract table** + +Current (lines 178-183): + +```markdown +## Handoff Contract + +| Direction | Carrier | +|-----------|---------| +| user → `brainstorm` | new milestone request | +| `brainstorm` → `planner` | path to spec + iteration scope | +``` + +Replace with: + +```markdown +## Handoff Contract + +| Direction | Carrier | +|-----------|---------| +| 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 | +``` + +- [ ] **Step 2.3: Amend the "No private agents" cross-reference bullet** + +Current (lines 213-219): + +```markdown +- **No private agents.** This skill is dialogue-driven. The Boss + MAY ad-hoc dispatch `skills/planner/agents/ailang-plan-recon.md` + during Step 1 when the milestone enters code territory the Boss + has not recently read; this is opt-in and not part of the standard + process. Rationale: brainstorm's recon phase is interwoven with + the user Q&A — see `docs/specs/2026-05-11-plan-recon-subagent.md` + for the full reasoning. +``` + +Replace with: + +```markdown +- **Private agent:** `skills/brainstorm/agents/ailang-grounding-check.md` + — dispatched in Step 7.5 as a hard-gate. The agent reads the spec + with fresh context and reports PASS / BLOCK / INFRA_ERROR. See + `docs/specs/2026-05-11-brainstorm-grounding-check.md` for the + design rationale. +- **Ad-hoc dispatch.** The Boss MAY also ad-hoc dispatch + `skills/planner/agents/ailang-plan-recon.md` during Step 1 when + the milestone enters code territory the Boss has not recently + read; this is opt-in and not part of the standard process. + Rationale: brainstorm's recon phase is interwoven with the user + Q&A — see `docs/specs/2026-05-11-plan-recon-subagent.md` for the + full reasoning. +``` + +- [ ] **Step 2.4: Verify edits** + +Run: `grep -c "^### Step " skills/brainstorm/SKILL.md` + +Expected: `9` — eight original steps (1-8) plus the new 7.5, for +nine `### Step ` headings total. (Step 9 stays as Step 9 — only 7.5 +is inserted.) + +Run: `grep -n "ailang-grounding-check" skills/brainstorm/SKILL.md | wc -l` + +Expected: `≥3` — at least three references (Step 7.5 dispatch, +Handoff Contract row, Private-agent cross-reference). + +- [ ] **Step 2.5: Commit** + +```bash +git add skills/brainstorm/SKILL.md +git commit -m "iter gc.1: brainstorm SKILL — insert Step 7.5 (grounding-check hard-gate)" +``` + +--- + +## Task 3: Update `skills/README.md` + +**Files:** +- Modify: `skills/README.md:64-149` + +Two edits: agent-roster row and symlink discovery entry. Same file, +related concern, single commit. + +- [ ] **Step 3.1: Insert agent-roster row** + +The agent-roster table (lines 64-76) currently starts with header at +lines 64-65 and the first row (`ailang-plan-recon`) at line 66. +Insert a new row at line 66, BEFORE the current `ailang-plan-recon` +row, to preserve pipeline order (brainstorm precedes planner). + +New row: + +```markdown +| `ailang-grounding-check` | `brainstorm/agents/` | `brainstorm` (Step 7.5; spec grounding hard-gate) | +``` + +- [ ] **Step 3.2: Insert symlink discovery entry** + +The discovery block (lines 142-149) currently lists six symlinks +starting with `planner` at line 143. Insert a new entry at line +143, BEFORE the current `planner` entry, to preserve pipeline +order. + +New line: + +``` +.claude/agents/brainstorm -> skills/brainstorm/agents +``` + +(Note: two spaces before `->` to match the visual alignment of the +existing entries.) + +- [ ] **Step 3.3: Verify edits** + +Run: `grep -c "ailang-" skills/README.md` + +Expected: increases by 1 from the current count (the new +`ailang-grounding-check` row). + +Run: `grep "\.claude/agents/brainstorm" skills/README.md` + +Expected: one match showing the new symlink entry. + +- [ ] **Step 3.4: Commit** + +```bash +git add skills/README.md +git commit -m "iter gc.1: skills README — roster + symlink for ailang-grounding-check" +``` + +--- + +## Task 4: Symlink `.claude/agents/brainstorm` + +**Files:** +- Create: `.claude/agents/brainstorm` (symlink) + +Order dependency: Task 1 must have run first, because the target +directory `skills/brainstorm/agents/` is created implicitly by the +`Write` of the agent file. If Task 1 has not run, the symlink will +be dangling. + +- [ ] **Step 4.1: Verify target directory exists** + +Run: `ls -d skills/brainstorm/agents/` + +Expected: prints `skills/brainstorm/agents/` (directory exists from +Task 1's Write). + +- [ ] **Step 4.2: Create the symlink** + +Run: `ln -s ../../skills/brainstorm/agents .claude/agents/brainstorm` + +Expected: no output on success. + +- [ ] **Step 4.3: Verify the symlink resolves** + +Run: `ls -la .claude/agents/brainstorm` + +Expected: shows `brainstorm -> ../../skills/brainstorm/agents`. + +Run: `readlink -f .claude/agents/brainstorm` + +Expected: resolves to the absolute path +`/home/brummel/dev/ailang/skills/brainstorm/agents`. + +- [ ] **Step 4.4: Commit** + +```bash +git add .claude/agents/brainstorm +git commit -m "iter gc.1: symlink .claude/agents/brainstorm -> skills/brainstorm/agents" +``` + +--- + +## Task 5: Retire Spec-23 + roadmap forward-pointer + +**Files:** +- Delete: `docs/specs/2026-05-10-23-eq-ord-prelude.md` +- Modify: `docs/roadmap.md:44-52` + +This task closes the loop opened on 2026-05-11: the in-flight +Spec-23 is removed, and the existing P1 Post-22 Prelude roadmap +entry is amended to record the retirement and name the new +dependency. + +- [ ] **Step 5.1: Delete Spec-23** + +Run: `git rm docs/specs/2026-05-10-23-eq-ord-prelude.md` + +Expected output: `rm 'docs/specs/2026-05-10-23-eq-ord-prelude.md'`. + +- [ ] **Step 5.2: Amend the P1 Post-22 Prelude entry in roadmap** + +Current (lines 44-52): + +```markdown +- [ ] **\[milestone\]** Post-22 Prelude — ship `Show` / `Eq` / `Ord` + with the three total-orderable primitive instances (Int, Bool, Str); + rewire `print` through `Show.show`. Float gets `Show` but **not** + `Eq` / `Ord` (partial — see Floats milestone). Originally queued + as 22b.4 in the typeclass milestone, kept on hold pending demand. + - context: JOURNAL 2026-05-09 ("JOURNAL queue"). Floats milestone + closed 2026-05-10 — partial-Eq/Ord-for-Float story is documented + in DESIGN.md §"Float semantics", so the Prelude can decide + what's instanced (Show: yes, Eq/Ord: no for Float). +``` + +Replace with: + +```markdown +- [ ] **\[milestone\]** Post-22 Prelude — ship `Show` / `Eq` / `Ord` + with the three total-orderable primitive instances (Int, Bool, Str); + rewire `print` through `Show.show`. Float gets `Show` but **not** + `Eq` / `Ord` (partial — see Floats milestone). Originally queued + as 22b.4 in the typeclass milestone, kept on hold pending demand. + - context: JOURNAL 2026-05-09 ("JOURNAL queue"). Floats milestone + closed 2026-05-10 — partial-Eq/Ord-for-Float story is documented + in DESIGN.md §"Float semantics", so the Prelude can decide + what's instanced (Show: yes, Eq/Ord: no for Float). + - context: Iter 23.1-23.3 shipped Ordering ADT, Eq / Ord classes, + primitive instances on Int / Bool / Str, and runtime helpers + (`ail_str_eq` / `compare`). Remaining: polymorphic free fns + (`ne` / `lt` / `le` / `gt` / `ge`), `Show` class, `print` + rewire. The original Spec-23 draft was retired 2026-05-11 + because it silently assumed polymorphic free fns are + mono-specialised the same way as class methods; that assumption + is false today. Re-brainstorm pending — `ailang-grounding-check` + (gc.1) will be the gating mechanism on the new draft. + - depends on: polymorphic-free-fn mono-specialisation (symmetric + to class-method monomorphisation in 22b.3) — not currently + ratified by any green test. +``` + +- [ ] **Step 5.3: Verify roadmap edit** + +Run: `grep -n "polymorphic-free-fn mono-specialisation" docs/roadmap.md` + +Expected: one match in the P1 section. + +Run: `grep -n "retired 2026-05-11" docs/roadmap.md` + +Expected: one match in the P1 section. + +- [ ] **Step 5.4: Confirm Spec-23 is gone** + +Run: `ls docs/specs/2026-05-10-23-eq-ord-prelude.md 2>&1` + +Expected: `ls: cannot access ...: No such file or directory`. + +- [ ] **Step 5.5: Commit** + +```bash +git add docs/roadmap.md docs/specs/2026-05-10-23-eq-ord-prelude.md +git commit -m "iter gc.1: retire Spec-23, roadmap forward-pointer to re-brainstorm" +``` + +--- + +## Final regression smoke + +After all five tasks have committed: + +- [ ] **Step F.1: Workspace regression smoke** + +Run: `cargo test --workspace --no-run 2>&1 | tail -5` + +Expected: clean compile, no test failures during build. (No Rust +code touched, but this confirms no accidental cross-contamination.) + +- [ ] **Step F.2: Brainstorm-skill structural sanity** + +Run: `grep -E "^### Step " skills/brainstorm/SKILL.md | awk '{print $2, $3}'` + +Expected output (one per line): +``` +### Step +### Step +### Step +### Step +### Step +### Step +### Step +### Step +### Step +``` +(Nine step headings: 1, 2, 3, 4, 5, 6, 7, 7.5, 8, 9. wc -l = 9.) + +- [ ] **Step F.3: Agent-roster table size** + +Run: `awk '/^\| Agent \|/,/^$/' skills/README.md | wc -l` + +Expected: `≥14` — header + separator + 12 rows (was 11; added 1). + +If any of F.1–F.3 fails, do NOT proceed to journal-write. Re-open +the failing task, fix, re-commit, then re-run the smoke.