§XVIII.5 posed agent binding as widen-the-convention vs. add-a-word. Both accept a premise the code does not support: the pairing is already recorded explicitly at bind time, and the ~user reconstruction is a redundant second derivation of information the mechanism already holds. sk_repl_dispatch_line() does two separable things. The guard builds console_get_vm_name() + "~user" and checks it is live. The actual relay then sends to index 3 -- and repl.c's own comment says that slot is "set once at pairing time," which PAIR-TEST's header confirms from the other side. Routing never uses the derived string; only the liveness guard does, and the stored pairing can answer that question without deriving anything. This is also the documented cause of a known silent failure. CONSOLE-ATTACH's own comment records that a console named anything other than the identity's base name reconstructs the wrong target and quietly falls back to direct interpretation with no error. Its "takes exactly one name" constraint is a workaround for that derivation, not a requirement of the problem. Ruling: the guard reads the recorded pairing, CONSOLE-ATTACH resolves the target as given, and ~user survives as a naming convention rather than a mechanism. Agent binding then stops being a special case -- a GPIO VM binds by the same unchanged path, because nothing appends anything to its name. Punch item 19 is retired rather than fixed: with no string to mismatch there is nothing to make loud. The six memcpy sites split cleanly -- three name a VM at birth and stay, two re-derive a partner for lookup and go. Only the derivation sites change, which is why the convention can survive without the mechanism. Also separates what §V.1 conflated: reachability is kernel-Hermes's, fabric access is vocabulary and ACL, and binding proper is the console path. An agent VM does not routinely bind at all. Scoped per §XIV.1: this states the principle kernel-Hermes must carry forward, not a proposal to patch the legacy FORTH path in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
1820 lines
108 KiB
Markdown
1820 lines
108 KiB
Markdown
# FABRIC-3.5.md — the Tripod/kernel reshuffle
|
||
|
||
**Status:** Standalone working document, opened 2026-09-18 by direct instruction ("we write
|
||
this in `FABRIC-3.5.md` as its own document, it's this important"). Topic: **relocating Hermes
|
||
into the kernel, reconstituting the Tripod as Hera/Artemis/Hestia, generalizing `BIRTH`, and
|
||
adopting one fleet-wide failure/recovery ladder.**
|
||
|
||
**Why 3.5 and not 4, and why not a section of 3.** `FABRIC-4.md` is explicitly the
|
||
lower-discipline scratchpad for theory-stage ideas "caught early... often missing a stated
|
||
'why' on purpose." This is not that: it is a ratified architectural direction with a stated
|
||
shape, and it needs the full discipline every numbered FABRIC document carries. But it is
|
||
also not bare-metal boot, which is `FABRIC-3.md`'s declared topic, and it is not a successor
|
||
to `FABRIC-3.md` — **`FABRIC-3.md` remains open, living, and authoritative for its own
|
||
topic; nothing here supersedes it, and this document does not trigger the
|
||
close-and-carry-forward discipline** the `FABRIC-0` → `-1` → `-2` → `-3` chain used (that
|
||
chain triggers on *closing* a document). It sits at 3.5 because it is a peer in rigor and an
|
||
outsider in topic.
|
||
|
||
**How to use this document.** Same discipline as the rest of the series: write the decision
|
||
and its reasoning down before building, close items with a dated note citing real evidence,
|
||
never silently drop a stale claim. New findings and decisions for the reshuffle get added
|
||
here, not to `FABRIC-3.md`.
|
||
|
||
**Scope discipline, stated up front: this is a reorganization, not an invention.** Per the
|
||
instruction opening it — "most of the underlying logic (Hermes routing, Artemis block I/O,
|
||
Hera lifecycle/ACL, Console framebuffer) already exists and is expected to be relocated and
|
||
rewired rather than rewritten." Any item in this document that turns out to need a genuinely
|
||
new algorithm is by that fact out of scope and gets flagged, not quietly built.
|
||
|
||
**No code is authorized by this document.** Design only. Per Captain Bob's Law
|
||
(`.claude/CLAUDE.md`): never apply a fix not explicitly requested.
|
||
|
||
**Provenance convention used below.** This series distinguishes what was read from what was
|
||
recalled, so each claim says which. **"Traced 2026-09-18"** = the file was read directly while
|
||
writing this document. **"Per §X"** = the fact is reported by an existing FABRIC section that
|
||
did its own end-to-end read; it is cited, not re-verified here. **"Open"** = not decided.
|
||
Several items below are deliberately marked for re-verification before any code is written,
|
||
because a reorganization that trusts a stale map moves the wrong things.
|
||
|
||
---
|
||
|
||
## I. The current shape, traced rather than recalled
|
||
|
||
Before moving anything, what is actually there today. All of §I traced 2026-09-18 against the
|
||
working tree at commit `e56974e`, except where marked.
|
||
|
||
### I.1 — Hermes is a FORTH capsule VM, and the routing layer is FORTH, not C
|
||
|
||
`capsules/hermes/init.4th` is short and load-bearing. Its block 5116 says it outright:
|
||
|
||
> Hermes owns the one real, canonical `COMMON-CH`. Every other VM subscribes into it via
|
||
> `VM-EXEC` (see Artemis's and Hera's own `init.4th`); Hera always exists first, so Hermes
|
||
> adds her here rather than Hera subscribing to a VM that doesn't exist yet at Hera's own
|
||
> birth.
|
||
|
||
It then does `S" common:messaging.4th" EXEC`, `MSG-CD-INIT`, `1 MY-CH-ID !`, and adds members
|
||
`1` and `0` to `COMMON-CH`. That is the whole of Hermes's own identity: it is the VM that
|
||
happens to hold the canonical channel.
|
||
|
||
The mechanism it holds is `capsules/common/messaging.4th` (504 lines) — **generic per-VM
|
||
messaging vocabulary that every participating VM loads its own copy of.** This matters more
|
||
than it first appears. Block 5005 allocates the arenas with `CREATE ... ALLOT`:
|
||
|
||
```
|
||
CREATE MSG-ARENA MSG-MAX MSG-CELLS * CELLS ALLOT
|
||
CREATE CH-ARENA CH-MAX CH-CELLS * CELLS ALLOT
|
||
CREATE MBR-ARENA MBR-MAX MBR-CELLS * CELLS ALLOT
|
||
```
|
||
|
||
`CREATE`/`ALLOT` carves out of *the dictionary of whichever VM is interpreting*. So today
|
||
there is no single routing fabric — there are N per-VM copies of the same vocabulary, and
|
||
Hermes is distinguished only by convention (it holds `COMMON-CH`; it is routing table index
|
||
1). **The arbitration is distributed and conventional, not centralized and structural.**
|
||
|
||
### I.2 — Hermes is a hard, by-name dependency of its peers
|
||
|
||
> **CORRECTED 2026-09-18 by §XIII.1 — this section undercounts.** It names two call sites; the
|
||
> full repo-wide inventory is **14 by-name FORTH references across 5 files, plus 3 C-side
|
||
> sites and a DoE CSV schema site.** The two below are real, are among the only three *live*
|
||
> ones, and remain the sharpest edge — but read §XIII.1 for the actual extent. Left in place
|
||
> rather than rewritten, per this series' own "never silently drop a stale claim" rule.
|
||
|
||
Artemis does not talk to an abstract routing layer. It talks to a VM called `Hermes`, by name,
|
||
via `VM-EXEC`. Two live call sites in `capsules/artemis/init.4th`:
|
||
|
||
- line ~138: `S" 2 ENQUEUE-READY" S" Hermes" VM-EXEC`
|
||
- line ~501: `S" 2 COMMON-CH @ CH-ADD-MBR" S" Hermes" VM-EXEC`
|
||
|
||
Both execute FORTH text *inside Hermes's own dictionary*. Either one breaks the moment
|
||
Hermes is not a VM with a dictionary. This is the single most concrete consequence of the
|
||
move and §III.3 is about it.
|
||
|
||
### I.3 — The routing table pins 0/1/2 and says so
|
||
|
||
`messaging.4th` block 5006, verbatim comment:
|
||
|
||
> VM routing table. §XIX: 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.
|
||
|
||
`VM-NAMES-INIT` registers `Hera` 0, `Hermes` 1, `Artemis` 2, then identities from 3 up via
|
||
`DOE-IDX>MSG-IDX ( doe-idx -- msg-idx ) 2 +`. **"Never renumbered" is an existing, written
|
||
commitment, and the reshuffle walks straight into it** (§IV.2).
|
||
|
||
### I.4 — Message types in use, and the free numbers
|
||
|
||
Traced across `messaging.4th`: `SPAWN-EVENT` 1, `PAUSE-EVENT` 2, `RESUME-EVENT` 3,
|
||
`KILL-EVENT` 4, `CONSOLE-CMD-EVENT` 7, `ELEVATE-REQUEST` 8, `BLK-ATTACH-EVENT` 9. Reserved
|
||
status sentinels at the top of the range: `MSG-NACKED` 253, `MSG-DELIVERED` 255.
|
||
|
||
**5 and 6 are unallocated gaps; 10 is the next in sequence.** Relevant to §VII, which needs a
|
||
number for `SOS`. Also relevant: per §XX, `SPAWN-EVENT` was grepped for every consumer across
|
||
the tree and **has none** — "an unwired placeholder, not working infrastructure." Do not
|
||
model `SOS` on it as though it were a working precedent.
|
||
|
||
### I.5 — `BIRTH` is already VM-agnostic in C; Hera's monopoly is registration-time
|
||
|
||
Per §XX, which read `mama_word_birth` (`mama_forth_words.c:229`, `BIRTH`'s C implementation)
|
||
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... Hera's practical monopoly on
|
||
> `BIRTH` is a registration-time fact (only `register_mama_forth_words()` registers it), not
|
||
> a check inside `BIRTH` itself.
|
||
|
||
**This is the single most important pre-existing fact in this document.** §VI is not a
|
||
redesign of `BIRTH`; it is a change to which VMs get it registered, plus an inheritance rule.
|
||
|
||
### I.6 — Hestia already has a real bind mechanism, built and live-verified
|
||
|
||
Per §XXXII.2, closed 2026-09-16: `CONSOLE-ATTACH ( name-c name-u -- ok? )` exists, is a plain
|
||
unconditional primitive (deliberately *not* an identity capability bit — that was tried and
|
||
rejected on two counts), and was verified end to end on amd64: `UNATTENDED-BIRTH` a VM named
|
||
`bob` → `CONSOLE-ATTACH bob` → `S" bob" USE` → typing `5 6 + .` at the new console relayed to
|
||
and executed on the target identity VM, printing `[zuse@bob~user] 11 ok>`.
|
||
|
||
Also live: `capsule_console_birth()` (minimal relay proxy, bare username) paired to
|
||
`capsule_runcap_birth()` (the real identity, `<username>~user`) by name convention plus one
|
||
`VM-NAME-REG` executed inside the console VM's own dictionary — **confirmed per-console-VM,
|
||
not a global singleton, so after-the-fact pairing already works structurally.**
|
||
|
||
**§V is therefore mostly a promotion of an existing, proven mechanism to an architectural
|
||
role — not new construction.**
|
||
|
||
### I.7 — The headless-until-login invariant
|
||
|
||
Per §VIII.1 (ratified) and §XXXII.2: `g_wirebind_attached_username` is what
|
||
`sk_console_identity_present()` reads (`capsule_wirebind.c:321-327`), and that function is the
|
||
live "no thumbdrive, no prompt" gate. §XXXII.2 states the rule as an explicit invariant for
|
||
any new birth path: **never set that global, never touch the console-pairing mechanism, or you
|
||
bring up a console with no human present and reopen a gate that was deliberately closed.**
|
||
§V and §VI both have to carry this invariant forward.
|
||
|
||
### I.8 — The idle pump, and why Hera is special-cased in it
|
||
|
||
Per §XX: `repl.c`'s idle loop walks the VM registry every idle beat, `VM-EXEC`ing `"MSG-TICK"`
|
||
into every *other* live VM to drain its queue, skipping Hera — because Hera *is* the pump and
|
||
self-targeting `VM-EXEC` would hit a known reentrancy class. Hera instead gets a direct
|
||
`MSG-TICK` word dispatch in her own context, guarded by a fresh `vm_find_word` + `acl_allow`
|
||
check every tick rather than a cached flag.
|
||
|
||
**So there is already a kernel-resident component driving the messaging layer's clock.** The
|
||
pump is in `repl.c`, in C, today. §III is in part an admission that the arbiter's center of
|
||
gravity is already partly there.
|
||
|
||
---
|
||
|
||
## II. What the reshuffle is, in one paragraph
|
||
|
||
Hermes stops being a peer VM on the Stadium floor and becomes a kernel-resident arbiter
|
||
between the floor and the HAL. It stops being a *client* of ACL-checked, Hermes-routed
|
||
messaging and becomes the routing and arbitration layer itself. The Tripod — which was Hera,
|
||
Hermes, Artemis — is reconstituted as **Hera, Artemis, Hestia**, with Artemis keeping its
|
||
existing storage/block-arbitration role and Hestia taking the vacated third slot. Hestia's
|
||
own role widens from owning the drawing fabric to being the **bind point** where users and
|
||
agent VMs (the GPIO VM of `FABRIC-4.md` §2, future networking VMs) attach. `BIRTH` becomes a
|
||
general primitive any VM with standing may invoke, with authority bounded by inheritance
|
||
rather than by a separate check. And every VM in the fleet — current and future — adopts one
|
||
escalation ladder on failure: recover gently, escalate to a from-scratch birth, then fail fast
|
||
and total.
|
||
|
||
---
|
||
|
||
## III. Hermes moves into the kernel
|
||
|
||
### III.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
Hermes is no longer a Tripod VM. It becomes kernel-resident, sitting between the Stadium floor
|
||
and the HAL. **It no longer participates in Hermes-routed, ACL-checked messaging the way the
|
||
other VMs do — it *is* the routing/arbitration layer now, not a client of it.**
|
||
|
||
### III.2 — What that actually changes, structurally
|
||
|
||
The self-reference in "Hermes cannot be a client of Hermes" is the whole point, and it has a
|
||
concrete reading against §I.1: today Hermes holds `COMMON-CH` inside a FORTH dictionary that
|
||
is itself subject to the same ACL and Stadium-heat economy as every other VM's. An arbiter
|
||
whose own arbitration state can be evicted, cooled, or ACL-denied by the mechanism it arbitrates
|
||
is a circular dependency that happens not to have bitten yet. Moving it into the kernel breaks
|
||
the circle by construction.
|
||
|
||
Note this is also what makes §VII's `SOS` exception (Hermes cannot route a message announcing
|
||
its own routing failure) not a special case but a direct corollary — see §VIII.
|
||
|
||
### III.3 — The by-name `VM-EXEC` dependency has to go somewhere. Open.
|
||
|
||
> **SUPERSEDED 2026-09-18 by §XIV.1/§XIV.2 — this question dissolved.** The three options below
|
||
> all assume the existing FORTH callers must be preserved. Captain Bob ruled the FORTH
|
||
> messaging layer legacy, so §XIII.1's inventory becomes input to a dead-FORTH cleanup rather
|
||
> than a migration constraint. Left in place, not rewritten.
|
||
|
||
§I.2's two Artemis call sites are the sharp edge. `S" ..." S" Hermes" VM-EXEC` requires a
|
||
target VM with a dictionary. Three shapes are visible; **none is chosen here:**
|
||
|
||
1. **Kernel primitives replace the by-name calls.** `ENQUEUE-READY` and `CH-ADD-MBR` become
|
||
registered C words callable directly by any VM, and Artemis simply calls them. Closest to
|
||
"relocated, not rewritten"; largest registration-surface change.
|
||
2. **A vestigial `Hermes` name that the kernel answers.** `VM-EXEC` to `Hermes` is intercepted
|
||
and serviced by the kernel arbiter, leaving caller text untouched. Smallest diff, but it
|
||
preserves a fiction and this project has a standing distaste for exactly that
|
||
(§XXXII.2 Q3's rejection of an unreachable gate on doctrine grounds, not just mechanics).
|
||
3. **Artemis subscribes through a new kernel-side registration call at birth**, removing the
|
||
peer-to-peer step entirely.
|
||
|
||
**Decide this on paper before touching code.** Whichever wins, the two Artemis lines and the
|
||
`STARTUP-BANNER`/`LOG-INFO"` scaffolding in `capsules/hermes/init.4th` are the concrete edit
|
||
set, plus whatever else a full grep for `S" Hermes" VM-EXEC` turns up — **that grep has not
|
||
been run exhaustively for this document and must be, repo-wide, before scoping.**
|
||
|
||
### III.4 — The per-VM-arena question. Open, and the biggest unknown here.
|
||
|
||
> **RESOLVED 2026-09-18 by §XIV.1/§XIV.2.** Answered in the "full centralization" direction,
|
||
> but without the migration cost this section feared: with the FORTH legacy there is no live
|
||
> state to port. This was named the root dependency throughout §X; it is closed. Left in
|
||
> place, not rewritten.
|
||
|
||
Per §I.1 the arenas are per-VM dictionary allocations. If arbitration centralizes into the
|
||
kernel, does `MSG-ARENA`/`CH-ARENA`/`MBR-ARENA` centralize with it, or does each VM keep its
|
||
own outbox/inbox with only the *routing* centralized? These are very different amounts of
|
||
work and very different risk:
|
||
|
||
- **Routing-only centralization** keeps `messaging.4th` largely intact, keeps the Stadium heat
|
||
economy's "sender pays" property (per §XX: `STADIUM-RES-PULL`/`-PUSH` operate on the
|
||
*calling* VM's own reservoir), and is genuinely a reshuffle.
|
||
- **Full arena centralization** moves FORTH dictionary state into kernel C, changes every
|
||
VM's `dict_hash`, and needs the three-arch parity story re-established from scratch.
|
||
|
||
**Not decided.** Flagged here because the executive framing ("relocated and rewired rather
|
||
than rewritten") holds comfortably for the first and is strained by the second.
|
||
|
||
### III.5 — Parity consequence, stated so it is not discovered late
|
||
|
||
Any change to what `register_*_words()` registers, or to what `init.4th` loads, changes VM
|
||
dictionary contents and therefore `dict_hash`. §XX's own verification standard applies: the
|
||
property that matters is **identical `dict_hash` across amd64/aarch64/riscv64, not an
|
||
unchanging absolute value.** Expect the absolute hashes to move; require the cross-arch
|
||
identity to hold. Acceptance is the three-arch QEMU boot to `zuse)ok>` with zero
|
||
`UNKNOWN WORD` faults, per `.claude/CLAUDE.md`'s non-negotiable criteria — there is no other
|
||
test.
|
||
|
||
---
|
||
|
||
## IV. The Tripod reconstituted: Hera, Artemis, Hestia
|
||
|
||
### IV.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
Tripod = **Hera, Artemis, Hestia.** Artemis keeps its existing role (storage/block
|
||
arbitration) unchanged. Hestia takes the slot Hermes vacates.
|
||
|
||
### IV.2 — The "never renumbered" collision. Open, needs a ruling.
|
||
|
||
> **DISSOLVED 2026-09-18 by §XIV.1/§XIV.2 — via option 3 below, exactly as this section
|
||
> predicted.** The FORTH routing table is legacy, so the slot-numbering question has no
|
||
> subject. Option 3's own caveat ("settle §III.4 first") was the correct call. Left in place,
|
||
> not rewritten.
|
||
|
||
§I.3's comment commits to Hera/Hermes/Artemis at 0/1/2 and to identities at 3–10 *never*
|
||
being renumbered. Hermes leaving index 1 forces a choice, and the existing comment forecloses
|
||
the laziest option:
|
||
|
||
1. **Hestia takes index 1.** Tidy, preserves the "Tripod occupies 0/1/2" shape, and requires
|
||
no identity renumbering — but it silently redefines what slot 1 *means*, and
|
||
`artemis:init.4th`'s dependence on the numbering is on 2, not 1, so it may be survivable.
|
||
2. **Index 1 is retired; Hestia takes a fresh slot.** Honest, costs a slot out of 16, and
|
||
leaves a permanent hole that needs a comment explaining itself forever.
|
||
3. **The routing table stops being a FORTH array at all**, because §III moved routing into the
|
||
kernel — in which case this question dissolves into §III.4's arena question and should not
|
||
be answered separately.
|
||
|
||
**Not decided. Note option 3 makes 1 and 2 moot, so settle §III.4 first.** This ordering
|
||
matters: answering IV.2 before III.4 risks ratifying a table that the kernel move deletes.
|
||
|
||
---
|
||
|
||
## V. Hestia's role expands: the bind point
|
||
|
||
### V.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
Beyond owning the drawing fabric, Hestia becomes **the bind point for users and agent VMs** —
|
||
GPIO VM, future networking VMs, and whatever follows. The attach point that was previously
|
||
implicit or undecided now lives here, explicitly.
|
||
|
||
### V.2 — This is mostly promotion of an existing mechanism, not new construction
|
||
|
||
Per §I.6, `CONSOLE-ATTACH` already resolves a target's liveness by name *before* birthing a
|
||
console (so a typo refuses cleanly with no orphaned VM — verified live), and console/user
|
||
pairing already works after the fact. The reshuffle's contribution is **declaring that this is
|
||
the fleet's attach point**, and then asking the question the current mechanism does not yet
|
||
answer: it was built for *human at a console attaching to an identity VM*. An agent VM — a
|
||
GPIO VM per `FABRIC-4.md` §2, pinned and born at boot with no human anywhere near it — is a
|
||
different shape wearing the same word.
|
||
|
||
### V.3 — Genuinely open
|
||
|
||
1. **Does an agent VM bind through `CONSOLE-ATTACH` or through a sibling word?**
|
||
`sk_repl_dispatch_line()`'s pairing check reconstructs the target as
|
||
`console_get_vm_name() + "~user"` (per §XXXII.2, and the cause of a real bug caught live
|
||
when a console was named anything else). A GPIO VM is not a `~user` identity. Either the
|
||
naming convention widens or agent binding takes its own path.
|
||
2. **Does binding an agent VM touch `g_wirebind_attached_username`?** It must not — §I.7. State
|
||
this as an explicit invariant in whatever implements it, exactly as §XXXII.2 required of
|
||
unattended birth.
|
||
3. **Is Hestia's bind role ACL-gated, and if so where?** Per `.claude/CLAUDE.md`'s hard rule
|
||
and §XXXII.2 Q3's correction: policy belongs in `ACL.4th`, never in C. The shape is
|
||
`' CONSOLE-ATTACH ACL-PIN` (or a sibling word's equivalent) in `ACL.4th`, not a C-side
|
||
capability check — and specifically **not** a `vm_identity_has_cap()` gate, which §XXXII.2
|
||
proved unreachable because `identity.installed` is 0 for Hera/Hermes/Artemis and for every
|
||
console-proxy VM.
|
||
4. **Does Hestia-as-bind-point survive Hestia being a Tripod member?** A Tripod VM is pinned
|
||
and born at boot (`session_register()`/`session_set_pinned()`, per `FABRIC-2.md` §H.12
|
||
step 4; "pinned sessions never leave," §H.1 — **cited from `.claude/CLAUDE.md`'s and §XX's
|
||
references, not re-read for this document; verify before relying on it**). Whether the
|
||
drawing-fabric owner and the bind-point arbiter are the same VM or two roles that happen to
|
||
share a name is not settled here.
|
||
|
||
---
|
||
|
||
## VI. `BIRTH` as a general primitive
|
||
|
||
### VI.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
`BIRTH` is a general primitive, not Hera-exclusive. **Any VM with standing can invoke it.** A
|
||
birthed VM inherits its ACL/DNA from the birthing VM. **A VM can never birth something with
|
||
more authority than it itself holds — enforced by inheritance, not by a separate
|
||
authorization check.**
|
||
|
||
### VI.2 — Why this is small in C and large in policy
|
||
|
||
Per §I.5 the C implementation is already VM-agnostic; the monopoly is which registration
|
||
function hands out the word. So the mechanical change is registration, and the design work is
|
||
entirely in the inheritance rule.
|
||
|
||
The rule as stated is elegant precisely because it needs no gate: if a child's authority is
|
||
*derived* from the parent's, "cannot exceed the parent" is not a check that can be bypassed,
|
||
forgotten, or misconfigured — it is a property of how the child is constructed. This is the
|
||
same doctrine §XXXII.2 Q3 landed on from the opposite direction (a bespoke gate that can never
|
||
open is worse than no gate), and the same doctrine `ZUSE-ELIGIBILITY-ADD` already carries.
|
||
|
||
### VI.3 — "ACL/DNA" needs a precise referent. Open, and this is the real work.
|
||
|
||
The system has a **word-level** ACL: four `DictEntry` fields (`acl_ttl`, `acl_allow`,
|
||
`acl_mode`, `acl_pinned`), a C primitive `ACL-INHERIT` (traced 2026-09-18 in `capsules/ACL.4th`'s
|
||
own primitive list, line 6), and the semantics "pin is one-way; inheritance clears pin, copies
|
||
mode" (per `.claude/CLAUDE.md`). What §VI.1 describes is **VM-level** inheritance — a different
|
||
axis. Two things must be settled before any code:
|
||
|
||
1. **Is VM-level DNA just "the child's dictionary is built from the parent's, with per-word
|
||
state carried by the existing `ACL-INHERIT`"?** If yes, this is genuinely a reshuffle and
|
||
the existing primitive does the work. If no, something new is being invented and that
|
||
contradicts this document's own scope discipline — flag it rather than build it.
|
||
2. **Hard constraint:** `.claude/CLAUDE.md` states "Never add `acl_*` fields to `DictEntry`
|
||
beyond the four already present." Any DNA design that wants a fifth per-word field is
|
||
ruled out at the door. If VM-level authority needs state, it belongs on the VM, not on
|
||
every dictionary entry.
|
||
|
||
### VI.4 — "With standing" is undefined. Open.
|
||
|
||
§VI.1 says *any VM with standing*. Standing is not currently a concept in this codebase —
|
||
traced: no such notion appears in the ACL vocabulary or the Stadium words. Candidate readings:
|
||
(a) standing = simply having `BIRTH` registered, which collapses it into §VI.2's registration
|
||
question and makes the phrase decorative; (b) standing = a Stadium-economy property (sufficient
|
||
reservoir to pay for a child, consistent with "sender pays"); (c) standing = an `ACL.4th`
|
||
policy predicate. **Not decided.** (a) is the minimal reading and the one most consistent with
|
||
"do not over-engineer"; (b) is the one most consistent with the rest of the fleet's physics.
|
||
|
||
### VI.5 — Invariants that must survive
|
||
|
||
- The reverse guard preventing Hera from re-birthing herself (per §I.5) still has to hold, and
|
||
now has to hold for *every* birther with respect to itself.
|
||
- `capsule_birth_baby()` must stay the generic path — per §XXXII.2 it is already what every
|
||
`(p)` capsule uses across four call sites, and `capsule_runcap_birth()` was explicitly
|
||
established as the wrong tool for build-time-sourced births.
|
||
- Unattended/agent births must not set `g_wirebind_attached_username` (§I.7).
|
||
- `' BIRTH` must not enter `capsules/ACL.4th` — per `.claude/CLAUDE.md`, `ACL.4th` is shared
|
||
and portable, `BIRTH` is kernel-only, and the file deliberately omits it (comment at ~line
|
||
64). Generalizing `BIRTH` does **not** change this; pin it in a kernel-specific capsule.
|
||
|
||
---
|
||
|
||
## VII. One fleet-wide failure/recovery ladder
|
||
|
||
### VII.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
A single escalation shape, applied consistently across the fleet — current VMs and future ones
|
||
(GPIO, networking, whatever comes):
|
||
|
||
1. **Recover gently first.** For a VM with continuity to preserve (Hera being the type case),
|
||
this means **warm restart — resume with prior state intact.**
|
||
2. **Escalate if gentle recovery fails.** Fall back to a **from-scratch `BIRTH`** — no
|
||
continuity, rebuild fleet-state/trust from nothing.
|
||
3. **Fail brutally once genuinely exhausted.** No lingering, no partial states. Once recovery
|
||
options are spent the failure is **fast and total, not a slow degrade.**
|
||
|
||
The value here is uniformity: one shape for Hera, Hermes, Hestia and every future VM, instead
|
||
of bespoke handling per component.
|
||
|
||
### VII.2 — `SOS` as a standard message type
|
||
|
||
**Decided:** `SOS` is a standard message type **any** VM can emit — not specific to any one
|
||
component. It applies to non-Tripod VMs and to two of the three Tripod VMs (Hera and Hestia).
|
||
Hermes is the exception, for a structural reason — §VIII.
|
||
|
||
**Grounding and open points:**
|
||
- It takes a number from §I.4's space. **5 and 6 are unallocated gaps; 10 is next in
|
||
sequence.** Picking a gap vs. appending is a small call but should be made deliberately, not
|
||
by whoever types first.
|
||
- **Do not model it on `SPAWN-EVENT`.** Per §XX that constant has zero consumers anywhere in
|
||
the tree — it is an unwired placeholder. A message type with no dispatcher is exactly the
|
||
failure mode `SOS` cannot afford.
|
||
- **Open: who consumes an `SOS`, and what do they do with it?** The executive framing says
|
||
`SOS` is emitted; it does not say who acts. Given §IX (no VM assumes another's authority),
|
||
the consumer set is constrained but not specified.
|
||
|
||
### VII.3 — The existing precedent this should be reconciled with
|
||
|
||
> **WITHDRAWN 2026-09-18 by §XV.2 — this section's premise is wrong.** It assumed the ladder
|
||
> needs a detection mechanism. Death is compudynamic: no detector, no declarer, nothing to
|
||
> build. The closing claim below ("a recovery ladder with no detection story only ever triggers
|
||
> on failures loud enough to notice by accident") does not hold. The wellness-check idea stands
|
||
> on its own merits, unrelated to this ladder. Left in place, not rewritten.
|
||
|
||
Per §XX, closed as captured-for-later: 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 "deliberately not built as part of this fix."
|
||
|
||
**That idea and this ladder are the same problem approached from two ends**: wellness checks
|
||
are how a failure gets *detected*; the ladder is what happens *after*. Neither document has
|
||
reconciled them. **Flagged as open, and as the natural next thing to settle**, because a
|
||
recovery ladder with no detection story only ever triggers on failures loud enough to notice
|
||
by accident.
|
||
|
||
### VII.4 — Open: what "warm restart" concretely means
|
||
|
||
Warm restart implies a state boundary — what is "prior state" for a VM, and where does it live
|
||
across the restart? Candidate anchors traced or cited: the Stadium reservoir/heat state, the
|
||
VM's dictionary, its message arenas (§III.4 — if those centralize into the kernel, warm
|
||
restart gets *easier*, which is an argument to settle §III.4 first), its `identity` struct.
|
||
**Not designed here.** Note also that "fail brutally" must not mean "leave the Stadium's
|
||
conservation invariant K broken" — per `FABRIC-3.md` §XVIII that invariant is continuously
|
||
verified, so a brutal death still has to return what it held. **Cited from §XVIII's heading,
|
||
not re-read for this document; verify before relying on it.**
|
||
|
||
---
|
||
|
||
## VIII. Hermes's exception: the sinking semaphore
|
||
|
||
### VIII.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
**Hermes cannot emit `SOS`**, because Hermes is the message arbiter and it cannot route a
|
||
message announcing its own routing failure. Instead of emitting `SOS`, Hermes **raises a
|
||
semaphore signaling that it is sinking, and holds it until it goes down.** This gives the rest
|
||
of the fleet a window to shut down cleanly rather than going dark with no warning.
|
||
|
||
### VIII.2 — Why this is a corollary, not a special case
|
||
|
||
This is the direct consequence of §III.2. The instant Hermes stops being a client of its own
|
||
routing layer, any failure-announcement it might send has no transport — the transport is the
|
||
thing that failed. A semaphore is the right shape precisely because it is *not* a message: it
|
||
does not require the failed subsystem to work, and a held-until-death signal degrades
|
||
correctly (release = gone) rather than requiring a successful final transmission.
|
||
|
||
Worth stating plainly because it reframes the whole design: **the fleet's failure signalling is
|
||
two mechanisms, not one, and which one a VM uses is determined by whether it is above or below
|
||
the routing layer.** Everything on the Stadium floor sends `SOS`. The arbiter beneath it raises
|
||
a semaphore. That is a clean rule with no exceptions list to maintain.
|
||
|
||
### VIII.3 — Open
|
||
|
||
> **PARTLY SETTLED 2026-09-18 by §XVI.** The second bullet (what a clean-shutdown routine does)
|
||
> is answered: forced `blk_flush(0)`, then `BYE`; Hera's is suicide via a permanent
|
||
> `arch_halt()` loop. The third (is the window bounded) answers itself — the window ends when
|
||
> Hera halts, a bound by construction rather than by timer (§XVI.4). **The first bullet, where
|
||
> the semaphore mechanically lives, remains open.** Left in place, not rewritten.
|
||
|
||
- **Where does the semaphore live, mechanically?** It must be readable by VMs whose messaging
|
||
is dying. Kernel-resident, below the routing layer, is the only coherent answer, but the
|
||
concrete form is unspecified.
|
||
- **What does a VM's "clean shutdown routine" actually do?** §IX makes this fleet-wide
|
||
behavior, so it needs a single definition — and it must satisfy §VII.4's note about the
|
||
conservation invariant.
|
||
- **Is the window bounded?** "Holds it until it goes down" gives no deadline. If Hermes sinks
|
||
slowly, do VMs shut down on the signal alone or wait for release?
|
||
|
||
---
|
||
|
||
## IX. Birther failure: no provisional handoff
|
||
|
||
### IX.1 — Decided (Captain Bob, 2026-09-18)
|
||
|
||
If a VM responsible for birthing/lifecycle decisions (total Hera failure is the type case)
|
||
exhausts its own ladder — warm restart, then from-scratch `BIRTH` — and still cannot recover,
|
||
there is **no provisional handoff of its authority to another VM. No VM assumes partial or
|
||
stolen authority on another's behalf.** Instead, the rest of the fleet runs its own shutdown
|
||
routines — the same clean-shutdown behavior §VIII's sinking semaphore triggers, applied
|
||
fleet-wide.
|
||
|
||
### IX.2 — Why this is consistent rather than merely austere
|
||
|
||
It is the same invariant as §VI, read from the other side. §VI says a VM can never birth
|
||
something with more authority than it holds. §IX says a VM can never *acquire* authority it
|
||
was not born with, even when the holder is gone and the authority is going begging. Together:
|
||
**authority only ever flows down the birth graph, never sideways and never up.** No VM ends up
|
||
holding authority it wasn't born with, and no VM limps in a half-failed state — every path
|
||
terminates in either full recovery or fast, clean termination.
|
||
|
||
That is a strong, checkable property, and it is worth writing down as the thing to defend when
|
||
some future failure mode makes a provisional handoff look temporarily attractive.
|
||
|
||
### IX.3 — Open
|
||
|
||
> **PREMISE REJECTED 2026-09-18 by §XV.2.** The first bullet asks the wrong question. Nobody
|
||
> declares a VM dead — it dies a compudynamic death. The "circular by construction" difficulty
|
||
> was an artifact of assuming death is a judgment someone renders rather than a physical
|
||
> outcome of the physics. Left in place, not rewritten.
|
||
|
||
- **What has standing to declare a birther dead?** Circular by construction: the fleet must
|
||
conclude Hera is gone without Hera participating. Ties directly to §VII.3's undesigned
|
||
detection story.
|
||
- **Does fleet shutdown mean the kernel halts, or that the floor empties and the kernel
|
||
survives?** Materially different outcomes, not specified.
|
||
|
||
---
|
||
|
||
## X. Sequencing — dependencies between the open questions
|
||
|
||
These do not decompose into independent work items; several answers foreclose others. The
|
||
dependency order that fell out of writing this up:
|
||
|
||
1. **§III.4 (arenas: routing-only vs. full centralization) is the root.** It determines
|
||
whether §IV.2's routing-table question exists at all, and materially changes §VII.4's warm
|
||
restart.
|
||
2. **§III.3 (the by-name `VM-EXEC` dependency)** — needs a repo-wide `S" Hermes" VM-EXEC` grep
|
||
first, which has not been done.
|
||
3. **§IV.2 (slot numbering)** — only if §III.4 leaves a FORTH routing table standing.
|
||
4. **§VI.3 (what "ACL/DNA" refers to)** — independent of the above; gates all of §VI.
|
||
5. **§VII.3 (reconciling the ladder with the wellness-check idea)** — gates §VII.2's consumer
|
||
question and §IX.3's declare-dead question, which are the same question twice.
|
||
6. **§V.3 (agent-VM binding)** — needs §VI settled, since an agent VM is birthed before it is
|
||
bound.
|
||
|
||
---
|
||
|
||
## XI. Punch list — design only, no code authorized
|
||
|
||
Nothing here is started. Nothing here authorizes an edit. Numbered for discussion order, not
|
||
execution order.
|
||
|
||
1. ✅ **CLOSED 2026-09-18 (§XIII.1).** Repo-wide by-name Hermes inventory: 14 FORTH sites
|
||
across 5 files, 3 C-side sites, 1 DoE CSV schema site. Only 3 are live. §I.2 corrected.
|
||
2. ✅ **CLOSED 2026-09-18 (§XIII.4).** All three citations verified against source; §V.3.4 and
|
||
§VII.4 may now be relied on.
|
||
3. ⬜ Settle §III.4: routing-only vs. full arena centralization. **Root dependency — do first.**
|
||
4. ⬜ Settle §III.3 given 3.
|
||
5. ⬜ Settle §IV.2 if and only if 3 leaves a FORTH routing table standing.
|
||
6. ⬜ Settle §VI.3: precise referent for "ACL/DNA", against the four-field `DictEntry`
|
||
constraint.
|
||
7. ⬜ Settle §VI.4: what "standing" means, or rule it decorative.
|
||
8. ⬜ Reconcile §VII.3: the ladder vs. the wellness-check detection idea.
|
||
9. ⬜ Assign `SOS` a message-type number deliberately (§VII.2), with a named consumer.
|
||
10. ⬜ Specify the sinking semaphore's mechanism and the clean-shutdown routine (§VIII.3).
|
||
11. ⬜ Answer §IX.3: what declares a birther dead, and what fleet shutdown means concretely.
|
||
12. ⬜ **NEW 2026-09-18 (§XIII.5).** Rule on whether the Hestia Tripod leg is a *new*
|
||
singleton, distinct from today's plural per-attach console proxies. **Gates §IV.1 and
|
||
§IV.2** — sits above the slot-numbering question, not beside it.
|
||
13. ⬜ **NEW 2026-09-18 (§XIII.2), not part of this reshuffle.** Authorize a
|
||
`capsules/MANIFEST.md` correction pass for two false claims: block 4055's "immutable ABI"
|
||
(`FABRIC-2.md` declared it stale and it was never corrected) and block 2049's stated
|
||
contents. Reported, not fixed, per Captain Bob's Law.
|
||
|
||
**Acceptance for anything that eventually comes out of this list**, per `.claude/CLAUDE.md`'s
|
||
non-negotiable criteria: three-arch QEMU boot (`amd64`, `aarch64`, `riscv64`, one at a time, in
|
||
the foreground, `clean` before `qemu`), all reaching `zuse)ok>` with zero `UNKNOWN WORD`
|
||
faults, logs present under `logs/`, and `dict_hash` identical across all three architectures.
|
||
There is no other test.
|
||
|
||
---
|
||
|
||
## XII. Explicitly not decided anywhere in this document
|
||
|
||
Collected so nothing here is mistaken for settled. **Updated 2026-09-18 after §XV's rulings.**
|
||
Most of this list is now closed — see §XIV.2 and §XV.6 for what resolved, dissolved, or had its
|
||
premise rejected.
|
||
|
||
**Still genuinely open — updated again 2026-09-18 after §XVII closed item 12. Nothing
|
||
structural remains; what follows are small local decisions, one placement question, and one
|
||
build-time check.**
|
||
- **Item 9 (§VII.2/§XVI.5)** — half-answered. The consumer action is defined for the two
|
||
fleet-fatal cases; open is whether an *ordinary peer's* `SOS` is actionable or merely
|
||
advisory, plus the trivial number allocation.
|
||
- **§VIII.3 first bullet** — where the sinking semaphore mechanically lives. The rest of
|
||
§VIII.3 is settled by §XVI.
|
||
- **Item 16 (§XV.4)** — an implementation check rather than a decision: every message-holding
|
||
teardown path must reach `STADIUM-EVICT`, verifiable via `fleet_conserved`.
|
||
- **Item 17 (§XVI.2)** — does Hera's suicide replace `BYE`'s current cold-restart, or become a
|
||
separate word? Small, but it changes a live registered word either way.
|
||
- **Item 18 (§XVI.7)** — if Hera is already dead, nobody performs the halt. Proposed shape (an
|
||
empty floor as a kernel-observable condition) is **analysis, not a ruling.**
|
||
|
||
§XIII.5's proposed Hestia resolution shape remains **analysis, not a ruling.** §XIV.4's and
|
||
§XIV.5's proposals were both superseded by §XV.4 and §XV.3 respectively.
|
||
|
||
What **is** decided, all by Captain Bob on 2026-09-18 and recorded in §III.1, §IV.1, §V.1,
|
||
§VI.1, §VII.1, §VII.2, §VIII.1 and §IX.1: Hermes goes into the kernel and becomes the arbiter
|
||
rather than a client; the Tripod becomes Hera/Artemis/Hestia; Hestia becomes the bind point;
|
||
`BIRTH` is general with authority bounded by inheritance; the fleet shares one
|
||
gentle→from-scratch→brutal ladder; `SOS` is a standard message type with Hermes excepted via a
|
||
sinking semaphore; and a failed birther's authority is never provisionally handed off.
|
||
|
||
---
|
||
|
||
## XIII. Punch-list items 1 and 2 worked — CLOSED 2026-09-18, with three corrections to this document's own §I
|
||
|
||
Worked per the series' standing discipline: items 1 and 2 were the two pure-investigation
|
||
entries on §XI, carrying no design commitment, so they were executable without a ruling. All
|
||
findings below traced directly against the working tree at `e56974e` on 2026-09-18. **No code
|
||
written, no design question answered, nothing in the tree modified.**
|
||
|
||
### XIII.1 — Item 1 CLOSED: the by-name Hermes inventory. §I.2 undercounted by an order of magnitude.
|
||
|
||
**Correction to §I.2, which is wrong as written.** It claimed the by-name dependency was
|
||
Artemis's "two live call sites" and framed Artemis as *the* dependent. The real inventory is
|
||
**13 by-name FORTH references across 5 files, plus 3 independent C-side sites.** §I.2's two
|
||
sites are real and still the sharpest edge, but they are not the extent of it, and the
|
||
executive framing ("relocated and rewired") has to cover all of it. Full inventory:
|
||
|
||
| # | Site | Call | Live? |
|
||
|---|---|---|---|
|
||
| 1 | `common/msg.4th:7` | `S" MSG-ACK-LAST" S" Hermes" VM-EXEC` | **dead** — §XIII.2 |
|
||
| 2 | `common/msg.4th:10` | `S" MSG-NACK-LAST" S" Hermes" VM-EXEC` | **dead** — §XIII.2 |
|
||
| 3 | `artemis/init.4th:138` | `S" 2 ENQUEUE-READY" S" Hermes" VM-EXEC` | live |
|
||
| 4 | `artemis/init.4th:501` | `S" 2 COMMON-CH @ CH-ADD-MBR" S" Hermes" VM-EXEC` | live |
|
||
| 5 | `process.4th:12` | `S" 1 EVENT-EMIT" S" Hermes" VM-EXEC` (SPAWN) | **dead** — §XIII.2 |
|
||
| 6 | `process.4th:15` | `S" 2 EVENT-EMIT" S" Hermes" VM-EXEC` (PAUSE) | **dead** |
|
||
| 7 | `process.4th:21` | `S" 3 EVENT-EMIT" S" Hermes" VM-EXEC` (RESUME) | **dead** |
|
||
| 8 | `process.4th:26` | `S" 4 EVENT-EMIT" S" Hermes" VM-EXEC` (KILL-VM) | **dead** |
|
||
| 9 | `doe-campaign.4th:6` | `S" Hermes" BIRTH` | not auto-run |
|
||
| 10 | `doe-campaign.4th:7` | `S" LOAD-DOE" S" Hermes" VM-EXEC` | not auto-run |
|
||
| 11 | `doe-campaign.4th:17` | `S" DOE-WORK" S" Hermes" VM-EXEC` | not auto-run |
|
||
| 12 | `doe-campaign.4th:28` | `S" DOE-WORK" S" Hermes" VM-EXEC` | not auto-run |
|
||
| 13 | `doe-campaign.4th:54` | `S" 1959 1 EXEC-DOE" S" Hermes" VM-EXEC` | not auto-run |
|
||
| 14 | `messaging.4th:77` | `S" Hermes" 1 VM-NAME-REG` | live (§I.3) |
|
||
|
||
**The good news is real: only 3 of the 14 are live production paths** (#3, #4, #14). Seven are
|
||
dead code (§XIII.2), four are in a campaign orchestrator `docs/working/architecture/
|
||
DOE-LIBRARY-HOWTO-20260819.md` itself records as "Not auto-run anywhere." **This materially
|
||
lowers the estimated cost of §III.3** — but it must be re-confirmed rather than trusted, since
|
||
"not auto-run" is a claim about today's boot path, not a guarantee nothing invokes it.
|
||
|
||
### XIII.2 — Seven of those sites are dead code, and `MANIFEST.md` carries a claim FABRIC-2 already declared stale
|
||
|
||
**`common/msg.4th` is loaded by nothing.** Traced: `S" common:msg.4th" EXEC` appears exactly
|
||
once in the tree — inside `common/msg.4th`'s own header comment, as usage documentation. No
|
||
capsule EXECs it. `capsules/init.4th` (block 2049) loads `ACL.4th`, `block-acl.4th`,
|
||
`zuse-eligibility.4th`, `lib.4th`, `fabric.4th`, `font.4th`, `common:messaging.4th` — and
|
||
nothing else.
|
||
|
||
This is **already known and already written down.** `FABRIC-2.md:2770-2773` states it
|
||
outright: the `HERMES-ACK`/`HERMES-NACK` wrappers "are now obsolete (every VM has its own
|
||
local `MSG-ACK-LAST`/`MSG-NACK-LAST` — no `VM-EXEC` indirection needed) but the file itself
|
||
was left in place, unloaded, rather than deleted unprompted; `capsules/MANIFEST.md`'s
|
||
'immutable ABI' claim for block 4055 is now stale." `messaging.4th:411` carries the same note
|
||
from the other side: "common:msg.4th's HERMES-ACK/NACK indirection is retired."
|
||
|
||
**`capsules/MANIFEST.md` was never corrected.** Line 317 still reads: "Immutable: this is the
|
||
cross-VM ACK/NACK ABI. Every messaging VM (Hera, Hermes, Artemis) loads this at birth.
|
||
Changing the block or the word names breaks the Hermes delivery protocol." That is false on
|
||
every clause. A second MANIFEST claim also fails against the source: line 52 describes block
|
||
2049 as loading "compudynamics, VM-INIT, lib, common:msg, fleet-k, process; BIRTHs Artemis +
|
||
Hermes" — `init.4th` block 2049 loads none of `common:msg`/`process` and contains no `BIRTH`
|
||
at all (Hermes and Artemis are birthed from C — §XIII.3).
|
||
|
||
**`process.4th` is likewise EXEC'd nowhere**, making sites #5–#8 dead with it.
|
||
|
||
**Reported, not fixed**, per Captain Bob's Law ("if you identify a bug, report it; do not fix
|
||
it unless the user says to"). Flagged here because a reshuffle that reads `MANIFEST.md` as
|
||
current will conclude the ACK/NACK path is a live immutable Hermes ABI and scope around a
|
||
constraint that stopped existing in `FABRIC-2.md`'s era. **Recommend a MANIFEST.md correction
|
||
pass as its own authorized item; it is not part of this reshuffle.**
|
||
|
||
### XIII.3 — The Tripod is hardcoded as a name-triple in C, in three independent places
|
||
|
||
Not previously recorded in this document. Each is an edit site the moment the Tripod's
|
||
membership changes (§IV.1):
|
||
|
||
1. **`capsule_birth.c:793-796`** — `is_fleet_foundation` is literally
|
||
`vm_name_prefix_eq_nocase(capsule_name, "Hera") || ... "Hermes" || ... "Artemis"`. It gates
|
||
`StadiumPatronHeader` setup and the `session_register()`/`session_set_pinned()` pinning
|
||
calls. **This is the Tripod, encoded as a string test.** Swapping Hermes for Hestia is a
|
||
one-line change here — and that single line is what makes a VM pinned.
|
||
2. **`kernel_main.c:864-874`** — `vm_interpret(mama, "S\" Hermes\" BIRTH")` plus a
|
||
`capsule_vm_find_by_name_nocase("Hermes", ...)` liveness check and console banner. The
|
||
comment cites `FABRIC-2.md` D.7 (birth-by-message-only, 2026-08-28): the Tripod legs "must
|
||
be alive session-less so a later thumbdrive-attach flow has a running Hermes/Artemis to
|
||
message." **Note the stated rationale for Hermes being born early is precisely that other
|
||
flows need it available — which a kernel-resident arbiter satisfies trivially and
|
||
permanently.** §III is consistent with D.7's intent, not in tension with it.
|
||
3. **`kernel_main.c:1007-1009`** — `sk_vm_switch_signal_register(hermes_entry.vm_id)`, the
|
||
preemptive context-switch registration from `FABRIC-3.md` §XXVIII.
|
||
|
||
**A fourth site is not code but schema, and is the expensive one: `doe_log.c`.** The per-tick
|
||
DoE CSV hardcodes the Tripod across six columns — 16/17/18 (`hera_heat_q48`,
|
||
`hermes_heat_q48`, `artemis_heat_q48`, populated by `doe_log_heat_by_name("Hera"/"Hermes"/
|
||
"Artemis")` at lines 206-208) and 23/24/25 (`switch_*_readiness`), with column 22 documented
|
||
as "0=Hera, 1=Hermes, 2=Artemis by current registration order." **Changing Tripod membership
|
||
changes the DoE CSV schema**, which bears directly on comparability with every campaign
|
||
already run (§XXXIV/§XXXV's segmented per-ISA design in `FABRIC-3.md` is mid-flight). Flagged
|
||
as a real cost, not a blocker, and **not** something to resolve by quietly renaming a column.
|
||
|
||
### XIII.4 — Item 2 CLOSED: all three flagged citations verified against source
|
||
|
||
§XI item 2 flagged three citations this document took from headings and `.claude/CLAUDE.md`
|
||
rather than from the source. All three check out; §V.3.4 and §VII.4 may now be relied on.
|
||
|
||
- **`FABRIC-2.md` §H.1** — real, at line 3699, "Session = Stadium patron, admission restated."
|
||
The pinning claim is at line 3713: pinned sessions are exempt from "the normal departure
|
||
path (heat decay / `COOL`): they never leave, permanently." Confirmed as §V.3.4 used it.
|
||
- **`FABRIC-2.md` §H.12** — real, at line 4057, "Implementation punch list (2026-09-03)."
|
||
Independently corroborated from the code side: `capsule_birth.c:785-788` cites "§H.12 step 4"
|
||
by name for the `session_register()`/`session_set_pinned()` soft-fail convention.
|
||
- **`FABRIC-3.md` §XVIII** — confirmed. `K` is `vm_physics_fleet_heat_sum()` over **all** live
|
||
VMs, which the reservoir-transfer accounting holds exactly at `Q48_ONE`, surfaced as the
|
||
`fleet_k_q48`/`fleet_conserved` CSV columns. §VII.4's warning stands as written: a brutal
|
||
death must still return what it held, or it breaks a continuously-verified invariant.
|
||
|
||
### XIII.5 — New finding, and the most consequential of this pass: Hestia today is plural, ephemeral, and capsule-less
|
||
|
||
**This was not known to §IV or §V when they were written, and it changes what §IV.1 is asking
|
||
for.** Traced in `capsule_console.c`:
|
||
|
||
- **Hestia has no capsule.** `capsules/` contains `hermes/` and `artemis/` directories but
|
||
**no `console/`**. A console VM's entire personality is a 3-line C string literal,
|
||
`CONSOLE_IDENTITY_SRC` (`capsule_console.c:28-31`): `Block 4997`, `S" common:messaging.4th"
|
||
EXEC`, `MSG-CD-INIT`. That is all of it.
|
||
- **Hestia is deliberately *not* on the routing table.** The source comment is explicit: "No
|
||
`COMMON-CH` subscription: a console's own traffic is direct 1:1 with its paired user VM
|
||
(`CONSOLE-CMD-EVENT`), not broadcast, so there's no need to resolve an index in Hermes's own
|
||
routing table for it."
|
||
- **Hestia is plural and per-attach.** `capsule_console_birth(const char *console_name, ...)`
|
||
is called from three sites (`capsule_wirebind.c:245`, `mama_forth_words.c:1591` and `:2015`)
|
||
and mints a fresh heap-built single-entry capsule directory each time. There are as many
|
||
console VMs as there are attachments.
|
||
|
||
**Consequence.** Hera, Hermes and Artemis are singular, pinned, born-at-boot, capsule-backed,
|
||
routing-table-indexed. Hestia today is **none of those five things.** So §IV.1's "Hestia
|
||
takes the vacated third slot" is **not** a relocation of an existing pinned VM — as stated it
|
||
would create a Hestia that does not currently exist. That is worth naming plainly, because it
|
||
is the one place this document's "reorganization, not invention" scope discipline is genuinely
|
||
strained.
|
||
|
||
> **CORRECTED 2026-09-18 by §XVII — the paragraph above compares the wrong object.** The
|
||
> singular pinned Hestia *does* already exist: it is the HAL drawing fabric
|
||
> (`hal/console.c`, `framebuffer.c`, `vt100.c`, `font_8x16.c`), already singular, permanent
|
||
> and kernel-resident — it simply has no VM face and no owner. The per-attach proxies this
|
||
> section measured against are what *binding produces*, not what Hestia *is*. The scope
|
||
> discipline is therefore **not** strained: the leg is an existing singleton given an owner,
|
||
> and the only genuinely new artifact is a capsule personality. The resolution shape proposed
|
||
> below was right; this justification for it was wrong. **RATIFIED — see §XVII.2.** Left in
|
||
> place, not rewritten.
|
||
|
||
**The shape that resolves it without inventing anything** — offered as analysis, **not
|
||
ratified, Captain Bob's call**: distinguish **Hestia** (singular, pinned, capsule-backed, the
|
||
Tripod leg — owns the drawing fabric and is the bind point, per §V.1) from **console proxies**
|
||
(plural, ephemeral, per-attach — exactly what `capsule_console_birth()` mints today,
|
||
unchanged). The Tripod leg is new; the proxies are untouched. This reading makes §V.1's "bind
|
||
point" precise: the leg is what you bind *to*, the proxy is what binding *produces*.
|
||
|
||
### XIII.6 — §V and §VI are load-bearing for each other, which neither section noticed
|
||
|
||
If Hestia is the bind point (§V.1), it is Hestia that must mint console proxies — and
|
||
minting a VM is `BIRTH`. Today all three `capsule_console_birth()` call sites run in Hera's or
|
||
the caller's context. **So "Hestia is the bind point" cannot be implemented while `BIRTH`
|
||
remains Hera-exclusive; it requires §VI.1's generalization.** They are one change, not two.
|
||
|
||
Mechanically this already works, which strengthens both: two of the three call sites pass
|
||
`vm->stadium_vm_id` — *whichever VM invoked* — rather than a hardcoded Hera
|
||
(`capsule_wirebind.c:245` passes `mama_vm->stadium_vm_id` because that path genuinely is
|
||
Hera's). That matches §I.5's finding that `capsule_birth_baby()` treats `stadium_vm_id`
|
||
generically as "whoever is birthing this VM." **Parentage is already generic; only
|
||
registration is not.**
|
||
|
||
This also supplies the first concrete answer to §VI.4's open "what is standing": Hestia needs
|
||
`BIRTH` to do its declared job, so it has standing by role. That is evidence for reading (a)
|
||
(standing = having `BIRTH` registered), not a ruling.
|
||
|
||
### XIII.7 — Effect on §X's sequencing
|
||
|
||
Nothing found here dislodges §III.4 as the root dependency. Two adjustments:
|
||
|
||
- **§III.3 is cheaper than §I.2 implied** (3 live sites, not a broad web) and can be scoped as
|
||
soon as §III.4 lands.
|
||
- **§IV.1 needs a prior ruling that §IV.2 does not cover**: is the Tripod's Hestia leg a *new*
|
||
singleton distinct from today's proxies (§XIII.5)? That question sits *above* the slot
|
||
numbering, not beside it. **Added to the punch list as item 12.**
|
||
|
||
### XIII.8 — Punch-list status after this pass
|
||
|
||
- ✅ **Item 1 CLOSED** — inventory complete (§XIII.1), 14 FORTH sites + 3 C sites + 1 CSV
|
||
schema site; §I.2 corrected.
|
||
- ✅ **Item 2 CLOSED** — all three citations verified against source (§XIII.4).
|
||
- ⬜ **Item 12, NEW** — rule on §XIII.5: is the Hestia Tripod leg a new singleton, distinct
|
||
from today's per-attach proxies? **Gates §IV.1 and §IV.2.**
|
||
- ⬜ **Item 13, NEW, not part of this reshuffle** — authorize a `capsules/MANIFEST.md`
|
||
correction pass for the two false claims in §XIII.2 (block 4055 "immutable ABI"; block 2049
|
||
contents). Reported, not fixed.
|
||
|
||
Items 3–11 unchanged and still open.
|
||
|
||
---
|
||
|
||
## XIV. Two rulings that collapse the root dependency (Captain Bob, 2026-09-18)
|
||
|
||
### XIV.1 — RULING: the existing FORTH messaging layer is legacy. Kernel Hermes is greenfield.
|
||
|
||
**Captain Bob, 2026-09-18, verbatim:** "as far as Hermes the VM and Hermes the kernel
|
||
component, forget all the forth existing and call it legacy for now. We'll do a code cleanup
|
||
for all the dead FORTH anyway."
|
||
|
||
So kernel-Hermes is **not** a migration of `capsules/common/messaging.4th`. It is a new C
|
||
implementation; the FORTH messaging layer becomes legacy on arrival and is retired by a
|
||
separate dead-FORTH cleanup pass. This reverses the framing §III.3 and §III.4 were built on —
|
||
both assumed the existing FORTH had to be carried across.
|
||
|
||
### XIV.2 — What this collapses
|
||
|
||
Four of this document's open questions dissolve rather than get answered:
|
||
|
||
- **§III.4 (the root dependency) — RESOLVED by fiat, in the "full centralization" direction,
|
||
but without the migration cost that made it frightening.** The kernel owns message and
|
||
channel state; `messaging.4th`'s per-VM `CREATE`/`ALLOT` arenas are legacy, not something to
|
||
centralize. §III.4 feared a painful port of live FORTH state; there is no port.
|
||
- **§III.3 (the by-name `VM-EXEC` dependency) — dissolved.** The three-option framing
|
||
(kernel primitives / vestigial name / birth-time registration) was about preserving callers.
|
||
With the FORTH legacy, §XIII.1's 14-site inventory stops being a migration constraint and
|
||
becomes an input to the cleanup pass. **§XIII.1's inventory is still the right list — its
|
||
purpose changed, not its content.**
|
||
- **§IV.2 (routing-table slot numbering) — dissolved, exactly as §IV.2's own option 3
|
||
predicted:** "the routing table stops being a FORTH array at all... in which case this
|
||
question dissolves into §III.4's arena question." It did. `VM-NAMES-INIT`'s 0/1/2 pinning and
|
||
the "never renumbered" commitment are legacy artifacts, not constraints on the new design.
|
||
- **§XI item 13 (the `MANIFEST.md` corrections) — absorbed.** Bob's "we'll do a code cleanup
|
||
for all the dead FORTH anyway" covers §XIII.2's findings. Still worth doing deliberately;
|
||
no longer a separate ask.
|
||
|
||
**§XIII.1, §XIII.2 and §XIII.3 keep their value** — the C-side sites (§XIII.3) are *not*
|
||
legacy and remain real edit sites, and the dead-FORTH inventory now feeds the cleanup.
|
||
|
||
### XIV.3 — RULING: Artemis is the persistence path. And it needs no layering inversion.
|
||
|
||
**Captain Bob, 2026-09-18:** "For persistence though, use Artemis as much as possible. We're
|
||
good with that part for sure." Ratified.
|
||
|
||
**A layering question this raises, traced 2026-09-18 and answered cleanly.** Artemis is a VM on
|
||
the Stadium floor; kernel-Hermes sits *below* the floor. "Persist via Artemis" reads at first
|
||
like an inversion — the kernel arbiter calling up into a floor VM. It is not, because storage
|
||
is already two layers, not one:
|
||
|
||
- **The block subsystem is kernel/shared C, below the floor:** `src/block_subsystem.c`,
|
||
`src/blkio_*.c`, `src/starkernel/virtio/virtio_blk.c`. `capsule_loader.c:98-100` calls
|
||
`blk_subsys_init()` and `blk_subsys_add_raw_device()` directly, with no Artemis involved at
|
||
all.
|
||
- **Artemis is the storage *policy arbiter* on the floor:** it owns attach/registration
|
||
(`blk_subsys_attach_device()` via the `BLK-ATTACH` primitive — `repl.c:525-531` states it
|
||
outright, "Artemis's own domain now, not Hera's") and the on-disk Artemis format.
|
||
|
||
So the ruling is satisfiable without inversion, by keeping the two straight: **floor-level and
|
||
fleet persistence goes through Artemis, its domain and its format; anything kernel-Hermes
|
||
itself needs uses the same block subsystem Artemis is built on — never a new one, and never by
|
||
messaging Artemis.**
|
||
|
||
Worth recording that the kernel *already* calls up into Artemis by name today
|
||
(`repl.c:539-541`, `S" %llu HERA-BLK-ATTACH-REQ" S" Artemis" VM-EXEC`), with a comment
|
||
explaining it is a direct `VM-EXEC` rather than a real message because Hera can't use her own
|
||
`MSG-SEND` there. That precedent exists; this section is about not *depending* on it.
|
||
|
||
### XIV.4 — The one real hazard in the persistence ruling, and the shape that avoids it
|
||
|
||
**Kernel-Hermes must not depend on Artemis for the persistence it needs during its own
|
||
failure.** This is the same structural trap as §VIII: if Hermes must write something at death
|
||
and reaching Artemis requires routing, the dependency closes a circle on exactly the mechanism
|
||
that is broken. §VIII solved the *signalling* case with a semaphore; the persistence case
|
||
needs the same discipline rather than a second special case.
|
||
|
||
**Recommended shape — analysis, not a ruling, Captain Bob's call: kernel-Hermes holds only
|
||
reconstructible state.** If the arbiter's routing state can be rebuilt from the live VM
|
||
registry (which `capsule_birth.c` already maintains as the authority on who exists), then:
|
||
|
||
- Hermes has nothing that *must* be persisted, so the Artemis dependency never arises.
|
||
- §VII.4's "what does warm restart mean for Hermes" becomes trivial — rebuild from the
|
||
registry, no saved state to reconcile.
|
||
- Losing in-flight messages when the arbiter dies is consistent with §VII.1 step 3's "no
|
||
lingering, no partial states," and with §VIII's clean-shutdown window.
|
||
|
||
This costs message durability across an arbiter death. **Flagged as the real trade**, and the
|
||
one to rule on: if in-flight messages must survive Hermes dying, Hermes needs durable state,
|
||
and that durable state cannot route through Artemis at death-time.
|
||
|
||
### XIV.5 — Still open, and now more urgent, not less: the scheduler firewall
|
||
|
||
Raised 2026-09-18 and **not yet ruled on**. Recorded here because §XIV.1 changes its timing.
|
||
|
||
The fleet already has a scheduler: §XXVIII built timer-driven preemption, and `MSG-SEND`
|
||
(`messaging.4th` block 5021) already calls `SWITCH-MARK-WORK` → `sk_vm_switch_signal_mark_work()`,
|
||
setting `has_work` on the target's switch slot; `sk_vm_switch_signal_tick()` switches when
|
||
`readiness >= SK_SWITCH_READINESS_THRESHOLD` **and** `has_work`. **Message arrival is already
|
||
a scheduling input.** This directly contradicts `VM-PHYSICS-DYNAMIC-FLEET-DESIGN-20260705.md`'s
|
||
"Explicitly not wanted: a VM scheduler. Nothing gets built that decides whose turn it is to
|
||
execute" — a live tension in the project that predates this document and is not this
|
||
document's to resolve, but is this document's to not make worse.
|
||
|
||
**Why §XIV.1 sharpens it.** Today that coupling runs FORTH `MSG-SEND` → C primitive → switch
|
||
slot. With the FORTH legacy, **kernel-Hermes becomes the caller of
|
||
`sk_vm_switch_signal_mark_work()` directly** — eligibility marking moves inside the arbiter.
|
||
That is the consolidation to guard against, and it happens by default unless the boundary is
|
||
stated up front. Greenfield is the right time to state it; retrofitting it later is how this
|
||
becomes a conventional scheduler by accident.
|
||
|
||
**Proposed invariant, for ruling:** *kernel-Hermes carries, resolves and ACL-checks. It
|
||
publishes facts — "this VM has mail" — and never reads readiness, never orders traffic by
|
||
priority, and never decides turn order. `switch.c` remains the sole owner of "who runs next."*
|
||
|
||
The argument for it is empirical and from this project's own history: §XXVIII.2 is a record of
|
||
switch-storms caused by **two sources of truth disagreeing** about who was running
|
||
(`vm_log_attributed_vm()` vs. the real trampoline state) — QEMU pinned near 100%, serial log
|
||
frozen solid. This codebase punishes duplicated authority with hangs. Two deciders would be
|
||
worse than one scheduler.
|
||
|
||
### XIV.6 — Punch list after these rulings
|
||
|
||
- ✅ **Item 3 (§III.4, the root) — RESOLVED** by §XIV.1. Kernel owns messaging; FORTH is legacy.
|
||
- ✅ **Item 4 (§III.3) — DISSOLVED** by §XIV.1; §XIII.1's inventory becomes cleanup input.
|
||
- ✅ **Item 5 (§IV.2) — DISSOLVED** by §XIV.1, as §IV.2 option 3 predicted.
|
||
- ✅ **Item 13 — ABSORBED** into the dead-FORTH cleanup pass.
|
||
- ⬜ **Item 14, NEW** — rule on §XIV.5's scheduler firewall invariant. **Raised, not ruled.**
|
||
- ⬜ **Item 15, NEW** — rule on §XIV.4: does message durability survive an arbiter death? If
|
||
yes, Hermes needs durable state that cannot route through Artemis at death-time.
|
||
- ⬜ Items 6, 7, 8, 9, 10, 11, 12 unchanged and still open.
|
||
|
||
**Note the shape of what remains.** With the root dependency resolved, the surviving open
|
||
items are no longer about *mechanism* — they are about *authority*: who may birth (6, 7), who
|
||
decides a VM is dead (8, 11), who owns turn order (14), and what survives a death (15). That
|
||
is a better class of question to be left with, and §IX's "authority only ever flows down the
|
||
birth graph" is the principle most of them should be tested against.
|
||
|
||
---
|
||
|
||
## XV. The authority questions, answered (Captain Bob, 2026-09-18)
|
||
|
||
§XIV.6 observed that the surviving open items were no longer about mechanism but about
|
||
authority — who may birth, who declares a VM dead, who owns turn order, what survives a death.
|
||
All four are answered here, and three of the four are answered by **rejecting the question's
|
||
premise** rather than by naming an owner. That pattern is the finding.
|
||
|
||
### XV.1 — RULING: any VM may birth a near-clone of itself, carrying its own ACL DNA
|
||
|
||
**Captain Bob, verbatim:** "Any VM can birth another VM that is almost a clone of itself with
|
||
its own ACL DNA whatever ya wanna call it."
|
||
|
||
This closes **§VI.3** and **§VI.4** together:
|
||
|
||
- **§VI.3 ("ACL/DNA" needs a precise referent) — ANSWERED: inheritance by copy, from the
|
||
parent.** The child is *almost a clone* of its birther: it starts from the parent's own
|
||
state and carries **its own** DNA — a copy it owns and may diverge, not a shared reference
|
||
to the parent's. This is the reading §VI.3 hoped for: it uses the existing word-level
|
||
`ACL-INHERIT` semantics (pin cleared, mode copied) rather than inventing a VM-level
|
||
construct, so it stays inside the "reorganization, not invention" scope, and it does not
|
||
need a fifth `acl_*` field on `DictEntry` (the constraint §VI.3 flagged).
|
||
- **§VI.4 ("standing" is undefined) — ANSWERED: standing is decorative.** "Any VM can birth"
|
||
confirms reading (a) — standing means nothing more than having `BIRTH` registered. Per §I.5
|
||
the C implementation is already VM-agnostic, so this is a registration change, exactly as
|
||
§VI.2 predicted. No Stadium-economy gate, no `ACL.4th` predicate. Consistent with
|
||
`.claude/CLAUDE.md`'s "do not over-engineer — if the user says 'BIRTH is a primitive', that
|
||
is the complete specification."
|
||
|
||
**Why the authority bound still holds without a check.** A near-clone cannot exceed its parent
|
||
because it is *built from* the parent. §VI.1's "enforced by inheritance, not by a separate
|
||
authorization check" is therefore literal, not aspirational — there is no gate to bypass
|
||
because there is no gate.
|
||
|
||
### XV.2 — RULING: nobody declares a VM dead. It dies a compudynamic death.
|
||
|
||
**Captain Bob, verbatim:** "Nobody declares a VM dead, it died a compudynamic death."
|
||
|
||
**This rejects the premise of §IX.3 and of §VII.3's detection gap, and both were wrong to ask
|
||
what they asked.** §IX.3 asked "what has standing to declare a birther dead?" and called it
|
||
"circular by construction." The circularity was an artifact of assuming death is a *judgment*
|
||
someone renders. It is not: death is a physical outcome of the compudynamics — heat exhausts,
|
||
the reservoir empties, the patron leaves the Stadium floor. There is no detector, no quorum, no
|
||
supervisor, and nothing to build.
|
||
|
||
**This retires the largest scheduler-shaped risk in the whole design.** §VII's ladder appeared
|
||
to need a supervisor — some component watching liveness and deciding to escalate — and §XIV.5
|
||
warned that a supervisor with a timer is a scheduler's twin. With death compudynamic, **that
|
||
component does not exist and is not needed.** The ladder is self-applied while a VM is alive;
|
||
once it is dead it is dead, which is exactly §VII.1 step 3's "fast and total, not a slow
|
||
degrade." No actor, no handoff (§IX.1 already forbade one), no partial states.
|
||
|
||
**Consequence for §VII.3.** The "wellness check at the nearest participating wellness center"
|
||
idea recorded in `FABRIC-3.md` §XX does **not** need to be reconciled with this ladder as a
|
||
detection mechanism, because no detection mechanism is required. It remains an independent idea
|
||
on its own merits. §VII.3's framing ("a ladder with no detection story only fires on failures
|
||
loud enough to notice by accident") was built on the same wrong premise and is withdrawn.
|
||
|
||
### XV.3 — RULING: nobody owns turn order. Turn order is compudynamic.
|
||
|
||
**Captain Bob, verbatim:** "Nobody owns the turn order. The turn order is compudynamic."
|
||
|
||
This answers **§XIV.5 (item 14)** with a stronger invariant than the one proposed there. §XIV.5
|
||
suggested a firewall — *"`switch.c` remains the sole owner of who runs next."* That named an
|
||
owner, and naming an owner is what a conventional scheduler is. **The correct invariant names
|
||
none:**
|
||
|
||
> **Turn order is an emergent output of the compudynamics, not a decision any component makes.
|
||
> Kernel-Hermes publishes facts into that system — "this VM has mail" — and computes no
|
||
> ordering. Neither does anything else.**
|
||
|
||
This is consistent with the project's own standing position, independently of this document:
|
||
`FABRIC-3.md` §XIX records the design direction as "fix the gap **without a scheduler**," with
|
||
the reasoning that "a fixed round-robin across identities would just be a different hardcoded
|
||
policy — not in the spirit of" the design. §XV.3 is that same position restated for the
|
||
reshuffle.
|
||
|
||
**One honest observation, offered as a flag rather than an objection.** Traced 2026-09-18:
|
||
`sk_vm_switch_signal_tick()` gates on `readiness >= SK_SWITCH_READINESS_THRESHOLD && has_work`,
|
||
and `SK_SWITCH_READINESS_THRESHOLD` is `50u`, a hardcoded constant
|
||
(`capsule_vm_switch_signal.c:52`). That is a fixed policy sitting in the middle of a
|
||
mechanism this section calls compudynamic — the same category §XIX rejected as "a different
|
||
hardcoded policy."
|
||
|
||
The layering does reconcile: the compudynamic **turn-attractor** (§XIX/§XXI) decides what work
|
||
is assigned, and the CPU-level switch signal is the mechanical follower that moves the
|
||
processor. Turn order in the meaningful sense is the attractor, and it is compudynamic as
|
||
ruled. But the constant `50` is a real seam, and it is the exact place where a hardcoded policy
|
||
could quietly start deciding turns. **Flagged for later, not proposed as work here** — it
|
||
predates this reshuffle and is `FABRIC-3.md` §XXVIII's own territory. Noted so it is not
|
||
discovered later and mistaken for something this document introduced. (`FABRIC-4.md` §1's
|
||
fixed-then-adaptive `rate` graduation is the precedent for how such a constant earns its way
|
||
to adaptive: measure against a fixed baseline first, self-tune only after.)
|
||
|
||
### XV.4 — §XIV.4 reframed: the question was persistence; the answer is conservation
|
||
|
||
§XIV.4 asked whether in-flight messages must survive an arbiter's death, and warned that
|
||
answering "yes" would force Hermes to hold durable state it could not safely write through
|
||
Artemis at death-time. **Captain Bob, on that item: "What survives the death of what? I don't
|
||
understand that last part."** Fair — it was posed as a persistence question, which is the wrong
|
||
frame and the reason it read as opaque.
|
||
|
||
**The right frame, given §XV.2.** A message is not only content; it is *heat*. Traced
|
||
2026-09-18 in `capsules/common/messaging.4th`: `MSG-ALLOC` pulls `Q.SLOT` from the caller's own
|
||
reservoir before admitting a message (rolling back via `STADIUM-RES-PUSH` on refusal, line
|
||
127), and `MSG-FREE-NODE` releases it with `STADIUM-EVICT` (line 135-136). An arbiter dying
|
||
while holding N messages is holding **N × `Q.SLOT` of fleet heat.**
|
||
|
||
So the question is not "must the payloads be saved." It is:
|
||
|
||
> **Does a dying arbiter return the heat its undelivered messages were holding?**
|
||
|
||
- **Payloads may vanish.** Consistent with §VII.1 step 3's "no lingering, no partial states."
|
||
- **The heat may not.** `K` = `vm_physics_fleet_heat_sum()` is held at `Q48_ONE` and
|
||
continuously verified (`FABRIC-3.md` §XVIII, `fleet_k_q48`/`fleet_conserved`). Heat that
|
||
dies with the arbiter is heat that breaks a live invariant.
|
||
|
||
**The answer to "what survives the death of what" is therefore: nothing survives except K.**
|
||
|
||
**This dissolves §XIV.4's hazard rather than resolving it.** There is nothing to persist, so
|
||
there is no death-time write, so there is no circular dependency on Artemis, so the
|
||
stateless-arbiter shape §XIV.4 recommended is simply correct rather than a trade-off. And since
|
||
death is compudynamic (§XV.2), a VM's death *is* already a Stadium eviction event — returning
|
||
heat is not a special case bolted onto death, it is what dying consists of. **§XIV.3's
|
||
"Artemis for persistence" ruling stands untouched and applies to fleet/floor persistence; the
|
||
arbiter simply never needed any.**
|
||
|
||
**The one thing to verify when this is eventually built** (not a design question, an
|
||
implementation check): that every message-holding structure's teardown path actually reaches
|
||
`STADIUM-EVICT`, so a mass teardown returns heat rather than leaking it. `fleet_conserved`
|
||
already makes that directly testable — a leak shows up as K ≠ `Q48_ONE`, not as a silent
|
||
error. Added as punch item 16.
|
||
|
||
### XV.5 — What these four rulings have in common
|
||
|
||
Three of the four answers reject the question rather than answer it. There is no death
|
||
declarer, no turn-order owner, and nothing to persist — and in each case the thing that seemed
|
||
to need an authority turned out to be an outcome of the physics instead. The one question that
|
||
*was* answered directly (§XV.1, who may birth) was answered with "anyone," which also declines
|
||
to create an authority.
|
||
|
||
**That is the actual defence against becoming a conventional scheduler**, and it is stronger
|
||
than the firewall §XIV.5 proposed. A firewall constrains a component that owns something. These
|
||
rulings mean **there is no owner to constrain.** The design's protection is structural, not
|
||
procedural: authority only ever flows down the birth graph (§IX.2), and everything else —
|
||
death, turn order, conservation — is physics rather than policy.
|
||
|
||
### XV.6 — Punch list after these rulings
|
||
|
||
- ✅ **Item 6 (§VI.3, "ACL/DNA" referent) — ANSWERED** (§XV.1): inheritance by copy; existing
|
||
`ACL-INHERIT` semantics suffice; no fifth `DictEntry` field.
|
||
- ✅ **Item 7 (§VI.4, "standing") — ANSWERED** (§XV.1): decorative; reading (a) confirmed.
|
||
- ✅ **Item 8 (§VII.3, ladder vs. detection) — WITHDRAWN** (§XV.2): premise wrong, no detection
|
||
mechanism required.
|
||
- ✅ **Item 11 (§IX.3, who declares a birther dead) — PREMISE REJECTED** (§XV.2): nobody;
|
||
compudynamic death.
|
||
- ✅ **Item 14 (§XIV.5, scheduler firewall) — ANSWERED** (§XV.3), with a stronger invariant
|
||
than the one proposed: no owner, not a named owner.
|
||
- ✅ **Item 15 (§XIV.4, message durability) — DISSOLVED** (§XV.4): reframed from persistence to
|
||
conservation; nothing survives but K.
|
||
- ⬜ **Item 16, NEW** (§XV.4) — implementation check, not a design question: verify every
|
||
message-holding teardown path reaches `STADIUM-EVICT` so mass teardown returns heat.
|
||
Testable directly via `fleet_conserved`.
|
||
- ⬜ **Item 9** (§VII.2 — `SOS` message-type number and its consumer) — still open. Note §XV.2
|
||
narrows it: with no death-declarer, an `SOS` consumer cannot be a supervisor, so the question
|
||
is now specifically what a *peer* does on receipt.
|
||
- ⬜ **Item 10** (§VIII.3 — the sinking semaphore's mechanism, the clean-shutdown routine's
|
||
definition, and whether the window is bounded) — still open, and now the largest remaining
|
||
design item.
|
||
- ⬜ **Item 12** (§XIII.5 — is the Hestia Tripod leg a new singleton, distinct from today's
|
||
per-attach proxies?) — still open, and still gates §IV.
|
||
|
||
**Remaining open: items 9, 10, 12, 16.** Item 10 is the substantive one; 9 is downstream of it,
|
||
12 is independent, and 16 is a build-time check rather than a decision.
|
||
|
||
---
|
||
|
||
## XVI. Item 10 settled: clean shutdown is forced flush + `BYE`; Hera's is suicide (Captain Bob, 2026-09-18)
|
||
|
||
**Captain Bob, verbatim:** "A clean shutdown is a VM termination where flush is forced and the
|
||
VM says BYE. Hera is the special case that should just halt the processor. Call it suicide I
|
||
guess."
|
||
|
||
This settles §VIII.3's second open point (what a clean-shutdown routine concretely does) and,
|
||
as a consequence, its third (is the window bounded). Traced 2026-09-18: **the ruling is almost
|
||
entirely existing mechanism, with exactly one behavioural change to a word that already
|
||
exists.**
|
||
|
||
### XVI.1 — Every piece of this already exists
|
||
|
||
- **Forced flush — `blk_flush(0)`.** `block_subsystem.c:988-990`; the source comment states it
|
||
directly: "**0 is the 'flush all' sentinel**." Already called that way at
|
||
`block_subsystem.c:849`, and already the Stadium's own write-back action for
|
||
`STADIUM_BEHAVIOUR_MIGRATE` (`stadium.c:336`, `:373`). Nothing new to build.
|
||
- **A child VM's `BYE` — `system_word_bye()`** (`src/word_source/system_words.c:143-147`):
|
||
sets `vm->halted = 1`, signalling the REPL to stop. That is already precisely "a VM
|
||
termination." Confirmed by `mama_forth_words.c:2262-2263`'s own doc comment: "In child VMs
|
||
this word is never registered; children use the standard `system_word_bye` which sets
|
||
`vm->halted` and returns to the parent's REPL."
|
||
- **Halting the processor — `arch_halt()`**, declared at `include/starkernel/arch.h:64` and
|
||
implemented on **all three architectures** (`amd64/arch.c:207`, `aarch64/arch.c:126`,
|
||
`riscv64/arch.c:170`). Three-arch parity already holds, so the non-negotiable acceptance
|
||
criteria are satisfiable without new per-arch work.
|
||
|
||
**So a child VM's clean shutdown is `blk_flush(0)` then `BYE`** — two existing calls in
|
||
sequence. This sits comfortably inside the "reorganization, not invention" scope discipline.
|
||
|
||
### XVI.2 — The one real change: Hera's `BYE` does not currently halt. It cold-restarts.
|
||
|
||
**This is the finding of this section, and it is a behavioural change to a live, registered
|
||
word — not a gap to fill.** `mama_word_bye()` (`mama_forth_words.c:2265-2271`) is Hera's own
|
||
`BYE`, and its doc comment says outright: "**Hera-only: reap all children then cold-restart the
|
||
machine.**" The body is exactly two actions:
|
||
|
||
```c
|
||
capsule_vm_kill_all_nonmama(); /* "BYE: reaping children" */
|
||
arch_cold_reset(); /* "BYE: cold restart" */
|
||
```
|
||
|
||
Against Bob's ruling:
|
||
|
||
- **`capsule_vm_kill_all_nonmama()` already matches** the "fleet shuts down" half. (The
|
||
contract is documented downstream too — `include/starkernel/capsule_birth.h:339` describes
|
||
it as called "from Hera's BYE immediately before `arch_cold_reset()` to reap all children.")
|
||
- **`arch_cold_reset()` does not match.** The ruling is *halt*, not restart. A cold reset
|
||
reboots the machine; suicide stops it. These are opposite outcomes, and today's code does the
|
||
wrong one.
|
||
|
||
**Implementation shape, traced:** `arch_cold_reset()` is `__attribute__((noreturn))`
|
||
(`arch.h:67`), but `arch_halt()` is **not** — it halts only until the next interrupt and is
|
||
called once per idle iteration in normal use (`amd64/arch.c:200-205`'s own comment). A
|
||
permanent halt is therefore `arch_disable_interrupts()` followed by a `for(;;) arch_halt();`
|
||
loop — which is exactly the pattern amd64's *own* `arch_cold_reset()` already uses as its
|
||
unreachable fallback (`for (;;) __asm__ volatile ("cli; hlt");`, `arch.c:218`) and the same
|
||
shape the kernel panic path uses. **No new primitive; an existing pattern applied
|
||
deliberately.**
|
||
|
||
**Flagged for a conscious decision, not resolved here.** `.claude/CLAUDE.md` carries a hard
|
||
rule: "Never modify a registered, tested word to 'fix' it." This is not a fix — it is a ruled
|
||
behavioural change — which is a different thing, and the rule's own reasoning ("the problem is
|
||
almost certainly in the caller") does not apply. But the change is real and should be made
|
||
knowingly rather than discovered in a diff. **Whether Hera's suicide is spelled as a changed
|
||
`BYE` or as a separate word leaving `BYE`'s cold-restart intact is an implementation choice,
|
||
and is not decided here.** Worth noting that cold-restart-on-`BYE` is plausibly wanted behaviour
|
||
for an interactive operator typing `BYE` at Hera's REPL, which is an argument for two words
|
||
rather than one.
|
||
|
||
### XVI.3 — A shared-source constraint on where the flush goes
|
||
|
||
`system_word_bye()` lives in `src/word_source/system_words.c` — **vendored/shared source that
|
||
must compile and behave correctly in the hosted build as well as the kernel**
|
||
(`.claude/CLAUDE.md`: gate kernel-only code with `#ifdef __STARKERNEL__`). Forcing a
|
||
`blk_flush(0)` inside `system_word_bye()` itself would change hosted-build behaviour for a word
|
||
that has nothing to do with this design.
|
||
|
||
**So the forced flush belongs in the kernel-side shutdown path that calls `BYE`, not inside
|
||
`BYE`.** Stated here as a constraint on implementation so the obvious-looking edit is not made
|
||
in the obvious-looking place.
|
||
|
||
### XVI.4 — §VIII.3's third question answers itself: Hera's halt is the bound
|
||
|
||
§VIII.3 asked whether the shutdown window is bounded, noting that "holds it until it goes down"
|
||
gives no deadline. **It is bounded, and by construction rather than by a timer: the window ends
|
||
when Hera halts the processor.** Children flush and say `BYE`; Hera reaps whatever remains and
|
||
stops the machine. There is no deadline to choose, no timeout to tune, and — consistent with
|
||
§XV.3 — nothing that has to *decide* when time is up. The sequence terminates because its last
|
||
step is physically terminal.
|
||
|
||
This also satisfies §VII.1 step 3's "no lingering, no partial states" literally: after
|
||
`arch_halt()` in a disabled-interrupt loop there is no state left to linger in.
|
||
|
||
### XVI.5 — Item 9 is now half-answered
|
||
|
||
§VII.2 left two questions on `SOS`: which message-type number, and "who consumes an `SOS`, and
|
||
what do they do with it?" **The second is answered for the two fleet-fatal cases:** on Hermes's
|
||
sinking semaphore (§VIII.1) and on total birther failure (§IX.1), the response is now concrete
|
||
— forced flush, `BYE`, and Hera's suicide as the terminal step.
|
||
|
||
**Still genuinely open, and narrower than before:** what a peer does on receiving an *ordinary*
|
||
VM's `SOS`. A single non-Tripod VM in trouble is presumably not fleet-fatal, so "everyone
|
||
shuts down" cannot be the universal answer — but §XV.2 rules out the obvious alternative, since
|
||
with no death-declarer an `SOS` consumer cannot be a supervisor that decides another VM's fate.
|
||
The remaining question is therefore specifically: **is a peer's `SOS` actionable at all, or is
|
||
it purely advisory/diagnostic?** Plus the trivial number allocation (§I.4: 5 and 6 are
|
||
unallocated gaps, 10 is next in sequence).
|
||
|
||
### XVI.6 — Punch list after this ruling
|
||
|
||
- ✅ **Item 10 (§VIII.3) — SETTLED** (§XVI). Clean shutdown = `blk_flush(0)` + `BYE`; Hera =
|
||
suicide via a permanent `arch_halt()` loop. Window bounded by Hera's halt (§XVI.4). All
|
||
mechanism exists on all three architectures.
|
||
- 🔶 **Item 9 (§VII.2) — HALF-ANSWERED** (§XVI.5). Consumer action defined for the two
|
||
fleet-fatal cases. Open: whether a peer `SOS` is actionable or advisory, plus the number.
|
||
- ⬜ **Item 12 (§XIII.5)** — Hestia Tripod leg: new singleton or not? Unchanged; still gates §IV.
|
||
- ⬜ **Item 16 (§XV.4)** — implementation check: teardown paths must reach `STADIUM-EVICT`.
|
||
- ⬜ **Item 17, NEW** (§XVI.2) — decide whether Hera's suicide replaces `BYE`'s cold-restart or
|
||
becomes a separate word. Small, but it changes a live registered word either way.
|
||
|
||
### XVI.7 — One residual edge, raised not answered
|
||
|
||
**If Hera is already dead, nobody performs the halt.** §XV.2 makes death compudynamic and §IX.1
|
||
forbids any VM assuming her authority, so on total Hera failure there is no actor left to run
|
||
`arch_halt()`. The machine would be a live kernel with an empty Stadium floor — which is
|
||
precisely the "lingering, partial state" §VII.1 step 3 rules out.
|
||
|
||
The shape that resolves it without violating §IX: **an empty floor is a kernel-observable
|
||
condition, not a VM's decision.** The kernel noticing "no live VMs remain" and halting is not a
|
||
VM inheriting Hera's authority — it is the machine having nothing left to run. That keeps
|
||
authority flowing only down the birth graph (§IX.2) while still terminating.
|
||
|
||
**Offered as analysis, not a ruling — Captain Bob's call.** Added as punch item 18.
|
||
|
||
---
|
||
|
||
## XVII. Item 12 CLOSED — "Console" already exists as a singleton; it just has no VM face
|
||
|
||
Taken as closing **item 12** (§XIII.5's Hestia-singleton question), the largest remaining
|
||
design item and the one gating §IV.
|
||
|
||
**§XIII.5 framed this wrongly, and the error is worth naming before the answer.** It compared
|
||
the Tripod legs against `capsule_console_birth()`'s per-attach proxies, found Hestia "plural,
|
||
ephemeral and capsule-less," and concluded that a singular pinned Hestia "does not currently
|
||
exist" — so §IV.1 would be creating one, straining the reorganization-not-invention discipline.
|
||
**That comparison picked the wrong object.** Traced 2026-09-18: there are three distinct things
|
||
called "console" in this kernel, not two.
|
||
|
||
### XVII.1 — The three consoles, traced
|
||
|
||
1. **The HAL console — the drawing fabric itself.** `src/starkernel/hal/console.c` (14 KB),
|
||
`framebuffer.c` (13 KB), `vt100.c` (43 KB), `font_8x16.c` (27 KB) — ~98 KB of kernel C.
|
||
**Already singular. Already permanent. Already kernel-resident.** It is not a VM and has no
|
||
owner in the fleet sense.
|
||
2. **The console proxy VMs** — `capsule_console_birth()`, plural, ephemeral, minted per attach
|
||
from a 3-line C string literal (§XIII.5).
|
||
3. **The active-console-VM name** — a single global, `console_set_vm_name()`/
|
||
`console_get_vm_name()` (`include/starkernel/console.h:190-191`), swapped by every dispatch
|
||
in the "switch, do work, switch back" pattern.
|
||
|
||
### XVII.2 — RULING: the Hestia Tripod leg is (1), given a VM face. Not a promoted proxy.
|
||
|
||
The singular, permanent Hestia this design wants **already exists in substance** — it is the
|
||
drawing fabric. What it lacks is an *owner*: today the fabric is an ownerless kernel singleton
|
||
that any VM reaches into through a global. So §IV.1's "Hestia takes the vacated third slot"
|
||
is **not** the invention §XIII.5 feared. It is giving an existing singleton a VM face.
|
||
|
||
That resolves the tension cleanly and without inventing anything:
|
||
|
||
- **The Hestia leg is singular, pinned and born-at-boot** — because the fabric it owns already
|
||
is all three.
|
||
- **The proxies are untouched.** They stay plural and ephemeral, which is correct: they are
|
||
what *binding produces*, not what Hestia *is* (§XIII.5's own phrasing, now properly
|
||
grounded).
|
||
- **§V.1's "bind point" falls out rather than being asserted.** The VM that owns the fabric is
|
||
necessarily what a user or agent VM binds *to*.
|
||
|
||
**§XIII.5's proposed shape was right; its justification was wrong.** It proposed exactly this
|
||
leg/proxy split but called the leg new. The leg is not new — only its VM face is.
|
||
|
||
### XVII.3 — The evidence that the fabric actually wants an owner
|
||
|
||
This is not merely tidy. The ownerless global in (3) has already caused a real, live bug,
|
||
documented in the kernel's own header (`console.h:193-203`): `console_get_vm_name()` alone is
|
||
**not** safe for save-then-restore, because it returns a pointer into the single internal
|
||
buffer that `console_set_vm_name()` copies into — so an intervening call in the normal
|
||
"switch, do work, switch back" pattern overwrites the very bytes the saved pointer points at
|
||
**before the restore runs**. Found live 2026-08-28; the restore silently no-opped.
|
||
`console_save_vm_name()` exists solely to work around it.
|
||
|
||
That is the signature of shared mutable state with no owner. **Giving the fabric an owning VM
|
||
is a structural fix for the class**, not just a reorganization — and it is an argument *for*
|
||
Bob's reshuffle that this document had not previously identified.
|
||
|
||
### XVII.4 — What this commits to, concretely
|
||
|
||
Consequences of the ruling, so they are not discovered late:
|
||
|
||
- **Hestia needs a capsule personality.** `capsules/hestia/init.4th` — a new directory beside
|
||
`hermes/` and `artemis/`. This is the one genuinely new artifact, and it is a capsule, not a
|
||
mechanism.
|
||
- **`is_fleet_foundation` changes membership** (`capsule_birth.c:793-796`): the name-prefix
|
||
triple becomes Hera / Artemis / Hestia. That single line is what makes a VM pinned
|
||
(§XIII.3), so it is also what makes Hestia a Tripod leg.
|
||
- **`kernel_main.c:865`'s `S" Hermes" BIRTH` becomes Hestia's birth**, and the switch-signal
|
||
registration at `:1007` follows it.
|
||
- **The DoE CSV schema changes** — `doe_log.c`'s six Tripod-named columns (§XIII.3). Still the
|
||
expensive consequence, still not to be resolved by quietly renaming a column.
|
||
- **Hestia must have `BIRTH` registered** (§XIII.6): binding mints a proxy, and minting is
|
||
`BIRTH`. Already settled in principle by §XV.1's "any VM can birth."
|
||
- **Hestia becomes the owner of the `console_set_vm_name()` discipline** — the fix in §XVII.3
|
||
is available once there is an owner, but is **not** in this reshuffle's scope. Flagged, not
|
||
scheduled.
|
||
|
||
### XVII.5 — §IV is unblocked, and §XIII.5's marker corrected
|
||
|
||
With item 12 closed, **§IV.1 (Tripod = Hera/Artemis/Hestia) stands as ratified with no
|
||
outstanding objection**, and §IV.2 remains dissolved per §XIV.2. §XIII.5's "this is the one
|
||
place the scope discipline is genuinely strained" no longer holds and is corrected there.
|
||
|
||
### XVII.6 — Punch list after this ruling
|
||
|
||
- ✅ **Item 12 — CLOSED** (§XVII). The Hestia leg is the existing drawing-fabric singleton
|
||
given a VM face; proxies unchanged. §IV unblocked.
|
||
- 🔶 **Item 9** — half-answered (§XVI.5): open is whether an ordinary peer's `SOS` is actionable
|
||
or advisory, plus the number allocation.
|
||
- ⬜ **§VIII.3 first bullet** — where the sinking semaphore mechanically lives.
|
||
- ⬜ **Item 16** (§XV.4) — implementation check: teardown paths must reach `STADIUM-EVICT`.
|
||
- ⬜ **Item 17** (§XVI.2) — does Hera's suicide replace `BYE`'s cold-restart or become a
|
||
separate word?
|
||
- ⬜ **Item 18** (§XVI.7) — if Hera is already dead, nobody performs the halt.
|
||
|
||
**Nothing structural remains open.** Items 9, 17 and 18 are small, local decisions; §VIII.3's
|
||
first bullet is a placement question; item 16 is a build-time check. Every load-bearing
|
||
architectural question this document opened — what Hermes becomes, what the Tripod is, what
|
||
`BIRTH` means, who owns death, who owns turn order, what survives, what shutdown is — is now
|
||
ruled.
|
||
|
||
---
|
||
|
||
## XVIII. The Hestia component, designed in full (2026-09-18)
|
||
|
||
§XVII settled *what* the Hestia leg is. This section designs the component. Everything below
|
||
traced 2026-09-18 against `e56974e`; decisions are marked, proposals are marked, and open
|
||
questions are marked.
|
||
|
||
### XVIII.1 — Hestia is three layers, and only the middle one is new
|
||
|
||
| Layer | What | Where it lives today | Change |
|
||
|---|---|---|---|
|
||
| **0 — the fabric** | Raw output: framebuffer, VT100, glyph raster, UART | `hal/console.c`, `framebuffer.c`, `vt100.c`, `font_8x16.c` (~98 KB C) | **None.** Stays kernel HAL. |
|
||
| **1 — Hestia the VM** | Tripod leg. Owns fabric *policy*, is the bind point | **Does not exist** | **New — and it is a capsule, not a mechanism.** |
|
||
| **2 — console proxies** | Per-attach relay VMs, one per bound user/agent | `capsule_console_birth()` | **None**, except their birther becomes Hestia. |
|
||
|
||
The design is almost entirely layer 1, and layer 1 is mostly a *relocation* of vocabulary that
|
||
already exists in the wrong dictionary (§XVIII.3).
|
||
|
||
### XVIII.2 — The constraint that shapes everything: the HAL must never know a VM exists
|
||
|
||
**This is not a preference, it is a defended invariant with a documented rationale**
|
||
(`include/starkernel/console.h:220-224`, verbatim):
|
||
|
||
> `console.c` is a clean HAL module with no dependency on capsule/WIREBIND logic
|
||
> (`zuse_session`, `capsule_wirebind_attached_username()`) — pulling either in directly here
|
||
> would be a **real layering violation, not just a style preference.**
|
||
|
||
So **Hestia-the-VM may not be implemented by making `console.c` VM-aware.** Ownership flows one
|
||
way only: Hestia reaches *down* into the HAL; the HAL never reaches *up*.
|
||
|
||
**The sanctioned pattern for the cases where the HAL does need something VM-shaped already
|
||
exists and should be reused rather than reinvented:** `console_set_user_prefix_provider()`
|
||
(`console.h:231`) — a callback that lets `repl.c` supply the "user" half of the `[user@VMName]`
|
||
prompt "without `console.c` knowing anything about VMs, sessions, or WIREBIND." Any further
|
||
HAL→Hestia coupling this design needs takes that shape: a registered callback, never an
|
||
include.
|
||
|
||
**Consequence, stated plainly:** Hestia's "ownership" of the fabric is by *convention,
|
||
vocabulary and registration* — it is the VM that holds the drawing words — **not** by any
|
||
enforcement inside `console.c`. That is weaker than it sounds and is exactly right: it keeps
|
||
the HAL reusable and the layering intact.
|
||
|
||
### XVIII.3 — Hestia's dictionary: 1,051 lines of Hestia vocabulary currently live in Hera
|
||
|
||
**The most concrete finding in this section.** `capsules/fabric.4th`'s own header reads:
|
||
|
||
> `fabric.4th` — **Console drawing-fabric coordinate machinery.** `FABRIC-0.md` item 4.3.3.
|
||
> 45-degree cavalier orthographic projection... Raw pixel write (`PLOT`/`FB-WIDTH`/`FB-HEIGHT`)
|
||
> is C; **this capsule is the FORTH-side policy on top of it.**
|
||
|
||
It is named Hestia's fabric, it *is* the FORTH-side fabric policy — and it loads into **Hera's**
|
||
dictionary (`capsules/init.4th` block 2049: `S" fabric.4th" EXEC`, `S" font.4th" EXEC`).
|
||
|
||
| Capsule | Lines | Loads into today | Should load into |
|
||
|---|---|---|---|
|
||
| `fabric.4th` | 319 | **Hera** (`init.4th` b2049) | **Hestia** |
|
||
| `font.4th` | 733 | **Hera** (`init.4th` b2049) | **Hestia** |
|
||
| `turtle.4th` | 99 | `sdk.4th` (opt-in, not boot) | unchanged — it is SDK, not fabric |
|
||
|
||
**Plus the C primitives underneath:** `PLOT`, `FB-WIDTH`, `FB-HEIGHT`
|
||
(`src/word_source/framebuffer_words.c:62-64`). Their *registration* moves to Hestia's word
|
||
table; the implementations do not change.
|
||
|
||
**DECIDED (proposal — Captain Bob's call, but this is the direct consequence of §XVII.2):**
|
||
`fabric.4th` and `font.4th` move from `init.4th` to `capsules/hestia/init.4th`. This is a pure
|
||
relocation of 1,051 lines — the single most obviously-correct edit in the whole reshuffle, and
|
||
the clearest evidence that the fabric wants an owner: it already *has* the vocabulary, just
|
||
attached to the wrong VM.
|
||
|
||
**Parity consequence** (§III.5): Hera's `dict_hash` will shrink, Hestia's is new. Per §XX's
|
||
standard, the property that matters is cross-architecture identity, not an unchanging absolute.
|
||
|
||
### XVIII.4 — Hestia's capsule personality
|
||
|
||
`capsules/hestia/init.4th` — a new directory beside `hermes/` and `artemis/`, and **the one
|
||
genuinely new artifact this reshuffle creates.**
|
||
|
||
Contents, in load order:
|
||
|
||
1. `S" common:messaging.4th" EXEC` + `MSG-CD-INIT` — Hestia is a Tripod leg and a full
|
||
messaging participant. **Note this differs from the proxies**, which deliberately skip
|
||
`COMMON-CH` (`capsule_console.c:23-26`: "a console's own traffic is direct 1:1 with its
|
||
paired user VM"). The *leg* subscribes; the *proxies* still do not.
|
||
2. `S" fabric.4th" EXEC` and `S" font.4th" EXEC` — per §XVIII.3.
|
||
3. Hestia's own bind vocabulary (§XVIII.5).
|
||
4. A `WELCOME`/banner word, matching `hermes/init.4th`'s and `artemis/init.4th`'s shape.
|
||
|
||
**Block allocation is a real to-do, not a formality.** `mkcapsule`'s actual constraints, per
|
||
§XXXII.2's correction: block range **`[2048, 5120)`** and a hard **16-content-line-per-block**
|
||
cap (*not* the 1024-byte framing `.claude/CLAUDE.md` still describes — that doc error is
|
||
outstanding). **Block 4997 is already taken** by the proxy's own C string literal
|
||
(`capsule_console.c:28-31`), so Hestia's range must avoid it. Allocate against
|
||
`capsule-reserved.txt` and verify with `mkcapsule --lint capsules/` (§XXIV's collision
|
||
machinery covers this; it is blind to content, only to numbers).
|
||
|
||
### XVIII.5 — The bind point: flow and vocabulary
|
||
|
||
**Binding, end to end, after the reshuffle:**
|
||
|
||
```
|
||
human attaches thumbdrive agent VM needs a console
|
||
│ │
|
||
▼ ▼
|
||
WIREBIND path CONSOLE-ATTACH
|
||
│ │
|
||
└──────────► Hestia ◄───────────┘
|
||
│
|
||
BIRTH a proxy (§XV.1 makes this legal:
|
||
│ any VM may birth)
|
||
▼
|
||
proxy paired to target
|
||
(VM-NAME-REG, unchanged)
|
||
```
|
||
|
||
- **`CONSOLE-ATTACH ( name-c name-u -- ok? )` already exists and is live-verified** (§I.6,
|
||
closed 2026-09-16). It resolves the target's liveness *before* birthing, so a typo refuses
|
||
cleanly with no orphaned VM. **Keep it exactly as is.** The change is *who runs it*: today
|
||
the three `capsule_console_birth()` call sites run in Hera's or the caller's context
|
||
(`capsule_wirebind.c:245`, `mama_forth_words.c:1591`, `:2015`). Under this design Hestia is
|
||
the birther.
|
||
- **This is why Hestia needs `BIRTH` registered** (§XIII.6) — binding *mints a proxy*, and
|
||
minting is `BIRTH`. Already legal per §XV.1.
|
||
- **Mechanically this already works:** two of the three call sites pass `vm->stadium_vm_id` —
|
||
whichever VM invoked — so parentage is already generic (§I.5, §XIII.6). Only registration
|
||
changes.
|
||
|
||
**OPEN — agent-VM binding and the `~user` convention** (§V.3.1, still unresolved). The pairing
|
||
check in `sk_repl_dispatch_line()` reconstructs the target as `console_get_vm_name() + "~user"`
|
||
— a convention built for *human at a console → identity VM*. A GPIO VM (`FABRIC-4.md` §2) is
|
||
not a `~user` identity. §XXXII.2 records that a console named anything else "silently falls
|
||
back to direct interpretation with no error," caught live. **Two shapes, neither chosen:**
|
||
(a) widen the convention so the suffix is a property of the *binding*, not hardcoded; (b) give
|
||
agent binding its own word alongside `CONSOLE-ATTACH`. **(a) is preferable on
|
||
no-bespoke-gate grounds but touches a live, bug-prone path; flagged rather than decided.**
|
||
|
||
### XVIII.6 — Headless-until-login survives, and the invariant that makes it survive
|
||
|
||
**Hestia the leg is born at boot. A console session is not.** These must not be conflated, or
|
||
§VIII.1's ratified headless-until-login policy reopens — the exact failure §XXXII.2 warned
|
||
about for unattended birth.
|
||
|
||
**INVARIANT, to be stated in whatever code implements Hestia:**
|
||
|
||
> Hestia's birth at boot must not set `g_wirebind_attached_username`, must not cause
|
||
> `sk_console_identity_present()` (`repl.c:122`) to report an identity, and must not mint a
|
||
> proxy. Hestia owns the fabric from boot; it presents nothing until something binds.
|
||
|
||
This is the same invariant §XXXII.2 imposed on unattended identity birth, applied to a second
|
||
path. It is cheap to hold — Hestia births no proxy until asked — but it is exactly the kind of
|
||
thing that gets violated by a well-meaning "initialise the console at startup" line.
|
||
|
||
### XVIII.7 — What Hestia does *not* own
|
||
|
||
Stated because a component that owns "the bind point" attracts responsibilities that belong
|
||
elsewhere, and this document has already had to defend against exactly that (§XV.3):
|
||
|
||
- **Not turn order.** Nothing owns it (§XV.3).
|
||
- **Not routing.** That is kernel-Hermes (§III), which sits *below* Hestia.
|
||
- **Not the lifecycle of anything but its own proxies.** Hestia births proxies; it does not
|
||
birth, kill, or supervise identity VMs. Authority flows down the birth graph only (§IX.2).
|
||
- **Not the prompt's user half.** That stays `repl.c`'s, supplied to the HAL via the existing
|
||
provider callback (§XVIII.2). Moving it into Hestia would be the layering violation
|
||
`console.h` explicitly names.
|
||
|
||
### XVIII.8 — Hestia's own failure behaviour
|
||
|
||
Hestia is a Stadium-floor VM **above** the routing layer, so §VIII.2's rule applies without an
|
||
exception: **Hestia emits `SOS`**; only Hermes uses the semaphore. Its clean shutdown is
|
||
§XVI's: forced `blk_flush(0)`, then `BYE`.
|
||
|
||
**A pleasant property worth recording: Hestia's death degrades gracefully by construction.**
|
||
Because layer 0 is HAL C (§XVIII.1) and ownership is by convention rather than enforcement
|
||
(§XVIII.2), a dead Hestia leaves the framebuffer, VT100 and UART fully functional — the fabric
|
||
simply becomes ownerless again, which is precisely today's status quo. The kernel can still
|
||
print. **This is the opposite of Hermes**, whose death takes the transport with it. So the
|
||
Tripod's three legs have three genuinely different failure characters: Artemis's death costs
|
||
storage arbitration, Hestia's costs only fabric *policy*, Hermes's costs the transport itself —
|
||
which is why only Hermes needed the semaphore.
|
||
|
||
### XVIII.9 — Punch list for Hestia
|
||
|
||
Design items, in dependency order. **No code authorized.**
|
||
|
||
1. ⬜ Ratify §XVIII.3's relocation: `fabric.4th` + `font.4th` move from `init.4th` to
|
||
`capsules/hestia/init.4th`; `PLOT`/`FB-WIDTH`/`FB-HEIGHT` registration moves to Hestia.
|
||
2. ⬜ Allocate Hestia's block range against `capsule-reserved.txt`, avoiding 4997; verify with
|
||
`mkcapsule --lint` (§XVIII.4).
|
||
3. ✅ **SETTLED 2026-09-19 by §XX** — neither option. The pairing is already recorded at bind
|
||
time; the `~user` reconstruction is a redundant derivation and is removed. Agent binding
|
||
then needs no new mechanism.
|
||
4. ⬜ Confirm Hestia in the `is_fleet_foundation` triple (`capsule_birth.c:793-796`) and its
|
||
birth at `kernel_main.c:865`, replacing Hermes's (§XVII.4).
|
||
5. ⬜ Handle the `doe_log.c` CSV schema change (§XIII.3) — still the expensive consequence.
|
||
6. ⬜ State §XVIII.6's headless invariant in the implementation.
|
||
7. ⬜ **Not in this reshuffle:** the `console_set_vm_name()` ownerless-global fix (§XVII.3) is
|
||
now *available* once Hestia exists, but remains out of scope. Flagged, not scheduled.
|
||
|
||
---
|
||
|
||
## XIX. RULING: the third Tripod leg is named Hestia, not Console (Captain Bob, 2026-09-19)
|
||
|
||
**The Tripod is: Hera, Artemis, Hestia.** Applied throughout this document — 99 occurrences
|
||
renamed; three verbatim quotations deliberately left saying "Console" (§XIX.4).
|
||
|
||
### XIX.1 — The naming convention, stated so it stops being re-litigated
|
||
|
||
`antiprosopos` (Gk. representative/delegate) was considered first and **rejected, on Captain
|
||
Bob's reasoning, which is the correct reasoning and is recorded here because it generalizes:**
|
||
|
||
> "Now this is just a name of a Greek mythos god, it doesn't have to carry full/perfect
|
||
> [fidelity], it's only a contextual display... After all, Artemis isn't exactly the perfect
|
||
> name for a memory manager/storage manager either."
|
||
|
||
That is the convention, and it had never been written down: **a Greek deity name, evocative
|
||
rather than literal.** Checked against what exists — Hera (queen/mother → the Mama VM) is a
|
||
close fit, Hermes (messenger → messaging) is the closest, and **Artemis (huntress, wilderness →
|
||
block storage and freemap arbitration) is a loose fit that has never caused anyone a
|
||
problem.** Fidelity was never the standard.
|
||
|
||
`antiprosopos` failed on being the wrong *kind* of word: a common noun straining for literal
|
||
accuracy, which is the opposite of how the other three work. `Hestia` — goddess of the hearth —
|
||
is a deity, is evocative (the hearth is the fixed centre of the household, where everyone
|
||
gathers), and carries a pleasing incidental: **Hestia is the one who never leaves.** That maps
|
||
onto the pinned-session model (`FABRIC-2.md` §H.1, "they never leave, permanently") without
|
||
having been chosen for it.
|
||
|
||
**Two costs that `antiprosopos` carried are retired by this choice, not merely tolerated:**
|
||
- **Pattern.** `antiprosopos` is Greek vocabulary, not a deity — it half-joined the set.
|
||
`Hestia` joins it fully.
|
||
- **Typo surface.** Twelve characters of unusual spelling, in a path where a VM-name mismatch
|
||
fails *silently* (§XIX.5). `Hestia` is six, comparable to `Hermes` and `Artemis`.
|
||
|
||
### XIX.2 — Why renaming at all is structural, not cosmetic
|
||
|
||
§XVII.1 found three distinct things in this kernel all called "console" — the HAL fabric, the
|
||
VM, and the per-attach proxies — and that collision is exactly what led §XIII.5 to the wrong
|
||
conclusion about whether a singular Console existed. Naming the VM separately resolves it by
|
||
construction:
|
||
|
||
| Layer | Name after this ruling |
|
||
|---|---|
|
||
| 0 — the drawing fabric (HAL C) | **the console** — `console.c`, unchanged |
|
||
| 1 — the Tripod leg, owns the fabric | **Hestia** |
|
||
| 2 — per-attach relay VMs | **console proxies** — unchanged |
|
||
|
||
"Hestia owns `console.c`" is unambiguous in a way "Console owns `console.c`" cannot be. This
|
||
document has already paid once for that ambiguity; the rename is what stops it recurring.
|
||
|
||
### XIX.3 — What is NOT renamed
|
||
|
||
The ruling names a VM. It does not rename the subsystem:
|
||
|
||
- **The HAL stays `console.c`/`console.h`** and every `console_*()` function. Renaming them
|
||
would be churn across ~98 KB of C for no gain, and would re-create the confusion by making
|
||
the HAL sound like the VM.
|
||
- **`capsule_console_birth()` / `CONSOLE_IDENTITY_SRC` stay** — they mint console proxies,
|
||
still called console proxies.
|
||
- **`CONSOLE-ATTACH` stays.** `.claude/CLAUDE.md`'s "never modify a registered, tested word"
|
||
applies with more force to *renaming* one, and the word remains accurate: it attaches a
|
||
console. **Recommended, not ruled.**
|
||
- **`CONSOLE-CMD-EVENT` and `sk_console_identity_present()` stay** — both are layer 0/2
|
||
business (a console session), not Hestia's (§XVIII.6).
|
||
|
||
**Net code-visible rename surface:** the VM's registry name, its capsule directory
|
||
(`capsules/hestia/init.4th`), and the places the Tripod is enumerated (§XIX.6).
|
||
|
||
### XIX.4 — Three quotations deliberately still say "Console"
|
||
|
||
Quoted source is not silently edited to match a later decision:
|
||
|
||
1. **Line 26** — the opening brief's own wording ("Hera lifecycle/ACL, Console framebuffer").
|
||
2. **§XVIII.3** — `capsules/fabric.4th`'s verbatim header, "Console drawing-fabric coordinate
|
||
machinery." That is what the file says *today*; it changes when the file is edited, and
|
||
**that edit belongs to the §XVIII.3 relocation, not to this ruling.**
|
||
3. **§XVII's heading** — a meta-reference to the name itself, which is that section's subject.
|
||
|
||
### XIX.5 — `~user` is a separate question, unaffected
|
||
|
||
`antiprosopos` was first raised as a replacement for the `~user` registry-name suffix. **That
|
||
remains punch item 3** (§XVIII.5), and the Hestia ruling does not touch it. Recorded so the two
|
||
never get conflated:
|
||
|
||
Traced 2026-09-18 — as a *suffix* it does not fit the buffers. `VM_NAME_MAX` is 64 and
|
||
`USER_IDENTITY_USERNAME_MAX` 32, so the name fits in principle, but every construction buffer
|
||
is sized `+ 8`, tuned exactly to `"~user"` (5 chars + NUL = 6): `capsule_wirebind.c:222` (=40),
|
||
`mama_forth_words.c:1855`/`:1991` and `repl.c:1243` (=72), each guarding on a hardcoded `+ 6`.
|
||
A 14-byte suffix would not overflow them — it would make them **refuse**, silently failing to
|
||
bind usernames over 26 characters and registry names over 58. Six `memcpy` sites and five
|
||
guards hardcode that `6`, and `FABRIC-3.md` §XXVI was itself a truncation fix.
|
||
|
||
**And it would not answer item 3 regardless:** a GPIO VM is neither a user nor a human's
|
||
representative. The structural fix is making the suffix a property of the *binding*; settle
|
||
that first and land any suffix rename inside it, since the same eleven sites are touched either
|
||
way.
|
||
|
||
### XIX.6 — Edit surface
|
||
|
||
All were already edit sites for the Tripod membership change (§XVII.4); the rename changes the
|
||
string, not the count:
|
||
|
||
- `capsule_birth.c:793-796` — `is_fleet_foundation`'s prefix triple becomes
|
||
Hera / Artemis / **Hestia** (matched by `vm_name_prefix_eq_nocase`, as today).
|
||
- `kernel_main.c:865` — `S" Hestia" BIRTH`; the liveness check and the switch-signal
|
||
registration at `:1007` follow.
|
||
- `capsules/hestia/init.4th` — the new capsule directory (§XVIII.4).
|
||
- `doe_log.c` — CSV columns become `hestia_heat_q48` and `switch_hestia_readiness`. Still the
|
||
expensive consequence (§XIII.3), but `hestia` is the same width as `hermes`, so the schema
|
||
churn is a rename rather than a reflow.
|
||
|
||
### XIX.7 — One hazard, recorded and generalized
|
||
|
||
A VM-name mismatch in this system **fails quietly.** §XXXII.2 records it caught live on the
|
||
first attempt: a console named anything other than the expected form "silently falls back to
|
||
direct interpretation with no error" — typing `5 6 + .` printed a direct `11` instead of a
|
||
relayed one, with nothing reported.
|
||
|
||
`Hestia` is short and ordinary enough that this is no longer an argument about the name. But
|
||
the class remains: **if the §XVIII.5 binding work touches that path anyway, making an
|
||
unresolved or mismatched name *say so* would retire the hazard for every VM name, not just this
|
||
one.** Raised as punch item 19, not scheduled.
|
||
|
||
---
|
||
|
||
## XX. Item 3 SETTLED: delete the suffix from the mechanism — neither widen it nor add a word
|
||
|
||
§XVIII.5 posed agent-VM binding as a choice between (a) widening the `~user` convention and
|
||
(b) a sibling word for agent binding. **Both options are wrong, because both accept a premise
|
||
the code does not support.** Traced 2026-09-18/19: the pairing is *already recorded
|
||
explicitly*, and the `~user` reconstruction is a redundant second derivation of information the
|
||
mechanism already holds.
|
||
|
||
### XX.1 — The relay does not route by name. It routes by a slot recorded at bind time.
|
||
|
||
`sk_repl_dispatch_line()` (`repl.c:1225-1265`) does two separate things, and only one of them
|
||
involves the suffix:
|
||
|
||
1. **The guard** builds `paired_name = console_get_vm_name() + "~user"`
|
||
(`repl.c:1243-1247`) and checks `capsule_vm_find_by_name(paired_name, ...)` is `VM_STATE_LIVE`.
|
||
2. **The actual relay** then sends `CONSOLE-CMD-EVENT 0 3 S" <line>" 0 MSG-SEND` — **to index
|
||
3**, with this comment verbatim: *"to-index 3: the fixed convention this console's own
|
||
`VM-NAME-REG` entry for its paired user VM uses (**set once at pairing time** — see the
|
||
pairing word)."*
|
||
|
||
`PAIR-TEST`'s own header says the same from the other side (`mama_forth_words.c:1542-1543`):
|
||
"**Registers the pairing in the console's own VM-name routing table at the fixed index (3) that
|
||
relay uses.**"
|
||
|
||
**So the target is already stored, per-proxy, at bind time.** The suffix string is used only to
|
||
answer "is my partner alive?" — a question the stored pairing can answer directly, without
|
||
deriving anything.
|
||
|
||
### XX.2 — This is the documented cause of the known silent-failure bug
|
||
|
||
`CONSOLE-ATTACH`'s own doc comment (`mama_forth_words.c:1931-1940`) states it outright:
|
||
|
||
> `sk_repl_dispatch_line()`'s own pairing check (`repl.c`) reconstructs the target as
|
||
> `console_get_vm_name() + "~user"`... **A console named anything other than the identity's own
|
||
> base name reconstructs the wrong target string and silently falls back to direct
|
||
> interpretation — no error, just quietly never relays.**
|
||
|
||
`CONSOLE-ATTACH` already carries a workaround for this: it "takes exactly one name, not an
|
||
independently chosen console name," collapsing two arguments into one *so the reconstruction
|
||
cannot disagree*. That is a constraint imposed by the derivation, not by the problem.
|
||
|
||
### XX.3 — RULING (proposed): the bind records its target; nothing re-derives it
|
||
|
||
**Replace the derivation with a read of what bind time already stored.**
|
||
|
||
- **`sk_repl_dispatch_line()`'s guard** asks "does this console have a recorded pairing, and is
|
||
that target live?" instead of "does `<name>~user` exist?"
|
||
- **`CONSOLE-ATTACH`** resolves the target **as given**, rather than appending `~user`
|
||
(`mama_forth_words.c:2000`).
|
||
- **`~user` survives as a naming convention, not as a mechanism.** It still disambiguates
|
||
`rajames` the proxy from `rajames~user` the identity in the prompt — the whole point of the
|
||
`[user@VMName]` form (§XXV follow-up, 2026-09-13). It simply stops being load-bearing.
|
||
|
||
**Four things fall out, none of which needed designing:**
|
||
|
||
1. **Agent-VM binding stops being a special case.** A GPIO VM named `gpio` binds by the same
|
||
unchanged path as `bob~user`, because nothing appends anything to its name. **There is no
|
||
agent-binding mechanism to build.**
|
||
2. **`CONSOLE-ATTACH`'s one-name constraint can relax** if ever wanted — it exists only to
|
||
prevent a reconstruction that no longer happens. Not proposed as work; noted so the
|
||
constraint is not later mistaken for a requirement.
|
||
3. **The silent-fallback class is dissolved rather than fixed.** With no string to mismatch,
|
||
the states are "a pairing is recorded" or "none is" — determinate and reportable. **This
|
||
retires punch item 19** (§XIX.7's "make mismatch loud") by removing what could mismatch,
|
||
which is strictly better than making it noisy.
|
||
4. **The suffix-rename question becomes purely cosmetic** (§XIX.5). Once lookup no longer
|
||
derives the suffix, the remaining sites only ever *construct* a name.
|
||
|
||
### XX.4 — The six `memcpy` sites split cleanly in two
|
||
|
||
This is what makes the change small. Traced 2026-09-18:
|
||
|
||
| Site | Role | Under this ruling |
|
||
|---|---|---|
|
||
| `capsule_wirebind.c:229` | **names** the identity VM at birth | **stays** — naming |
|
||
| `mama_forth_words.c:1864` (`UNATTENDED-BIRTH`) | **names** the registry entry | **stays** — naming |
|
||
| `mama_forth_words.c:1579` (`PAIR-TEST`) | **names** both halves; diagnostic word | **stays** — naming |
|
||
| `repl.c:1247` | **re-derives** the partner for a liveness guard | **goes** |
|
||
| `mama_forth_words.c:2000` (`CONSOLE-ATTACH`) | **re-derives** the target | **goes** |
|
||
|
||
**Only the two derivation sites change.** The naming sites are untouched, which is why `~user`
|
||
can remain a convention without remaining a mechanism.
|
||
|
||
### XX.5 — What "binding" means for an agent VM, stated because §V.1 conflated two things
|
||
|
||
§V.1 called Hestia "the bind point for users and agent VMs." Worth separating, since the two
|
||
need different things and only one of them is binding:
|
||
|
||
- **Reachability** — being addressable by other VMs — is **kernel-Hermes's** job (§III), not
|
||
Hestia's. A GPIO VM is reachable because routing exists, not because it bound to anything.
|
||
- **Fabric access** — a VM that wants to *draw* — is **vocabulary and ACL**, not binding: it
|
||
needs Hestia's drawing words (§XVIII.3), gated the `ACL.4th` way if gated at all.
|
||
- **Binding proper** — acquiring a console proxy so a human can type at a target — is what
|
||
`CONSOLE-ATTACH` does, and after §XX.3 it works for **any** live VM by name.
|
||
|
||
**So an agent VM does not routinely bind at all.** It binds only when a human wants to attach
|
||
to it for inspection or control — and that is the ordinary console path, unchanged. The
|
||
"agent-binding problem" was an artifact of the hardcoded suffix; removing the suffix removes
|
||
the problem rather than solving it.
|
||
|
||
### XX.6 — Punch list
|
||
|
||
- ✅ **Item 3 — SETTLED** (§XX.3): the bind records its target; nothing re-derives it. Agent
|
||
binding needs no new mechanism.
|
||
- ✅ **Item 19 — RETIRED** (§XX.3.3): dissolved by removing the mismatch, not by making it loud.
|
||
- 🔶 **Item 9** — unchanged: is an ordinary peer's `SOS` actionable or advisory, plus its number.
|
||
- ⬜ **§VIII.3 first bullet** — where the sinking semaphore mechanically lives.
|
||
- ⬜ **Items 16, 17, 18** — unchanged (teardown/`STADIUM-EVICT` check; `BYE` vs. a separate
|
||
suicide word; the empty-floor halt).
|
||
|
||
**Caveat on scope, per §XIV.1.** `repl.c`'s relay and the routing-slot-3 convention are part of
|
||
the FORTH messaging layer Captain Bob ruled legacy. This ruling states the *principle* — the
|
||
pairing is recorded, never derived — which kernel-Hermes must carry forward. It is not a
|
||
proposal to patch the legacy path in place.
|