# Punch List: Gaps from 2026-07-24 Session Carried over to fix in a fresh session. Written at end-of-session while wrapping up — see `CHANGELOG.md` on both branches for what was accomplished today; this file is only the leftover gaps. --- ## 1. Port master's riscv64 bug fixes to `lithosananke` (highest priority) Getting the hosted riscv64 acceptance test to build under clang on `master` surfaced several real bugs. They were fixed on `master` only. **This broke an invariant established at the start of today's session**: we verified via SHA-256 that the ASM-optimization headers (including `include/vm_asm_opt_riscv64.h`) were byte-identical between `master` and `lithosananke`. That's no longer true. Most important: `include/vm_asm_opt_riscv64.h`'s `vm_pop_asm`/`vm_rpop_asm` had a genuine SIGSEGV-causing register-reuse hazard (the inline asm referenced the `dsp`/`rsp` memory operand both before and after writing the output value operand, with nothing pinning the address register in between — clang's allocator picked the same register for both and corrupted the write-back; GCC happened to pick different registers and never hit it). Fixed on `master` (commit `4db9946a`) by writing `dsp`/`rsp` back before loading the value. **This bug is still live and unpatched in `lithosananke`'s copy of the same file** — latent today only because `lithosananke`'s kernel build currently uses GCC, but it's a real crash risk if that ever changes (different GCC version, different `-O` level, or a future switch to clang). Also unported to `lithosananke`, all from `master` commit `4db9946a`: - `src/inference_engine.c` — `q48_from_u64(0.8)` → `q48_from_double(0.8)` (was silently truncating to 0) - `src/math_portable.c` — `-100LL << 16` (UB, shifting a negative value) → `-(100LL << 16)` - `src/block_subsystem.c` — removed dead `lbn_to_pbn()` (unused function, clang caught it) - `src/physics_pipelining_metrics.c` — removed dead `q48_mul_q48()` - `src/word_source/editor_words.c` — removed dead `set_scr()` - `src/word_source/starforth_words.c` — removed dead `reset_count` local **Action:** cherry-pick or manually port these onto `lithosananke`, then re-verify the standing kernel 3-arch QEMU acceptance test still passes (dead-code removals and the two arithmetic fixes are behaviorally inert for the kernel path except where they touch real bugs; the asm fix is the one that actually matters). ## 2. Fix the broken riscv64 command in this branch's acceptance-test doc `docs/lithosananke/hosted-acceptance-test/README.md` still documents the riscv64 leg using `riscv64-linux-gnu-gcc`, which cannot build this tree (`nanosleep` visibility failure under `-std=c99`, unrelated to any project change). This was already fixed in `master`'s `.claude/CLAUDE.md` (the working command is `clang-18 --target=riscv64-linux-gnu --sysroot=/usr/riscv64-linux-gnu` with `-std=c11 -pthread` and `-fuse-ld=lld`) but the correction was never carried over to this doc. **Action:** copy the corrected command block from `master`'s `.claude/CLAUDE.md` (`### "Run the acceptance test"` section) into this doc. ## 3. riscv64 hosted build isn't reachable via plain `make` There's no Makefile target that builds riscv64 hosted with clang — the only working invocation is the long manual command living in CLAUDE.md and commit messages. A plain `make ARCH=riscv64` still fails with GCC. **Action (lower priority, needs a decision, not just a fix):** decide whether to (a) add a `riscv64-clang` (or similar) Makefile target that wires in the working toolchain automatically, (b) fix GCC riscv64 compatibility directly (would need to chase the `nanosleep` visibility issue at its root — not yet diagnosed beyond "gcc riscv64 fails, clang succeeds with different flags"), or (c) leave it manual and just keep the docs accurate. Not urgent since the documented manual path works. ## 4. amd64 kernel `dict_hash` non-determinism — root cause is a hypothesis, not proven Today's kernel acceptance re-run found amd64's `dict_hash` deviated from aarch64/riscv64 (which matched each other and the established reference exactly). Traced to `capsule_dict_hash_hook()` folding `execution_heat` into the hash, combined with amd64's boot log stating its timer runs in "RELATIVE mode (no determinism guarantees)" under this QEMU/hypervisor setup (no invariant TSC) — unlike aarch64/riscv64, which get real hardware timers. Plausible and consistent with existing ACL-RWT campaign data showing amd64's tick count already diverging from the other two architectures, but this was a **single observation**, not confirmed by repeated runs. **Action:** re-run the amd64 kernel leg 3-5 times back to back and confirm `dict_hash` actually varies each time (proving jitter) rather than being stable-but-different (which would point to something else). If confirmed, consider whether `CHANGELOG.md`/`CLAUDE.md`'s acceptance criteria need a one-line amendment: "identical dict_hash across all three architectures" should probably be scoped to aarch64/riscv64, with amd64 checked only for clean boot + `PARITY:OK` + E2E PASS. **CLOSED (2026-08-02): does not reproduce.** Ran the amd64 kernel leg 5 times back to back (`logs/20260802-074443`, `-074813`, `-075033`, `-075254`, `-075522`, plus the same day's earlier acceptance run at `-064424` — 5 runs total). `dict_hash` was byte-identical across every run for every VM (Artemis `0x7b29c1e7d6714051`, both Hermes instances `0x2e8c1b07d009507e`, Hera/MAMA_INIT `0x450998b22c298cd9`), and matched aarch64/riscv64 exactly in every case. Not jitter, and not stable-but-different either — just correct, every time. The hypothesis's premise still holds — the amd64 boot log still warns `invariant TSC not present under hypervisor... continuing in RELATIVE mode (no determinism guarantees)`, and `capsule_dict_hash_hook()` (`src/starkernel/capsule/capsule_vm_hooks.c:65-66`) still folds `execution_heat` into the hash, unchanged since this list was written. But `PARITY:MAMA_INIT` (and the child-VM `PARITY:BIRTH` lines) print *before* `Starting heartbeat...` in the boot sequence, and heat only decays on heartbeat ticks — so there is no window for wall-clock jitter to touch `execution_heat` before any of these hashes get computed. The mechanism is real; it just isn't reachable at this checkpoint. Most likely the original observation was a one-off (loaded host machine, coincidental timing) rather than a real gap. No code change made. No amendment to `CLAUDE.md`'s acceptance criteria — "identical dict_hash across all three architectures" holds up under repeated testing, not just the single run that first raised this. ## 5. `lfs/riscv64/starforth` isn't bit-for-bit what `make fastest` would produce The committed riscv64 LFS binary (on `master`) was built with my manual clang invocation, which omitted several of `TARGET_CFLAGS_fastest`'s flags (`-funroll-loops -finline-functions -fomit-frame-pointer -fno-plt -fno-semantic-interposition`) and used `-fuse-ld=lld` instead of the default linker. Functionally fine (acceptance test passed), but worth knowing it's not exactly reproducible via the standard `make fastest` recipe. Resolves naturally once item #3 is decided. ## 6. Repo size growth from committed QEMU acceptance-run artifacts Not a bug, just a trend worth being aware of: today's two kernel acceptance runs on this branch alone added 1M+ lines of committed log/DoE-CSV data, including one 82MB serial log GitHub explicitly warned about (`logs/20260724-191335/amd64/qemu-amd64-20260724-191335.log`). Matches existing project convention (every real acceptance run gets committed), but if this keeps compounding it may eventually be worth a retention/pruning policy for `logs/` and `experiments/bare_metal/runs/`. No action needed now — just flagging. --- ## Not gaps, just context for next time - The 2 pre-existing `SPAN.zero_input`/`SPAN.variable_test` test failures (727/800 baseline on all three hosted architectures, observed on `master`) predate today's session — confirmed present before any of today's fixes were applied. Not investigated further today; still an open item if anyone wants to chase it down. - Today's aarch64/riscv64 `.hidden` ISR hardening (commit `5fe188bd`) only has a CHANGELOG entry, not a dedicated writeup the way `docs/lithosananke/amd64-isr-fix/README.md` documents the original amd64 fix. Not urgent — the CHANGELOG entry covers it — but noting the asymmetry in case someone later wants doc parity.