Fix EXEC/LOAD block-persistence gap and WIREBIND/USE interpreter-race panic (FABRIC-3.md §XII)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

Found live while building a cross-ISA FORTH-79 dictionary exerciser:

- capsule_exec_init() zeroed a capsule's block content immediately after
  running it, so LOAD (a genuine FORTH-79 standard word, ACL-allowed even
  for locked identities) could never actually read back what EXEC had
  just written. Removed the clear from capsule_exec_init(); block content
  now persists like any other Standard BLOCK/BUFFER/UPDATE write.
  kernel_main.c's own explicit post-birth clear of Mama's init.4th range
  is untouched.

- USE could redirect the console to a WIREBIND identity's VM before that
  VM's vm_enable_interpreter() step of its own birth sequence had run,
  causing the next typed line to hit vm_assert_interpreter_enabled() and
  panic the entire machine -- not the per-session-recoverable ACL-fault
  path a redirected VM otherwise gets. USE now checks interpreter_enabled
  first and refuses with a retry message instead.

Also includes the amd64/aarch64/riscv64 acceptance boot logs and DoE CSVs
from this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
This commit is contained in:
Robert Allan James
2026-09-10 16:07:38 -04:00
co-authored by Claude Sonnet 5
parent d5722986b2
commit 662ef44e59
13 changed files with 36605 additions and 7 deletions
+69
View File
@@ -2035,3 +2035,72 @@ FORTH-79/83 personality and has been individually verified standalone. Not re-ru
3-arch acceptance pass on its own -- this is a data-only change to one thumbdrive image, no
kernel/capsule code touched, and amd64's own live verification above already exercises the same
code paths (§XI.4/§XI.5) the last 3-arch pass (§XI.5, commit `b301317`) already accepted.
## XII. Standard-dictionary cross-ISA exerciser campaign — two real bugs found live and CLOSED,
2026-09-10
Goal of the session: write one FORTH-79-standard-only exerciser program, run it identically
against every identity (`zuse` plus all 8 restricted identities) on all three architectures, and
diff the results for cross-ISA parity. Getting the mechanism working at all surfaced two real
bugs, both fixed here; the actual 27-leg campaign (3 arch × 9 identity) is what resumes next.
### XII.1 — `EXEC`/`LOAD` gap: a locked identity had no standard-compliant way to load capsule
source — CLOSED
`EXEC` (the kernel's named-capsule loader) was correctly found to be absent from
`ACL-STD79-LIST` (`capsules/acl-std79.4th`) -- not itself a bug, `EXEC` is kernel-specific, not a
FORTH-79 standard word. The real gap: `BLOCK`/`LOAD`/`THRU` (genuine standard words) *are* on the
allowlist, and `capsule_exec_payload()` genuinely does commit each capsule block's content to real
ramdrive storage (`write_ramdrive_block()`) before executing it -- so `LOAD` should have been a
legitimate standard-compliant fallback. It wasn't: `capsule_exec_init()` (what `EXEC` actually
calls, `mama_forth_words.c:1383`) followed `capsule_exec_payload()` with an unconditional
`capsule_clear_blocks()`, zeroing every block the capsule had just used before `EXEC` even
returned. The window where a capsule's content was actually present in block storage was entirely
inside one synchronous `EXEC` call -- nothing external, including a separately-running locked
identity's own session, could ever reach it with `LOAD` afterward. Confirmed by reading
`capsule_loader.c` directly, not inferred.
**Fix:** removed the `capsule_clear_blocks()` call from `capsule_exec_init()` (`capsule_loader.c`).
Block content written by `EXEC` now persists in ramdrive storage exactly like any other
Standard-compliant `BLOCK`/`BUFFER`/`UPDATE` write would, until something explicitly overwrites or
blanks it. The other caller of `capsule_clear_blocks()` -- `kernel_main.c`'s own explicit call
right after Mama's init.4th birth, to free that specific block range for later interactive
block-editor use -- is untouched; that one was already an explicit, separate, documented choice by
its own caller, not something `capsule_exec_init()` did on every caller's behalf. Verified:
`capsule_birth_mama()` calls `vm_exec_fn` directly (not `capsule_exec_init()`), so this fix has no
effect on Mama's own boot path.
### XII.2 — `USE` into a WIREBIND identity before its interpreter is enabled panics the whole
machine — CLOSED
Found live: attaching identity `03` via QMP hotplug, then immediately sending
`S" 03" USE` the moment the log printed `WIREBIND: 03 attached and ready -- USE it to begin`,
produced not an ACL fault but a full kernel panic --
`[StarKernel HAL] PANIC: interpreter invoked before bootstrap completion` -- and the machine
halted completely (`System halted.`, QEMU process left spinning uselessly). Root cause: a WIREBIND
identity's VM starts with `interpreter_enabled = 0` (`vm_bootstrap.c:162`) and only gets
`vm_enable_interpreter()` called as a later, separate step of the same birth sequence. The
"attached and ready" message prints as soon as the VM is registered, before that later step is
guaranteed to have run. `mama_word_use()` (`USE`) checked the target for dead/stillborn state but
never checked interpreter readiness before redirecting the whole console's input to it -- the very
next line typed would hit `vm_assert_interpreter_enabled()` inside `vm_interpret()` and call
`host->panic()`, which is a hard, unrecoverable halt, not the per-session-recoverable ACL-fault
path a redirected VM otherwise gets (§XI.3's fix). This is a real race independent of automation
speed: a human typing `USE` right after seeing "ready" hits it exactly the same way.
**Fix:** `mama_word_use()` (`mama_forth_words.c`) now checks `((VM *)entry.vm_ptr)->interpreter_
enabled` before redirecting, refusing with `USE: <name> not ready yet -- still bootstrapping, try
again` instead of performing the redirect. The caller just retries a moment later. Did not touch
the birth sequence itself (i.e., did not try to make the "attached and ready" message wait for
`vm_enable_interpreter()` to actually run first) -- narrower, lower-risk fix at the point of actual
failure.
**Both fixes verified:** amd64 rebuild clean, zero new warnings.
**Status:** exerciser campaign resuming with the fixed build. The 24-case exerciser itself (see
scratchpad `std79-exerciser.fth`, not yet committed -- FORTH-79 standard words only, biased toward
mixed/double-precision arithmetic and shift/negate boundary cases per cross-ISA risk) had already
produced one interesting, unconfirmed data point before the panic: `-123 456 M*` printed
`DOUBLE-OVERFLOW` via `D.` on amd64, identically for both `zuse` and `rajames` -- worth checking
against the other two architectures once the campaign completes; not yet root-caused or reported
as a bug on its own.