Files
xenia-rs/audit-runs/audit-046-loop-exit/findings.md
MechaCat02 8e709b0a24 chore: track audit-runs summary artifacts (md/csv/diff/txt/json/etc)
Snapshot of every non-log artifact under audit-runs/ from audits 003
through 058: findings.md per audit, comparison CSVs, probe diffs,
schema docs, register-dump txts, lr-trace JSONL streams, the saved
canary patch diffs, etc. ~284 files / ~52 MB total.

Excluded (per .gitignore): probe stdout/stderr/log streams (the raw
firehose), guest-memory dumps under audit-026/027/029 (4.5 GB of
.bin files; *.bin pattern added to .gitignore this commit).

Also adds the orphan audit-058-sub825070F0-activation directory that
a subagent accidentally created at project-root instead of
under xenia-rs/audit-runs/; relocated to its proper home.

Purpose: cross-machine continuity. With these summaries committed,
a fresh clone gives the next session the full per-audit context
(findings + tables + cascade predictions) without dependence on
local-only working tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:36:41 +02:00

8.1 KiB
Raw Blame History

AUDIT-046 — Loop-exit predicate at 0x82450904

Date: 2026-05-10 Mode: READ-ONLY xenia-rs HEAD: 7bc9e3a (unchanged) xenia-canary HEAD: 6de80dffe (patch reverted clean at session close) Discipline gate: 5/5 PASS

Question

Does the audit-034 / audit-035 frame-chain divergence at sub_82450720+0x160..+0x1F4 reflect a real behavioral divergence — specifically, does the loop-exit bne predicate at PC 0x82450904 succeed early in canary (3.75/5 iters per audit-034) and fail every iter in ours (5/5)? If yes, audit-035's slot-pointer heap-region split (canary 0xBC3xxxxx physical vs ours 0x4024xxxx v40-bump) becomes a sharp causal target.

Method

  1. Re-applied audit-030 --log_lr_on_pc patch verbatim from audit-runs/audit-045-cluster-ctor-probe/canary-patch.diff (30 LOC, 4 files in xenia-canary). Saved here as canary-patch.diff.
  2. Built canary Debug variant.
  3. Probed canary at three PCs (60-90s wall each):
    • 0x82450904 — the bne predicate itself
    • 0x82450918 — the loop-completion no-match exit (post-bdnz block-entry)
    • 0x82450934 — early-match handler (block-entry on predicate success while r25<5)
  4. Probed ours at four block-entry PCs (-n 500000000):
    • 0x82450720 — outer-call entry (sub_82450720)
    • 0x82450890 — loop-back top
    • 0x82450908 — post-bne fall-through (fires every iter that fails predicate)
    • 0x82450918 — loop-completion no-match exit
  5. Dumped slot table at 0x828F3BD4 + 2 adjacent windows in ours via --dump-addr=0x828F3BD4,0x828F3C14,0x828F3C54.
  6. Reverted canary patch (git checkout of touched files) and confirmed clean tree.

⚠️ Per AUDIT-045 reading-error class #13: ours --pc-probe only fires at basic-block entry; canary --log_lr_on_pc fires per-instruction inline in HIR. 0x82450904 is the bne instruction itself (mid-block) → ours-side direct probe at that PC would yield 0 fires regardless. Worked around by probing the block-entry alternatives 0x82450908 (post-bne fall-through, fires every iter that fails) and 0x82450918 (loop-completion exit, fires once per outer call).

Results

Canary (per probe)

PC Site Wall Fires
0x82450904 bne predicate 70s 140
0x82450918 no-match completion 70s 22 outer-call completions
0x82450934 early-match handler 70s 0

Canary's predicate fires 140 times across 22 outer-call completions ≈ 5+ iters per outer call. The predicate never resolves to cr0.eq=1 (early-match handler 0x82450934 sees zero fires). Canary always exits via the no-match path.

Ours (single multi-PC run, -n 500000000)

PC Site Fires
0x82450720 sub_82450720 outer entry 16
0x82450874 post-prologue block-entry 16
0x82450880 post-prologue block-entry 16
0x82450890 loop-back top 64 (= 16 outer × 4 loop-backs)
0x82450908 post-bne fall-through 80 (= 16 outer × 5 fail iters)
0x82450918 no-match completion 16

Ours exhibits 5/5 iters per outer call with 0 early matches, falling through to 0x82450918 exactly once per outer call.

Slot table at 0x828F3BD4 (ours, end-of-run)

Walking 5 slots × 20 bytes from base, bytes [0x0C..0x13] per slot are the (ptr, size) pair:

Slot Offset Content Region
0 0xBD4 all zeros
1 0xBE8 ptr=0x4024A240 size=0x00000008 v40-bump
2 0xBFC ptr=0x4024AEE0 size=0x00000008 v40-bump
3 0xC10 all zeros (audit-035's "over-cycled" slot, now stable)
4 0xC24 ptr=0x4024A300 size=0x00000008 v40-bump

Slot 0 zero in both engines per audit-035. Audit-035 reported canary slots 1/2/4 holding 0xBC3xxxxx physical-heap pointers; here ours slots 1/2/4 hold 0x4024xxxx v40-bump pointers. Region split confirmed and persistent.

Verdict

Hypothesis FALSIFIED

The loop-exit predicate at 0x82450904 does not match in either engine. Both engines:

  1. Run the full 5/5 iters every outer call.
  2. Never resolve the predicate to cr0.eq=1 (canary 0x82450934 early-match handler sees 0 fires).
  3. Exit via the no-match path at 0x82450918.

Why audit-035's region split is behaviorally inert

The predicate at 0x82450904 compares two values:

  • LHS: a sum derived by sub_82451E20's vptr-walk return (objects in the same heap region as the slot table)
  • RHS: each slot's local sum (ptr + size pair from the slot table itself)

Both LHS and RHS originate from the same heap region within a given engine. In ours, both come from v40-bump (0x4024xxxx). In canary, both come from physical (0xBC3xxxxx). The cross-engine address-space difference is internally consistent within each engine's view, so it cancels as a divergence cause at this predicate.

The slot-table region split is REAL DATA but does NOT gate any predicate behavior here. The data observation does not become a behavioral divergence.

Why audit-034's "canary 3.75/5 vs ours 5/5" measurement is also falsified

Canary 70s probe yields 140 fires of 0x82450904 across 22 outer-call completions = ~6.4 fires/call (5 fail-iters + tail). Ours yields 80 fail-iter fires across 16 outer-call completions = exactly 5/5. Both engines exhibit identical 5/5 loop shape. Audit-034's earlier measurement was either pre-overhaul or stale.

Strategic implication

The audit-035/036 frame-chain divergence at sub_82450720 is now triple-refuted as a causal target:

Audit Refuted layer
036 "η-class record-layout divergence as stated" — refined to ε-class heap-region
043 ε-class heap-region as "missing/wrong write at +0x00" — VA-equality fallacy (12th reading-error class)
046 ε-class heap-region as causally responsible at predicate 0x82450904 (this audit)

Recommendation: drop the sub_82450720 chain entirely as a critical-path target. The slot-table region split is data hygiene, not a behavioral gate.

Reading-error class 13 reconfirmed

Mid-block PCs are unprobeable in ours via --pc-probe; canary's --log_lr_on_pc fires per-instruction. Working pattern validated here: probe the post-bne block-entry PC (0x82450908) instead — fires every fail iter as expected (80 = 16×5). Plus the loop-completion block-entry (0x82450918) for outer-call counting (16). Future audits should follow this pattern when the target is a mid-block predicate.

γ-cluster handle wedges per audit-042. Concrete stalled handles at end-of-run in our impl: 0x10A0+0x10A4 (Event+Sema worker pair, tid=6), 0x12AC (Sema with 2 waiters, tid=14,15), 0x1004 (Event/Manual, tid=11), plus 0x1020/0x1040/0x1544/0x1578. These are γ-class missing-signaler bugs — concrete and reachable.

Sharp 4-dim cascade prediction (γ-fix on a single wedge):

  • A: signal_attempts on the wedged handle 0 → ≥1
  • B: stalled tid state Blocked → Ready
  • C: <NO_SIGNALS> count drops ≥2
  • D: swaps>2 OR draws>0 UNKNOWN — γ-cluster typically plateaus on a sister wedge, low cascade probability per audit-042

Cost: 1 ours run + 1-2 canary probes ≈ ~10 min runtime + analysis.

Discipline confirmation

  • xenia-rs HEAD 7bc9e3a unchanged. No source modifications, no commits.
  • xenia-canary HEAD 6de80dffe clean tree (git status --short empty for tracked files after revert).
  • Tests count: not re-run (no source changes; preserved at 645 per audit-038 baseline).
  • Lockstep determinism: not re-run (no source changes).
  • Master plateau: swaps=2 draws=0 intact.

Trace artifacts (this directory)

  • canary-patch.diff — verbatim audit-045 patch
  • canary-0x82450904.{log,err} — 22MB, 140 fires
  • canary-0x82450918.{log,err} — 21MB, 22 outer-call completions
  • canary-0x82450934.{log,err} — 28MB, 0 fires (early-match handler)
  • ours-entry-probe.{log,err} — 16 outer-call entries
  • ours-loop-probe.{log,err} — 64 loop-back fires + 16 completion fires
  • ours-loop-detailed.{log,err} — 80 post-bne fall-through fires + 16 completion fires
  • slot-table-dump-ours.{log,err} — 5-slot table at 0x828F3BD4 with v40-bump pointers
  • findings.md — this document