FABRIC-3.5.md §XVIII: the Console component designed in full
Console is three layers and only the middle one is new: the HAL fabric (~98 KB of C) is unchanged, the per-attach proxies are unchanged, and Console the VM is a capsule rather than a mechanism. The finding that shapes the design is that 1,051 lines of Console vocabulary already exist in the wrong dictionary. fabric.4th's own header calls it "Console drawing-fabric coordinate machinery" and says outright that it is the FORTH-side policy over the C pixel primitives -- and it loads into Hera, along with font.4th, from init.4th block 2049. Moving both to capsules/console/init.4th is a pure relocation and the clearest evidence that the fabric wants an owner: it already has the vocabulary, just attached to the wrong VM. PLOT/FB-WIDTH/FB-HEIGHT registration moves with it; the implementations do not change. Records the invariant that constrains everything else. console.h:220-224 states that console.c must have no dependency on capsule or WIREBIND logic, calling it a real layering violation rather than a style preference. So Console the VM cannot be built by making console.c VM-aware: ownership flows one way, and where the HAL genuinely needs something VM-shaped it takes the shape already established by console_set_user_prefix_provider() -- a registered callback, never an include. Console's ownership is therefore by vocabulary and registration, not enforcement, which is weaker than it sounds and exactly right. Carries the headless-until-login invariant onto this second path: Console is born at boot, a console session is not, and Console's birth must not touch g_wirebind_attached_username or mint a proxy. Same rule §XXXII.2 imposed on unattended birth, cheap to hold and easy to violate with a well-meaning startup line. Notes what Console does not own, since a component owning "the bind point" attracts responsibilities belonging elsewhere, and records that the three Tripod legs have three different failure characters -- Console degrades gracefully because the fabric is HAL C and survives its owner, which is why only Hermes needed the semaphore. One genuinely open design question remains: whether agent-VM binding widens the ~user convention or takes a sibling word. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkM1zHGvBerLF6aqkHPweP
This commit is contained in:
+197
@@ -1378,3 +1378,200 @@ first bullet is a placement question; item 16 is a build-time check. Every load-
|
||||
architectural question this document opened — what Hermes becomes, what the Tripod is, what
|
||||
`BIRTH` means, who owns death, who owns turn order, what survives, what shutdown is — is now
|
||||
ruled.
|
||||
|
||||
---
|
||||
|
||||
## XVIII. The Console component, designed in full (2026-09-18)
|
||||
|
||||
§XVII settled *what* the Console leg is. This section designs the component. Everything below
|
||||
traced 2026-09-18 against `e56974e`; decisions are marked, proposals are marked, and open
|
||||
questions are marked.
|
||||
|
||||
### XVIII.1 — Console is three layers, and only the middle one is new
|
||||
|
||||
| Layer | What | Where it lives today | Change |
|
||||
|---|---|---|---|
|
||||
| **0 — the fabric** | Raw output: framebuffer, VT100, glyph raster, UART | `hal/console.c`, `framebuffer.c`, `vt100.c`, `font_8x16.c` (~98 KB C) | **None.** Stays kernel HAL. |
|
||||
| **1 — Console the VM** | Tripod leg. Owns fabric *policy*, is the bind point | **Does not exist** | **New — and it is a capsule, not a mechanism.** |
|
||||
| **2 — console proxies** | Per-attach relay VMs, one per bound user/agent | `capsule_console_birth()` | **None**, except their birther becomes Console. |
|
||||
|
||||
The design is almost entirely layer 1, and layer 1 is mostly a *relocation* of vocabulary that
|
||||
already exists in the wrong dictionary (§XVIII.3).
|
||||
|
||||
### XVIII.2 — The constraint that shapes everything: the HAL must never know a VM exists
|
||||
|
||||
**This is not a preference, it is a defended invariant with a documented rationale**
|
||||
(`include/starkernel/console.h:220-224`, verbatim):
|
||||
|
||||
> `console.c` is a clean HAL module with no dependency on capsule/WIREBIND logic
|
||||
> (`zuse_session`, `capsule_wirebind_attached_username()`) — pulling either in directly here
|
||||
> would be a **real layering violation, not just a style preference.**
|
||||
|
||||
So **Console-the-VM may not be implemented by making `console.c` VM-aware.** Ownership flows one
|
||||
way only: Console reaches *down* into the HAL; the HAL never reaches *up*.
|
||||
|
||||
**The sanctioned pattern for the cases where the HAL does need something VM-shaped already
|
||||
exists and should be reused rather than reinvented:** `console_set_user_prefix_provider()`
|
||||
(`console.h:231`) — a callback that lets `repl.c` supply the "user" half of the `[user@VMName]`
|
||||
prompt "without `console.c` knowing anything about VMs, sessions, or WIREBIND." Any further
|
||||
HAL→Console coupling this design needs takes that shape: a registered callback, never an
|
||||
include.
|
||||
|
||||
**Consequence, stated plainly:** Console's "ownership" of the fabric is by *convention,
|
||||
vocabulary and registration* — it is the VM that holds the drawing words — **not** by any
|
||||
enforcement inside `console.c`. That is weaker than it sounds and is exactly right: it keeps
|
||||
the HAL reusable and the layering intact.
|
||||
|
||||
### XVIII.3 — Console's dictionary: 1,051 lines of Console vocabulary currently live in Hera
|
||||
|
||||
**The most concrete finding in this section.** `capsules/fabric.4th`'s own header reads:
|
||||
|
||||
> `fabric.4th` — **Console drawing-fabric coordinate machinery.** `FABRIC-0.md` item 4.3.3.
|
||||
> 45-degree cavalier orthographic projection... Raw pixel write (`PLOT`/`FB-WIDTH`/`FB-HEIGHT`)
|
||||
> is C; **this capsule is the FORTH-side policy on top of it.**
|
||||
|
||||
It is named Console's fabric, it *is* the FORTH-side fabric policy — and it loads into **Hera's**
|
||||
dictionary (`capsules/init.4th` block 2049: `S" fabric.4th" EXEC`, `S" font.4th" EXEC`).
|
||||
|
||||
| Capsule | Lines | Loads into today | Should load into |
|
||||
|---|---|---|---|
|
||||
| `fabric.4th` | 319 | **Hera** (`init.4th` b2049) | **Console** |
|
||||
| `font.4th` | 733 | **Hera** (`init.4th` b2049) | **Console** |
|
||||
| `turtle.4th` | 99 | `sdk.4th` (opt-in, not boot) | unchanged — it is SDK, not fabric |
|
||||
|
||||
**Plus the C primitives underneath:** `PLOT`, `FB-WIDTH`, `FB-HEIGHT`
|
||||
(`src/word_source/framebuffer_words.c:62-64`). Their *registration* moves to Console's word
|
||||
table; the implementations do not change.
|
||||
|
||||
**DECIDED (proposal — Captain Bob's call, but this is the direct consequence of §XVII.2):**
|
||||
`fabric.4th` and `font.4th` move from `init.4th` to `capsules/console/init.4th`. This is a pure
|
||||
relocation of 1,051 lines — the single most obviously-correct edit in the whole reshuffle, and
|
||||
the clearest evidence that the fabric wants an owner: it already *has* the vocabulary, just
|
||||
attached to the wrong VM.
|
||||
|
||||
**Parity consequence** (§III.5): Hera's `dict_hash` will shrink, Console's is new. Per §XX's
|
||||
standard, the property that matters is cross-architecture identity, not an unchanging absolute.
|
||||
|
||||
### XVIII.4 — Console's capsule personality
|
||||
|
||||
`capsules/console/init.4th` — a new directory beside `hermes/` and `artemis/`, and **the one
|
||||
genuinely new artifact this reshuffle creates.**
|
||||
|
||||
Contents, in load order:
|
||||
|
||||
1. `S" common:messaging.4th" EXEC` + `MSG-CD-INIT` — Console is a Tripod leg and a full
|
||||
messaging participant. **Note this differs from the proxies**, which deliberately skip
|
||||
`COMMON-CH` (`capsule_console.c:23-26`: "a console's own traffic is direct 1:1 with its
|
||||
paired user VM"). The *leg* subscribes; the *proxies* still do not.
|
||||
2. `S" fabric.4th" EXEC` and `S" font.4th" EXEC` — per §XVIII.3.
|
||||
3. Console's own bind vocabulary (§XVIII.5).
|
||||
4. A `WELCOME`/banner word, matching `hermes/init.4th`'s and `artemis/init.4th`'s shape.
|
||||
|
||||
**Block allocation is a real to-do, not a formality.** `mkcapsule`'s actual constraints, per
|
||||
§XXXII.2's correction: block range **`[2048, 5120)`** and a hard **16-content-line-per-block**
|
||||
cap (*not* the 1024-byte framing `.claude/CLAUDE.md` still describes — that doc error is
|
||||
outstanding). **Block 4997 is already taken** by the proxy's own C string literal
|
||||
(`capsule_console.c:28-31`), so Console's range must avoid it. Allocate against
|
||||
`capsule-reserved.txt` and verify with `mkcapsule --lint capsules/` (§XXIV's collision
|
||||
machinery covers this; it is blind to content, only to numbers).
|
||||
|
||||
### XVIII.5 — The bind point: flow and vocabulary
|
||||
|
||||
**Binding, end to end, after the reshuffle:**
|
||||
|
||||
```
|
||||
human attaches thumbdrive agent VM needs a console
|
||||
│ │
|
||||
▼ ▼
|
||||
WIREBIND path CONSOLE-ATTACH
|
||||
│ │
|
||||
└──────────► Console ◄───────────┘
|
||||
│
|
||||
BIRTH a proxy (§XV.1 makes this legal:
|
||||
│ any VM may birth)
|
||||
▼
|
||||
proxy paired to target
|
||||
(VM-NAME-REG, unchanged)
|
||||
```
|
||||
|
||||
- **`CONSOLE-ATTACH ( name-c name-u -- ok? )` already exists and is live-verified** (§I.6,
|
||||
closed 2026-09-16). It resolves the target's liveness *before* birthing, so a typo refuses
|
||||
cleanly with no orphaned VM. **Keep it exactly as is.** The change is *who runs it*: today
|
||||
the three `capsule_console_birth()` call sites run in Hera's or the caller's context
|
||||
(`capsule_wirebind.c:245`, `mama_forth_words.c:1591`, `:2015`). Under this design Console is
|
||||
the birther.
|
||||
- **This is why Console needs `BIRTH` registered** (§XIII.6) — binding *mints a proxy*, and
|
||||
minting is `BIRTH`. Already legal per §XV.1.
|
||||
- **Mechanically this already works:** two of the three call sites pass `vm->stadium_vm_id` —
|
||||
whichever VM invoked — so parentage is already generic (§I.5, §XIII.6). Only registration
|
||||
changes.
|
||||
|
||||
**OPEN — agent-VM binding and the `~user` convention** (§V.3.1, still unresolved). The pairing
|
||||
check in `sk_repl_dispatch_line()` reconstructs the target as `console_get_vm_name() + "~user"`
|
||||
— a convention built for *human at a console → identity VM*. A GPIO VM (`FABRIC-4.md` §2) is
|
||||
not a `~user` identity. §XXXII.2 records that a console named anything else "silently falls
|
||||
back to direct interpretation with no error," caught live. **Two shapes, neither chosen:**
|
||||
(a) widen the convention so the suffix is a property of the *binding*, not hardcoded; (b) give
|
||||
agent binding its own word alongside `CONSOLE-ATTACH`. **(a) is preferable on
|
||||
no-bespoke-gate grounds but touches a live, bug-prone path; flagged rather than decided.**
|
||||
|
||||
### XVIII.6 — Headless-until-login survives, and the invariant that makes it survive
|
||||
|
||||
**Console the leg is born at boot. A console session is not.** These must not be conflated, or
|
||||
§VIII.1's ratified headless-until-login policy reopens — the exact failure §XXXII.2 warned
|
||||
about for unattended birth.
|
||||
|
||||
**INVARIANT, to be stated in whatever code implements Console:**
|
||||
|
||||
> Console's birth at boot must not set `g_wirebind_attached_username`, must not cause
|
||||
> `sk_console_identity_present()` (`repl.c:122`) to report an identity, and must not mint a
|
||||
> proxy. Console owns the fabric from boot; it presents nothing until something binds.
|
||||
|
||||
This is the same invariant §XXXII.2 imposed on unattended identity birth, applied to a second
|
||||
path. It is cheap to hold — Console births no proxy until asked — but it is exactly the kind of
|
||||
thing that gets violated by a well-meaning "initialise the console at startup" line.
|
||||
|
||||
### XVIII.7 — What Console does *not* own
|
||||
|
||||
Stated because a component that owns "the bind point" attracts responsibilities that belong
|
||||
elsewhere, and this document has already had to defend against exactly that (§XV.3):
|
||||
|
||||
- **Not turn order.** Nothing owns it (§XV.3).
|
||||
- **Not routing.** That is kernel-Hermes (§III), which sits *below* Console.
|
||||
- **Not the lifecycle of anything but its own proxies.** Console births proxies; it does not
|
||||
birth, kill, or supervise identity VMs. Authority flows down the birth graph only (§IX.2).
|
||||
- **Not the prompt's user half.** That stays `repl.c`'s, supplied to the HAL via the existing
|
||||
provider callback (§XVIII.2). Moving it into Console would be the layering violation
|
||||
`console.h` explicitly names.
|
||||
|
||||
### XVIII.8 — Console's own failure behaviour
|
||||
|
||||
Console is a Stadium-floor VM **above** the routing layer, so §VIII.2's rule applies without an
|
||||
exception: **Console emits `SOS`**; only Hermes uses the semaphore. Its clean shutdown is
|
||||
§XVI's: forced `blk_flush(0)`, then `BYE`.
|
||||
|
||||
**A pleasant property worth recording: Console's death degrades gracefully by construction.**
|
||||
Because layer 0 is HAL C (§XVIII.1) and ownership is by convention rather than enforcement
|
||||
(§XVIII.2), a dead Console leaves the framebuffer, VT100 and UART fully functional — the fabric
|
||||
simply becomes ownerless again, which is precisely today's status quo. The kernel can still
|
||||
print. **This is the opposite of Hermes**, whose death takes the transport with it. So the
|
||||
Tripod's three legs have three genuinely different failure characters: Artemis's death costs
|
||||
storage arbitration, Console's costs only fabric *policy*, Hermes's costs the transport itself —
|
||||
which is why only Hermes needed the semaphore.
|
||||
|
||||
### XVIII.9 — Punch list for Console
|
||||
|
||||
Design items, in dependency order. **No code authorized.**
|
||||
|
||||
1. ⬜ Ratify §XVIII.3's relocation: `fabric.4th` + `font.4th` move from `init.4th` to
|
||||
`capsules/console/init.4th`; `PLOT`/`FB-WIDTH`/`FB-HEIGHT` registration moves to Console.
|
||||
2. ⬜ Allocate Console's block range against `capsule-reserved.txt`, avoiding 4997; verify with
|
||||
`mkcapsule --lint` (§XVIII.4).
|
||||
3. ⬜ Decide §XVIII.5's agent-binding shape: widen the `~user` convention, or a sibling word.
|
||||
**The only genuinely open design question in this section.**
|
||||
4. ⬜ Confirm Console in the `is_fleet_foundation` triple (`capsule_birth.c:793-796`) and its
|
||||
birth at `kernel_main.c:865`, replacing Hermes's (§XVII.4).
|
||||
5. ⬜ Handle the `doe_log.c` CSV schema change (§XIII.3) — still the expensive consequence.
|
||||
6. ⬜ State §XVIII.6's headless invariant in the implementation.
|
||||
7. ⬜ **Not in this reshuffle:** the `console_set_vm_name()` ownerless-global fix (§XVII.3) is
|
||||
now *available* once Console exists, but remains out of scope. Flagged, not scheduled.
|
||||
|
||||
Reference in New Issue
Block a user