spec: design-md-rolesplit — DESIGN.md role-split into design/ contracts+models ledger
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).
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user