The third Tripod leg's first real file (FABRIC-3.5.md SII/SIV). Blocks
4986-4987 of the 4986-4996 allocated in task 1.1 (b624133a): WELCOME
banner, then common:messaging.4th load + MSG-CD-INIT + COMMON-CH join
on slot 11, modeled on hermes/init.4th's equivalent shape. No fabric.4th/
font.4th yet -- tasks 1.6/1.7. Not yet birthed -- task 1.4.
Slot 11 is a fresh routing-table slot, not Hermes's slot 1: Hera/
Hermes/Artemis hold 0/1/2 and identities hold 3-10 (messaging.4th:
78-85), and Hermes stays live and fleet-foundation through Phase 1-3
(SXXXIV.4) so his slot isn't free yet.
Deliberately did not add a VM-NAME-REG entry for "Hestia" to
messaging.4th's VM-NAMES-INIT -- Phase 1's own gate is "messaging
untouched" and that table lives in messaging.4th. Consequence: once
birthed, Hestia is COMMON-CH-reachable by raw slot but not yet
VM-EXEC-addressable by name. Flagged in FABRIC-3.6.md rather than
decided -- whichever task first needs name lookup settles where that
one-line addition goes, and it will need its own authorization since
it touches a file Phase 1 promised not to.
mkcapsule --lint capsules/ clean, 38 files / 0 violations. MANIFEST.md
given a matching entry. Three-arch boot clean: amd64/aarch64/riscv64
all reach [zuse@Hera] ok>, zero UNKNOWN WORD, byte-identical to task
0.7's baseline (same dict_hash triple) -- exactly as expected, since an
unbirthed capsule is inert.
Authorized by Captain Bob ("YES").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
469 lines
33 KiB
Markdown
469 lines
33 KiB
Markdown
# FABRIC-3.6.md — the Tripod/kernel reshuffle: execution log
|
||
|
||
> ## START HERE — session handoff
|
||
>
|
||
> **If you have just been told "go build it", read this section, then `FABRIC-3.5.md`'s §XLI,
|
||
> then start at task 0.0 below. Do not re-derive the design — it is settled.**
|
||
>
|
||
> **Where the code is.** This repo is **LithosAnanke, on the Gitea instance at
|
||
> `gitea.strshipos.com`, repo `admin/LithosAnanake`** — Captain Bob has the credentials.
|
||
> **Confirm you are in the right repo before anything else.** `git remote -v` must show
|
||
> `gitea.strshipos.com/admin/LithosAnanake`. **Nothing outside Gitea is this project.** (The
|
||
> handoff was authored in a container whose default working directory was a *different*, empty
|
||
> repo on an unrelated remote — if you ever see that, you are in the wrong place.) `master` is
|
||
> the sole production line. Work on branch **`claude/starshipos-tripod-kernel-reshuffle-itbjns`**
|
||
> (a clean fast-forward of `master` at `e56974e`; **documentation only — no reshuffle code has
|
||
> been written**. The branch head is the source of truth; do not trust a commit id quoted here).
|
||
>
|
||
> **The two documents.** `FABRIC-3.5.md` is the **design record and is authoritative** — every
|
||
> ruling, with its reasoning and evidence, §I–§XLIII. **This** document is the execution log.
|
||
> Rulings are cited here, never restated. **If a task proves a ruling wrong, record the finding
|
||
> here and amend `FABRIC-3.5.md` — never silently diverge.**
|
||
>
|
||
> **First action: task 0.0**, the three-ISA baseline. It is a gate, not a formality — see its
|
||
> own rationale below. **Nothing else starts until it is recorded.**
|
||
>
|
||
> **Five traps this project's own history proves are real. A fresh session will walk into these:**
|
||
>
|
||
> 1. **Silent failure is the dominant mode here.** `FABRIC-3.5.md` §XXXV.0 lists four
|
||
> independent instances. Most relevantly: *"a switch storm and a healthy idle REPL produce an
|
||
> identical serial log."* **A green boot is weak evidence.** Name the specific observation
|
||
> that proves a task worked, before running it.
|
||
> 2. **`grep` cannot establish capsule reachability.** Capsules are birthed by name from runtime
|
||
> strings. A reference count over `capsules/` and `src/` put the six live `init-l8-*`
|
||
> capsules at **zero references**; including `experiments/` found 18–19 each. §XXII.2. **Use
|
||
> the three routes, never grep alone.**
|
||
> 3. **`fleet_conserved` cannot see Stadium heat.** The two heat accountings are entirely
|
||
> decoupled (§XXXIX). A leaking message allocator leaves `fleet_conserved` reporting a serene
|
||
> `1`. **Stage B's evidence is the ledger plus `stadium_conserved()`, never `fleet_conserved`.**
|
||
> 4. **`dict_hash` *changing* is expected; `dict_hash` *diverging* across architectures is the
|
||
> stop condition.** §XXXIV.6. Do not "fix" a changed hash.
|
||
> 5. **Documentation in this repo drifts from the code — trust the code.** `.claude/CLAUDE.md`
|
||
> carried four stale claims; **all four were corrected 2026-09-19 (§XLIV) and it is now
|
||
> reliable.** Others are not: `capsules/MANIFEST.md` still describes block 4055 as a live
|
||
> "immutable ABI" that `FABRIC-2.md:2773` declared stale, and still misdescribes block 2049.
|
||
> `FABRIC-0.md` §25.7 lists resolved defects as open. **Where a document and the code
|
||
> disagree, the code wins — and record the drift rather than working around it.**
|
||
>
|
||
> **Blocked, and not to be worked around:** Phase 3 needs three decisions from Captain Bob —
|
||
> **B1** channels (one membership or negotiation), **B2** the `SK_SWITCH_MAX_SLOTS` ceiling of
|
||
> 16, **B4** the payload bound against `INPUT_BUFFER_SIZE` 1025. **All design is complete; these
|
||
> are rulings, not investigations.**
|
||
>
|
||
> **Do not:** create branches, stash, fix defects found in passing, bundle tasks into one
|
||
> commit, or start any task without explicit authorization. Captain Bob's Law,
|
||
> `.claude/CLAUDE.md`.
|
||
|
||
**Status: LIVING WORKING DOCUMENT, opened 2026-09-19.** This is the **execution** record for
|
||
the reshuffle designed in `FABRIC-3.5.md`. Work is tracked, annotated and closed here.
|
||
|
||
**Why this is a separate document, per the series' own rule.** `FABRIC-1.md` closed at **4,420
|
||
lines** for a stated reason: *"continuing to append here made the still-open work hard to find."*
|
||
`FABRIC-3.5.md` stands at **4,452 lines** with 40+ open punch items scattered among hundreds of
|
||
settled rulings — **it has crossed the same threshold, for the same reason.** Annotating a task
|
||
list inside it, commit by commit, would bury the design record it exists to be.
|
||
|
||
**The split of responsibility is strict, and stated because `FABRIC-3.5.md` §XXXI found that
|
||
documents in this series lose track of each other:**
|
||
|
||
| | `FABRIC-3.5.md` | `FABRIC-3.6.md` (this) |
|
||
|---|---|---|
|
||
| **Holds** | The design record — every ruling, its reasoning, its evidence | The work — tasks, results, dates, commits |
|
||
| **State** | Design phase closed; archival close at `v2.1.0` (§XXVI.5) | Living until the work is done |
|
||
| **On a conflict** | **Authoritative** | Defers, and records the discrepancy |
|
||
|
||
**Design rulings are never restated here, only cited** (`§XXXIV.2`, `§XL.4`, …). If a task needs
|
||
a rule explained, read `FABRIC-3.5.md`. **If executing a task proves a ruling wrong, that is a
|
||
finding: record it here and amend `FABRIC-3.5.md` there** — never silently diverge.
|
||
|
||
**The checkbox convention is deliberate.** `FABRIC-3.5.md` §XXXI.2 found the series'
|
||
carry-forward discipline was mechanically auditable (`grep -c '\- \[ \]'`) up to `FABRIC-2.md`,
|
||
and **broke at `FABRIC-3.md`, which uses no checkboxes at all** — after which "is anything still
|
||
open?" stopped being a `grep` and became a reading exercise. **This document restores the
|
||
convention**, so that question stays answerable by machine.
|
||
|
||
---
|
||
|
||
## Standing rules
|
||
|
||
Apply to **every** task, from `.claude/CLAUDE.md` and `FABRIC-3.5.md` §XXXIV:
|
||
|
||
- **One task, one commit.** No bundling.
|
||
- **Acceptance is the three-architecture QEMU boot** — `clean qemu`, amd64/aarch64/riscv64, one
|
||
at a time, in the foreground. Logs committed. There is no other acceptance test.
|
||
- **`dict_hash` changing is expected. `dict_hash` *diverging* between architectures is a stop
|
||
condition** (§XXXIV.6).
|
||
- **`mkcapsule --lint capsules/` clean** after any capsule change.
|
||
- **No task starts without explicit authorization.** Captain Bob's Law.
|
||
- **Report, don't fix.** A defect found while doing a task is recorded here, not repaired in
|
||
passing.
|
||
|
||
## Annotation convention
|
||
|
||
```
|
||
- [x] 0.2 — Strip common/msg.4th
|
||
2026-09-DD · commit abc1234 · 3-arch boot clean, lint 0 violations
|
||
note: <anything surprising; a finding gets its own entry below>
|
||
```
|
||
|
||
Mark `[~]` for started-not-finished, with what is outstanding. **Never mark `[x]` on a task
|
||
whose check did not actually run** — `FABRIC-3.5.md` §XXXV.6 records that declaring done too
|
||
early is this project's most repeated failure.
|
||
|
||
---
|
||
|
||
## Pre-flight — establish the baseline before anything changes
|
||
|
||
**Branch state at open (2026-09-19):** `claude/starshipos-tripod-kernel-reshuffle-itbjns`, head
|
||
`3a4e5cf`, **working tree clean, pushed, 33 commits ahead of `master`** — all documentation, no
|
||
code. `master` is unmoved at `e56974e`, so the branch remains a clean fast-forward. **Execution
|
||
starts from this commit.**
|
||
|
||
- [x] **0.0** — **Three-ISA baseline smoke test on the unmodified branch.**
|
||
`make -f Makefile.starkernel ARCH=<arch> clean qemu` for amd64, aarch64, riscv64 — one at
|
||
a time, in the foreground, per `.claude/CLAUDE.md`.
|
||
*Check:* all three reach `zuse)ok>`; zero `UNKNOWN WORD`; logs committed under
|
||
`logs/<timestamp>/<arch>/`; **record each `dict_hash` and confirm the three are
|
||
identical.**
|
||
2026-09-19 · `logs/20260919-130023/amd64/`, `logs/20260919-130137/aarch64/`,
|
||
`logs/20260919-130319/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`.
|
||
`dict_hash` identical across all three: Hera (`PARITY:M7.1a`) `0x6824fe5993239838`,
|
||
Hermes `0x062252c4da6858da`, Artemis `0xed80117724c26f36`.
|
||
note: **first attempt confounded, see findings log** — `logs/20260919-124835/amd64/` and
|
||
`logs/20260919-124952/aarch64/` (kept, not deleted) show Artemis's `dict_hash` diverging
|
||
(`0xed80117724c26f36` vs `0x93d6e815354b61c0`) purely because `disk/artemis.img` is shared
|
||
across all three ISAs' `qemu` targets (`FABRIC-3.md` §XXXV.2) and the second run resumed
|
||
the first run's already-formatted disk instead of formatting its own. Restored
|
||
`disk/artemis.img` and `disk/thumbdrives/zuse-thumb-ident.img` to their committed blank
|
||
state (`git checkout --`) before each of the three reruns above to remove the confound.
|
||
|
||
**Why this is a gate and not a formality.** Every task in this document takes the
|
||
three-architecture boot as its acceptance (§XXXIV). **Without a known-good baseline captured
|
||
first, the first red boot is ambiguous** — pre-existing fault or something task 0.2 just did?
|
||
This project has been bitten by exactly that ambiguity before (`FABRIC-3.md` §XXVI: "the
|
||
lockdown was never broken — wrong VM tested"). The baseline is what makes every later
|
||
acceptance run interpretable, and the recorded `dict_hash` triple is the reference every
|
||
subsequent §XXXIV.6 divergence check compares against.
|
||
|
||
**Run it yourself — you are expected to.** Captain Bob confirmed (2026-09-19) that execution
|
||
happens on his PC with the full toolchain installed, so **the session reading this can and
|
||
should run task 0.0 directly**, once authorized. Verify first that `qemu-system-x86_64`,
|
||
`qemu-system-aarch64`, `qemu-system-riscv64`, the aarch64/riscv64 cross-compilers and
|
||
OVMF/AAVMF are all present; **if any are missing you are not on the intended machine — stop and
|
||
say so rather than improvising a partial test.**
|
||
|
||
*(Historical note: this document was authored in a container with none of that toolchain, which
|
||
is why task 0.0 was written but never run. Do not take its unchecked state as a prior failure —
|
||
it has simply not been attempted.)*
|
||
|
||
---
|
||
|
||
## Phase 0 — Preparation (no behaviour change)
|
||
|
||
**Gate:** all three architectures boot to `zuse)ok>`, `stadium_conserved()` true, no
|
||
`UNKNOWN WORD`.
|
||
|
||
- [x] **0.1** — Establish Category A reachability by §XXII.2's three routes (boot path, tooling,
|
||
baked capsule directory). **Never by grep alone.**
|
||
*Check:* a written list naming the route that proves each entry dead.
|
||
2026-09-19 · investigation only, no code changed. Checked by all three routes — a boot-path
|
||
trace of `init.4th`/`hera`/`hermes/init.4th`/`artemis/init.4th` for any `EXEC`/`S" name"`
|
||
load, an experiments/tools/docs invocation search, and confirming presence in the baked
|
||
capsule directory doesn't by itself make a name reachable if nothing constructs it at
|
||
runtime:
|
||
|
||
| Candidate | Boot path | Tooling/experiments/docs | Verdict |
|
||
|---|---|---|---|
|
||
| `capsules/common/msg.4th` | zero `EXEC`/load sites in any boot-loaded capsule | zero invocations; its only two words `HERMES-ACK`/`HERMES-NACK` have zero callers anywhere; `messaging.4th` block 5033's own comment: "common:msg.4th's HERMES-ACK/NACK indirection is retired" | **DEAD** |
|
||
| `capsules/process.4th` | zero `EXEC` sites anywhere | zero invocations; its four words `SPAWN`/`PAUSE`/`RESUME`/`KILL-VM` have zero callers outside the file itself | **DEAD** |
|
||
| `SPAWN-EVENT` (constant, `messaging.4th`) | N/A — a constant, only ever defined, never read by name | zero invocations by name anywhere | **DEAD** |
|
||
|
||
Both files are present in the baked capsule directory (`mkcapsule` build log: `[p]
|
||
common:msg.4th`, `[p] process.4th`) — noted per §XXII.2 that presence alone proves
|
||
nothing; it only means nothing constructs either name at runtime to reach them, which the
|
||
other two routes confirm.
|
||
|
||
finding: `EVENT-EMIT`/`EVENT-WAIT`/`EVENT-DRAIN` (`messaging.4th`, Category B, staying)
|
||
have one caller beyond `process.4th` that §XXXIII.3 missed — `tools/hermes_smoke.sh` calls
|
||
all three directly. This does not make them live: the script is already broken on its own
|
||
terms, referencing `capsules/core/init.4th` and `build/amd64/standard/starforth`, neither
|
||
of which exists in this repo, and calling the pre-rename `CD-INIT` word (`messaging.4th`
|
||
block 5033 renamed it to `MSG-CD-INIT`) — it cannot currently execute. Task 0.3's plan
|
||
stands unchanged; recorded because §XXXIII.3's "only other reference is `MANIFEST.md`"
|
||
was itself an undercount of exactly the kind §XXII.2 warns about, even though the
|
||
conclusion survives.
|
||
|
||
finding: `PAUSE-EVENT`/`RESUME-EVENT`/`KILL-EVENT` (`messaging.4th`) are exactly as
|
||
dead-by-name as `SPAWN-EVENT` — zero references anywhere outside their own definition;
|
||
`process.4th`'s calls pass bare numeric literals (`1`/`2`/`3`/`4`), never the constant
|
||
names. Task 0.4 only names `SPAWN-EVENT`; not expanding its scope here, but flagging that
|
||
the other three meet the identical bar for whoever picks up Category A stripping next.
|
||
- [x] **0.2** — Strip `capsules/common/msg.4th`. *Check:* 3-arch boot; lint clean.
|
||
2026-09-19 · `logs/20260919-131945/amd64/`, `logs/20260919-132054/aarch64/`,
|
||
`logs/20260919-132226/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`.
|
||
`mkcapsule --lint capsules/` clean, 38 files, 0 violations (was 39 before the strip).
|
||
`dict_hash` **unchanged** from the task 0.0 baseline on all three (Hera
|
||
`0x6824fe5993239838`, Hermes `0x062252c4da6858da`, Artemis `0xed80117724c26f36`) — expected,
|
||
not a defect: task 0.1 confirmed `msg.4th` was never `EXEC`'d into any VM's dictionary, so
|
||
removing the dead file from the baked capsule directory doesn't move anything actually
|
||
loaded. `capsule-reserved.txt` not yet touched — block 4055's range is returned in task 0.6
|
||
per the punchlist's own ordering. `MANIFEST.md`'s stale block-4055 entry not yet corrected
|
||
— bundled into task 0.5 alongside block 2049's correction, per the punchlist.
|
||
- [x] **0.3** — Strip `capsules/process.4th` (takes `EVENT-EMIT`/`-WAIT`/`-DRAIN` with it,
|
||
§XXXIII.3). *Check:* 3-arch boot; lint clean.
|
||
2026-09-19 · `logs/20260919-132914/amd64/`, `logs/20260919-133024/aarch64/`,
|
||
`logs/20260919-133156/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`.
|
||
`mkcapsule --lint capsules/` clean, 37 files, 0 violations (was 38). Deleted
|
||
`capsules/process.4th` outright and `messaging.4th`'s Block 5030 in full
|
||
(`EVENT-EMIT`/`EVENT-WAIT`/`EVENT-DRAIN` — a self-contained block, nothing else in it).
|
||
`dict_hash`: Hera's `PARITY:M7.1a` snapshot unchanged (`0x6824fe5993239838` — it fires
|
||
before any capsule loads, so capsule edits never move it); Hermes and Artemis both moved
|
||
(`0xa0f5c639a1228596`, `0x1650cb7153056160`) since both load `messaging.4th` — **identical
|
||
across all three architectures**, which is the actual property that matters (§XXII.4: every
|
||
strip changes `dict_hash`, cross-arch identity is the invariant). `capsule-reserved.txt`
|
||
still untouched (task 0.6); `MANIFEST.md`'s stale block-4055/2049 entries still untouched
|
||
(task 0.5, now unblocked since both 0.2 and 0.3 are done).
|
||
- [x] **0.4** — Strip `SPAWN-EVENT`. *Check:* 3-arch boot; lint clean.
|
||
2026-09-19 · `logs/20260919-133452/amd64/`, `logs/20260919-133559/aarch64/`,
|
||
`logs/20260919-133731/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`.
|
||
`mkcapsule --lint capsules/` clean, 37 files, 0 violations (unchanged — a one-line edit
|
||
within `messaging.4th`, no file added or removed). Removed the single `1 CONSTANT
|
||
SPAWN-EVENT` line only, per task 0.1's finding — `PAUSE-EVENT`/`RESUME-EVENT`/`KILL-EVENT`
|
||
left in place, matching the punchlist's stated scope. `dict_hash` moved for Hermes/Artemis
|
||
(`0x52801b746e063ae9`, `0x6ad92fa3935918d4`), identical across all three architectures;
|
||
Hera's `PARITY:M7.1a` snapshot unchanged as before. `capsule-reserved.txt` and
|
||
`MANIFEST.md`'s stale entries still untouched — Phase 0's strips (0.2–0.4) are now all
|
||
done; 0.5 and 0.6 are next.
|
||
- [x] **0.5** — Correct `capsules/MANIFEST.md` blocks 4055 and 2049 **as their files are
|
||
stripped** (§XXII.5). *Check:* manifest describes no file that no longer exists.
|
||
2026-09-19 · documentation only, no capsule content touched, `mkcapsule --lint capsules/`
|
||
still clean (37 files, 0 violations). Block 2049's justification rewrote its claimed
|
||
`init.4th` load list (`compudynamics`, `common:msg`, `fleet-k`, `process`) against the
|
||
file's actual current content — none of those four are loaded there; two were already
|
||
deleted (`compudynamics.4th`/`fleet-k.4th`, `9323f776`), two are this pass's own strips.
|
||
The standalone `common/msg.4th` and `process.4th` sections (former blocks 4055 and
|
||
4300–4301) were removed and folded into "Deleted capsules (historical)" alongside the
|
||
existing `compudynamics.4th`/`fleet-k.4th` entry, same convention. Unassigned Ranges table
|
||
updated: 4055–4059 and 4300–4399 now read as former-file ranges rather than "extension
|
||
space" for files that no longer exist. Verified every remaining `### \`*.4th\`` section in
|
||
the manifest names a file actually present on disk — zero stale entries left.
|
||
- [x] **0.6** — Return freed block ranges to `capsule-reserved.txt`. *Check:* lint clean.
|
||
2026-09-19 · added `4055-4059` (former `common/msg.4th`) and `4300-4399` (former
|
||
`process.4th`) to `tools/capsule-reserved.txt`, each noted as freed by this reshuffle's
|
||
strip rather than owned by non-capsule infrastructure (the file's usual purpose) —
|
||
documented as lifted, not permanent, once someone deliberately wants a range back.
|
||
`mkcapsule --lint capsules/` clean, 37 files, 0 violations, and `check_reserved_conflicts()`
|
||
(the hard build-gate that actually reads this file, `tools/mkcapsule.c:974`) passes clean
|
||
on a real `make -f Makefile.starkernel ARCH=amd64 all` — confirms the new entries don't
|
||
collide with anything currently baked. Documentation/registry only, no capsule content
|
||
touched, so no 3-arch boot run for this task. All of Phase 0's strips and documentation
|
||
corrections (0.1–0.6) are now done; `stadium_conserved()` (0.7) and the `PLOT`/`FB-WIDTH`/
|
||
`FB-HEIGHT` registration audit (0.8) remain before Phase 0's gate is fully met.
|
||
- [x] **0.7** — Add `stadium_conserved()`: `Σ patron + reservoir + consumed == Q48_ONE`,
|
||
**epsilon zero** (§XL.4, item 41). *Check:* true on a clean boot, all three arches.
|
||
2026-09-19 · `logs/20260919-135137/amd64/`, `logs/20260919-135240/aarch64/`,
|
||
`logs/20260919-135417/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`,
|
||
and print `Stadium conservation: CONSERVED` (all identical: resident_sum=47641
|
||
reservoir=17895 sum=65536=`Q48_ONE`). Implemented `int stadium_conserved(VMUuid vm_id)` in
|
||
`src/starkernel/vm/stadium.c` (declared `include/starkernel/vm/stadium.h`) as
|
||
`stadium_resident_sum(vm_id) + stadium_reservoir_peek(vm_id) == Q48_ONE` — the **two-term**
|
||
form, not three. §XL.4's `consumed` term is a Phase 2 kernel-Hermes ledger deliverable that
|
||
doesn't exist yet; nothing draws on any VM's Stadium quota today (Phase 2 task 2.2 is
|
||
literally where that wiring gets built), so `consumed` is honestly zero right now and
|
||
folding it in would be inventing Phase 2 state ahead of it existing. Doc comment on the
|
||
function says exactly this, so whoever builds Phase 2's ledger extends this function rather
|
||
than working around it. Wired into the existing per-VM boot diagnostic
|
||
(`stadium_words_print_boot_diagnostics()`, `kernel_main.c:810`, Hera only — the sole
|
||
existing call site) rather than adding a new one. No compiler warnings on either edited
|
||
file (checked with a forced recompile).
|
||
- [x] **0.8** — Audit that `PLOT`/`FB-WIDTH`/`FB-HEIGHT` are registered **nowhere** but the
|
||
table Hestia will own (item 33). *Check:* read-only; a second site is a defect to report.
|
||
2026-09-19 · read-only audit, no code changed. **Finding: they are reachable from every
|
||
VM today, not confined to one table.** Traced the two layers separately:
|
||
- **FORTH level** (the drawing vocabulary): `capsules/fabric.4th`/`font.4th` (which build
|
||
`CART-PLOT` etc. on top of raw `PLOT`) are `EXEC`'d only from `capsules/init.4th` — Hera
|
||
only. Neither `hermes/init.4th` nor `artemis/init.4th` load them. This layer matches
|
||
item 33's expectation and is exactly what tasks 1.6/1.7 move to `hestia/init.4th`.
|
||
- **C level** (the raw primitives themselves): `register_framebuffer_words()`
|
||
(`src/word_source/framebuffer_words.c:60-65`, registering `PLOT`/`FB-WIDTH`/
|
||
`FB-HEIGHT`) is called unconditionally from `register_forth79_words()`
|
||
(`src/word_registry.c:139`), which is itself called unconditionally from `vm_init()`
|
||
(`src/starkernel/vm/vm_bootstrap.c:263`) — **the generic per-VM bootstrap every VM goes
|
||
through, no identity check, no `#ifdef`.** So the raw primitives are already in every
|
||
VM's C-level dictionary at birth, Hestia or not.
|
||
- **Verified live, not just from source**: booted amd64 (`logs/20260919-140231/amd64/`)
|
||
and ran `S" FB-WIDTH ." S" Hermes" VM-EXEC` and the same against `Artemis` — **both
|
||
returned `1280`, not `UNKNOWN WORD`.** Neither loads `fabric.4th`, so this is the raw
|
||
C primitive itself answering, confirmed reachable from VMs that were never meant to
|
||
draw.
|
||
**Not fixed here** — read-only per the task, and this is exactly task 1.8's own stated
|
||
check ("a non-Hestia VM calling `PLOT` gets `UNKNOWN WORD` — verify positively"), which
|
||
this finding confirms currently **fails** and gives 1.8 a concrete starting state:
|
||
`register_framebuffer_words()`'s call site in `register_forth79_words()` will need to
|
||
become conditional on VM identity (or moved out of the universal bootstrap entirely),
|
||
not just the FORTH-level `fabric.4th` relocation tasks 1.6/1.7 already plan for.
|
||
|
||
**Phase 0 gate met**: all three architectures have repeatedly booted to `[zuse@Hera] ok>`
|
||
with `stadium_conserved()` true and zero `UNKNOWN WORD` across tasks 0.2–0.7. Phase 0 is
|
||
closed; Phase 1 (Hestia, messaging untouched) is next.
|
||
|
||
## Phase 1 — Hestia (messaging untouched)
|
||
|
||
**Gate:** Tripod is Hera/Artemis/Hestia **plus** Hermes; drawing works from Hestia and only
|
||
Hestia; headless policy intact.
|
||
|
||
- [x] **1.1** — Allocate Hestia's block range vs. `capsule-reserved.txt`, **avoiding 4997**.
|
||
*Check:* lint clean.
|
||
2026-09-19 · allocated **`4986–4996`** (11 blocks) for `hestia/init.4th`, documented in
|
||
`capsules/MANIFEST.md`'s Unassigned Ranges table (not `capsule-reserved.txt` — that file is
|
||
for blocks owned by non-capsule infrastructure, per its own header comment; a real capsule
|
||
allocation belongs in `MANIFEST.md`, same as every other infrastructure capsule). Checked
|
||
against the actual current occupancy, not the table's own stale blanket "4853+ OPEN" line:
|
||
`fabric.4th` occupies 4900–4924 and `font.4th` 4925–4985 already (both are their own
|
||
standalone capsule files, `EXEC`'d by `init.4th` but block-numbered independently of it —
|
||
task 1.6/1.7 relocate *which capsule EXECs them*, not their own block ranges), and 4997 is
|
||
the console proxy's hardcoded `Block 4997` string literal (`capsule_console.c:27-29`).
|
||
4986–4996 sits in the gap between the two, avoiding 4997 as required, with room for
|
||
Hestia's initial messaging-load/banner shape (task 1.2) plus moderate growth (bind
|
||
vocabulary, per §XVIII.5) without colliding with anything. No `.4th` file created yet.
|
||
`mkcapsule --lint capsules/` still clean, 37 files, 0 violations (documentation-only, no
|
||
capsule content changed).
|
||
- [x] **1.2** — Create `capsules/hestia/init.4th`: messaging load, `MSG-CD-INIT`, banner. **No
|
||
fabric yet.** *Check:* boots; Hestia not yet birthed.
|
||
2026-09-19 · `logs/20260919-162642/amd64/`, `logs/20260919-162747/aarch64/`,
|
||
`logs/20260919-162920/riscv64/` — all three reach `[zuse@Hera] ok>`, zero `UNKNOWN WORD`,
|
||
**byte-identical to task 0.7's baseline** (same `dict_hash` triple, same word counts) —
|
||
exactly as expected, since an unbirthed capsule is inert. Created
|
||
`capsules/hestia/init.4th` (blocks 4986–4987 of the 4986–4996 allocated in task 1.1, only 2
|
||
used so far): `WELCOME` banner (block 4986) plus `common:messaging.4th` load + `MSG-CD-INIT`
|
||
+ `COMMON-CH` join on **slot 11** (block 4987), modeled on `hermes/init.4th`'s equivalent
|
||
shape. `mkcapsule --lint capsules/` clean, 38 files, 0 violations. `MANIFEST.md` given a
|
||
matching entry (same pass, since the file now exists — unlike task 1.1, which deliberately
|
||
held off documenting a file that didn't exist yet).
|
||
|
||
**A scope decision, not a defect:** slot 11 is a fresh routing-table slot (0–2 are Hera/
|
||
Hermes/Artemis, 3–10 are the 8 identities, `messaging.4th:78-85`) rather than Hermes's slot
|
||
1, because Hermes stays live and fleet-foundation through Phase 1–3 (§XXXIV.4) — his slot
|
||
isn't free yet. **Deliberately did not add a `VM-NAME-REG` entry for "Hestia"** to
|
||
`messaging.4th`'s `VM-NAMES-INIT`, since Phase 1's own gate is "messaging untouched" and
|
||
that table lives in `messaging.4th`. Consequence: once birthed, Hestia will be
|
||
`COMMON-CH`-reachable by raw slot number but **not yet `VM-EXEC`-addressable by name**
|
||
(`S" Hestia" VM-EXEC` would fail to resolve). Flagged here rather than decided — whichever
|
||
later task first needs name lookup (birth itself, task 1.4, or something after) is where
|
||
that one-line addition belongs, and it will need explicit authorization since it touches
|
||
the file Phase 1 promised not to.
|
||
- [ ] **1.3** — Add Hestia to `is_fleet_foundation` (`capsule_birth.c:793-796`) — **four names,
|
||
Hermes retained** (§XXXIV.4). *Check:* 3-arch boot; Hermes still live.
|
||
- [ ] **1.4** — Birth Hestia in `kernel_main.c`, **alongside** Hermes's existing birth.
|
||
*Check:* registry shows both; `dict_hash` identical across arches.
|
||
- [ ] **1.5** — Register Hestia for switch signals (the `:1007` pattern). *Check:* boot clean;
|
||
**no switch storm** (§XXVIII.2's shape — and note it is invisible by default, §XXXV.0).
|
||
- [ ] **1.6** — Move `fabric.4th` from `init.4th` to `hestia/init.4th`. *Check:* Hera's dict
|
||
shrinks, Hestia's grows; cross-arch identity holds.
|
||
- [ ] **1.7** — Move `font.4th` likewise. *Check:* same.
|
||
- [ ] **1.8** — Move `PLOT`/`FB-WIDTH`/`FB-HEIGHT` registration to Hestia's table **only**.
|
||
*Check:* **positively verify** a non-Hestia VM calling `PLOT` gets `UNKNOWN WORD`.
|
||
- [ ] **1.9** — Assert §XVIII.6's headless invariant: Hestia's birth sets no
|
||
`g_wirebind_attached_username` and mints no proxy. *Check:* boot headless, no thumbdrive,
|
||
**no prompt appears**.
|
||
|
||
## Phase 2 — Allocator and audit (inert) — **the real go/no-go**
|
||
|
||
**Gate:** task 2.7. **If it fails, stop and re-plan. Do not proceed to Phase 3.**
|
||
|
||
- [ ] **2.1** — Kernel-Hermes message/membership structures, **wired to nothing, drawing no
|
||
heat**. *Check:* boot byte-identical; `dict_hash` unmoved.
|
||
- [ ] **2.2** — Allocate: pull `Q.SLOT` from the caller's reservoir; roll back on refusal.
|
||
*Check:* N allocs against a known reservoir; refusal at the right count.
|
||
- [ ] **2.3** — Release: return remaining heat via the eviction path. *Check:* reservoir
|
||
restored exactly for an undecayed message.
|
||
- [ ] **2.4** — The four counters: `held`, `pulled`, `returned`, `consumed` (§XL.4). *Check:*
|
||
each increments at exactly one site.
|
||
- [ ] **2.5** — Decay: apply, and **record the delta into `consumed`** (§XXXVII.3). *Check:*
|
||
`consumed` grows by exactly `heat_before − heat_after`.
|
||
- [ ] **2.6** — Self-audit: `held == pulled − returned − consumed`, **epsilon zero**. *Check:*
|
||
holds across the cycle; **deliberately corrupt a counter → audit fires on the first unit**.
|
||
- [ ] **2.7** — **Stage B proof** (§XXXIV.3 as corrected by §XXXIX.4): alloc/free cycle
|
||
verifying **(a)** the ledger and **(b)** `stadium_conserved()` before and after.
|
||
*Check:* both true, all three arches. **`fleet_conserved` is not evidence here** — it
|
||
cannot see Stadium heat (§XXXIX.1).
|
||
- [ ] **2.8** — Scan-based cross-check of the counters, diagnostics only, off the hot path
|
||
(§XXXVII.4). *Check:* scan agrees with counters.
|
||
|
||
## Phase 3 — Cutover — **BLOCKED**
|
||
|
||
**Not buildable until all three clear.** Shape once unblocked (§XXXIV.3): cut over
|
||
`BLK-ATTACH-EVENT` alone, then remaining types one at a time, under §XXXIV.2's partition rule —
|
||
one message type owned by exactly one layer, no message shared.
|
||
|
||
- [ ] **B1** — **Item 27**: channels — negotiation, or one broadcast membership? (§XXXIII.5
|
||
recommends the latter; unruled.)
|
||
- [ ] **B2** — **Item 32**: `SK_SWITCH_MAX_SLOTS` is 16 and §XXXII made the switcher the sole
|
||
mover of control. Constant bump or table redesign?
|
||
- [x] **B3** — **CLEARED 2026-09-19 by `FABRIC-3.5.md` §XLIII**: the target drains its own
|
||
queue at its own outermost interpret checkpoint; kernel-Hermes publishes and never
|
||
dispatches. Reuses `sk_vm_at_outermost_interpret()` and the Stage 3 checkpoint.
|
||
- [ ] **B4** — **Item 44**: payload bound or chunking against `INPUT_BUFFER_SIZE` 1025
|
||
(§XLIII.6.1). Decide before Phase 3.
|
||
|
||
## Phase 4 — Category B strip
|
||
|
||
Only after every live type is cut over. **Hermes leaves `is_fleet_foundation` and
|
||
`kernel_main.c` here, not earlier** (§XXXIV.4).
|
||
|
||
- [ ] **4.1** — Strip `capsules/hermes/init.4th`.
|
||
- [ ] **4.2** — Strip the FORTH routing table and slot-3 pairing convention.
|
||
- [ ] **4.3** — Strip `capsules/common/messaging.4th`.
|
||
- [ ] **4.4** — Remove Hermes from `is_fleet_foundation` and its birth from `kernel_main.c`.
|
||
|
||
## Phase 5 — Close-out
|
||
|
||
- [ ] **5.1** — Isabelle/HOL pass. **Deliverable is the restated boundary**, explicitly
|
||
including §XXV.4's coverage loss — *not* a green build (§XXV.3).
|
||
- [~] **5.2** — Documentation sweep, grepping **by exclusion** (§XXVIII.3).
|
||
**CLAUDE.md's four errors: DONE 2026-09-19 (§XLIV), pointer to this document added.**
|
||
Outstanding: `MANIFEST.md` (rides the strip, §XXII.5), the `TRIPOD.md`/0.1 contradiction,
|
||
item 42's K-qualification, the superseded subsystem docs' update-or-archive call, and
|
||
item 45 (`experiments/bare_metal/README.md` block framing).
|
||
- [ ] **5.3** — `make sbom`; check `Created:` and `DocumentName` (§XXVI.2).
|
||
- [ ] **5.4** — `LITHOS_VERSION = 2.1.0`; engine `VERSION` per §XXX.6's rule; roadmap table
|
||
gains its `2.1.0` line in two live places (§XXVIII.2).
|
||
- [ ] **5.5** — Resolve the stray `refs/heads/v2.0.1` and PR #1 (§XXVI.4). **Investigate, do
|
||
not delete.**
|
||
- [ ] **5.6** — Merge to `master`; tag `v2.1.0`.
|
||
- [ ] **5.7** — Archival close of `FABRIC-3.5.md` (§XXVI.5) and of this document.
|
||
|
||
---
|
||
|
||
## Findings log
|
||
|
||
*Defects and surprises found while executing. Reported, not fixed (unless the task was to fix
|
||
them). A finding that contradicts a `FABRIC-3.5.md` ruling must also be amended there.*
|
||
|
||
**2026-09-19, task 0.0 — shared `disk/artemis.img` confounds cross-ISA `dict_hash` comparison
|
||
unless reset between runs.** Not a code defect and does not contradict any `FABRIC-3.5.md`
|
||
ruling — `FABRIC-3.md` §XXXV.2 already documents that the disk is deliberately shared across all
|
||
three ISAs' `qemu` targets. But it means a same-order rerun of the three architectures will have
|
||
run 2 and 3 silently take Artemis's `resuming` branch instead of its `blank disk -- formatting`
|
||
branch, producing a different `dict_hash` for Artemis alone (Hera and Hermes are unaffected —
|
||
neither touches the artdisk at birth). Worth carrying forward: **any task in this document that
|
||
checks `dict_hash` identity across architectures and involves Artemis should restore
|
||
`disk/artemis.img` and `disk/thumbdrives/zuse-thumb-ident.img` to their committed blank state
|
||
(`git checkout --`) before each architecture's run**, or the check will fail on a confound rather
|
||
than a real divergence.
|
||
|
||
---
|
||
|
||
## Out of scope, carried for visibility
|
||
|
||
Recorded in `FABRIC-3.5.md`, deliberately **not** part of this reshuffle. Listed so they are not
|
||
absorbed by accident:
|
||
|
||
- **Item 43** — should a Stadium reservoir ever replenish? (§XL.6) A VM's send capacity declines
|
||
monotonically today.
|
||
- **Items 23–26** — the `FABRIC-3.5.md` §XXXI gap-analysis follow-ups: re-home `FABRIC-2` §17.4,
|
||
consolidate the three reported-not-scheduled registries, decide `FABRIC-2`'s five orphaned
|
||
design items, reconcile `FABRIC-0`'s seven opens.
|
||
- **`src/*.c.bak`** — tracked-but-stale, reported in three places and actioned in none
|
||
(§XXII.5).
|