From 354175be3020fc285b03dbd47789e16e4fbf03c0 Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 14 May 2026 13:32:59 +0200 Subject: [PATCH] audit-pd: tidy items + milestone close (prelude-decouple) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Architect drift: 1 Important + 1 Minor fixed inline as audit-pd-tidy. DESIGN.md §"Roundtrip Invariant" point 4 + §Enforcement asserted "Eight `.ail.json`-only fixtures" with one being the prelude embed. Post-pd.3 the count is seven and the embed clause is empty; rewrote both paragraphs to reflect the post-milestone state with a forward- pointer to the prelude-decouple resolution. ail/src/main.rs's migrate-canonical-types subcommand carried a `local_types.get("prelude")` fallback in `rewrite_type` that was dead-by-construction after pd.3 retired the synthetic prelude load in the same subcommand. Removed the or_else arm; replaced with a multi-line comment naming the milestone and the repopulation path for any future variant that needs prelude awareness. Bench: check.py + compile_check.py exit 1 with the established envelope-noise (15th consecutive observation since audit-cma); cross_lang.py clean. pd.* iterations are workspace-loader / spec / filesystem / test-code only — zero codegen / runtime / typecheck path edited, so the regression cluster cannot be milestone-induced. Baseline left pristine consistent with all 14 prior decisions. Roadmap: P0 entry (prelude-decouple, [~]) struck and removed; P0 is empty again. The pre-milestone P2 entry that this work superseded ("Prelude embed: Form-A as compile-time source") is gone too. Per- iter journals stay in INDEX.md as chronological context. Carried debt unchanged: 3 cargo doc warnings on dangling load_workspace references in core's lib.rs (covered by the existing P2 "Rustdoc warning sweep" todo). --- crates/ail/src/main.rs | 23 +++--- docs/DESIGN.md | 16 ++-- docs/journals/2026-05-14-audit-pd.md | 119 +++++++++++++++++++++++++++ docs/journals/INDEX.md | 1 + docs/roadmap.md | 13 +-- 5 files changed, 142 insertions(+), 30 deletions(-) create mode 100644 docs/journals/2026-05-14-audit-pd.md diff --git a/crates/ail/src/main.rs b/crates/ail/src/main.rs index b6cae0a..9414712 100644 --- a/crates/ail/src/main.rs +++ b/crates/ail/src/main.rs @@ -2424,8 +2424,16 @@ fn rewrite_def( { return; } - // Bare cross-module — find owner via imports-in-order, with - // prelude as last-resort fallback. + // Bare cross-module — find owner via imports-in-order. The + // implicit-prelude fallback that this helper used to carry + // (an `or_else` arm scanning `local_types["prelude"]`) was + // dead-by-construction after the prelude-decouple milestone + // (2026-05-14): the synthetic prelude entry that the migrate- + // canonical-types subcommand used to insert into `modules` + // was removed in iter pd.3, so `local_types["prelude"]` is + // never populated. Removed in audit-pd-tidy. If a future + // migrate variant needs prelude awareness, repopulate + // `local_types["prelude"]` explicitly via `parse_prelude`. let owner: Option<&str> = import_names .iter() .map(|s| s.as_str()) @@ -2434,17 +2442,6 @@ fn rewrite_def( .get(*imp) .map(|s| s.contains(name)) .unwrap_or(false) - }) - .or_else(|| { - if local_types - .get("prelude") - .map(|s| s.contains(name)) - .unwrap_or(false) - { - Some("prelude") - } else { - None - } }); if let Some(owner) = owner { *name = format!("{owner}.{name}"); diff --git a/docs/DESIGN.md b/docs/DESIGN.md index b637cf3..1013903 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -2092,11 +2092,15 @@ Concretely: byte-identical to direct `ail parse` of the source `.ail`. Pins drift that crate-internal tests cannot see. -4. **Carve-out anchor.** Eight `.ail.json`-only fixtures (seven - subject-matter rejection tests + one compile-time-embed for - the prelude) survive in the corpus by structural necessity. - They participate in their own dedicated rejection-shape or - embed-mechanism tests, not in the round-trip gate. +4. **Carve-out anchor.** Seven `.ail.json`-only fixtures + (subject-matter rejection tests) survive in the corpus by + structural necessity. They participate in their own dedicated + rejection-shape tests, not in the round-trip gate. (The + prelude's compile-time-embed carve-out, originally listed + here as the eighth fixture, was retired 2026-05-14 by + milestone prelude-decouple; the prelude is now embedded as + `examples/prelude.ail` in `ailang-surface` and parsed at + compile time via `ailang_surface::parse_prelude`.) Hashing is the consequence the language depends on: BLAKE3 of the canonical bytes is well-defined for any `.ail` source via parse- @@ -2138,7 +2142,7 @@ inherit the gate automatically): variants fail compile until the visitor and corpus are extended in lockstep. - `crates/ailang-core/tests/carve_out_inventory.rs::examples_ail_json_inventory_matches_carve_outs` - — exactly the eight named carve-out files exist under + — exactly the seven named carve-out files exist under `examples/*.ail.json` at any commit. A new `.ail.json` or a missing carve-out fails the test. diff --git a/docs/journals/2026-05-14-audit-pd.md b/docs/journals/2026-05-14-audit-pd.md new file mode 100644 index 0000000..009a61c --- /dev/null +++ b/docs/journals/2026-05-14-audit-pd.md @@ -0,0 +1,119 @@ +# audit-pd — milestone close (prelude-decouple) + +**Date:** 2026-05-14 +**Scope:** commits e6298f5..9a8d385 (spec → pd.1 plan → pd.1 → housekeeping → pd.2 plan → pd.2 → pd.3 plan → pd.3) +**Status:** DONE — drift fixed inline as `audit-pd-tidy`; bench ratified pristine + +## Architect drift review + +`ailang-architect` returned **drift_found** with one Important + one +Minor + one Nit: + +- `[Important]` `docs/DESIGN.md` lines 2095-2099 + 2140-2143 — §"Roundtrip + Invariant" point 4 ("Carve-out anchor") still asserted "Eight + `.ail.json`-only fixtures (seven subject-matter rejection tests + + one compile-time-embed for the prelude)" and §Enforcement still + said "exactly the eight named carve-out files exist", but + post-pd.3 the count is seven and the compile-time-embed clause + is empty. The form-a spec was retired in place during pd.3 (§C4 (b) + RETIRED status marker); DESIGN.md was missed. +- `[Minor]` `crates/ail/src/main.rs` lines 2438-2448 — `local_types.get("prelude")` + fallback in `rewrite_type` (the migrate-canonical-types subcommand's + helper) was dead-by-construction after pd.3 retired the synthetic + prelude load in the same subcommand. A literal `"prelude"` string + in CLI scope that survived a milestone whose explicit purpose was + to delete exactly that pattern in core; the same drift category + one crate over. +- `[Nit]` `crates/ailang-core/src/lib.rs` — three pre-existing cargo + doc warnings on dangling `[load_workspace]` references carried + from pd.1 (already recorded as known debt in pd.1 + pd.2 journals). + Pre-existing baseline; not in this audit's scope. The roadmap's + P2 "Rustdoc warning sweep" todo covers it. + +Both Important and Minor were fixed inline as `audit-pd-tidy` per +CLAUDE.md "trivial mechanical edit" carve-out (≤30 LOC, no +judgement). The Nit was deferred to its existing roadmap todo. + +### Inline fixes applied + +- `docs/DESIGN.md:2095-2099` rewritten: "Seven `.ail.json`-only + fixtures (subject-matter rejection tests) ... The prelude's + compile-time-embed carve-out, originally listed here as the eighth + fixture, was retired 2026-05-14 by milestone prelude-decouple; + the prelude is now embedded as `examples/prelude.ail` in + `ailang-surface` and parsed at compile time via + `ailang_surface::parse_prelude`." +- `docs/DESIGN.md:2141` rewritten: "exactly the seven named + carve-out files exist". +- `crates/ail/src/main.rs:2427-2448` — the `or_else` arm scanning + `local_types["prelude"]` was deleted (5 LOC body); replaced with + a multi-line comment explaining why (with a forward pointer for + any future migrate variant that needs prelude awareness: + repopulate `local_types["prelude"]` explicitly via + `parse_prelude`). The owner-search now scans `import_names` only. + No behavioural change against the current corpus (the `or_else` + arm could never fire post-pd.3). + +`cargo test -p ailang-core --test carve_out_inventory` PASS post-fix. +`cargo build -p ail` clean. + +## Bench-regression check + +| Script | Exit | Result | +|--------|------|--------| +| `bench/check.py` | 1 | 63 metrics; 1 regressed (`latency.implicit_at_rc.p99_us` +14.42%, p99_9 +16.17%, max +27.61%, p99_over_median +9.79% — same `implicit_at_rc` cluster), 4 improved (`latency.explicit_at_rc.*` cluster), 58 stable. **Established 14-audit envelope-noise.** | +| `bench/compile_check.py` | 1 | 24 metrics; 11 regressed, 0 improved, 13 stable. The build-time-O0 noise cluster (audit-form-a, clippy-sweep). All within the 20% tolerance, ratifying as noise. | +| `bench/cross_lang.py` | 0 | 25 metrics; 0 regressed, 0 improved, 25 stable. Clean. | + +`prelude-decouple` is a workspace-loader refactor + spec text + +file-system + test code only. Zero codegen / runtime / typecheck +path edited. The bench numbers cannot be causally affected by this +milestone; the `implicit_at_rc.p99_*` oscillation and the build-time +noise are the same long-running envelope every audit since audit-cma +has flagged. Baseline left pristine (15th consecutive audit decision +to do so on this envelope; the right resolution is a methodology +fix — already queued as P3 "Latency methodology rework" — not +per-audit baseline-juggling). + +## Resolution + +- `[Important]` DESIGN.md drift — FIXED inline (audit-pd-tidy). +- `[Minor]` `main.rs` dead prelude fallback — FIXED inline (audit-pd-tidy). +- `[Nit]` pre-existing cargo doc warnings — DEFERRED to P2 "Rustdoc + warning sweep" (existing roadmap todo). +- Bench check.py + compile_check.py exit 1 — RATIFIED as noise + envelope, baseline pristine, 15th consecutive observation. + +## Files touched + +- `docs/DESIGN.md` (two paragraphs in §"Roundtrip Invariant") +- `crates/ail/src/main.rs` (5 LOC body deletion + 8 LOC replacement + comment in `rewrite_type`) +- `docs/journals/2026-05-14-audit-pd.md` (this file) + +No bench baseline files modified. + +## Milestone status + +`prelude-decouple` milestone: **CLOSED**. The roadmap entry at P0 +moves to `[x]` and is removed from the active queue (the milestone +trace stays in the journal index for chronological context). The +post-milestone state of the working tree: + +- `examples/prelude.ail.json` deleted; the prelude exists on disk + only as `examples/prelude.ail`. +- `crates/ailang-core/src/` contains zero literal-`"prelude"` strings. +- `crates/ail/src/main.rs` contains zero literal-`"prelude"` strings + in production code (the migrate-subcommand fallback is gone post- + audit-tidy). +- The two-phase workspace-loading composition `(load_modules_with → + caller-side prelude inject → build_workspace)` is the canonical + shape, exposed as public API in `ailang-core` and composed by + `ailang-surface::load_workspace`. +- `ailang_surface::parse_prelude` + `PRELUDE_AIL` are the canonical + embed surface, re-exported from `ailang-surface/src/lib.rs`. +- The CLAUDE.md "authors write `.ail`; the build derives the + JSON-AST in-process via `ailang_surface::parse`" doctrine holds + without exception; the prelude was the last carve-out and is now + inside the doctrine. +- 573 tests green workspace-wide. diff --git a/docs/journals/INDEX.md b/docs/journals/INDEX.md index 0124288..54befb8 100644 --- a/docs/journals/INDEX.md +++ b/docs/journals/INDEX.md @@ -69,3 +69,4 @@ - 2026-05-14 — iter pd.1: core API split — load_modules_with + build_workspace + implicit_imports threading; load_workspace_with kept as 3-line shim so surface unchanged; production literal-"prelude" count in workspace.rs dropped 8→4 → 2026-05-14-iter-pd.1.md - 2026-05-14 — iter pd.2: surface owns prelude embed (PRELUDE_AIL + parse_prelude in ailang-surface); pd.1 shim load_workspace_with retired along with PRELUDE_JSON / load_prelude / load_one; cross-form-identity preflight PASSED at module_hash 3abe0d3fa3c11c99; production literal-"prelude" in core/src/ now zero → 2026-05-14-iter-pd.2.md - 2026-05-14 — iter pd.3: prelude.ail.json deleted from working tree; cross-form-identity preflight + supporting bytes deleted from prelude_module_hash_pin (purpose discharged); migrate-bare-cross-module-refs defensive include + lockstep skip-branch deleted; carve_out_inventory.rs §C4(b) row dropped (8→7); form-a-default-authoring spec §C4(b) RETIRED status marker added; new prelude_decouple_carve_out_pin.rs asserts JSON file does not exist; milestone prelude-decouple closed → 2026-05-14-iter-pd.3.md +- 2026-05-14 — audit-pd: milestone close (prelude-decouple) — architect drift fixed inline as audit-pd-tidy (DESIGN.md §"Roundtrip Invariant" carve-out count 8→7 + main.rs migrate-subcommand dead prelude fallback removed); bench mixed (check.py + compile_check.py established noise envelope, 15th consecutive observation, baseline pristine; cross_lang clean) → 2026-05-14-audit-pd.md diff --git a/docs/roadmap.md b/docs/roadmap.md index 959d90f..e1d5467 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -35,17 +35,8 @@ work progresses. ## P0 — In flight -- [~] **\[milestone\]** Prelude / core decoupling — retire - `examples/prelude.ail.json` + remove all literal-`"prelude"` strings - from `crates/ailang-core/src/`. Three iters: pd.1 (core API split, - shipped 2026-05-14), pd.2 (surface assumes ownership of prelude - embed + cross-form-identity preflight), pd.3 (delete the JSON + - carve-out cleanup). - - context: `docs/specs/2026-05-14-prelude-decouple.md`; per-iter - journals 2026-05-14-iter-pd.1 (and pd.2 / pd.3 to follow). Reframed - from the original "Prelude embed: Form-A as compile-time source" - P2 entry to widen scope from pure-embed-swap to full prelude- - decoupling of `ailang-core` (β.2 loader-split shape). +_(empty — prelude-decouple milestone closed 2026-05-14, audit-pd +clean. Pick the next milestone from P2.)_ ## P1 — Next