iter remove-mut-var-assign.tidy: form_a.md grammar deletion + audit close

Milestone-close audit for remove-mut-var-assign (48e7774..07f0802).

Architect drift: one [high] — crates/ailang-core/specs/form_a.md
still documented the full mut/var/assign construct (EBNF 286-288,
prose 308-328, dangling `like mut` at 332). The spec named it for
deletion; the iter missed it. Root cause = the recon-undercount
class (4th recurrence) plus a Boss error: a plan-time grep checked
only docs/form_a.md (dir-scoped), got "No such file", and that
unverified non-existence claim propagated into the recon brief —
the real file is crates/ailang-core/specs/form_a.md. A stale doc
never compile-fails so the implement compile-sweep could not catch
it. Fixed inline as a Boss .tidy (CLAUDE.md context-already-loaded
carve-out; full review discipline kept — tree-wide verified zero
construct residue except the roadmap entry naming the milestone
itself; grammar now reads coherently reuse-as -> loop -> recur).

Bench causally exonerated: HEAD vs 48e7774 bench binaries
cmp-byte-identical (the -2520-line removal alters zero bytes of the
firing fixtures' machine code). check.py exit 1's 3 firings are the
tracked P2 bump_s environmental staleness + single-sample -n5
max_us jitter (explicit_at_rc.max_us +108% -> -2.30% ok on
identical-code rerun). PRISTINE met on the merits; NO baseline
ratify (Iron Law + spec foreclosure).

Roadmap: P0 refreshed (audit clean, fieldtest remains); the
ailang-plan-recon P2 escalated in place to a structural
recon-contract defect (2 named gaps + concrete fix); a new distinct
P2 filed for the check.py *.max_us -n5 3-for-3 false-positive.
This commit is contained in:
2026-05-18 11:19:48 +02:00
parent 07f080256c
commit 4837871ddf
4 changed files with 172 additions and 46 deletions
+1 -25
View File
@@ -283,9 +283,6 @@ Parenthesised forms:
(seq EFFECTFUL-TERM RESULT-TERM) ; sequence; lhs evaluated for effect
(clone TERM) ; explicit RC clone (Iter 18c.1)
(reuse-as SOURCE-TERM BODY-TERM) ; explicit reuse hint (Iter 18d.1)
(mut (var NAME TYPE INIT)* BODY-TERM+) ; local mutable-state block (Iter mut.1)
(var NAME TYPE INIT) ; mut-var declaration; only inside (mut ...)
(assign NAME VALUE-TERM) ; mut-var update; only inside (mut ...)
(loop (NAME TYPE INIT)* BODY-TERM+) ; strict iteration block (loop-recur)
(recur ARG*) ; re-enter enclosing loop (loop-recur)
```
@@ -305,31 +302,10 @@ Notes:
- `reuse-as` requires `SOURCE-TERM` to be a bare variable reference
(a `NAME` in the term grammar). Anything else fails the linearity
check with `reuse-as-source-not-bare-var`.
- `mut` opens a lexically-scoped block of mutable bindings. The
body is a flat sequence of zero or more Unit-typed statements
followed by exactly one final expression of any supported type;
the parser right-folds this trailing sequence into `Term::Seq`
inside `Term::Mut.body`, so the canonical JSON-AST always sees a
single `body: Term`. The `vars` array stays present in canonical
JSON even when empty (a `(mut EXPR)` form with no vars is legal
and round-trips uniformly). A `(mut)` form with neither vars nor
body is rejected at parse. Mut-var element types are restricted
to the stack-resident primitives Int / Float / Bool / Unit in
this milestone; the typecheck pass (iter mut.2) rejects other
types with `mut-var-unsupported-type`.
- `(var NAME TYPE INIT)` is only legal as a leading entry inside a
`(mut ...)` block. Outside the parser rejects `var` as an
unknown term head.
- `(assign NAME VALUE-TERM)` is only legal as a sub-term inside a
`(mut ...)` block whose `vars` includes a var with the matching
`NAME`. Outside the parser accepts the shape but the typecheck
pass (iter mut.2) rejects it with `mut-assign-out-of-scope`. The
expression's static type is Unit. See spec
`docs/specs/2026-05-15-mut-local.md`.
- `loop` opens a strict iteration block. `(NAME TYPE INIT)` binder
triples (zero or more) are followed by a body of zero or more
Unit-typed statements and exactly one final expression (right-
folded into `Term::Seq` like `mut`). `recur` re-enters the
folded into `Term::Seq`). `recur` re-enters the
lexically innermost enclosing `loop`, rebinding its binders
positionally; `(recur ARG*)`'s arg count must equal the binder
count and `recur` must be in tail position of the loop body —
@@ -0,0 +1,108 @@
# audit — remove-mut-var-assign milestone close
**Date:** 2026-05-18
**Scope:** `48e7774..07f0802` (prev close → the single terminal iter)
**Outcome:** CLEAN after one inline `.tidy` fix; bench causally
exonerated; two P2 roadmap todos filed/strengthened. Fieldtest
remains (surface-touching milestone).
## Step 1 — Architect drift review
**`[high]``crates/ailang-core/specs/form_a.md` (EBNF 286-288,
prose 308-328, dangling `like mut` at 332).** The live in-tree
Form-A grammar reference still documented the full `mut`/`var`/
`assign` construct. The spec (Components #2, Architecture table
row 2) explicitly named "form_a.md" for deletion; the
schema-vs-doc honesty invariant the milestone advertises was
broken. **Root cause = the recon-undercount class (4th
recurrence), and specifically a Boss error:** at plan time the
Boss grepped `docs/form_a.md` (dir-scoped), got "No such file",
concluded "form_a.md does not exist", and propagated that
unverified non-existence claim into the recon brief. The file
lives at `crates/ailang-core/specs/form_a.md` and is actively
maintained (form-a.tidy edited it) — not frozen historical
record. A compile-driven sweep cannot catch this: a stale doc
never produces `E0004`/`E0061`.
**Resolution — inline Boss `.tidy`, not planner+implement.**
Rationale (CLAUDE.md "When NOT to delegate": context already
loaded, an agent would redo all milestone reading for a ~40-line
single-file doc deletion whose design was already settled by the
approved spec): deleted the three EBNF productions (keeping
`reuse-as``loop``recur`), the three mut/var/assign prose
bullets, and reworded the surviving `loop` bullet so its
"right-folded into `Term::Seq`" no longer back-references the
deleted `mut`. Full review-and-commit discipline kept (no
discipline shed for the carve-out): verified tree-wide that the
only remaining `Term::Mut`/`Term::Assign`/`MutVar` strings in
`crates/` + `docs/DESIGN.md` + `docs/roadmap.md` are the roadmap
entry *describing the milestone itself* (not residue), and
form_a.md's two remaining `mut`/`var` substrings are the unrelated
`[unbound-var]` / `reuse-as-source-not-bare-var` diagnostic names.
Grammar + notes read coherently after the cut.
**`[medium]` — process-drift, recon-undercount 4th recurrence.**
The existing loop-recur.tidy P2 (`ailang-plan-recon`
cross-crate-caller-undercount) is demonstrably insufficient: the
class now recurs through a *new* site type each time (test bodies,
drift pins, carve-out files, and now a spec-named non-compiled
doc + an unverified existence claim feeding the recon brief).
Escalated that P2 in place — broadened from "cross-crate caller"
to a structural recon-contract defect with two named gaps
(non-compile-checked spec-named sites; unverified "X does not
exist" claims inheriting into a recon brief), and a concrete
agent-definition fix (compile-driven enumeration as authoritative
code-site set **plus** an `ls`-verified spec-named-path existence
table). Not a code defect; an agent-discipline fix, parked P2.
## Step 2 — Bench-regression
`bench/check.py` **exit 1** (3 firings); `compile_check.py`
**exit 0** (24/24 stable — no check-time tax, consistent with a
pure removal); `cross_lang.py` **exit 0** (25/25 stable, incl. the
independent `bench_list_sum.ail_bump_s` +2.95% ok).
check.py firings: `throughput.bench_list_sum.bump_s` +12.51%;
`latency.explicit_at_rc.max_us` +108.38%;
`latency.implicit_at_rc.max_us` +66.46%. All medians/p99 stable.
**Bencher localisation — causal exoneration (decisive).** Built
`ail` at HEAD and at pre-milestone `48e7774`; the three
firing-relevant bench binaries (`list_sum_bump`, `lat_expl_rc`,
`lat_impl_rc`) are **`cmp`-byte-identical** across the milestone.
The 2520-line removal diff does not alter one byte of these
fixtures' machine code (none contain `mut`); no causal mechanism
exists. By elimination every firing is non-code-caused.
Per-firing verdict: `bump_s` = the tracked P2 environmental
staleness (stable ~+1114% across 4 runs, byte-identical binary,
cross_lang corroborates); both `*.max_us` = single-sample `-n 5`
jitter (`explicit_at_rc.max_us` collapsed +108%→**-2.30% ok** by
an identical-code rerun3; `implicit_at_rc.max_us` swings
477→1172→843→756 on the identical binary while its median holds
+3.1…3.9%).
**Resolution: PRISTINE met on the merits. NO baseline ratify.**
The Iron Law forbids ratifying noise into the baseline and the
spec explicitly forecloses opportunistic ratification here; the
non-pristine exit code is bench-harness noise, not a code defect,
and does not block close. Filed a **new, distinct P2** (separate
from the `*.bump_s` staleness P2): `check.py` RC-latency
`*.max_us` at `-n 5` is a structural false-positive — 3-for-3 on
consecutive no-runtime-change milestones — recommending drop
`max_us` from gating / raise `-n` / cpuset-pin (mitigation choice
left to a future iteration).
## Step 3/4 — Classification & resolution
| Item | Class | Outcome |
|------|-------|---------|
| form_a.md construct doc | fix | inline Boss `.tidy` (this commit) |
| recon-undercount 4th recurrence | process-drift | P2 escalated in place (roadmap) |
| `bump_s` +12.51% | carry-on | tracked P2 (no ratify) |
| `*.max_us` ×2 | carry-on | new P2 filed (no ratify) |
Milestone audit **CLEAN** post-tidy. Next pipeline step:
`fieldtest` (the removal is a user-visible Form-A surface change —
`mut`/`var`/`assign` no longer lex; an LLM author must now reach
for `let`/`if`/`loop`/`recur`).
+1
View File
@@ -89,3 +89,4 @@
- 2026-05-18 — iter prose-loop-binders.1 (single-iteration milestone, DONE): Form-B prose `loop` now renders binders as a parenthesised init-list on the keyword line — `loop(acc = 0, i = 1) { … }` — instead of bare `name = init;` statements inside the body block, which had implied C/Rust re-init-every-iteration semantics. Projection-only single-arm rewrite of the `Term::Loop` case of `write_term` (`crates/ailang-prose/src/lib.rs`); init exprs render at `level` (keyword line, not the indented block), mirroring the untouched adjacent `Term::Recur` `enumerate()`+`", "` idiom — making the binder list positionally isomorphic to `recur(...)`, which teaches the correct "recur re-binds these positionally" model instead of obscuring it. RED-first via the existing stem-explicit `check_snapshot` harness: two new committed `examples/{loop_sum_to_run,loop_forever_build}.prose.txt` whole-file byte-equality fixtures + two `snapshot_loop_*` `#[test]` fns, verified `0 passed; 2 failed` against the old renderer before the arm rewrite turned them green. Loop/recur AST, Form-A, JSON-AST, typecheck, codegen and the Form-A↔JSON round-trip invariant untouched by construction (no signature change, no caller touched, prose is a one-way lossy projection off the round-trip path — spec §Architecture states this explicitly so milestone-close audit does not chase a phantom). Full `ailang-prose` suite 10/0; both `ail prose | diff` live-CLI byte-matches `MATCH`; post-cleanup porcelain exactly the expected paths. Surfaced from the 2026-05-18 user prose review of the just-closed loop/recur milestone; brainstorm spec `docs/specs/2026-05-18-prose-loop-binders.md` (Step-7.5 grounding-check PASS), plan `docs/plans/prose-loop-binders.1.md`. Both implement review phases first-pass, 0 re-loops. Milestone-close `audit` is the Boss's next pipeline step (projection-only, no Form-A surface change → no fieldtest). → 2026-05-18-iter-prose-loop-binders.1.md
- 2026-05-18 — audit prose-loop-binders (milestone CLOSE, clean / carry-on): milestone-close tidy for the single-iteration prose-loop-binders milestone (range `6cbd0fe..c9355d7`). Architect drift review **clean** — zero drift, zero debt, verified against the diff not journal trust: single `Term::Loop` `write_term` hunk in `crates/ailang-prose/src/lib.rs`, the two non-render `Term::Loop` sites + all `Term::Recur` arms absent from the diff, DESIGN.md/PROSE_ROUNDTRIP.md make no claim about prose `loop` rendering (so the spec's "no doc edit needed" is correct not a skipped obligation), no carve-out/hash-pin/round-trip lockstep bypassed (prose is off the Form-A↔JSON round-trip path by construction). Bench: `compile_check.py` 0/24 + `cross_lang.py` 0/25 both **exit 0** (cross_lang's independent `ail_bump_s` +1.50% ±15% ok corroborates check.py's bump_s firing is baseline-staleness not a real regression); `check.py` exit 1, first run 3 regressed but a confirmatory identical re-run (no code change) returned `latency.implicit_at_rc.p99_9_us` +37.30%→+10.22% **ok** and `.max_us` +114.14%→+22.17% **ok** (median/p99 within tol both runs) — the two latency-tail firings proven single-sample 5-run RC-mode jitter by re-run; `bench_list_sum.bump_s` persisted ~+12% = the already-tracked P2 roadmap todo (byte-oracle-proven environmental at the 2026-05-16 iteration-discipline-revert audit, causally impossible to attribute to a projection-only `ailang-prose` change). **All items carry-on**: no fix iteration, no baseline ratify — explicitly NOT bumping the `*.bump_s` baseline opportunistically inside an unrelated projection-only milestone (the P2 todo owns a holistic recapture; piecemeal bump is the "regression is expected" rationalisation the Iron Law forbids). Fieldtest **not applicable / not dispatched**: projection-only change to the Form-B *reading* surface; the fieldtester authors `.ail` Form-A and would not exercise the prose-render change (no friction/bug/spec-gap axis); the two whole-file byte-equality `.prose.txt` snapshots + live-CLI `ail prose|diff` checks are the projection-only E2E gate. Milestone **CLOSED clean**; roadmap P0 entry flipped `[~]``[x]`, WhatsNew.md user-facing entry appended (user present → no notify.sh fired per notification policy). → 2026-05-18-audit-prose-loop-binders.md
- 2026-05-18 — iter remove-mut-var-assign.1 (single terminal iteration, DONE): `mut`/`var`/`assign` removed from AILang entirely and atomically — `Term::Mut`/`Term::Assign`/`struct MutVar`, the three Form-A keywords + `parse_mut`/`parse_assign` + grammar EBNF, the 4 `mut` `CheckError` variants, the `mut_scope_stack` synth threading (param dropped from `synth` + every internal/external/test caller), the two `lower_term` arms, and every exhaustive no-`_` `Term::Mut`/`Term::Assign` match arm across 17 source files — cut in lockstep with DESIGN.md + fixtures + drift trio + carve-out + roadmap so the schema is honest at every commit (no `_ =>` wildcard introduced — Boss-verified). `loop`/`recur` + `let`/`if` are the surviving forms. Shared codegen alloca machinery survives (loop reuses it): `mut_var_allocas``binder_allocas` (representation-only, loop codegen byte-identical) and the shared `Term::Lam` escape guard simplified to `!loop_stack.is_empty()` with the loop half (`LoopBinderCapturedByLambda`) kept byte-equivalent. Feature-acceptance applied inverted (removed feature fails clause 2 redundant + clause 3 IS the iterated-mutable-state bug class). Behaviour-preservation proof executable: `mut_counter`/`mut_sum_floats` still print `55` after the faithful `let`/`if` rewrite (factorial→120, horner→18, classify 22→2, has_small_factor 91→true); the "removal made executable" gate is the new `mut_removed_pin.rs` (4 must-fail pins: `mut`/`assign` keyword rejected, `{"t":"mut"}`/`{"t":"assign"}` serde unknown-variant). Independent Boss verification: full `cargo test --workspace` **605/0**, zero residual mut symbols in any crate source, loop/recur non-regression all green (55 / 500000500000 / infinite-compiles / `lambda_capturing_loop_binder` pin), `roundtrip_cli` PASS. One systemic DONE_WITH_CONCERNS — 4th recurrence of the recon-undercount `feedback_plan_pseudo_vs_reality` class (in-source `mod tests` fns + a drift-pin fn + 5 orphaned mut `.ail.json` carve-outs + a non-enumerated `codegen_import_map_fallback_pin.rs` E0599 the recon missed; all resolved within implementer remit via Task-3's identical whole-file-deletion rationale, no behaviour change, e2e bodies preserved per plan) — worth a planner/recon-agent countermeasure, pairs with the existing loop-recur.tidy P2 todo. Milestone-close `audit` then `fieldtest` (surface-touching) are the Boss's next pipeline steps. spec `docs/specs/2026-05-18-remove-mut-var-assign.md` (grounding-check PASS), plan `docs/plans/remove-mut-var-assign.1.md` → 2026-05-18-iter-remove-mut-var-assign.1.md
- 2026-05-18 — audit remove-mut-var-assign (milestone close, CLEAN after one inline `.tidy`): scope `48e7774..07f0802`. Architect drift: one `[high]``crates/ailang-core/specs/form_a.md` (live in-tree Form-A grammar still documented the full `mut`/`var`/`assign` construct: EBNF 286-288, prose 308-328, dangling `like mut` at 332); the spec named it for deletion, the iter missed it. Root cause = recon-undercount class **4th recurrence + a Boss error**: a plan-time grep checked only `docs/form_a.md` (dir-scoped), got "No such file", and the Boss propagated that unverified non-existence claim into the recon brief — the real file is `crates/ailang-core/specs/form_a.md`, actively maintained, and a stale doc never produces a compile error so the implement compile-sweep could not catch it. Fixed inline as a Boss `.tidy` (CLAUDE.md context-already-loaded carve-out; full review discipline kept — tree-wide verified zero construct residue except the roadmap entry that names the milestone itself; grammar reads coherently reuse-as→loop→recur). One `[medium]` process-drift: escalated the existing loop-recur.tidy `ailang-plan-recon` P2 in place — broadened from cross-crate-caller to a structural recon-contract defect with two named gaps (non-compile-checked spec-named sites; unverified "X does not exist" claims inheriting into a recon brief) + a concrete fix (compile-driven enumeration as authoritative code-site set PLUS an `ls`-verified spec-named-path existence table). Bench: `compile_check.py` 0/24 + `cross_lang.py` 0/25 exit 0; `check.py` exit 1 (3 firings: `bench_list_sum.bump_s` +12.51%, `latency.{explicit,implicit}_at_rc.max_us` +108%/+66%). Bencher causal exoneration **decisive**: HEAD vs `48e7774` `list_sum_bump`/`lat_expl_rc`/`lat_impl_rc` binaries `cmp`-byte-identical — the 2520-line removal alters zero bytes of these fixtures' machine code, no causal mechanism; `bump_s` = the tracked P2 environmental staleness, both `*.max_us` = single-sample `-n 5` jitter (`explicit_at_rc.max_us` +108%→**-2.30% ok** on identical-code rerun, medians held). **PRISTINE met on the merits; NO baseline ratify** (Iron Law forbids ratifying noise, spec forecloses it). Filed a NEW distinct P2 (separate from `*.bump_s` staleness): `check.py` RC-latency `*.max_us` at `-n 5` is a 3-for-3 structural false-positive on no-runtime-change milestones → drop from gating / raise `-n` / cpuset-pin. Milestone audit **CLEAN**; only `fieldtest` (surface-touching) remains before close → 2026-05-18-audit-remove-mut-var-assign.md
+62 -21
View File
@@ -46,11 +46,17 @@ work progresses.
alloca machinery kept (loop reuses it) + renamed `binder_allocas`,
shared `Term::Lam` escape guard keeps its `loop` half. Explicitly
decoupled from Stateful-islands (separate, deferred). Spec
approved + planned + implemented (605/0, loop/recur
non-regression green, removal made executable); milestone-close
`audit` then `fieldtest` (surface-touching) remain.
approved + planned + implemented (605/0, loop/recur non-regression
green, removal made executable); milestone-close `audit` clean —
architect `[high]` (a spec-named in-tree grammar doc the iter
missed) fixed in `.tidy`, bench causally exonerated (HEAD vs
pre-milestone binaries `cmp`-byte-identical; the 3 `check.py`
firings are the tracked P2 `bump_s` staleness + the new P2
`max_us` `-n 5` false-positive — no ratify). Only `fieldtest`
(surface-touching) remains before close.
- context: `docs/specs/2026-05-18-remove-mut-var-assign.md`;
`docs/journals/2026-05-18-iter-remove-mut-var-assign.1.md`
`docs/journals/2026-05-18-iter-remove-mut-var-assign.1.md`;
`docs/journals/2026-05-18-audit-remove-mut-var-assign.md`
- [x] **\[milestone\]** Prose `loop` binders — projection redesign —
CLOSED 2026-05-18. Form-B prose now renders loop binders as a
@@ -315,23 +321,37 @@ work progresses.
intra-crate links). All predate the design-md-consolidation
milestone; treat as a one-off sweep.
- context: JOURNAL 2026-05-10 ("Audit close: design-md-consolidation").
- [ ] **\[todo\]** `ailang-plan-recon` cross-crate-caller-undercount
countermeasure — the recon agent hand-lists exhaustive-`match`/caller
sites and has under-counted the true blast radius **three times in
one milestone** (loop-recur.1 walker arms, loop-recur.2 cross-module
`synth` callers, loop-recur.tidy implicit). Each was caught only by
the implement orchestrator's compile-driven sweep, not by the plan.
The pattern is structural: a hand-enumerated site list for a
workspace-wide signature/exhaustive-match change is inherently
lossy. Tighten `skills/planner/agents/ailang-plan-recon.md` so that
for any signature-change / additive-enum-variant scope the recon
REPORTS the compile-driven enumeration command as the authoritative
site set (and frames its own hand-list as advisory), rather than
presenting the hand-list as complete. No language change; an
agent-definition discipline fix.
- context: loop/recur milestone-close audit (architect `[low]`,
2026-05-18); pairs with the planner Step-5 items 7+8 added the
same milestone (those scrub the *plan*; this scrubs the *recon*).
- [ ] **\[todo\]** `ailang-plan-recon` site-undercount countermeasure
(P2, **escalated** — now a structural recon-contract defect, no
longer a single-milestone curiosity) — the recon agent hand-lists
the change blast radius and has under-counted it **four times across
two milestones, through a different site type each time**:
loop-recur.1 walker arms, loop-recur.2 cross-module `synth` callers,
loop-recur.tidy implicit, and now remove-mut-var-assign.1 (in-source
`mod tests` fns + a drift-pin fn + 5 orphaned `.ail.json` carve-outs
+ a non-enumerated `codegen_import_map_fallback_pin.rs` E0599) **plus
a spec-named doc the recon was told did not exist**
(`crates/ailang-core/specs/form_a.md` — the spec listed it for
deletion; a Boss plan-time grep checked only `docs/form_a.md`,
concluded "no such file", and propagated that into the recon brief;
caught only at milestone-close audit). Two distinct gaps: (a) the
compile-driven sweep catches exhaustive-`match`/caller misses but
**not** non-compile-checked sites (docs, fixtures, drift pins) —
those need a separate "every spec-named path is verified to exist
and is handled" cross-check; (b) a recon brief must never inherit an
unverified "X does not exist" — existence claims feeding a recon are
themselves load-bearing and must be tree-wide, not dir-scoped.
Tighten `skills/planner/agents/ailang-plan-recon.md`: for any
signature-change / enum-variant / removal scope the recon REPORTS
the compile-driven enumeration as the authoritative code-site set
(hand-list advisory) AND emits a spec-named-path existence table
(every path the spec names, `ls`-verified, with its handling task).
No language change; an agent-definition discipline fix.
- context: loop/recur close audit (architect `[low]`, 2026-05-18) +
remove-mut-var-assign close audit (architect `[high]` form_a.md +
`[medium]` process-drift, 2026-05-18); pairs with planner Step-5
items 7+8 (those scrub the *plan*; this scrubs the *recon* and the
*recon brief*).
- [ ] **\[todo\]** `design_schema_drift.rs` fidelity widening —
current test checks anchor *presence* anywhere in DESIGN.md;
the audit found that `[high]` schema gaps in §"Data model"
@@ -399,6 +419,27 @@ work progresses.
recalibrate the `bump_s` baseline+tolerance pair (or widen the
tolerance) so the noise floor stops tripping `check.py` exit 1.
Pure bench-harness recalibration; no language change.
- [ ] **\[todo\]** `check.py` RC-latency `*.max_us` is a structural
false-positive at `-n 5` — **distinct** from the `*.bump_s`
staleness above (different metric family, different root cause).
`latency.{explicit,implicit}_at_rc.max_us` is the single worst of
~5000 samples over only 5 runs, dominated by OS scheduling / THP /
IRQ jitter on a shared host, not allocator behaviour. It has fired
a false `REGRESSION` on **three consecutive no-runtime-change
milestones** (iteration-discipline-revert, prose-loop-binders,
remove-mut-var-assign) and vanished on identical-code re-run every
time (remove-mut-var-assign close: HEAD vs `48e7774` bench binaries
`cmp`-byte-identical, `explicit_at_rc.max_us` collapsed
+108%→-2.30% ok by rerun3) — a ~3-for-3 false-positive rate on null
changes, while the median/p99/p99.9 of the same benchmarks held
across all re-runs. Pick one mitigation: drop `*.max_us` from the
gating set (keep median/p99/p99.9, which are the trustworthy
signal), or raise `-n` substantially for the tail metrics, or pin
the latency arm to an isolated cpuset. Pure bench-harness change;
no language change.
- context: remove-mut-var-assign close audit, bencher localisation
(2026-05-18) — byte-identical-binary causal exoneration + the
3-milestone false-positive history.
- context: `docs/journals/2026-05-16-audit-iteration-discipline-revert.md`
(the bencher localisation evidence).
- [x] **\[todo\]** `check_in_workspace` per-module overlay narrowing —