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).
5.9 KiB
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.mdlines 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.rslines 2438-2448 —local_types.get("prelude")fallback inrewrite_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-2099rewritten: "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 asexamples/prelude.ailinailang-surfaceand parsed at compile time viaailang_surface::parse_prelude."docs/DESIGN.md:2141rewritten: "exactly the seven named carve-out files exist".crates/ail/src/main.rs:2427-2448— theor_elsearm scanninglocal_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: repopulatelocal_types["prelude"]explicitly viaparse_prelude). The owner-search now scansimport_namesonly. No behavioural change against the current corpus (theor_elsearm 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.rsdead 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 inrewrite_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.jsondeleted; the prelude exists on disk only asexamples/prelude.ail.crates/ailang-core/src/contains zero literal-"prelude"strings.crates/ail/src/main.rscontains 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 inailang-coreand composed byailang-surface::load_workspace. ailang_surface::parse_prelude+PRELUDE_AILare the canonical embed surface, re-exported fromailang-surface/src/lib.rs.- The CLAUDE.md "authors write
.ail; the build derives the JSON-AST in-process viaailang_surface::parse" doctrine holds without exception; the prelude was the last carve-out and is now inside the doctrine. - 573 tests green workspace-wide.