FABRIC-3.5.md: open the Tripod/kernel reshuffle as its own document
Opened by direct instruction as a standalone document rather than a FABRIC-4 scratchpad entry: the reshuffle is a ratified architectural direction needing full FABRIC discipline, but it is not bare-metal boot, so it does not belong in FABRIC-3 and does not close it. FABRIC-3 stays open, living and authoritative for its own topic. Records what was decided 2026-09-18 (Hermes into the kernel as arbiter rather than client; Tripod reconstituted as Hera/Artemis/Console; Console as the fleet bind point; BIRTH general with authority bounded by inheritance; one gentle -> from-scratch -> brutal recovery ladder; SOS as a standard message type with Hermes excepted via a sinking semaphore; no provisional handoff of a failed birther's authority), and separates it from what is still open. Grounded against the tree rather than recalled, with provenance marked per claim. Notes the concrete consequences the move runs into: Artemis's two by-name S" Hermes" VM-EXEC call sites, the routing table's written "never renumbered" commitment on slots 0/1/2, and the per-VM CREATE/ALLOT message arenas that decide whether this stays a reshuffle or becomes a rewrite. Design only. No code authorized, nothing else in the tree touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
This commit is contained in:
+564
@@ -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, `<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, 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.
|
||||
Reference in New Issue
Block a user