From 4837871ddfd88f3b0293d43728048c137984783c Mon Sep 17 00:00:00 2001 From: Brummel Date: Mon, 18 May 2026 11:19:48 +0200 Subject: [PATCH] iter remove-mut-var-assign.tidy: form_a.md grammar deletion + audit close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- crates/ailang-core/specs/form_a.md | 26 +---- .../2026-05-18-audit-remove-mut-var-assign.md | 108 ++++++++++++++++++ docs/journals/INDEX.md | 1 + docs/roadmap.md | 83 ++++++++++---- 4 files changed, 172 insertions(+), 46 deletions(-) create mode 100644 docs/journals/2026-05-18-audit-remove-mut-var-assign.md diff --git a/crates/ailang-core/specs/form_a.md b/crates/ailang-core/specs/form_a.md index 798f299..aa0e119 100644 --- a/crates/ailang-core/specs/form_a.md +++ b/crates/ailang-core/specs/form_a.md @@ -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 — diff --git a/docs/journals/2026-05-18-audit-remove-mut-var-assign.md b/docs/journals/2026-05-18-audit-remove-mut-var-assign.md new file mode 100644 index 0000000..1415b36 --- /dev/null +++ b/docs/journals/2026-05-18-audit-remove-mut-var-assign.md @@ -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 ~+11–14% 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`). diff --git a/docs/journals/INDEX.md b/docs/journals/INDEX.md index 8117c50..f5f37ec 100644 --- a/docs/journals/INDEX.md +++ b/docs/journals/INDEX.md @@ -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 diff --git a/docs/roadmap.md b/docs/roadmap.md index 0062d72..b8220cc 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -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 —