6.7 KiB
audit Embedding ABI — M3 (milestone close)
Date: 2026-05-18
Milestone range: 9a609ae..4ea8bc5 (M2 roadmap-close → M3 DONE)
Outcome: DRIFT — one [medium] + one [low] doc-honesty item
→ a single docs-honesty tidy iteration; bench check.py exit 1
decisively causally exonerated (byte-identical generated IR),
NO ratify. compile_check / cross_lang clean.
Step 1 — Architect drift review (drift_found)
Dispatched ailang-architect over 9a609ae..HEAD.
What holds (audited clean):
- Invariant 1 (clean core): zero
Cargo.toml/runtime dep changes;ailang-core/ailang-codegen/runtime/touches are only the spec-scoped widen + lockstep comments + pins. Nodata-server/finance knowledge entered. - M1/M2 internal-convention byte-invariant held: the M2
Target::StaticLibforwarder body and the internal@ail_<mod>_<fn>/_adapter/_closconvention are absent from the diff (untouched). Thellvm_scalar/is_c_abi_typewiden is exactly the spec scope — no newCheckErrorvariant, no schema field, no Form-A change (M2-style honoured). - Frozen-layout SSOT consistent: DESIGN.md
### Frozen value layout(:2321-2359) is present-tense and matches bothmatch_lower.rslower_ctor(size = 8 + n*8, tag@0, fields@8+i*8) and the enforcing byte-pin (@ailang_rc_alloc(i64 24), tag@0, @8/@16). All three lockstep// FROZEN ABIpointers present and aimed at the SSOT. The Boss spec-consistency repair note + §"Testing strategy" 3/4 + the journal Boss-adjudication / Re-dispatch sections are mutually consistent and honest about the M2-TLS cross-attribution (correct behaviour, not a leak).
Drift / debt:
[medium]docs/DESIGN.md:2299-2302— a surviving M1-era paragraph still asserts modes "apply only to heap-shaped types, which the scalar-only rule above forbids at an export boundary anyway".:2280-2284was rewritten to accept a single-ctor record, so there is no longer a scalar-only rule; this sentence now contradicts the section's own freeze and the(own (con State))/(borrow (con State))mode contract at:2345-2351. Canonical-spec internal contradiction the milestone owned. → fix (docs-honesty tidy).[low]crates/ailang-codegen/src/lib.rs:608-610— the forwarder-body comment still says the gate "guarantees every param and the ret areInt/Float; map Int→i64, Float→double", now false (records→ptr). The architect classified this "carried debt, not a scope miss" — the forwarder body is contractually byte-frozen, so the comment was genuinely outside any M3 edit region. Comment-only; correcting it changes no emitted IR (the byte-pin + forwarder-IR pin assert IR, not source comments). → fix, folded into the same tidy (doc-honesty hygiene; the IR pins are the guard that generated code stays byte-frozen).
(Boss already caught + fixed in-line one sibling stale //
gate-comment block at check/lib.rs:1917-1922 during the DONE
inspect; the architect found no further siblings.)
Step 2 — Bench-regression trio
| script | exit | summary |
|---|---|---|
bench/check.py |
1 | 63 metrics; 3 regressed, 2 improved, 58 stable |
bench/compile_check.py |
0 | 24 metrics; 0 regressed, 24 stable |
bench/cross_lang.py |
0 | 25 metrics; 0 regressed, 25 stable (every rc_over_c within tol) |
check.py exit 1 — the 3 firings:
| metric | baseline | actual | diff | tol |
|---|---|---|---|---|
throughput.bench_list_sum.bump_s |
0.046 | 0.052 | +12.62% | 10.0% |
latency.implicit_at_rc.p99_9_us |
452.0 | 580.6 | +28.45% | 25.0% |
latency.implicit_at_rc.max_us |
477.3 | 645.2 | +35.18% | 30.0% |
Both are the two standing tracked P2 noise families (roadmap
P2): the *.bump_s stale-baseline (~+5–13% environmental band on
current hardware) and the *.max_us/p99_9 -n 5 tail-jitter
structural false-positive (signature: same benchmark's median_us
+5.11% ok, p99_us +15.08% ok — only the extreme tail quantiles
fire, the worst-of-~5000-samples-over-5-runs pattern).
Causal exoneration (decisive, not hand-waved — M2-audit method).
M3 changed no executable-path codegen (architect-confirmed: M2
forwarder body byte-unchanged; the only codegen touches are the
llvm_scalar record→ptr arm — reachable solely for an (export)
single-ctor record, and no bench_* program has an (export) — the
ailang-check is_c_abi_type widen, and lockstep comments). Built
ail at HEAD and at the pre-M3 commit 9a609ae in an isolated
worktree; the generated IR is byte-identical (cmp -s) for every
firing benchmark and its neighbours:
bench_list_sum: IR BYTE-IDENTICAL (HEAD == 9a609ae)
bench_list_sum_explicit: IR BYTE-IDENTICAL
bench_latency_implicit: IR BYTE-IDENTICAL
bench_tree_walk: IR BYTE-IDENTICAL
The IR is what is handed to clang -O2 (deterministic), so the
bench binaries are byte-identical and M3 causation is logically
impossible. NO baseline ratify (these are not M3 artefacts; the
two P2 items stay separately tracked). Bench → carry-on.
Step 3 — Classification
| item | class | recommendation |
|---|---|---|
[medium] DESIGN.md:2299-2302 scalar-only-rule contradiction |
drift | fix — docs-honesty tidy |
[low] codegen forwarder-comment Int/Float-only staleness |
drift | fix — folded into the same tidy |
check.py exit 1 (3 firings) |
tracked-noise | carry-on, NO ratify (byte-identical-IR causal exoneration) |
| compile_check / cross_lang | clean | carry-on |
Step 4 — Resolution (Boss)
- Drift → one docs-honesty tidy iteration
embedding-abi-m3.tidy(the M2-audit[medium]+[low] doc-honesty → tidyprecedent shape): reconcile the stale DESIGN.md:2299-2302 "scalar-only rule above forbids" paragraph against the frozen SSOT + the own/borrow mode contract, pin-safe (thedocs_honesty_pin.rs:135pinned sentence — "Export parameters are written bare…", shifted to ~:2299by the M3.1 DONE — sits in/adjacent to the edit zone; the tidy plan must keep it byte-verbatim+contiguous, planner Step-5 item-6 / M2.tidy precedent); plus the[low]codegen forwarder-comment honesty fix (comment-only, the byte-pin + forwarder-IR pin stay green as the guard that generated code is untouched). Routed viaplanner→implement. - Bench → carry-on, NO ratify. Causally exonerated; the two tracked P2 noise todos stay as-is.
Milestone is substantively closed + sound (record crosses the C ABI
in/out, ownership follows the declared mode, the value layout is
frozen + byte-pin-enforced, all contract invariants held,
Invariant 1 clean). The roadmap M3 [~]→[x] follows the tidy
landing clean.