diff --git a/docs/plans/2026-05-09-22-tidy-design-drift.md b/docs/plans/2026-05-09-22-tidy-design-drift.md new file mode 100644 index 0000000..422e2c8 --- /dev/null +++ b/docs/plans/2026-05-09-22-tidy-design-drift.md @@ -0,0 +1,322 @@ +# 22-tidy — DESIGN.md and spec drift after milestone-22 close + +> **Parent spec:** `docs/specs/2026-05-09-22-typeclasses.md` (already +> amended for the 22b.4b drop and 22c rescope). +> +> **Trigger:** `audit` skill found drift between `docs/DESIGN.md` +> Decision 11 §"Prelude (built-in) classes" / §"What this decision +> does NOT commit to" and what milestone 22 actually shipped. + +**Goal:** reconcile DESIGN.md, the spec's Components-table row for +22b.4, and stale comments in `crates/ailang-prose/src/lib.rs` with +the milestone outcome (Prelude dropped, 22b.4a Form-A arms shipped, +22c acceptance fixture lands as user-class e2e). After this iter, +the project's load-bearing docs accurately describe what is. + +**Architecture:** pure documentation + comment edits, three files. +No production-code changes. No new tests. The audit suite re-runs +as the gate. + +**Tech Stack:** doc edits only. `git`, `grep`. + +--- + +## Files this plan modifies + +- Modify: `docs/DESIGN.md:1725-1766` — rewrite §"Prelude (built-in) + classes" and §"What this decision does NOT commit to" to match + the 22b.4b-deferral + `__` separator decisions. +- Modify: `docs/specs/2026-05-09-22-typeclasses.md:50-56` — split + the 22b.4 components-table row into 22b.4a (shipped) + 22b.4b + (post-22); mark 22c shipped. +- Modify: `crates/ailang-prose/src/lib.rs:80-101` — update the + ClassDef/InstanceDef placeholder comment; the prose-renderer + arms for the new schema nodes are queued indefinitely (not + to a named iter). +- Modify: `docs/JOURNAL.md` — append the tidy iteration entry + + milestone-22 close note. + +No code-logic changes. No new fixtures. Bench gates re-run as the +audit's verification, but this iter does not change anything they +measure. + +--- + +## Task 1: DESIGN.md drift + +**Files:** `docs/DESIGN.md` lines 1725-1766. + +The current text (verified 2026-05-09) reads: + +> 22a/22b ship a fixed Prelude consisting of three classes: **`Show`, +> `Eq`, `Ord`**, with instances for the four primitive types `Int`, +> `Float`, `Bool`, `String`. … `print x` is rewired through +> `Show.show`: at codegen, the existing print primitive routes its +> argument through the resolved `show@T`. This is the one +> operator-routing change in 22b. + +Plus the §"What this decision does NOT commit to" section that +references "Form-B (prose) projection of class/instance … is 22b +implementer scope" and "exact textual form is fixed in 22b +alongside the existing mangling scheme". + +Three reconciliations: + +1. **No Prelude shipped, no `print` rewiring.** The amendment + `2026-05-09 — 22b.4b dropped` records why (LLM-utility + + missing `int_to_str` runtime primitive). DESIGN.md should + describe the actual outcome, not the original ambition. +2. **`Float` is not in the language.** AILang has no `Float` + type. The Prelude paragraph naming `Int / Float / Bool / String` + is a phantom commitment. +3. **Mono-symbol naming is `__`, not "fixed in 22b".** 22b.3 chose + `__` over `#` for LLVM-IR-identifier legality; the spec + amendment recorded it. DESIGN.md should mirror that. + +### Step 1.1 — Rewrite §"Prelude (built-in) classes" + +Replace the entire §"Prelude (built-in) classes" subsection +(`docs/DESIGN.md:1725-1746`) with: + +```markdown +### Prelude (built-in) classes + +Milestone 22 ships **no built-in Prelude classes**. The original +22a draft committed to a fixed Prelude (Show / Eq / Ord on the +primitives), but the implementation work to wire `int_to_str` as a +heap-allocated-string runtime primitive proved substantively +separable from the typeclass machinery itself, and the LLM-utility +case for primitive `Show` is weak (LLM-natural form is `int_to_str +x`, not `show x` through a single-instance class). The user-class +end-to-end path is the milestone's typeclass acceptance gate +(22c's `class Foo a` + `data IntBox` + `instance Foo IntBox` +fixture); see `docs/specs/2026-05-09-22-typeclasses.md` +"Amendments" §"22b.4b dropped" for the substantive rationale. + +A future milestone may add a Prelude when concrete LLM-author code +surfaces a case that benefits from `Show a` / `Eq a` / `Ord a` +over per-type primitive functions. Until then, primitive output +goes through `io/print_int` / `io/print_bool` / `io/print_str` +directly. + +`==`, `<`, `<=`, `>`, `>=` REMAIN primitive operators (unchanged +from the 22a draft). Class methods are accessed by name (`eq x y`, +`lt x y`, …), not via these operators. Routing operators through +classes is deliberately deferred — it would require migrating every +existing fixture and would re-baseline the bench corpus, which is a +new-baseline decision rather than an iter detail. + +`Num` is NOT in milestone 22. Arithmetic operators (`+`, `-`, `*`, +`/`) stay primitive and per-type. Class-based numeric overloading +would invoke literal-defaulting which axis-7 already excluded. +``` + +### Step 1.2 — Update §"What this decision does NOT commit to" + +Replace the bullet list at `docs/DESIGN.md:1750-1766` with: + +```markdown +- **Operator routing.** `==`, `<`, etc. stay primitive in milestone + 22. Class-routing operators is a future-iteration option, not a + Decision-11 commitment. +- **Form-B (prose) projection of class/instance.** The prose + renderer for the new schema nodes is one-way (no parser by + design) and was deferred from milestone 22 entirely; the + placeholder render in `crates/ailang-prose/src/lib.rs` is + informational only. A future iter ships the full prose + projection if/when prose-side authoring needs surface. +- **Specific monomorphised-symbol naming format.** Milestone 22 + uses `__` for primitive type targets + (e.g. `show__Int`) and `__<8-hex-prefix>` for compound + types (where `<8-hex-prefix>` is the BLAKE3 hash of the canonical + type bytes). The `__` separator was chosen over `#` and `@` for + LLVM IR identifier legality. +- **Mode annotations on class methods.** Class method signatures + ARE full FnSigs and DO carry mode annotations per Decision 10; + the convention is `borrow` for read-only methods. User-defined + classes pick modes per method. +- **Number of Prelude classes.** Milestone 22 ships zero (no + Prelude). A future Prelude milestone gates class additions on + the Feature-acceptance criterion at the time of proposal. +``` + +### Step 1.3 — Commit + +```bash +git add docs/DESIGN.md +git commit -m "iter 22-tidy.1: DESIGN.md — reconcile Decision 11 with milestone-22 outcome (no Prelude, '__' separator)" +``` + +--- + +## Task 2: Spec components-table drift + +**Files:** `docs/specs/2026-05-09-22-typeclasses.md` lines 50-56. + +The Components table still has the original 22b.4 row (Prelude + +Form-B + retire) which the amendments section supersedes. Reader +of the spec would see two contradictory descriptions of milestone +scope. + +### Step 2.1 — Replace the components table + +Find the Components table (lines 50-56) and replace it with: + +```markdown +| Iter | Status | Scope | Closes when | +|---|---|---|---| +| 22b.1 | shipped 2026-05-09 | Schema floor (`ClassDef`, `InstanceDef`, `FnDef.type` extension), workspace registry with three coherence checks (orphan/duplicate/missing-method), hash-stability proof, fixture filter for round-trip gate. | JOURNAL entry committed (done) | +| 22b.2 | shipped 2026-05-09 | Typecheck arms: `FnDef.type.constraints` field activation; class-schema validation (`kind-mismatch`, `invalid-superclass-param`, `constraint-references-unbound-type-var`); per-call-site `missing-constraint` and `no-instance`; `overriding-non-existent-method`, `method-name-collision`, `missing-superclass-instance`. | All new diagnostics fire on dedicated fixtures; bench gates green | +| 22b.3 | shipped 2026-05-09 | Monomorphisation pass — synthesised `FnDef`s from `(method, type-hash)` pairs, call rewriting, cache by key. Synthetic class+instance fixture for e2e validation. `__` separator chosen over `#` for LLVM IR identifier legality. | Synthetic fixture compiles, runs, correct stdout; bench gates green | +| 22b.4a | shipped 2026-05-09 | Form-A parser+printer arms for ClassDef / InstanceDef; `Type::Forall.constraints` round-trip gap fix; round-trip skip-list retired (70 → 106 fixtures green). | Round-trip green for every `examples/*.ail.json`; bench gates green | +| 22b.4b | dropped (post-22) | Originally: Prelude module Show#Int + `int_to_str` C-runtime primitive. Removed from milestone-22 scope per Amendments §"22b.4b dropped" — substantively separable runtime work; LLM-utility for primitive Show is weak. | (deferred) | +| 22c | shipped 2026-05-09 | Single end-to-end fixture: `class Foo a` + `data IntBox` + `instance Foo IntBox` + `main` printing 42. Surfaced and fixed a mono-pass user-ADT bug as part of close. | Fixture compiles, runs, correct stdout; bench gates green | +``` + +(The narrative paragraph at lines 58-67 explaining 22c's promotion +remains as-is — it's still historically accurate.) + +### Step 2.2 — Commit + +```bash +git add docs/specs/2026-05-09-22-typeclasses.md +git commit -m "iter 22-tidy.2: spec — components table reflects 22b.4a/b split + 22c shipped" +``` + +--- + +## Task 3: Prose-lib comment drift + +**Files:** `crates/ailang-prose/src/lib.rs` lines 80-101. + +Three lines reference `22b.4`: + +- line 85: `// is deferred to 22b.4 alongside the prose-roundtrip parser` +- line 94: `out.push_str(") -- 22b.4 will render full Form-B\n");` +- line 100: `out.push_str(") -- 22b.4 will render full Form-B\n");` + +22b.4 was retired (split into 22b.4a + 22b.4b, latter dropped). The +prose Form-B projection for ClassDef/InstanceDef has no named +target iter. + +### Step 3.1 — Update the comment + +Replace the comment block at lines 80-87 with: + +```rust + // ClassDef / InstanceDef render as a single-line + // placeholder so prose round-trip survives a module that + // contains them. The full Form-B projection (mirror of the + // ClassDef / InstanceDef Form-A schema, with method bodies + // re-indented and superclass / default markers spelled out) + // is queued post-22 — `crates/ailang-prose` is one-way (no + // parser by design), so the placeholder is informational + // only, and the round-trip mediator does not read these + // back. +``` + +### Step 3.2 — Update the placeholder text + +Replace `-- 22b.4 will render full Form-B` (lines 94, 100) with +`-- full Form-B projection deferred (post-22)`. Both occurrences. + +### Step 3.3 — Verify build green + +``` +cargo build --workspace +cargo test --workspace +``` + +Expected: green; the strings are inside string literals, no +behavioural impact. + +### Step 3.4 — Commit + +```bash +git add crates/ailang-prose/src/lib.rs +git commit -m "iter 22-tidy.3: prose-lib — drop 22b.4 reference from class/instance placeholder" +``` + +--- + +## Task 4: JOURNAL entry + milestone-22 close + +**Files:** `docs/JOURNAL.md`. + +### Step 4.1 — Append entry + +```markdown + +## 2026-05-09 — Iteration 22-tidy: DESIGN.md and spec drift after milestone-22 close + +Audit (architect drift review) flagged three doc-drift sites +where DESIGN.md and the spec described an as-originally-planned +milestone 22 (Prelude shipping, `print` rewired through Show.show, +`Float` type, Form-B class/instance render in 22b.4) instead of +what actually shipped (no Prelude, primitive print primitives, +no Float, prose render queued post-22). The fix is mechanical +across three files; no code logic changes. + +**Per-task subjects:** + +- 22-tidy.1: DESIGN.md — reconcile Decision 11 with milestone-22 outcome (no Prelude, '__' separator) +- 22-tidy.2: spec — components table reflects 22b.4a/b split + 22c shipped +- 22-tidy.3: prose-lib — drop 22b.4 reference from class/instance placeholder + +**Milestone-22 status: CLOSED.** The four acceptance criteria from +the spec are all satisfied: + +1. ✓ JOURNAL entries committed: 22b.1, 22b.2, 22b.3, 22b.4a, 22c. +2. ✓ Audit suite green — drift report addressed (this iter); bench + gates 0/0/0 at iteration 22c close (rerun confirmed at + milestone-22 audit on 2026-05-09). +3. ✓ 22c user-class fixture compiles, runs, prints `42`. +4. ✓ Round-trip skip-list retired in 22b.4a; all `examples/*.ail.json` + pass round-trip (106 fixtures). + +**Carried debt (not gating, not in this iter's scope):** + +- Primitive-name set duplicated across 4 sites + (`crates/ailang-check/src/mono.rs:316-327`, `linearity.rs:143`, + `lib.rs:1240`, `lib.rs:2222`). Flagged in 22b.3 JOURNAL, + re-flagged by milestone-22 audit. Consolidation is a real + refactor (one helper, four call sites) and benefits from being + its own iter. Queued. +- Strict duplicate-clause detection in `parse_fn` / `parse_data` + / `parse_const` (sibling parsers to the 22b.4a additions). The + asymmetry is documented; promoting siblings to the strict + pattern is queued. +- Form-B (prose) printer arms for ClassDef / InstanceDef. One-way, + not gating. +- DESIGN.md still describes the milestone-22 *outcome* but no + Decision-11 successor is queued — open whether the next + typeclass-related milestone (Prelude, deriving, operator routing) + is a "12-something" or stays under Decision-11. + +**What's next:** orchestrator's call. The JOURNAL queue's next +substantive items per recent entries are: post-22 Prelude +milestone (gated on user-author demand for primitive +`Show`/`Eq`/`Ord`), operator routing through `Eq`/`Ord` (gated on +bench re-baselining), or unrelated work. The milestone-cycle +dictates `brainstorm` for whichever lands next. +``` + +### Step 4.2 — Commit + +```bash +git add docs/JOURNAL.md +git commit -m "iter 22-tidy: journal entry — milestone 22 closed" +``` + +--- + +## Acceptance gate (run after Task 4) + +``` +cargo test --workspace +python3 bench/check.py +python3 bench/compile_check.py +python3 bench/cross_lang.py +``` + +All four green is the iteration close — and the milestone-22 close.