Stage D batch 5: mama_forth_words.c group 3 -- cross-VM execution/dispatch, both flagged special cases resolved (FABRIC-3.md §XXXII.6)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

VM-STEP/VM-EXEC/VM-CALL (5 sites) gained console_println() diagnostics
matching their own existing sibling guards.

SWITCH-MARK-WORK and VM-HEAT (3 sites) resolved per §XXXII.3's own
recommendation: dropped vm->error entirely rather than diagnosing it,
matching each function's own doc comment ("must never error or spam
the console" / "does not print/error"). SWITCH-MARK-WORK is the same
function §XXVIII.3 already fixed once for an off-by-one that fired
silently on every MSG-SEND in the system -- the guard now genuinely
cannot repeat that by contract, not just by the threshold being right.
VM-HEAT's guards now push 0 and return, matching its own
always-returns-a-value stack effect.

Three-arch clean qemu acceptance passed. Zuse's own WIREBIND attach
(every boot) drives MSG-SEND -> SWITCH-MARK-WORK, so this batch's most
safety-critical fix is exercised by standard acceptance, not just
compiled.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
Robert Allan James
2026-09-15 19:23:12 -04:00
co-authored by Claude Sonnet 5
parent b42c3b195c
commit 8b5300fc4f
10 changed files with 27219 additions and 12 deletions
+20
View File
@@ -4634,3 +4634,23 @@ gold-standard default for a function with nothing else to match against.
`BIRTH` itself is exercised heavily by every boot (Hermes/Artemis birth), a real regression check
beyond compile-cleanliness for this specific batch.
**Batch 5 -- DONE, 2026-09-15: group 3, cross-VM execution/dispatch (`VM-STEP`/`VM-EXEC`/
`VM-CALL`/`SWITCH-MARK-WORK`/`VM-HEAT`) -- 11 sites, including both flagged special cases.**
`VM-STEP` (1 site), `VM-EXEC` (2), `VM-CALL` (2) gained `console_println()` diagnostics matching
their own existing sibling guards, same shape as batch 4.
**The two flagged special cases resolved per §XXXII.3's own recommendation -- dropped the error
entirely, not diagnosed.** `SWITCH-MARK-WORK`'s underflow guard (`dsp < 1`) now bare-returns,
matching its own doc comment's "must never error or spam the console" contract exactly -- this
is the same function §XXVIII.3 already fixed once for an off-by-one that fired on every
`MSG-SEND` in the system; the guard now genuinely cannot do that again, by contract rather than
by accident of the threshold being right. `VM-HEAT`'s two guards (`dsp < 1`, bad address) now
push `0` and return, matching the word's own "unknown name -> push 0, never error" contract and
its own always-returns-a-value stack effect -- previously these two specific guards were the
only ways to make this word violate its own documented promise.
**Verified:** three-architecture `clean qemu` acceptance (amd64/aarch64/riscv64) passed. Zuse's
own WIREBIND attach (every boot) drives `HERA-BLK-ATTACH-REQ`'s `MSG-SEND`, which tail-calls
`SWITCH-MARK-WORK` -- so this fix's own most safety-critical path is exercised by the standard
acceptance boot itself, not just compiled.
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-15T22:41:56Z -->
<!-- Generated by mkcapsule --manifest 2026-09-15T23:13:32Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+54 -11
View File
@@ -680,7 +680,11 @@ static void mama_word_vm_step(VM *vm)
VM *target;
char saved_name[VM_NAME_MAX];
if (vm->dsp < 1) { vm->error = 1; return; }
if (vm->dsp < 1) {
console_println("VM-STEP: expects S\" name\" VM-STEP -- nothing on the stack");
vm->error = 1;
return;
}
u = vm_pop(vm);
caddr = vm_pop(vm);
@@ -692,7 +696,11 @@ static void mama_word_vm_step(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)caddr);
if (!p) { vm->error = 1; return; }
if (!p) {
console_println("VM-STEP: invalid address on the stack");
vm->error = 1;
return;
}
src = (const char *)p;
}
for (i = 0; i < (uint32_t)u; i++) name_buf[i] = src[i];
@@ -741,7 +749,11 @@ static void mama_word_vm_exec(VM *vm)
VM *target;
char saved_name[VM_NAME_MAX];
if (vm->dsp < 3) { vm->error = 1; return; }
if (vm->dsp < 3) {
console_println("VM-EXEC: expects S\" cmd\" S\" name\" VM-EXEC -- too few items on the stack");
vm->error = 1;
return;
}
/* TOS: vm-name-u, vm-name-caddr, cmd-u, cmd-caddr */
vm_u = vm_pop(vm);
@@ -760,7 +772,11 @@ static void mama_word_vm_exec(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
if (!p) { vm->error = 1; return; }
if (!p) {
console_println("VM-EXEC: invalid VM-name address on the stack");
vm->error = 1;
return;
}
src = (const char *)p;
}
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
@@ -768,7 +784,11 @@ static void mama_word_vm_exec(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
if (!p) { vm->error = 1; return; }
if (!p) {
console_println("VM-EXEC: invalid command address on the stack");
vm->error = 1;
return;
}
src = (const char *)p;
}
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
@@ -823,7 +843,12 @@ static void mama_word_switch_mark_work(VM *vm)
uint32_t i;
VMRegistryEntry entry;
if (vm->dsp < 1) { vm->error = 1; return; }
/* FABRIC-3.md §XXXII.6, 2026-09-15: this guard used to set vm->error on
* underflow, contradicting this function's own doc comment above ("must
* never error or spam the console") -- flagged as a special case in
* §XXXII.3's triage, not just a missing diagnostic. Silently ignored,
* matching every other malformed-input case in this same function. */
if (vm->dsp < 1) return;
u = vm_pop(vm);
caddr = vm_pop(vm);
@@ -860,7 +885,11 @@ static void mama_word_vm_call(VM *vm)
VM *target;
char saved_name[VM_NAME_MAX];
if (vm->dsp < 3) { vm->error = 1; return; }
if (vm->dsp < 3) {
console_println("VM-CALL: expects S\" cmd\" S\" name\" VM-CALL -- too few items on the stack");
vm->error = 1;
return;
}
vm_u = vm_pop(vm);
vm_caddr = vm_pop(vm);
@@ -878,7 +907,11 @@ static void mama_word_vm_call(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
if (!p) { vm->error = 1; return; }
if (!p) {
console_println("VM-CALL: invalid VM-name address on the stack");
vm->error = 1;
return;
}
src = (const char *)p;
}
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];
@@ -886,7 +919,11 @@ static void mama_word_vm_call(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)cmd_caddr);
if (!p) { vm->error = 1; return; }
if (!p) {
console_println("VM-CALL: invalid command address on the stack");
vm->error = 1;
return;
}
src = (const char *)p;
}
for (i = 0; i < (uint32_t)cmd_u; i++) cmd_buf[i] = src[i];
@@ -952,7 +989,13 @@ static void mama_word_vm_heat(VM *vm)
const char *src;
VMRegistryEntry entry;
if (vm->dsp < 1) { vm->error = 1; return; }
/* FABRIC-3.md §XXXII.6, 2026-09-15: both guards below used to set
* vm->error, contradicting this function's own doc comment above
* ("does not print/error") -- flagged as a special case in §XXXII.3's
* triage. Push the same 0 the "unknown name" case already returns,
* matching this word's own always-returns-a-value contract, instead
* of erroring. */
if (vm->dsp < 1) { vm_push(vm, 0); return; }
vm_u = vm_pop(vm);
vm_caddr = vm_pop(vm);
@@ -964,7 +1007,7 @@ static void mama_word_vm_heat(VM *vm)
{
const uint8_t *p = vm_ptr(vm, (vaddr_t)vm_caddr);
if (!p) { vm->error = 1; return; }
if (!p) { vm_push(vm, 0); return; }
src = (const char *)p;
}
for (i = 0; i < (uint32_t)vm_u; i++) vm_name[i] = src[i];