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
+14 -2
View File
@@ -581,8 +581,20 @@ CapsuleRunResult capsule_exec_init(
const uint8_t *payload = capsule_get_payload(cap, arena);
if (!payload) return CAPSULE_RUN_ERR_INVALID;
/* Unified: populate block device + execute; then free slots for userspace */
/* Populate block device + execute. Block content is left in place
* afterward -- capsule_exec_payload() already commits it to real
* ramdrive storage (write_ramdrive_block()) specifically so FORTH
* code can address it by number; a Standard BLOCK/LOAD on that same
* number must be able to read back what EXEC just ran, the same way
* any other block-storage write persists until something explicitly
* overwrites or blanks it. Previously this called capsule_clear_blocks()
* here, zeroing the slots immediately after execution -- that made
* capsule content invisible to LOAD the instant EXEC returned, which
* is not how FORTH-79 BLOCK/LOAD is supposed to behave, and is also
* the reason a FORTH-79/83-locked identity (no EXEC in its own
* dictionary, see capsules/acl-std79.4th) had no standard-compliant
* way to ever load capsule-authored source: LOAD was on the allowlist
* but nothing was ever left for it to find. Found and fixed 2026-09-10. */
int rc = capsule_exec_payload(vm, payload, cap->length);
capsule_clear_blocks(payload, cap->length);
return (rc == 0) ? CAPSULE_RUN_OK : CAPSULE_RUN_ERR_EXEC_FAIL;
}
+16
View File
@@ -483,6 +483,22 @@ void mama_word_use(VM *vm)
return;
}
/* Found live 2026-09-10: WIREBIND announces "attached and ready --
* USE it to begin" the moment the target VM is registered, but
* vm_enable_interpreter() is a separate, later step of that same
* birth sequence. USE redirecting here before that step lands means
* the very next line typed hits vm_assert_interpreter_enabled()
* inside vm_interpret() and calls host->panic() -- a hard, whole-
* machine halt, not the per-session-recoverable fault path the REPL
* loop otherwise gives a redirected VM. Refuse the redirect instead;
* the caller can just retry USE a moment later once birth finishes. */
if (entry.vm_ptr && !((VM *)entry.vm_ptr)->interpreter_enabled) {
console_puts("USE: ");
console_puts(name_buf);
console_println(" not ready yet -- still bootstrapping, try again");
return;
}
/* BINDSTEP (FABRIC-2.md §F.9/§F.24): if the target has a real
* installed identity (WIREBIND set this at attach time), re-verify
* it against whatever drive is CURRENTLY attached -- live, not