diff --git a/FABRIC-3.5.md b/FABRIC-3.5.md new file mode 100644 index 00000000..99f348c2 --- /dev/null +++ b/FABRIC-3.5.md @@ -0,0 +1,564 @@ +# 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/Console, 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 + +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 — Console 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, `~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, Console**, with Artemis keeping its +existing storage/block-arbitration role and Console taking the vacated third slot. Console'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. + +§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. + +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, Console + +### IV.1 — Decided (Captain Bob, 2026-09-18) + +Tripod = **Hera, Artemis, Console.** Artemis keeps its existing role (storage/block +arbitration) unchanged. Console takes the slot Hermes vacates. + +### IV.2 — The "never renumbered" collision. Open, needs a ruling. + +§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. **Console 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; Console 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. Console's role expands: the bind point + +### V.1 — Decided (Captain Bob, 2026-09-18) + +Beyond owning the drawing fabric, Console 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 Console'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 Console-as-bind-point survive Console 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, Console 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 Console). +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 + +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 + +- **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 + +- **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. ⬜ Run the repo-wide `S" Hermes" VM-EXEC` grep and inventory every by-name Hermes dependency + (§III.3). Pure investigation; no design commitment. +2. ⬜ Re-verify the §V.3.4 and §VII.4 citations taken from headings and `.claude/CLAUDE.md` + rather than from the source (`FABRIC-2.md` §H.1/§H.12, `FABRIC-3.md` §XVIII). +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. + +**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: §III.3, §III.4, §IV.2, §V.3 (all four), +§VI.3, §VI.4, §VII.2 (number and consumer), §VII.3, §VII.4, §VIII.3 (all three), §IX.3 (both). + +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/Console; Console 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.