# FABRIC-3.9.0.md — Observers and participants: the Tripod steps outside the compudynamics **Status: DESIGN, for Captain Bob's review. Nothing here authorizes an edit.** The execution plan and log are in `FABRIC-3.9.8.md`. **Provenance.** Opened 2026-09-24. This design follows `FABRIC-3.8.md`, whose Stages A–I are all done. The per-ISA DoE relaunch on the rebuilt driver (`FABRIC-3.8.md` §6) was stopped once a progress check showed: - Hera's `MU-WAIT-ALL` busy loop took an equal share of the CPU as workers finished; - it wrote 43% of all heartbeat rows so far (Hera 75,117 against `mu0`'s 75,114). Two fixes were tried and set aside: - **A capsule-level `100 WAIT`,** reverted. Captain Bob: *"not liking this much … redistribute work when hera is the major consumer."* The application must not steer its own scheduling. - **A kernel-side absolute-heat-share charge.** Built and tested (a cfg-0 trial took about 150 s against about 210 s), but never committed. It is superseded by this design (§5). Captain Bob, 2026-09-24: - *"Hera, Hestia, and Artemis no longer participate in the calculations. However, they observe them and act on them."* - *"let's do it."* --- ## 1. The idea The fleet splits into two roles. - **Participants** are every VM that does the work being done and measured: DoE workers, WIREBIND user and console VMs, and anything `BIRTH`-ed. For these, FABRIC-3.8's compudynamics stays exactly as built: - per-beat charge; - work heat, with floor on contact; - coolest VM with work goes next; - ties to the incumbent, then to the one waiting longest. - **Observers** are Hera, Artemis and Hestia, the Tripod. They are not compared, not charged work heat, and not counted in any floor. They **observe** the participants' physics and **act on events**: mail, console input, device events. **In thermodynamic terms,** the observers are the environment (the heat bath) and the participants are the system under study. - Hera already behaves like a reservoir: she starts holding all of `Q48_ONE`, as the root that `vm_physics_retire()` returns heat to. - Every problem since Stage G came from making the reservoir compete as if it were one more particle: - her endowment made her "hottest"; - her busy-wait took a fair share of the CPU and polluted the data; - two fixes had to push her back out. ## 2. What changes for observers **2.1 Who is an observer.** It's a structural fact, set by the kernel, not a name test in the switcher. - `capsule_birth_baby()` already computes `is_fleet_foundation` (Hera/Artemis/Hestia) for session pinning. The observer role reuses that. - Hera, born through `capsule_birth_mama()`, is marked where `kernel_main.c` registers her. - Nothing a VM executes can set or clear the role. **2.2 Not in the calculation.** - `sk_vm_switch_decide()` never offers an observer as a heat candidate. - `vm_physics_charge()` doesn't accrue observers' work heat. - `sk_vm_switch_signal_note_work_gained()` leaves observers out of the floor. - Proposed (ruling O-2): observers aren't charged **absolute** heat either. The reservoir doesn't heat itself by running. Participants still pull absolute heat off it through their own charges, and `retire` returns it, so fleet K stays conserved. **2.3 Observers act on events.** An observer is runnable only when it has an event: - **Mail:** its kernel-Hermes queue is non-empty (`MU-DONE`, `BLK-ATTACH`, `ELEVATE-REQUEST`, a relayed console line). - **Console input**, for Hera: `sk_console_key_available()`, as today. - **A device event**, for Hera: xHCI and USB attach or detach. See §4, ruling O-4. **2.4 When an observer runs (ruling O-1: the central question).** Proposed: **at the next clean boundary, an observer with an event goes ahead of the participants.** - The boundaries are the same owned checkpoints, trampoline points and idle point FABRIC-3.8 built. - Among several observers with events, the one waiting longest (the existing unique wait stamps) goes first, with no heat. - Once it has no events left it parks, and the participants' physics resumes. Why this isn't a scheduler: - There is no run queue, no priority number, and no ordering computed or kept. - It is a **role** (environment versus system), not a rank among peers. - Observers never compete with participants on the same scale; they respond to what happens. - The honest risk: an observer with a long event (a heavy command typed at Hera's own prompt) holds the CPU until it finishes, because nothing displaces an observer. §4 lists this. Work meant to share the CPU belongs in a participant. A user's commands already go to their own WIREBIND user VM, which is a participant. The alternative, observers run only when no participant has work, is pure but brings back C-4 (α)'s starvation: under load, the console, USB and storage wait until every worker is idle. **2.5 Hera's own mail is delivered at the idle point, not on the timer.** - Today her queue is drained by `sk_repl_idle()`'s pump at the `SK_IDLE_BEAT_INTERVAL` cadence (timer-paced; the last such delivery left, `FABRIC-3.8.md` Stage I). - As an observer that acts on events, her mail must be acted on promptly, so her drain moves to `sk_vm_idle_point()`. - It keeps the readline `n > 0` mid-edit gate, so a drained payload never prints into a line being typed. ## 3. What this lets the DoE become **The driver becomes event-driven. Hera never waits in a loop.** - `DOE` sets up the campaign and starts trial 1 (birth all, send all), then returns to the prompt. - Each worker's final `SEND` delivers `MU-DONE` to Hera as mail. - She acts on it at her idle point: increments the count, and on the last one ends the trial (`KILL` all, marker, persist) and starts the next. - After the last trial she prints `MU-CAMPAIGN: complete`. - `MU-WAIT-ALL` is deleted. This is the §3.9 design's own "ordinary words" rule, applied: Hera reacts to messages, which is what messages are for. **The heartbeat rows then measure the system, not the environment.** - An observer produces rows only while acting on an event. - Proposed (ruling O-3): its rows stay in the CSV, tagged by `vm_name` as today, and the analysis filters by role. This keeps the CSV layout unchanged. The alternative is to suppress them. ## 4. Known limits and open questions - **O-4: device servicing.** xHCI event polling and USB attach/detach run in `sk_repl_idle()` at the timer-paced `SK_IDLE_BEAT_INTERVAL`, and only when Hera reaches her idle point. - Under participant load, Hera reaches it only when she has another event, so USB goes unserviced. A USB keyboard is a device event that can only be *seen* by polling. - Options: (a) treat "the device-poll interval elapsed" as a Hera event; that's I/O housekeeping triggering a switch, not a scheduling decision, but it is timer-paced. (b) Move xHCI polling to an interrupt path. (c) Accept it for now; the DoE doesn't need USB mid-run. - Proposed: (c) for the relaunch, (b) as later work. - **A long event on an observer holds the CPU** (§2.4). Accepted by the role design: heavy work belongs in participants. - **Artemis and Hestia become observers too.** - Artemis's storage work (attach, block sync) and Hestia's framebuffer are responses to events, which fits. - If a future Tripod duty is compute-heavy, it would have to move to a participant. - **Stage G's evidence** (two participants interleave) and C-b's walk-order property are unaffected: observers aren't candidates. - **The WIREBIND relay** stays participant-delivered: the user VM gets the console line as mail and is switched to by heat among participants. Only Hera's own forwarding is observer work. ## 5. What this supersedes - **Absolute-heat-share charge** (uncommitted: `capsule_vm_physics.c/.h` working-tree changes on 2026-09-24). No longer needed once Hera isn't compared. Proposed: discard it. - **`MU-WAIT-ALL`**, and every busy-wait in the DoE driver. - **The C-4 (α) consequence** recorded at C-b, where the console got no turn under worker load. An observer with console input goes ahead of the participants at the next boundary. ## 6. Rulings needed from Captain Bob 1. **O-1:** observers with an event go ahead of participants at the next clean boundary (proposed), or observers run only when no participant has work. 2. **O-2:** observers aren't charged absolute heat either (proposed), or they keep the C-a absolute charge and are only left out of work heat. 3. **O-3:** observer heartbeat rows kept and tagged, filtered in analysis (proposed), or suppressed. 4. **O-4:** device servicing under load: (c) accept for the relaunch and (b) interrupt-driven later (proposed), or (a) treat the device-poll interval as a Hera event. 5. **Discard the uncommitted absolute-heat-share charge** (proposed), or keep it as a safety net. **RULED 2026-09-24, Captain Bob: "all as proposed."** O-1 through O-4 and the discard (5) all go as proposed above. ## 7. Raised 2026-09-24: messaging should flow on its own (OPEN, not yet designed) **Captain Bob, verbatim:** *"Another potential defect is perhaps in messaging itself. We shouldn't have to actually specifically decide to send a message … that should be autonomous by the operating system itself … The messages should just flow. … However, I would still have a manual method of sending and receiving messages … I should be able to create channels manually, I should be able to destroy channels manually, I should be able to inject messages into the queue, all of that should be manual, but also able to operate autonomously."* **What exists today** (traced, not proposed): - **The kernel side is complete in C:** `sk_hermes_channel_create/destroy/subscribe/unsubscribe/ is_member/member_count`, `sk_hermes_publish`, `sk_hermes_send_one`, and the negotiation calls (`channel_request/respond/close/open_policy`), in `kernel_hermes.c`. - **Only `SEND` reaches FORTH.** There are also the fixed-purpose `KH-BLK-ATTACH-SEND` and `KH-ELEVATE-SEND`. There is no FORTH word to create or destroy a channel, subscribe, publish, or inspect a queue. - **Every message today is sent because some code decided to send it:** the console relay, BLK-ATTACH, `SEND` in a job. Nothing is routed by the OS on its own. **Two parts, which separate cleanly:** - **Manual.** FORTH words over the existing C API: create/destroy a channel, subscribe and unsubscribe, publish, inject a message into a queue, and inspect queues. Mechanical: mostly exposure, not new mechanism. The ACL decides who may use them (`ACL.4th`, never C). - **Autonomous.** What should flow without anyone deciding, and on what trigger, is a real design question. Candidates to discuss: - events the OS already knows about (a VM born, killed, parked idle; a device attached); - results a VM leaves on its stack or in a known place, routed to whoever subscribed; - heat/physics events routed to observers, which fits "observers act on events". Not designed. It needs Captain Bob's framing first. **Relation to the O stages:** independent of O-B to O-D. The event-driven DoE driver (O-C) is one concrete case: a worker's completion notice is today a `SEND` in the job text, and could become an OS event ("worker parked idle after its job") if autonomous flow lands first.