From a64b2ccb2a925d2e0868fff66a199572847447e5 Mon Sep 17 00:00:00 2001 From: Brummel Date: Tue, 19 May 2026 11:58:07 +0200 Subject: [PATCH] =?UTF-8?q?spec:=20design-md-rolesplit=20=E2=80=94=20DESIG?= =?UTF-8?q?N.md=20role-split=20into=20design/=20contracts+models=20ledger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Role-split the 3020-line docs/DESIGN.md into design/contracts/ (the hot, test-linked invariant set), design/models/ (one whitepaper per model), and design/INDEX.md as the sole addressable spine; decision- records rehomed to docs/journals/. Clean cut (DESIGN.md deleted, no stub), ###-subsection relocation granularity, build-atomic landing (design_schema_drift.rs include_str! forces one commit), polymorphic INDEX links (code-SoT contracts point at source //!, no prose dup), typed-INDEX anti-regrowth pin (design_index_pin.rs). grounding-check PASS 13/13 after one re-dispatch (commitment-4 pin-status claim corrected: Decision-6 :242 audit-trail sentence is pinned by no test, retired to the decision-record journal, no successor pin by design). roadmap: DESIGN.md->design/ marked [~] in flight (spec landed). --- docs/roadmap.md | 13 +- docs/specs/2026-05-19-design-md-rolesplit.md | 512 +++++++++++++++++++ 2 files changed, 520 insertions(+), 5 deletions(-) create mode 100644 docs/specs/2026-05-19-design-md-rolesplit.md diff --git a/docs/roadmap.md b/docs/roadmap.md index a2b35d6..5913c13 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -381,7 +381,7 @@ work progresses. ## P2 — Medium-term -- [ ] **\[milestone\]** DESIGN.md → `design/` — role-split into a +- [~] **\[milestone\]** DESIGN.md → `design/` — role-split into a typed contract ledger + per-model whitepapers, decision-records rehomed to `docs/journals/`. `docs/DESIGN.md` is one 2905-line file doing three different jobs for three different consumers @@ -473,10 +473,13 @@ work progresses. implementation that closes audits against the current DESIGN.md. Brainstorm hard-gate before any plan/code — it rewrites enforced invariants and agent contracts. - - context: 2026-05-18 chat (DESIGN.md-management dialogue — - six-turn convergence: role-conflation diagnosis, three-job - split axis, "let the code speak" principle, qmd rejection, - blast-radius sequencing). No journal entry yet; pre-brainstorm. + - context: spec `docs/specs/2026-05-19-design-md-rolesplit.md` + (grounding-check PASS 13/13, one re-dispatch after a corrected + commitment-4 pin-status claim); 2026-05-18 chat + (DESIGN.md-management dialogue — six-turn convergence: + role-conflation diagnosis, three-job split axis, "let the code + speak" principle, qmd rejection, blast-radius sequencing). + In flight — ABI-arc sequencing blocker cleared by M5 close. - [ ] **\[milestone\]** Flat array/slice primitive — performance follow-up to the Embedding ABI arc, *not* a capability gap. diff --git a/docs/specs/2026-05-19-design-md-rolesplit.md b/docs/specs/2026-05-19-design-md-rolesplit.md new file mode 100644 index 0000000..dd19999 --- /dev/null +++ b/docs/specs/2026-05-19-design-md-rolesplit.md @@ -0,0 +1,512 @@ +# DESIGN.md → `design/` role-split — Design Spec + +**Date:** 2026-05-19 +**Status:** Draft — awaiting user spec review +**Authors:** Brummel (orchestrator) + Claude + +## Goal + +`docs/DESIGN.md` is one **3020-line** file doing three different jobs +for three different consumers with three different lifetimes. The +line count is the *symptom* of role-conflation, not of mess: the +just-closed `docs-honesty-lint` milestone ran a full honesty pass and +DESIGN.md stayed 3020 lines, because honesty-lint operates *within* a +job and its own audit-trail invariant *mandates retaining* the bulky +decision-record prose (DESIGN.md Decision 6, lines 241–243: "records +the *why* … for the audit trail"). You cannot clean your way out of +conflation; the conflation is the structural defect. + +Replace `docs/DESIGN.md` with a `design/` directory split on the +**consumer/lifetime axis** — `design/contracts/` (the hot, +test-linked invariant set), `design/models/` (one whitepaper per +model) — with `design/INDEX.md` as the **sole addressable spine**. +Decision-record prose moves to `docs/journals/`. The split is a +**clean cut**: `docs/DESIGN.md` is deleted; every named reference is +repointed in one build-atomic milestone. + +The three conflated jobs and their distinct consumers: + +- **Contract** — prescriptive, test-linked invariants (Decision 6's + binding Form-A constraints, the Roundtrip Invariant, the + borrow/own binding rules, the frozen value layout). Consumer: + `architect` (mandatory full read at *every* milestone close), + `grounding-check` (every spec), the honesty sweep. Wants: + structured, addressable, test-linked, small, hot. The only job on + the per-milestone hot path. +- **Model exposition** — whitepaper-shaped narratives (RC + + Uniqueness, typeclasses, effects, the authoring-surface rationale). + Consumer: onboarding (fresh-context LLM, `fieldtester`). + Irreducible — the code cannot speak the gestalt. +- **Decision-record / relitigating-guard** — why X was chosen, why + Y/Z were rejected (region inference, tracing GC, …). Consumer: a + future `brainstorm`, so it does not re-propose a settled-and- + rejected idea. This already has a home — `docs/journals/`. + +Underlying principle: the code is authoritative for *what it does*; +the spec's irreducible job is *what is promised* plus a pointer to +the green test that ratifies it. + +## Architecture + +``` +design/ + INDEX.md sole addressable spine — a typed two-table ledger + contracts/ prose-authoritative invariants (the architect hot path) + feature-acceptance.md authoring-surface.md roundtrip-invariant.md + memory-model.md typeclasses.md float-semantics.md + frozen-value-layout.md honesty-rule.md tail-calls.md + data-model.md embedding-abi.md verification.md + models/ one whitepaper per model (onboarding path) + rc-uniqueness.md typeclasses.md effects.md authoring-surface.md pipeline.md + +docs/journals/2026-05-19-design-decision-records.md relitigation-guard archive +docs/DESIGN.md DELETED (clean cut) +``` + +Five structural commitments: + +1. **Polymorphic INDEX link.** An INDEX row's `link` is *either* a + `design/` file *or* an authoritative source path. Where code is + the single source of truth (mangling, env construction, + qualified-cross-module-ref resolution), there is **no prose + contract file** — the row points at the source `//!` header and + names the ratifying test, killing the prose-vs-code second truth. + `frozen-value-layout` is the deliberate dual-link exception (a + one-way human commitment *and* a codegen contract → both a prose + file and a source pointer). The polymorphic disposition is fixed + per-contract in the Components disposition table below. + +2. **`###`-subsection is the unit of relocation.** No sentence- + surgery. Each `###` subsection of DESIGN.md moves whole to + `contracts/`, `models/`, or the decision-record journal. The + MIXED `##` Decisions (6/9/10/11) decompose at their existing + `###` seam, which recon confirmed resolves cleanly. + +3. **Build-atomic, not just semantically atomic.** + `crates/ailang-core/tests/design_schema_drift.rs:22` uses + `include_str!("../../../docs/DESIGN.md")` — a compile-time path. + The instant `docs/DESIGN.md` is deleted the workspace **does not + compile** until that `include_str!` is retargeted. The content + move + the 4-executable retarget + the 2-diagnostic/2-E2E + retarget + the new pin test land in **one commit**; the tree is + never half-moved. This is a fail-closed property, not a hazard. + +4. **The honesty-rule self-repointing resolves the internal + contradiction.** Two distinct self-referential passages, with + *different* pin status (grounding-check verified): + - `### What this document is — and the honesty rule it holds + itself to` (DESIGN.md:56–82) **is** pinned: `docs_honesty_pin.rs:70` + pins `"the honesty rule it holds itself to"` and `:72` pins + `"whether the document asserts something exists, works, or + changed that does not"` (both inside + `design_md_present_tense_anchors_present`). This becomes + `contracts/honesty-rule.md`, **rewritten** so the rule states + the new home (rationale → `docs/journals/`); those two pins are + retargeted to the new file *and* the new wording in the same + atomic change. + - Decision 6's :242 sentence — *"The rest of this section records + the why of Decision 6 for the audit trail; the constraints + listed below describe the surface as shipped."* — is pinned by + **no test anywhere** (grounding-check grepped `crates/*/tests/`, + in-source `crates/*/src/`, `effect_doc_honesty_pin.rs`: zero + matches). It is itself decision-record self-assertion describing + the *old conflated structure*. The milestone **retires** it: its + "why of Decision 6" content moves to the decision-record journal; + the meta-sentence that asserts DESIGN.md retains audit-trail + prose is not carried forward and needs **no successor pin** — + code never protected it, and should not, because that sentence + is exactly the audit-trail self-claim the split removes from the + contract surface. + + The internal contradiction (a doc asserting of itself that it + "records the why for the audit trail" while the milestone moves + the why out) is closed *by* the milestone: the asserting sentence + is retired, and the only honesty self-claim that survives — + "rationale lives in `docs/journals/`" — is the rewritten + `honesty-rule.md`, which the retargeted `:70,72` pins protect. + +5. **Clean cut, no stub, no redirect.** `docs/DESIGN.md` is deleted. + No transitional pointer file (a "see elsewhere" file is itself + history-pointing — a doc-honesty violation in the milestone that + exists to enforce doc honesty). Matches the no-deprecation-window + precedent (mut/var/assign removal) and the current-state-mirror + discipline. + +## Concrete code shapes + +### 1. The delivered artifacts (this is an infra milestone — these are the headline) + +**`design/INDEX.md`** — the typed two-table ledger. `link` is +polymorphic; `ratifying-test` is mandatory for `kind=contract`: + +```markdown +# AILang Design — Index + +The sole addressable entry point. Every contract and model is +reached from here. A contract is a prescriptive, test-linked +invariant; a model is a whitepaper narrative. `ratifying-test` names +the green test that proves a contract still holds. `link` is +polymorphic: a `design/` file, or the authoritative source `//!` +header when the code is the single source of truth. + +## Contracts +| id | consumer / lifetime | ratifying-test | link | +|----|---------------------|----------------|------| +| feature-acceptance | brainstorm-gate / stable | skills/brainstorm/SKILL.md Step 4 | contracts/feature-acceptance.md | +| authoring-surface | LLM author / stable | crates/ailang-surface round_trip.rs | contracts/authoring-surface.md | +| roundtrip-invariant | every release / stable | crates/ailang-surface round_trip.rs | contracts/roundtrip-invariant.md | +| memory-model | LLM author / stable | crates/ailang-check uniqueness/mode tests | contracts/memory-model.md | +| data-model | LLM author / stable | crates/ailang-core design_schema_drift.rs | contracts/data-model.md | +| mangling | codegen / stable | crates/ail eq_ord_e2e.rs | crates/ailang-codegen/src/lib.rs //! | +| env-construction | codegen / stable | crates/ailang-codegen duplicate_ctor_pin.rs | crates/ailang-codegen/src/lib.rs //! | +| frozen-value-layout | embedding ABI / one-way-frozen| crates/ailang-codegen embed_record_layout_pin.rs | contracts/frozen-value-layout.md + runtime/rc.c §layout | +| float-semantics | LLM author / stable | crates/ail eq_float_noinstance.rs | contracts/float-semantics.md | +| typeclasses | LLM author / stable | crates/ail show_no_instance_e2e.rs | contracts/typeclasses.md | +| tail-calls | codegen / stable | crates/ailang-check tail-call tests | contracts/tail-calls.md | +| honesty-rule | architect+grounding / stable | crates/ailang-core docs_honesty_pin.rs | contracts/honesty-rule.md | +| embedding-abi | embedding host / stable | crates/ailang-codegen embed_record_layout_pin.rs | contracts/embedding-abi.md | +| verification | architect / stable | bench/architect_sweeps.sh | contracts/verification.md | + +## Models +| id | consumer / lifetime | link | +|----|---------------------|------| +| rc-uniqueness | onboarding / evolves | models/rc-uniqueness.md | +| typeclasses | onboarding / evolves | models/typeclasses.md | +| effects | onboarding / evolves | models/effects.md | +| authoring-surface | onboarding / evolves | models/authoring-surface.md | +| pipeline | onboarding / evolves | models/pipeline.md | +``` + +The `ratifying-test` column above shows illustrative tokens. The +planner resolves each to an exact, recon-verified file path (the +`design_index_pin.rs` clause-2 check requires every token to resolve +to a real file); the spec owns the *shape and the disposition*, the +planner owns the exact bytes per the planner Iron Law. + +**A sample contract file** — `design/contracts/float-semantics.md` +(content moved verbatim from DESIGN.md:2700–2838, header re-levelled +to file root, all decision-record/why-prose stripped to the journal): + +```markdown +# Float semantics + +Float is the IEEE-754 double-precision primitive. Float has **no +`Eq` and no `Ord` instance by design**: IEEE-754 ordering is partial +(NaN is unordered), so a total `Eq`/`Ord` would be a lie about the +type. … [present-tense contract prose only] … + +`float_to_str` is type-installed; codegen is reserved and not yet +shipped. + +Ratified by: `crates/ail/tests/eq_float_noinstance.rs`. +``` + +**The anti-regrowth guard** — `crates/ailang-core/tests/design_index_pin.rs` +(the concrete must-fail artifact for an infra milestone — its correct +behaviour is to go RED the instant the structure re-conflates): + +```rust +//! Structural pin for the design/ ledger. Sibling of +//! docs_honesty_pin.rs. Fails RED the instant the design/ split +//! re-conflates contract + rationale + narrative, an INDEX row +//! dangles, a contract loses its ratifying test, or docs/DESIGN.md +//! is resurrected. + +// helper: workspace root = CARGO_MANIFEST_DIR/../.. ; norm() = +// split_whitespace().join(" ") — line-wrap-independent, identical +// shape to docs_honesty_pin.rs. + +#[test] +fn design_md_is_gone() { + // clause 4 — clean-cut pin + assert!(!root().join("docs/DESIGN.md").exists(), + "docs/DESIGN.md was resurrected; the split is clean-cut"); +} + +#[test] +fn every_index_link_resolves() { + // clause 1 — parse design/INDEX.md tables; for each row, the + // `link` target (design/ file OR source path; the dual-link + // row's first segment before " + ") exists on disk. +} + +#[test] +fn every_contract_names_a_resolvable_ratifying_test() { + // clause 2 — every kind=contract row's ratifying-test token + // resolves to a real file under crates/**/tests, bench/, or + // skills/**/SKILL.md. +} + +#[test] +fn contracts_carry_no_decision_record_prose() { + // clause 3 — the conflation tripwire. For each + // design/contracts/*.md, norm() the body and assert it contains + // none of: "we rejected", "an earlier draft", "Why not other", + // "was retired in iter", "rollback plan", "previously all". +} +``` + +### 2. The one real code change — compiler diagnostic, before → after + +This is the clause-1 / clause-3 evidence. The pre-existing fixture +the diagnostic E2E runs (unchanged), the program an LLM author +writes that **must fail** to typecheck: + +```scheme +; examples/eq_float_noinstance.ail +(module eq_float_noinstance + (fn main + (type (fn-type (params) (ret (con Unit)) (effects IO))) + (params) + (body (app print (if (app eq 1.0 2.0) 1 0))))) +``` + +`crates/ailang-check/src/lib.rs:873` (the Float branch): + +``` +- orderability per IEEE-754); see DESIGN.md §\"Float semantics\".", ++ orderability per IEEE-754); see design/contracts/float-semantics.md.", +``` + +`crates/ailang-check/src/lib.rs:888` (the Show branch): + +``` +- the prelude; see DESIGN.md §\"Prelude (built-in) \ +- classes\". User types declare their own \ ++ the prelude; see design/contracts/typeclasses.md. \ ++ User types declare their own \ +``` + +`crates/ail/tests/eq_float_noinstance.rs:40` — the assertion +currently passes on `"Float semantics" || "DESIGN"`; both substrings +vanish, so it updates in lockstep: + +```rust +- no_inst.message.contains("Float semantics") || no_inst.message.contains("DESIGN"), +- "expected NoInstance message to cross-reference DESIGN.md §Float semantics, got: {:?}", ++ no_inst.message.contains("design/contracts/float-semantics.md"), ++ "expected NoInstance message to cross-reference the float-semantics contract, got: {:?}", +``` + +`crates/ail/tests/show_no_instance_e2e.rs:48` — analogous: the +asserted substring becomes `"design/contracts/typeclasses.md"`. + +### 3. The four executable retargets (before → after) + +`bench/architect_sweeps.sh:22-28`: + +```sh +- DESIGN="docs/DESIGN.md" +- [[ ! -f "$DESIGN" ]] && { echo "could not find $DESIGN"; exit 2; } ++ INDEX="design/INDEX.md" ++ [[ ! -f "$INDEX" ]] && { echo "could not find $INDEX"; exit 2; } +``` + +Each `run_sweep` greps the `design/contracts/*.md` + `design/models/*.md` +set instead of the single file; exit-code contract preserved +(0 clean / 1 anchor-found / 2 spine-not-found). Sweep 5 (honesty) +scans all `design/` prose; the verbatim regexes are unchanged. + +`crates/ailang-core/tests/design_schema_drift.rs:22`: + +```rust +- const DESIGN_MD: &str = include_str!("../../../docs/DESIGN.md"); ++ const DATA_MODEL: &str = include_str!("../../../design/contracts/data-model.md"); +``` + +The `data_model_section()` slicer (`## Data model` … `\n## Pipeline`) +and `data_model_section_is_bounded` are **removed**: the whole file +is now the data-model contract, so the section-extraction premise +vanishes — a simplification the split enables. Every +`section.contains(anchor)` assertion runs against the whole +`DATA_MODEL` string. + +`crates/ailang-core/tests/docs_honesty_pin.rs` and +`effect_doc_honesty_pin.rs`: the `read("docs/DESIGN.md")` calls split +into reads of the specific `design/` files where each pinned sentence +now lives. The present/absent pin strings are unchanged **except** +the two honesty-rule anchors at `docs_honesty_pin.rs:70,72` (`"the +honesty rule it holds itself to"` / `"whether the document asserts +something exists, works, or changed that does not"`), which are +updated to the rewritten `contracts/honesty-rule.md` wording in +lockstep with that file. The Decision-6 `:242` audit-trail sentence +is pinned by no test (verified) and is retired to the decision-record +journal, not retargeted — there is nothing to repoint, by design. + +### 4. Agent reading-list rewrite (representative before → after) + +`skills/audit/agents/ailang-architect.md:30`: + +``` +- 2. `docs/DESIGN.md` — the canonical specification. Drift is measured against ++ 2. `design/INDEX.md` — the typed contract ledger and sole spine. ++ Walk the Contracts table; drift is measured against each row's ++ `link` target (a `design/contracts/` file or the source `//!` ++ it names). `design/models/` is context, not a drift surface. +``` + +The other ~11 reading-list bullets +(`grounding-check`, `fieldtester`, `debugger`, `bencher`, `tester`, +`implementer`, `implement-orchestrator`, `spec-reviewer`, +`quality-reviewer`, `plan-recon`, `docwriter`) are rewritten to their +role: grounding-check and architect read `contracts/`; fieldtester +reads `INDEX.md` + `models/` (no-edit limit preserved, repointed); +bencher reads `models/rc-uniqueness.md` (Decision-9/Boehm narrative); +the rest point at `design/INDEX.md` as the spine. + +## Components + +The per-contract disposition (fixes the polymorphic link, planner +does not re-decide it): + +| Contract | Disposition | Rationale | +|----------|-------------|-----------| +| feature-acceptance | prose file | gate text, prose-authoritative | +| authoring-surface | prose file | binding Form-A constraints, prose-stated | +| roundtrip-invariant | prose file | the invariant statement is prose | +| memory-model | prose file | Decision 10 `### Language-design constraints (binding)` + `### Schema additions` + `### Codegen contract`; binding, prose-stated | +| data-model | prose file | the wire schema an author must produce is a *promise* (prose-authoritative); `design_schema_drift.rs` `include_str!`s it | +| float-semantics | prose file | author-facing; the diagnostic points here | +| typeclasses | prose file | coherence/dispatch rules + prelude classes; the Show diagnostic points here | +| tail-calls | prose file | the propagation rule is prose-stated, check-ratified | +| frozen-value-layout | prose file **+** source link | one-way human commitment AND codegen contract — deliberate dual-link | +| honesty-rule | prose file | rewritten; resolves the internal contradiction | +| embedding-abi | prose file | the M3-frozen ABI contract, author + host facing | +| verification | prose file | the cross-cycle verification contract | +| mangling | **source link only** | codegen behaviour; prose would duplicate code; `eq_ord_e2e.rs` ratifies | +| env-construction | **source link only** | codegen behaviour; `duplicate_ctor_pin.rs` ratifies | + +Models (always prose whitepapers): `rc-uniqueness` (Decision 10 +narrative + Decision 9 Boehm rationale), `typeclasses` (resolution / +monomorphisation narrative), `effects` (Decision 3 narrative), +`authoring-surface` (notation rationale, candidate notations, +empirical addendum), `pipeline` (Pipeline + CLI). + +Decision-record archive — `docs/journals/2026-05-19-design-decision-records.md`: +the `### Why not other memory models`, `### What this Decision +deliberately does not do` (×N), `### Empirical addendum`, +`### First choice and rollback plan`, and every "considered and +rejected" passage, moved whole at `###` granularity. The journals +`INDEX.md` gets the one-line pointer per project convention. + +## Data flow + +- **Architect, milestone close:** reads `design/INDEX.md` → walks + the Contracts table → for each row reads the `link` target → + measures drift against it. `architect_sweeps.sh` scans the + `design/` prose set; exit codes unchanged. +- **grounding-check, per spec:** reads `design/INDEX.md` → the + contract rows the spec's assumptions touch → composes. +- **LLM author, NoInstance:** the diagnostic names + `design/contracts/float-semantics.md` (or `…/typeclasses.md`) → + opens exactly that contract → self-corrects. +- **Future brainstorm tempted to re-propose region inference:** the + "why rejected" prose is in + `docs/journals/2026-05-19-design-decision-records.md`, reachable + from the journals INDEX — not in any contract file. +- **`design_index_pin.rs`, every `cargo test`:** parses INDEX.md → + asserts all links resolve, all contracts name a resolvable + ratifying-test, no contract carries decision-record prose, + `docs/DESIGN.md` is absent. + +## Error handling + +All failure modes fail closed: + +- INDEX row → missing target ⇒ `design_index_pin.rs` + `every_index_link_resolves` RED. +- A `contracts/` file regrows "we rejected"/"Why not other"/… ⇒ + `contracts_carry_no_decision_record_prose` RED (the conflation + tripwire — the milestone's reason to exist, enforced in code). +- `docs/DESIGN.md` resurrected ⇒ `design_md_is_gone` RED. +- A contract names a ratifying-test that does not resolve ⇒ + `every_contract_names_a_resolvable_ratifying_test` RED. +- `architect_sweeps.sh` cannot find `design/INDEX.md` ⇒ exit 2 + (preserved "infra missing" semantics, repointed). +- Content move lands without the `include_str!` retarget ⇒ + `cargo build` fails. This is the build-atomic fail-closed + property; the planner sequences the single landing build-green. +- **Recon-undercount countermeasure (acceptance gate).** The + milestone's acceptance includes a tree-wide + `grep -rIn 'DESIGN\.md'` over *all file types* + (`bench/ skills/ crates/ runtime/ ail-embed/ examples/ docs/ + CLAUDE.md`) returning **only** the append-only history docs + (`docs/journals/`, `docs/specs/`, `docs/plans/`, + `docs/roadmap.md`, `docs/WhatsNew.md`, `docs/journal-archive.md`) + — zero live references in code, scripts, agent files, or + comments. Recon proved the carrier's file-type list + (`*.md *.rs *.py *.sh *.toml`) silently misses `.c`/`.h`/`.ail`; + the gate is unfiltered (`grep -rIn`, no `--include`) and any + claimed-absent path is `ls`-verified. This is the + fourth-recurrence recon-undercount class made an explicit gate. + +## Testing strategy + +- **RED-first spine:** `design_index_pin.rs` (the 4 clauses above) + is written first; RED until `design/` exists, is consistent, and + `docs/DESIGN.md` is gone; GREEN when the split is complete and + faithful. +- **Retarget, not rewrite:** `design_schema_drift.rs`, + `docs_honesty_pin.rs`, `effect_doc_honesty_pin.rs` keep their + *property* (the schema/honesty invariant stays documented); only + the path/anchor moves. `design_schema_drift.rs` additionally + *simplifies* (the `## Data model`/`## Pipeline` slicer is removed + — the file boundary now bounds the section). +- **Lockstep E2Es:** `eq_float_noinstance.rs`, + `show_no_instance_e2e.rs` updated with the diagnostic strings; + they continue to assert the author-affordance (a correct, + resolvable pointer). +- **Whole-suite GREEN:** `cargo test` workspace-wide must be green + post-split (the `include_str!` retarget + all path moves + consistent). Build-atomicity makes a half-move a compile failure, + not a silent-wrong state. +- **Bench unaffected:** recon confirmed the bench harness + (`bench/check.py`, `compile_check.py`, `cross_lang.py`, + `run.sh`) has zero `DESIGN.md` references; only + `architect_sweeps.sh` (audit-time, not bench-time) opens it. + Generated IR is byte-identical (no codegen change — the + diagnostic *string* is not in the IR). Any bench firing is the + tracked P2 noise and is causally exonerable by byte-identical-IR. +- **Audit, mandatory at milestone close:** architect drift review + against the *new* `design/` (the architect's own reading list is + one of the rewritten artifacts — the audit validates the + structure it now reads); bencher causal exoneration as usual. +- **No fieldtest:** zero authoring-surface change. The + diagnostic-string change is a doc-pointer, not a language or + authoring-surface change. (Recorded explicitly so the post-audit + step is not skipped by omission but by reasoned exclusion.) + +## Acceptance criteria + +1. `docs/DESIGN.md` does not exist; `design/INDEX.md`, + `design/contracts/*.md`, `design/models/*.md`, and + `docs/journals/2026-05-19-design-decision-records.md` exist and + are internally consistent. +2. Every `###` subsection of the former DESIGN.md is accounted for + in exactly one destination (contract / model / decision-record); + no content is silently dropped. +3. `design/INDEX.md` Contracts table: every `link` resolves, every + row names a resolvable `ratifying-test`. Models table: every + `link` resolves. +4. `crates/ailang-core/tests/design_index_pin.rs` is GREEN with all + four clauses; it was demonstrably RED before the split landed. +5. `design_schema_drift.rs`, `docs_honesty_pin.rs`, + `effect_doc_honesty_pin.rs` are GREEN against the new files; + their protected properties are unchanged. +6. The compiler emits `design/contracts/float-semantics.md` / + `design/contracts/typeclasses.md` in the two NoInstance + diagnostics; `eq_float_noinstance.rs` and `show_no_instance_e2e.rs` + assert the new pointer and are GREEN. +7. `cargo test` workspace-wide is GREEN; `cargo build` is clean. +8. Tree-wide `grep -rIn 'DESIGN\.md'` (no `--include`) returns + matches **only** in the append-only history docs; zero live + references in code, scripts, agent files, SKILL bodies, + `CLAUDE.md`, `skills/README.md`, or comments. +9. `bench/architect_sweeps.sh` runs against `design/`, exits 0 on + the clean tree, and its exit-2 path triggers on a missing + `design/INDEX.md`. +10. The ~12 agent reading lists, the 5 SKILL.md bodies, + `CLAUDE.md`, and `skills/README.md` name the new spine; no agent + contract still instructs reading a file that does not exist. +11. The milestone landed in a build-atomic shape (no commit leaves + the workspace non-compiling).