Author SHA1 Message Date
Robert Allan JamesandClaude Sonnet 5 8edbd3cce6 Phase 5.5: investigate stray v2.0.1 branch and PR #1, don't delete/close (FABRIC-3.6.md)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
refs/heads/v2.0.1's tip is the exact merge-base with master -- a strict
ancestor, fully subsumed, confirmed by its own commit message ("master
fast-forwarded to v2.0.1, verified"). Stale ref hygiene debt, safe to
delete, not deleted here -- needs Captain Bob's explicit go-ahead.

PR #1 turned out not to be a stray reference at all: it's a PR from this
same branch against master, already closed (not merged) 20 seconds after
it was opened on 2026-09-18, before any of this reshuffle's work existed.
Nothing to resolve beyond recording what it is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 19:50:03 -04:00
Robert Allan JamesandClaude Sonnet 5 2a084ba037 Phase 5 corrections: sharpen 5.1's boundary claim, fix hosted Makefile's own stale VERSION
Advisor review of the Phase 5 close-out commit caught two real issues:

- Task 5.1's write-up claimed the Isabelle pass "confirms no regression" --
  overstated. Nothing in proof/'s scope changed, so the pass isn't
  regression evidence, it's a build-completeness formality; the boundary
  argument alone already supports the real conclusion. Sharpened.

- sbom.spdx was regenerated before the 5.4 version bump, so it briefly
  understated the engine version. Root cause: the hosted Makefile carries
  its own separate hardcoded VERSION (Makefile:17, still 3.1.0), distinct
  from Makefile.starkernel's copy that 5.4 bumped -- duplication CLAUDE.md's
  own "two independently tracked version strings" note doesn't document.
  Bumped to 3.2.0 to match, regenerated (PackageVersion now correct), and
  rebuilt the hosted starforth binary so lfs/amd64/starforth reflects it.

Also recorded why 5.1-5.4 landed as one commit (deviation from this
document's per-task-commit discipline) and sharpened the riscv64 log
entry so the FAILED run and the accepted retry aren't ambiguous to a
future reader grepping logs/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 19:49:08 -04:00
Robert Allan JamesandClaude Sonnet 5 a4ad14aec6 Phase 5 close-out: Isabelle pass, doc sweep, SBOM, version bump (FABRIC-3.6.md tasks 5.1-5.4)
5.1: Isabelle/HOL pass (52 theories, clean) -- restated the boundary rather
than just citing the green build: proof/ scope was already entirely
outside this reshuffle's footprint (src/starkernel/, capsules/*.4th),
so the boundary is unchanged, not moved.

5.2: Documentation sweep. CLAUDE.md's stale WIP banner and Tripod fleet
description updated now that Phases 0-4 have actually landed (Hera/
Artemis/Hestia, no Hermes). MANIFEST.md rides the strip -- hermes/init.4th's
block table replaced with a deletion note, init.4th/doe-campaign.4th/
hestia/init.4th entries corrected to match the post-strip live files.
Confirmed the TRIPOD.md/0.1 contradiction was already resolved (2026-08-13).
Settled the superseded-docs call explicitly: archive as-is, do not rewrite.
Fixed experiments/bare_metal/README.md's block-size framing (still said
1024-byte budget; real rule is 64 chars x 16 lines). K-qualification
checked clean against the two living documents; full retroactive sweep
of the closed archival FABRIC corpus explicitly declined as disproportionate.

5.3: make sbom. Installed syft (user-local, approved). Found and fixed a
real Makefile bug while at it -- the sbom target hardcoded
--source-name StarForth, so DocumentName was wrong even after regenerating.

5.4: LITHOS_VERSION 2.0.0 -> 2.1.0, engine VERSION 3.1.0 -> 3.2.0 (minor,
per the dictionary-visible-only rule). Replaced the stale version-comment
block in Makefile.starkernel (had the odd/even LTS rule backwards) and
docs/lithosananke/ROADMAP.md's retired versioning-policy section with the
ratified ladder. Verified on all three architectures; riscv64's first pass
hit a transient virtio_blk timeout during boot-time Zuse genesis mint,
reported and confirmed non-reproducing on an immediate clean retry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 19:46:34 -04:00
Robert Allan JamesandClaude Sonnet 5 3e201c82a5 Stage E: Category B strip -- remove Hermes, messaging.4th, old routing (FABRIC-3.6.md task 4.1-4.4)
All FORTH-owned message types were cut over to kernel-Hermes in Phase 3
(tasks 3.8-3.10). This removes the now-dead FORTH messaging layer and
the Hermes VM itself: capsules/common/messaging.4th, capsules/hermes/init.4th,
the slot-3 VM-NAME-REG pairing convention, and every load-site/birth-site
reference across capsules/init.4th, artemis/init.4th, hestia/init.4th,
doe-campaign.4th (Artemis-only now), capsule_console.c, capsule_mint.c,
capsule_wirebind.c, capsule_birth.c, and kernel_main.c.

Verified on all three architectures: clean boot, mkcapsule --lint clean
(36 files, 0 violations), zero UNKNOWN WORD, identical dict_hash across
amd64/aarch64/riscv64 for every VM, and a full mint -> WIREBIND-attach ->
USE -> relay round-trip exercising the two highest-risk edits
(capsule_console.c/capsule_mint.c).

Found, not fixed: deleting messaging.4th removes SEND-ELEVATE-REQUEST,
which was the only caller of KH-ELEVATE-SEND and the only path to
ELEVATE-GRANT (zuse-eligibility.4th, still loaded at boot) -- Phase 8
PKI's own elevation entrypoint. Needs a decision before Phase 5 close-out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 18:29:51 -04:00
Robert Allan JamesandClaude Sonnet 5 cab9b5a31f Stage D: ELEVATE-REQUEST real cutover -- FABRIC-3.6.md task 3.10
Reachability verified live before writing any code, per this
project's own standing rule (grep cannot establish reachability
alone): FIND SEND-ELEVATE-REQUEST / FIND ELEVATE-GRANT / FIND
CH-REQUEST all resolve on a live Hera boot, though grep across
capsules/experiments/docs found zero callers of SEND-ELEVATE-REQUEST
-- a real, complete, directly-callable entrypoint (H.5/H.8's own
design) with no current automatic trigger, not dead code.

Correction to a prior finding, made in the course of this check: task
3.8's write-up claimed "Hera's own pre-existing inability to load
common:messaging.4th" -- false. capsules/init.4th (Hera's own
MAMA_INIT capsule) loads it directly, and SEND-ELEVATE-REQUEST lives
and works in her dictionary right now. Task 3.8's own actual scope is
unaffected by this correction.

Cutover: SEND-ELEVATE-REQUEST (messaging.4th) no longer ends in
CH-REQUEST's COMMON-CH/MSG-SEND path; it now calls KH-ELEVATE-SEND
(repl.c), a new C word wrapping sk_hermes_send_one(), registered
unconditionally for every VM. from/to are derived from the calling VM
and sk_get_mama_vm() directly in C, never taken from the stack -- a
real correctness improvement over CH-REQUEST's own initiator-only
gate, which only existed because a caller COULD pass the wrong from
value; deriving it in C makes that spoof structurally impossible.
SK_HERMES_MSG_TYPE_ELEVATE_REQUEST reuses ELEVATE-REQUEST's own value
(8), same partition-rule reasoning as tasks 3.8/3.9. Delivery is
unchanged task 3.4 machinery. No new static-buffer lifetime caveat --
the payload-aliasing fix landed before this task started.

CH-REQUEST (messaging.4th) is now dead code, its one real caller just
removed -- found, not fixed, per Captain Bob's Law.

Verified live on all three architectures: 0 0 0 0 S" DUP"
SEND-ELEVATE-REQUEST (deliberately-invalid pubkey, so ELEVATE-GRANT
correctly refuses -- the check is the pipeline running, not a grant
succeeding) fires the evidence line and completes cleanly, DUP
unaffected afterward. Zero UNKNOWN WORD, dict_hash identical across
all three architectures (changed uniformly from prior runs -- one new
word registered -- not diverged, matching SXXXIV.6's own rule).

This closes task 3.11 (Phase 3 gate): all of messaging.4th's live
FORTH-owned message types (BLK-ATTACH-EVENT, CONSOLE-CMD-EVENT,
ELEVATE-REQUEST) are now real kernel-Hermes cutovers. Phase 4 may
begin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 17:00:11 -04:00
Robert Allan JamesandClaude Sonnet 5 d4f8a568ee Silence routine diagnostic noise; fix a real CRLF double-submit bug
Two separate fixes, found and closed together after task 3.9/prompt-
format landed (Captain Bob: "finish the work first then we'll do
cleanup before 3.10 begins").

1. Logging noise (confirmed live via QMP screendump): three sources
   were cluttering ordinary interactive console sessions.
   - INFERENCE "Output validation failed, ignoring results"
     (vm_runtime.c, kernel; vm_time.c, hosted mirror) and xhci "CSW
     status = FAILED"/"unit not ready -- retrying" (xhci.c) were
     already log_message(LOG_WARN/LOG_ERROR, ...) calls, just visible
     at the default runtime LOG_WARN level -- downgraded to LOG_INFO,
     all three fire routinely and self-resolve (xhci.c's own existing
     comment already documents the retry as expected SCSI UNIT
     ATTENTION behavior, not a driver defect).
   - Stadium: dispatch cell=... (stadium.c's stadium_dispatch()) was a
     genuine defect: an unconditional console_puts()/console_println()
     sequence with no level gating at all, printing on every single
     dispatch. Rewritten through log_message(LOG_DEBUG, ...).

2. CRLF double-submit (found while investigating why the cleaned-up
   noise still didn't look like a normal single-VM session):
   sk_console_readline() (repl.c) breaks on '\r' OR '\n' as independent
   terminators, so a line sent as both bytes submits twice -- the real
   line, then an immediate empty-line submit on the second byte, each
   printing its own " ok". Pre-dates Stage D entirely, not an async-
   relay artifact. Fixed with a single non-blocking peek-and-discard
   for the paired byte right where the line terminates.

Verified live on all three architectures for both fixes: zero UNKNOWN
WORD, dict_hash identical to every prior acceptance run in this
document (both changes are display/interaction-only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 16:33:29 -04:00
Robert Allan JamesandClaude Sonnet 5 5c07745c18 Fix SkHermesMessage payload-aliasing defect (task 3.8 findings log)
sk_hermes_send_one() -- the single funnel every sender, including
sk_hermes_publish(), already goes through -- used to store the
caller's own payload_addr pointer as-is. Two sends before either
drains meant both messages pointed at the same caller-owned buffer,
whichever send wrote last silently winning: real, confirmed live (a
second identity thumbdrive attached at boot alongside Zuse's own left
its WIREBIND pairing silently never happening).

SkHermesMessage gains an inline payload_buf[SK_HERMES_CHUNK_MAX_
PAYLOAD] field; sk_hermes_send_one() now memcpy()s the caller's
payload into it and points payload_addr at that copy instead. No
sender or reader call site needed to change -- every existing reader
already only ever reads through payload_addr, which still points at
valid bytes of the same length, now message-owned. g_kh_blk_attach_buf/
g_kh_console_cmd_buf (repl.c, tasks 3.8/3.9) no longer need to survive
past their own send call; their doc comments, which had claimed the
old aliasing shape was benign, are corrected.

Verified the original bug is actually gone: reproduced the exact
original scenario (a real, sequentially-minted rajames identity
attached at boot alongside Zuse's own, two simultaneous BLK-ATTACH-
EVENT sends in one idle-loop pass) -- WIREBIND pairing, USE, and the
Stage D relay all now work where WIREBIND previously silently failed.
Standard three-ISA acceptance also clean: zero UNKNOWN WORD, dict_hash
identical across all three and matching every prior acceptance run in
this document.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 14:16:29 -04:00
Robert Allan JamesandClaude Sonnet 5 21734b1a52 Console prompt: identity/machine both sides once redirected off Hera
sk_console_user_prefix() (repl.c) previously always returned "zuse"
(or the WIREBIND-attached username) as the left side of the bracket
prefix, regardless of which VM the console was actually pointed at --
"[zuse@rajames]" after USE rajames, always showing the authenticating
superuser rather than the active identity.

Changed on Captain Bob's direct instruction: once the console is
redirected into a WIREBIND identity's own console VM
(console_get_vm_name() != "Hera"), show that same name on both sides
-- "[rajames@rajames]" -- since WIREBIND births the console VM
literally named after the identity, so the identity IS that VM, not a
separate label. At the top level (still on Hera, nothing has
redirected yet), the original zuse_session/WIREBIND-username logic is
unchanged.

An earlier, more ambitious attempt (separate identity/machine tracked
state across every console_set_vm_name() call site) regressed live to
a wrong [zuse@Artemis] prompt and was fully reverted before reaching
any acceptance run -- the landed fix needed none of that new state,
just this one function.

Verified live on all three architectures: [zuse@Hera] at the top
level and after a live WIREBIND attach (before USE), [rajames@rajames]
after USE rajames, with task 3.9's Stage D relay still firing
correctly on top of it. Zero UNKNOWN WORD, dict_hash unaffected
(display-only change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 13:50:40 -04:00
Robert Allan JamesandClaude Sonnet 5 3975dc61cd Stage D: CONSOLE-CMD-EVENT real cutover -- FABRIC-3.6.md task 3.9
Send-side cutover: sk_repl_dispatch_line()'s FORTH-string
"CONSOLE-CMD-EVENT 0 3 S\" ...\" 0 MSG-SEND" interpret is replaced with
a direct sk_hermes_send_one() call (SK_HERMES_MSG_TYPE_CONSOLE_CMD,
kernel_hermes.h, deliberately reusing CONSOLE-CMD-EVENT's own value 7,
same partition-rule reasoning as task 3.8's BLK-ATTACH-EVENT cutover).

Real finding along the way: kernel-Hermes's drain only ever runs as a
side effect of vm_interpret() being called on the target VM. Task
3.8's target (Hera) is always being interpreted via the interactive
REPL loop; task 3.9's target is a WIREBIND identity's own ~user VM, a
passive receiver nothing else drives. The existing idle-loop pump only
ticked VMs with the old FORTH MSG-TICK word ACL-allowed -- a VM minted
with the STD79-lockdown personality never has it, so the pump silently
skipped it forever and queued messages never delivered. Fixed by
adding an unconditional, direct sk_hermes_drain_checkpoint() call in
the same pump loop, independent of the MSG-TICK gate.

Verified live on all three architectures: WIREBIND-attach a real
identity, USE into it, type a plain console line, confirm the Stage D
evidence line and correct relayed execution result. Zero UNKNOWN WORD,
dict_hash identical across all three ISAs and matching task 3.8's own
baseline. The FABRIC-3.md-documented USE/BINDSTEP crash did not
reproduce in any of these live sessions (recorded as a finding, not
chased further).

Depends on the zuse_root_pubkey_known fix already landed in ac4d431 --
without it, WIREBIND cannot attach any identity on a fresh boot at
all, which blocked this task's own verification until found and fixed
separately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 13:34:20 -04:00
Robert Allan JamesandClaude Sonnet 5 ac4d431aee Fix zuse_root_pubkey_known never set after a same-session genesis mint
capsule_zuse_boot_load_root_pubkey() is the only writer of
zuse_root_pubkey_known, and it only ever runs once, synchronously, at
Artemis's boot-time virtio-blk attach -- before genesis mint has
happened on a fresh artemis.img, so it finds no marker yet and leaves
the flag 0. Nothing re-triggers it after genesis mint completes.

Silent result: capsule_wirebind_try_attach()'s own
`if (!mama_vm->zuse_root_pubkey_known) return;` gate then refuses
every identity attach for the rest of that boot, with no message at
all -- meaning WIREBIND was silently dead on any boot that reset
artemis.img fresh, which is exactly what this project's own
acceptance convention does before every run.

Found live verifying FABRIC-3.6.md task 3.9's console-session
acceptance. Fixed at the source: install_and_activate() already has
the root pubkey in hand (from genesis mint or an already-Zuse
re-attach) -- activate it directly there instead of relying on a disk
re-read that may never happen in-session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 12:38:40 -04:00
Robert Allan JamesandClaude Sonnet 5 7944abca36 Findings: task 3.8 payload-aliasing defect found while starting 3.9
While orienting for task 3.9 (CONSOLE-CMD-EVENT cutover, per Captain
Bob's ruling to verify via a real QMP/serial-socket console session),
booting with a second real identity drive attached alongside Zuse's
own exposed a real defect in the already-closed task 3.8 code:
g_kh_blk_attach_buf (repl.c) is one static buffer, and
sk_hermes_send_one() stores payload_addr as a caller-owned pointer,
not a copy. Two real USB-MSC attaches in one sk_repl_idle() pass send
before either drains, so both messages alias the same buffer -- only
one identity ever completed.

Task 3.8's own write-up claimed this "carries the same single-buffer-
reuse shape ATTACH-ACK-BUF itself already had... not a new hazard" --
that claim was wrong and is amended in FABRIC-3.6.md's findings log.
FORTH's own MSG-SEND had the identical pointer-aliasing shape but
never hit the window: MSG-TICK drained from the same sk_repl_idle()
pass that queues attaches. Kernel-Hermes drains at interpret
checkpoints, which don't fire during that pass at all -- the cutover
changed not just how delivery happens but when, opening a window
FORTH's own design never had.

Reported, not fixed here, per Captain Bob's Law: this is a defect in
closed task 3.8 code, found while scoping a different task. A real
fix changes SkHermesMessage's own shape to own its payload bytes
rather than reference a caller's pointer -- bigger than a repl.c
patch, touches every existing sender, needs its own three-ISA
acceptance.

Task 3.9's own send-side cutover (kernel_hermes.h, repl.c) is written
but deliberately left uncommitted -- it would inherit the identical
defect shape if shipped now. logs/20260922-111840/amd64/ is the
reproduction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 11:26:13 -04:00
Robert Allan JamesandClaude Sonnet 5 bbfd9103f4 Stage C: cut over BLK-ATTACH-EVENT alone -- FABRIC-3.6.md task 3.8
The reply leg (Artemis -> Hera ack) that used to flow through
common:messaging.4th's MSG-SEND/MSG-TICK now goes through
kernel-Hermes's sk_hermes_send_one()/sk_hermes_drain_checkpoint()
instead -- FORTH Hermes never sees a BLK-ATTACH-EVENT message again
(SXXXIV.2's partition rule). The request leg was never real FORTH
messaging traffic to begin with (a direct VM-EXEC, no type tag,
forced by Hera's own inability to load common:messaging.4th), so it
is untouched.

New KH-BLK-ATTACH-SEND (repl.c) wraps sk_hermes_send_one(), reached
from capsules/artemis/init.4th's HERA-BLK-ATTACH-REQ. Delivery reuses
task 3.4's already-wired sk_hermes_drain_checkpoint(); BLK-ATTACH-ACK
itself is unchanged, just reached by a different layer.
SK_HERMES_MSG_TYPE_BLK_ATTACH deliberately reuses BLK-ATTACH-EVENT's
own value (9) to document this as a cutover of the same message, not
a new one.

Two real bugs found on the way, both recorded in FABRIC-3.6.md's
findings log:
- A popped FORTH CREATE-buffer address was raw-cast to a host pointer
  instead of going through vm_ptr() -- silently read all-zero memory,
  no crash, no error, just a message that arrived and did nothing.
  Fixed; the rule and its exception (repl.c's own dev-addr is
  legitimately a raw pointer, formatted that way by its own pushing
  code) are written up for the next FORTH-facing C word.
- A separate, genuine hang on the very first live exercise of this
  path, never reproduced across ten subsequent boots. Reported, not
  chased -- not blocking, per the task's own check being otherwise
  fully satisfied.

Also found live: log_message() is invisible in this build's actual
serial-log capture at every level -- settled on a single
console_println in the real drain target instead, one line per real
USB attach, not a hot-path.

Final acceptance (logs/20260922-105501, -105758, -110304, disk images
reset before each): dict_hash identical across all three
architectures for every VM, zero UNKNOWN WORD, mkcapsule --lint
clean, real ledger+stadium_conserved(Artemis)=true evidence on every
boot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 11:08:26 -04:00
Robert Allan JamesandClaude Sonnet 5 f37aa0fb17 Channel-open policy hook -- FABRIC-3.6.md task 3.7
Added HERMES-CHANNEL-OPEN? ( req-hi req-lo -- allow? ) at
capsules/ACL.4th block 4008 (default: approve everything) -- the one
word policy authors edit. sk_hermes_channel_open_policy(VM*, VMUuid)
(kernel_hermes.h/.c) is the C-side query that calls it via plain
word-dispatch against the target VM's own dictionary/stack, never
vm_interpret() (avoids task 3.4's input-buffer cursor hazard entirely)
and never decides the answer itself. Fails closed: no policy word,
a policy error, or stack underflow all deny, matching CLAUDE.md's
posture that absence of policy must never mean "always allow."

Two real bugs found and fixed before this was called done:
missing current_executing_entry assignment before calling the word's
func pointer (colon words silently no-op without it, vm_core.c:730 --
no crash, just a wrong answer); and a second FAIL with debug
instrumentation still in place whose precise cause isn't
reconstructable, since no intermediate commit exists for that attempt.

Self-test proves the task's check four ways against the same
unchanged C function: default approve, live redefinition to deny
(zero C change), restore, and a VM with no ACL.4th loaded at all
(fail closed). A fifth check wires the result into task 3.6's
sk_hermes_channel_respond() end to end: a denied policy produces a
NACK and no channel, ledger/stadium_conserved() holding throughout.

Scope, per Captain Bob's ruling: closes with the query built and
proven; sk_hermes_channel_respond() still takes a caller-supplied
approved bool rather than calling the policy internally. Wiring a
real channel-open call site to only this query is deferred to
whichever later task first needs a live decision.

dict_hash identical across amd64/aarch64/riscv64 for every VM, zero
UNKNOWN WORD, mkcapsule --lint clean (38 files, 0 violations).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 09:08:48 -04:00
Robert Allan JamesandClaude Sonnet 5 205a49ecd0 ACK/NACK and private-channel negotiation -- FABRIC-3.6.md task 3.6
Extracted sk_hermes_send_one() from sk_hermes_publish()'s own
per-subscriber body -- one code path for both point-to-point and
fan-out delivery, so the ledger can never diverge between them.
Point-to-point addressing turned out to be load-bearing, not
incidental: sk_hermes_publish()'s fan-out sets msg->to to whichever
member it is iterating, so a negotiation message "published" to the
common channel would spuriously reach every member, not just the real
target (checked with advisor() before building the naive version).
"Over the common channel" means every VM is reachable from birth (task
3.2), not that the exchange itself fans out -- messaging.4th's own
CH-REQUEST carried an explicit `to` for the same reason.

sk_hermes_channel_request/respond/close build the mechanics: request ->
grant (creates a private channel, subscribes both parties, sends
CH_GRANT + one ACK) or NACK ("a deny is a NACK", SXLV.1 -- no separate
type); close authorized by membership alone. The grant/deny decision is
a plain caller-supplied `approved` bool -- task 3.7 replaces the call
site that produces it with a real ACL.4th query, not this signature.

Self-test covers the task's own three checks plus a sibling advisor()
flagged: an approved respond() whose channel creation itself fails
(table exhausted) must still fall through to NACK, not a silent false
grant or half-open channel -- verified by exhausting the whole channel
table and confirming the fallback.

Bug found and fixed before this was called done: the first draft
dropped a message via pending_pop() alone, without releasing it first,
leaking its Stadium heat and failing the self-test's own ledger
baseline check (logs/20260922-065946/amd64/, kept as audit trail).
Fixed and re-verified PASS on all three architectures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 07:25:51 -04:00
Robert Allan JamesandClaude Sonnet 5 8a2ee0fdad Payload bound and chunking -- FABRIC-3.6.md task 3.5
sk_hermes_publish() now enforces SK_HERMES_CHUNK_MAX_PAYLOAD (1024) on
every message's payload_len uniformly, chunked or not -- closing the
gap task 3.3 explicitly parked. A chunk carrier is
[SkHermesChunkHeader][content slice], slice capped at
1024 - sizeof(header) rather than 1024 itself, so every message on the
wire satisfies the same one-block bound vm_interpret()'s own drain
limit already requires -- a future chunk-aware drain never has to
special-case a carrier that can't be handed to vm_interpret() as-is.

Deliberately no chunking-sender API: building one would need
kernel-Hermes to own chunk-buffer memory with a real lifetime it has no
way to track (kept alive until every subscriber drains it). Sending is
a loop pattern a caller writes with sk_hermes_chunk_count() +
sk_hermes_publish(), demonstrated by this task's own self-test.
sk_hermes_reassemble() is pure and memory-agnostic: validates msg_id
agreement, exact seq coverage, and per-chunk slice sizes before a
single memcpy, with the total length computed once and checked against
the caller's buffer once -- never order-dependent on which chunk
happens to overflow.

Verified live on all three architectures: a 1024-byte payload as one
message, a 1025-byte send refused outright with the ledger untouched,
and a 3000-byte payload split into 3 chunks, drained, and reassembled
byte-exact against the original. dict_hash unmoved and identical
across architectures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 06:51:48 -04:00
Robert Allan JamesandClaude Sonnet 5 2b1ba031a5 Drain at the outermost checkpoint -- FABRIC-3.6.md task 3.4
sk_hermes_drain_checkpoint() interprets one queued payload per checkpoint
(ruled: one message per checkpoint), reusing sk_vm_at_outermost_interpret()
and placed before the switch-signal block in vm_core.c's existing
cooperative checkpoint (sk_vm_context_switch() doesn't return until
switched back to, so drain must come first or it silently never runs on
a switching checkpoint).

Amends FABRIC-3.5.md SXLIII.5, caught by advisor() before writing the
naive version: "recursive drain is prevented for free" via
g_vm_interpret_depth is true but only for same-message re-drain -- it
doesn't cover the separate same-VM reentrancy hazard FABRIC-3.md SXX
already named for Hera specifically (VMCallState saves rsp/exit_colon/
ecw_nesting only, never input_buffer/input_length/input_pos). Draining
calls vm_interpret() on the same vm whose own vm_interpret() call is
still paused mid-word at the checkpoint; without saving and restoring
the cursor by hand, the enclosing REPL line or LOAD block would be
silently truncated. sk_hermes_drain_checkpoint() snapshots and restores
input_buffer/input_length/input_pos/mode/error/abort_requested around
the call. Not a divergence from the ruling -- cursor preservation is the
implementer's own obligation inside the ruled mechanism.

Gated behind a system-wide pending-total counter so the common
no-message-in-flight case costs one integer read per word dispatch, not
a stadium_max_vm_count()-sized queue scan (also flagged by advisor() as
a real hot-path cost, not deferred).

Verified live on all three architectures: a self-test publishes a real
payload to Hermes, proves the depth gate via VM-EXEC-ing an existing
harmless colon word into Hermes (genuine nested vm_interpret(), depth 2,
must not drain), then drains directly from genuinely-outermost context
and confirms exactly one clean drain. dict_hash unmoved and identical
across architectures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 01:27:11 -04:00
Robert Allan JamesandClaude Sonnet 5 1f6343bc03 Publish path, no dispatch -- FABRIC-3.6.md task 3.3
sk_hermes_publish() allocates one SkHermesMessage per channel member
(heat-cost ruling 2026-09-21: one message per subscriber, funded by
the publisher's own reservoir) and enqueues each onto a new
per-subscriber SkHermesPendingQueue -- found-or-created lazily by
vm_id, sized from stadium_max_vm_count() like the channel/switch
tables. Best-effort across subscribers: a failed allocation or full
queue skips and rolls back just that one subscriber, not the whole
publish -- the natural reading of "ledger and stadium_conserved() hold
across N publishes to M subscribers" (the task's own check), not a
separate ruling.

Dispatches nothing -- sk_hermes_pending_count()/peek()/pop() are the
read/drain primitives task 3.4's real checkpoint-driven drain will
build on; this task's own self-test uses them directly since no
checkpoint hook exists yet.

Verified live on all three architectures: pending-queue table sized
50/202/50 slots (tracking the channel table's own per-arch sizing), a
synthetic publish self-test (2 publishes to 3 subscribers) confirms
exact per-subscriber delivery counts, and ledger/stadium_conserved()
invariants hold both mid-publish and after manually draining every
queue back to baseline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 00:49:22 -04:00
Robert Allan JamesandClaude Sonnet 5 a4afdfa591 Channel table + common channel, inert (B1) -- FABRIC-3.6.md task 3.2
Adds SkHermesChannel: a channel is an index into a boot-time,
stadium_max_vm_count()-sized table (same sizing pattern task 3.1
established for the switch table -- no separate numeric rule was ruled
for this table, so task 3.1's bound is extended directly, flagged as
such rather than restated as a new ruling). No name field, mirroring
messaging.4th's own nameless CH-ARENA.

The common channel (index 0) is created at boot and permanent. Hera
subscribes explicitly in kernel_main.c (she is the one VM never born
through capsule_birth_baby()); every other VM -- Tripod fleet and
future WIREBIND identities alike -- subscribes inside
capsule_birth_baby() itself, the single choke point every other birth
already passes through.

Inert: no publish, no dispatch, no ACK/NACK, no ACL hook (tasks 3.3,
3.6, 3.7). Verified live on all three architectures: channel table
sized to 50/202/50 slots (matching switch-signal's own per-arch
sizing), common-channel fleet self-test confirms all four Tripod
members are members, and a synthetic create/subscribe/unsubscribe/
destroy round-trip against a private topic passes, including refusing
to destroy the common channel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 00:25:13 -04:00
Robert Allan JamesandClaude Sonnet 5 c19ef365fe Dynamic switch table (B2) -- FABRIC-3.6.md task 3.1
Replaces the fixed SK_SWITCH_MAX_SLOTS=16 compile-time array with a
boot-time, RAM-derived allocation via a new sk_vm_switch_signal_boot_init(),
kmalloc'd to stadium_max_vm_count() entries -- the same pattern
session_boot_init() already established for Stadium-derived sizing.
Every switch-signal participant is a Stadium VM, so this reuses that
bound directly rather than deriving a separate one.

Verified live on all three architectures: switch table sized to 50
slots (amd64), 202 slots (aarch64), 50 slots (riscv64) -- all well
past the old fixed cap. All three boot to [zuse@Hera] ok> cleanly;
dict_hash for Hermes/Hestia identical across architectures, unmoved
from pre-task values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 23:59:50 -04:00
Robert Allan JamesandClaude Sonnet 5 66ea4a5e74 Record task 3.0 rulings (FABRIC-3.5.md §XLVI); close FABRIC-3.6.md task 3.0
Captain Bob ruled all five §XLV.4 sub-items plus task 3.3's heat-cost
design point: ACK on channel-open+delivery only; the channel-open ACL
hook is a new word in ACL.4th; switch-table sizing mirrors Stadium's
stadium_max_vm_count_val; chunks carry (msg_id, seq, is_last); drain
one message per outermost-interpret checkpoint; publish costs one
message per subscriber. Tasks 3.1-3.7 may now be written precisely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 23:29:12 -04:00
Robert Allan JamesandClaude Sonnet 5 f2f7111dff Draft Phase 3 task breakdown (3.0-3.11), awaiting review -- FABRIC-3.6.md
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 10:49:10 -04:00
Robert Allan JamesandClaude Sonnet 5 303b0c7edf Record B1/B2/B4 rulings (FABRIC-3.5.md §XLV); clear Phase 3 blockers in FABRIC-3.6.md
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 08:55:21 -04:00
Robert Allan JamesandClaude Sonnet 5 feace42397 Add diagnostic scan cross-check of the Hermes counters -- FABRIC-3.6.md task 2.8
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 08:46:07 -04:00
Robert Allan JamesandClaude Sonnet 5 2a2bf6eb35 Stage B proof: add per-VM consumed term to stadium_conserved -- FABRIC-3.6.md task 2.7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 21:31:45 -04:00
Robert Allan JamesandClaude Sonnet 5 313ffc89e6 Add exact-equality Hermes ledger self-audit -- FABRIC-3.6.md task 2.6
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 21:02:27 -04:00
Robert Allan JamesandClaude Sonnet 5 d11eb2e5db Add sk_hermes_decay(), ledgering decay into consumed -- FABRIC-3.6.md task 2.5
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 18:48:46 -04:00
Robert Allan JamesandClaude Sonnet 5 493d410028 Add the four ledger counters (held/pulled/returned/consumed) -- FABRIC-3.6.md task 2.4
FABRIC-3.5.md SXL.4's ledger: held == pulled - returned - consumed,
epsilon zero. Added sk_hermes_ledger() (an accessor, not a mutator)
plus four static counters in kernel_hermes.c.

Each counter has exactly one increment/decrement site: held/pulled
both move at sk_hermes_alloc()'s single success path, after every
refusal branch has already returned; held/returned both move at
sk_hermes_release()'s single success path. consumed is declared and
always reads 0 -- its one increment site doesn't exist yet, and won't
until task 2.5 gives decay something to record.

sk_hermes_release() now reads the Stadium cell's live header.heat
immediately before calling stadium_evict(), rather than assuming the
original pulled amount -- stadium_evict() zeroes the header as part of
freeing the cell and its own return value is a success code, not the
credited amount, so this is the only point the true remaining heat is
available. Today this always equals the original Q.SLOT pull; once
task 2.5's decay exists, this is what keeps returned correct without
touching this function again.

Self-test (kernel_main.c) extended: snapshots the ledger before
running so it checks its own deltas, verifies held/pulled grow by
exactly got_n * Q_SLOT on allocation with returned/consumed untouched,
then verifies held returns to its starting value and returned grows by
the same amount on release, and checks the audit invariant itself as a
bonus (task 2.6 formalizes this properly).

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, dict_hash unmoved. All three print PASS with
identical final ledger: held=0 pulled=65536 returned=65536 consumed=0.
No compiler warnings.

Authorized by Captain Bob ("keep going with rhe 6.5 document").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 05:59:09 -04:00
Robert Allan JamesandClaude Sonnet 5 2c1dc1753a Correct sk_hermes_alloc() to admit a real Stadium patron; add sk_hermes_release() -- FABRIC-3.6.md tasks 2.2 (amended) + 2.3
Real finding, caught before building release on a foundation that
couldn't support it: task 2.2's first cut of sk_hermes_alloc() pulled
reservoir heat but never admitted a real Stadium-floor patron -- just a
local in_use flag. FABRIC-3.5.md SXXXIII.4 item 1 says MSG-FREE-NODE
returns heat "via STADIUM-EVICT", which only means something if
allocation admitted something. SXL.4's own invariant, Sigma(resident
patron heat) + reservoir + consumed == Q48_ONE, cannot balance if held
heat is invisible to every term while held. Flagged to Captain Bob
before proceeding; authorized to correct 2.2 in the same pass as
building 2.3 on top of the fix.

sk_hermes_alloc() now calls stadium_admit() with heat = the pulled
amount, behaviour = STADIUM_BEHAVIOUR_DELIVER (matching messaging.4th's
own SB-DELIVER STADIUM-ADMIT exactly), and identity = the message's own
slot index (matching the FORTH precedent -- caught live in the first
boot of this fix that omitting this made stadium_dispatch()'s existing
DELIVER diagnostic print msg_idx=0 for every message instead of a
distinct value). The returned cell index is stored in the message's
own stadium_cell field. Stadium-floor refusal (independent of reservoir
affordability) rolls back the pull the same way the other refusal
paths already do.

sk_hermes_release() -- the function task 2.3 actually asks for -- calls
stadium_evict() on that cell, which itself returns the departing
patron's remaining heat to its owning VM's reservoir, matching
MSG-FREE-NODE's exact shape. Release does not touch the reservoir
directly.

Self-test (kernel_main.c) extended: keeps every allocated message's
pointer, allocates to exhaustion as before, releases all of them, and
checks the reservoir returns to precisely its starting value.
"Undecayed" is true by construction (no decay/TTL logic exists yet,
task 2.5) -- exact restoration, not approximate.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, dict_hash unmoved from task 2.2. All three print
identical PASS arithmetic: reservoir0=65536, reservoir_after_alloc=0,
reservoir_final=65536. No compiler warnings.

stadium_dispatch()'s DELIVER-case console output (one line per
eviction) is pre-existing instrumentation, not new -- confirmed real
and load-bearing per stadium.c's own comment, verbose but expected.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 04:20:14 -04:00
Robert Allan JamesandClaude Sonnet 5 9d129fdb1c Add sk_hermes_alloc(), the heat-coupled allocator -- FABRIC-3.6.md task 2.2, item 28
The piece FABRIC-3.5.md SXXXIII.6 calls "what remains genuinely hard,"
built and proven first per its own recommendation. Added
src/starkernel/vm/kernel_hermes.c (wired into Makefile.starkernel's
LOADER_EXTRA_SRCS -- this repo lists vm/*.c files explicitly, no glob)
and sk_hermes_alloc()'s declaration in kernel_hermes.h.

Checks stadium_reservoir_peek(vm_id) >= SK_HERMES_Q_SLOT before
touching the reservoir at all -- refusal this way needs no rollback,
since nothing was pulled -- with an explicit rollback path
(stadium_reservoir_push) kept defensively for the pull-then-short case,
though nothing in this single-core kernel is expected to reach it.

SK_HERMES_Q_SLOT = Q48_ONE / SK_HERMES_MSG_MAX (2048), deliberately
simpler than messaging.4th's own formula, which reserves a Q.1/3 floor
for COMMON-CH's own Stadium heat -- kernel-Hermes has no such object
(SXXXIII.4/SXXXIII.5's flat membership list carries no heat of its
own), so there is nothing left for that floor to protect.

Self-test in kernel_main.c, same diagnostic-only synthetic-VM pattern
as the existing Stadium quota grant self-test (lo=3, distinct from
that test's lo=1): reads back the actual granted reservoir rather than
assuming a number, derives expected_n from it, allocates to refusal,
and checks the refusal lands at exactly expected_n, the reservoir
doesn't move on the refused attempt (rollback proven, not assumed),
and the final reservoir is exactly reservoir0 minus got_n times
Q_SLOT.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, dict_hash unmoved from task 2.1 (pure C, no FORTH
touched). All three print identical self-test arithmetic: reservoir0=
65536 Q_SLOT=2048 expected_n=32 got_n=32 reservoir_after=0. No compiler
warnings.

Noted, not fixed: Q_SLOT's divisor and SK_HERMES_MSG_MAX are the same
32, so reservoir and arena exhaustion land at exactly the same count by
construction -- this test can't distinguish which refusal reason
fired, only that refusal is correct and rolls back correctly.

Deliberately not evidence for stadium_conserved(): allocating alone
(no release yet, task 2.3) leaves pulled heat held off the Stadium
floor, so the two-term check would correctly read false right now if
run mid-hold. That's expected, not a bug -- Stage B (task 2.7) is
defined as "before and after the alloc/free cycle," not "continuously
during." This task's self-test checks reservoir arithmetic directly
instead.

Authorized by Captain Bob ("Yes continue").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 21:00:20 -04:00
Robert Allan JamesandClaude Sonnet 5 f10fa7ae83 Add kernel-Hermes message/membership structures -- FABRIC-3.6.md task 2.1, Phase 2 begins
Phase 2, task 2.1 only: type definitions, wired to nothing, drawing no
heat -- no allocator, no protocol logic, no registration anywhere.
FABRIC-3.5.md SXXII.4: Phase 2 structures come first and prove nothing
until the allocator is built on top (task 2.2 onward, each its own
commit).

Added include/starkernel/vm/kernel_hermes.h:

SkHermesMessage -- field-for-field mirror of messaging.4th's live
9-cell MSG-* layout (type/from/to/payload addr+len/Stadium cell
index/seq/channel/orig-type), per SXXXIII.4 item 1 ("roughly half the
file is accessors that become struct fields"), plus an explicit
in_use flag for task 2.2's allocator. Deliberately no separate heat
field: per SXL.4, a message's heat IS the Stadium cell it occupies,
not a value copied alongside it -- one source of truth for the
conservation invariant stadium_conserved() (task 0.7) checks.

SkHermesMembership -- one flat broadcast membership list, SXXXIII.4/
SXXXIII.5's recommended replacement for messaging.4th's 28-word channel
abstraction (traced to exactly one live caller, CH-ADD-MBR). Item 27
(negotiation vs. broadcast, Phase 3 blocker B1) is not answered by this
structure and isn't meant to be -- a flat list is correct either way.

Genuinely wired to nothing: no .c file, no Makefile change, no include
from any compiled source. Syntax-checked standalone (gcc -std=c99
-Wall -Wextra -Werror -fsyntax-only) before touching the real build.

Boot byte-identical to task 1.9's baseline on amd64 (same dict_hash
triple, zero UNKNOWN WORD). Did not repeat aarch64/riscv64 -- the file
compiles into no object on any architecture, so there is no mechanism
by which it could diverge.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 20:48:24 -04:00
Robert Allan JamesandClaude Sonnet 5 1e75bb8039 Assert Hestia's headless invariant -- FABRIC-3.6.md task 1.9, Phase 1 closed
Audited first: neither capsules/hestia/init.4th nor her birth block in
kernel_main.c references g_wirebind_attached_username, CONSOLE-ATTACH,
MINT, or any proxy-minting mechanism -- the invariant already held
structurally, by absence. Stated it explicitly anyway, per the task:
added a comment at Hestia's birth site quoting FABRIC-3.5.md SXVIII.6's
invariant verbatim, warning future edits not to add console/wirebind/
proxy code there without re-reading it first.

Verified live with the actual no-thumbdrive boot
(ARCH=<arch> qemu ZUSEDISK=), not the default. All four VMs born
successfully on all three architectures, zero UNKNOWN WORD, and zero
ok> occurrences anywhere in any of the three full logs -- genuinely
silent, matching sk_repl_headless_wait()'s own documented "no banner,
no prompt, no input surface at all." Watched each log's line count
post-birth for 8-10s to confirm it stayed flat rather than eventually
printing something late.

Confirmed no regression on the standard (with-thumbdrive) path on
amd64: dict_hash identical to task 1.8's baseline. Did not repeat that
check on aarch64/riscv64 -- the change is a comment only, cannot
diverge by compiler, and the headless invariant itself was already
proven identically on all three.

Phase 1 is now fully closed (tasks 1.1-1.9). Tripod is Hera/Artemis/
Hestia plus Hermes (retained through Phase 1-3 per SXXXIV.4); Hestia
owns the drawing fabric exclusively; headless-until-login intact with
Hestia in the fleet. Phase 2 is next.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:46:32 -04:00
Robert Allan JamesandClaude Sonnet 5 6c6293cd52 Move PLOT/FB-WIDTH/FB-HEIGHT registration to Hestia only -- FABRIC-3.6.md task 1.8
Real fix for task 0.8's finding. register_framebuffer_words() was
called unconditionally from register_forth79_words() (word_registry.c),
itself called unconditionally from vm_init_with_host() -- the generic
per-VM bootstrap every VM goes through, with no way to know a VM's
name at that point.

Removed the unconditional call. Added a name-gated call instead in
capsule_birth_baby() (capsule_birth.c), beside the existing
is_fleet_foundation check -- the one place in the birth path where
capsule_name and the newly-allocated VM* are both in scope together:
Hestia gets register_framebuffer_words(), nobody else does.

Positively verified live, exactly as the task's own check demands:
FB-WIDTH via VM-EXEC returns UNKNOWN WORD in Hermes and Artemis, 1280
in Hestia. Confirmed at the fundamental level too: Hera's own base
PARITY:M7.1a word count dropped from 531 to 528 -- exactly the three
words removed -- identical across all three architectures.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD during boot. mkcapsule --lint capsules/ clean, 38
files / 0 violations (pure C change, no capsule content touched). No
compiler warnings.

Side effect on the vendored hosted build, expected and not a
regression: capsule_birth.c is kernel-only, so the hosted starforth
binary has no Hestia concept and now never registers these words at
all -- confirmed live. framebuffer_words.c's own top comment already
calls this surface "kernel-only, no-op on hosted builds," so the prior
stub registration was already vestigial. Ran a plain `make` sanity
build per CLAUDE.md's own stated purpose for that target; regenerated
lfs/amd64/starforth included here rather than left stale.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:36:18 -04:00
Robert Allan JamesandClaude Sonnet 5 5afb33049f Move fabric.4th + font.4th to hestia/init.4th -- FABRIC-3.6.md tasks 1.6+1.7 (merged)
Tasks 1.6 and 1.7 are not independent, and the punchlist's split was
wrong: font.4th calls G-LINE/G-ELLIPSE, which are fabric.4th's own
words. Confirmed live before committing to an approach -- removed only
fabric.4th's EXEC from init.4th, left font.4th's in place, booted
amd64: Hera's boot floods with UNKNOWN WORD: 'G-LINE'/'G-ELLIPSE' the
moment font.4th loads (logs/20260919-171047/amd64/, kept as evidence).
Reverted that partial state, asked Captain Bob how to proceed given
neither task can independently pass its own three-arch-boot check, and
was told to use best practices.

Moved both together, in their original relative order, into a new
capsules/hestia/init.4th block 4988 -- a deliberate, documented
deviation from "one task, one commit," not a bundling of convenience.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD. Hestia's dict_hash identical across all three
architectures. Verified the shrink/grow live, not just inferred from
hash movement: HERE reads 20008 in Hera, 63040 in Hestia post-move.
CART-PLOT in Hera is UNKNOWN WORD; the identical call routed into
Hestia via VM-EXEC reaches the word and fails on a stack underflow
instead, proof it exists there since an unknown word can't underflow.

mkcapsule --lint capsules/ clean, 38 files / 0 violations. MANIFEST.md
updated: init.4th's block 2049 entry no longer lists fabric.4th/
font.4th; hestia/init.4th's entry gains block 4988.

Authorized by Captain Bob ("Use best practices.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:25:23 -04:00
Robert Allan JamesandClaude Sonnet 5 487769e18a Register Hestia for switch signals -- FABRIC-3.6.md task 1.5
Added a fourth capsule_vm_find_by_name_nocase("Hestia", ...) +
sk_vm_switch_signal_register(...) block in src/starkernel/kernel_main.c,
same shape as the existing Hermes/Artemis blocks, placed after all four
fleet members are confirmed born -- the existing comment on this block
already states why: no critical-section protection during setup, so
registering earlier risks the signal firing mid-birth.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, hashes identical to task 1.4's baseline (this is
pure C runtime state, doesn't touch any FORTH dictionary). No compiler
warnings.

Took FABRIC-3.5.md SXXXV.0's "invisible by default" warning literally
rather than trusting a clean boot log alone: SXXVIII.2's own recorded
switch-storm signature is "QEMU pinned near 100% CPU, serial log frozen
solid," not an error message. Confirmed normal wall-clock boot time on
all three (~30s) and, since TCG itself always shows ~100% CPU
regardless of guest workload, watched each serial log's line count at
the idle prompt for 5-10s and confirmed it stopped growing rather than
flooding or silently stalling.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:07:19 -04:00
Robert Allan JamesandClaude Sonnet 5 10e2d654e5 Birth Hestia in kernel_main.c -- FABRIC-3.6.md task 1.4
Added a birth block immediately after Hermes's own, same shape:
S" Hestia" BIRTH followed by a registry-lookup confirmation. Fleet is
now Hera/Hermes/Artemis/Hestia, four VMs, through Phase 1-3
(FABRIC-3.5.md SXXXIV.4) until Phase 4 retires Hermes.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD. Registry shows all four (BIRTH: Hermes live, BIRTH:
Hestia live, PARITY:BIRTH for all three non-Hera VMs). Hestia's
dict_hash identical across all three architectures (0x31cab513929eea89).
Hera/Hermes hashes unchanged from task 1.3; Artemis's vm_id shifted
(now the 4th birth instead of 3rd -- sequence-derived, not identity-
derived, so expected) but its dict_hash is unchanged and still
identical across arches. No compiler warnings.

Noted, not a regression: Hestia's birth log shows the same
"( Unterminated comment" HADES warning Artemis's birth has shown since
task 0.0's first baseline.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:01:05 -04:00
Robert Allan JamesandClaude Sonnet 5 ff00de9a63 Add Hestia to is_fleet_foundation -- FABRIC-3.6.md task 1.3
Fourth vm_name_prefix_eq_nocase(capsule_name, "Hestia") check alongside
Hera/Hermes/Artemis in src/starkernel/capsule/capsule_birth.c's
is_fleet_foundation local -- Hermes retained, per FABRIC-3.5.md
SXXXIV.4 (he stays live and fleet-foundation through Phase 1-3). The
flag's only consequence is session_set_pinned(vm_id, 1) for whichever
VM name matches.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, byte-identical to the pre-change baseline -- expected,
since nothing births anything named "Hestia" yet (task 1.4), so the
added name never matches. Hermes confirmed still present in the check
and still born normally in all three logs.

Authorized by Captain Bob ("yes").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 16:53:40 -04:00
Robert Allan JamesandClaude Sonnet 5 4f7cbe78fc Create capsules/hestia/init.4th -- FABRIC-3.6.md task 1.2
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>
2026-09-19 16:31:59 -04:00
Robert Allan JamesandClaude Sonnet 5 b624133a28 capsules/MANIFEST.md: allocate Hestia's block range 4986-4996 -- FABRIC-3.6.md task 1.1
Documentation only, no capsule file created yet (that's task 1.2).
Checked against actual current occupancy rather than trusting
MANIFEST.md's own stale blanket "4853+ OPEN" line: fabric.4th already
occupies 4900-4924 and font.4th 4925-4985 (both standalone capsule
files EXEC'd by init.4th, block-numbered independently of it -- tasks
1.6/1.7 relocate which capsule EXECs them, not their own ranges), and
4997 is the console proxy's hardcoded Block 4997 string literal
(capsule_console.c:27-29). Allocated 4986-4996, the gap between the
two, avoiding 4997 as the task requires.

Split the Unassigned Ranges table's single blanket line into an
explicit claim for 4986-4996 plus a corrected "OPEN" line that excludes
the ranges actually in use. Recorded in MANIFEST.md rather than
tools/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 alongside every other infrastructure
capsule's entry.

mkcapsule --lint capsules/ clean, 37 files / 0 violations, unchanged.

Authorized by Captain Bob ("YES").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 16:22:03 -04:00
Robert Allan JamesandClaude Sonnet 5 eed2a9dfb5 FABRIC-3.6.md task 0.8: PLOT/FB-WIDTH/FB-HEIGHT reachability audit -- Phase 0 closed
Read-only audit, no code changed. Finding: reachable from every VM
today, not confined to one table, contrary to item 33's premise.

FORTH level matches expectation: fabric.4th/font.4th are EXEC'd only
from capsules/init.4th (Hera). C level does not: register_framebuffer_
words() (src/word_source/framebuffer_words.c:60-65) is called
unconditionally from register_forth79_words() (src/word_registry.c:
139), 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.

Verified live rather than trusting the source trace alone: booted
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 the raw C primitive itself is answering.

Not fixed here, per the task's own read-only scope. Gives task 1.8 a
concrete starting state: its own check ("a non-Hestia VM calling PLOT
gets UNKNOWN WORD") currently fails, and register_framebuffer_words()'s
call site will need to become conditional or move out of the universal
bootstrap -- not just the FORTH-level relocation tasks 1.6/1.7 already
plan for.

Phase 0 gate met across tasks 0.2-0.7 (three-arch boot, stadium_
conserved() true, zero UNKNOWN WORD, repeatedly). Phase 0 is closed;
Phase 1 (Hestia, messaging untouched) is next.

Authorized by Captain Bob ("Continue.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 14:04:50 -04:00
Robert Allan JamesandClaude Sonnet 5 380f0a09c9 Add stadium_conserved() -- FABRIC-3.6.md task 0.7, item 41
Boolean analogue of vm_physics_conserved(), for the Stadium per-VM
quota invariant rather than fleet-wide execution heat
(FABRIC-3.5.md SXXXIX.4). int stadium_conserved(VMUuid vm_id), in
src/starkernel/vm/stadium.c alongside stadium_resident_sum()/
stadium_reservoir_peek() that it's built from, declared in
include/starkernel/vm/stadium.h.

Implements the two-term form -- resident_sum(vm_id) +
reservoir_peek(vm_id) == Q48_ONE -- not the three-term form SXL.4
rules for the eventual system. That ruling'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 (task 2.2 is literally
where that wiring gets built), so consumed is honestly zero right now.
Folding it in as a placeholder would be inventing Phase 2 state ahead
of it existing -- the doc comment says so explicitly, 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,
printing CONSERVED/DRIFTED the same shape vm_physics_status() already
uses.

Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, all print "Stadium conservation: CONSERVED" with
identical resident_sum=47641 reservoir=17895 sum=65536=Q48_ONE. No
compiler warnings on either edited file (forced recompile checked).

Authorized by Captain Bob ("Yes.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:56:14 -04:00
Robert Allan JamesandClaude Sonnet 5 9886ad5315 tools/capsule-reserved.txt: return freed block ranges -- FABRIC-3.6.md task 0.6
Added 4055-4059 (former common/msg.4th) and 4300-4399 (former
process.4th) as reserved, each noted as freed by this reshuffle's
strip rather than owned by non-capsule infrastructure -- the file's
usual purpose (Artemis's own block usage, etc.). Framed explicitly as
lifted, not permanent, once someone deliberately wants a range back,
per FABRIC-3.5.md SSXVIII.4/XXII.4: freed ranges should be returned
here rather than silently available for a future capsule to reclaim
without anyone noticing.

mkcapsule --lint capsules/ clean, 37 files / 0 violations.
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`, confirming the new
entries don't collide with anything currently baked. Registry/
documentation 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.

Authorized by Captain Bob ("Go for it.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:45:01 -04:00
Robert Allan JamesandClaude Sonnet 5 e233d09fa1 capsules/MANIFEST.md: correct blocks 4055 and 2049 -- FABRIC-3.6.md task 0.5
Block 2049's justification claimed init.4th loads compudynamics,
common:msg, fleet-k and process. Read the live file: it loads none of
these. compudynamics.4th/fleet-k.4th were already deleted (9323f776,
2026-07-05); common:msg.4th/process.4th are this reshuffle's own
Category A strips (tasks 0.2/0.3, a0e97258/aafcce43) and were never
EXEC'd from this block even before that -- the manifest entry was
already wrong prior to this pass, just not yet caught.

Removed the standalone common/msg.4th (former block 4055) and
process.4th (former blocks 4300-4301) sections, since both files no
longer exist, and folded them into "Deleted capsules (historical)"
alongside the existing compudynamics.4th/fleet-k.4th entry -- same
convention, same section. Noted that common/msg.4th's own entry had
claimed it was an immutable ABI "every messaging VM loads at birth",
a claim FABRIC-2.md:2773 had already flagged stale before this
correction landed. Updated the Unassigned Ranges table so 4055-4059
and 4300-4399 read as former-file ranges rather than "extension space"
for files that no longer exist.

Documentation only -- no capsule content touched, mkcapsule --lint
capsules/ still clean (37 files, 0 violations). Verified every
remaining ### `*.4th` section in the manifest names a file actually
present on disk.

Authorized by Captain Bob ("Keep going.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:42:25 -04:00
Robert Allan JamesandClaude Sonnet 5 bcc678e354 Strip SPAWN-EVENT from messaging.4th -- FABRIC-3.6.md task 0.4
Dead per task 0.1's reachability check (156d1642): zero references by
name anywhere in the tree outside its own definition -- process.4th's
own SPAWN/PAUSE/RESUME/KILL-VM calls passed bare numeric literals
(1/2/3/4), never this constant's name. Removed the single line only;
PAUSE-EVENT/RESUME-EVENT/KILL-EVENT are left in place, matching the
punchlist's stated scope -- they are equally dead-by-name but that
widening was flagged in 0.1's findings, not folded into this task.

mkcapsule --lint capsules/ clean, 37 files / 0 violations, unchanged
(one-line edit, no file added or removed). Three-arch boot clean:
amd64/aarch64/riscv64 all reach [zuse@Hera] ok>, zero UNKNOWN WORD.
dict_hash moved for Hermes/Artemis (both load messaging.4th) and is
identical across all three architectures; Hera's PARITY:M7.1a snapshot
unchanged as in the prior two strips.

Phase 0's three strips (0.2-0.4) are now all done. capsule-reserved.txt
and MANIFEST.md's stale block-4055/2049 entries remain for 0.5/0.6.

Authorized by Captain Bob ("Yes, please continue.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:39:06 -04:00
Robert Allan JamesandClaude Sonnet 5 aafcce4320 Strip capsules/process.4th and its EVENT-EMIT/-WAIT/-DRAIN -- FABRIC-3.6.md task 0.3
process.4th is dead per task 0.1's reachability check (156d1642): zero
EXEC sites anywhere, and its four words (SPAWN/PAUSE/RESUME/KILL-VM)
have zero callers outside the file itself. Deleted outright.

EVENT-EMIT/EVENT-WAIT/EVENT-DRAIN (messaging.4th Block 5030) had
exactly one live caller -- process.4th, per FABRIC-3.5.md SXXXIII.3 --
so they go with it. Block 5030 was self-contained (nothing else in
it), so the whole block was removed rather than edited down.

mkcapsule --lint capsules/ clean, 37 files / 0 violations (was 38).
Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD. dict_hash moved for Hermes and Artemis (both load
messaging.4th) but is identical across all three architectures, which
is the invariant that matters, not an unchanging absolute value
(SXXII.4). Hera's own PARITY:M7.1a snapshot is unchanged since it fires
before any capsule loads.

capsule-reserved.txt and MANIFEST.md's stale block-4055/2049 entries
still untouched -- tasks 0.5 and 0.6, now unblocked since both strips
are done.

Authorized by Captain Bob ("Yes, you may continue.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:33:42 -04:00
Robert Allan JamesandClaude Sonnet 5 a0e9725883 Strip capsules/common/msg.4th -- FABRIC-3.6.md task 0.2
Dead per task 0.1's reachability check (156d1642): zero EXEC sites in
any boot-loaded capsule, and its only two words (HERMES-ACK/
HERMES-NACK) have zero callers anywhere -- messaging.4th's own block
5033 comment already says outright that this file's ACK/NACK
indirection is retired.

mkcapsule --lint capsules/ clean, 38 files / 0 violations (was 39).
Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, dict_hash unchanged from the task 0.0 baseline on
all three -- expected, since the file was never loaded into any VM's
dictionary in the first place.

capsule-reserved.txt and MANIFEST.md's stale block-4055 entry are left
untouched here, per the punchlist's own ordering -- 0.6 returns the
freed block range and 0.5 corrects the manifest once 0.3's strip is
also done.

Authorized by Captain Bob ("Go ahead.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:24:03 -04:00
Robert Allan JamesandClaude Sonnet 5 156d1642de FABRIC-3.6.md task 0.1: Category A reachability established
Checked the three §XXII.2 routes for capsules/common/msg.4th,
capsules/process.4th, and the SPAWN-EVENT constant, never by grep
count alone: a boot-path trace of every capsule init.4th loads at
birth, a tools/experiments/docs invocation search, and confirmation
that mere presence in the baked capsule directory doesn't make a name
reachable if nothing constructs it at runtime. All three are dead by
every route -- zero EXEC sites, zero callers of their exported words.

Two findings recorded, neither changing the punchlist's plan:

tools/hermes_smoke.sh calls EVENT-EMIT/EVENT-WAIT/EVENT-DRAIN directly,
a caller FABRIC-3.5.md SXXXIII.3 missed when it said the only other
reference was MANIFEST.md. Doesn't make them live -- the script is
already broken on its own terms (references capsules/core/init.4th and
build/amd64/standard/starforth, neither exists; calls the pre-rename
CD-INIT word). Task 0.3's plan to strip these three words alongside
process.4th stands.

PAUSE-EVENT/RESUME-EVENT/KILL-EVENT are exactly as dead-by-name as
SPAWN-EVENT -- process.4th's own calls pass bare numeric literals, never
the constant names. Task 0.4 only names SPAWN-EVENT; flagged for
whoever picks up Category A stripping next rather than expanding this
task's scope.

Investigation only, no code changed.

Authorized by Captain Bob ("begin.").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:18:09 -04:00
Robert Allan JamesandClaude Sonnet 5 4544877a36 FABRIC-3.6.md task 0.0: three-ISA baseline smoke test, PASS
amd64/aarch64/riscv64 all boot clean to [zuse@Hera] ok>, zero UNKNOWN
WORD, and dict_hash identical across all three: Hera (PARITY:M7.1a)
0x6824fe5993239838, Hermes 0x062252c4da6858da, Artemis
0xed80117724c26f36. This is the gate task 0.0 exists for -- every later
task's acceptance in this document assumes this baseline is known-good.

Found and worked around a real confound along the way: disk/artemis.img
is deliberately shared across all three ISAs' qemu targets (FABRIC-3.md
SXXXV.2), so a same-order rerun has run 2 and 3 silently resume run 1's
already-formatted disk instead of formatting their own. The first
attempt (logs/20260919-124835 amd64, logs/20260919-124952 aarch64,
both kept for the record) shows exactly this: Artemis's dict_hash
diverges between the two runs even though Hera's and Hermes's do not,
because only Artemis's birth path branches on disk state. Restored
disk/artemis.img and disk/thumbdrives/zuse-thumb-ident.img to their
committed blank state before each of the three reruns that produced
the clean, matching baseline above, and recorded the finding in
FABRIC-3.6.md so a later task doesn't mistake the same confound for a
real architecture divergence.

capsules/BLOCK_MAP.md's timestamp header is regenerated by the build,
per .claude/CLAUDE.md's documented behavior for that generated file.

Authorized by Captain Bob ("begin", "clean new disk",
"document, commit, and push").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 13:08:32 -04:00
283 changed files with 1364578 additions and 1235 deletions
+34 -18
View File
@@ -11,20 +11,31 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
> **Superseded subsystem docs (Captain Bob, 2026-08-15):** `.claude/TRIPOD.md`,
> `.claude/HERMES.md`, `.claude/ARTEMIS.md`, and `.claude/CONSOLE.md` are all superseded —
> `FABRIC-0.md`, `FABRIC-1.md`, and `FABRIC-2.md` (all design history/archival as of
> 2026-09-04) and `FABRIC-3.md` (current/living, topic: bare metal boot, read this one first)
> are the sole authoritative source for Tripod/Hermes/Artemis/Console work now. The four
> subsystem docs remain in the repo as historical record only; each carries its own
> superseded-header pointing here. Do not treat them as current, do not read them for design
> authority, and do not cite them in place of `FABRIC-0.md`/`FABRIC-1.md`/`FABRIC-2.md`/
> `FABRIC-3.md`.
> 2026-09-04), `FABRIC-3.md` (current/living, topic: bare metal boot), and `FABRIC-3.5.md`/
> `FABRIC-3.6.md` (Tripod/kernel reshuffle, design + execution) are the sole authoritative
> source for Tripod/Hermes/Artemis/Console work now. The four subsystem docs remain in the
> repo as pure historical record — they describe the pre-reshuffle Hera/Hermes/Artemis fleet,
> and `.claude/HERMES.md` in particular now describes a VM that no longer exists in this
> codebase at all, not merely a superseded design. Each carries its own superseded-header
> pointing here. Do not treat them as current, do not read them for design authority, and do
> not cite them in place of `FABRIC-0.md`/`FABRIC-1.md`/`FABRIC-2.md`/`FABRIC-3.md`/
> `FABRIC-3.5.md`/`FABRIC-3.6.md`. **Decision (Captain Bob, 2026-09-22, FABRIC-3.6.md task
> 5.2): archive as-is, do not rewrite.** These four docs stay frozen at their 2026-08-15
> superseded state; they are not updated to reflect Hermes's removal, since they are already
> explicitly out of scope for current design authority and rewriting historical record to
> track a codebase it no longer describes would defeat its purpose as a record.
> **WORK IN PROGRESS — Tripod/kernel reshuffle (2026-09-19).** Hermes moves into the kernel;
> the Tripod becomes **Hera / Artemis / Hestia**. Design is complete and ruled in
> **`FABRIC-3.5.md`** (authoritative); execution is tracked in **`FABRIC-3.6.md`** — **start
> there, at its `START HERE` section.** `FABRIC-3.md` remains open and authoritative for its
> own topic (bare metal boot); nothing in the reshuffle supersedes it. **No reshuffle code has
> been written yet.** The descriptions of the Tripod elsewhere in this file describe the
> *current* fleet (Hera/Hermes/Artemis) and stay correct until the reshuffle lands.
> **Tripod/kernel reshuffle — Phases 0–4 COMPLETE (2026-09-22); Phase 5 close-out in
> progress.** Hermes moved into the kernel as kernel-Hermes (`src/starkernel/vm/kernel_
> hermes.c`); the Tripod is now **Hera / Artemis / Hestia** — **the Hermes VM, `capsules/
> hermes/init.4th`, and `capsules/common/messaging.4th` no longer exist in this codebase.**
> Design is complete and ruled in **`FABRIC-3.5.md`** (authoritative); execution is tracked in
> **`FABRIC-3.6.md`**. `FABRIC-3.md` remains open and authoritative for its own topic (bare
> metal boot); nothing in the reshuffle supersedes it. **The Tripod/fleet descriptions
> elsewhere in this file have been updated to match** (Hera/Artemis/Hestia, no Hermes) — this
> is no longer a "stays correct until it lands" caveat, it already landed. Remaining:
> Isabelle pass ✅, doc sweep (this note) ✅, SBOM/version bump/master-merge still open — see
> `FABRIC-3.6.md` Phase 5 for status.
> **Scope:** This repo is LithosAnanke — the bare-metal UEFI kernel that boots StarForth
> directly on hardware. StarForth (the hosted FORTH-79 VM) has its own separate repository
@@ -181,8 +192,11 @@ userspace runtime. No libc, no traditional OS underneath. It is the bare-metal t
removed as an active target.)
**Current status: M7.1** — capsule birth protocol, Mama FORTH vocabulary, Tripod multi-VM
fleet (Hera/Hermes/Artemis), and word-level ACL (Phases 1–7) are live; POST at boot verifies
parity hash across amd64/aarch64/riscv64 with a 453-word Mama capsule dictionary.
fleet (Hera/Artemis/Hestia — Hermes moved into the kernel as kernel-Hermes, FABRIC-3.6.md
Phase 4, 2026-09-22), and word-level ACL (Phases 1–7) are live; POST at boot verifies parity
hash across amd64/aarch64/riscv64 with a 530-word Mama capsule dictionary (word count as of
the Phase 4 strip; verify against a live `PARITY:M7.1a word_count=` line before citing, it
changes with any new C word registration).
**Key distinguishing features:**
@@ -191,9 +205,11 @@ parity hash across amd64/aarch64/riscv64 with a 453-word Mama capsule dictionary
- Content-addressed, immutable **capsules** as the primary organizational unit — no dynamic
allocator in the traditional sense; identity is a content hash (XXHash64), mutation
produces a new capsule
- **Tripod** — a named multi-VM fleet (Hera the Mama VM, two Hermes instances, Artemis)
that births, runs, and re-births independently; verified booting live pre-REPL on all
three architectures. See `.claude/TRIPOD.md`, `.claude/HERMES.md`, `.claude/ARTEMIS.md`.
- **Tripod** — a named multi-VM fleet (Hera the Mama VM, Artemis, Hestia) that births, runs,
and re-births independently; verified booting live pre-REPL on all three architectures.
Hermes moved into the kernel as kernel-Hermes (`src/starkernel/vm/kernel_hermes.c`) and is
no longer a Tripod VM — see `FABRIC-3.5.md`/`FABRIC-3.6.md`, not the archived
`.claude/TRIPOD.md`/`.claude/HERMES.md`/`.claude/ARTEMIS.md`.
- Word-level ACL security system with kernel parity (see above) — measured overhead three
orders of magnitude below the measurement floor
- Kconfig-based build configuration (~40 discoverable symbols spanning physics/heartbeat/
+105
View File
@@ -4593,6 +4593,34 @@ any checkpoint reached *during* the drain sees `depth > 1` and will not drain ag
counter that defines the safe boundary also makes the drain non-reentrant**, with no flag, no
lock and no new state.
**Amendment, found while building task 3.4 (2026-09-22): this claim is true and covers a
different hazard than the one that actually mattered.** Non-reentrant drain (the same message
cannot drain twice) is real, but `g_vm_interpret_depth` was built for *cross-VM* nesting — the
checkpoint's own comment frames it as "nested inside a `VM-EXEC`/`VM-CALL` dispatch **from
another VM's own `vm_interpret()` call**." A different VM means a different `VM` struct, so
`input_buffer`/`input_length`/`input_pos` never collide in that case. **Same-VM reentrancy —
draining calls `vm_interpret()` on the very `vm` whose own `vm_interpret()` call is still
paused on the C stack, mid-word, at the checkpoint that triggered the drain — is a genuinely
separate hazard §XLIII.5 never named.** `FABRIC-3.md` §XX had already flagged this exact class
for Hera specifically: the old messaging pump skipped her because "self-targeting `VM-EXEC`
would hit the same reentrancy class… (`input_buffer`/`input_pos` not being saved by
`vm_state_push`/`pop`)." Read directly: `VMCallState` (`vm_state_push()`/`vm_state_pop()`,
`mama_forth_words.c`) saves only `rsp`/`exit_colon`/`ecw_nesting` — never `input_buffer`,
`input_length`, or `input_pos`. Left unaddressed, the enclosing `vm_interpret()` call's own
while loop would silently lose the rest of its input line or block the moment a drain fires
mid-line — the same failure shape as the `INPUT_BUFFER_SIZE` 256 defect `.claude/CLAUDE.md`
calls non-negotiable, and trap #1 in `FABRIC-3.6.md`'s own START HERE ("a green boot is weak
evidence").
**Not a divergence from this section's ruling — the mechanism is exactly as ruled.** Cursor
preservation is the implementer's own obligation *inside* the ruled mechanism, the same way
§XLIV.1 found `mkcapsule`'s "1024-byte limit" was arithmetically right and operationally
incomplete: fixing one thing while leaving a real gap unnamed. `FABRIC-3.6.md` task 3.4's own
implementation snapshots `vm->input_buffer`/`input_length`/`input_pos`, plus `vm->mode` (a
checkpoint reached mid-colon-definition must not let a drained payload's words compile into
the enclosing definition) and `vm->error`/`abort_requested` (a bad message must not abort the
enclosing execution), around the `vm_interpret()` call, restoring all six afterward.
### XLIII.6 — Three constraints, named rather than discovered later
1. **`INPUT_BUFFER_SIZE` is 1025** — 1024 content bytes plus NUL, and `.claude/CLAUDE.md` calls
@@ -4665,3 +4693,80 @@ not edited from here. `.claude/CLAUDE.md` now carries the full 64×16 rule.
`MANIFEST.md`'s ride the strip per §XXII.5.
- ⬜ **Item 45, NEW** — carry §XLIV.1's 64-char line limit into the `experiments/bare_metal/README.md`
capsule guidance if it repeats the byte framing. **Not checked; flagged.**
---
## XLV. B1, B2, B4 SETTLED by Captain Bob (2026-09-21) — channels negotiate, the switch table is dynamic, payloads are one block
Three of Phase 3's blockers (`FABRIC-3.6.md` B1/B2/B4) ruled in one session. **These are rulings,
recorded as given; the reasoning below is the design consequence, not new design.**
### XLV.1 — B1 (item 27): negotiated channels, pub/sub, ACK/NACK
> **Messaging is publish/subscribe. There is one common channel every VM listens to. A private
> channel is created by request → grant/deny over the common channel, and the granted channel
> is a new topic with its own membership. ACK/NACK negotiation runs throughout.**
This **overrules §XXXIII.5's recommendation** (one flat broadcast membership) in favour of the
negotiation that `messaging.4th`'s CH-REQUEST/ACCEPT/CONFIRM/CLOSE already sketched. Consequences:
- **`SkHermesMembership` (task 2.1) is per-channel.** The flat list is right *per topic*; there
is now one per channel, held in a **dynamic** table with no fixed channel maximum (same
reasoning as XLV.2).
- **The common channel is a permanent topic**; every VM is subscribed from birth.
- **A deny is a NACK.** ACK/NACK are ordinary message types on the existing heat-coupled
allocator (tasks 2.2–2.7), so they draw and decay heat like any message.
- **Advised, not ruled — open for Captain Bob:** ACK the private-channel open and delivery, not
every common-channel message, since ACK-everything roughly doubles message heat draw against
the consumption economy (§XL.4).
- **Advised, not ruled — open:** who may open a channel with whom is policy and belongs in
`ACL.4th` (CLAUDE.md: policy in FORTH, never gated on `zuse_session`); kernel-Hermes should
ask, not decide. Where that hook lives must be settled before the grant task is written.
### XLV.2 — B2 (item 32): the switch table is dynamic, not a constant
> **`SK_SWITCH_MAX_SLOTS` (16) is not to be fixed and static; it becomes a dynamic component.**
Precedent already in the tree: Stadium sizes its VM quota table from RAM at boot
(`stadium_max_vm_count_val`, kmalloc'd, 2026-08-15). The switch table follows the same pattern.
**The concrete sizing rule is not yet specified** and is a task-writing prerequisite.
### XLV.3 — B4 (item 44): payload bound is one block; larger payloads chunk
> **Follow the block convention the `*.4th` files use.**
Read as (confirmed by Captain Bob 2026-09-21): a message payload is bounded to **one block =
1024 bytes** (64×16, §XLIV.1), which matches §XLIII.6.1's `INPUT_BUFFER_SIZE − 1` drain limit;
anything larger is **chunked across messages**. Chunk framing (sequence/last-chunk marking) is
a Phase 3 task-writing prerequisite. Note the 64-char line rule (§XLIV.1) governs *capsule
source blocks*; whether it also constrains message payload content is **not** ruled here.
### XLV.4 — Punch list
- ✅ **Items 27, 32, 44 — SETTLED** (§XLV.1–.3).
- ✅ **NEW** — ACK cadence (XLV.1); ACL hook for channel-open policy (XLV.1); dynamic switch-table
sizing rule (XLV.2); chunk framing (XLV.3). **SETTLED §XLVI.**
- ✅ **Phase 3 task breakdown** — drafted `FABRIC-3.6.md` tasks 3.0–3.11, 2026-09-21.
## XLVI. §XLV.4 sub-items SETTLED by Captain Bob (2026-09-21) — task 3.0 closed
All five `FABRIC-3.6.md` task 3.0 sub-items, plus task 3.3's heat-cost design point, ruled in one
session (all recommended defaults accepted):
- **3.0(a) ACK cadence:** channel-open + delivery only, not every common-channel message —
confirms §XLV.1's own advised default.
- **3.0(b) Channel-open ACL hook location:** a new word in `ACL.4th` itself (e.g.
`HERMES-CHANNEL-OPEN?`), extending its scope from per-word ACL to also cover channel-open
policy, rather than a separate policy file. Keeps "all policy in `ACL.4th`" as one rule with
no exceptions.
- **3.0(c) Dynamic switch-table sizing:** mirrors Stadium's `stadium_max_vm_count_val` pattern —
RAM-derived at boot, no separate sizing formula.
- **3.0(d) Chunk framing:** each chunk carries `(msg_id, seq, is_last)` ahead of up to 1024
bytes of payload; receiver reassembles by `msg_id`+`seq` order.
- **3.0(e) Drain cadence:** one message per outermost-interpret checkpoint (§XLIII.6.3's own
recommendation) — a backlog drains across several checkpoint hits, not in one burst.
- **Task 3.3 heat cost per publish:** one message per subscriber (separate heat draw each),
matching the existing heat-coupled allocator 1:1 — no refcount machinery to add to the
allocator/ledger.
`FABRIC-3.6.md` task 3.0 is closed by this ruling; tasks 3.1–3.7 may now be written precisely.
+1544 -51
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -14,7 +14,7 @@
# CONFIGURATION
# ==============================================================================
VERSION ?= 3.1.0
VERSION ?= 3.2.0
CC = gcc
# Isabelle configuration
@@ -744,7 +744,7 @@ sbom:
exit 1; \
fi
@syft dir:. -o spdx-json=sbom.spdx.json -o spdx=sbom.spdx \
--source-name StarForth \
--source-name LithosAnanke \
--source-version $(VERSION) \
--exclude './build/**' --exclude './tools/**' --exclude './.git/**'
@echo "✅ SBOM generated:"
+24 -11
View File
@@ -71,16 +71,28 @@ MAKEFLAGS += -j$(NPROC)
endif
# Version
# Roadmap (per docs/lithosananke/ROADMAP.md "Release Versioning Policy" and
# FABRIC-2.md §G — X.0.0 = QEMU release, X.5.0 = hardware bare-metal release):
# v1.0.x — serial-only production (released)
# v1.5.x — framebuffer VT100 terminal/console milestone (released)
# v2.0.0 — QEMU release (even major = LTS): three-arch QEMU story complete
# v2.0.1 — SER5 hardware-track line: RDRAND backend + generic thumbdrive image goal
# v2.2.0 — amd64 bare-metal (Beelink SER5) — see ROADMAP "Board-by-board rollout"
# v2.5.0 — hardware bare-metal release: real per-arch RNG + real-board boot
VERSION ?= 3.1.0
LITHOS_VERSION ?= 2.0.0
# Versioning policy (FABRIC-3.5.md §XXX, ratified 2026-09-19, replaces the old
# X.0.0/X.5.0 QEMU/hardware encoding this comment used to carry):
# Major: ODD = LTS line (non-breaking fixes only). EVEN = working line
# (breaking changes land here). Minor: release within the line.
# Patch: working builds within a release.
# v1.0.x — serial-only production (released, historical encoding)
# v1.5.x — framebuffer VT100 console milestone (released, historical encoding)
# v2.0.0 — QEMU release: three-arch QEMU story complete (released)
# v2.0.1 — SER5 hardware-track line (historical; superseded by this policy)
# v2.1.0 — Tripod/kernel reshuffle: Hermes into the kernel, Tripod = Hera/Artemis/Hestia
# v2.2.0 — amd64 bare-metal bring-up (Beelink SER5)
# v2.x — further working releases; riscv64 / aarch64 board bring-up
# v3.0.0 — FIRST LTS, when and only when FABRIC-3.5.md §XXX.5's 5 criteria are met
# LITHOS_VERSION (kernel) and VERSION (embedded StarForth engine) are independent
# and do not auto-sync (§XXX.4) — do not infer a relationship if they ever coincide.
# Engine VERSION bumps at tag time by what actually changed (§XXX.6): major = any
# FORTH-79-visible word semantics change; minor = words added/removed/relocated;
# patch = build-only. This reshuffle is a minor bump: BIRTH's registration widened,
# the messaging layer was replaced by kernel-Hermes, PLOT/FB-* relocated to Hestia —
# all dictionary-visible, no FORTH-79 word semantics changed.
VERSION ?= 3.2.0
LITHOS_VERSION ?= 2.1.0
# ==============================================================================
# BUILD PATHS
@@ -552,7 +564,8 @@ LOADER_EXTRA_SRCS := \
$(KERNEL_SRC)/vm/stadium.c \
$(KERNEL_SRC)/vm/stadium_words.c \
$(KERNEL_SRC)/vm/stadium_blocks.c \
$(KERNEL_SRC)/vm/session.c
$(KERNEL_SRC)/vm/session.c \
$(KERNEL_SRC)/vm/kernel_hermes.c
KERNEL_EXTRA_SRCS := $(LOADER_EXTRA_SRCS)
+10
View File
@@ -98,6 +98,16 @@ Block 4007
( rewired: physics-style regression belongs to the kernel )
( exclusively, and this file is deliberately host-portable. )
Block 4008
( HERMES-CHANNEL-OPEN? -- FABRIC-3.6.md task 3.7 hook. )
( Stack: req-hi req-lo -- allow? Kernel-Hermes asks )
( this word, never decides in C, never gates on )
( zuse_session (CLAUDE.md). Default: approve every )
( request. Policy authors edit THIS word's body only -- )
( kernel_hermes.c's own query function never changes. )
: HERMES-CHANNEL-OPEN? ( req-hi req-lo -- allow? )
2DROP 1 ;
Block 4015
( Self-activation - runs after all ACL words are defined )
ACL-BOOT
+85 -130
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-16T19:45:24Z -->
<!-- Generated by mkcapsule --manifest 2026-09-22T22:29:26Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -8,27 +8,24 @@
| Capsule | Blocks claimed | xxHash64 | Signed |
|---------|----------------|----------|--------|
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4015 | `0xd781d22148ff171d` | yes |
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4015 | `0xf8890c05c0d8f921` | yes |
| `acl-std79.4th` | 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048 | `0x773bf9209df191d1` | yes |
| `artemis:init.4th` | 4110, 4111, 4112, 4113, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4177, 4178, 4179, 4180, 4181, 4182, 4851, 4852, 4853, 4854, 4856, 4857, 4858, 4860 | `0xf55edc4e76a8c294` | yes |
| `artemis:init.4th` | 4110, 4111, 4112, 4113, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4177, 4178, 4179, 4180, 4181, 4182, 4851, 4852, 4853, 4854, 4856, 4857, 4858, 4860 | `0xe6fba9ae56e1c916` | yes |
| `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | yes |
| `common:messaging.4th` | 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042 | `0x201cfd6d39fcb22d` | yes |
| `common:msg.4th` | 4055 | `0x850a0382344ea6c4` | yes |
| `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x3d4549142d91ec20` | yes |
| `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x26fb485e5c9dc6ff` | yes |
| `doe.4th` | 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107 | `0xf154616d248e861f` | yes |
| `fabric.4th` | 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 5000, 5001, 5002 | `0x9d9489cbeca4099b` | yes |
| `font.4th` | 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985 | `0x3f305911500c78f6` | yes |
| `hermes:init.4th` | 4153, 4855, 5116 | `0x2df61924448a6812` | yes |
| `hestia:init.4th` | 4986, 4987, 4988 | `0x64e111990fbc45ff` | yes |
| `init-l8-diverse.4th` | 4820, 4821, 4822 | `0xaa293201a6c91838` | yes |
| `init-l8-omni.4th` | 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079 | `0x5979e314d6452045` | yes |
| `init-l8-stable.4th` | 4806 | `0xdc3830f189063a9a` | yes |
| `init-l8-temporal.4th` | 4830, 4831 | `0x51abd4c138246651` | yes |
| `init-l8-transition.4th` | 4840, 4841, 4842 | `0xbcc1a81976f0a4c9` | yes |
| `init-l8-volatile.4th` | 4810, 4811, 4812, 4813 | `0x98caabbbd92abac4` | yes |
| `init.4th` | 2049, 2050, 2057 | `0x1ef4939ed32ec1e6` | yes |
| `init.4th` | 2049, 2050, 2057 | `0xea038ba684c53443` | yes |
| `lib.4th` | 4050 | `0x4b216635c359ef73` | yes |
| `multiuser-doe.4th` | 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055 | `0x22140588ee7c39e6` | yes |
| `process.4th` | 4300, 4301 | `0x781afc1dbd0294f7` | yes |
| `sdk.4th` | 5109, 5110, 5111, 5112, 5113, 5114, 5115 | `0x008fdbbb62c94a3a` | yes |
| `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | yes |
| `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | yes |
@@ -45,16 +42,16 @@
| `workload-8.4th` | 2160 | `0x56b7f2f0efa000df` | yes |
| `workload-9.4th` | 4706, 4715, 4725, 4735, 4745 | `0x3f2bec73142aa424` | yes |
| `workload-calib1.4th` | 5043 | `0x3b9f2d17b554fabc` | yes |
| `zuse-eligibility.4th` | 4021, 4022 | `0x8b49c1bc1e01dc58` | yes |
| `zuse-eligibility.4th` | 4021, 4022 | `0x7b28f4776a32e0b7` | yes |
| `zuse.4th` | 4016, 4017, 4018 | `0x490ded9be257a90b` | yes |
## Block Map (sorted by LBN)
| LBN | Capsule | xxHash64 | Status |
|-----|---------|----------|--------|
| 2049 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
| 2050 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
| 2057 | `init.4th` | `0x1ef4939ed32ec1e6` | ok |
| 2049 | `init.4th` | `0xea038ba684c53443` | ok |
| 2050 | `init.4th` | `0xea038ba684c53443` | ok |
| 2057 | `init.4th` | `0xea038ba684c53443` | ok |
| 2064 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2065 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2066 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
@@ -102,22 +99,23 @@
| 2160 | `workload-8.4th` | `0x56b7f2f0efa000df` | ok |
| 2200 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
| 2201 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
| 4000 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4001 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4002 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4003 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4004 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4005 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4006 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4007 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4015 | `ACL.4th` | `0xd781d22148ff171d` | ok |
| 4000 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4001 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4002 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4003 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4004 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4005 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4006 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4007 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4008 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4015 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4016 | `zuse.4th` | `0x490ded9be257a90b` | ok |
| 4017 | `zuse.4th` | `0x490ded9be257a90b` | ok |
| 4018 | `zuse.4th` | `0x490ded9be257a90b` | ok |
| 4019 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok |
| 4020 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok |
| 4021 | `zuse-eligibility.4th` | `0x8b49c1bc1e01dc58` | ok |
| 4022 | `zuse-eligibility.4th` | `0x8b49c1bc1e01dc58` | ok |
| 4021 | `zuse-eligibility.4th` | `0x7b28f4776a32e0b7` | ok |
| 4022 | `zuse-eligibility.4th` | `0x7b28f4776a32e0b7` | ok |
| 4023 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4024 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4025 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
@@ -145,64 +143,60 @@
| 4047 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4048 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4050 | `lib.4th` | `0x4b216635c359ef73` | ok |
| 4055 | `common:msg.4th` | `0x850a0382344ea6c4` | ok |
| 4060 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4061 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4062 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4063 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4064 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4065 | `doe-campaign.4th` | `0x3d4549142d91ec20` | ok |
| 4110 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4111 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4112 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4113 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4122 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4123 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4124 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4125 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4126 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4127 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4128 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4129 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4130 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4131 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4132 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4133 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4134 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4135 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4136 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4137 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4138 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4139 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4140 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4141 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4153 | `hermes:init.4th` | `0x2df61924448a6812` | ok |
| 4160 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4161 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4162 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4163 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4164 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4165 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4166 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4167 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4168 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4169 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4170 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4171 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4172 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4173 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4174 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4177 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4178 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4179 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4180 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4181 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4182 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4060 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4061 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4062 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4063 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4064 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4065 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4110 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4111 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4112 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4113 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4122 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4123 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4124 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4125 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4126 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4127 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4128 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4129 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4130 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4131 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4132 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4133 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4134 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4135 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4136 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4137 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4138 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4139 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4140 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4141 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4160 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4161 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4162 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4163 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4164 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4165 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4166 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4167 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4168 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4169 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4170 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4171 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4172 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4173 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4174 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4177 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4178 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4179 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4180 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4181 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4182 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4200 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
| 4201 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
| 4202 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
| 4300 | `process.4th` | `0x781afc1dbd0294f7` | ok |
| 4301 | `process.4th` | `0x781afc1dbd0294f7` | ok |
| 4406 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
| 4415 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
| 4425 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
@@ -237,15 +231,14 @@
| 4840 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4841 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4842 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4851 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4852 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4853 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4854 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4855 | `hermes:init.4th` | `0x2df61924448a6812` | ok |
| 4856 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4857 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4858 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4860 | `artemis:init.4th` | `0xf55edc4e76a8c294` | ok |
| 4851 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4852 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4853 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4854 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4856 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4857 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4858 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4860 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4900 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 4901 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 4902 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
@@ -332,49 +325,12 @@
| 4983 | `font.4th` | `0x3f305911500c78f6` | ok |
| 4984 | `font.4th` | `0x3f305911500c78f6` | ok |
| 4985 | `font.4th` | `0x3f305911500c78f6` | ok |
| 4986 | `hestia:init.4th` | `0x64e111990fbc45ff` | ok |
| 4987 | `hestia:init.4th` | `0x64e111990fbc45ff` | ok |
| 4988 | `hestia:init.4th` | `0x64e111990fbc45ff` | ok |
| 5000 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 5001 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 5002 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 5003 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5004 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5005 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5006 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5007 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5008 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5009 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5010 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5011 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5012 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5013 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5014 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5015 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5016 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5017 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5018 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5019 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5020 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5021 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5022 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5023 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5024 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5025 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5026 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5027 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5028 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5029 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5030 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5031 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5032 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5033 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5034 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5035 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5036 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5037 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5038 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5039 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5040 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5041 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5042 | `common:messaging.4th` | `0x201cfd6d39fcb22d` | ok |
| 5043 | `workload-calib1.4th` | `0x3b9f2d17b554fabc` | ok |
| 5044 | `multiuser-doe.4th` | `0x22140588ee7c39e6` | ok |
| 5045 | `multiuser-doe.4th` | `0x22140588ee7c39e6` | ok |
@@ -408,11 +364,10 @@
| 5113 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5116 | `hermes:init.4th` | `0x2df61924448a6812` | ok |
## Conflicts
None.
---
*39 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
*36 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
+87 -74
View File
@@ -49,7 +49,7 @@ Blocks: **2049–2052, 2057**
| Block | Immutable | Justification |
|-------|-----------|---------------|
| 2049 | No | Hera VM init: loads compudynamics, VM-INIT, lib, common:msg, fleet-k, process; BIRTHs Artemis + Hermes. VM-TREE + VM-CHILDREN implemented (`b52281b9`), unrolled for v1 Tripod |
| 2049 | No | Hera VM init: `VM-TREE`/`VM-PARENT`/`VM-CHILDREN`; loads `ACL.4th`, `block-acl.4th`, `zuse-eligibility.4th`, `lib.4th`. **Corrected 2026-09-19 (three times)** — first pass removed a stale listing of `compudynamics`/`common:msg`/`fleet-k`/`process` (none loaded here; two already-deleted, two stripped in the same pass, FABRIC-3.6.md tasks 0.2/0.3). Second pass (same day): `fabric.4th`/`font.4th` **removed** from this list — relocated to `hestia/init.4th` (FABRIC-3.6.md tasks 1.6/1.7), Hera no longer loads either. Third pass (2026-09-22, FABRIC-3.6.md Phase 4 Stage E): `common:messaging.4th` + `MSG-CD-INIT` **removed** — the file itself is deleted (see "Deleted capsules" below); every FORTH-owned message type was cut over to kernel-Hermes first (Phase 3) |
| 2050 | No | BOOT-BANNER call — separated so the banner block can be swapped without touching init logic |
| 2051 | No | TRIPOD-TEST — 6 acceptance gates per TRIPOD.md. Dead EVENT-WAIT step replaced with HERMES-TICK liveness check (`3436d564`) |
| 2052 | No | TRIPOD-TEST invocation block |
@@ -308,14 +308,6 @@ Blocks: **4050**
|-------|-----------|---------------|
| 4050 | No | N. COMMA CRLF CSV-COL CSV-LAST Q.SHOW USE RUN. Not immutable: these are utilities; adding words is safe. Removing or renaming existing words requires audit of all callers |
### `common/msg.4th` — Hermes participant interface
Blocks: **4055**
| Block | Immutable | Justification |
|-------|-----------|---------------|
| 4055 | Yes | HERMES-ACK / HERMES-NACK. Immutable: this is the cross-VM ACK/NACK ABI. Every messaging VM (Hera, Hermes, Artemis) loads this at birth. Changing the block or the word names breaks the Hermes delivery protocol |
### `doe-campaign.4th` — DoE campaign harness
Blocks: **4060–4065**
@@ -325,74 +317,51 @@ Blocks: **4060–4065**
matched the file at any point on record. Rewritten to match the actual
content, migrated this pass off the deleted `compudynamics.4th`/
`fleet-k.4th` primitives onto the `VM-PHYSICS-STATUS`/`VM-CONSERVED?`
mechanism — see `capsules/hermes/init.4th` block 4153 and
mechanism — see (historical) `hermes/init.4th` block 4153 and
`capsules/artemis/init.4th` block 4852 for the companion `LOAD-DOE` fix
this migration also required.
**Note (2026-09-22, FABRIC-3.6.md Phase 4 Stage E):** `SETUP-HERMES` and every
Hermes touch in `PHASE1-DOE`/`CD-TICK`/`SMOKE-CAMPAIGN` removed — Hermes no
longer exists. Every block below is now Artemis-only.
| Block | Immutable | Justification |
|-------|-----------|---------------|
| 4060 | No | `SETUP-HERMES`/`SETUP-ARTEMIS`/`SETUP-VMS`: `BIRTH` + remote `LOAD-DOE` VM-EXEC per child VM. Not immutable: setup sequence may grow |
| 4061 | No | `PHASE1-DOE`: real per-VM `DOE-WORK` baseline touches. Historical note: dead `CD-WORK` (index-dispatch, deleted VM-HERA/HERMES/ARTEMIS constants) removed here 2026-07-08 |
| 4062 | No | `CD-TICK`/`CD-DOE`: one real fleet-touch pass (`VM-EXEC "DOE-WORK"` on Hermes+Artemis), looped N times. `CAMPAIGN-STATUS`: `VM-PHYSICS-STATUS` + `VM-CONSERVED?` check. Not immutable: workload/status content may evolve |
| 4060 | No | `SETUP-ARTEMIS`/`SETUP-VMS`: `BIRTH` + remote `LOAD-DOE` VM-EXEC on Artemis. Not immutable: setup sequence may grow |
| 4061 | No | `PHASE1-DOE`: real per-VM `DOE-WORK` baseline touch, Artemis only. Historical note: dead `CD-WORK` (index-dispatch, deleted VM-HERA/HERMES/ARTEMIS constants) removed here 2026-07-08 |
| 4062 | No | `CD-TICK`/`CD-DOE`: one real fleet-touch pass (`VM-EXEC "DOE-WORK"` on Artemis), looped N times. `CAMPAIGN-STATUS`: `VM-PHYSICS-STATUS` + `VM-CONSERVED?` check. Not immutable: workload/status content may evolve |
| 4063 | No | `CAMPAIGN`: full campaign — baselines then 30 real fleet touches |
| 4064 | No | `SMOKE-CAMPAIGN`: 1-rep seed-1959 smoke test + 16 real fleet touches |
| 4065 | No | `THREE-VM-CAMPAIGN`: loads `doe.4th` locally on Hera, then 48 real fleet touches, all three VMs as Compudynamics peers |
### `hermes/init.4th` — Hermes VM (messenger)
### `hermes/init.4th` — DELETED 2026-09-22 (formerly Hermes VM, the messenger)
Blocks: **4100–4109, 4114–4121, 4142–4153**
**Deleted, FABRIC-3.6.md Phase 4 Stage E (task 4.1).** Formerly blocks
**4100–4109, 4114–4121, 4142–4153** (gaps 4110–4113 and 4122–4141 were always
Artemis's, hard-locked, never Hermes's — see the `artemis/init.4th` entry below,
unaffected by this deletion). Every FORTH-owned message type this file's
`messaging.4th` companion implemented (`BLK-ATTACH-EVENT`, `CONSOLE-CMD-EVENT`,
`ELEVATE-REQUEST`) was cut over to kernel-Hermes first (Phase 3, tasks 3.8–3.10),
verified live on all three architectures at each step; only then was the Hermes
VM itself, this capsule, and `capsules/common/messaging.4th` removed. Full
three-architecture acceptance for the deletion: `logs/20260922-181141/amd64/`,
`logs/20260922-181753/aarch64/`, `logs/20260922-182136/riscv64/` — zero
`UNKNOWN WORD`, identical `dict_hash` across all three. See FABRIC-3.6.md's own
Phase 4 entry for the full account, including one found-not-fixed collateral
defect (`SEND-ELEVATE-REQUEST`, this file's own former caller into
`zuse-eligibility.4th`'s `ELEVATE-GRANT`, is now unreachable — Captain Bob's
2026-09-22 decision: leave it, Phase 8 PKI will build its own entrypoint).
Former blocks 4100–4153 (ex-Artemis-gaps) are now UNASSIGNED — see Unassigned
Ranges below. The per-block justification table this section used to carry
(arena allocator ABI, message/channel field accessors, the VM-name routing
table, channel negotiation, broadcast) is not reproduced here; it is historical
detail about deleted code, recoverable from git history (`git show
<pre-strip-commit>:capsules/hermes/init.4th`) if ever needed again.
Gap 4110–4113 = Artemis. **HARD LOCKED. Never touch from Hermes side.**
Gap 4122–4141 = Artemis (extended — see below). Never touch from Hermes side.
| Block | Immutable | Justification |
|-------|-----------|---------------|
| 4100 | Yes | Hermes constants: event codes, channel states, node sizes, arena sizes, MSG-DELIVERED. Immutable: changing node size constants corrupts all arena math |
| 4101 | Yes | Arena CREATE: MSG-ARENA CH-ARENA MBR-ARENA; free-list roots; MSG-SEQ CH-ACTIVE. Immutable: CREATE allocates memory at compile time; re-running changes VM memory layout |
| 4102 | Yes | MSG-INIT-FREE + CH-INIT-FREE. Immutable: free-list init is called once from CD-INIT; structure change breaks allocator |
| 4103 | Yes | MBR-INIT-FREE + MSG-ALLOC + MSG-FREE-NODE. Immutable: allocator ABI; MSG-ALLOC is called by every MSG-SEND |
| 4104 | Yes | CH-ALLOC + CH-FREE-NODE + MBR-ALLOC + MBR-FREE-NODE. Immutable: same allocator ABI constraint |
| 4105 | Yes | Message field accessors (MSG-TYPE@/! through MSG-SEQ@/!). Immutable: field offsets are load-bearing; changing breaks every accessor caller |
| 4106 | Yes | Channel + member accessors (CH-ID@/! through MBR-VM@). Immutable: same field offset constraint |
| 4107 | No | VARIABLE MSG-LAST-MSG + IDX>NAME + MSG-DELIVER. Not fully immutable: MSG-DELIVER may evolve for async model. IDX>NAME now a table lookup over VM-NAME-ADDRS/LENS (see 4142) |
| 4108 | No | MSG-SEND. Not immutable: send protocol may evolve |
| 4109 | No | MSG-REAP. Ordering bug fixed (`8ca0cda2`) — type cleared before free-node prepend |
| — | — | 4110–4113: ARTEMIS. NEVER TOUCH. |
| 4114 | No | VARIABLE CH-SCAN + CH-COOL-ALL + CH-TOTAL-HEAT. Not immutable: channel cooling may evolve |
| 4115 | No | CH-REAP-SAFE. Not immutable: channel reaping logic may evolve |
| 4116 | No | VARIABLE COMMON-CH + COMMON-INIT + HERMES-TICK. Not immutable: HERMES-TICK drives the event loop; may grow |
| 4117 | No | EVENT-EMIT + EVENT-WAIT + EVENT-DRAIN (backward compat). Not immutable: EVENT-WAIT is a diagnostic peek only per HERMES.md |
| — | — | 4118: reserved, currently empty (former HERA-NOTIFY-SPAWN/KILL, removed `9323f776` — notification is automatic via `vm_physics_init`/`retire`) |
| 4119 | No | CH-MINT-ID + CH-REQUEST. Not immutable: channel negotiation protocol may expand (multi-party invite deferred) |
| 4120 | No | CD-INIT. Not immutable: init sequence may grow |
| 4121 | No | MSG-ACK-LAST + MSG-NACK-LAST. Not immutable: NACK-requeue (reduced heat, retry) deferred; block may need extension |
| — | — | 4122–4141: ARTEMIS (extended). NEVER TOUCH. |
| 4142 | No | VM name routing table: VM-NAME-ADDRS/LENS + VM-NAME-REG + VM-NAMES-INIT. Not immutable: table-driven, grows via VM-MAX |
| 4143 | Yes | MSG-CH@/! + MSG-ORIG-TYPE@/! + MSG-NACKED. Immutable: field offset constraint, same as 4105 |
| 4144 | No | MSG-SEND. Not immutable: send protocol may evolve |
| 4145 | No | MSG-TOTAL-HEAT + MSG-REDELIVER-NACKED. Not immutable: cooling/redelivery logic may evolve |
| 4146 | No | MSG-DELIVER-ALL. Not immutable: delivery logic may evolve |
| 4147 | No | HERMES-K + WELCOME. Not immutable: may grow |
| 4148 | No | CH-ACCEPT + CH-CONFIRM + CH-CLOSE. Not immutable: channel negotiation protocol may expand |
| 4149 | No | HERMES-STATUS (MSG-USED + CH-USED). Not immutable: status may expand |
| 4150 | No | Member management: MBR-NEXT!/VM! + CH-ADD-MBR + HERMES-MSG-TEST. Not immutable: may grow |
| 4151 | No | Phase 2 real multi-member broadcast: MSG-BROADCAST + BC-* variables. Not immutable: broadcast protocol may expand |
| 4152 | No | Phase 2 COMMON-CH membership + test: BCAST-GOT/BCAST-RECV/REGISTER-COMMON-MEMBERS/SEND-BROADCAST-TEST. Not immutable: test harness may grow |
| 4153 | No | `LOAD-DOE` ( -- ): `S" doe.4th" EXEC`. Added 2026-07-08 — `doe-campaign.4th`'s `SETUP-HERMES` calls this remotely so Hermes gets `DOE-WORK`; was missing entirely before this pass, so `doe-campaign.4th` could never have worked even pre-dating the VM-fleet-physics redesign. Not immutable: trivial wrapper |
**2026-07-05 collision fix:** blocks 4142–4150 were previously numbered
4122–4131 (interleaved with the blocks below them in this list), directly
colliding with Artemis's real block range. The collision was introduced
`fca7b09a` (Jul 1) when the VM-name routing table was added without
checking MANIFEST.md, and went undetected for 4 days because `mkcapsule`'s
build path doesn't run conflict detection (only `--manifest` does). Found
via `mkcapsule --manifest` while syncing this document; renumbered into
genuinely free space and reverified with a clean amd64 TRIPOD-TEST boot
(`PASS: fleet K`, `PASS: Hermes liveness`, `PASS: Artemis ready`, `K soak`,
`PASS: E2E msg flow` — Hermes's kill/rebirth soak test reproduced an
identical `dict_hash` before and after, confirming the reload path is now
clean). amd64-only per the rev-f iteration rule; three-arch not yet run for
this fix. See Conflict Register entry C5.
**2026-07-05 collision fix (historical, still relevant to Conflict Register
C5 below):** blocks 4142–4150 were previously numbered 4122–4131, directly
colliding with Artemis's real block range, introduced `fca7b09a` (Jul 1),
found and resolved via `mkcapsule --manifest`. See Conflict Register entry C5.
### `artemis/init.4th` — Artemis VM (flat pool disk manager v2)
@@ -439,14 +408,19 @@ Hermes (see above). The table below reflects the actual current footprint.
| 4851 | No | ART-PING ( -- ): cheap O(1) touch target for Phase 3 fleet DoE workload, unlike ART-TICK/ART-STATUS which scan all ART-DATA-BLKS. Not immutable: may extend |
| 4852 | No | `LOAD-DOE` ( -- ): `S" doe.4th" EXEC`. Added 2026-07-08 — same missing-word fix as `hermes/init.4th` 4153; `doe-campaign.4th`'s `SETUP-ARTEMIS` calls this remotely. Not immutable: trivial wrapper |
### `process.4th` — VM process management
### `hestia/init.4th` — Hestia VM (third Tripod leg, bind point)
Blocks: **4300–4301**
Blocks: **4986–4988** (allocated 4986–4996, FABRIC-3.6.md task 1.1; 3 of the 11 used so far)
Added 2026-09-19 (FABRIC-3.6.md tasks 1.2/1.4/1.6/1.7, Tripod/kernel reshuffle — see
FABRIC-3.5.md §II/§IV). Reconstitutes the Tripod as Hera/Artemis/Hestia. Birthed (task 1.4)
and owns the drawing fabric (`fabric.4th`/`font.4th`, tasks 1.6/1.7 — see block 4988).
| Block | Immutable | Justification |
|-------|-----------|---------------|
| 4300 | No | Event code constants + SPAWN + PAUSE lifecycle operators. Not immutable: process model may evolve |
| 4301 | No | RESUME + KILL-VM. Not immutable: process model may evolve |
| 4986 | No | `WELCOME` banner word + call. Not immutable: message text may change |
| 4988 | No | `S" fabric.4th" EXEC` + `S" font.4th" EXEC` — moved here from `init.4th` (Hera), tasks 1.6/1.7, **merged into one commit rather than done separately as the punchlist originally split them**: `font.4th` calls `G-LINE`/`G-ELLIPSE`, which are `fabric.4th`'s own words, so moving one without the other strands the dependency in whichever VM keeps only half — confirmed live, moving `fabric.4th` alone floods Hera's boot with `UNKNOWN WORD: 'G-LINE'`. Order preserved (`fabric.4th` before `font.4th`), matching `init.4th`'s own prior load order. Not immutable: may grow if more of the drawing/font surface relocates here |
| 4987 | No | **Rewritten 2026-09-22, FABRIC-3.6.md Phase 4 Stage E.** Originally joined `COMMON-CH` on slot 11 (Hera/Hermes/Artemis held 0/1/2, identities held 3–10, `messaging.4th:78-85`) — that whole `COMMON-CH` concept no longer exists, `messaging.4th` is deleted. Now just `S" lib.4th" EXEC` + `LOG-INFO" Hestia: ready"` + `STARTUP-BANNER`. Not immutable: startup sequence may grow |
### Deleted capsules (historical)
@@ -458,6 +432,31 @@ generalized VM fleet physics mechanism (`capsule_vm_physics.c`/`.h`,
and `docs/working/archive/session-logs/2026-07-05-worklog.md`. Their
former ranges are now UNASSIGNED (see Namespace Map).
`common/msg.4th` (formerly 4055) and `process.4th` (formerly 4300–4301)
were deleted 2026-09-19 (FABRIC-3.6.md tasks 0.2/0.3, part of the
Tripod/kernel reshuffle's Category A surgical strip — see FABRIC-3.5.md
§XXII). Both were confirmed dead by all three of §XXII.2's reachability
routes: zero `EXEC` sites in any boot-loaded capsule, and zero callers
anywhere of their exported words (`HERMES-ACK`/`HERMES-NACK` for the
former; `SPAWN`/`PAUSE`/`RESUME`/`KILL-VM` for the latter).
`common/msg.4th`'s block-4055 entry had claimed it was an immutable ABI
"every messaging VM loads at birth" — `FABRIC-2.md:2773` had already
flagged that claim as stale before this correction. `process.4th`'s
removal also took `messaging.4th`'s `EVENT-EMIT`/`EVENT-WAIT`/
`EVENT-DRAIN` (former block 5030) with it, its only live caller. Their
former ranges are now UNASSIGNED (see Namespace Map).
`hermes/init.4th` (formerly 4100–4109, 4114–4121, 4142–4153) and
`common/messaging.4th` were deleted 2026-09-22 (FABRIC-3.6.md Phase 4 Stage E,
tasks 4.1/4.3), the final step of the Tripod/kernel reshuffle — the Hermes VM
itself and its FORTH messaging layer, superseded by kernel-Hermes
(`src/starkernel/vm/kernel_hermes.c`) after every live message type was cut
over in Phase 3 (see the `hermes/init.4th` entry above for the full account).
Their former ranges are now UNASSIGNED (see Namespace Map). This is the same
"cut over first, delete after, one commit per Category B item, verified on all
three architectures" discipline `compudynamics.4th`/`fleet-k.4th` and
`common/msg.4th`/`process.4th` were deleted under above.
---
## Unassigned Ranges
@@ -476,14 +475,16 @@ former ranges are now UNASSIGNED (see Namespace Map).
| 4008–4009 | UNASSIGNED | ACL extension space |
| 4019–4049 | UNASSIGNED | ACL / zuse extension space |
| 4051–4054 | UNASSIGNED | lib.4th extension space |
| 4056–4059 | UNASSIGNED | common:msg extension space |
| 4055–4059 | UNASSIGNED | Former `common/msg.4th` range (deleted 2026-09-19, FABRIC-3.6.md task 0.2) |
| 4066–4099 | UNASSIGNED | doe-campaign extension space |
| 4154–4199 | UNASSIGNED | Hermes extension space (post-4153) |
| 4100–4153 | UNASSIGNED | Former `hermes/init.4th` range (deleted 2026-09-22, FABRIC-3.6.md Phase 4 Stage E task 4.1). Excludes 4110–4113/4122–4141, which were always Artemis's, hard-locked, unaffected |
| 4154–4199 | UNASSIGNED | Hermes extension space (post-4153), now moot along with 4100–4153 above |
| 4200–4299 | UNASSIGNED | Former compudynamics.4th range (deleted `9323f776`) |
| 4302–4399 | UNASSIGNED | process extension space |
| 4300–4399 | UNASSIGNED | Former `process.4th` range (deleted 2026-09-19, FABRIC-3.6.md task 0.3) |
| 4400–4405 | UNASSIGNED | Former fleet-k.4th range (deleted `9323f776`) |
| 4410–4414, 4420–4424, 4430–4434 | UNASSIGNED | workload-1.4th's private zone, room for growth |
| 4853+ | OPEN | Future capsules — claim here first |
| 4986–4996 | CLAIMED | `hestia/init.4th`, allocated 2026-09-19 (FABRIC-3.6.md task 1.1, Tripod/kernel reshuffle) — file not yet created (task 1.2). Sits between `font.4th`'s last block (4985) and the console proxy's hardcoded `Block 4997` (`capsule_console.c:27-29`) — chosen specifically to avoid 4997, per §XVIII.4 |
| 4853–4985, 4998+ | OPEN | Future capsules — claim here first (excludes 4900–4985, already `fabric.4th`/`font.4th`, and 4986–4996, now claimed above) |
---
@@ -536,3 +537,15 @@ before this doc pass. Not re-verified this pass: whether every other
still-unflagged row elsewhere in this document matches source exactly —
this was a targeted correction of the rows touched by recent work plus
`doe.4th`/`ACL.4th`, not a full line-by-line re-audit of all ~250 blocks.*
*Doc-debt pass, 2026-09-22 — MANIFEST.md updated to ride the Tripod/kernel
reshuffle's Category B strip (FABRIC-3.6.md Phase 4 Stage E, task 5.2 close-out
sweep, §XXII.5). `hermes/init.4th`'s block-by-block table replaced with a
deletion note (git history retains the detail); `common/messaging.4th`'s
deletion recorded in "Deleted capsules"; `init.4th` block 2049,
`doe-campaign.4th` blocks 4060–4062, and `hestia/init.4th` block 4987 updated
to match the post-strip live files (verified by direct read, not by this
document's own prior claims, same discipline as every other pass here).
Former Hermes range (4100–4153, excluding Artemis's hard-locked 4110–4113/
4122–4141) marked UNASSIGNED. Not re-verified this pass: the ~230 other rows
this strip didn't touch.*
+7 -11
View File
@@ -492,13 +492,9 @@ Block 4853
CD-INIT
S" lib.4th" EXEC
Block 4854
( Phase C 2026-08-28: own messaging vocab + subscribe into )
( Hermes's canonical COMMON-CH (idx 2 = Artemis, VM-NAMES- )
( INIT). Hermes always exists by Artemis's birth. )
S" common:messaging.4th" EXEC
MSG-CD-INIT
2 MY-CH-ID !
S" 2 COMMON-CH @ CH-ADD-MBR" S" Hermes" VM-EXEC
( FABRIC-3.6.md Phase 4, Stage E: common:messaging.4th/ )
( MSG-CD-INIT/MY-CH-ID/COMMON-CH subscription all removed )
( -- Hermes, the channel, and the words are all gone. )
STARTUP-BANNER
Block 4856
@@ -525,8 +521,9 @@ Block 4857
Block 4858
( HERA-BLK-ATTACH-REQ ( dev-addr -- ): VM-EXEC'd by MSG- )
( DELIVER when Hera's request arrives. Runs BLK-ATTACH on )
( Artemis's own dictionary (real ACL gating, same as any )
( other message payload), then replies to Hera (idx 0). )
( Artemis's own dictionary, then replies to Hera via kernel- )
( Hermes's KH-BLK-ATTACH-SEND (repl.c) -- FABRIC-3.6.md task )
( 3.8 Stage C, FORTH Hermes no longer sees this message type. )
: HERA-BLK-ATTACH-REQ ( dev-addr -- )
0 ATTACH-ACK-LEN !
DUP ACK-APPEND-NUM
@@ -535,8 +532,7 @@ Block 4858
DROP
BL ACK-APPEND-CHAR
S" BLK-ATTACH-ACK" ACK-APPEND
BLK-ATTACH-EVENT 2 0 ATTACH-ACK-BUF
ATTACH-ACK-LEN @ 0 MSG-SEND ;
ATTACH-ACK-BUF ATTACH-ACK-LEN @ KH-BLK-ATTACH-SEND DROP ;
Block 4860
( LOG-APPEND ( level ts msg-addr msg-u -- ) )
-504
View File
@@ -1,504 +0,0 @@
Block 5003
( common:messaging.4th -- generic per-VM messaging vocab. )
1 CONSTANT SPAWN-EVENT
2 CONSTANT PAUSE-EVENT
3 CONSTANT RESUME-EVENT
4 CONSTANT KILL-EVENT
0 CONSTANT CH-NEGOTIATING
1 CONSTANT CH-OPEN
2 CONSTANT CH-CLOSING
9 CONSTANT MSG-CELLS
6 CONSTANT CH-CELLS
2 CONSTANT MBR-CELLS
32 CONSTANT MSG-MAX
16 CONSTANT CH-MAX
64 CONSTANT MBR-MAX
65208 CONSTANT Q-DECAY
255 CONSTANT MSG-DELIVERED
Block 5038
( CONSOLE-CMD-EVENT: console-VM -> paired user-VM command )
( relay message type, async MSG-SEND/MSG-DELIVER. )
7 CONSTANT CONSOLE-CMD-EVENT
( ELEVATE-REQUEST: H.5/H.8 -- word-ACL elevation ask, )
( carried to Zuse via CH-REQUEST. See SEND-ELEVATE- )
( REQUEST/ELEVATE-GRANT below and in zuse-eligibility.4th. )
8 CONSTANT ELEVATE-REQUEST
Block 5041
( BLK-ATTACH-EVENT: Hera -> Artemis storage-attach request, )
( and Artemis -> Hera ack. Payload is FORTH text, executed )
( by the receiver, same as every other message here -- see )
( HERA-BLK-ATTACH-REQ (artemis:init.4th) and BLK-ATTACH-ACK )
( (repl.c). Messaging-migration decision, Bob, 2026-09-07: )
( Hera keeps polling/sig-checking; the storage-registration )
( step (blk_subsys_attach_device) moves to a real message )
( instead of a direct C call, so identity birth only )
( proceeds once Artemis confirms storage succeeded. )
9 CONSTANT BLK-ATTACH-EVENT
Block 5004
( StadiumBehaviour tags, match stadium.h's enum )
0 CONSTANT SB-MIGRATE
1 CONSTANT SB-DELIVER
2 CONSTANT SB-EXPIRE
3 CONSTANT SB-COOL
-1 CONSTANT STADIUM-NONE
( per-item admission heat for MSG-SEND/CH-ACCEPT. )
( Remaining reservoir after COMMON-CH's Q.1/3 floor, split )
( evenly across MSG-MAX messages + non-COMMON CH-MAX-1 slots. )
Q.1 Q.1 3 / - MSG-MAX CH-MAX 1- + / CONSTANT Q.SLOT
Block 5005
( arenas. heat/capacity via Stadium; MBR keeps its own )
( free list (not part of heat economy). )
CREATE MSG-ARENA MSG-MAX MSG-CELLS * CELLS ALLOT
CREATE CH-ARENA CH-MAX CH-CELLS * CELLS ALLOT
CREATE MBR-ARENA MBR-MAX MBR-CELLS * CELLS ALLOT
VARIABLE MSG-ALLOC-SLOT
VARIABLE CH-ALLOC-SLOT
VARIABLE MBR-FREE-HEAD
VARIABLE MSG-SEQ
VARIABLE CH-ACTIVE
VARIABLE COMMON-CH
VARIABLE MY-CH-ID
Block 5006
( VM routing table. SXIX: 16 slots, not 8 -- see FABRIC-3.md. )
( Hera/Hermes/Artemis stay 0/1/2 (artemis:init.4th depends on )
( it); identities get NEW slots 3-10, never renumbered. )
16 CONSTANT VM-MAX
CREATE VM-NAME-ADDRS VM-MAX CELLS ALLOT
CREATE VM-NAME-LENS VM-MAX CELLS ALLOT
: VM-NAME-REG ( addr u idx -- )
DUP VM-MAX >= IF DROP 2DROP EXIT THEN
>R R@ CELLS VM-NAME-LENS + !
R> CELLS VM-NAME-ADDRS + ! ;
Block 5042
( doe-idx (std79-doe.fth ID-NAME) -> msg-idx: 1..8 -> 3..10. )
: DOE-IDX>MSG-IDX ( doe-idx -- msg-idx ) 2 + ;
: VM-NAMES-INIT ( -- )
S" Hera" 0 VM-NAME-REG
S" Hermes" 1 VM-NAME-REG
S" Artemis" 2 VM-NAME-REG
S" rajames" 1 DOE-IDX>MSG-IDX VM-NAME-REG
S" 00" 2 DOE-IDX>MSG-IDX VM-NAME-REG
S" 01" 3 DOE-IDX>MSG-IDX VM-NAME-REG
S" 02" 4 DOE-IDX>MSG-IDX VM-NAME-REG
S" 03" 5 DOE-IDX>MSG-IDX VM-NAME-REG
S" 04" 6 DOE-IDX>MSG-IDX VM-NAME-REG
S" 05" 7 DOE-IDX>MSG-IDX VM-NAME-REG
S" 06" 8 DOE-IDX>MSG-IDX VM-NAME-REG ;
Block 5007
( INIT-FREE. stamps STADIUM-NONE into each slot's stadium- )
( cell field (msg off 5, ch off 3). Raw offsets: accessors )
( aren't defined yet in file order. )
: MSG-INIT-FREE ( -- )
MSG-MAX 0 DO
STADIUM-NONE I MSG-CELLS * CELLS MSG-ARENA + 5 CELLS + !
LOOP ;
: CH-INIT-FREE ( -- )
CH-MAX 0 DO
STADIUM-NONE I CH-CELLS * CELLS CH-ARENA + 3 CELLS + !
LOOP ;
Block 5008
( MBR-INIT-FREE (member free list, untouched) )
: MBR-INIT-FREE ( -- )
MBR-MAX 1- 0 DO
I MBR-CELLS * CELLS MBR-ARENA +
I 1+ MBR-CELLS * CELLS MBR-ARENA + SWAP !
LOOP
0 MBR-MAX 1- MBR-CELLS * CELLS MBR-ARENA + !
MBR-ARENA MBR-FREE-HEAD ! ;
Block 5009
( MSG-ALLOC: finds a free slot (TYPE=0) first, admits into )
( Stadium only once confirmed free (no leak). )
: MSG-FIND-FREE-SLOT ( -- addr|0 )
MSG-ARENA MSG-MAX 0 DO
DUP @ 0= IF UNLOOP EXIT THEN
MSG-CELLS CELLS +
LOOP DROP 0 ;
Block 5010
( MSG-ALLOC: pulls heat from reservoir first, admits )
( (identity=idx, heat=pulled), rolls back on refusal. )
: MSG-ALLOC ( heat -- addr|0 )
MSG-FIND-FREE-SLOT DUP 0= IF SWAP DROP EXIT THEN
MSG-ALLOC-SLOT !
STADIUM-RES-PULL
MSG-ALLOC-SLOT @ MSG-ARENA - MSG-CELLS CELLS /
SWAP DUP >R
SB-DELIVER STADIUM-ADMIT
DUP STADIUM-NONE = IF
DROP R> STADIUM-RES-PUSH 0 EXIT
THEN
R> DROP
MSG-ALLOC-SLOT @ MSG-CELLS CELLS 0 FILL
MSG-ALLOC-SLOT @ 5 CELLS + !
MSG-ALLOC-SLOT @ ;
Block 5011
( MSG-FREE-NODE: evict from Stadium, clear field )
: MSG-FREE-NODE ( addr -- )
DUP 5 CELLS + @ STADIUM-EVICT DROP
DUP 5 CELLS + STADIUM-NONE SWAP !
DROP ;
Block 5012
( MBR alloc/free (unchanged; not heat economy) )
: MBR-ALLOC ( -- addr|0 )
MBR-FREE-HEAD @ DUP 0= IF EXIT THEN
DUP @ MBR-FREE-HEAD !
DUP MBR-CELLS CELLS 0 FILL ;
: MBR-FREE-NODE ( addr -- )
MBR-FREE-HEAD @ OVER ! MBR-FREE-HEAD ! ;
Block 5013
( CH-FIND-FREE-SLOT. No TYPE field, so freeness is )
( stadium-cell = STADIUM-NONE. CH-ALLOC -> block 4176. )
: CH-FIND-FREE-SLOT ( -- addr|0 )
CH-ARENA CH-MAX 0 DO
DUP 3 CELLS + @ STADIUM-NONE = IF UNLOOP EXIT THEN
CH-CELLS CELLS +
LOOP DROP 0 ;
Block 5014
( CH-ALLOC: pulls heat from reservoir first, admits )
( (identity=idx, heat=pulled), rolls back on refusal. )
: CH-ALLOC ( heat -- addr|0 )
CH-FIND-FREE-SLOT DUP 0= IF SWAP DROP EXIT THEN
CH-ALLOC-SLOT !
STADIUM-RES-PULL
CH-ALLOC-SLOT @ CH-ARENA - CH-CELLS CELLS /
SWAP DUP >R
SB-COOL STADIUM-ADMIT
DUP STADIUM-NONE = IF
DROP R> STADIUM-RES-PUSH 0 EXIT
THEN
R> DROP
CH-ALLOC-SLOT @ CH-CELLS CELLS 0 FILL
CH-ALLOC-SLOT @ 3 CELLS + !
CH-ALLOC-SLOT @ ;
Block 5015
( CH-FREE-NODE: evict from Stadium, clear field )
: CH-FREE-NODE ( addr -- )
DUP 3 CELLS + @ STADIUM-EVICT DROP
DUP 3 CELLS + STADIUM-NONE SWAP !
DROP ;
Block 5016
( message field accessors )
: MSG-TYPE@ ( m -- n ) @ ;
: MSG-TYPE! ( n m -- ) ! ;
: MSG-FROM@ ( m -- n ) 1 CELLS + @ ;
: MSG-FROM! ( n m -- ) 1 CELLS + ! ;
: MSG-TO@ ( m -- n ) 2 CELLS + @ ;
: MSG-TO! ( n m -- ) 2 CELLS + ! ;
: MSG-PADDR@ ( m -- a ) 3 CELLS + @ ;
: MSG-PADDR! ( a m -- ) 3 CELLS + ! ;
: MSG-PLEN@ ( m -- u ) 4 CELLS + @ ;
: MSG-PLEN! ( u m -- ) 4 CELLS + ! ;
( offset 5 = Stadium cell idx. MSG-HEAT@/! -> 4154. )
: MSG-STADIUM-CELL@ ( m -- cell ) 5 CELLS + @ ;
: MSG-STADIUM-CELL! ( cell m -- ) 5 CELLS + ! ;
: MSG-SEQ@ ( m -- n ) 6 CELLS + @ ;
: MSG-SEQ! ( n m -- ) 6 CELLS + ! ;
Block 5017
( message accessors: CH@/CH! )
: MSG-CH@ ( m -- c ) 7 CELLS + @ ;
: MSG-CH! ( c m -- ) 7 CELLS + ! ;
: MSG-ORIG-TYPE@ ( m -- n ) 8 CELLS + @ ;
: MSG-ORIG-TYPE! ( n m -- ) 8 CELLS + ! ;
253 CONSTANT MSG-NACKED
Block 5018
( channel + member accessors )
: CH-ID@ ( c -- n ) @ ;
: CH-ID! ( n c -- ) ! ;
: CH-OWNER@ ( c -- n ) 1 CELLS + @ ;
: CH-OWNER! ( n c -- ) 1 CELLS + ! ;
: CH-STATE@ ( c -- n ) 2 CELLS + @ ;
: CH-STATE! ( n c -- ) 2 CELLS + ! ;
( offset 3 = Stadium cell index. CH-HEAT@/! -> 4154. )
: CH-STADIUM-CELL@ ( c -- cell ) 3 CELLS + @ ;
: CH-STADIUM-CELL! ( cell c -- ) 3 CELLS + ! ;
: CH-MBRS@ ( c -- a ) 4 CELLS + @ ;
: CH-MBRS! ( a c -- ) 4 CELLS + ! ;
: CH-NEXT@ ( c -- a ) 5 CELLS + @ ;
: CH-NEXT! ( a c -- ) 5 CELLS + ! ;
: MBR-NEXT@ ( m -- a ) @ ;
: MBR-VM@ ( m -- n ) 1 CELLS + @ ;
Block 5019
( composed MSG/CH-HEAT@/!, same names/stacks, bodies )
( routed via Stadium. Callers need no changes. )
: MSG-HEAT@ ( m -- q ) MSG-STADIUM-CELL@ STADIUM-HEAT@ ;
: MSG-HEAT! ( q m -- ) MSG-STADIUM-CELL@ STADIUM-HEAT! ;
: CH-HEAT@ ( c -- q ) CH-STADIUM-CELL@ STADIUM-HEAT@ ;
: CH-HEAT! ( q c -- ) CH-STADIUM-CELL@ STADIUM-HEAT! ;
Block 5020
( deliver )
VARIABLE MSG-LAST-MSG
VARIABLE MSG-SEND-TO-IDX
: IDX>NAME ( idx -- addr u )
DUP VM-MAX >= IF DROP 0 0 EXIT THEN
DUP CELLS VM-NAME-ADDRS + @
SWAP CELLS VM-NAME-LENS + @ ;
: MSG-DELIVER ( m -- )
DUP MSG-LAST-MSG !
DUP MSG-PADDR@ OVER MSG-PLEN@
ROT MSG-TO@ IDX>NAME VM-EXEC ;
Block 5021
( MSG-SEND. heat -> MSG-ALLOC's admission directly )
( (zero-heat would lose eviction-fallback density )
( comparisons), not set afterward as before. )
: MSG-SEND ( type from to paddr plen ch -- )
3 PICK MSG-SEND-TO-IDX !
Q.SLOT MSG-ALLOC DUP 0= IF 2DROP 2DROP 2DROP DROP EXIT THEN
>R
MSG-SEQ @ 1+ DUP MSG-SEQ ! R@ MSG-SEQ!
R@ MSG-CH!
R@ MSG-PLEN! R@ MSG-PADDR!
R@ MSG-TO! R@ MSG-FROM! DUP R@ MSG-TYPE! R@ MSG-ORIG-TYPE!
R> DROP
MSG-SEND-TO-IDX @ IDX>NAME SWITCH-MARK-WORK ;
Block 5022
( MSG-COOL-ONE/ALL: linear decay per tick )
VARIABLE MSG-SCAN
: MSG-COOL-ONE ( m -- )
DUP MSG-HEAT@ Q-DECAY Q.* SWAP MSG-HEAT! ;
: MSG-COOL-ALL ( -- )
MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-HEAT@ 0 > IF
MSG-SCAN @ MSG-COOL-ONE
THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
Block 5023
( MSG-TOTAL-HEAT )
: MSG-TOTAL-HEAT ( -- q48 )
0 MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-TYPE@ 0 <> IF
MSG-SCAN @ MSG-HEAT@ +
THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
: MSG-REDELIVER-NACKED ( -- )
MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-TYPE@ MSG-NACKED = IF
MSG-SCAN @ MSG-ORIG-TYPE@ MSG-SCAN @ MSG-TYPE! THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
Block 5024
( MSG-DELIVER-ALL )
: MSG-DELIVER-ALL ( -- )
MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-TYPE@ 0 <>
MSG-SCAN @ MSG-TYPE@ MSG-DELIVERED <> AND
MSG-SCAN @ MSG-TYPE@ MSG-NACKED <> AND IF
MSG-SCAN @ MSG-DELIVER
MSG-SCAN @ MSG-TYPE@ 0 <> IF
MSG-DELIVERED MSG-SCAN @ MSG-TYPE!
THEN
THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
Block 5025
( message reaping )
( K reap only fires at heat=0: freed K contribution is 0. )
( Force-reap not yet implemented. If added: explicit )
( K redistribution will be required here. )
: MSG-REAP ( -- )
MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-HEAT@ 0 = IF
MSG-SCAN @ MSG-TYPE@ 0 <> IF
0 MSG-SCAN @ MSG-TYPE!
MSG-SCAN @ MSG-FREE-NODE
THEN
THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
Block 5026
( channel cooling + heat aggregate )
VARIABLE CH-SCAN
: CH-COOL-ALL ( -- )
CH-ACTIVE @ CH-SCAN !
BEGIN CH-SCAN @ 0 <> WHILE
CH-SCAN @ CH-HEAT@ Q-DECAY Q.* CH-SCAN @ CH-HEAT!
CH-SCAN @ CH-NEXT@ CH-SCAN !
REPEAT ;
: CH-TOTAL-HEAT ( -- q48 )
0 CH-ACTIVE @ CH-SCAN !
BEGIN CH-SCAN @ 0 <> WHILE
CH-SCAN @ CH-HEAT@ +
CH-SCAN @ CH-NEXT@ CH-SCAN !
REPEAT ;
Block 5027
( channel reaping )
: CH-REAP-SAFE ( -- )
CH-ACTIVE @ CH-SCAN !
0 CH-ACTIVE !
BEGIN CH-SCAN @ 0 <> WHILE
CH-SCAN @ CH-NEXT@
CH-SCAN @ CH-HEAT@ 0 =
CH-SCAN @ COMMON-CH @ <> AND IF
CH-SCAN @ CH-FREE-NODE
ELSE
CH-ACTIVE @ CH-SCAN @ CH-NEXT!
CH-SCAN @ CH-ACTIVE !
THEN
CH-SCAN !
REPEAT ;
Block 5028
( COMMON + MSG-TICK (was HERMES-TICK -- generic now). )
( floor=Q.1/3. COMMON-CH VARIABLE is in block 4101. )
: COMMON-INIT ( -- )
Q.1 3 / CH-ALLOC DUP COMMON-CH !
0 OVER CH-ID! 0 OVER CH-OWNER!
CH-OPEN OVER CH-STATE!
0 OVER CH-MBRS!
CH-ACTIVE @ OVER CH-NEXT!
CH-ACTIVE ! ;
( floor-refresh is reservoir-constrained, may no-op under )
( pressure. )
: MSG-TICK ( -- )
MSG-DELIVER-ALL MSG-REDELIVER-NACKED
MSG-COOL-ALL MSG-REAP
CH-COOL-ALL CH-REAP-SAFE
Q.1 3 / COMMON-CH @ CH-HEAT! ;
Block 5029
( MSG-K (was HERMES-K -- generic now). WELCOME stays )
( behind in each VM's own init.4th. )
: MSG-K ( -- q48 )
MSG-TOTAL-HEAT CH-TOTAL-HEAT + STADIUM-RES@ +
STADIUM-WORD-HEAT + ;
Block 5030
( event compat interface. SPAWN/KILL notify-Hera is )
( automatic: see vm_physics_init/retire in mama_word_birth. )
: EVENT-EMIT ( type -- ) DROP ;
: EVENT-WAIT ( -- type )
MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-TYPE@ 0 <> IF
MSG-SCAN @ MSG-TYPE@ UNLOOP EXIT THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP 0 ;
: EVENT-DRAIN ( -- )
( no-op: MSG-REAP owns cleanup; drain breaks async ) ;
Block 5031
( channel negotiation: mint/request )
: CH-MINT-ID ( owner -- id )
MSG-SEQ @ 1+ DUP MSG-SEQ !
SWAP 32 LSHIFT OR ;
( H.8: initiator-only gate. Refuses if `from` doesn't )
( match MY-CH-ID -- no posting while claiming another VM. )
: CH-REQUEST ( type from to paddr plen -- )
3 PICK MY-CH-ID @ <> IF 2DROP 2DROP DROP EXIT THEN
COMMON-CH @ CH-STATE@ CH-OPEN = IF
COMMON-CH @ MSG-SEND
ELSE 2DROP 2DROP DROP THEN ;
Block 5032
( channel ops: accept confirm close )
: CH-ACCEPT ( -- ch|0 )
Q.SLOT CH-ALLOC DUP 0= IF EXIT THEN
1 CH-MINT-ID OVER CH-ID!
1 OVER CH-OWNER!
CH-NEGOTIATING OVER CH-STATE!
0 OVER CH-MBRS!
CH-ACTIVE @ OVER CH-NEXT!
DUP CH-ACTIVE ! ;
: CH-CONFIRM ( ch -- )
DUP CH-STATE@ CH-NEGOTIATING = IF CH-OPEN SWAP CH-STATE!
ELSE DROP THEN ;
: CH-CLOSE ( ch -- )
DUP COMMON-CH @ = IF DROP EXIT THEN
CH-CLOSING SWAP CH-STATE! ;
Block 5033
( MSG-CD-INIT (was CD-INIT -- renamed to avoid colliding )
( with Artemis's own unrelated block-subsystem CD-INIT). )
( common:msg.4th's HERMES-ACK/NACK indirection is retired: )
( every VM now has its own local MSG-ACK-LAST/NACK-LAST. )
: MSG-CD-INIT ( -- )
MSG-ARENA MSG-MAX MSG-CELLS * CELLS 0 FILL
CH-ARENA CH-MAX CH-CELLS * CELLS 0 FILL
MBR-ARENA MBR-MAX MBR-CELLS * CELLS 0 FILL
MSG-INIT-FREE
CH-INIT-FREE
MBR-INIT-FREE
0 MSG-SEQ !
0 MSG-LAST-MSG !
0 CH-ACTIVE ! -1 MY-CH-ID !
COMMON-INIT
VM-NAMES-INIT ;
Block 5034
( ACK/NACK -- now purely local, no VM-EXEC indirection. )
: MSG-ACK-LAST ( -- )
MSG-LAST-MSG @ DUP 0= IF DROP EXIT THEN
0 OVER MSG-TYPE! MSG-FREE-NODE ;
: MSG-NACK-LAST ( -- )
MSG-LAST-MSG @ DUP 0= IF DROP EXIT THEN
DUP MSG-HEAT@ 2 / OVER MSG-HEAT!
MSG-NACKED SWAP MSG-TYPE! ;
Block 5035
( MSG-STATUS (was HERMES-STATUS -- generic now) )
: MSG-USED ( -- n )
0 MSG-ARENA MSG-SCAN !
MSG-MAX 0 DO
MSG-SCAN @ MSG-TYPE@ 0 <> IF 1+ THEN
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP ;
: CH-USED ( -- n )
0 CH-ACTIVE @ CH-SCAN !
BEGIN CH-SCAN @ 0 <> WHILE
1+
CH-SCAN @ CH-NEXT@ CH-SCAN !
REPEAT ;
: MSG-STATUS ( -- )
MSG-USED . ." msgs " CH-USED . ." channels" CR ;
Block 5036
( member management )
: MBR-NEXT! ( a m -- ) ! ;
: MBR-VM! ( n m -- ) 1 CELLS + ! ;
: CH-ADD-MBR ( vm ch -- )
MBR-ALLOC DUP 0= IF DROP 2DROP EXIT THEN
ROT OVER MBR-VM!
OVER CH-MBRS@ OVER MBR-NEXT!
SWAP CH-MBRS! ;
Block 5037
( Phase 2: real multi-member broadcast )
VARIABLE BC-TYPE VARIABLE BC-FROM
VARIABLE BC-PADDR VARIABLE BC-PLEN
VARIABLE BC-CH VARIABLE BC-SCAN
: MSG-BROADCAST ( type from paddr plen ch -- )
BC-CH ! BC-PLEN ! BC-PADDR ! BC-FROM ! BC-TYPE !
BC-CH @ CH-MBRS@ BC-SCAN !
BEGIN BC-SCAN @ 0<> WHILE
BC-TYPE @ BC-FROM @ BC-SCAN @ MBR-VM@
BC-PADDR @ BC-PLEN @ BC-CH @ MSG-SEND
BC-SCAN @ MBR-NEXT@ BC-SCAN !
REPEAT ;
Block 5039
( H.8: SEND-ELEVATE-REQUEST payload builder -- )
( scratch text buffer + append primitives. )
CREATE ELEVATE-REQ-BUF 256 ALLOT
VARIABLE ELEVATE-REQ-LEN
: ELEVATE-REQ-RESET ( -- ) 0 ELEVATE-REQ-LEN ! ;
: ELEVATE-REQ-PUTC ( c -- )
ELEVATE-REQ-BUF ELEVATE-REQ-LEN @ + C!
1 ELEVATE-REQ-LEN +! ;
: ELEVATE-REQ-APPEND ( addr u -- )
>R
ELEVATE-REQ-BUF ELEVATE-REQ-LEN @ +
R@ CMOVE
ELEVATE-REQ-LEN @ R> + ELEVATE-REQ-LEN ! ;
: ELEVATE-REQ-NUM ( n -- )
<# 0 SWAP #S #> ELEVATE-REQ-APPEND ;
Block 5040
( SEND-ELEVATE-REQUEST: ask Zuse for word-ACL )
( elevation. pk3..pk0 order so top-down emits )
( pk0 first; waddr/wu = target word name text. )
: SEND-ELEVATE-REQUEST ( pk3 pk2 pk1 pk0 waddr wu -- )
ELEVATE-REQ-RESET
83 ELEVATE-REQ-PUTC 34 ELEVATE-REQ-PUTC
32 ELEVATE-REQ-PUTC
ELEVATE-REQ-APPEND
34 ELEVATE-REQ-PUTC 32 ELEVATE-REQ-PUTC
ELEVATE-REQ-NUM 32 ELEVATE-REQ-PUTC
ELEVATE-REQ-NUM 32 ELEVATE-REQ-PUTC
ELEVATE-REQ-NUM 32 ELEVATE-REQ-PUTC
ELEVATE-REQ-NUM 32 ELEVATE-REQ-PUTC
S" ELEVATE-GRANT" ELEVATE-REQ-APPEND
ELEVATE-REQUEST MY-CH-ID @ 0 ELEVATE-REQ-BUF
ELEVATE-REQ-LEN @ CH-REQUEST ;
-10
View File
@@ -1,10 +0,0 @@
Block 4055
( common:msg.4th — Hermes participant interface )
( Load into every messaging VM at birth: )
( S" common:msg.4th" EXEC )
: HERMES-ACK ( -- )
LOG-DEBUG" msg: ACK sent"
S" MSG-ACK-LAST" S" Hermes" VM-EXEC ;
: HERMES-NACK ( -- )
LOG-DEBUG" msg: NACK sent"
S" MSG-NACK-LAST" S" Hermes" VM-EXEC ;
+7 -10
View File
@@ -1,20 +1,17 @@
Block 4060
( doe-campaign.4th: Compudynamics DoE campaign orchestrator )
( Requires: doe.4th (word-level) + real VM fleet touches. )
( Child VMs must define LOAD-DOE. )
: SETUP-HERMES ( -- )
S" Hermes" BIRTH
S" LOAD-DOE" S" Hermes" VM-EXEC ;
( Child VMs must define LOAD-DOE. FABRIC-3.6.md Phase 4, )
( Stage E: SETUP-HERMES removed -- Hermes no longer exists. )
: SETUP-ARTEMIS ( -- )
S" Artemis" BIRTH
S" LOAD-DOE" S" Artemis" VM-EXEC ;
: SETUP-VMS ( -- )
SETUP-HERMES SETUP-ARTEMIS ;
SETUP-ARTEMIS ;
Block 4061
( Phase 1: each VM runs DOE-WORK once for baseline. )
( FABRIC-3.6.md Phase 4, Stage E: Hermes's own line removed. )
: PHASE1-DOE ( -- )
." Phase 1: Hermes" CR
S" DOE-WORK" S" Hermes" VM-EXEC
." Phase 1: Artemis" CR
S" DOE-WORK" S" Artemis" VM-EXEC ;
( HISTORICAL: CD-WORK removed 2026-07-08 -- dead code, )
@@ -24,8 +21,9 @@ Block 4062
( CD-TICK: one real fleet touch pass -- not a fake pump. )
( Heat only moves via real VM-EXEC/VM-CALL/VM-STEP now; )
( there is nothing left to artificially bump per VM. )
( FABRIC-3.6.md Phase 4, Stage E: Hermes's own line )
( removed -- one touch per tick now, not two. )
: CD-TICK ( -- )
S" DOE-WORK" S" Hermes" VM-EXEC
S" DOE-WORK" S" Artemis" VM-EXEC ;
: CD-DOE ( n -- ) 0 DO CD-TICK LOOP ;
: CAMPAIGN-STATUS ( -- )
@@ -47,11 +45,10 @@ Block 4064
( Smoke test: 1 rep seed 1959 + 16 real fleet touches )
( HISTORICAL: VM-HEAT! artificial seeding removed -- new )
( VMs start at zero heat by construction, no seed needed. )
( FABRIC-3.6.md Phase 4, Stage E: Hermes's own rep removed. )
: SMOKE-CAMPAIGN ( -- )
." === Smoke: 1 rep seed 1959 ===" CR
SETUP-VMS
." Hermes 1 rep..." CR
S" 1959 1 EXEC-DOE" S" Hermes" VM-EXEC
." Artemis 1 rep..." CR
S" 1959 1 EXEC-DOE" S" Artemis" VM-EXEC
." 16 real fleet touches..." CR
-23
View File
@@ -1,23 +0,0 @@
Block 4855
( Hermes v1 -- WELCOME. Generic messaging vocab moved to )
( common:messaging.4th, FABRIC-2.md Phase C 2026-08-28. )
: WELCOME ( -- ) LOG-INFO" Hermes: loaded" ;
WELCOME
Block 4153
( LOAD-DOE: pulls in doe.4th's word-level DOE-WORK )
( workload, for doe-campaign.4th's remote VM-EXEC. )
: LOAD-DOE ( -- ) S" doe.4th" EXEC ;
Block 5116
( Hermes owns the one real, canonical COMMON-CH. Every )
( other VM subscribes into it via VM-EXEC (see Artemis's )
( and Hera's own init.4th); Hera always exists first, so )
( Hermes adds her here rather than Hera subscribing to a )
( VM that doesn't exist yet at Hera's own birth. )
S" common:messaging.4th" EXEC
MSG-CD-INIT
1 MY-CH-ID !
S" lib.4th" EXEC
1 COMMON-CH @ CH-ADD-MBR
0 COMMON-CH @ CH-ADD-MBR
LOG-INFO" Hermes: ready"
STARTUP-BANNER
+22
View File
@@ -0,0 +1,22 @@
Block 4986
( Hestia -- WELCOME. Third Tripod leg (Hera/Artemis/Hestia, )
( FABRIC-3.5.md SII/SIV), bind point + drawing fabric owner. )
: WELCOME ( -- ) LOG-INFO" Hestia: loaded" ;
WELCOME
Block 4988
( fabric.4th/font.4th moved here from init.4th (Hera) -- )
( FABRIC-3.6.md tasks 1.6/1.7, merged into one commit: they )
( are not independent -- font.4th's G-LINE/G-ELLIPSE calls )
( are fabric.4th's own words, so moving one without the )
( other breaks whichever VM keeps only half the pair. Order )
( preserved: fabric.4th before font.4th, same as init.4th's )
( own load order before this move. )
S" fabric.4th" EXEC
S" font.4th" EXEC
Block 4987
( FABRIC-3.6.md Phase 4, Stage E: common:messaging.4th/ )
( MSG-CD-INIT/MY-CH-ID/COMMON-CH subscription all removed )
( -- the whole COMMON-CH concept is gone with the file. )
S" lib.4th" EXEC
LOG-INFO" Hestia: ready"
STARTUP-BANNER
+2 -5
View File
@@ -17,11 +17,8 @@ S" ACL.4th" EXEC
S" block-acl.4th" EXEC
S" zuse-eligibility.4th" EXEC
S" lib.4th" EXEC
S" fabric.4th" EXEC
S" font.4th" EXEC
( SXX: same pattern Hermes/Artemis/console/mint already use. )
S" common:messaging.4th" EXEC
MSG-CD-INIT
( FABRIC-3.6.md Phase 4, Stage E: common:messaging.4th/ )
( MSG-CD-INIT removed -- no longer exists, no longer needed. )
Block 2050
( Hera boot — banner )
BOOT-BANNER
-28
View File
@@ -1,28 +0,0 @@
Block 4300
( process.4th — lifecycle phase operators )
( Event codes must match hermes/init.4th )
1 CONSTANT SPAWN-EVENT
2 CONSTANT PAUSE-EVENT
3 CONSTANT RESUME-EVENT
4 CONSTANT KILL-EVENT
( SPAWN: birth VM, notify Hermes )
: SPAWN ( c-addr u -- )
BIRTH
LOG-INFO" process: spawned"
S" 1 EVENT-EMIT" S" Hermes" VM-EXEC ;
( PAUSE: notify Hermes, send STOP to the named VM )
: PAUSE ( c-addr u -- )
S" 2 EVENT-EMIT" S" Hermes" VM-EXEC
S" STOP" 2SWAP VM-EXEC ;
Block 4301
( Lifecycle operators: resume, kill, phase )
( RESUME: notify Hermes, START the named VM )
: RESUME ( c-addr u -- )
S" 3 EVENT-EMIT" S" Hermes" VM-EXEC
LOG-INFO" process: resumed"
START ;
( KILL-VM: notify Hermes, then kill VM )
: KILL-VM ( c-addr u -- )
S" 4 EVENT-EMIT" S" Hermes" VM-EXEC
LOG-INFO" process: killed"
KILL ;
+3 -3
View File
@@ -3,9 +3,9 @@ Block 4021
( C prims: ZUSE-ELIGIBILITY-ADD ZUSE-ELIGIBLE? )
( NAME>XT ELEVATE-PUBKEY-UNPACK )
( Policy word this file: ELEVATE-GRANT. Runs in )
( Hera's own dict -- delivered here by messaging.4th's )
( MSG-DELIVER via VM-EXEC when a session calls the )
( common:messaging.4th SEND-ELEVATE-REQUEST entrypoint. )
( Hera's own dict -- delivered here by kernel-Hermes's own )
( drain checkpoint (FABRIC-3.6.md task 3.10), not FORTH )
( MSG-DELIVER (messaging.4th, removed Phase 4 Stage E). )
( FABRIC-2.md H.12 step 21, 2026-09-03. )
CREATE ELEVATE-PK-BUF 32 ALLOT
+56 -20
View File
@@ -7,34 +7,70 @@ longer exists here — see `.claude/CLAUDE.md`'s "On the branch topology" note)
---
## Release Versioning Policy (decided 2026-08-28)
## Release Versioning Policy (ratified 2026-09-19, FABRIC-3.5.md §XXX — supersedes the
2026-08-28 policy below)
This is the standing release-versioning policy for LithosAnanke. It is authoritative; the
FABRIC documents track implementation against it, and any permanent change to the policy
belongs here.
- **`X.0.0` — QEMU release.** A whole-number minor in the `X.0` position is the QEMU-only
release: the point where the three-architecture (amd64/aarch64/riscv64) story under QEMU
is complete and defensible on its own terms. Nothing real-hardware-only is required to cut
an `X.0.0`.
- **`X.5.0` — Hardware bare-metal release.** A `X.5` release is the real-hardware release:
the point where the same story transfers to bare metal on real boards (SER5, RasPi 6,
Milk-V, Zynq FPGA). Real-hardware-only work — the per-arch RNG drivers behind the unified
entropy entry point, and real-board boot validation — gates `X.5.0`, not `X.0.0`.
- **Even major numbers are LTS.** A release whose major number (`X`) is even is a
Long-Term-Support release — maintained and supported long-term (bug fixes, security,
backports) rather than a point-in-time cut. Odd major numbers are non-LTS development
lines.
**Superseded 2026-09-19.** The original 2026-08-28 policy (`X.0.0` = QEMU release, `X.5.0` =
hardware bare-metal release, **even** major = LTS) used the minor field to carry a milestone
meaning and had the LTS parity backwards relative to the ratified policy below. It is kept
struck through immediately after this note for historical traceability, not as current rule.
Applied to the two planned releases: the **v2.0.0** cut (even major, so LTS) is the QEMU
release; **v2.5.0** is the hardware bare-metal release that transfers v2.0.0's QEMU story to
real boards. See `FABRIC-2.md` §G for the release-gate punch lists.
- **Major: ODD = LTS line** (non-breaking fixes only — backports, never redesigns). **EVEN =
working line** (breaking changes land here). The line you are on tells you whether breakage
is possible at all — not the major number's parity signaling "supported vs. not" the way the
retired policy read it.
- **Minor** — release within that line. No longer carries a milestone meaning (`X.5.0` no
longer means anything special) — milestones are roadmap entries now, not arithmetic.
- **Patch** — working builds within a release.
- **`LITHOS_VERSION` (kernel) and `VERSION` (embedded StarForth engine) are independent and do
not auto-sync** — do not infer a relationship if they ever coincide.
- **Engine `VERSION` bumps at tag time by what actually changed:** major = any
FORTH-79-visible word semantics change; minor = words added/removed/relocated; patch =
build-only, no dictionary-visible change.
```
v1.0.x — serial-only production (released, historical encoding)
v1.5.x — framebuffer VT100 console milestone (released, historical encoding)
v2.0.0 — QEMU release: three-arch QEMU story complete (released)
v2.0.1 — SER5 hardware-track line (historical; superseded by this policy)
v2.1.0 — Tripod/kernel reshuffle: Hermes into the kernel, Tripod = Hera/Artemis/Hestia
v2.2.0 — amd64 bare-metal bring-up (Beelink SER5)
v2.x — further working releases; riscv64 / aarch64 board bring-up
v3.0.0 — FIRST LTS, when and only when all 5 criteria below are met
```
**LTS criteria (a tag may take an odd major only when all five hold):** real-hardware boot
demonstrated on at least the amd64 reference board, logs committed as audit artifacts; no
known-reproducible silent-failure defect open; ACL Phase 8 closed (or explicitly scoped out in
writing); the `proof/` boundary restated and not contracted relative to the prior LTS; a soak —
architecture unchanged for at least one full release cycle. The first tag meeting all five
takes the odd major — no judgement call.
See `FABRIC-3.5.md` §XXX for the full ratified policy text and reasoning, and `FABRIC-2.md` §G
for the release-gate punch lists this ladder replaced the arithmetic reading of.
<details>
<summary>Historical: the retired 2026-08-28 policy (kept for traceability only)</summary>
- ~~`X.0.0` — QEMU release. A whole-number minor in the `X.0` position is the QEMU-only
release: the point where the three-architecture (amd64/aarch64/riscv64) story under QEMU
is complete and defensible on its own terms.~~
- ~~`X.5.0` — Hardware bare-metal release. Real-hardware-only work gates `X.5.0`, not
`X.0.0`.~~
- ~~Even major numbers are LTS.~~ **Wrong — the ratified policy is odd = LTS.**
</details>
**Board-by-board hardware rollout, decided 2026-08-29 (extends the above as boards come
online).** Real silicon is arriving incrementally (Beelink SER5 in hand now; RasPi 5 + Milk-V
orderable around Mon 2026-08-31), so the hardware release is split per real board in hand,
each its own even-minor cut on the same line (each `X.Y.0` here is an LTS point-in-time cut,
not a separate dev line):
online; corrected 2026-09-22 for the ratified §XXX policy — these are working-line minor
releases, not LTS cuts, since v2.x is the even/working line).** Real silicon is arriving
incrementally (Beelink SER5 in hand now; RasPi 5 + Milk-V orderable around Mon 2026-08-31), so
the hardware release is split per real board in hand, each its own minor cut on the v2.x
working line (v2.1.0, the Tripod/kernel reshuffle, landed first — see the ladder above):
- **v2.2.0 — amd64 bare metal.** Beelink SER5 (in hand). Gate: the generic GPT/FAT32
thumbdrive image (`make -f Makefile.starkernel ARCH=amd64 thumbdrive`) flashes to and boots
+10 -4
View File
@@ -137,16 +137,22 @@ before building) rather than wiring it into `doe.4th`.
## `.4th` File Structure
Every `.4th` file must follow StarForth's block format. The block system
maps source text to 1024-byte logical blocks; the `Block NNNN` header tells
the loader which block slot to fill.
maps source text to logical blocks; the `Block NNNN` header tells the loader
which block slot to fill.
**Mandatory rules:**
1. The first line of each logical block must be `Block NNNN` (capital B,
single space, decimal integer).
2. Block numbers must be unique within a single capsule file.
2. Block numbers must be unique within a single capsule file, and must fall
in `[2048, 5120)`.
3. Blocks are loaded in file order and executed top-to-bottom.
4. Each block can hold up to 1024 bytes of source text.
4. Each block can hold at most 16 content lines, each at most 64 characters
long (`validate_forth_blocks` in `tools/mkcapsule.c`, corrected 2026-09-19
against the tool itself — **not** a 1024-byte budget: 8 lines of 128
characters is 1024 bytes and still fails, since the limit is enforced
per-line and per-line-count, not as a total byte count). Verify with
`mkcapsule --lint capsules/`, not `wc -c`.
5. Comments use `( ... )` — parentheses with spaces inside.
6. Word definitions use `: NAME ... ;` — standard FORTH-79.

Some files were not shown because too many files have changed in this diff Show More