Hera can't message: root-caused and fixed by symmetry (FABRIC-3.md §XX)
Hera never loaded common:messaging.4th, unlike every other VM in the fleet. The standing belief was this was deliberate, to avoid moving her dict_hash off baseline. Checked live instead of assumed: loading messaging.4th into her dictionary silently dropped every colon- definition referencing one of 8 STADIUM-* primitives that register_child_vm_words() gives every other VM but register_mama_forth_words() never gave her -- a missing-primitive gap, not a designed privilege boundary. Confirmed mama_word_birth is genuinely VM-agnostic and SPAWN-EVENT is an unwired placeholder before proposing the fix. Fix: register the same 8 STADIUM-* primitives for Hera, load messaging.4th from init.4th the same way Hermes/Artemis/console/mint already do, and give her own idle-loop context a direct MSG-TICK call (not VM-EXEC, which would hit the same reentrancy class the existing per-other-VM pump loop already guards against) so her own queued messages actually drain. Her dictionary is now a proper superset of every child VM's, plus her remaining extra privileges -- not structurally different from any other VM, just additionally privileged. Verified: dict_hash identical across amd64/aarch64/riscv64 (0xc8f4b09e36f4fc4a), Hermes/Artemis dict_hashes unchanged and still cross-arch identical, all three boot clean to zuse)ok> with zero UNKNOWN WORD faults, mkcapsule --lint clean. Unblocks rewriting the turn-attractor (FABRIC-3.md §XIX) to coordinate via real MSG-SEND/MSG-TICK instead of blocking VM-EXEC. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5a9425b91b
commit
7edccd2c35
+98
@@ -2754,3 +2754,101 @@ from §XV. The actual heat-driven "coolest live identity goes next" turn loop, a
|
||||
the whole campaign (including whether K still holds under genuinely interleaved multi-VM
|
||||
contention, which is the actual point of building this) is the next step, not done here.
|
||||
|
||||
## XX. Hera can't message -- root-caused and fixed by symmetry, not special-cased (2026-09-12)
|
||||
|
||||
**Why this had to happen before the turn-attractor.** Building the §XIX turn-attractor around
|
||||
`MSG-SEND`/`MSG-TICK` (the project's real async coordination layer, rather than blocking
|
||||
`VM-EXEC`) requires Hera to be a genuine participant in that layer. She wasn't: Hera never
|
||||
loaded `common:messaging.4th`, unlike Hermes, Artemis, and every identity VM. Before designing
|
||||
around that gap, Captain Bob's framing was checked directly: "I don't want us to begin thinking
|
||||
of Hera as being different than any other VM... the only real difference in Hera should be
|
||||
access to the kernel capsule repository." That's a testable claim about the code, not just a
|
||||
preference, so it was tested rather than assumed.
|
||||
|
||||
**Root cause, not a design boundary.** The standing belief (recorded in the old comment this
|
||||
section replaces, `kernel_main.c`) was that Hera's messaging exclusion was deliberate --
|
||||
"to avoid moving Hera's dict_hash off item 4.1's baseline." Checked live instead of trusted:
|
||||
loading `common:messaging.4th` into Hera's own dictionary silently dropped every colon-definition
|
||||
that referenced one of eight `STADIUM-*` primitives (`STADIUM-ADMIT`, `STADIUM-EVICT`,
|
||||
`STADIUM-RES@`, `STADIUM-RES-PULL`, `STADIUM-RES-PUSH`, `STADIUM-HEAT@`, `STADIUM-HEAT!`,
|
||||
`STADIUM-WORD-HEAT`) -- `register_child_vm_words()` gives every child VM these eight, but
|
||||
`register_mama_forth_words()` never did. Referencing an undefined word during FORTH compilation
|
||||
doesn't raise a hard error, it silently drops the definition being compiled -- so `MSG-HEAT@/!`,
|
||||
`CH-HEAT@/!`, `MSG-COOL-ALL`, `MSG-TICK`, and everything else in `messaging.4th` that touches
|
||||
Stadium came out missing after boot, with no error printed. Not a messaging bug and not a
|
||||
designed privilege boundary -- a plain missing-primitive gap in Hera's own dictionary
|
||||
specifically, that happened to surface as silently-vanished word definitions.
|
||||
|
||||
**Two things independently checked before proposing a fix, not guessed at:**
|
||||
- `mama_word_birth` (`mama_forth_words.c:229`, `BIRTH`'s C implementation) was read in full.
|
||||
It is genuinely VM-agnostic -- it operates on whichever `vm` calls it, with no check that the
|
||||
caller is Hera specifically. The only Hera-specific logic anywhere in it is the reverse guard
|
||||
preventing Hera from re-birthing *herself*. `capsule_birth_baby()` treats `vm->stadium_vm_id`
|
||||
generically as "whoever is birthing this VM." So "any VM could theoretically birth another" is
|
||||
already true in the code, independent of this fix -- Hera's practical monopoly on `BIRTH` is
|
||||
a registration-time fact (only `register_mama_forth_words()` registers it), not a check inside
|
||||
`BIRTH` itself.
|
||||
- `SPAWN-EVENT` (defined as the constant `1` in both `messaging.4th` and `process.4th`) was
|
||||
grepped for every consumer across the tree. There are none -- it is never dispatched or
|
||||
matched on anywhere. An unwired placeholder, not working infrastructure that this fix needed
|
||||
to route through.
|
||||
|
||||
**The fix, scoped and approved before being built ("scope it, plan it and after approval do
|
||||
it"):** register the same eight `STADIUM-*` primitives for Hera that `register_child_vm_words()`
|
||||
already gives every other VM -- in both of Hera's own registration sites
|
||||
(`register_mama_forth_words()`'s root vocabulary and her MAMA vocabulary), matching
|
||||
`register_child_vm_words()`'s list exactly. Then load `common:messaging.4th` from
|
||||
`capsules/init.4th` (block 2049) the same way Hermes/Artemis/console/mint already do, and call
|
||||
`MSG-CD-INIT`. This makes Hera's dictionary a proper *superset* of every child VM's, plus her
|
||||
own remaining extra privileges (`BIRTH`, the capsule-repository words, `MINT`) -- not
|
||||
structurally different from any other VM, just additionally privileged on top of an otherwise
|
||||
identical base. Fixed by symmetry, exactly as scoped, no special-casing introduced.
|
||||
|
||||
**A necessary follow-on, caught while updating the stale comment rather than just rewriting the
|
||||
text.** `repl.c`'s idle-loop pump already walked the VM registry every idle beat, `VM-EXEC`ing
|
||||
`"MSG-TICK"` into every *other* live VM to drain their queues -- explicitly skipping Hera's own
|
||||
registry entry. Re-reading why (not assumed): the skip exists because Hera *is* the pump, and
|
||||
self-targeting `VM-EXEC` would hit the same reentrancy class the loop's own dispatch guard
|
||||
exists for (the same class documented elsewhere for `input_buffer`/`input_pos` not being saved
|
||||
by `vm_state_push`/`pop`) -- not because she lacked `MSG-TICK`. With messaging now loaded for
|
||||
her, that skip would silently leave her own queued messages undrained forever if left alone. Not
|
||||
requested explicitly, but a necessary completion of "Hera is a genuine peer" -- if her own
|
||||
messages never get pumped, she isn't actually participating in the layer, just able to compile
|
||||
against it. Fixed by calling `MSG-TICK` directly in her own context (a plain word dispatch in
|
||||
her own dictionary, not a `VM-EXEC` into anyone else's input buffer -- no reentrancy risk),
|
||||
guarded the same defensive way as the loop above it (`vm_find_word` + `acl_allow` checked fresh
|
||||
every tick, not a cached flag).
|
||||
|
||||
**Verification: dict_hash parity held across all three architectures**, the property that
|
||||
actually matters (identical value across amd64/aarch64/riscv64, not an unchanging absolute
|
||||
value) -- confirmed identical post-fix on all three: `dict_hash=0xc8f4b09e36f4fc4a`,
|
||||
`capsule_hash=0x1ef4939ed32ec1e6`. Hermes' and Artemis' own dict_hashes
|
||||
(`0x0046d7d93aa33935`, `0x0e9e13b9c3a08542`) also matched across all three architectures,
|
||||
confirming the larger, now-symmetric dictionary didn't perturb child-VM parity either. All
|
||||
three booted clean to `zuse)ok>` with zero `UNKNOWN WORD` faults. `mkcapsule --lint capsules/`
|
||||
passes clean (0 violations) after the `messaging.4th`/`init.4th` block-namespace edits this
|
||||
required.
|
||||
|
||||
**Files touched:** `src/starkernel/capsule/mama_forth_words.c` (8 `STADIUM-*` registrations +
|
||||
forward declarations, in both Hera registration sites), `capsules/init.4th` (block 2049, load
|
||||
`common:messaging.4th` + `MSG-CD-INIT`), `capsules/common/messaging.4th` (VM routing table
|
||||
widened 8→16 slots for the identity VMs, block 5006/5042, `mkcapsule --lint` clean),
|
||||
`src/starkernel/repl.c` (direct `MSG-TICK` call for Hera's own context after the existing
|
||||
per-other-VM pump loop), `src/starkernel/kernel_main.c` (stale Phase C comment corrected to
|
||||
describe the fix instead of the old, now-disproven constraint).
|
||||
|
||||
**Explicitly captured for later, not in scope here:** Captain Bob's self-healing idea --
|
||||
"all VMs participating in a wellness check at their nearest participating wellness center" --
|
||||
a distributed liveness/failure-detection concept floated during this discussion, deliberately
|
||||
not built as part of this fix.
|
||||
|
||||
**Next step, now unblocked:** rewrite `EXEC-STD79-DOE-CD` (the draft turn-attractor sketched in
|
||||
§XIX, written *before* this pivot and not yet reworked) to coordinate via `MSG-SEND`/`MSG-TICK`
|
||||
rather than direct blocking `VM-EXEC`, add a `TIE-BREAK ( idx1 idx2 -- idx )` word (seeded coin
|
||||
toss via `RANDOM` to start, swappable for inference later), change turn priority from raw
|
||||
`VM-HEAT` to `VM-HEAT / tests-remaining`, confirm the natural "sender pays" reservoir economy
|
||||
(`STADIUM-RES-PULL`/`STADIUM-RES-PUSH` operate on the *calling* VM's own reservoir, confirmed
|
||||
via `mama_forth_words.c` -- turn cost falls on whichever VM sends, not a "winner pays" model),
|
||||
then rerun the full 3×9×3 DoE campaign from the top per the standing rule that any defect
|
||||
repair requires a clean re-run before a result counts as closed.
|
||||
|
||||
|
||||
+46
-45
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-12T18:51:37Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-12T20:00:38Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
@@ -12,7 +12,7 @@
|
||||
| `acl-std79.4th` | 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047 | `0x5a622e41d1fd0bb9` | yes |
|
||||
| `artemis:init.4th` | 4110, 4111, 4112, 4113, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4177, 4178, 4179, 4180, 4181, 4182, 4851, 4852, 4853, 4854, 4856, 4857, 4858 | `0xac215ecb873c4db3` | yes |
|
||||
| `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | yes |
|
||||
| `common:messaging.4th` | 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041 | `0x5cfb02a42f4a8323` | yes |
|
||||
| `common:messaging.4th` | 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042 | `0xedde53f6faed7355` | yes |
|
||||
| `common:msg.4th` | 4055 | `0x850a0382344ea6c4` | yes |
|
||||
| `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x3d4549142d91ec20` | yes |
|
||||
| `doe.4th` | 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107 | `0xf154616d248e861f` | yes |
|
||||
@@ -35,7 +35,7 @@
|
||||
| `init-l8-temporal.4th` | 4830, 4831 | `0x51abd4c138246651` | yes |
|
||||
| `init-l8-transition.4th` | 4840, 4841, 4842 | `0xbcc1a81976f0a4c9` | yes |
|
||||
| `init-l8-volatile.4th` | 4810, 4811, 4812, 4813 | `0x98caabbbd92abac4` | yes |
|
||||
| `init.4th` | 2049, 2050, 2057 | `0x5d35c5c6a6eafe04` | yes |
|
||||
| `init.4th` | 2049, 2050, 2057 | `0x1ef4939ed32ec1e6` | yes |
|
||||
| `lib.4th` | 4050 | `0x4b216635c359ef73` | yes |
|
||||
| `process.4th` | 4300, 4301 | `0x781afc1dbd0294f7` | yes |
|
||||
| `sdk.4th` | 5109, 5110, 5111, 5112, 5113, 5114, 5115 | `0x008fdbbb62c94a3a` | yes |
|
||||
@@ -48,9 +48,9 @@
|
||||
|
||||
| LBN | Capsule | xxHash64 | Status |
|
||||
|-----|---------|----------|--------|
|
||||
| 2049 | `init.4th` | `0x5d35c5c6a6eafe04` | ok |
|
||||
| 2050 | `init.4th` | `0x5d35c5c6a6eafe04` | ok |
|
||||
| 2057 | `init.4th` | `0x5d35c5c6a6eafe04` | ok |
|
||||
| 2049 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
|
||||
| 2050 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
|
||||
| 2057 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
|
||||
| 2064 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
|
||||
| 2065 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
|
||||
| 2066 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
|
||||
@@ -329,45 +329,46 @@
|
||||
| 5000 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
|
||||
| 5001 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
|
||||
| 5002 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
|
||||
| 5003 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5004 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5005 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5006 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5007 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5008 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5009 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5010 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5011 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5012 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5013 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5014 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5015 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5016 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5017 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5018 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5019 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5020 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5021 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5022 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5023 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5024 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5025 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5026 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5027 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5028 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5029 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5030 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5031 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5032 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5033 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5034 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5035 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5036 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5037 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5038 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5039 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5040 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5041 | `common:messaging.4th` | `0x5cfb02a42f4a8323` | ok |
|
||||
| 5003 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5004 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5005 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5006 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5007 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5008 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5009 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5010 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5011 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5012 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5013 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5014 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5015 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5016 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5017 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5018 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5019 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5020 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5021 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5022 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5023 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5024 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5025 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5026 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5027 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5028 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5029 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5030 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5031 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5032 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5033 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5034 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5035 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5036 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5037 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5038 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5039 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5040 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5041 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5042 | `common:messaging.4th` | `0xedde53f6faed7355` | ok |
|
||||
| 5100 | `turtle.4th` | `0x4d470418ca543365` | ok |
|
||||
| 5101 | `turtle.4th` | `0x4d470418ca543365` | ok |
|
||||
| 5102 | `turtle.4th` | `0x4d470418ca543365` | ok |
|
||||
|
||||
@@ -59,19 +59,31 @@ VARIABLE CH-ACTIVE
|
||||
VARIABLE COMMON-CH
|
||||
VARIABLE MY-CH-ID
|
||||
Block 5006
|
||||
( VM name routing table -- same fixed table every VM loads, )
|
||||
( so IDX>NAME resolves identically everywhere. )
|
||||
8 CONSTANT VM-MAX
|
||||
( VM routing table. SXIX: 16 slots, not 8 -- see FABRIC-3.md. )
|
||||
( Hera/Hermes/Artemis stay 0/1/2 (artemis:init.4th depends on )
|
||||
( it); identities get NEW slots 3-10, never renumbered. )
|
||||
16 CONSTANT VM-MAX
|
||||
CREATE VM-NAME-ADDRS VM-MAX CELLS ALLOT
|
||||
CREATE VM-NAME-LENS VM-MAX CELLS ALLOT
|
||||
: VM-NAME-REG ( addr u idx -- )
|
||||
DUP VM-MAX >= IF DROP 2DROP EXIT THEN
|
||||
>R R@ CELLS VM-NAME-LENS + !
|
||||
R> CELLS VM-NAME-ADDRS + ! ;
|
||||
Block 5042
|
||||
( doe-idx (std79-doe.fth ID-NAME) -> msg-idx: 1..8 -> 3..10. )
|
||||
: DOE-IDX>MSG-IDX ( doe-idx -- msg-idx ) 2 + ;
|
||||
: VM-NAMES-INIT ( -- )
|
||||
S" Hera" 0 VM-NAME-REG
|
||||
S" Hermes" 1 VM-NAME-REG
|
||||
S" Artemis" 2 VM-NAME-REG ;
|
||||
S" Artemis" 2 VM-NAME-REG
|
||||
S" rajames" 1 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 00" 2 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 01" 3 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 02" 4 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 03" 5 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 04" 6 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 05" 7 DOE-IDX>MSG-IDX VM-NAME-REG
|
||||
S" 06" 8 DOE-IDX>MSG-IDX VM-NAME-REG ;
|
||||
Block 5007
|
||||
( INIT-FREE. stamps STADIUM-NONE into each slot's stadium- )
|
||||
( cell field (msg off 5, ch off 3). Raw offsets: accessors )
|
||||
|
||||
@@ -19,6 +19,9 @@ S" zuse-eligibility.4th" EXEC
|
||||
S" lib.4th" EXEC
|
||||
S" fabric.4th" EXEC
|
||||
S" font.4th" EXEC
|
||||
( SXX: same pattern Hermes/Artemis/console/mint already use. )
|
||||
S" common:messaging.4th" EXEC
|
||||
MSG-CD-INIT
|
||||
Block 2050
|
||||
( Hera boot — banner )
|
||||
BOOT-BANNER
|
||||
|
||||
Binary file not shown.
@@ -1592,6 +1592,18 @@ static void mama_word_connect_hermes(VM *vm)
|
||||
console_set_vm_name(saved_name);
|
||||
}
|
||||
|
||||
/* Forward declarations: these 8 are defined later in this file (originally
|
||||
* only ever used from register_child_vm_words(), which comes after them),
|
||||
* but FABRIC-3.md SXX now also registers them here, earlier in the file. */
|
||||
static void mama_word_stadium_admit(VM *vm);
|
||||
static void mama_word_stadium_evict(VM *vm);
|
||||
static void mama_word_stadium_res_fetch(VM *vm);
|
||||
static void mama_word_stadium_res_pull(VM *vm);
|
||||
static void mama_word_stadium_res_push(VM *vm);
|
||||
static void mama_word_stadium_heat_fetch(VM *vm);
|
||||
static void mama_word_stadium_heat_store(VM *vm);
|
||||
static void mama_word_stadium_word_heat(VM *vm);
|
||||
|
||||
/**
|
||||
* @brief Register Mama FORTH vocabulary words with the VM
|
||||
*
|
||||
@@ -1634,6 +1646,26 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
/* FABRIC-3.md SXX: the 8 STADIUM-* primitives register_child_vm_words()
|
||||
* gives every other VM, added here too -- root cause of "Hera cannot
|
||||
* load common:messaging.4th" (kernel_main.c's old Phase C comment):
|
||||
* messaging.4th's own colon-definitions (MSG-HEAT@, CH-HEAT@,
|
||||
* MSG-COOL-ALL, MSG-TICK, etc.) reference these, and referencing an
|
||||
* undefined word during compilation silently drops the definition
|
||||
* rather than raising a compile error -- not a messaging bug, a
|
||||
* missing-primitive gap in Hera's own dictionary specifically. Fixed
|
||||
* by symmetry, not a special case: Hera's dictionary is now a proper
|
||||
* superset of every child VM's, plus her own extra privileges
|
||||
* (BIRTH, the capsule-repository words, MINT) -- not structurally
|
||||
* different from any other VM, just additionally privileged. */
|
||||
register_word(vm, "STADIUM-ADMIT", mama_word_stadium_admit);
|
||||
register_word(vm, "STADIUM-EVICT", mama_word_stadium_evict);
|
||||
register_word(vm, "STADIUM-RES@", mama_word_stadium_res_fetch);
|
||||
register_word(vm, "STADIUM-RES-PULL", mama_word_stadium_res_pull);
|
||||
register_word(vm, "STADIUM-RES-PUSH", mama_word_stadium_res_push);
|
||||
register_word(vm, "STADIUM-HEAT@", mama_word_stadium_heat_fetch);
|
||||
register_word(vm, "STADIUM-HEAT!", mama_word_stadium_heat_store);
|
||||
register_word(vm, "STADIUM-WORD-HEAT", mama_word_stadium_word_heat);
|
||||
register_word(vm, "CAPSULE-TEST", mama_word_capsule_test);
|
||||
|
||||
/* Create and switch to MAMA vocabulary */
|
||||
@@ -1672,6 +1704,26 @@ void register_mama_forth_words(VM *vm)
|
||||
register_word(vm, "VM-EXEC", mama_word_vm_exec);
|
||||
register_word(vm, "VM-CALL", mama_word_vm_call);
|
||||
register_word(vm, "VM-HEAT", mama_word_vm_heat);
|
||||
/* FABRIC-3.md SXX: the 8 STADIUM-* primitives register_child_vm_words()
|
||||
* gives every other VM, added here too -- root cause of "Hera cannot
|
||||
* load common:messaging.4th" (kernel_main.c's old Phase C comment):
|
||||
* messaging.4th's own colon-definitions (MSG-HEAT@, CH-HEAT@,
|
||||
* MSG-COOL-ALL, MSG-TICK, etc.) reference these, and referencing an
|
||||
* undefined word during compilation silently drops the definition
|
||||
* rather than raising a compile error -- not a messaging bug, a
|
||||
* missing-primitive gap in Hera's own dictionary specifically. Fixed
|
||||
* by symmetry, not a special case: Hera's dictionary is now a proper
|
||||
* superset of every child VM's, plus her own extra privileges
|
||||
* (BIRTH, the capsule-repository words, MINT) -- not structurally
|
||||
* different from any other VM, just additionally privileged. */
|
||||
register_word(vm, "STADIUM-ADMIT", mama_word_stadium_admit);
|
||||
register_word(vm, "STADIUM-EVICT", mama_word_stadium_evict);
|
||||
register_word(vm, "STADIUM-RES@", mama_word_stadium_res_fetch);
|
||||
register_word(vm, "STADIUM-RES-PULL", mama_word_stadium_res_pull);
|
||||
register_word(vm, "STADIUM-RES-PUSH", mama_word_stadium_res_push);
|
||||
register_word(vm, "STADIUM-HEAT@", mama_word_stadium_heat_fetch);
|
||||
register_word(vm, "STADIUM-HEAT!", mama_word_stadium_heat_store);
|
||||
register_word(vm, "STADIUM-WORD-HEAT", mama_word_stadium_word_heat);
|
||||
register_word(vm, "CAPSULE-TEST", mama_word_capsule_test);
|
||||
register_word(vm, "EXEC", mama_word_exec);
|
||||
|
||||
|
||||
@@ -790,19 +790,30 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase C (2026-08-28): Hera does NOT get her own common:messaging.4th
|
||||
* arena -- register_child_vm_words()'s own doc comment (mama_forth_
|
||||
* words.c) explains why: the eight STADIUM-* FORTH primitives that
|
||||
* word depends on (CH-HEAT@/!, MSG-HEAT@/! etc. all route through
|
||||
* them) are deliberately never added to register_mama_forth_words(),
|
||||
* to avoid moving Hera's dict_hash off item 4.1's baseline. Confirmed
|
||||
* live: loading messaging.4th into Hera's own dictionary silently
|
||||
* dropped every colon-definition that referenced one of those
|
||||
* primitives (MSG-HEAT@/!, CH-HEAT@/!, MSG-COOL-ALL, MSG-TICK all
|
||||
* missing after boot) -- not a timing bug, a real, pre-existing
|
||||
* constraint. Hera orchestrates via BIRTH/VM-EXEC/VM-CALL directly
|
||||
* instead; the idle-loop pump (repl.c) skips her own registry entry
|
||||
* for the same reason. */
|
||||
/* FABRIC-3.md SXX (2026-09-12, supersedes the Phase C note this used to
|
||||
* be): Hera now DOES get her own common:messaging.4th arena, like
|
||||
* every other VM -- root-caused, not special-cased around. The real
|
||||
* cause of the old "loading messaging.4th silently drops colon-
|
||||
* definitions" symptom was never "Hera is special": messaging.4th's
|
||||
* own definitions (MSG-HEAT@/!, CH-HEAT@/!, MSG-COOL-ALL, MSG-TICK,
|
||||
* etc.) reference 8 STADIUM-* primitives that register_child_vm_
|
||||
* words() gives every other VM but register_mama_forth_words() never
|
||||
* gave Hera -- a plain missing-primitive gap, not a designed privilege
|
||||
* boundary, that happened to surface as silently-dropped definitions
|
||||
* because referencing an undefined word during compilation doesn't
|
||||
* raise a hard error. Fixed by symmetry: those same 8 primitives are
|
||||
* now registered for Hera too, making her dictionary a proper
|
||||
* superset of every child VM's (plus her own extra privileges --
|
||||
* BIRTH, the capsule-repository words, MINT). Verified live on all
|
||||
* three architectures: dict_hash is identical across amd64/aarch64/
|
||||
* riscv64 with the new, larger, still-symmetric baseline
|
||||
* (0xc8f4b09e36f4fc4a) -- the actual property that ever mattered was
|
||||
* cross-architecture consistency, not the value never changing. The
|
||||
* idle-loop pump (repl.c) still skips VM-EXECing "MSG-TICK" into
|
||||
* Hera via the registry loop -- that's because she IS the pump
|
||||
* (self-targeting VM-EXEC hits the reentrancy class the loop's own
|
||||
* guard exists for), not because she lacks MSG-TICK now -- and calls
|
||||
* it directly in her own context instead, right after that loop. */
|
||||
|
||||
/* Hermes is now a permanent fleet-foundation VM, not self-test
|
||||
* scaffolding -- FABRIC-2.md D.7 (birth-by-message-only, 2026-08-28):
|
||||
|
||||
@@ -621,6 +621,22 @@ static void sk_repl_idle(VM *active_vm)
|
||||
vm_interpret(mama, cmd);
|
||||
}
|
||||
}
|
||||
/* FABRIC-3.md SXX: Hera now genuinely has her own MSG-ARENA/CH-ARENA
|
||||
* (the messaging-load root cause above is fixed -- see kernel_main.c's
|
||||
* own updated comment at the Hermes-birth call site), so her own
|
||||
* queued messages need draining too, same as every other VM's. She's
|
||||
* excluded from the loop above not because she lacks MSG-TICK now, but
|
||||
* because she IS the pump -- self-targeting VM-EXEC would hit the same
|
||||
* reentrancy class the guard above exists for. No such problem calling
|
||||
* MSG-TICK directly here, though: it's a plain word in her own
|
||||
* dictionary, not a VM-EXEC dispatch into anyone else's input buffer.
|
||||
* Guarded the same defensive way as the loop above, not assumed. */
|
||||
{
|
||||
DictEntry *msgtick = vm_find_word(mama, "MSG-TICK", 8);
|
||||
if (msgtick && msgtick->acl_allow) {
|
||||
vm_interpret(mama, "MSG-TICK");
|
||||
}
|
||||
}
|
||||
g_idle_pump_active = 0;
|
||||
|
||||
if (console_tx_count() == tx_before_idle) {
|
||||
|
||||
Reference in New Issue
Block a user