diff --git a/FABRIC-3.5.md b/FABRIC-3.5.md index 19bd0c9c..9e42d970 100644 --- a/FABRIC-3.5.md +++ b/FABRIC-3.5.md @@ -3236,3 +3236,108 @@ the ruling. Every design decision stands. discipline was *verifiable* only while the documents used checkboxes (§XXXI.2). If the series continues in prose, "what is still open" needs a deliberate mechanism — because two documents have now closed with items nobody chose to drop. + +--- + +## XXXII. Item 22 SETTLED: retire the pump — the switcher becomes the sole mover of control + +§XXXI.5 found that `FABRIC-3.md` carries an open defect — "**both mechanisms can independently +move control between the same VMs**" — which is a live instance of what §XV.3 forbids as a +principle. Settled here, and **the reshuffle turns out to be the thing that closes it rather +than the thing that inherits it.** + +### XXXII.1 — The two mechanisms, and why only one should survive + +| | How it moves control | Fate | +|---|---|---| +| **The MSG-TICK pump** (`repl.c` idle loop) | `VM-EXEC`s `"MSG-TICK"` into a VM — a nested `vm_interpret()` on the **shared kernel C stack** | **Retired** | +| **The Stage-3/4 switcher** (`sk_vm_context_switch()`) | Saves and restores a **per-VM native stack**, timer-driven | **Sole survivor** | + +**RULING: kernel-Hermes publishes eligibility; it does not dispatch.** It marks a target as +having work and the switcher — the one mechanism that moves control — delivers when it next +resumes that VM on the VM's own stack. Two control-movement paths collapse into one. + +### XXXII.2 — Three reasons this is the right direction, not merely a tidy one + +1. **The pump is already legacy by §XIV.1.** It exists for exactly one purpose: to drain + *per-VM FORTH message queues* by executing `MSG-TICK` inside each VM's dictionary. Once + kernel-Hermes holds the queues, there is nothing for it to drain. **Retiring it is not a new + decision — it is a consequence of a ruling already made.** +2. **The pump is a known scaling wall, already band-aided once.** `FABRIC-3.md` §XXII records + it walking the entire live-VM registry every idle beat, `VM-EXEC`ing into every VM — "O(N) + per tick, forever, with no cap" — **caught live as a real bottleneck at just 9 VMs on + riscv64**, where a campaign that finished in 200–340 s on amd64/aarch64 never finished at + all. Fixed by round-robin batching (`SK_MSG_PUMP_BATCH`), which bounds cost to O(K) **at the + price of per-VM latency depending on registry position.** Its own comment names the + endgame: "the real fleet is headed toward hundreds of VMs, at which point this isn't a + riscv64 quirk — unconditional O(N) per second is a wall on every architecture." + **Retiring the pump removes the wall and the latency tradeoff together.** +3. **"Not observed failing" is worth very little in this specific subsystem**, and + `FABRIC-3.md` says so itself. §XXVIII.1 is a correction to §XXVIII's own "Stage 3 CLOSED" + claim: "Zero fault indicators" was true only of what was *visible*, because "**Stage 3 emits + nothing per switch by default, so a switch storm and a healthy idle REPL produce an + identical serial log.** The corruption below was already live in every one of those 'clean' + Stage 3 boots; nothing in that verification pass could have shown it." + **A defect flagged "not observed failing" in a subsystem that is invisible by default is not + evidence of health.** That is the project's own finding, not an inference. + +### XXXII.3 — Reconciling with §XV.3: one *mover*, still no *owner* + +§XV.3 ruled that **nothing owns turn order.** Naming the switcher the sole mover looks like it +names an owner. It does not, and the distinction is the one §XV.3 already relies on: + +> **Moving control is a mechanism. Deciding whose turn it is is a policy.** The switcher is the +> mechanism. The compudynamics remains the policy, and it is still owned by nobody. + +So §XV.3 stands unamended. **The dual-ownership defect was never about deciding** — both the +pump and the switcher move control without either claiming to choose who runs next. It is about +two *physical paths* for the same transfer, which is a correctness problem (stack ownership), +not an authority problem. Collapsing them resolves it without touching the principle. + +**And it makes §XXIII.4 implementable.** That section ruled the sinking latch is checked "on +giving a VM its turn" — which silently assumes there is **one** place a VM gets its turn. With +two movers that check has two homes, or one, and misses. **§XXIII.4 already depended on this +ruling without saying so.** + +### XXXII.4 — The dependency this rests on, verified + +The ruling strands identity VMs unless the switcher covers them. **Checked:** `FABRIC-3.md` +§XXX — "**Stage 4 — WIREBIND-scope extension, built and verified live (2026-09-14/15)**," +Captain Bob's call to proceed immediately, built in the same one-commit-per-increment +discipline as Stages 0–3. + +**So the switcher already covers WIREBIND identity VMs, not just the Tripod fleet.** Had Stage 4 +still been the "ratified-decision-only, not implemented" step §XXVIII left it as, this ruling +would have been unbuildable and identity VMs would have lost their delivery path entirely. +**It holds only because Stage 4 landed.** + +### XXXII.5 — Open for the build, not decided here + +1. **Where the payload waits.** Delivery must still cause the payload to *execute inside* the + target — `messaging.4th` block 5041: "Payload is FORTH text, executed by the receiver, same + as every other message here." Under this ruling the switcher resumes the target on its own + stack, so kernel-Hermes must leave the payload somewhere the target consumes on resume. The + shape of that hand-off is a build decision. +2. **Hera's special case.** Per §XX of `FABRIC-3.md`, Hera is skipped by the pump and instead + gets a direct `MSG-TICK` word dispatch in her own context, because "she *is* the pump" and + self-targeting `VM-EXEC` would hit a known reentrancy class. **With the pump gone, that + special case should go with it** — her queue is kernel-held like everyone's. Confirm rather + than assume. +3. **The reentrancy guards.** `g_mama_interpreting` and `g_idle_pump_active` (`repl.c`) exist + specifically because the pump makes nested `vm_interpret()` calls. They likely retire with + it — **but carefully**, since §XXVIII.2's switch storm lived in this neighbourhood. Remove + only what is provably unreachable, per §XXII's own strip discipline. + +### XXXII.6 — Punch list + +- ✅ **Item 22 — SETTLED** (§XXXII): retire the pump; the switcher is the sole mover of control; + kernel-Hermes publishes eligibility and does not dispatch. **Folds into the kernel-Hermes + work (item 6) rather than preceding it** — §XXXI.5 filed it ahead on the assumption it was a + separate defect to fix first; it is instead a property of how kernel-Hermes is built. +- ⬜ Items 23–26 unchanged (§XXXI.8): re-home §17.4; consolidate the reported-not-scheduled + registries; decide `FABRIC-2`'s five orphaned design items; reconcile `FABRIC-0`'s seven opens. + +**Worth recording as the pattern this makes four of:** §XXXI.5 read as a risk the reshuffle +would walk into. Examined, it is a defect the reshuffle *removes* — because the mechanism that +creates it is the same FORTH messaging layer already ruled legacy. **The gap analysis found a +problem that the design had already solved without noticing.**