FABRIC-3.5.md §XXIII: the sinking latch settled -- design phase complete
The last open design question. The signal is a plain scalar in kernel-Hermes's own translation unit, written only by Hermes, read by every VM through a registered primitive. That invents nothing: it is the same registration path §XX already established when register_child_vm_ words() hands the eight STADIUM-* primitives to every VM and Hera's two sites mirror them. Reading a scalar needs no queue, channel, routing table or working arbiter, which is precisely the requirement -- the transport is the thing that failed. Names it accurately. "Semaphore" was the original framing but the mechanism is a one-way latch, and the distinction carries correctness. Per §VII.1 a VM attempts its own recovery before announcing anything, so raising the latch means recovery already failed and there is no path back to not-sinking. Single writer, many readers, one irreversible transition, both observable values valid -- which is the discipline heartbeat.c:33-34 already states verbatim and §XXVIII Stage 3 already reused once rather than inventing new locking. This is the third such variable and takes the same route for the same reason. Calling it a semaphore in code would imply counting and blocking semantics it must not acquire. Settles who reads it, which is the part §XXVIII's shared C stack constrains: a VM has no thread and cannot poll. So the check happens at the dispatch point, and the split is the design -- the kernel delivers the fact, the VM runs its own flush-and-BYE in its own context. The kernel publishes, never decides, so §XV.3 and §XIV.5 hold, and each VM running its own shutdown is what §IX.1 already ruled. The window needs no deadline because Hera's halt is physically terminal. Completes §VIII.2's two-mechanism rule with no exceptions list: floor VMs send SOS through routing, the arbiter beneath raises the latch, and which one applies is decided entirely by which side of the routing layer the sender sits on. Every design question this document opened is now ruled. What remains is build sequencing plus two small local decisions, items 17 and 18. No code is authorized. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
This commit is contained in:
+136
-2
@@ -487,6 +487,11 @@ a semaphore. That is a clean rule with no exceptions list to maintain.
|
||||
|
||||
### VIII.3 — Open
|
||||
|
||||
> **FULLY SETTLED — §XVI (2026-09-18) and §XXIII (2026-09-19).** The first bullet, where the
|
||||
> semaphore lives, is answered by §XXIII: a kernel-resident single-writer scalar read through a
|
||||
> registered primitive, and a one-way latch rather than a counting semaphore. The note below is
|
||||
> kept as written.
|
||||
>
|
||||
> **PARTLY SETTLED 2026-09-18 by §XVI.** The second bullet (what a clean-shutdown routine does)
|
||||
> is answered: forced `blk_flush(0)`, then `BYE`; Hera's is suicide via a permanent
|
||||
> `arch_halt()` loop. The third (is the window bounded) answers itself — the window ends when
|
||||
@@ -607,8 +612,9 @@ structural remains; what follows are small local decisions, one placement questi
|
||||
build-time check.**
|
||||
- ~~**Item 9**~~ — **SETTLED 2026-09-19 by §XXI**: actionable to the sender's birther, advisory
|
||||
to peers; payload descriptive, never executable; number **10**.
|
||||
- **§VIII.3 first bullet** — where the sinking semaphore mechanically lives. The rest of
|
||||
§VIII.3 is settled by §XVI.
|
||||
- ~~**§VIII.3 first bullet**~~ — **SETTLED 2026-09-19 by §XXIII**: a single-writer kernel
|
||||
scalar in kernel-Hermes's scope, read through a registered primitive; a one-way latch, not a
|
||||
counting semaphore. **This was the last open design question.**
|
||||
- **Item 16 (§XV.4)** — an implementation check rather than a decision: every message-holding
|
||||
teardown path must reach `STADIUM-EVICT`, verifiable via `fleet_conserved`.
|
||||
- **Item 17 (§XVI.2)** — does Hera's suicide replace `BYE`'s current cold-restart, or become a
|
||||
@@ -2073,3 +2079,131 @@ Then, unchanged in content but now downstream of it:
|
||||
9. ⬜ Item 17 — Hera's suicide: replace `BYE`'s cold-restart, or a separate word (§XVI.2).
|
||||
10. ⬜ Item 18 — the empty-floor halt when Hera is already gone (§XVI.7).
|
||||
11. ⬜ Category B strips, each as coding proves the item dead (§XXII.1, §XXII.4.4).
|
||||
|
||||
---
|
||||
|
||||
## XXIII. §VIII.3 SETTLED: the sinking latch is a kernel-resident scalar, read through a registered primitive
|
||||
|
||||
The last open design question in this document. §VIII.1 ruled *what* the signal is and *why* it
|
||||
is not a message; this settles where it mechanically lives and who reads it.
|
||||
|
||||
### XXIII.1 — What the mechanism has to satisfy
|
||||
|
||||
Collected from the rulings, because together they constrain the answer almost completely:
|
||||
|
||||
1. **Readable by a VM whose messaging is dying** (§VIII.2) — so it cannot itself route.
|
||||
2. **Below the routing layer** (§III.2) — kernel-resident, in kernel-Hermes's own scope.
|
||||
3. **Must not require Hermes to still be working** — the whole point is that the transport is
|
||||
the thing that failed.
|
||||
4. **Must not make the kernel a supervisor** (§XV.3, §XIV.5) — the kernel may publish a fact;
|
||||
it may not decide another VM's fate.
|
||||
5. **Must be actionable by a VM that has no thread of its own** — per `FABRIC-3.md` §XXVIII
|
||||
there is no per-VM native stack; every VM runs on the one shared kernel C stack and only
|
||||
executes when dispatched.
|
||||
|
||||
### XXIII.2 — RULING: a single-writer kernel scalar, exposed as a registered primitive
|
||||
|
||||
**The latch is a plain scalar in kernel-Hermes's own translation unit, written only by Hermes,
|
||||
read by every VM through a primitive registered into its dictionary** — e.g.
|
||||
`SINKING? ( -- flag )`.
|
||||
|
||||
This invents nothing. The registration path is the one §XX of `FABRIC-3.md` already
|
||||
established and fixed: `register_child_vm_words()` hands the eight `STADIUM-*` primitives to
|
||||
every child VM, and Hera's two registration sites mirror them so her dictionary is a proper
|
||||
superset. **A ninth kernel-state reader is that same pattern, not a new mechanism** — and it
|
||||
satisfies (1) and (3) exactly, because reading a scalar needs no queue, no channel, no routing
|
||||
table and no working arbiter.
|
||||
|
||||
**Deliberately a plain unconditional primitive, not gated.** Same doctrine `CONSOLE-ATTACH` and
|
||||
`ZUSE-ELIGIBILITY-ADD` already carry (§XXXII.2 Q3): restricting who may call it, if that is
|
||||
ever wanted, is `' SINKING? ACL-PIN` in `ACL.4th`, never a bespoke C check. Reading a fact is
|
||||
not an authority.
|
||||
|
||||
**Keep it a bare scalar, not a field in a larger struct.** Robustness, not style: the reader
|
||||
must get a coherent answer while the writer's own subsystem is failing. A standalone word-sized
|
||||
value cannot be observed mid-update; a field inside a structure being torn down can.
|
||||
|
||||
### XXIII.3 — It is a one-way latch, not a counting semaphore — and that is what makes it safe
|
||||
|
||||
"Semaphore" was the word in the original framing; the accurate word is **latch**, and the
|
||||
distinction matters both for naming and for correctness.
|
||||
|
||||
**It is monotonic.** Per §VII.1, a VM attempts its own gentle recovery *before* anything is
|
||||
announced. So Hermes raising the latch means recovery has already failed and it is committed to
|
||||
going down — there is no path back to "not sinking." Raise once; never lower.
|
||||
|
||||
That gives a concurrency story with nothing in it:
|
||||
|
||||
- **Single writer** (Hermes, mainline), **many readers**, **one irreversible transition.** A
|
||||
reader either sees the old value or the new one, and **both are valid** — seeing "not
|
||||
sinking" one moment before the raise is indistinguishable from having read a moment earlier,
|
||||
which is fine.
|
||||
- **This is the discipline this codebase has already sanctioned twice, and reuses on purpose.**
|
||||
`heartbeat.c:33-34` states it verbatim: "Single writer (mainline, via `vm_tick()`'s Loop #7
|
||||
site), single reader (the ISR's re-arm call) — **no lock needed**, per §21.1's finding."
|
||||
`FABRIC-3.md` §XXVIII Stage 3 then reused that same sanctioned pattern for a second variable
|
||||
rather than "inventing new locking or overturning the ruling itself." **This is the third
|
||||
such variable, and it takes the same route for the same reason.**
|
||||
|
||||
Naming it a semaphore in code would imply counting and blocking semantics it does not have and
|
||||
must not acquire. **Call it what it is.**
|
||||
|
||||
### XXIII.4 — Who reads it, and when: the kernel delivers the fact, the VM performs the act
|
||||
|
||||
The subtle part, and the one constraint (5) forces. **A VM cannot poll.** With no per-VM thread
|
||||
(§XXVIII), a VM only runs when dispatched — so "every VM watches the latch" is not
|
||||
implementable as stated.
|
||||
|
||||
**So the check belongs at the dispatch point, and the split of responsibility is the whole
|
||||
design:**
|
||||
|
||||
> On giving a VM its turn, the kernel checks the latch. If raised, that VM runs **its own**
|
||||
> clean-shutdown routine — `blk_flush(0)` then `BYE` (§XVI) — **in its own context**, instead
|
||||
> of its normal work.
|
||||
|
||||
- **The kernel publishes a fact and delivers it.** It does not shut anyone down, does not
|
||||
decide who dies, does not order anything. §XV.3 and §XIV.5 hold.
|
||||
- **Each VM performs its own shutdown**, which is exactly what §IX.1 already ruled for
|
||||
fleet-wide shutdown ("the rest of the fleet runs its own shutdown routines") and §XVI
|
||||
defined the content of.
|
||||
- **No timer, no watcher, no supervisor.** A VM acts when it next runs, which is the
|
||||
doctrine's own sanctioned "a VM's own internal state determining whether it does anything."
|
||||
|
||||
**And the window closes by itself.** Per §XVI.4, Hera's suicide bounds it: children flush and
|
||||
`BYE` as they are dispatched, Hera reaps what remains and halts the processor. §VIII.3's "is
|
||||
the window bounded?" needs no deadline because the last step is physically terminal — there is
|
||||
nothing to time out.
|
||||
|
||||
### XXIII.5 — The two-mechanism rule, now complete
|
||||
|
||||
§VIII.2 predicted the shape; with §XXI and §XXIII both settled it closes cleanly, with no
|
||||
exceptions list to maintain:
|
||||
|
||||
| Sender is… | Signal | Why |
|
||||
|---|---|---|
|
||||
| **On the Stadium floor** (Hera, Artemis, Hestia, identity VMs, agent VMs) | **`SOS`**, a routed message (§XXI) | Routing is available to them; it travels up the birth graph to the one VM with authority to act |
|
||||
| **The arbiter beneath the floor** (kernel-Hermes) | **the sinking latch** (§XXIII) | It cannot route a message announcing that routing has failed |
|
||||
|
||||
**Which mechanism a VM uses is determined entirely by which side of the routing layer it sits
|
||||
on.** Nothing is special-cased, and there is no list of exceptions to keep in sync — a property
|
||||
worth defending if a future component is ever tempted to want "just a small" third signal.
|
||||
|
||||
### XXIII.6 — Punch list: the design phase is complete
|
||||
|
||||
**Every design question this document opened is now ruled.** What remains is build sequencing
|
||||
and three small local decisions:
|
||||
|
||||
1. ⬜ **SURGICAL STRIP — Category A** (§XXII.6). Precedes everything.
|
||||
2. ⬜ Hestia: relocate `fabric.4th` + `font.4th`; move `PLOT`/`FB-WIDTH`/`FB-HEIGHT` (§XVIII.9.1).
|
||||
3. ⬜ Hestia's block range, avoiding 4997 (§XVIII.9.2).
|
||||
4. ⬜ Hestia into `is_fleet_foundation`; birth at `kernel_main.c:865`; switch registration (§XIX.6).
|
||||
5. ⬜ `doe_log.c` CSV schema (§XIII.3) — the expensive consequence.
|
||||
6. ⬜ §XVIII.6's headless invariant stated in the implementation.
|
||||
7. ⬜ Item 16 — teardown paths reach `STADIUM-EVICT`; verify via `fleet_conserved` (§XV.4).
|
||||
8. ⬜ Item 17 — Hera's suicide: replace `BYE`'s cold-restart, or a separate word (§XVI.2).
|
||||
9. ⬜ Item 18 — the empty-floor halt when Hera is already gone (§XVI.7).
|
||||
10. ⬜ Category B strips, each as coding proves the item dead (§XXII.4).
|
||||
|
||||
**Items 8 and 9 are the only two carrying an unmade decision**; the rest are execution. Nothing
|
||||
on this list is authorized by this document — per Captain Bob's Law, no code without an
|
||||
explicit instruction.
|
||||
|
||||
Reference in New Issue
Block a user