# Audit — Embedding ABI — M2 (milestone close)

**Date:** 2026-05-18
**Scope:** `2db737c..fbeeade` (M2 = spec `1c58055` → plan `b3388c8` →
iter `c9a84b3` PARTIAL 4/9 + Boss spec-defect repair → iter `fbeeade`
DONE 5–9). HEAD `fbeeade`, working tree clean at audit time.
**Outcome:** DRIFT (one `[medium]` + coupled `[low]` doc-honesty
item → fix via tidy iteration). Bench `check.py` exit 1 — **all
firings causally exonerated as the two tracked roadmap-P2 noise
families; NO baseline ratified, NOT an M2 regression.**

## Step 1 — Architect drift review

Status: `drift_found`. No DESIGN.md/spec-contract drift, no
unrequested extras, Invariant 1 intact, internal-convention
byte-invariance held, Decision-10 atomicity note present-tense-
correct (sanitiser-verified this iter), spec→DESIGN.md→code lockstep
complete, `docs_honesty_pin.rs` green unmodified, the Boss
spec-defect repair correctly reflected in both spec and shipped
tests.

Actionable drift (one item, two coupled sites):

- **`[medium]` `docs/DESIGN.md:2266`** — the section header reads
  `## Embedding ABI (M1)` while the body (`:2285–2295`) now
  describes the post-M2 ctx ABI as present-tense current state
  ("Every exported entrypoint takes a mandatory leading
  `ailang_ctx_t*` (M2)… the ctx-threaded C signature is the M2
  shape"). Current-state-mirror honesty mismatch: a header that
  misdescribes its own present-tense body. Not a Sweep-5 catch (the
  body prose itself is correctly present-tense — the
  docs-honesty-lint machinery does not auto-flag a header/body
  desync; only a read catches it). The iter journal's Concerns +
  Known-debt flagged it accurately and truthfully — Task 7's edit
  regions were *deliberately* scope-limited (provisional-until-M3
  sentence + Decision 10) to preserve the `docs_honesty_pin.rs:135`
  verbatim "Export parameters are written **bare**…" assertion 12
  lines below the header. Deferral reasoning sound; the mismatch is
  real drift that must not persist past this milestone close.
- **`[low]` `docs/DESIGN.md:2354`** — schema-block cross-reference
  comment still reads `see §"Embedding ABI (M1)"`; stale xref
  coupled to the header above. Must move in lockstep with any
  header rename so the fix is scoped header + xref +
  `docs_honesty_pin.rs:134–136` `(M1)`-token audit together, not
  the header alone.

Architect recommendation: one scoped tidy iteration.

## Step 2 — Bench regression

| Script | Exit |
|---|---|
| `bench/check.py` | **1** |
| `bench/compile_check.py` | 0 (clean — 24/24 stable) |
| `bench/cross_lang.py` | 0 (clean — 25/25 stable, **every `rc_over_c` ratio within tol**) |

`check.py` 63 metrics: 3 regressed, 2 improved-beyond-tol, 58 stable.
The 3 firings (verbatim): `throughput.bench_list_sum.bump_s`
0.046→0.052 +13.57% (tol 10%); `latency.explicit_at_rc.max_us`
413.0→751.5 +81.96% (tol 25%); `latency.implicit_at_rc.max_us`
477.3→661.4 +38.57% (tol 30%). Every `*.rc_s`/`*.gc_s` throughput and
every rc-latency median/p99/p99.9 stable within tol.

Because M2 genuinely changed the benched runtime path
(`runtime/rc.c`: the two RC-counter sites gained a `__thread` load +
null-branch ahead of `g_rc_*++`), the byte-identical exoneration
method did **not** apply — `ailang-bencher` was dispatched for
hypothesis-driven localisation (H0 = real M2 regression; H1 =
tracked-P2 noise, M2 bench-neutral).

**Bencher verdict: H0 refuted; all three firings
tracked-noise-causally-exonerated.** Method: swapped *only* `rc.c`
between `2db737c` and `fbeeade` (same `ail` binary, same fixtures),
disassembled the delta, interleaved core-pinned A/B.
- `bump_s`: causally **impossible** from M2 — `bump_malloc`
  disassembly has 0 refs to `__ail_tls_ctx`/rc counters; the
  M2-inert bump binary independently reproduces ~+12% vs the stale
  0.046 baseline. Roadmap-P2 `*.bump_s` environmental staleness.
- M2's rc.c hunk compiled **branchless** (3 insns: `mov %fs`,
  `test`, `cmovne`) and measured **free** (HEAD median −0.63% vs
  pre-M2, inside intra-arm spread) — the H0 mechanism does not
  exist; no per-alloc cost.
- `*.max_us`: median/p99 flat across rc.c variants (a systematic
  per-alloc cost must move them and does not); max_us
  non-reproducible within a single fixed binary (3.2× spread).
  Roadmap-P2 `*.max_us` `-n 5` structural false-positive (now its
  4th consecutive no-runtime-change-attributable firing).

Limitations (bencher-stated): single host; N=15 moderate for
max-tail — median/p99 verdict solid, max verdict rests on the
(strong, N-bounded) non-reproducibility argument; gc latency arm not
re-measured (no gc firing; rc/gc share the identical M2 hunk).

## Step 3 — Classification & resolution

| Item | Class | Resolution |
|---|---|---|
| `[medium]` DESIGN.md:2266 stale `(M1)` header + `[low]` :2354 xref | **fix** | one tidy iteration `embedding-abi-m2.tidy`: rename the `## Embedding ABI (M1)` header to drop the milestone tag (current-state-mirror), lockstep the `:2354` cross-reference and the `docs_honesty_pin.rs:134–136` comment/assert-message `(M1)` token — the pinned *substring* (`:135`, the "Export parameters are written **bare**…" sentence) stays verbatim untouched. planner → implement. |
| `check.py` exit 1 — 3 firings | **carry-on** | causally exonerated as the two pre-existing roadmap-P2 noise families (`*.bump_s` staleness; `*.max_us` `-n 5` false-positive). **No baseline ratified** (bencher wrote nothing to baseline; these are not M2 artefacts). The P2 items remain tracked on the roadmap; retiring the `bump_s` stale baseline is a separate roadmap-P2 action against that item, explicitly NOT this milestone. |
| `compile_check.py` / `cross_lang.py` | carry-on | clean (exit 0). |

**Milestone M2 is substantively closed and sound** (capability
sanitiser-verified, all contract invariants held). The one open
drift is a doc-honesty header desync, fixed by the tidy iteration
dispatched next; the roadmap `[~]`→`[x]` flip follows the tidy
landing clean. No ratify. No re-audit deferral.
