# Persistence experiment — `XENIA_CACHE_PERSIST=1` impact on matched-prefix ## Setup * Binary: `xenia-rs/target/release/xrs-c10` (active C+10 build, both engines). * Window: 50M instructions per boot. * Flag: `XENIA_CACHE_PERSIST=1`; mount falls back to `$HOME/.local/share/xenia-rs/cache` because `XDG_DATA_HOME` is empty on the host. * Comparison baseline: C+10 default-tmpdir digest `instructions=50000002 imports=40465 swaps=1 draws=0` (with stable-digest md5 `b8fa0e0460359a4f660adb7605e053de`); event log `xenia-rs/audit-runs/phase-c10-NtQueryFullAttributesFile/canary.jsonl`. * Diff tool: `xenia-rs/tools/diff-events/diff_events.py --tid-map 6=1`. ## Boot-by-boot digests | boot | mode | instructions | imports | swaps | draws | |---|---|---|---|---|---| | C+10 baseline (default tmpdir) | wipe-on-boot | 50000002 | 40465 | 1 | 0 | | Persist boot 1 (cold persist) | persistent | **50000003** | **40485** | 1 | 0 | | Persist boot 2 (warm persist) | persistent | 50000003 | 40485 | 1 | 0 | The persistence path is +1 instruction / +20 imports over the default-tmpdir baseline. Warm boot is identical to cold boot at the digest level (no regression observed at 50M; AUDIT-053's regression was at 500M+). ## On-disk cache state per boot ### After persist boot 1 (cold) Total: 7 files / 1.4 MB. ``` d 4096 /access ← BUG: should be 240 B file (canary) d 4096 /ignore ← BUG: not in canary's cache d 4096 /recent ← BUG: should be 160 B file (canary) d 4096 /d4ea4615 d 4096 /d4ea4615/e d 4096 /69d8e45c d 4096 /69d8e45c/9 d 4096 /69d8e45c/e d 4096 /aab216c3 d 4096 /aab216c3/5 d 4096 /aab216c3/a f 2400 /d4ea4615e46ee8ca.tmp f 5784 /69d8e45ce534ffea.tmp f 12288 /69d8e45c9355f2f8.tmp f 12288 /69d8e45c973a5c0a.tmp f 12288 /aab216c35ee70e0a.tmp f 614400 /aab216c3a2c8c185.tmp f 685464 /69d8e45c939a9dcc.tmp ``` Notable: * `access`, `ignore`, `recent` exist as DIRECTORIES (bug #2). * `.tmp` flat journals exist (cache-build path is firing). * Hash subdirectories exist (AUDIT-054's `FILE_DIRECTORY_FILE` handling works). * **Hierarchical leaf files** (e.g. `d4ea4615/e/46ee8ca`) **do not exist** — the `.tmp` → leaf rename is being silently dropped (bug #1). ### After persist boot 2 (warm) Total: 7 files / 1.6 MB (`.tmp` files grew). | file | boot 1 | boot 2 | growth | canary's equivalent leaf size | |---|---|---|---|---| | `d4ea4615e46ee8ca.tmp` | 2400 | 2800 | +400 | 400 B (`d4ea4615/e/46ee8ca`) | | `69d8e45ce534ffea.tmp` | 5784 | 6748 | +964 | 964 B (`69d8e45c/e/534ffea`) | | `69d8e45c9355f2f8.tmp` | 12288 | 14336 | +2048 | 2048 B (`69d8e45c/9/355f2f8`) | | `69d8e45c973a5c0a.tmp` | 12288 | 14336 | +2048 | 2048 B (`69d8e45c/9/73a5c0a`) | | `aab216c35ee70e0a.tmp` | 12288 | 14336 | +2048 | 2048 B (`aab216c3/5/ee70e0a`) | | `aab216c3a2c8c185.tmp` | 614400 | 716800 | +102400 | 102400 B (`aab216c3/a/2c8c185`) | | `69d8e45c939a9dcc.tmp` | 685464 | 799708 | +114244 | 114244 B (`69d8e45c/9/39a9dcc`) | **The per-boot growth of each `.tmp` file exactly matches the byte size of the corresponding canary hierarchical leaf.** Strong indirect evidence that the `.tmp` contains the same data as canary's leaf but is being appended on each boot instead of being renamed-to-leaf and consumed. This is exactly AUDIT-053's "journal-style appends per boot" pattern. AUDIT-053 predicted a `runtime_error` regression at warm-start because the version header would go stale; in the 50M window of this experiment, that regression has not yet manifested (AUDIT-054's report had it at 500M+). ## Phase A diff vs C+10 canary baseline Command: ``` python3 xenia-rs/tools/diff-events/diff_events.py \ --canary xenia-rs/audit-runs/phase-c10-NtQueryFullAttributesFile/canary.jsonl \ --ours xenia-rs/audit-runs/cache-subsystem-plan/persist-warm-events.jsonl \ --tid-map 6=1 ``` Result: ``` | canary_tid | ours_tid | matched | canary_total | ours_total | first_divergence_at | |---|---|---|---|---|---| | 6 | 1 | 102404 | 315020 | 108471 | 102404 | ``` **Matched-prefix unchanged from C+10 baseline (102404).** Divergence event: ``` canary [6][102404] kernel.return NtQueryFullAttributesFile return_value=0 ours [1][102404] kernel.return NtQueryFullAttributesFile return_value=0xC0000034 ``` Pre-context shows both engines reach the same path query `cache:\d4ea4615\e\46ee8ca` byte-for-byte, but ours returns NOT_FOUND because that leaf doesn't exist on disk (only the flat `.tmp` does). ## Conclusion Persistence is **necessary but not sufficient**. The plan's Stage 1 (rename fix) is required to convert `.tmp` flat journals into hierarchical leaves. Stage 2 (top-level file misclassification) is required to fix the `access`/`ignore`/ `recent` directory-vs-file bug. Stage 3 (flip default) follows after both bugs are addressed. Expected matched-prefix advance after all three stages: hundreds-to-thousands of events, until a non-cache divergence appears. ## Reproduction commands ```bash cd "/home/fabi/RE - Project Sylpheed" # Clean cache for cold start rm -rf ~/.local/share/xenia-rs/cache # Boot 1 (cold) XENIA_CACHE_PERSIST=1 ./xenia-rs/target/release/xrs-c10 check \ -n 50000000 --stable-digest --out /tmp/digest-boot1.json \ "Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja).iso" # Inspect resulting cache layout find ~/.local/share/xenia-rs/cache -mindepth 1 -printf '%y %s\t%p\n' | sort # Boot 2 (warm) — same command, no rm XENIA_CACHE_PERSIST=1 ./xenia-rs/target/release/xrs-c10 check \ -n 50000000 --stable-digest --out /tmp/digest-boot2.json \ "Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja).iso" # Boot 2 with Phase A event log XENIA_CACHE_PERSIST=1 ./xenia-rs/target/release/xrs-c10 exec \ -n 50000000 --quiet \ --phase-a-event-log xenia-rs/audit-runs/cache-subsystem-plan/persist-warm-events.jsonl \ "Project Sylpheed - Arc of Deception (USA, Europe) (En,Ja).iso" # Diff python3 xenia-rs/tools/diff-events/diff_events.py \ --canary xenia-rs/audit-runs/phase-c10-NtQueryFullAttributesFile/canary.jsonl \ --ours xenia-rs/audit-runs/cache-subsystem-plan/persist-warm-events.jsonl \ --tid-map 6=1 ``` ## State at session end `~/.local/share/xenia-rs/cache/` is left in its post-boot-2 state (7 `.tmp` files, ~1.6 MB, 3 directories that should be files, 7 empty hash subdirs). Next session should `rm -rf ~/.local/share/xenia-rs/cache` before Stage 1 work to start from a clean slate.