Files
AILang/docs/plans/0012-design-md-consolidation-1-history-anchors.md
Brummel 832375f2ac convention: counter-prefix file naming across docs/specs/, docs/plans/, design/contracts/, design/models/
All 176 files in the four accumulating directories now use a
zero-padded 4-digit counter prefix that reflects creation order
(`NNNN-slug.md`). The counter is assigned per directory in strict
git-log creation order; ties broken alphabetically by original name.
The old `YYYY-MM-DD-` prefix on docs/specs/ and docs/plans/ files is
dropped — the date is recoverable from git log and the counter
carries the ordering.

A file's counter is stable for the life of the file: never reassigned,
never reused, never compacted. Deleted files retire their counter;
subsequent files do not fill the gap. This is the property that lets
cross-references stay literal — refs use the full filename including
the counter (`design/contracts/0007-honesty-rule.md`) so they grep
cleanly and resolve directly without a glob step.

313 cross-references updated across .md/.rs/.toml/.c/.json files
(test pins, include_str! paths, design-INDEX entries, baseline notes,
runtime C comments, inter-contract markdown links incl. bare basename
and `../models/foo.md` forms).

CLAUDE.md gets a new "File-naming convention" section spelling out
the rule and rationale. skills/brainstorm/SKILL.md and
skills/planner/SKILL.md updated so new spec/plan creation produces
counter-prefixed names from the start.

The full test suite (cargo test --workspace) passes.
2026-05-28 13:31:31 +02:00

22 KiB
Raw Permalink Blame History

design-md-consolidation iter 1 — sweep 1: history anchors

Parent spec: docs/specs/0004-design-md-consolidation.md §"Sweep 1 — Remove history anchors"

For agentic workers: REQUIRED SUB-SKILL: use skills/implement to run this plan. Steps use - [ ] checkboxes for tracking.

Goal: Remove every iter tag, family tag, date anchor, status marker, and historical bench data-point anchor from docs/DESIGN.md without changing the semantic content of any decision.

Architecture: Documentation-only refactor. Each task targets one marker class; "RED" is a pre-task grep that lists hit sites, "GREEN" is the post-task grep returning empty for that class. No code changes; cargo test --workspace and the bench gates serve as sanity checks at end-of-iter.

Tech Stack: Edit (docs/DESIGN.md), grep, cargo test --workspace, bench/check.py, bench/compile_check.py.

Files this plan modifies:

  • Modify: docs/DESIGN.md — five marker-class removal passes.
  • Append: docs/JOURNAL.md — one iter entry summarising what was discarded with anchor examples.

Task 1: Status markers

Files: Modify: docs/DESIGN.md (4 sites — lines 168, 509, 595, 684 at iter start; line numbers shift as edits land).

  • Step 1: Pre-test — list status-marker sites
grep -nE '\*\*Status: ' docs/DESIGN.md

Expected: 4 lines:

168:**Status: shipped.** Form (A) was chosen in Iter 14b and implemented as
509:**Status: shipped.** Family 20 (Iter 20a20d, 2026-05-08) ships a
595:**Status: REVERTED in Iter 14g.** This decision was made on shaky grounds —
684:**Status: half-retirement as of 2026-05-09.** Originally framed
  • Step 2: Remove **Status: shipped.** prefix at line 168

The bold-marker-plus-period plus trailing space introduces the sentence. Strip the marker; the sentence reads cleanly without it.

Edit (Decision 6, "authoring surface" section opener):

  • old: **Status: shipped.** Form (A) was chosen in Iter 14b and implemented as
  • new: Form (A) is implemented as

Note: Iter 14b reference is left for Task 4 to handle.

  • Step 3: Remove **Status: shipped.** prefix at line 509

Edit (Decision 6 §"Form (B) — human prose projection"):

  • old: **Status: shipped.** Family 20 (Iter 20a20d, 2026-05-08) ships a
  • new: AILang ships a

Note: Family 20, the date, and the iter-range are left for Tasks 2, 3, 4 to handle.

  • Step 4: Remove **Status: REVERTED in Iter 14g.** prefix at line 595

The reverted-decision body itself is removed in sweep 2. Sweep 1 strips only the marker; the body text remains as transitional state between iterations.

Edit (Decision 7 opener):

  • old: **Status: REVERTED in Iter 14g.** This decision was made on shaky grounds —

  • new: This decision was made on shaky grounds —

  • Step 5: Remove **Status: half-retirement as of 2026-05-09.** prefix at line 684

Edit (Decision 9 opener):

  • old: **Status: half-retirement as of 2026-05-09.** Originally framed
  • new: Originally framed

Note: the "Originally framed ... then re-framed ... 2026-05-09 revision flips" narrative is sweep-2 territory; sweep 1 only strips the marker.

  • Step 6: Post-test — verify no status markers remain
grep -nE '\*\*Status: ' docs/DESIGN.md

Expected: empty output.

  • Step 7: Commit
git add docs/DESIGN.md
git commit -m "design-md-consolidation 1.1: drop **Status:** markers from DESIGN.md"

Task 2: Family tags

Files: Modify: docs/DESIGN.md (4 sites — lines 33, 507, 509, 2060 at iter start).

  • Step 1: Pre-test — list family-tag sites
grep -nE 'Family [0-9]+' docs/DESIGN.md

Expected: 4 lines (or 3 if Task 1's edits coincided with line 509, which is acceptable — the family tag survived Task 1 only at the suffix).

  • Step 2: Strip Family 20 from "Project ecosystem" entry (line 33)

Edit:

  • old: parse ∘ print = id gating every release. ailang-prose (Family 20)`
  • new: `parse ∘ print = id` gating every release. `ailang-prose`

The parenthetical is removed entirely; the surrounding sentence already names the crate.

  • Step 3: Strip (Family 20) from Decision 6 §"Form (B)" header (line 507)

Edit:

  • old: ### Form (B) — human prose projection (Family 20)

  • new: ### Form (B) — human prose projection

  • Step 4: Strip Family 20 (Iter 20a20d, 2026-05-08) from line 509

Already partially edited by Task 1 (the **Status: shipped.** prefix is gone). The remaining sentence opener "AILang ships a" is free of the family tag, but line 509's body may still contain "Family 20" — re-grep to confirm.

If still present:

  • old (whatever Task 1 left): AILang ships a (this should already not contain "Family 20")
  • expected: line 509 contains no Family [0-9]+ after Task 1; if the grep at Step 1 of Task 2 reported it, the residue is the sentence "Family 20 (Iter 20a20d, 2026-05-08) ships a" survived partially. Recheck and edit accordingly.

If still present (Task 1 did not touch this region as expected):

  • old: **Status: shipped.** Family 20 (Iter 20a20d, 2026-05-08) ships a

  • new: AILang ships a

  • Step 5: Strip Family 20 from CLI table (line 2060)

Edit:

  • old: ail prose <module.ail.json> — JSON-AST → form-B (lossy human prose, no parser; Family 20)

  • new: ail prose <module.ail.json> — JSON-AST → form-B (lossy human prose, no parser)

  • Step 6: Post-test — verify no family tags remain

grep -nE 'Family [0-9]+' docs/DESIGN.md

Expected: empty output.

  • Step 7: Commit
git add docs/DESIGN.md
git commit -m "design-md-consolidation 1.2: drop Family-N tags from DESIGN.md"

Task 3: Date anchors

Files: Modify: docs/DESIGN.md (≤13 sites at iter start; subset already removed by Tasks 1-2 — re-grep at Task 3 Step 1).

  • Step 1: Pre-test — list date-anchor sites
grep -nE '2026-[0-9]{2}-[0-9]{2}' docs/DESIGN.md

Expected: ≤13 lines. The expected residue spans Decision 9 (lines ~684-688), Decision 10 (Committed 2026-05-08, mentions of 2026-05-09), Decision 11 (Committed 2026-05-09, 2026-05-10 mono-vs-vdisp), and the Pipeline section (since 2026-05-09).

  • Step 2: Decision 9 opener (line 684 + surrounding paragraph)

The Decision 9 opener is currently a three-paragraph narrative of how the framing changed across three dates. Strip only the dates; the narrative-of-changes-across-dates is sweep-2 territory.

For each occurrence in lines 684-688:

  • Originally framed → keep ("Originally framed" is sweep-2 territory but no date here)
  • (2026-05-07) as "transitional Boehm…" → strip the parenthetical date wrapper
  • (2026-05-08) → strip
  • The 2026-05-09 revision flips → keep "The revision flips" (sweep 2 will rewrite this whole paragraph; sweep 1 only strips the date)

Edit pattern (apply to each line):

  • (2026-05-07) → ``
  • (2026-05-08) → ``
  • 2026-05-09 revisionrevision
  • 2026-05-09 default-flipdefault-flip (line 1410 region)

Note: clean up any double-spaces created by removing inline parentheticals.

  • Step 3: Decision 10 opener (line 835)

Edit:

  • old: **Committed 2026-05-08, after the GC bench (bench/run.sh) showed

  • new: **The GC bench (bench/run.sh) showed

  • Step 4: Decision 10 §"Why not other memory models" (line 1436)

Edit:

  • old: mainstream RC position. The 2026-05-08 follow-up discussion

  • new: mainstream RC position. A follow-up discussion

  • Step 5: Decision 11 opener (line 1451)

Edit:

  • old: **Committed 2026-05-09 (Iter 22a), as the design pass that gates

  • new: **The design pass that gates (the trailing Iter 22a is Task 4 territory; this step strips only the date and the "Committed" framing).

  • Step 6: Decision 11 §"Why mono, not virtual dispatch" (line 1611)

Edit:

  • old: indirect-jump cost. The 2026-05-10 mono-vs-vdisp micro-benchmark

  • new: indirect-jump cost. A mono-vs-vdisp micro-benchmark

  • Step 7: Decision 11 §"What 22a explicitly does NOT support" (line 1723)

Edit:

  • old: rationale recorded in JOURNAL 2026-05-09; constraint-bearing

  • new: rationale recorded in JOURNAL; constraint-bearing

  • Step 8: Decision 11 §"Prelude" (line 1753)

Edit:

  • old: fixture); see docs/specs/0002-22-typeclasses.md``
  • new: fixture); see docs/specs/22-typeclasses.md``

NOTE: this step renames the spec-file reference. The actual file docs/specs/0002-22-typeclasses.md exists on disk; sweep 1 does NOT rename the file (that would lose git history). Instead, the in-text reference is left as the date-prefixed actual filename because it points to a real file. Revert this step if the filename on disk uses the date prefix.

Verify before editing:

ls docs/specs/0002-22-typeclasses.md

If the file exists with the date prefix, KEEP the reference and add the bare filename to a "deliberate exceptions" list to be recorded in the JOURNAL entry at Task 6. The grep pattern at the sweep-1 acceptance check then reports this single line as a known exception.

  • Step 9: Pipeline section (line 2024)

Edit:

  • old: since 2026-05-09: the typechecker enforces

  • new: the typechecker enforces

  • Step 10: Default-flip mention in Decision 10 (~line 1410)

Edit:

  • old: default-flip (2026-05-09 — --alloc=rc becomes the CLI default,
  • new: default-flip (--alloc=rc is the CLI default,

Sentence-level cleanup: the surrounding "executes in two steps: first a default-flip … ; second a full removal" describes a state that is partly past (default-flip happened) and partly future (full removal pending). Sweep-1 stays mechanical: the date goes; the narrative of "first … second" is sweep-2 territory.

  • Step 11: Post-test — verify date anchors gone (with permitted exception)
grep -nE '2026-[0-9]{2}-[0-9]{2}' docs/DESIGN.md

Expected: empty, OR exactly one line — the spec-file path docs/specs/0002-22-typeclasses.md (if the file on disk uses that prefix). Record this in the JOURNAL exception list.

  • Step 12: Commit
git add docs/DESIGN.md
git commit -m "design-md-consolidation 1.3: drop date anchors from DESIGN.md"

Task 4: Iter tags

Files: Modify: docs/DESIGN.md (~97 sites at iter start; subset already removed by Tasks 1-3 — re-grep at Task 4 Step 1).

The iter-tag class has the largest count and the most contextual variation. Pre-test reveals all sites; the editor walks them top-to-bottom, applying the matching pattern below per site.

  • Step 1: Pre-test — list iter-tag sites
grep -nE 'Iter [0-9]+[a-z]?(\.[0-9]+)?' docs/DESIGN.md

Expected: ~70-90 sites (down from 97 after Tasks 1-3 stripped some co-located in Status/Date sentences).

  • Step 2: Apply per-site pattern, top to bottom

Walk the grep output top to bottom. For each line, apply the matching rewrite pattern below. Some sites need a custom rewrite — when in doubt, prefer "remove the iter tag and surrounding bookkeeping phrase, keep the technical content".

Pattern set (apply the first that matches):

a. Subsection header ### Iter Xy — feature name

  • old: ### Iter 18a — parameter modes on \Type::Fn``
  • new: ### Parameter modes on \Type::Fn``

b. Bold prefix **Iter Xy — feature name.**

  • old: **Iter 18a — parameter modes on \Type::Fn`.**`
  • new: **Parameter modes on \Type::Fn`.**`

c. Parenthetical (Iter Xy) standalone

  • old: ... mode wrappers (Iter 18a):
  • new: ... mode wrappers:

d. Inline Iter Xy chose / introduced / shipped / extended ...

  • old: Iter 14b chose Form (A)
  • new: Form (A) was chosen

e. since Iter Xy / from Iter Xy onward

  • old: since Iter 13a
  • new: currently or remove (whichever scans cleaner)

f. per Iter Xy / from the Iter Xy …

  • old: per Iter 14e
  • new: remove the qualifier; the sentence describes the rule, not its origin

g. (Iter Xy, …) with multiple parts

  • old: (Iter 16b.1, lift_letrecs)
  • new: (lift_letrecs)

h. Cross-reference see Iter Xy / Iter Xy onward

  • old: see Iter 14e
  • new: remove the cross-reference; the prose preceding/following it must stand alone. If the iter-cross-ref is load-bearing (i.e. the meaning is unrecoverable without it), bounce to orchestrator — that signals a content-not-mechanical edit.

i. Anchor in a list item like // Iter 18e opt-in; omitted when false

  • old: "drop-iterative": true // Iter 18e opt-in; omitted when false (pre-18e hash-stable)
  • new: "drop-iterative": true // opt-in; omitted when false (hash-stable when omitted)

The "pre-Xy hash-stable" form occurs in the Data-model section several times. Pattern: (pre-Xy hash-stable)(hash-stable when omitted) or removed if the surrounding "omitted when …" already carries the meaning.

  • Step 3: Spot-checks for sentence integrity

After all sites are edited, read the affected sections end-to-end in the editor (or use head -200 docs/DESIGN.md / sed -n '500,700p' docs/DESIGN.md for spot reads). The most common drift mode after iter-tag stripping is: the surrounding sentence referenced "Iter Xy" structurally and now reads as "X was chosen in" with no agent. Fix by trimming the dangling phrase.

Specific high-risk sections (re-read each):

  • Decision 6 §"Why this is opening up" (lines 181-220 region) — references "Iters 1 through 14a" structurally.

  • Decision 6 §"Form refinements during Iter 14c implementation" (line 454) — the section title itself contains the iter tag. Rewrite header to ### Form refinements during implementation.

  • Decision 9 — Iter 14e tail-call notes, Iter 14f, Iter 17a.

  • Decision 10 §"Migration plan" — 7 numbered iters. Sweep 2 will delete the whole section; sweep 1 still strips the iter tags inside it for grep cleanliness.

  • "What is not (yet) supported" §"Recently lifted gates" — every bullet is iter-anchored. Sweep 4 deletes the paragraph entirely; sweep 1 strips the iter tags inside for grep cleanliness.

  • Step 4: Post-test — verify iter tags gone

grep -nE 'Iter [0-9]+[a-z]?(\.[0-9]+)?' docs/DESIGN.md

Expected: empty output, OR the date-prefixed spec-file reference from Task 3 Step 11 (the path docs/specs/0002-22-typeclasses.md does not match this iter pattern, so the exception list need not grow here).

  • Step 5: Commit
git add docs/DESIGN.md
git commit -m "design-md-consolidation 1.4: drop Iter-N tags from DESIGN.md"

Task 5: Bench data-points

Files: Modify: docs/DESIGN.md (12 sites at iter start, lines 836, 843, 855, 857, 865, 873, 875, 876, 899, 1615, 1619, 1620).

The bench-data-point class has the most per-site judgement. Each site is decided as REMOVE (transient measurement) or KEEP (target / contract / policy commitment).

  • Step 1: Pre-test — list bench data-point sites
grep -nE '[0-9]+%|[0-9]+\.[0-9]+×|[0-9]+\.[0-9]+x' docs/DESIGN.md

Expected: 12 lines.

  • Step 2: Apply per-site decisions
Site Today's text fragment Decision New form
836 Boehm contributing ~60% of runtime on allocation-heavy workloads REMOVE the percentage; keep the structural claim Boehm contributing a substantial fraction of runtime on allocation-heavy workloads (bench notes in JOURNAL)
843 ~2.8× slower than a bump pointer REMOVE; structural claim structurally slower than a bump pointer
855 target 1.3× on \bench/run.sh`` KEEP — this is the active retirement contract unchanged
857 **Workload scope of the 1.3× target.** KEEP — header references the kept target unchanged
865 closure-chain fixture's measured \rc/bump = 4.14×`` CONDENSE — historical measurement closure-chain fixture measures wider than the 1.3× linear/tree target (current value recorded in JOURNAL bench entries)
873 1.3× retirement target therefore applies KEEP — repeats the target unchanged
875 21'g baseline records \4.14×`` CONDENSE baseline records the closure-chain ratio with ±15% tolerance (the iter tag 21'g is also stripped here per Task 4 — order-of-operations: Task 4 already ran, so this site no longer carries 21'g; verify)
876 as the \rc_over_bump` reference value with ±15% tolerance` KEEP — config metadata; tolerance is a contract unchanged
899 Boehm's bench number (~60% allocate-… REMOVE percentage Boehm's bench overhead is structurally on the allocate path (JOURNAL bench notes)
1615 1.000x on Zen 3 / clang -O2 REMOVE — bench-setup detail reformulate sentence: the same-shape non-inlined direct call is comparable in cost to indirect dispatch when the branch predictor saturates on a monomorphic target (drop the number)
1619 3.31x vs non-inlinable direct call CONDENSE — kept claim is "mono enables inlining" substantial vs the non-inlinable direct call
1620 4.00x vs polymorphic vdisp (4 distinct targets cycling) CONDENSE larger again vs polymorphic vdisp

The 12-site pass collapses around two patterns: (a) policy commitments tied to the 1.3× target stay verbatim (sites 855, 857, 873, 876); (b) historical measurements either disappear from the text (with the policy claim they grounded surviving in surrounding prose) or condense to a JOURNAL pointer.

  • Step 3: Post-test — verify only KEEP-class numbers remain
grep -nE '[0-9]+%|[0-9]+\.[0-9]+×|[0-9]+\.[0-9]+x' docs/DESIGN.md

Expected: 4 lines, each anchored on the 1.3× target (sites 855, 857, 873, plus the ±15% at 876 — note that ±15% does not match the percent regex if the regex is [0-9]+% matching 15%; the tolerance does. Re-evaluate which sites the regex flags post-edit). Acceptable residue: any line that mentions the 1.3× retirement target or the ±15% tolerance.

If unexpected residue: re-walk the table above, find the site that slipped, fix it.

  • Step 4: Commit
git add docs/DESIGN.md
git commit -m "design-md-consolidation 1.5: condense historical bench data-points in DESIGN.md"

Task 6: Final validation + JOURNAL entry

Files: Read: docs/DESIGN.md. Append: docs/JOURNAL.md.

  • Step 1: Run the sweep-1 composite acceptance grep
grep -nE 'Iter [0-9]+[a-z]?(\.[0-9]+)?|Family [0-9]+|^[^/]*2026-[0-9]{2}-[0-9]{2}|\*\*Status: ' docs/DESIGN.md

Expected: empty, OR up to one line (the docs/specs/0002-22-typeclasses.md path from Task 3 Step 11, if the file on disk has that prefix). The leading ^[^/]* in the date regex pre-filters paths that begin with docs/specs/.

If a path-anchored exception remains, record it in the JOURNAL entry below as a deliberate exception.

  • Step 2: Run the cargo test sweep
cargo test --workspace 2>&1 | tail -20

Expected: test result: ok. … 0 failed for every test binary.

This is a sanity check: no source-code changes were made in this iter, so any test failure is a real regression unrelated to the sweep.

  • Step 3: Run the bench gates
python3 bench/check.py && python3 bench/compile_check.py

Expected: each script exits 0 / prints 0/N with no failures.

  • Step 4: Append the JOURNAL entry

Append to docs/JOURNAL.md (after the last entry):

## 2026-05-10 — Iteration design-md-consolidation 1: history-anchor sweep

First iteration of the milestone defined in
`docs/specs/0004-design-md-consolidation.md`. Sweep 1 closes
the "history anchors in DESIGN.md" item: every iter tag, family
tag, date anchor, status marker, and historical bench data-point
that anchored the document to a specific moment is removed.
DESIGN.md now reads as a state-only document; the *narratives* of
how decisions changed (Decision 9's three-frame story, Decision
11's mono-vs-vdisp correction) remain in their narrative form
this iter and are condensed in sweep 2.

Sites stripped (counts at iter start):
- Iter tags: ~97 sites across all decisions and the data-model /
  pipeline / what-is-not-yet-supported sections.
- Family tags: 4 sites.
- Date anchors: 13 sites.
- Status markers: 4 sites (`shipped` ×2, `REVERTED`, `half-retirement`).
- Bench data-points: 12 sites — 4 KEPT (the 1.3× retirement target
  and ±15% tolerance, which are policy contracts), 8 REMOVED or
  CONDENSED.

Specific anchor examples discarded (representative):
- Decision 6 opener: `**Status: shipped.** Form (A) was chosen in
  Iter 14b and implemented as` → `Form (A) is implemented as`.
- Decision 9 opener: `**Status: half-retirement as of 2026-05-09.**
  Originally framed (2026-05-07) as "transitional Boehm…"` →
  `Originally framed as "transitional Boehm…"` (the narrative-of-changes
  paragraph is sweep-2 territory).
- Decision 10 opener: `**Committed 2026-05-08, after the GC bench
  showed Boehm contributing ~60% of runtime…` → `**The GC bench
  showed Boehm contributing a substantial fraction of runtime
  (bench notes in JOURNAL).`

Deliberate exceptions to the sweep-1 grep pattern (if any):
- `docs/specs/0002-22-typeclasses.md` — date-prefixed spec
  filename, kept verbatim because the on-disk file uses that
  prefix and renaming would lose git history. Record only.

Acceptance:
- composite grep returns empty (or the one path-anchored exception above).
- `cargo test --workspace` 0 FAILED across all test binaries.
- `bench/check.py` and `bench/compile_check.py` 0/0.

The 1.3× Boehm-retirement target and the ±15% closure-band
tolerance are KEPT verbatim — they are policy contracts, not
historical measurements. The historical bench data-points that
grounded those targets (60% allocate-path overhead; 2.8× malloc
slowdown; 4.14× rc/bump on closure-chain; 3.31x / 4.00x mono-vs-vdisp)
are removed from DESIGN.md; their values remain in JOURNAL bench
entries (`bench/run.sh` baseline records, mono-dispatch micro-bench
2026-05-10 entry).

Carried into sweep 2: Decision 7's body (still present, awaiting
removal), Decision 9's "Originally framed … then re-framed …
revision flips" narrative, Decision 10's "Migration plan", Decision
11's "Why mono, not virtual dispatch (the empirically-grounded
version)" correction history, and the "future iter may"
speculations.

Adjust the discarded-anchor examples and the carried-into-sweep-2 list to match what was actually edited; the template above lists the planned outcomes.

  • Step 5: Commit the JOURNAL entry
git add docs/JOURNAL.md
git commit -m "design-md-consolidation 1: journal entry"