Files
LithosAnanake/FABRIC-3.5.md
T
Claude bcf41e5618 FABRIC-3.5.md §XIII: work punch items 1 and 2, CLOSED with evidence
Items 1 and 2 were the two pure-investigation entries, carrying no design
commitment, so they were executable without a ruling. Traced against the
tree at e56974e. No code written, no open design question answered.

Item 1 CLOSED: the by-name Hermes inventory is 14 FORTH sites across 5
files, 3 C-side sites, and a DoE CSV schema site -- not the two this
document's own §I.2 claimed. §I.2 corrected in place with a pointer
rather than rewritten, per the series' never-silently-drop rule. Good
news in the count: only 3 of the 14 are live production paths, which
materially lowers the estimated cost of §III.3.

Item 2 CLOSED: FABRIC-2 §H.1 (line 3699/3713), §H.12 (line 4057, also
cited from capsule_birth.c:785-788), and FABRIC-3 §XVIII (K held at
Q48_ONE) all verified against source. §V.3.4 and §VII.4 may now be
relied on.

Three findings not previously recorded. The Tripod is hardcoded as a
name-triple in C at capsule_birth.c:793 (is_fleet_foundation, the line
that makes a VM pinned), kernel_main.c:865 and :1007, plus six DoE CSV
columns in doe_log.c -- so changing Tripod membership changes the CSV
schema and bears on campaign comparability. Seven of the inventoried
FORTH sites are dead code in two capsules loaded by nothing, and
MANIFEST.md still carries a block-4055 "immutable ABI" claim FABRIC-2
declared stale and nobody corrected; reported, not fixed, as new punch
item 13.

Most consequential: Console today is plural, ephemeral and capsule-less
-- a 3-line C string literal, deliberately off the routing table, minted
fresh per attach. It is none of the five things the other Tripod legs
are, so "Console takes the vacated third slot" is not a relocation as
stated. Raised as punch item 12, gating §IV. A resolution shape is
offered as analysis, explicitly not ratified. Also notes that §V and §VI
are one change rather than two: Console cannot be the bind point while
BIRTH stays Hera-exclusive, since binding mints a proxy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
2026-09-18 21:26:45 +00:00

46 KiB
Raw Blame History

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

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 — 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-EXECing "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. ✅ 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 Console 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: §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), and — added 2026-09-18 — §XIII.5's Console-singleton question (punch item 12), which gates §IV entirely. §XIII.5's proposed resolution shape is analysis, not a ruling.

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.


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 Console 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: Console 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:

  • Console 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.
  • Console 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."
  • Console 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. Console today is none of those five things. So §IV.1's "Console takes the vacated third slot" is not a relocation of an existing pinned VM — as stated it would create a Console 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.

The shape that resolves it without inventing anything — offered as analysis, not ratified, Captain Bob's call: distinguish Console (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 Console is the bind point (§V.1), it is Console 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 "Console 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": Console 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 Console 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 Console 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.