Compare commits
58
Commits
+34
-18
@@ -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/
|
||||
|
||||
+125
-31
@@ -1,37 +1,26 @@
|
||||
# FABRIC-3.5.md — the Tripod/kernel reshuffle
|
||||
|
||||
**Status: REOPENED 2026-09-19, by direct instruction ("reopen 3.5 and write it up as a gap
|
||||
analysis section"), to add §XXXI — a gap-analysis sweep of the whole FABRIC set. The design
|
||||
phase remains closed; §XXXI adds findings, not new design.**
|
||||
**Status: CLOSED/ARCHIVAL as of 2026-09-22, at tag `v2.1.0`.** Per §XXVI.5's own close
|
||||
condition ("this document closes when the tag exists"). Produced the full design ruling for
|
||||
the Tripod/kernel reshuffle: Hermes moves from a FORTH VM into the kernel as kernel-Hermes; the
|
||||
Tripod becomes Hera/Artemis/Hestia; every design question this document opened is ruled (§XXX.7
|
||||
/ §XLI's punch list). Execution against that design is recorded in `FABRIC-3.6.md`, not here —
|
||||
all five phases (0–5) closed there, ending in the `v2.1.0` tag this header names. **Nothing is
|
||||
carried forward and no successor is created** — this document is not part of the
|
||||
`FABRIC-0 → -1 → -2 → -3` chain (§XXVI.5), so closing it hands nothing to a successor.
|
||||
**`FABRIC-3.md` remains open, living and authoritative for its own topic** (bare metal boot);
|
||||
nothing here ever superseded it.
|
||||
|
||||
> **Prior status, kept rather than overwritten: DESIGN PHASE CLOSED as of 2026-09-19, by
|
||||
> direct instruction ("close the document for now"). Not yet archival.** That close stood for
|
||||
> the duration of the sweep and its substance is unchanged — every design question was and
|
||||
> remains ruled. The reopen is recorded rather than the close deleted, per this series' own
|
||||
> rule against silently rewriting a prior state.
|
||||
|
||||
**What is closed, and what is deliberately not.** Every design question this document opened is
|
||||
ruled — see §XXX.7. **No code has been written and no code is authorized.** The execution
|
||||
sequence (§XXVI.6, as amended by §XXX.7) is untouched: the surgical strip, the build, the
|
||||
Isabelle/HOL pass, the documentation sweep, the SBOM, the merge to `master`, and the `v2.1.0`
|
||||
tag all remain ahead.
|
||||
|
||||
**This is therefore a narrower close than §XXVI.5 specified**, and the difference is stated
|
||||
rather than glossed. §XXVI.5 ruled that this document closes *when the tag exists*, in
|
||||
`FABRIC-2.md`'s CLOSED/ARCHIVAL form, naming the tag it closed at. **The tag does not exist**,
|
||||
so claiming that close would be a label running ahead of the real state — the exact error
|
||||
`FABRIC-3.md` §I.2 corrected when it rolled `LITHOS_VERSION` back, and the same standard §XXIX
|
||||
applied to the LTS question. **The archival close specified by §XXVI.5 still stands and still
|
||||
happens at `v2.1.0`.** This header is the provisional one the instruction's own "for now" asks
|
||||
for.
|
||||
|
||||
**Nothing is carried forward and no successor is created.** As §XXVI.5 establishes, this
|
||||
document is not part of the `FABRIC-0 → -1 → -2 → -3` chain, so closing it hands nothing to a
|
||||
successor. **`FABRIC-3.md` remains open, living and authoritative for its own topic** (bare
|
||||
metal boot); nothing here supersedes it. The live artifact from this document is its punch list
|
||||
(§XXVI.6 / §XXX.7) — that, not this header, is what the build works from.
|
||||
|
||||
**Open by design, not by omission:** items 10–17 of §XXVI.6 are execution, not decisions.
|
||||
> **Prior status headers, kept rather than overwritten, per this series' own rule against
|
||||
> silently rewriting a prior state:**
|
||||
>
|
||||
> **REOPENED 2026-09-19**, by direct instruction ("reopen 3.5 and write it up as a gap analysis
|
||||
> section"), to add §XXXI — a gap-analysis sweep of the whole FABRIC set.
|
||||
>
|
||||
> **DESIGN PHASE CLOSED as of 2026-09-19**, by direct instruction ("close the document for
|
||||
> now"). Not yet archival at that point — the execution sequence (surgical strip, build,
|
||||
> Isabelle pass, doc sweep, SBOM, merge, tag) was still entirely ahead. That gap is now closed:
|
||||
> `FABRIC-3.6.md`'s Phases 0–5 are the execution this header once described as pending.
|
||||
Three things recorded here are explicitly *outside* this reshuffle and still need their own
|
||||
authorization — the `.claude/CLAUDE.md`/`MANIFEST.md` documentation reconciliation (§XXVI.1),
|
||||
the `src/*.c.bak` hygiene question (§XXII.5), and the stray `refs/heads/v2.0.1` branch and
|
||||
@@ -4593,6 +4582,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 +4682,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.
|
||||
|
||||
+1585
-55
File diff suppressed because it is too large
Load Diff
+205
@@ -0,0 +1,205 @@
|
||||
# FABRIC-3.7.md — Phase 8 PKI: the elevation entrypoint
|
||||
|
||||
**Status: OPEN — design only, no code written or authorized.**
|
||||
|
||||
**CORRECTION (2026-09-22, before any code was written against this document): §2's central
|
||||
claim — that the old `SEND-ELEVATE-REQUEST` passed a raw cross-VM address into `ELEVATE-GRANT`'s
|
||||
`waddr` — is wrong.** Found while starting Part A's implementation: reading the actual deleted
|
||||
source (`git show 3e201c8^:capsules/common/messaging.4th`, block 5040) shows
|
||||
`SEND-ELEVATE-REQUEST` copied the target word's **name as literal character bytes** (via
|
||||
`ELEVATE-REQ-APPEND`'s `CMOVE`) into a scratch buffer, building the text `S" <name-text>" <pk0>
|
||||
<pk1> <pk2> <pk3> ELEVATE-GRANT`, and sent *that whole string* to Hera. When Hera's own
|
||||
interpreter runs `S" <name-text>"`, it allocates a fresh string **in Hera's own memory** and
|
||||
pushes Hera's own valid address — no numeric cross-VM address ever appears anywhere in this
|
||||
flow. §2 was written from `ELEVATE-GRANT`'s signature alone, assuming the caller forwarded a raw
|
||||
address, without first reading how the caller actually built its message. It didn't.
|
||||
|
||||
**What is still real, much narrower than originally claimed:** if a future caller ever spliced
|
||||
*attacker-influenced* text into the name field without checking for an embedded `"` character,
|
||||
that could break out of the `S" ... "` literal early and inject arbitrary FORTH source, executed
|
||||
with Hera's privilege. That's an input-validation discipline question for whoever writes the new
|
||||
caller (validate: no embedded `"`, or just always use a compile-time-fixed literal name, never a
|
||||
runtime-supplied one) — not an architectural cross-VM-memory defect requiring the buffer/message
|
||||
redesign §3 originally called for. **§3's proposed mechanism (Hera-side fixed receive buffer,
|
||||
kernel-constructed integer-literal-only command) is not needed** — the original text-copy
|
||||
design was already safe against the bug as actually diagnosed. Kept below, struck through, for
|
||||
traceability, per this series' own rule against silently rewriting a prior state.
|
||||
|
||||
Successor to
|
||||
`FABRIC-3.5.md`/`FABRIC-3.6.md` (both CLOSED/ARCHIVAL at `v2.1.0`) for exactly one topic: the
|
||||
Ed25519-challenge-response elevation entrypoint that `.claude/CLAUDE.md`'s ACL section names as
|
||||
Phase 8, the last open item in the word-level ACL system. This is a **new document**, not a
|
||||
reopening of `FABRIC-3.6.md` — that document's own close header says future fleet work gets its
|
||||
own document, and this is that.
|
||||
|
||||
**Provenance.** Written 2026-09-22, immediately after `FABRIC-3.6.md`'s close, from a design
|
||||
conversation with Captain Bob about a security concern he raised directly: how to rebuild the
|
||||
elevation entrypoint that Phase 4's Category B strip left dangling, without reopening a hole.
|
||||
The design below was proposed, and Captain Bob asked for it in writing here rather than left
|
||||
only in session memory.
|
||||
|
||||
---
|
||||
|
||||
## 1. What's dangling, and why
|
||||
|
||||
`FABRIC-3.6.md` Phase 4 (Category B strip, 2026-09-22) deleted `capsules/common/messaging.4th`
|
||||
after every FORTH-owned message type had been cut over to kernel-Hermes. One casualty was
|
||||
collateral, not intended: `SEND-ELEVATE-REQUEST` (`messaging.4th` block 5040) was the only
|
||||
caller of both `KH-ELEVATE-SEND` (`src/starkernel/repl.c`) and, transitively, `ELEVATE-GRANT`
|
||||
(`capsules/zuse-eligibility.4th`, blocks 4021–4022). All three still exist in the tree.
|
||||
`ELEVATE-GRANT` is still loaded at boot (`capsules/init.4th:18`). Nothing can call it any more.
|
||||
|
||||
Captain Bob's decision at the time (`FABRIC-3.6.md`'s own Phase 4 entry): leave it unreachable,
|
||||
don't patch a caller back in as part of that strip. Phase 8 builds its own entrypoint instead of
|
||||
resuming this one. **This document is that entrypoint's design.**
|
||||
|
||||
<details>
|
||||
<summary>Original §2/§3 (WRONG — see the correction at the top of this document; kept for
|
||||
traceability, not current design)</summary>
|
||||
|
||||
### 2. The security hole in the old mechanism — found before any code was written
|
||||
|
||||
`ELEVATE-GRANT`'s signature, unchanged since it was written:
|
||||
|
||||
```
|
||||
ELEVATE-GRANT ( waddr wu pk0 pk1 pk2 pk3 -- )
|
||||
```
|
||||
|
||||
`waddr`/`wu` are an address/length pair meant to point at the string naming the word to elevate.
|
||||
`pk0`–`pk3` are the caller's Ed25519 pubkey, packed 8 bytes per cell (`ELEVATE-PUBKEY-UNPACK`,
|
||||
`mama_forth_words.c`).
|
||||
|
||||
**The old `SEND-ELEVATE-REQUEST` computed `waddr` in the *sending* VM's own address space, but
|
||||
`ELEVATE-GRANT` always executes on Hera** (`ELEVATE-GRANT always runs on Hera` — `repl.c`'s own
|
||||
comment on `KH-ELEVATE-SEND`, still there). A word's name string lives in the sending VM's
|
||||
memory. `ELEVATE-GRANT` dereferences `waddr` in Hera's memory. Those are not the same address
|
||||
space by construction — `vaddr_t` is per-VM.
|
||||
|
||||
**Consequence:** whoever controls `waddr` controls what bytes `NAME>XT` reads and resolves as a
|
||||
word name, in Hera's dictionary, not the caller's. This is not "the string might be malformed" —
|
||||
it is a primitive for making Hera's own `ELEVATE-GRANT` grant `ACL-ALLOW!`/`ACL-TTL!` on
|
||||
*whatever dictionary entry the attacker's chosen `waddr` happens to land on*, regardless of what
|
||||
word name the caller claims to be requesting elevation for. A caller who can influence `waddr`
|
||||
at all — not forge a signature, not defeat `zuse_eligibility_is_member()`, just choose a number
|
||||
— has a privilege-escalation primitive against the fleet governor.
|
||||
|
||||
This was never exploited (the entrypoint has had zero live callers since the file that called it
|
||||
was deleted), and is reported here as a design defect found by inspection, not a live incident.
|
||||
|
||||
### 3. The fix: never cross an address, only ever cross bytes
|
||||
|
||||
This project already solved the general version of this problem once, this same session
|
||||
(`FABRIC-3.6.md` tasks 3.8/3.9, the payload-aliasing fix): a kernel-Hermes message's payload
|
||||
must be **copied into the message's own storage**, never a pointer into the sender's memory that
|
||||
might be reused or freed before the receiver drains it. `SkHermesMessage.payload_buf`
|
||||
(`include/starkernel/vm/kernel_hermes.h:160`, `SK_HERMES_CHUNK_MAX_PAYLOAD` = 1024 bytes) is
|
||||
exactly that fix, already built, already proven on all three architectures.
|
||||
|
||||
**The elevation entrypoint's hole is the same defect one level up: an address crossing a
|
||||
boundary it isn't valid on the other side of.** The fix generalizes directly:
|
||||
|
||||
1. **Never send `waddr`/`wu` across the kernel-Hermes boundary.** Send the pubkey (32 bytes,
|
||||
already the right shape for `payload_buf`) and the target word's **name, as literal bytes**,
|
||||
copied inline into the message payload — not an address, the actual characters. This is
|
||||
already how `CONSOLE-CMD-EVENT`'s payload works (a command string's bytes, not a pointer to
|
||||
one), so this isn't a new pattern, it's applying the existing one to the one caller that
|
||||
still passed a raw address.
|
||||
|
||||
2. **On receipt, kernel-Hermes's C drain-checkpoint copies those name bytes into a small,
|
||||
fixed, kernel-owned buffer that already lives in Hera's own VM memory** — a receive-side
|
||||
mirror of the existing send-side pattern (`g_kh_elevate_buf`, `repl.c:445`, is the
|
||||
already-built precedent for "a static buffer this mechanism owns"; this needs its Hera-side
|
||||
counterpart). The buffer's address is a compile-time constant, known to the kernel, never
|
||||
computed from anything the caller supplied.
|
||||
|
||||
3. **The FORTH command handed to `vm_interpret()` on Hera references only that fixed buffer's
|
||||
address and length as plain integer literals.** Both are always kernel-controlled. Neither is
|
||||
ever derived from caller input. `ELEVATE-GRANT` itself does not change — same signature, same
|
||||
`zuse_eligibility_is_member()` check, same `ACL-ALLOW!`/`ACL-TTL!` grant. Policy logic stays
|
||||
in FORTH, per `ACL.4th`'s own rule (no new C primitive for policy) — this fix is entirely
|
||||
about how bytes get from one VM to another, not about who is allowed to grant what.
|
||||
|
||||
**Why this closes the hole structurally, not by validation:** there is no string to sanitize and
|
||||
no address to bounds-check, because the interpreted command never contains anything an attacker
|
||||
touched except opaque data bytes that get copied, never dereferenced as a pointer, by the
|
||||
receiving side. The class of bug (cross-address-space pointer confusion) becomes impossible by
|
||||
construction, the same way `payload_buf` made use-after-free impossible by construction rather
|
||||
than by careful lifetime tracking.
|
||||
|
||||
</details>
|
||||
|
||||
## 2 (corrected). What the old mechanism actually did, and the one real gap in it
|
||||
|
||||
Re-read from the actual deleted source (`git show 3e201c8^:capsules/common/messaging.4th`,
|
||||
blocks 5039–5040): `SEND-ELEVATE-REQUEST ( pk3 pk2 pk1 pk0 waddr wu -- )` used `waddr`/`wu` only
|
||||
to `CMOVE` the target word's **name bytes**, as text, into a scratch buffer
|
||||
(`ELEVATE-REQ-BUF`/`ELEVATE-REQ-APPEND`) it owned — building the literal string `S"
|
||||
<name-text>" <pk0> <pk1> <pk2> <pk3> ELEVATE-GRANT` entirely in the *sending* VM's own memory.
|
||||
Only that finished string — not `waddr` itself — went to `KH-ELEVATE-SEND` and across to Hera.
|
||||
When Hera's interpreter runs `S" <name-text>"`, Hera's own `S"` allocates a fresh string **in
|
||||
Hera's own memory** and pushes Hera's own valid address. `waddr`/`wu` never cross the VM
|
||||
boundary as numbers at any point — only as copied character content. There is no cross-VM
|
||||
pointer dereference anywhere in this flow.
|
||||
|
||||
**The one real, much narrower gap:** the name text is spliced into `S" ... "` with no check for
|
||||
an embedded `"` character. If a future caller ever passed attacker-influenced text as the name
|
||||
(none ever did — the word had zero live callers), a `"` in the name would close the string
|
||||
literal early and let the rest of the name execute as raw FORTH source, with Hera's privilege.
|
||||
This is a caller-discipline / input-validation question, not an architectural defect: either
|
||||
always use a compile-time-fixed name literal at the call site (no runtime input, no risk at
|
||||
all), or validate for an embedded `"` before building the command if a name ever does need to
|
||||
come from something less trusted than the call site's own source code.
|
||||
|
||||
**Net effect on Phase 8 v1's scope:** Part A, as originally conceived in §3 above, is not
|
||||
needed. If a `SEND-ELEVATE-REQUEST` replacement is ever built, it can follow the original
|
||||
text-copy design as-is, with the one-line `"`-check added if and only if the name is ever
|
||||
runtime-supplied rather than a fixed literal. No kernel-Hermes/`repl.c` changes required. Part B
|
||||
(`capsules/zuse.4th`, gating `ZUSE-ELIGIBILITY-ADD`) stands on its own, independently verified,
|
||||
unaffected by this correction.
|
||||
|
||||
## 4. What Phase 8 actually needs to build
|
||||
|
||||
Corrected per §2's re-read above. Concretely, when Phase 8 next picks this up:
|
||||
|
||||
- If a caller into `ELEVATE-GRANT` is ever needed again, rebuild it close to the original
|
||||
`SEND-ELEVATE-REQUEST` shape (`ELEVATE-REQ-BUF`/`ELEVATE-REQ-APPEND`/text-copy into `S" ...
|
||||
"`) — it was already safe. Add the one-line embedded-`"` check only if the name is ever
|
||||
runtime-supplied rather than a call-site literal. No `kernel_hermes.c`/`kernel_hermes.h`/
|
||||
`repl.c` changes needed for this.
|
||||
- `ELEVATE-GRANT` unchanged either way.
|
||||
- **Part B is done** (`capsules/zuse.4th`, committed and three-arch verified this session,
|
||||
2026-09-22) — `ZUSE-ELIGIBILITY-ADD` denied by default, granted only inside `ACL-ZUSE-BOOT`'s
|
||||
authenticated branch. This closes the actual "grant yourself eligibility with no real drive at
|
||||
all" path — a real, independently-confirmed gap, unaffected by this correction.
|
||||
- **Defending against a cloned drive — settled, 2026-09-23: not going to happen, by design.**
|
||||
Today, WIREBIND/MINT trust whatever identity is stored on an attached thumbdrive with no
|
||||
challenge at all (confirmed by grep: no `ed25519_sign`/`ed25519_verify` call anywhere in
|
||||
`capsule_wirebind.c` or `capsule_mint.c`), and the private key seed itself is stored in
|
||||
plaintext on the drive, read in the same devblock as the pubkey/cert. **This is accepted, not
|
||||
a gap.** Captain Bob, directly: *"nothing like a pin or a password or secret code or any
|
||||
bullshit... Everybody has secrets. There's only the drive."* Physical possession of the drive
|
||||
is the entire, deliberate credential model — a byte-for-byte clone being equivalent to the
|
||||
real drive is the accepted design, not a defect to close. A PIN/passphrase second factor was
|
||||
built, live-tested on all three architectures, and fully reverted before commit
|
||||
(`/home/rajames/.claude/plans/jiggly-cuddling-stallman.md`, now marked rejected; memory
|
||||
`feedback_no_knowledge_factor_identity`) — **do not revisit a knowledge-factor approach here.**
|
||||
Any future work in this space needs a fundamentally different mechanism (not something typed
|
||||
and known) or stays an accepted limitation.
|
||||
- **Phase 8 v3, 2026-09-23 — done, a distinct and narrower concern from the item above.** The
|
||||
"accepted limitation" above is about a drive image copied *outside* StarshipOS entirely (e.g.
|
||||
imaged on an external computer) — that's still accepted, unchanged by this item. Captain Bob
|
||||
separately asked to close a narrower, different threat: **cloning a device's block content
|
||||
from *within* StarshipOS's own console**, using its own stock, unpinned words
|
||||
(`<src> BLOCK <dst> BUFFER 1024 MOVE`/`RELOCATE-BLOCK`). That's now closed — `MOVE`/`CMOVE`/
|
||||
`CMOVE>`/`RELOCATE-BLOCK` all refuse a same-VM, cross-device copy, verified live on all three
|
||||
architectures. See `/home/rajames/.claude/plans/jiggly-cuddling-stallman.md`'s "Phase 8 v3"
|
||||
section for the full design and verification record. The identity record itself
|
||||
(seed/pubkey/cert) was already unreachable from FORTH before this — this closes the one real
|
||||
gap the research found: ordinary block content, not the identity record.
|
||||
|
||||
## 5. What this document is not
|
||||
|
||||
Not a reopening of `FABRIC-3.6.md`, not a change to anything currently built, not an
|
||||
authorization to write code. Per this series' own convention: design here, execution gets its
|
||||
own document when the work actually starts, the same relationship `FABRIC-3.5.md` had to
|
||||
`FABRIC-3.6.md`.
|
||||
@@ -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:"
|
||||
|
||||
+34
-12
@@ -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)
|
||||
|
||||
@@ -584,6 +597,7 @@ KERNEL_OBJS := \
|
||||
.PHONY: qemu qemu-esp qemu-gdb
|
||||
.PHONY: thumbdrive iso-usb
|
||||
.PHONY: info help
|
||||
.PHONY: FORCE
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN TARGETS
|
||||
@@ -614,7 +628,15 @@ clean-kernel:
|
||||
# BUILD RULES
|
||||
# ==============================================================================
|
||||
|
||||
include/version.h:
|
||||
FORCE:
|
||||
|
||||
# FORCE prerequisite (matches the hosted Makefile's own pattern, Makefile:613/626):
|
||||
# this file is also written by the hosted Makefile with different, incompatible
|
||||
# content (no LITHOS_VERSION/LITHOS_VERSION_STR) -- without FORCE, a bare build
|
||||
# here after a hosted `make` run silently reuses that stale/wrong-flavored file
|
||||
# and fails with "LITHOS_VERSION_STR undeclared" deep in kernel_main.c, instead
|
||||
# of regenerating its own correct version.
|
||||
include/version.h: FORCE
|
||||
@mkdir -p include
|
||||
@BUILD_TS=$$(date -Iseconds 2>/dev/null || echo "unknown"); \
|
||||
printf '#ifndef STARFORTH_VERSION_H\n#define STARFORTH_VERSION_H\n\n' > $@; \
|
||||
|
||||
@@ -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
@@ -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
@@ -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.*
|
||||
|
||||
@@ -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 -- ) )
|
||||
|
||||
@@ -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 ;
|
||||
@@ -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 ;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ Block 4016
|
||||
( >BODY-then-store, so a pinned CONSTANT isn't tamper-proof. )
|
||||
( Read with ZUSE-PUBKEY@ / ZUSE-CERT-INSTALLED? -- both C )
|
||||
( primitives, read-only; the seed has no FORTH access at all. )
|
||||
( ZUSE-ELIGIBILITY-ADD denied by default -- see block 4017. )
|
||||
0 ['] ZUSE-ELIGIBILITY-ADD ACL-ALLOW!
|
||||
|
||||
Block 4017
|
||||
( ACL-ZUSE-BOOT ( -- ) re-invokable: capsule_zuse_boot.c )
|
||||
@@ -23,6 +25,8 @@ Block 4017
|
||||
: ACL-ZUSE-BOOT ( -- )
|
||||
ZUSE-CERT-INSTALLED? IF
|
||||
ZUSE-AUTHENTICATE
|
||||
1 ['] ZUSE-ELIGIBILITY-ADD ACL-ALLOW!
|
||||
['] ZUSE-ELIGIBILITY-ADD ACL-PIN
|
||||
LOG-INFO" zuse: activated"
|
||||
ELSE
|
||||
LOG-INFO" zuse: NOT activated -- no cert installed"
|
||||
|
||||
@@ -0,0 +1,787 @@
|
||||
# StarForth Primitive Word Reference
|
||||
|
||||
This reference covers every **C-implemented primitive** word that StarForth registers. It was built from
|
||||
`admin/LithosAnanake` at commit `6302dcb` (2026-09-23). It lists only words registered in C
|
||||
through `register_word()` or `vm_create_word()`. Words defined in FORTH inside capsules (`*.4th`) are out of scope.
|
||||
|
||||
Sources:
|
||||
|
||||
- `src/word_registry.c`: `register_forth79_words()` registers the core set in every VM.
|
||||
- `src/word_source/*.c`: one file per module.
|
||||
- `src/starkernel/capsule/mama_forth_words.c`: kernel-only Hera (Mama) and child-VM words.
|
||||
- `src/starkernel/repl.c` and `src/starkernel/doe_log.c`: kernel-only REPL and DoE words.
|
||||
|
||||
---
|
||||
|
||||
## Conventions
|
||||
|
||||
| Item | Meaning |
|
||||
|---|---|
|
||||
| Cell | `cell_t` is `int64_t`, so every cell is 64 bits and signed. |
|
||||
| Flag | TRUE is `-1` (all bits set) and FALSE is `0`. Words that take a flag treat any non-zero value as true. |
|
||||
| `addr` | A **VM address**: a byte offset into the VM's 5 MB linear memory (`VM_MEMORY_SIZE`), not a host pointer. |
|
||||
| `c-addr u` | A string given as its address and length. |
|
||||
| `d`, `ud` | A double-cell number made of two cells, with the **high cell on top**. |
|
||||
| `xt` | An execution token. In StarForth this is the `DictEntry*` of the word. |
|
||||
| `q` | A Q48.16 fixed-point value in one cell (`1.0` = `65536`). |
|
||||
| `"name"` | The word parses a name from the input stream after it. |
|
||||
| `( R: ... )` | The effect on the return stack. |
|
||||
| **IMM** | The word is IMMEDIATE, so it runs even while compiling. |
|
||||
| **CO** | The word is compile-only and sets `vm->error` if used outside a definition. |
|
||||
| **K** | The word is registered only in the kernel build (`__STARKERNEL__`). |
|
||||
| **H** | The word is registered only in the hosted build (the Linux or macOS binary). |
|
||||
|
||||
Errors: a primitive does not throw. On stack underflow or overflow, a bad address, or division by zero it sets
|
||||
`vm->error = 1` and logs a message.
|
||||
|
||||
Stack limits: the data stack and return stack hold 1024 cells each (`STACK_SIZE`). A word name can be at most 31
|
||||
characters (`WORD_NAME_MAX`).
|
||||
|
||||
Shadowing: when a later module registers a name again, the newer entry wins lookups. For example, `MOD`, `/MOD`,
|
||||
`*/` and `*/MOD` are registered by the arithmetic module and again by the mixed-arithmetic module, so the
|
||||
mixed-arithmetic versions are the active ones.
|
||||
|
||||
---
|
||||
|
||||
## Contents
|
||||
|
||||
1. [Stack](#1-stack)
|
||||
2. [Return stack](#2-return-stack)
|
||||
3. [Memory](#3-memory)
|
||||
4. [Arithmetic](#4-arithmetic)
|
||||
5. [Logic and comparison](#5-logic-and-comparison)
|
||||
6. [Mixed-precision arithmetic](#6-mixed-precision-arithmetic)
|
||||
7. [Double-cell numbers](#7-double-cell-numbers)
|
||||
8. [Number formatting and output](#8-number-formatting-and-output)
|
||||
9. [Strings, parsing, and input](#9-strings-parsing-and-input)
|
||||
10. [Terminal I/O](#10-terminal-io)
|
||||
11. [Blocks and mass storage](#11-blocks-and-mass-storage)
|
||||
12. [Dictionary space](#12-dictionary-space)
|
||||
13. [Dictionary manipulation](#13-dictionary-manipulation)
|
||||
14. [Vocabularies](#14-vocabularies)
|
||||
15. [System](#15-system)
|
||||
16. [Line editor](#16-line-editor)
|
||||
17. [Defining words and the compiler](#17-defining-words-and-the-compiler)
|
||||
18. [Control flow](#18-control-flow)
|
||||
19. [StarForth extensions](#19-starforth-extensions)
|
||||
20. [Word-level ACL](#20-word-level-acl)
|
||||
21. [Physics: benchmark and diagnostics](#21-physics-benchmark-and-diagnostics)
|
||||
22. [Physics: pipelining diagnostics](#22-physics-pipelining-diagnostics)
|
||||
23. [Physics: freeze, heat, and decay](#23-physics-freeze-heat-and-decay)
|
||||
24. [Dictionary heat optimisation](#24-dictionary-heat-optimisation)
|
||||
25. [Logging](#25-logging)
|
||||
26. [Q48.16 fixed-point math](#26-q4816-fixed-point-math)
|
||||
27. [Inference engine (SSM, L8, and Bayes)](#27-inference-engine-ssm-l8-and-bayes)
|
||||
28. [DEFER and IS](#28-defer-and-is)
|
||||
29. [Framebuffer (Hestia only)](#29-framebuffer-hestia-only)
|
||||
30. [Keyboard](#30-keyboard)
|
||||
31. [TrueType text](#31-truetype-text)
|
||||
32. [REPL scrollback](#32-repl-scrollback)
|
||||
33. [Kernel REPL and DoE hooks](#33-kernel-repl-and-doe-hooks)
|
||||
34. [Hera (Mama) and child-VM words](#34-hera-mama-and-child-vm-words)
|
||||
35. [Hosted lifecycle stubs](#35-hosted-lifecycle-stubs)
|
||||
36. [Implementation quirks to know](#36-implementation-quirks-to-know)
|
||||
|
||||
---
|
||||
|
||||
## 1. Stack
|
||||
`src/word_source/stack_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `DROP` | `( x -- )` | Discards the top cell. |
|
||||
| `DUP` | `( x -- x x )` | Copies the top cell. |
|
||||
| `?DUP` | `( x -- x x \| 0 -- 0 )` | Copies the top cell only when it is non-zero. The usual idiom is `?DUP IF ... THEN`. |
|
||||
| `SWAP` | `( x1 x2 -- x2 x1 )` | Swaps the top two cells. |
|
||||
| `OVER` | `( x1 x2 -- x1 x2 x1 )` | Copies the second cell to the top. |
|
||||
| `ROT` | `( x1 x2 x3 -- x2 x3 x1 )` | Moves the third cell to the top. |
|
||||
| `-ROT` | `( x1 x2 x3 -- x3 x1 x2 )` | Moves the top cell down to third place. This is the reverse of `ROT`. |
|
||||
| `DEPTH` | `( -- n )` | Pushes the number of cells that were on the data stack before `DEPTH` ran. |
|
||||
| `PICK` | `( xn … x0 n -- xn … x0 xn )` | Copies the n-th cell to the top. **0-based:** `0 PICK` is `DUP` and `1 PICK` is `OVER`. An error occurs if `n < 0` or `n ≥ depth`. |
|
||||
| `ROLL` | `( … n -- … )` | Moves a cell to the top and closes the gap. **Non-standard:** `n` counts from the *bottom* of the stack (1-based), so `1 ROLL` moves the deepest cell to the top. `0 ROLL` does nothing. See [§36](#36-implementation-quirks-to-know). |
|
||||
|
||||
## 2. Return stack
|
||||
`src/word_source/return_stack_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `>R` | `( x -- ) ( R: -- x )` | Moves a cell from the data stack to the return stack. Inside a definition, balance it with `R>` before `;` or `EXIT`. |
|
||||
| `R>` | `( -- x ) ( R: x -- )` | Moves a cell from the return stack back to the data stack. |
|
||||
| `R@` | `( -- x ) ( R: x -- x )` | Copies the top of the return stack without removing it. |
|
||||
|
||||
## 3. Memory
|
||||
`src/word_source/memory_words.c`. Every address is a VM byte offset and is checked against the VM's memory bounds.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `@` | `( addr -- x )` | Fetches the cell at `addr`. |
|
||||
| `!` | `( x addr -- )` | Stores `x` at `addr`. |
|
||||
| `C@` | `( addr -- c )` | Fetches the byte at `addr`, zero-extended. |
|
||||
| `C!` | `( c addr -- )` | Stores the low 8 bits of `c` at `addr`. |
|
||||
| `+!` | `( n addr -- )` | Adds `n` to the cell at `addr`. |
|
||||
| `-!` | `( n addr -- )` | Subtracts `n` from the cell at `addr`. |
|
||||
| `2@` | `( addr -- x-lo x-hi )` | Fetches two cells: the low cell from `addr` and the high cell from `addr+8`, leaving the high cell on top. |
|
||||
| `2!` | `( x-lo x-hi addr -- )` | Stores two cells: the low cell at `addr` and the high cell at `addr+8`. |
|
||||
| `FILL` | `( addr u c -- )` | Fills `u` bytes starting at `addr` with the byte `c`. |
|
||||
| `MOVE` | `( src dst u -- )` | Copies `u` bytes from `src` to `dst`. It is safe when the ranges overlap because it uses memmove semantics. |
|
||||
| `ERASE` | `( addr u -- )` | Sets `u` bytes to zero. |
|
||||
| `CELLS` | `( n -- n*8 )` | Scales a cell count to a byte count. |
|
||||
|
||||
## 4. Arithmetic
|
||||
`src/word_source/arithmetic_words.c`. All arithmetic is signed 64-bit, and division truncates toward zero as in C.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `+` | `( n1 n2 -- n1+n2 )` | Adds the two cells. |
|
||||
| `-` | `( n1 n2 -- n1-n2 )` | Subtracts `n2` from `n1`. |
|
||||
| `*` | `( n1 n2 -- n1*n2 )` | Multiplies the two cells. The result wraps modulo 2⁶⁴. |
|
||||
| `/` | `( n1 n2 -- n1/n2 )` | Divides, truncating toward zero. Division by zero sets an error. |
|
||||
| `MOD` | `( n1 n2 -- rem )` | Pushes the remainder of `n1 / n2`, which has the sign of `n1`. This name is shadowed by §6. |
|
||||
| `/MOD` | `( n1 n2 -- rem quot )` | Pushes the remainder and the quotient, with the quotient on top. This name is shadowed by §6. |
|
||||
| `*/` | `( n1 n2 n3 -- n1*n2/n3 )` | Multiplies and then divides using a wide intermediate. This name is shadowed by §6. |
|
||||
| `*/MOD` | `( n1 n2 n3 -- rem quot )` | Like `*/`, but also leaves the remainder. This name is shadowed by §6. |
|
||||
| `1+` `1-` | `( n -- n±1 )` | Increments or decrements by 1. |
|
||||
| `2+` `2-` | `( n -- n±2 )` | Adds or subtracts 2. |
|
||||
| `2*` | `( n -- n*2 )` | Shifts left by one bit. |
|
||||
| `2/` | `( n -- n/2 )` | Shifts right by one bit, keeping the sign (arithmetic shift). |
|
||||
| `ABS` | `( n -- \|n\| )` | Pushes the absolute value. |
|
||||
| `NEGATE` | `( n -- -n )` | Pushes the two's-complement negation. |
|
||||
| `MIN` `MAX` | `( n1 n2 -- n3 )` | Pushes the smaller or the larger value, compared as signed numbers. |
|
||||
|
||||
## 5. Logic and comparison
|
||||
`src/word_source/logical_words.c`. Comparison words return a proper flag of `-1` or `0`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `AND` `OR` `XOR` | `( x1 x2 -- x3 )` | Bitwise AND, OR, and XOR. |
|
||||
| `NOT` | `( x -- flag )` | **FORTH-79 logical NOT:** `0` gives `TRUE` and any other value gives `FALSE`. This is *not* a bitwise complement; use `INVERT` for that. |
|
||||
| `INVERT` | `( x -- ~x )` | Bitwise complement (from FORTH-83). |
|
||||
| `LSHIFT` | `( x u -- x<<u )` | Logical shift left by `u` bits. |
|
||||
| `RSHIFT` | `( x u -- x>>u )` | Logical (unsigned) shift right by `u` bits. |
|
||||
| `0=` | `( n -- flag )` | True if `n` is 0. |
|
||||
| `0<` | `( n -- flag )` | True if `n` is negative. |
|
||||
| `0>` | `( n -- flag )` | True if `n` is positive. |
|
||||
| `0<>` | `( n -- flag )` | True if `n` is not 0. |
|
||||
| `=` `<>` | `( n1 n2 -- flag )` | Tests for equality or inequality. |
|
||||
| `<` `>` `<=` `>=` | `( n1 n2 -- flag )` | Signed comparisons of `n1` against `n2`. |
|
||||
| `U<` `U>` | `( u1 u2 -- flag )` | Unsigned comparisons. |
|
||||
| `WITHIN` | `( n lo hi -- flag )` | True if `lo ≤ n < hi`, using the standard half-open range. |
|
||||
| `TRUE` | `( -- -1 )` | Pushes the canonical true flag. |
|
||||
| `FALSE` | `( -- 0 )` | Pushes the canonical false flag. |
|
||||
|
||||
## 6. Mixed-precision arithmetic
|
||||
`src/word_source/mixed_arithmetic_words.c`. A double here means two full 64-bit cells (128 bits).
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `M+` | `( d n -- d' )` | Adds a signed single to a double and propagates the carry into the high cell. |
|
||||
| `M-` | `( d n -- d' )` | Subtracts a signed single from a double and propagates the borrow. |
|
||||
| `M*` | `( n1 n2 -- d )` | Multiplies 64×64 into a full 128-bit signed product, using `__int128` internally. The result can be printed with `D.`. |
|
||||
| `M/MOD` | `( d n -- rem quot )` | Divides a 128-bit double by a single, leaving the quotient on top. It uses bit-serial long division, so it works in the freestanding kernel without libgcc. |
|
||||
| `MOD` | `( n1 n2 -- rem )` | **Active version.** Computes `n1 % n2`. Division by zero sets an error. |
|
||||
| `/MOD` | `( n1 n2 -- rem quot )` | **Active version.** Leaves the remainder under the quotient. Division by zero sets an error. |
|
||||
| `*/` | `( n1 n2 n3 -- n4 )` | **Active version.** Computes `(n1*n2)/n3` with a wide intermediate, so `n1*n2` does not overflow. Division by zero sets an error. Typical use is scaling, for example `x 355 113 */`. |
|
||||
| `*/MOD` | `( n1 n2 n3 -- rem quot )` | **Active version.** Like `*/`, but also leaves the remainder under the quotient. |
|
||||
|
||||
## 7. Double-cell numbers
|
||||
`src/word_source/double_words.c`. In every stack picture, `d` stands for the pair `( lo hi )` with the high cell on top.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `S>D` | `( n -- d )` | Sign-extends a single to a double. |
|
||||
| `D+` `D-` | `( d1 d2 -- d3 )` | Double add and subtract, with carry or borrow. |
|
||||
| `DNEGATE` | `( d -- -d )` | Negates a double. |
|
||||
| `DABS` | `( d -- \|d\| )` | Pushes the absolute value of a double. |
|
||||
| `DMAX` `DMIN` | `( d1 d2 -- d3 )` | Pushes the larger or smaller double, compared as signed values. |
|
||||
| `D<` | `( d1 d2 -- flag )` | Signed less-than on doubles. |
|
||||
| `D=` | `( d1 d2 -- flag )` | Equality on doubles. |
|
||||
| `D0=` | `( d -- flag )` | True if the double is zero. |
|
||||
| `D0<` | `( d -- flag )` | True if the double is negative. |
|
||||
| `D2*` | `( d -- d*2 )` | Shifts a double left by one bit across both cells. |
|
||||
| `D2/` | `( d -- d/2 )` | Shifts a double right by one bit (arithmetic shift) across both cells. |
|
||||
| `2DROP` | `( x1 x2 -- )` | Drops a cell pair. |
|
||||
| `2DUP` | `( x1 x2 -- x1 x2 x1 x2 )` | Duplicates a cell pair. |
|
||||
| `2SWAP` | `( p1 p2 -- p2 p1 )` | Swaps two cell pairs. |
|
||||
| `2OVER` | `( p1 p2 -- p1 p2 p1 )` | Copies the second pair to the top. |
|
||||
| `2ROT` | `( p1 p2 p3 -- p2 p3 p1 )` | Rotates three cell pairs. |
|
||||
| `2>R` | `( x1 x2 -- ) ( R: -- x1 x2 )` | Moves a pair to the return stack. |
|
||||
| `2R>` | `( -- x1 x2 ) ( R: x1 x2 -- )` | Moves a pair back from the return stack. |
|
||||
| `2R@` | `( -- x1 x2 ) ( R: x1 x2 -- x1 x2 )` | Copies a pair from the return stack. |
|
||||
|
||||
## 8. Number formatting and output
|
||||
`src/word_source/format_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `.` | `( n -- )` | Prints a signed number in the current `BASE`, followed by a space. |
|
||||
| `.R` | `( n width -- )` | Prints a signed number right-aligned in a field `width` characters wide. |
|
||||
| `U.` | `( u -- )` | Prints an unsigned number followed by a space. |
|
||||
| `U.R` | `( u width -- )` | Prints an unsigned number right-aligned. |
|
||||
| `D.` | `( d -- )` | Prints a signed double. |
|
||||
| `D.R` | `( d width -- )` | Prints a signed double right-aligned. |
|
||||
| `.S` | `( -- )` | Prints the data stack without changing it. This is the main debugging aid. |
|
||||
| `?` | `( addr -- )` | Prints the cell at `addr`; it is the same as `@ .`. |
|
||||
| `DUMP` | `( addr u -- )` | Prints a hex and ASCII dump of `u` bytes starting at `addr`. |
|
||||
| `<#` | `( -- )` | Starts pictured numeric output by resetting the conversion buffer. |
|
||||
| `#` | `( ud -- ud' )` | Converts one digit (`ud mod BASE`) into the buffer. It also accepts a single signed cell and converts its magnitude. |
|
||||
| `#S` | `( ud -- 0 0 )` | Converts digits until the value is zero, always producing at least one digit. It accepts a single cell the same way `#` does. |
|
||||
| `HOLD` | `( c -- )` | Inserts the character `c` into the pictured output buffer. |
|
||||
| `SIGN` | `( n -- )` | Inserts `-` if `n` is negative. |
|
||||
| `#>` | `( ud -- c-addr u )` | Ends conversion and leaves the string. It is tolerant: it pops `ud` only if one is present. |
|
||||
| `BASE` | `( -- addr )` | Pushes the address of the number-conversion radix variable. |
|
||||
| `DECIMAL` `HEX` `OCTAL` | `( -- )` | Sets `BASE` to 10, 16, or 8. |
|
||||
|
||||
Example: `: .$ ( n -- ) <# # # 46 HOLD #S #> TYPE ;` prints `1234` as `12.34`.
|
||||
|
||||
## 9. Strings, parsing, and input
|
||||
`src/word_source/string_words.c`. The comparison and search words below also accept a counted string in place of an
|
||||
`addr u` pair; they detect it when the first byte at `addr` equals `u`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `COUNT` | `( c-addr1 -- c-addr2 u )` | Converts a counted string (length byte followed by characters) into an address and length. |
|
||||
| `EXPECT` | `( addr u -- )` | Reads up to `u` characters from the terminal into `addr` and stores the count read in `SPAN`. |
|
||||
| `SPAN` | `( -- addr )` | Pushes the address of the variable that holds the count from the last `EXPECT`. |
|
||||
| `QUERY` | `( -- )` | Reads a line into `TIB` and resets `>IN`. |
|
||||
| `TIB` | `( -- addr )` | Pushes the address of the terminal input buffer. |
|
||||
| `>IN` | `( -- addr )` | Pushes the address of the offset into the current input source. |
|
||||
| `SOURCE` | `( -- addr u )` | Pushes the current input buffer and its length. |
|
||||
| `WORD` | `( c -- c-addr )` | Skips leading `c` characters, parses up to the next `c`, and returns a counted string. The usual form is `BL WORD`. |
|
||||
| `BL` | `( -- 32 )` | Pushes the ASCII space character. |
|
||||
| `S"` **IMM** | `( "ccc<">" -- c-addr u )` | In interpret mode, stores the string at `HERE` and pushes it. When compiling, it compiles `(s")` followed by the inline text. |
|
||||
| `(s")` | `( -- c-addr u )` | Runtime for a compiled `S"`: reads the inline `[len][chars][pad]` block and skips the IP past it. The compiler inserts it; you do not call it directly. |
|
||||
| `[']` **IMM** | `( "name" -- xt )` | While compiling, compiles the xt of `name` as a literal. In interpret mode it behaves like `'`. |
|
||||
| `LITERAL` `[LITERAL]` | – | Placeholders that do nothing. `LITERAL` is re-registered in §17 (the working version); `[LITERAL]` has no replacement and still does nothing. |
|
||||
| `CONVERT` | `( d1 addr1 -- d2 addr2 )` | Accumulates the digits at `addr1+1…` into `d1` and stops at the first non-digit. This is a simplified version. |
|
||||
| `NUMBER` | `( c-addr -- n flag )` | Converts a counted string to a number. Only base 10 is supported, and `flag` shows whether it succeeded. |
|
||||
| `ENCLOSE` | `( addr c -- addr n1 n2 n3 )` | The classic FIG parser: gives the offsets of the start of the token, the delimiter after it, and the next character. |
|
||||
| `-TRAILING` | `( addr u -- addr u' )` | Removes trailing spaces from the length. |
|
||||
| `CMOVE` | `( src dst u -- )` | Copies bytes upward from low to high addresses. It is safe for overlapping ranges when `dst ≤ src`. |
|
||||
| `CMOVE>` | `( src dst u -- )` | Copies bytes downward from high to low addresses. It is safe for overlapping ranges when `dst > src`. |
|
||||
| `COMPARE` | `( a1 u1 a2 u2 -- n )` | Compares two strings case-sensitively and returns `-1`, `0`, or `1`. |
|
||||
| `SEARCH` | `( a1 u1 a2 u2 -- a3 u3 flag )` | Finds string 2 inside string 1. If found, it returns the tail starting at the match and `-1`. If not, it returns string 1 unchanged and `0`. |
|
||||
| `SCAN` | `( addr u c -- addr' u' )` | Advances to the first occurrence of `c`. If there is none, it returns the end of the string and `0`. |
|
||||
| `SKIP` | `( addr u c -- addr' u' )` | Skips leading occurrences of `c`. |
|
||||
| `BLANK` | `( addr u -- )` | Fills `u` bytes with spaces. |
|
||||
|
||||
## 10. Terminal I/O
|
||||
`src/word_source/io_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `EMIT` | `( c -- )` | Prints one character. |
|
||||
| `CR` | `( -- )` | Prints a newline. |
|
||||
| `KEY` | `( -- c )` | Waits for a character and pushes it. |
|
||||
| `?TERMINAL` | `( -- flag )` | True if a key is waiting. It does not block. |
|
||||
| `TYPE` | `( c-addr u -- )` | Prints `u` characters. |
|
||||
| `SPACE` | `( -- )` | Prints one space. |
|
||||
| `SPACES` | `( n -- )` | Prints `n` spaces. |
|
||||
| `."` **IMM** | `( "ccc<">" -- )` | In interpret mode, prints the string immediately. When compiling, it compiles `(do-string)` and the inline text. |
|
||||
| `(do-string)` | `( -- )` | Runtime for a compiled `."`: prints the inline string and skips the IP past it. The compiler inserts it; you do not call it directly. |
|
||||
|
||||
## 11. Blocks and mass storage
|
||||
`src/word_source/block_words.c`. A block is 1024 bytes, viewed as 16 lines of 64 characters. Block numbers are
|
||||
LBNs (logical block numbers) in one address space that spans every attached device.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BLOCK` | `( u -- addr )` | Returns the VM address of the buffer holding block `u`, reading it from disk if needed. It does not mark the buffer dirty. |
|
||||
| `BUFFER` | `( u -- addr )` | Assigns a buffer to block `u` *without* reading from disk and marks it dirty. Use it when you will overwrite the whole block. |
|
||||
| `UPDATE` | `( -- )` | Marks the current (`SCR`) block dirty and syncs it to the C block layer. |
|
||||
| `SAVE-BUFFERS` | `( -- )` | Writes every dirty buffer to disk. |
|
||||
| `EMPTY-BUFFERS` | `( -- )` | Discards every buffer **without** writing it and zeroes the user block window. |
|
||||
| `FLUSH` | `( -- )` | Runs `SAVE-BUFFERS` and then invalidates all buffers. |
|
||||
| `LOAD` | `( u -- )` | Sets `SCR` to `u` and interprets the 1024 bytes of block `u` as FORTH source. Block 0 cannot be loaded. |
|
||||
| `THRU` | `( u1 u2 -- )` | Loads blocks `u1` through `u2`, including both ends. |
|
||||
| `-->` | `( -- )` | Inside a block being loaded, continues interpreting at the next block. |
|
||||
| `LIST` | `( u -- )` | Sets `SCR` to `u` and prints the block. |
|
||||
| `SCR` | `( -- addr )` | Pushes the address of the variable holding the block number last listed or loaded. |
|
||||
| `BLK-CONFIRM-FORMAT` | `( lbn -- )` | Commits the container format of the device that owns `lbn`. Until this has run, the block layer **refuses every write** to that device. Only the owner (for example Artemis) should call it, and only after checking the disk contents are safe to touch. |
|
||||
| `RELOCATE-BLOCK` | `( home target -- )` | Moves the contents of `home` to `target` and redirects all later access to `home` through `target`. It is a mechanical primitive: it does not check whether `target` is free or owned by the caller. |
|
||||
| `BLK-ACL-ALLOW@` | `( blk -- allow )` | Reads the cached allow/deny flag of a block's ACL. |
|
||||
| `BLK-ACL-ALLOW!` | `( allow blk -- )` | Sets a block's cached allow/deny flag. |
|
||||
| `BLK-ACL-TTL@` | `( blk -- ttl )` | Reads a block's ACL TTL countdown. |
|
||||
| `BLK-ACL-TTL!` | `( ttl blk -- )` | Sets a block's ACL TTL countdown. |
|
||||
| `BLK-OWNER@` | `( blk -- fp )` | Pushes the 8-byte owner fingerprint as the raw bits of one cell. There is no `BLK-OWNER!`: ownership is set only in C, during MINT or birth. |
|
||||
| `BLK-ATTACH` | `( dev-ptr -- ok? )` | Registers an already-open `blkio_dev_t*`, passed as a raw pointer cell, in the unified LBN space. The pointer is trusted without checks. Artemis's USB-attach handler uses it. |
|
||||
|
||||
## 12. Dictionary space
|
||||
`src/word_source/dictionary_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HERE` | `( -- addr )` | Pushes the next free byte in the dictionary. |
|
||||
| `ALIGN` | `( -- )` | Rounds `HERE` up to the next 8-byte cell boundary. |
|
||||
| `ALLOT` | `( n -- )` | Reserves `n` bytes at `HERE`. A negative `n` gives space back. |
|
||||
| `,` | `( x -- )` | Compiles one cell at `HERE` and advances `HERE`. |
|
||||
| `C,` | `( c -- )` | Compiles one byte. |
|
||||
| `2,` | `( x-lo x-hi -- )` | Compiles two cells, low cell first. |
|
||||
| `PAD` | `( -- addr )` | Pushes the address of a 512-byte scratch buffer near the top of memory. It is safe for temporary strings. |
|
||||
| `SP@` | `( -- n )` | Pushes the data stack pointer *index* (`dsp`). An empty stack gives `-1` and one item gives `0`. |
|
||||
| `SP!` | `( n -- )` | Restores the stack pointer index. It can only shrink the stack, never grow it. |
|
||||
| `LATEST` | `( -- addr )` | Pushes the address of the most recent definition. |
|
||||
|
||||
## 13. Dictionary manipulation
|
||||
`src/word_source/dictionary_manipulation_words.c`. Header-field words work on raw header addresses. They exist for
|
||||
FIG and FORTH-79 compatibility; take care with them.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `'` | `( "name" -- xt )` | Parses `name` and pushes its xt. It is not IMMEDIATE; inside a definition, use `[']`. |
|
||||
| `FIND` | `( "name" -- xt \| 0 )` | **Parses from the input stream**, not from a counted string on the stack. It pushes the entry, or `0` if the word is not found (a miss is not an error). For a counted string already in memory, use `(FIND)` from §14. |
|
||||
| `SMUDGE` | `( -- )` | **CO.** Toggles the smudge (hidden) bit on the latest word. |
|
||||
| `HIDDEN` | `( -- )` | **CO.** Sets the latest word's hidden bit (unlike `SMUDGE`, it does not toggle). |
|
||||
| `>BODY` | `( xt -- addr )` | Pushes the address of the parameter (data) field. |
|
||||
| `>NAME` | `( xt -- nfa )` | Pushes the name field. |
|
||||
| `NAME>` | `( nfa -- xt )` | Goes from the name field to the xt. |
|
||||
| `>LINK` | `( xt -- lfa )` | Pushes the link field. |
|
||||
| `LINK>` | `( lfa -- xt )` | Follows the link to the next (older) word. |
|
||||
| `CFA` `LFA` `NFA` `PFA` | `( addr -- addr' )` | FIG-style field-address conversions (code, link, name, and parameter fields). |
|
||||
| `TRAVERSE` | `( addr n -- addr' )` | Moves across a name field forward (`n=1`) or backward (`n=-1`). |
|
||||
| `INTERPRET` | `( -- )` | Runs the text interpreter on the rest of the current input. |
|
||||
|
||||
## 14. Vocabularies
|
||||
`src/word_source/vocabulary_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `VOCABULARY` | `( "name" -- )` | Creates a vocabulary. Running `name` later makes it the `CONTEXT` (search) vocabulary. |
|
||||
| `DEFINITIONS` | `( -- )` | Sets `CURRENT` to `CONTEXT`, so new definitions go into the vocabulary being searched. |
|
||||
| `CONTEXT` | `( -- addr )` | Pushes the address of the search-vocabulary pointer. |
|
||||
| `CURRENT` | `( -- addr )` | Pushes the address of the definition-vocabulary pointer. |
|
||||
| `FORTH` | `( -- )` | Makes the root `FORTH` vocabulary the context. |
|
||||
| `ORDER` | `( -- )` | Prints the search order (`CONTEXT`, then `FORTH`) and `CURRENT`. |
|
||||
| `(FIND)` | `( c-addr -- c-addr 0 \| xt 1 \| xt -1 )` | Looks up a counted string in `CONTEXT` and then in `FORTH`. It returns `1` for an IMMEDIATE word, `-1` for a normal word, and `0` if not found. |
|
||||
|
||||
Example: `VOCABULARY GRAPHICS GRAPHICS DEFINITIONS : BOX ... ; FORTH DEFINITIONS`
|
||||
|
||||
## 15. System
|
||||
`src/word_source/system_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `(` **IMM** | `( "ccc<)>" -- )` | Starts a comment that runs to the closing `)`. |
|
||||
| `\` **IMM** | `( "ccc<eol>" -- )` | Starts a comment that runs to the end of the line. |
|
||||
| `EXECUTE` | `( xt -- )` | Runs the word identified by `xt`. |
|
||||
| `NOP` | `( -- )` | Does nothing. |
|
||||
| `QUIT` **IMM** | `( -- ) ( R: … -- )` | Clears the return stack and the error flag and returns to the outer interpreter. The data stack is kept. It is refused (sets an error) inside a definition. |
|
||||
| `ABORT` | `( … -- )` | Clears both stacks and returns to the interpreter. It is **not** reported as an error. |
|
||||
| `ABORT"` **IMM** | `( flag "ccc<">" -- )` | If `flag` is non-zero, prints the message and runs `ABORT`. It works in both interpret and compile mode. |
|
||||
| `(ABORT")` | `( flag addr u -- )` | Runtime for a compiled `ABORT"`. The compiler inserts it; you do not call it directly. |
|
||||
| `COLD` | `( -- )` | Clears both stacks and the error flag, returns to interpret mode, and moves `HERE` back to 1024 if it is higher. Dictionary headers are **not** removed; this is a minimal cold start. |
|
||||
| `WARM` | `( -- )` | Clears both stacks and the error flag and returns to interpret mode. `HERE` and the dictionary are kept. |
|
||||
| `BYE` | `( -- )` | Leaves this VM. In a child VM it halts the VM and returns to the parent's REPL. On Hera, the kernel's `BYE` from §34 takes precedence. |
|
||||
| `REBOOT` | `( c-addr u -- )` | Sets the boot arguments and does a cold reset. Interpret mode only. |
|
||||
| `SAVE-SYSTEM` | `( -- )` | Takes a simple snapshot of the start of VM memory. |
|
||||
| `WORDS` | `( -- )` | Lists the words in the current vocabulary. |
|
||||
| `VLIST` | `( -- )` | Gives a detailed word listing. |
|
||||
| `SEE` | `( "name" -- )` | Decompiles and shows a definition. |
|
||||
| `PAGE` | `( -- )` | Clears the screen. |
|
||||
| `79-STANDARD` | `( -- flag )` | Pushes `-1` when FORTH-79 compliance mode is on. |
|
||||
|
||||
## 16. Line editor
|
||||
`src/word_source/editor_words.c`. The editor works on block `SCR` as 16 lines of 64 characters.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `L` | `( u -- )` | Prints line `u` (0–15) of the current screen. |
|
||||
| `S` | `( c-addr len u -- )` | Replaces line `u` with the string, padding with spaces or truncating to 64 characters. |
|
||||
| `SHOW` | `( -- )` | Prints the whole screen with line numbers. |
|
||||
| `EDIT` | `( u -- )` | Opens a minimal stdin/stdout line-editor shell on block `u`. |
|
||||
|
||||
## 17. Defining words and the compiler
|
||||
`src/word_source/defining_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `:` **IMM** | `( "name" -- )` | Starts a colon definition and switches to compile mode. The new word stays hidden until `;`. |
|
||||
| `;` **IMM** | `( -- )` | Compiles `EXIT`, ends the definition, reveals the word, and returns to interpret mode. |
|
||||
| `CREATE` | `( "name" -- )` | Makes a header whose runtime pushes its data-field address (`HERE` aligned to a cell). It allocates **no** space, so follow it with `ALLOT` or `,`. |
|
||||
| `VARIABLE` | `( "name" -- )` | Makes a word that pushes the address of one newly allocated cell. |
|
||||
| `CONSTANT` | `( x "name" -- )` | Makes a word that pushes `x`. |
|
||||
| `DOES>` **IMM** | `( -- )` | Inside a defining word, ends the create part. Words later made by that defining word run the code after `DOES>` with their body address on the stack. |
|
||||
| `IMMEDIATE` **IMM** | `( -- )` | Marks the latest definition IMMEDIATE. |
|
||||
| `STATE` | `( -- addr )` | Pushes the address of the compile-state cell (0 means interpreting). |
|
||||
| `[` **IMM** | `( -- )` | Switches to interpret mode inside a definition. |
|
||||
| `]` **IMM** | `( -- )` | Switches to compile mode. |
|
||||
| `LITERAL` **IMM** | `( x -- )` | Compiles `x` so that it is pushed at runtime. Typical use: `[ 6 7 * ] LITERAL`. |
|
||||
| `LIT` | `( -- x )` | Runtime for literals: pushes the next inline cell. The compiler inserts it; you do not call it directly. |
|
||||
| `COMPILE` **IMM** | `( "name" -- )` | Legacy form: compiles a call to `name`. |
|
||||
| `[COMPILE]` **IMM** | `( "name" -- )` | Compiles `name` even when it is IMMEDIATE. |
|
||||
| `FORGET` | `( "name" -- )` | Removes `name` and every newer word and moves `HERE` back. Words below `FENCE` cannot be forgotten. |
|
||||
| `FENCE` | `( -- )` | Moves the `FORGET` boundary up to the current top of the dictionary. A capsule calls it after loading to protect its own words. |
|
||||
| `does_rt` | – | Internal `DOES>` helper that switches the new child word to DODOES. It is registered only so the threaded code can refer to it; do not call it. |
|
||||
|
||||
Example: `: ARRAY ( n "name" -- ) CREATE CELLS ALLOT DOES> ( i -- addr ) SWAP CELLS + ;`
|
||||
|
||||
## 18. Control flow
|
||||
`src/word_source/control_words.c`. Every structure word is **IMM** and **CO**. Branch offsets are in bytes. Up to 64
|
||||
structures can be nested at compile time (`CF_STACK_MAX`).
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `IF` | `( flag -- )` | Runs the following code only if `flag` is non-zero. It compiles `(0BRANCH)`. |
|
||||
| `ELSE` | `( -- )` | Starts the code that runs when the `IF` flag was zero. |
|
||||
| `THEN` | `( -- )` | Ends an `IF` or `IF … ELSE` structure. |
|
||||
| `BEGIN` | `( -- )` | Marks the start of a loop. |
|
||||
| `UNTIL` | `( flag -- )` | Loops back to `BEGIN` while `flag` is zero. |
|
||||
| `AGAIN` | `( -- )` | Loops back to `BEGIN` unconditionally. Leave with `EXIT` or `ABORT`. |
|
||||
| `WHILE` | `( flag -- )` | In `BEGIN … WHILE … REPEAT`, leaves the loop when `flag` is zero. |
|
||||
| `REPEAT` | `( -- )` | Jumps back to `BEGIN` and resolves the exit of `WHILE`. |
|
||||
| `DO` | `( limit start -- ) ( R: -- limit index )` | Starts a counted loop that always runs at least once. |
|
||||
| `?DO` | `( limit start -- )` | Like `DO`, but skips the loop body when `start = limit`. |
|
||||
| `LOOP` | `( -- )` | Adds 1 to the index and loops while `index < limit`. |
|
||||
| `+LOOP` | `( n -- )` | Adds `n` to the index. For `n ≥ 0` it continues while `index < limit`; for `n < 0` it continues while `index ≥ limit`. |
|
||||
| `LEAVE` | `( -- )` | Exits the innermost `DO` loop immediately: it sets the index to the limit and jumps past `LOOP`. |
|
||||
| `I` | `( -- index )` | Pushes the index of the innermost loop. It is not IMMEDIATE. |
|
||||
| `J` | `( -- index )` | Pushes the index of the next outer loop. |
|
||||
| `UNLOOP` | `( -- ) ( R: limit index -- )` | Drops the loop parameters. Use it before `EXIT` inside a `DO` loop. |
|
||||
| `EXIT` | `( -- )` | Returns from the current colon definition. Using it in interpret mode is an error. |
|
||||
| `CASE` | `( x -- x )` | Starts a case structure. |
|
||||
| `OF` | `( x v -- \| x )` | If `x = v`, drops both and runs the clause; otherwise keeps `x` and skips to the next `OF`. |
|
||||
| `ENDOF` | `( -- )` | Ends an `OF` clause and jumps to `ENDCASE`. |
|
||||
| `ENDCASE` | `( x -- )` | Drops the selector and resolves every `ENDOF` jump. |
|
||||
| `(BRANCH)` | `( -- )` | Runtime: unconditional relative branch. The compiler inserts it; you do not call it directly. |
|
||||
| `(0BRANCH)` | `( flag -- )` | Runtime: branches when `flag` is 0. The compiler inserts it; you do not call it directly. |
|
||||
| `(DO)` `(?DO)` | `( limit start -- )` | Runtime for loop entry. The compiler inserts them; you do not call them directly. |
|
||||
| `(LOOP)` `(+LOOP)` | `( -- )` / `( n -- )` | Runtime for loop increment and test. The compiler inserts them; you do not call them directly. |
|
||||
| `(LEAVE)` | `( -- )` | Runtime for `LEAVE`: sets index to limit. The compiler inserts it; you do not call it directly. |
|
||||
|
||||
Examples:
|
||||
```forth
|
||||
: COUNTDOWN ( n -- ) BEGIN DUP . 1- DUP 0= UNTIL DROP ;
|
||||
: TABLE ( -- ) 5 0 DO 5 0 DO I J * 4 .R LOOP CR LOOP ;
|
||||
: COLOR ( n -- ) CASE 0 OF ." red" ENDOF 1 OF ." green" ENDOF ." ?" ENDCASE ;
|
||||
```
|
||||
|
||||
## 19. StarForth extensions
|
||||
`src/word_source/starforth_words.c`. These words are registered in both `FORTH` and the `STARFORTH` vocabulary.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `ENTROPY@` | `( xt -- n )` | Pushes the `execution_heat` counter of a word. The name says "entropy", but the value is execution heat. Registered only in the `STARFORTH` vocabulary. |
|
||||
| `ENTROPY!` | `( n xt -- )` | Sets a word's `execution_heat` counter. Registered only in the `STARFORTH` vocabulary. |
|
||||
| `WORD-ENTROPY` | `( -- )` | Prints the execution heat of every word. |
|
||||
| `RESET-ENTROPY` | `( -- )` | Sets every heat counter to zero. |
|
||||
| `TOP-WORDS` | `( n -- )` | Prints the `n` hottest words. |
|
||||
| `(-` | `( "ccc<)>" -- )` | A comment that marks metadata blocks to extract into `init.4th`. It consumes input up to `)`. |
|
||||
| `INIT` | `( -- )` | Reads `./capsules/core/init.4th`, copies its blocks from block 1 onward, and runs them. |
|
||||
| `VERSION` | `( -- )` | Prints `StarForth v<ver> <arch> <variant> <timestamp>`. |
|
||||
| `SEED` | `( n -- )` | Seeds the PRNG so random sequences can be reproduced. |
|
||||
| `RANDOM` | `( lo hi -- n )` | Pushes a pseudo-random number in `[lo, hi]`, including both ends. |
|
||||
| `WAIT` | `( n -- )` | Waits `n` heartbeat ticks by calling `vm_tick()` `n` times. It counts heartbeats, not wall-clock time, so it behaves the same on amd64, aarch64, and riscv64. |
|
||||
| `HEARTBEAT-TICKS@` | `( -- n )` | Pushes the canonical heartbeat tick count (Loop #7). The project uses this as its clock. It is read-only. |
|
||||
| `ZUSE-AUTHENTICATE` | `( -- )` | Sets `zuse_session = 1`. The write happens only in C. |
|
||||
| `ZUSE-SESSION?` | `( -- flag )` | True if `ZUSE-AUTHENTICATE` has run during this boot. It is read-only. |
|
||||
| `ZUSE-PUBKEY@` | `( i -- u )` | Pushes 8-byte little-endian chunk `i` (0–3) of Zuse's Ed25519 **public** key. An out-of-range `i` pushes 0 and sets an error. The private seed is never exposed. |
|
||||
| `ZUSE-CERT-INSTALLED?` | `( -- flag )` | True once the one-time certificate fuse has been blown. |
|
||||
|
||||
## 20. Word-level ACL
|
||||
`src/word_source/acl_words.c`. Every word takes an `xt`, obtained with `'` or `[']`. Writes are silently ignored for
|
||||
a **pinned** word.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `ACL-MODE@` | `( xt -- mode )` | Pushes the enforcement mode: 0 is STRICT (the decision is permanent) and 1 is TTL (the decision is rechecked when the countdown expires). |
|
||||
| `ACL-MODE!` | `( mode xt -- )` | Sets the enforcement mode. |
|
||||
| `ACL-TTL@` | `( xt -- n )` | Pushes the TTL countdown. At 0 in TTL mode, the interpreter calls `acl_recheck()`. |
|
||||
| `ACL-TTL!` | `( n xt -- )` | Sets the TTL, clamped to `[0, UINT32_MAX]`. |
|
||||
| `ACL-ALLOW@` | `( xt -- flag )` | Pushes the cached decision: `-1` means allowed and `0` means denied. |
|
||||
| `ACL-ALLOW!` | `( flag xt -- )` | Sets the cached decision; any non-zero value means allowed. |
|
||||
| `ACL-PINNED?` | `( xt -- flag )` | True if the ACL fields are pinned and therefore immutable. |
|
||||
| `ACL-PIN` | `( xt -- )` | Pins the word. **This is one-way**: no FORTH word can unpin it. |
|
||||
| `ACL-HEAT@` | `( xt -- heat )` | Pushes the execution heat. `ACL.4th` uses it to calibrate TTLs. |
|
||||
| `ACL-WORD-ID` | `( xt -- id )` | Pushes the word's stable `word_id`. It never changes, so it is safe to use as a table index. |
|
||||
| `ACL-INHERIT` | `( src-xt dst-xt -- )` | Copies the mode from `src` to `dst` and resets `dst`: unpinned, TTL 0, allowed. It is written in C because only C may clear a pin. |
|
||||
| `ACL-INIT-PRIMITIVES` | `( -- )` | For every unpinned word, sets TTL to 0, allow to 1, and mode to TTL. `ACL-BOOT` calls it. |
|
||||
|
||||
## 21. Physics: benchmark and diagnostics
|
||||
`src/word_source/physics_benchmark_words.c`. These are interactive diagnostics that print to the console.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BENCH-DICT-LOOKUP` | `( iterations -- )` | Benchmarks dictionary lookup and records Q48.16 latencies. Use at least 10,000 iterations; 100,000 is the standard run and 1,000,000 is a stress test. |
|
||||
| `PHYSICS-CACHE-STATS` | `( -- )` | Prints hot-words cache statistics. |
|
||||
| `PHYSICS-TOGGLE-CACHE` | `( -- )` | Turns the hot-words cache on or off, for A/B testing. |
|
||||
| `PHYSICS-RESET-STATS` | `( -- )` | Resets the cache statistics. |
|
||||
| `PHYSICS-BUILD-INFO` | `( -- )` | Prints the variant's build configuration. |
|
||||
| `PHYSICS-BAYESIAN-REPORT` | `( addr -- )` | Prints a Bayesian comparison of the current cache statistics against the baseline stored at `addr`. |
|
||||
|
||||
> `physics_diagnostic_words.c` also defines `PHYSICS-WORD-METRICS`, `PHYSICS-CALC-KNOBS`, `PHYSICS-BURN ( n -- )`
|
||||
> and `PHYSICS-SHOW-FEEDBACK`, but nothing calls `register_physics_diagnostic_words()`, so **none of them are in
|
||||
> the dictionary** at this commit.
|
||||
|
||||
## 22. Physics: pipelining diagnostics
|
||||
`src/word_source/physics_pipelining_diagnostic_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `PIPELINING-SHOW-STATS` | `( "name" -- )` | Prints the word-to-word transition metrics of `name`. |
|
||||
| `PIPELINING-SHOW-TOP-TRANSITIONS` | `( "name" n -- )` | Prints the `n` words that most often follow `name`. |
|
||||
| `PIPELINING-ANALYZE-WORD` | `( "name" -- )` | Prints a full analysis of one word's transitions, with hints for reading them. |
|
||||
| `PIPELINING-STATS` | `( -- )` | Prints pipelining statistics aggregated across the whole dictionary. |
|
||||
| `PIPELINING-RESET-ALL` | `( -- )` | Clears all transition metrics. |
|
||||
| `PIPELINING-ENABLE` | `( -- )` | Placeholder. Pipelining is switched on or off at compile time. |
|
||||
|
||||
## 23. Physics: freeze, heat, and decay
|
||||
`src/word_source/physics_freeze_words.c`. Words are named by `c-addr u` strings, for example `S" DUP" HEAT@`. An
|
||||
unknown name is not an error.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `FREEZE-WORD` | `( c-addr u -- )` | Sets `WORD_FROZEN` on the word, so Loop #3 decay stops lowering its heat. |
|
||||
| `UNFREEZE-WORD` | `( c-addr u -- )` | Clears `WORD_FROZEN` and leaves `WORD_PINNED` alone. |
|
||||
| `FROZEN?` | `( c-addr u -- flag )` | True if the word is frozen. An unknown word gives `0`. |
|
||||
| `HEAT!` | `( heat c-addr u -- )` | Writes `execution_heat` directly, bypassing Loops #1 and #3. For testing only. |
|
||||
| `HEAT@` | `( c-addr u -- heat )` | Reads `execution_heat`. An unknown word gives `0`. |
|
||||
| `SHOW-HEAT` | `( c-addr u -- )` | Prints `NAME: HEAT (frozen) (pinned)`. |
|
||||
| `ALL-HEATS` | `( -- )` | Prints up to 1024 words sorted by heat, hottest first. |
|
||||
| `DECAY-RATE@` | `( -- q )` | Pushes the base decay rate per µs (`DECAY_RATE_PER_US_Q16`) in Q48.16. |
|
||||
| `FREEZE-CRITICAL` | `( -- )` | Freezes 21 core words: `DUP DROP SWAP OVER ROT @ ! C@ C! EXECUTE IF THEN ELSE DO LOOP BEGIN UNTIL REPEAT . EMIT CR`. |
|
||||
|
||||
## 24. Dictionary heat optimisation
|
||||
`src/word_source/dictionary_heat_diagnostic_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HEAT-PERCENTILES` | `( -- p25 p50 p75 )` | Pushes the current heat percentile thresholds, with the 75th on top. |
|
||||
| `LOOKUP-STRATEGY@` | `( -- n )` | Pushes the lookup strategy: 0 is naive (newest-first linear scan) and 1 is heat-aware (hot bucket first). |
|
||||
| `LOOKUP-STRATEGY!` | `( n -- )` | Sets the strategy. Only 0 or 1 is accepted; other values are silently ignored. |
|
||||
| `REORG-BUCKETS` | `( -- )` | Re-sorts the lookup buckets by heat and refreshes the percentiles immediately, without waiting for the heartbeat. |
|
||||
| `SHOW-HEAT-OPTIMIZATION` | `( -- )` | Prints the strategy, the percentiles, and the hot, warm, and cool zones. |
|
||||
| `COMPARE-LOOKUPS` | `( iterations -- )` | Benchmarks naive against heat-aware lookup and prints the speedup. It restores the original strategy afterwards. |
|
||||
|
||||
## 25. Logging
|
||||
`src/word_source/log_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `LOG-ERROR` `LOG-WARN` `LOG-INFO` `LOG-TEST` `LOG-DEBUG` | `( -- level )` | Push the log level constants. |
|
||||
| `LOG-LEVEL!` | `( level -- )` | Sets the active log filter, clamped to `[LOG-ERROR, LOG-DEBUG]`. |
|
||||
| `LOG-LEVEL@` | `( -- level )` | Pushes the current log level. |
|
||||
| `LOG-ERROR"` `LOG-WARN"` `LOG-INFO"` `LOG-TEST"` `LOG-DEBUG"` **IMM** | `( "ccc<">" -- )` | Log a literal string at that level. In interpret mode the string is logged immediately; when compiling, a runtime word and the inline string are compiled. |
|
||||
| `LOG-ERROR-STR` `LOG-WARN-STR` `LOG-INFO-STR` `LOG-TEST-STR` `LOG-DEBUG-STR` | `( c-addr u -- )` | Log a string taken from the stack at that level. |
|
||||
| `(do-log-error)` `(do-log-warn)` `(do-log-info)` `(do-log-test)` `(do-log-debug)` | `( -- )` | Runtimes for the compiled `LOG-*"` words. The compiler inserts them; you do not call them directly. |
|
||||
| `(LOG-APPEND-RAW)` **K** | `( level timestamp c-addr u -- )` | Appends a raw entry to the kernel log ring, attributed to the calling VM (or `HADES`). It reports errors on the console, not through `log_message`, to avoid recursion. |
|
||||
|
||||
Example: `: CHECK ( n -- ) 0< IF LOG-WARN" negative input" THEN ;`
|
||||
|
||||
## 26. Q48.16 fixed-point math
|
||||
`src/word_source/q48_words.c`. A value is `n × 65536`. The underlying type is **unsigned** `uint64_t`; see
|
||||
[§36](#36-implementation-quirks-to-know) for what that means for negative values.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `Q.+` `Q.-` | `( q1 q2 -- q3 )` | Add and subtract. |
|
||||
| `Q.*` | `( q1 q2 -- q3 )` | Multiplies, computing `(a*b) >> 16`. |
|
||||
| `Q./` | `( q1 q2 -- q3 )` | Divides, computing `(a << 16) / b`. **Division by zero returns 0** and sets no error. |
|
||||
| `Q.ABS` | `( q -- \|q\| )` | Absolute value, treating the top bit as a sign bit. |
|
||||
| `Q.NEG` | `( q -- -q )` | Two's-complement negation. |
|
||||
| `Q.LOG` | `( q -- ln q )` | Natural logarithm by Newton-Raphson. Requires `q > 0`. |
|
||||
| `Q.EXP` | `( q -- e^q )` | Exponential by Taylor series. |
|
||||
| `Q.SQRT` | `( q -- √q )` | Square root by Newton-Raphson. |
|
||||
| `Q.SIN` `Q.COS` | `( q -- q' )` | Sine and cosine of an angle in radians. The argument is reduced to [-π, π] and then a Taylor series is applied. |
|
||||
| `Q.FROM-INT` | `( n -- q )` | Converts an integer to Q48.16 as `n << 16`. **A negative `n` becomes 0.** |
|
||||
| `Q.TO-INT` | `( q -- n )` | Converts to an integer as `q >> 16`, truncating. |
|
||||
| `Q.1` | `( -- 65536 )` | Pushes 1.0. |
|
||||
| `Q.0` | `( -- 0 )` | Pushes 0.0. |
|
||||
| `Q.SCALE` | `( -- 65536 )` | Pushes the scale factor; the same value as `Q.1`. |
|
||||
| `Q.=` | `( q1 q2 -- flag )` | Equality. |
|
||||
| `Q.<` `Q.>` | `( q1 q2 -- flag )` | Comparison, done **unsigned**. |
|
||||
| `Q.0=` | `( q -- flag )` | True if the value is zero. |
|
||||
| `Q.MAX` `Q.MIN` | `( q1 q2 -- q3 )` | Maximum and minimum, compared **unsigned**. |
|
||||
| `Q.PRINT` | `( q -- )` | Prints the value as `int.fffff ` with five fractional digits. |
|
||||
|
||||
Example: `3 Q.FROM-INT Q.SQRT Q.PRINT` prints approximately `1.732`.
|
||||
|
||||
## 27. Inference engine (SSM, L8, and Bayes)
|
||||
`src/word_source/inference_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `INFER-RUN` | `( -- )` | Runs the full inference engine on this VM's rolling window and dictionary heat, and caches the results. |
|
||||
| `INFER-WINDOW@` | `( -- u )` | Pushes the last inferred optimal window width. |
|
||||
| `INFER-DECAY@` | `( -- q )` | Pushes the last inferred decay slope. |
|
||||
| `INFER-VARIANCE@` | `( -- q )` | Pushes the last inferred variance. |
|
||||
| `INFER-FIT@` | `( -- q )` | Pushes the last fit quality. |
|
||||
| `INFER-EARLY-EXIT@` | `( -- flag )` | True if the last run exited early. |
|
||||
| `Q.VARIANCE` | `( addr u -- q )` | Pushes the variance of `u` uint64 cells at `addr`. |
|
||||
| `INFER-DECAY-SLOPE` | `( addr u -- q )` | Fits a decay slope to the array by linear regression. |
|
||||
| `INFER-WINDOW-WIDTH` | `( addr u -- n )` | Computes the optimal window width for the array. |
|
||||
| `WINDOW-DIVERSITY` | `( -- u )` | Pushes the number of distinct words in the rolling window. |
|
||||
| `L8-MODE` | `( -- n )` | Pushes the current L8 (legacy 16-mode) Jacquard selection. |
|
||||
| `L8-UPDATE` | `( entropy cv temporal stability -- )` | Feeds four Q48.16 metrics to `ssm_l8_update()`. `stability` is on top of the stack. |
|
||||
| `L8-APPLY` | `( -- )` | Applies the currently selected L8 mode. |
|
||||
| `L8-TABLE-FORCE` | `( idx -- )` | Forces the adaptive 128-config table to `idx & 127` as though the UCB bandit had picked it, and applies it. Unlike `L8-UPDATE` and `L8-APPLY`, this choice is not overwritten at the next heartbeat trial. Use it for DoE campaigns. |
|
||||
| `BAYES-CACHE-MEAN` `BAYES-CACHE-LOWER` `BAYES-CACHE-UPPER` | `( -- q )` | Push the posterior mean latency and the 95 % credible bounds for hot-words cache hits. |
|
||||
| `BAYES-BUCKET-MEAN` `BAYES-BUCKET-LOWER` `BAYES-BUCKET-UPPER` | `( -- q )` | Push the same three values for bucket searches. |
|
||||
|
||||
## 28. DEFER and IS
|
||||
`src/word_source/defer_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `DEFER` | `( "name" -- )` | Creates a vectored word. Running it before an action has been set with `IS` sets `vm->error`. |
|
||||
| `IS` | `( xt "name" -- )` | Sets the action of `name`. It is refused unless `name` was created by `DEFER`. |
|
||||
| `DEFER@` | `( "name" -- xt )` | Pushes the current action of a deferred word. |
|
||||
|
||||
Example: `DEFER GREET : HI ." hi" ; ' HI IS GREET GREET`
|
||||
|
||||
## 29. Framebuffer (Hestia only)
|
||||
`src/word_source/framebuffer_words.c`. These words are registered only in the Hestia VM, by `capsule_birth_baby()`,
|
||||
and not by `register_forth79_words()`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `PLOT` | `( x y color -- )` | Writes one raw pixel. The origin is top-left and Y increases downward. |
|
||||
| `FB-WIDTH` | `( -- n )` | Pushes the framebuffer width in pixels. |
|
||||
| `FB-HEIGHT` | `( -- n )` | Pushes the framebuffer height in pixels. |
|
||||
|
||||
## 30. Keyboard
|
||||
`src/word_source/keyboard_words.c`. These are diagnostics for the console fabric. On a platform without the device,
|
||||
each word pushes `0`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `KBD-SCAN` | `( -- sc -1 \| 0 )` | amd64 i8042: pops one raw XT scancode from the queue, if there is one. |
|
||||
| `KBD-DEBUG` | `( -- isr spurious )` | amd64: pushes the i8042 interrupt count and the spurious-interrupt count. |
|
||||
| `VKBD-EVENT` | `( -- code value -1 \| 0 )` | riscv64 and aarch64 virtio-input: pops one Linux-style `EV_KEY` code and value. |
|
||||
| `VKBD-DEBUG` | `( -- isr )` | riscv64 and aarch64: pushes the virtio-input interrupt count. |
|
||||
| `KEY-EVENT` | `( -- keycode pressed -1 \| 0 )` | The unified event on every architecture: pops one keycode with its pressed (1) or released (0) state. |
|
||||
| `ALT+TAB` | `( -- )` | Switches the console between text and graphics, the same as the physical Alt+Tab. |
|
||||
|
||||
## 31. TrueType text
|
||||
`src/word_source/ttf_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `TTF-TEXT` **K** | `( c-addr u x y size color -- )` | Draws the string with the TrueType renderer at pixel `(x, y)` in the given size and color. |
|
||||
|
||||
## 32. REPL scrollback
|
||||
`src/word_source/scroll_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `SCROLL-BACK` **K** | `( n -- )` | Scrolls the REPL view back `n` lines. |
|
||||
| `SCROLL-FWD` **K** | `( n -- )` | Scrolls the REPL view forward `n` lines, toward the live output. |
|
||||
|
||||
## 33. Kernel REPL and DoE hooks
|
||||
`src/starkernel/repl.c` and `src/starkernel/doe_log.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HB-ON` **K** | `( -- )` | Turns on per-tick DoE instrumentation. |
|
||||
| `HB-OFF` **K** | `( -- )` | Turns off per-tick DoE instrumentation. |
|
||||
| `BLK-ATTACH-ACK` **K** | `( dev-ptr ok? -- )` | The acknowledgement Artemis sends to Hera after `BLK-ATTACH`, delivered with `VM-EXEC`. On success, Hera runs the deferred Zuse or WIREBIND attach. |
|
||||
| `KH-BLK-ATTACH-SEND` **K** | `( c-addr u -- ok? )` | Sends a payload to Hera through kernel-Hermes. The sender and receiver are worked out in C, so the caller cannot spoof them. A refused send is logged. |
|
||||
| `KH-ELEVATE-SEND` **K** | `( c-addr u -- ok? )` | The same mechanism for elevation requests. Nothing calls it at present. |
|
||||
|
||||
## 34. Hera (Mama) and child-VM words
|
||||
`src/starkernel/capsule/mama_forth_words.c`. These are **K** only. Hera receives every word in this section, in
|
||||
both `FORTH` and the `MAMA` vocabulary. Child VMs receive only `STOP EXEC USE BIRTH CAPSULE-BIRTH VM-EXEC VM-CALL
|
||||
VM-HEAT VM-ERROR? SWITCH-MARK-WORK` and the `STADIUM-*` words. VM names are matched without regard to case.
|
||||
|
||||
### VM lifecycle
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BIRTH` | `( c-addr u -- )` | Births a VM from its capsule (`S" Artemis"` loads `artemis:init.4th`). If the VM is already live, nothing happens. `Hera` is rejected. |
|
||||
| `KILL` | `( c-addr u -- )` | Destroys a VM. Hera cannot be killed, and killing a dead VM does nothing. |
|
||||
| `START` | `( c-addr u -- )` | Enters the VM's REPL and blocks until it runs `STOP` or `BYE`. It refuses a VM that is LIVE, DEAD, or STILLBORN. |
|
||||
| `STOP` | `( -- )` | Halts the current VM, so its REPL loop returns. |
|
||||
| `USE` | `( c-addr u -- )` | Redirects console input to the named VM without nesting the C stack, and changes the prompt to `[Name]`. `S" Hera" USE` switches back to Hera. |
|
||||
| `EXEC` | `( c-addr u -- )` | Runs a named capsule inside the current VM. |
|
||||
| `EJECT` | `( -- )` | Cleanly detaches the identity attached through USB home blocks: it flushes the user VM and kills it, or logs Zuse out. |
|
||||
| `CONNECT-HERMES` | `( -- )` | Enters Hermes's REPL, birthing Hermes first if needed. |
|
||||
| `CONNECT-ARTEMIS` | `( -- )` | Enters Artemis's REPL, birthing Artemis first if needed. |
|
||||
| `BYE` | `( -- )` | **On Hera:** reaps every child and then cold-resets the machine. |
|
||||
|
||||
### Cross-VM execution (compudynamics)
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `VM-EXEC` | `( cmd-a cmd-u name-a name-u -- )` | Injects a command into the named VM and runs it immediately without blocking. Example: `S" DOE-WORK" S" Hermes" VM-EXEC`. |
|
||||
| `VM-CALL` | `( cmd-a cmd-u name-a name-u -- n )` | Like `VM-EXEC`, then pops the target's top of stack onto the caller's stack. If the target left nothing, it pushes 0 and sets an error. |
|
||||
| `VM-STEP` | `( c-addr u -- )` | Gives the named VM one REPL turn: one prompt, one line, then it returns. |
|
||||
| `VM-HEAT` | `( c-addr u -- q )` | Pushes the VM's `execution_heat_q48`. An unknown VM gives 0 and prints nothing. |
|
||||
| `VM-ERROR?` | `( c-addr u -- flag )` | True if the VM has `vm->error` set. An unknown VM gives `0`. |
|
||||
| `VM-COUNT` | `( -- n )` | Pushes the number of registered VMs. |
|
||||
| `VM-CONSERVED?` | `( -- flag )` | True if the total fleet heat is within ε of `Q.1`. |
|
||||
| `VM-PHYSICS-STATUS` | `( -- )` | Prints the fleet physics report. |
|
||||
| `SWITCH-MARK-WORK` | `( c-addr u -- )` | Marks a VM as having work, which makes it eligible for a context switch. The message path calls it, and it ignores bad names silently. |
|
||||
| `MAMA-VM-ID` | `( -- 0 0 )` | Pushes Hera's 128-bit VM ID, which is all zeros. |
|
||||
| `NAME>XT` | `( c-addr u -- xt \| 0 )` | Looks up a name held in a data buffer. A miss gives `0`. |
|
||||
|
||||
### Capsules
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `CAPSULE-COUNT` | `( -- n )` | Pushes the number of entries in the capsule directory. |
|
||||
| `CAPSULE@` | `( idx -- desc \| 0 )` | Pushes the descriptor for the capsule at `idx`. |
|
||||
| `CAPSULE-HASH@` | `( desc -- hash )` | Pushes the capsule's content hash. |
|
||||
| `CAPSULE-FLAGS@` | `( desc -- flags )` | Pushes the capsule's flags. |
|
||||
| `CAPSULE-LEN@` | `( desc -- len )` | Pushes the capsule's payload length. |
|
||||
| `CAPSULE-BIRTH` | `( id -- vmid-lo vmid-hi )` | Births an unnamed VM from a production (p) capsule and pushes its 128-bit ID. On failure both cells are all ones. |
|
||||
| `CAPSULE-RUN` | `( id -- )` | Runs an experiment (e) capsule on Hera. |
|
||||
| `CAPSULE-TEST` | `( -- )` | Prints a message confirming the capsule system is running. |
|
||||
| `WORKER-BIRTH` | `( cap-a cap-u name-a name-u -- ok? )` | Births a named, `VM-EXEC`-addressable worker from any p-capsule, with no identity attached. |
|
||||
| `UNATTENDED-BIRTH` | `( cap-a cap-u name-a name-u -- ok? )` | Births a VM and installs the verified identity whose `UNATTENDED-ID-UUID` and `UNATTENDED-ID-CERT` the capsule defined. |
|
||||
| `CONSOLE-ATTACH` | `( name-a name-u -- ok? )` | Pairs a new console VM with the live VM registered as `<name>~user`. |
|
||||
|
||||
### Identity, Zuse, and diagnostics
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `MINT` | `( fn-a fn-u un-a un-u em-a em-u ph-a ph-u restrict? -- ok? )` | Mints an identity onto the attached USB drive. The full name and username are required; pass an empty string for email or phone to leave them out. A non-zero `restrict?` selects the locked-down personality that allows only FORTH-79 and FORTH-83 words. |
|
||||
| `MINT-SCRATCH` | same as `MINT` | Mints onto the scratch device instead, prints the UUID, and pushes 1 or 0. |
|
||||
| `MINT-SCRATCH-EMIT` | `( -- ok? )` | Prints the last scratch mint as FORTH source (`CREATE UNATTENDED-ID-UUID` / `-CERT` byte lists) for copying by hand. It refuses (pushes 0) if no mint has succeeded. |
|
||||
| `ZUSE-ELIGIBILITY-ADD` | `( c-addr -- ok? )` | Adds the 32-byte Ed25519 public key at `c-addr` to Zuse's elevation list. |
|
||||
| `ZUSE-ELIGIBLE?` | `( c-addr -- flag )` | Checks whether a key is on the list. It fails closed. |
|
||||
| `ELEVATE-PUBKEY-UNPACK` | `( pk0 pk1 pk2 pk3 buf -- )` | Rebuilds a 32-byte public key from four cells. It is the inverse of `ZUSE-PUBKEY@`. |
|
||||
| `RUNCAP-TEST` | `( c-addr u -- ok? rc )` | Diagnostic: runs `capsule_runcap_birth()` against the current home-blocks drive. |
|
||||
| `PAIR-TEST` | `( c-addr u -- ok? )` | Diagnostic: births a console VM and a `<name>~user` VM as a pair. |
|
||||
|
||||
### Stadium (heat accounting)
|
||||
Heat values are Q48.16. Each word works only on the calling VM's own quota.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `STADIUM-ADMIT` | `( identity heat behaviour -- cell \| -1 )` | Admits a patron. `behaviour` must be 0–3. |
|
||||
| `STADIUM-EVICT` | `( cell -- flag )` | Reaps the patron in `cell`. It is refused if the cell is out of range, not resident, pinned, or blocked by what it contains. |
|
||||
| `STADIUM-HEAT@` | `( cell -- heat )` | Reads a resident cell's heat. A cell that is not the caller's gives 0. |
|
||||
| `STADIUM-HEAT!` | `( heat cell -- )` | Writes a cell's heat, pulling the difference from the reservoir or pushing it back. An increase the reservoir cannot cover is silently refused. |
|
||||
| `STADIUM-RES@` | `( -- heat )` | Pushes the VM's reservoir balance. |
|
||||
| `STADIUM-RES-PULL` | `( qty -- got )` | Pulls up to `qty` from the reservoir and pushes the amount actually taken. |
|
||||
| `STADIUM-RES-PUSH` | `( heat -- )` | Credits heat back to the reservoir. |
|
||||
| `STADIUM-WORD-HEAT` | `( -- heat )` | Pushes the total heat held by this VM's word-execution residents. |
|
||||
|
||||
## 35. Hosted lifecycle stubs
|
||||
`src/word_source/lifecycle_words_hosted.c`. These are **H** only; `main.c` registers them. Each word only logs
|
||||
`"<WORD> <name> (hosted)"`. They exist so that capsule scripts also parse in hosted builds.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BIRTH` `KILL` `PAUSE` `RESUME` `USE` | `( c-addr u -- )` | No-op stubs that only write a log line. |
|
||||
|
||||
---
|
||||
|
||||
## 36. Implementation quirks to know
|
||||
|
||||
These behaviours differ from what a FORTH-79 or ANS programmer would expect. Each was checked against the C source.
|
||||
|
||||
1. **`ROLL` counts from the bottom of the stack.** With `1 2 3` on the stack, `1 ROLL` gives `2 3 1`; ANS gives
|
||||
`1 3 2`. The test suite (`stack_words_test.c`) asserts the current behaviour, so it looks intended. Portable code
|
||||
should use `SWAP` and `ROT`.
|
||||
2. **`PICK` is 0-based,** as in ANS. FORTH-79's `PICK` was 1-based.
|
||||
3. **`FIND` parses the input stream.** It does not take a counted string. Use `(FIND)` for a counted string or
|
||||
`NAME>XT` (kernel only) for a name in a buffer.
|
||||
4. **The Q48.16 type is unsigned.** `Q.<`, `Q.>`, `Q.MIN`, `Q.MAX` and `Q.PRINT` treat a negative Q value as a huge
|
||||
positive one, and `Q.FROM-INT` turns a negative integer into 0. `Q.ABS` and `Q.NEG` do treat the top bit as a sign.
|
||||
5. **`Q./` by zero returns 0 without setting an error,** while the integer `/`, `MOD`, and `*/` all set `vm->error`.
|
||||
6. **`[LITERAL]` does nothing,** and `LITERAL` works only because §17 registers it again after the placeholder.
|
||||
7. **`MOD`, `/MOD`, `*/`, and `*/MOD` are registered twice.** The mixed-arithmetic versions (§6) are the ones used.
|
||||
8. **Four `PHYSICS-*` diagnostic words are not registered.** `PHYSICS-WORD-METRICS`, `PHYSICS-CALC-KNOBS`,
|
||||
`PHYSICS-BURN` and `PHYSICS-SHOW-FEEDBACK` are defined in C but never added to the dictionary.
|
||||
9. **`does_rt` is a visible dictionary entry.** It is an internal helper; do not call it.
|
||||
10. **The `STARFORTH` vocabulary registers its words twice** (once in `FORTH`, once in `STARFORTH`). Hera does the
|
||||
same with `MAMA`. As a result, those names appear twice in `WORDS` output.
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,698 @@
|
||||
# StarForth v4.0.0 — Primitive Decomposition
|
||||
|
||||
This document assigns every C primitive in StarForth v3 (`admin/LithosAnanake` at `6302dcb`) a fate in
|
||||
StarForth v4.0.0. v4 is built on a 32-instruction core derived from Chuck Moore's F18 (the GA144 node).
|
||||
Everything that is not one of those 32 instructions becomes capsule code, a service message to another
|
||||
node, a memory-mapped register, or is retired.
|
||||
|
||||
The rationale is in `JUSTIFICATION.md`. This document is the specification.
|
||||
|
||||
**Status.** Every colon definition below is written against the ISA in §1 and has been traced by hand,
|
||||
but none has been executed. Each one becomes a POST test target: it is correct when the hosted v4 golden
|
||||
model produces the same results as the v3 C primitive it replaces.
|
||||
|
||||
---
|
||||
|
||||
## Contents
|
||||
|
||||
0. [Fates](#0-fates)
|
||||
1. [The v4 core ISA](#1-the-v4-core-isa)
|
||||
2. [Compiler conventions](#2-compiler-conventions)
|
||||
3. [Open decisions](#3-open-decisions)
|
||||
4. [Foundation layer (new words)](#4-foundation-layer-new-words)
|
||||
5. [Fate of every v3 primitive](#5-fate-of-every-v3-primitive)
|
||||
6. [Messaging between nodes](#6-messaging-between-nodes)
|
||||
7. [Memory-mapped registers](#7-memory-mapped-registers)
|
||||
|
||||
---
|
||||
|
||||
## 0. Fates
|
||||
|
||||
| Code | Fate | Meaning |
|
||||
| --- | --- | --- |
|
||||
| **OP** | Instruction | One of the 32 core opcodes. |
|
||||
| **IN** | Inline macro | A short opcode sequence the compiler places in-line. Never called. Required for anything that touches the return stack, since a call would bury the return address. |
|
||||
| **CAP** | Core capsule | A colon definition in the core capsule, built only from OP, IN, and earlier CAP words. |
|
||||
| **CC** | Compiler capsule | Part of the compiler/interpreter capsule, which runs on the host node only. Mesh nodes receive compiled code. |
|
||||
| **DEV** | Device service | A message to a device node that owns real hardware (console, storage, display, keyboard, log). |
|
||||
| **HERA** | Hera service | A message to the Hera node, which owns lifecycle, identity, capsules, ACLs, and Stadium admission. |
|
||||
| **MM** | Memory-mapped | An `@` or `!` against a hardware register (heat counters, anti-clock, governor, stack pointer). |
|
||||
| **RET** | Retired | A diagnostic of v3's software machine that has no equivalent in v4. |
|
||||
|
||||
---
|
||||
|
||||
## 1. The v4 core ISA
|
||||
|
||||
### 1.1 Machine model
|
||||
|
||||
| Item | v4 node |
|
||||
| --- | --- |
|
||||
| Cell | 32 bits (mesh node). The host node's width is a build parameter; see D-5. |
|
||||
| Addressing | Word-addressed (pending D-1). |
|
||||
| Registers | `T` (top of data stack), `S` (second), `R` (top of return stack), `P` (program counter), `A` and `B` (address registers). |
|
||||
| Stacks | Hardware stacks below `S` and `R`. Depth and visibility are D-2. |
|
||||
| Instruction word | Six 5-bit slots, plus 2 spare bits. |
|
||||
|
||||
### 1.2 Instruction word layout
|
||||
|
||||
```
|
||||
31 27 26 22 21 17 16 12 11 7 6 2 1 0
|
||||
+--------+--------+--------+--------+--------+--------+----+
|
||||
| slot 0 | slot 1 | slot 2 | slot 3 | slot 4 | slot 5 | xx |
|
||||
+--------+--------+--------+--------+--------+--------+----+
|
||||
```
|
||||
|
||||
Slots execute left to right. A branch (`jump`, `call`, `next`, `if`, `-if`) takes its target from all
|
||||
bits to the right of its slot, and that target replaces the same low bits of `P` (page-relative, as in
|
||||
the F18). Branches are therefore legal in slots 0–3 only:
|
||||
|
||||
| Branch in slot | Address bits | Reach |
|
||||
| --- | --- | --- |
|
||||
| 0 | 27 | whole address space |
|
||||
| 1 | 22 | 4M words |
|
||||
| 2 | 17 | 128K words |
|
||||
| 3 | 12 | 4K words (node-local) |
|
||||
|
||||
### 1.3 The 32 opcodes
|
||||
|
||||
Opcode numbering follows the F18. Two names differ from Moore's: F18 `-` is renamed `inv` and F18 `or`
|
||||
(which is exclusive-or) is renamed `xor`, so instruction names never collide with FORTH-79 word names.
|
||||
|
||||
| Op | Name | Effect |
|
||||
| --- | --- | --- |
|
||||
| 00 | `;` | Return: `P ← R`, pop `R`. |
|
||||
| 01 | `ex` | Swap `P` and `R` (co-routine / execute). |
|
||||
| 02 | `jump a` | `P ← a`. |
|
||||
| 03 | `call a` | Push `P` to `R`, `P ← a`. |
|
||||
| 04 | `unext` | If `R ≠ 0`: decrement `R`, restart the current instruction word at slot 0. Else pop `R`. |
|
||||
| 05 | `next a` | If `R ≠ 0`: decrement `R`, `P ← a`. Else pop `R`. |
|
||||
| 06 | `if a` | If `T = 0`: `P ← a`. **Does not pop `T`.** |
|
||||
| 07 | `-if a` | If `T ≥ 0` (sign bit clear): `P ← a`. **Does not pop `T`.** |
|
||||
| 08 | `@p` | Push the word at `P`, `P ← P+1` (literal). |
|
||||
| 09 | `@+` | Push the word at `A`, `A ← A+1`. |
|
||||
| 0A | `@b` | Push the word at `B`. |
|
||||
| 0B | `@` | Push the word at `A`. |
|
||||
| 0C | `!p` | Store `T` at `P`, pop, `P ← P+1`. |
|
||||
| 0D | `!+` | Store `T` at `A`, pop, `A ← A+1`. |
|
||||
| 0E | `!b` | Store `T` at `B`, pop. |
|
||||
| 0F | `!` | Store `T` at `A`, pop. |
|
||||
| 10 | `+*` | Multiply step: if bit 0 of `A` is set, `T ← T+S`; then shift `T:A` right one bit. See D-3. |
|
||||
| 11 | `2*` | `T ← T << 1`. |
|
||||
| 12 | `2/` | `T ← T >> 1`, arithmetic. |
|
||||
| 13 | `inv` | `T ← ~T`. |
|
||||
| 14 | `+` | `T ← S + T`, pop. |
|
||||
| 15 | `and` | `T ← S & T`, pop. |
|
||||
| 16 | `xor` | `T ← S ^ T`, pop. |
|
||||
| 17 | `drop` | Pop `T`. |
|
||||
| 18 | `dup` | Push a copy of `T`. |
|
||||
| 19 | `pop` | Pop `R` onto the data stack. |
|
||||
| 1A | `over` | Push a copy of `S`. |
|
||||
| 1B | `a` | Push `A`. |
|
||||
| 1C | `nop` | Nothing. |
|
||||
| 1D | `push` | Pop `T` onto the return stack. |
|
||||
| 1E | `b!` | `B ← T`, pop. |
|
||||
| 1F | `a!` | `A ← T`, pop. |
|
||||
|
||||
Note that `@` and `!` address through `A`, not through `T`. The FORTH words `@` and `!` therefore become
|
||||
`a! @` and `a! !`.
|
||||
|
||||
### 1.4 Side effects that are not instructions
|
||||
|
||||
Execution itself drives the physics. Every retired instruction increments that opcode's heat counter and
|
||||
advances the anti-clock; every `call` increments the heat counter of its target. None of this costs an
|
||||
instruction. Capsule code reads it through the memory-mapped registers in §7.
|
||||
|
||||
---
|
||||
|
||||
## 2. Compiler conventions
|
||||
|
||||
**Literals.** A number in source compiles to `@p` followed by the value in the next word.
|
||||
|
||||
**Capsule `IF`.** Native `if` and `-if` leave the flag on the stack. The capsule-level `IF` consumes it,
|
||||
so the compiler drops it on both paths:
|
||||
|
||||
```
|
||||
IF body THEN → if L1 drop body jump L2
|
||||
L1: drop
|
||||
L2:
|
||||
|
||||
IF body1 ELSE body2 THEN → if L1 drop body1 jump L2
|
||||
L1: drop body2
|
||||
L2:
|
||||
```
|
||||
|
||||
`BEGIN ... WHILE ... REPEAT` and `BEGIN ... UNTIL` expand the same way.
|
||||
|
||||
**`FOR ... NEXT`.** `n FOR ... NEXT` compiles `push` then the body then `next`. The body runs `n+1`
|
||||
times, as on the F18. `FOR ... UNEXT` is the same but the body must fit in one instruction word.
|
||||
|
||||
**Register conventions.** `A` and `B` are caller-saved. A word that uses them says so. Words in this
|
||||
document that clobber `A`: `@ ! +! -! 2@ 2! C@ C! UM* * UM/MOD SEND RECV`. Words that clobber `B`:
|
||||
`SEND RECV`.
|
||||
|
||||
**Return-stack words** (`>R R> R@ 2>R 2R> 2R@ I J UNLOOP` and the loop runtimes) are always IN.
|
||||
|
||||
---
|
||||
|
||||
## 3. Open decisions
|
||||
|
||||
These must be settled before the golden model is built. Where a definition below depends on one, it
|
||||
says so.
|
||||
|
||||
| ID | Decision | Default in this document |
|
||||
| --- | --- | --- |
|
||||
| **D-1** | Word addressing (pure Moore) or byte addressing. | Word addressing. `C@`/`C!` are CAP; `CELLS` is a no-op. |
|
||||
| **D-2** | Stack depth, and whether the stacks are visible (needed by `DEPTH`, `PICK`, `ROLL`, `SP@`, `SP!`). | Stacks backed by node RAM, with the data stack pointer exposed as MM register `DSP`. |
|
||||
| **D-3** | Exact `+*` semantics at 32 bits: whether the add carries out of `T` into the shift. | Carry is kept (extended multiply step), so `UM*` returns a full 64-bit product. |
|
||||
| **D-4** | Node memory map, including port and register addresses. | Symbolic names only (§6, §7). |
|
||||
| **D-5** | Host node cell width. | 32 on a Zynq-7000 (Cortex-A9); 64 on an aarch64 host. The compiler capsule is written width-independent. |
|
||||
| **D-6** | Which heat structures exist in hardware: per-opcode counters only, or also per-call-target and word-to-word transition counters. | Per-opcode and per-call-target. Transition counters deferred. |
|
||||
| **D-7** | `ROLL` semantics. | Fix to ANS (count from the top). v3's bottom-counting `ROLL` is retired. |
|
||||
| **D-8** | Q48.16 signedness. | Signed. v3's unsigned comparisons and `Q.FROM-INT` clamping are retired. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Foundation layer (new words)
|
||||
|
||||
These words do not exist as primitives in v3 but everything else is built on them. They are listed in
|
||||
dependency order.
|
||||
|
||||
```forth
|
||||
\ ---- helpers ------------------------------------------------------------
|
||||
: NIP ( a b -- b ) push drop pop ;
|
||||
: SWAP ( a b -- b a ) over push push drop pop pop ;
|
||||
: OR ( a b -- a|b ) over inv and xor ;
|
||||
: NEGATE ( n -- -n ) inv 1 + ;
|
||||
: ROT ( a b c -- b c a ) push SWAP pop SWAP ;
|
||||
|
||||
\ ---- sign and zero tests (raw branches, labels shown) ------------------
|
||||
: 0< ( n -- flag ) -if L1 drop -1 ; L1: drop 0 ;
|
||||
: 0= ( n -- flag ) if L1 drop 0 ; L1: drop -1 ;
|
||||
|
||||
\ ---- unsigned compare ---------------------------------------------------
|
||||
: U< ( u1 u2 -- flag ) 2DUP xor 0< IF NIP 0< ELSE - 0< THEN ;
|
||||
|
||||
\ ---- multiply (D-3) -----------------------------------------------------
|
||||
: UM* ( u1 u2 -- ulo uhi ) a! 0 31 FOR +* UNEXT push drop a pop ;
|
||||
|
||||
\ ---- divide: 32-step restoring division, divisor held in A --------------
|
||||
: UM/MOD ( ulo uhi ud -- urem uquot )
|
||||
a!
|
||||
31 FOR
|
||||
over 0< NEGATE push \ R: lo's top bit (1/0)
|
||||
dup 0< push \ R: hi's top bit (-1/0)
|
||||
2* pop pop SWAP push OR pop \ lo hi' t hi shifted, lo bit brought in
|
||||
push SWAP 2* SWAP pop \ lo' hi' t
|
||||
over a U< 0= OR \ lo' hi' flag t OR hi' >= d
|
||||
IF a - SWAP 1 OR SWAP THEN
|
||||
NEXT
|
||||
SWAP ;
|
||||
|
||||
\ ---- signed division, truncating toward zero (v3 semantics) -------------
|
||||
: SM/REM ( d n -- rem quot )
|
||||
2DUP xor push \ R: quotient sign
|
||||
over push \ R: remainder sign (sign of dividend)
|
||||
ABS push DABS pop UM/MOD
|
||||
pop 0< IF push NEGATE pop THEN
|
||||
pop 0< IF NEGATE THEN ;
|
||||
```
|
||||
|
||||
`2DUP`, `-`, `ABS`, and `DABS` are defined in §5; the compiler resolves forward references within the
|
||||
core capsule.
|
||||
|
||||
---
|
||||
|
||||
## 5. Fate of every v3 primitive
|
||||
|
||||
Section numbers match the v3 primitive reference.
|
||||
|
||||
### 5.1 Stack
|
||||
|
||||
| Word | Fate | v4 definition / notes |
|
||||
| --- | --- | --- |
|
||||
| `DROP` | OP | `drop` |
|
||||
| `DUP` | OP | `dup` |
|
||||
| `OVER` | OP | `over` |
|
||||
| `SWAP` | CAP | §4 |
|
||||
| `?DUP` | CAP | `dup IF dup THEN` |
|
||||
| `ROT` | CAP | §4 |
|
||||
| `-ROT` | CAP | `ROT ROT` |
|
||||
| `DEPTH` | MM | Read `DSP` (D-2). |
|
||||
| `PICK` | MM + CAP | Read stack RAM at `DSP − n` (D-2). 0-based, as in v3. |
|
||||
| `ROLL` | CAP | Rewritten with ANS semantics (D-7), using `PICK` and a copy loop. |
|
||||
|
||||
### 5.2 Return stack
|
||||
|
||||
| Word | Fate | v4 definition |
|
||||
| --- | --- | --- |
|
||||
| `>R` | IN | `push` |
|
||||
| `R>` | IN | `pop` |
|
||||
| `R@` | IN | `pop dup push` |
|
||||
|
||||
### 5.3 Memory
|
||||
|
||||
| Word | Fate | v4 definition / notes |
|
||||
| --- | --- | --- |
|
||||
| `@` | IN | `a! @` |
|
||||
| `!` | IN | `a! !` |
|
||||
| `+!` | CAP | `a! @ + !` |
|
||||
| `-!` | CAP | `a! NEGATE @ + !` |
|
||||
| `2@` | CAP | `a! @+ @` (low cell at `addr`, high at `addr+1`, as in v3) |
|
||||
| `2!` | CAP | `a! SWAP !+ !` |
|
||||
| `C@` | CAP | See below (D-1). |
|
||||
| `C!` | CAP | See below (D-1). |
|
||||
| `FILL` | CAP | See below. |
|
||||
| `MOVE` | CAP | `push 2DUP U< IF pop CMOVE> ELSE pop CMOVE THEN` |
|
||||
| `ERASE` | CAP | `0 FILL` |
|
||||
| `CELLS` | IN | Empty (word-addressed). Becomes `2* 2*` if D-1 chooses bytes. |
|
||||
|
||||
```forth
|
||||
\ byte access on a word-addressed node, little-endian
|
||||
: C@ ( baddr -- c )
|
||||
dup 3 and 3 LSHIFT SWAP 2 RSHIFT a! @ SWAP RSHIFT 255 and ;
|
||||
|
||||
: C! ( c baddr -- )
|
||||
dup 2 RSHIFT a! \ A = word address
|
||||
3 and 3 LSHIFT \ c bits
|
||||
SWAP 255 and over LSHIFT \ bits c'
|
||||
SWAP 255 SWAP LSHIFT inv \ c' ~mask
|
||||
@ and OR ! ;
|
||||
|
||||
: FILL ( baddr u c -- )
|
||||
SWAP BEGIN dup WHILE 1- push 2DUP SWAP C! SWAP 1+ SWAP pop REPEAT 2DROP drop ;
|
||||
```
|
||||
|
||||
### 5.4 Arithmetic
|
||||
|
||||
| Word | Fate | v4 definition / notes |
|
||||
| --- | --- | --- |
|
||||
| `+` | OP | `+` |
|
||||
| `-` | CAP | `NEGATE +` |
|
||||
| `*` | CAP | `UM* drop` |
|
||||
| `/` | CAP | `/MOD NIP` |
|
||||
| `MOD` `/MOD` `*/` `*/MOD` (§4 versions) | RET | Shadowed duplicates. Only the §6 versions survive. |
|
||||
| `1+` `1-` `2+` `2-` | IN | `1 +`, `-1 +`, `2 +`, `-2 +` |
|
||||
| `2*` | OP | `2*` |
|
||||
| `2/` | OP | `2/` |
|
||||
| `ABS` | CAP | `dup 0< IF NEGATE THEN` |
|
||||
| `NEGATE` | CAP | §4 |
|
||||
| `MIN` | CAP | `2DUP > IF SWAP THEN drop` |
|
||||
| `MAX` | CAP | `2DUP < IF SWAP THEN drop` |
|
||||
|
||||
### 5.5 Logic and comparison
|
||||
|
||||
| Word | Fate | v4 definition / notes |
|
||||
| --- | --- | --- |
|
||||
| `AND` | OP | `and` |
|
||||
| `XOR` | OP | `xor` |
|
||||
| `OR` | CAP | §4 |
|
||||
| `INVERT` | OP | `inv` |
|
||||
| `NOT` | CAP | `0=` (FORTH-79 logical not, as in v3) |
|
||||
| `LSHIFT` | CAP | `BEGIN dup WHILE 1- SWAP 2* SWAP REPEAT drop` |
|
||||
| `RSHIFT` | CAP | `BEGIN dup WHILE 1- SWAP 2/ MSB inv and SWAP REPEAT drop` (clears the sign bit each step; `MSB` is the cell-width top-bit constant) |
|
||||
| `0=` `0<` | CAP | §4 |
|
||||
| `0<>` | CAP | `0= 0=` |
|
||||
| `0>` | CAP | `dup 0< SWAP 0= OR 0=` (correct for the most negative number) |
|
||||
| `=` | CAP | `xor 0=` |
|
||||
| `<>` | CAP | `xor 0<>` |
|
||||
| `<` | CAP | `2DUP xor 0< IF drop 0< ELSE - 0< THEN` (overflow-safe) |
|
||||
| `>` | CAP | `SWAP <` |
|
||||
| `<=` | CAP | `> 0=` |
|
||||
| `>=` | CAP | `< 0=` |
|
||||
| `U<` | CAP | §4 |
|
||||
| `U>` | CAP | `SWAP U<` |
|
||||
| `WITHIN` | CAP | `over - push - pop U<` |
|
||||
| `TRUE` | IN | `-1` |
|
||||
| `FALSE` | IN | `0` |
|
||||
|
||||
### 5.6 Mixed-precision arithmetic
|
||||
|
||||
A double is two 32-bit cells on a mesh node.
|
||||
|
||||
| Word | Fate | v4 definition |
|
||||
| --- | --- | --- |
|
||||
| `M+` | CAP | `S>D D+` |
|
||||
| `M-` | CAP | `NEGATE M+` |
|
||||
| `M*` | CAP | `2DUP xor push ABS SWAP ABS UM* pop 0< IF DNEGATE THEN` |
|
||||
| `M/MOD` | CAP | `SM/REM` |
|
||||
| `MOD` | CAP | `/MOD drop` |
|
||||
| `/MOD` | CAP | `push S>D pop SM/REM` |
|
||||
| `*/` | CAP | `*/MOD NIP` |
|
||||
| `*/MOD` | CAP | `push M* pop SM/REM` |
|
||||
|
||||
### 5.7 Double-cell numbers
|
||||
|
||||
| Word | Fate | v4 definition |
|
||||
| --- | --- | --- |
|
||||
| `S>D` | CAP | `dup 0<` |
|
||||
| `D+` | CAP | `push SWAP push over + 2DUP U> ROT drop NEGATE pop pop + +` |
|
||||
| `DNEGATE` | CAP | `inv SWAP inv SWAP 1 0 D+` |
|
||||
| `D-` | CAP | `DNEGATE D+` |
|
||||
| `DABS` | CAP | `dup 0< IF DNEGATE THEN` |
|
||||
| `D0=` | CAP | `OR 0=` |
|
||||
| `D0<` | CAP | `NIP 0<` |
|
||||
| `D=` | CAP | `D- D0=` |
|
||||
| `D<` | CAP | `ROT 2DUP = IF 2DROP U< ELSE SWAP < NIP NIP THEN` |
|
||||
| `DMAX` | CAP | `2OVER 2OVER D< IF 2SWAP THEN 2DROP` |
|
||||
| `DMIN` | CAP | `2OVER 2OVER D< 0= IF 2SWAP THEN 2DROP` |
|
||||
| `D2*` | CAP | `2* over 0< NEGATE OR SWAP 2* SWAP` |
|
||||
| `D2/` | CAP | `dup 1 and push 2/ SWAP 1 RSHIFT pop IF MSB OR THEN SWAP` |
|
||||
| `2DROP` | IN | `drop drop` |
|
||||
| `2DUP` | IN | `over over` |
|
||||
| `2SWAP` | CAP | `ROT push ROT pop` |
|
||||
| `2OVER` | CAP | `push push 2DUP pop pop 2SWAP` |
|
||||
| `2ROT` | CAP | `2>R 2SWAP 2R> 2SWAP` |
|
||||
| `2>R` | IN | `SWAP push push` |
|
||||
| `2R>` | IN | `pop pop SWAP` |
|
||||
| `2R@` | IN | `pop pop 2DUP push push SWAP` |
|
||||
|
||||
### 5.8 Number formatting and output
|
||||
|
||||
All output reaches the console through `EMIT` (DEV).
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `<#` `#` `#S` `HOLD` `SIGN` `#>` | CAP | Standard pictured-output definitions over `UM/MOD` and a hold buffer. v3's tolerant `#>` (pops `ud` only if present) is not kept; v4 follows the standard stack effect. |
|
||||
| `.` `.R` `U.` `U.R` `D.` `D.R` | CAP | Built on pictured output and `TYPE`. |
|
||||
| `.S` | CAP | Walks the stack via `DSP` (D-2). |
|
||||
| `?` | CAP | `@ .` |
|
||||
| `DUMP` | CAP | Loop over `@`/`C@` with pictured output. |
|
||||
| `BASE` | CAP | Variable. |
|
||||
| `DECIMAL` `HEX` `OCTAL` | CAP | `10 BASE !` and so on. |
|
||||
|
||||
### 5.9 Strings, parsing, and input
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `COUNT` | CAP | `dup 1+ SWAP C@` |
|
||||
| `CMOVE` | CAP | See below. |
|
||||
| `CMOVE>` | CAP | See below. |
|
||||
| `BLANK` | CAP | `32 FILL` |
|
||||
| `-TRAILING` | CAP | Loop from the end while the character is a space. |
|
||||
| `COMPARE` | CAP | Byte loop returning `-1`, `0`, or `1`. v3's counted-string auto-detection is not kept. |
|
||||
| `SEARCH` | CAP | Nested loop over `COMPARE`. Same note. |
|
||||
| `SCAN` `SKIP` | CAP | Byte loops. |
|
||||
| `BL` | IN | `32` |
|
||||
| `EXPECT` `QUERY` | CC | Built on `KEY` (DEV). |
|
||||
| `SPAN` `TIB` `>IN` `SOURCE` | CC | Interpreter state on the host node. |
|
||||
| `WORD` `ENCLOSE` | CC | Parser. |
|
||||
| `NUMBER` `CONVERT` | CC | Rewritten to honour `BASE` (v3's `NUMBER` is base 10 only). |
|
||||
| `S"` `(s")` `[']` | CC | Compiler words. |
|
||||
| `LITERAL` `[LITERAL]` (placeholders) | RET | The working `LITERAL` is in §5.17. |
|
||||
|
||||
```forth
|
||||
: CMOVE ( src dst u -- )
|
||||
BEGIN dup WHILE 1- push over C@ over C! 1+ SWAP 1+ SWAP pop REPEAT drop 2DROP ;
|
||||
|
||||
: CMOVE> ( src dst u -- )
|
||||
BEGIN dup WHILE 1- push over R@ + C@ over R@ + C! pop REPEAT drop 2DROP ;
|
||||
```
|
||||
|
||||
### 5.10 Terminal I/O
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `EMIT` | DEV | Console service: one-character message. |
|
||||
| `KEY` | DEV | Console service: blocking receive. |
|
||||
| `?TERMINAL` | DEV | Console service: non-blocking status. |
|
||||
| `TYPE` | CAP | Loop of `C@ EMIT`, or one string message to the console node. |
|
||||
| `CR` | CAP | `10 EMIT` |
|
||||
| `SPACE` | CAP | `BL EMIT` |
|
||||
| `SPACES` | CAP | `BEGIN dup 0> WHILE SPACE 1- REPEAT drop` |
|
||||
| `."` `(do-string)` | CC | Compiler words. |
|
||||
|
||||
### 5.11 Blocks and mass storage
|
||||
|
||||
The storage service belongs to the Artemis role, now a device node.
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `BLOCK` `BUFFER` `UPDATE` `SAVE-BUFFERS` `EMPTY-BUFFERS` `FLUSH` | DEV | Block-service messages. Buffers live in the requesting node's RAM or in DDR. |
|
||||
| `LOAD` `THRU` `-->` | CC | The interpreter reads blocks through the service. |
|
||||
| `LIST` | CAP | `BLOCK` plus `TYPE`. |
|
||||
| `SCR` | CAP | Variable. |
|
||||
| `BLK-CONFIRM-FORMAT` `RELOCATE-BLOCK` | DEV | Owner-only storage messages. |
|
||||
| `BLK-ACL-ALLOW@` `BLK-ACL-ALLOW!` `BLK-ACL-TTL@` `BLK-ACL-TTL!` | HERA | ACL state is held by Hera. |
|
||||
| `BLK-OWNER@` | HERA | Read-only, as in v3. |
|
||||
| `BLK-ATTACH` | RET | Took a raw host pointer. Replaced by an attach message from the device node. |
|
||||
|
||||
### 5.12 Dictionary space
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `HERE` `ALIGN` `ALLOT` `,` `C,` `2,` `PAD` `LATEST` | CC | The dictionary lives on the host node. |
|
||||
| `SP@` `SP!` | MM | `DSP` register (D-2). |
|
||||
|
||||
### 5.13 Dictionary manipulation
|
||||
|
||||
| Word | Fate |
|
||||
| --- | --- |
|
||||
| `'` `FIND` `SMUDGE` `HIDDEN` `>BODY` `>NAME` `NAME>` `>LINK` `LINK>` `CFA` `LFA` `NFA` `PFA` `TRAVERSE` `INTERPRET` | CC |
|
||||
|
||||
### 5.14 Vocabularies
|
||||
|
||||
| Word | Fate |
|
||||
| --- | --- |
|
||||
| `VOCABULARY` `DEFINITIONS` `CONTEXT` `CURRENT` `FORTH` `ORDER` `(FIND)` | CC |
|
||||
|
||||
### 5.15 System
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `(` `\` | CC | |
|
||||
| `EXECUTE` | CAP | `push ;` (tail-jumps to the xt; the xt returns to `EXECUTE`'s caller) |
|
||||
| `NOP` | OP | `nop` |
|
||||
| `QUIT` `ABORT` `ABORT"` `(ABORT")` `COLD` `WARM` | CC | |
|
||||
| `BYE` `REBOOT` | HERA | |
|
||||
| `SAVE-SYSTEM` | HERA | Snapshot becomes a capsule-image request. |
|
||||
| `WORDS` `VLIST` `SEE` | CC | |
|
||||
| `PAGE` | DEV | |
|
||||
| `79-STANDARD` | CC | |
|
||||
|
||||
### 5.16 Line editor
|
||||
|
||||
| Word | Fate |
|
||||
| --- | --- |
|
||||
| `L` `S` `SHOW` `EDIT` | CC |
|
||||
|
||||
### 5.17 Defining words and the compiler
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `:` `;` `CREATE` `VARIABLE` `CONSTANT` `DOES>` `IMMEDIATE` `STATE` `[` `]` `LITERAL` `COMPILE` `[COMPILE]` `FORGET` `FENCE` | CC | |
|
||||
| `LIT` | OP | `@p` |
|
||||
| `does_rt` | RET | Internal helper; `DOES>` is implemented by the compiler capsule. |
|
||||
|
||||
### 5.18 Control flow
|
||||
|
||||
| Word | Fate | v4 definition / notes |
|
||||
| --- | --- | --- |
|
||||
| `IF` `ELSE` `THEN` `BEGIN` `UNTIL` `AGAIN` `WHILE` `REPEAT` `DO` `?DO` `LOOP` `+LOOP` `LEAVE` `CASE` `OF` `ENDOF` `ENDCASE` | CC | Compile-time structure words. Expansions per §2 and below. |
|
||||
| `EXIT` | OP | `;` |
|
||||
| `(BRANCH)` | OP | `jump` |
|
||||
| `(0BRANCH)` | IN | `if L … drop` (§2) |
|
||||
| `(DO)` | IN | `SWAP push push` (R: limit index) |
|
||||
| `(?DO)` | IN | `2DUP = IF 2DROP jump past-loop THEN SWAP push push` |
|
||||
| `(LOOP)` | IN | See below. |
|
||||
| `(+LOOP)` | IN | Sign-aware boundary-crossing test; specified in the compiler capsule. |
|
||||
| `(LEAVE)` | IN | `pop drop pop dup push push jump loop-test` (sets index to limit) |
|
||||
| `I` | IN | `pop dup push` |
|
||||
| `J` | IN | `pop pop pop dup push SWAP push SWAP push` |
|
||||
| `UNLOOP` | IN | `pop pop drop drop` |
|
||||
|
||||
```
|
||||
(LOOP) expansion:
|
||||
pop 1 + pop \ index' limit
|
||||
2DUP xor \ index' limit flag (0 when equal)
|
||||
if Lexit
|
||||
drop push push \ R: limit index'
|
||||
jump Lbody
|
||||
Lexit: drop drop drop
|
||||
```
|
||||
|
||||
`(LOOP)` terminates when the index reaches the limit, which matches v3 for every loop where
|
||||
`start < limit`.
|
||||
|
||||
**New in v4:** `FOR`, `NEXT`, and `UNEXT` are native (§2). Counted loops that don't need an ascending
|
||||
index should use them; they cost one instruction per iteration.
|
||||
|
||||
### 5.19 StarForth extensions
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `ENTROPY@` `ENTROPY!` | MM | Per-call-target heat table (D-6). |
|
||||
| `WORD-ENTROPY` `RESET-ENTROPY` `TOP-WORDS` | CC | Reports over the heat registers. |
|
||||
| `(-` `INIT` | CC | |
|
||||
| `VERSION` | CC | |
|
||||
| `SEED` `RANDOM` | CAP | Deterministic PRNG (xorshift) in capsule code, reproducible from the seed. |
|
||||
| `WAIT` | CAP | Loop until the `ANTICLOCK` register has advanced `n`. |
|
||||
| `HEARTBEAT-TICKS@` | MM | `HEARTBEAT` register. |
|
||||
| `ZUSE-AUTHENTICATE` `ZUSE-SESSION?` `ZUSE-PUBKEY@` `ZUSE-CERT-INSTALLED?` | HERA | |
|
||||
|
||||
### 5.20 Word-level ACL
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `ACL-MODE@` `ACL-MODE!` `ACL-TTL@` `ACL-TTL!` `ACL-ALLOW@` `ACL-ALLOW!` `ACL-PINNED?` `ACL-PIN` `ACL-INHERIT` `ACL-INIT-PRIMITIVES` | HERA | Hera holds the ACL table. In the fabric, per-message ACL checks happen in the router (§6). |
|
||||
| `ACL-HEAT@` | MM | |
|
||||
| `ACL-WORD-ID` | CC | |
|
||||
|
||||
### 5.21 Physics: benchmark and diagnostics
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `BENCH-DICT-LOOKUP` `PHYSICS-CACHE-STATS` `PHYSICS-TOGGLE-CACHE` `PHYSICS-RESET-STATS` `PHYSICS-BUILD-INFO` | RET | Measure v3's software dictionary and hot-words cache, which do not exist on a node. |
|
||||
| `PHYSICS-BAYESIAN-REPORT` | CAP | Host node only; kept as an analysis tool. |
|
||||
| `PHYSICS-WORD-METRICS` `PHYSICS-CALC-KNOBS` `PHYSICS-BURN` `PHYSICS-SHOW-FEEDBACK` | RET | Never registered in v3. |
|
||||
|
||||
### 5.22 Physics: pipelining diagnostics
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `PIPELINING-*` (all six) | RET | Return as MM reports if D-6 adds transition counters. |
|
||||
|
||||
### 5.23 Physics: freeze, heat, and decay
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `FREEZE-WORD` `UNFREEZE-WORD` `FROZEN?` | MM | Freeze bit in the heat table. |
|
||||
| `HEAT@` `HEAT!` | MM | Test-only write retained. |
|
||||
| `SHOW-HEAT` `ALL-HEATS` | CC | |
|
||||
| `DECAY-RATE@` | MM | Governor parameter register. |
|
||||
| `FREEZE-CRITICAL` | CAP | Freezes the core set; the list is rewritten for v4 names. |
|
||||
|
||||
### 5.24 Dictionary heat optimisation
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `HEAT-PERCENTILES` `LOOKUP-STRATEGY@` `LOOKUP-STRATEGY!` `REORG-BUCKETS` `SHOW-HEAT-OPTIMIZATION` `COMPARE-LOOKUPS` | RET | Lookup strategy is a software-dictionary concern. The host compiler may keep a heat-ordered dictionary internally, but these words are not carried forward. |
|
||||
|
||||
### 5.25 Logging
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `LOG-ERROR` … `LOG-DEBUG` (levels) | IN | Constants. |
|
||||
| `LOG-LEVEL!` `LOG-LEVEL@` | CAP | Variable. |
|
||||
| `LOG-ERROR"` … `LOG-DEBUG"` | CC | |
|
||||
| `LOG-*-STR` | DEV | Log-ring service on the recorder (the ARM). |
|
||||
| `(do-log-*)` | CC | |
|
||||
| `(LOG-APPEND-RAW)` | DEV | |
|
||||
|
||||
### 5.26 Q48.16 fixed-point math
|
||||
|
||||
A Q48.16 value is 64 bits, so on a 32-bit node it occupies **two cells** and every Q word is a double
|
||||
word. Per D-8, v4 Q values are signed.
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `Q.+` `Q.-` | CAP | `D+`, `D-` |
|
||||
| `Q.*` | CAP | 64×64 product from four `UM*` partial products, shifted right 16. |
|
||||
| `Q./` | CAP | Shifted long division. **Division by zero sets an error** (v3 returned 0 silently). |
|
||||
| `Q.ABS` `Q.NEG` | CAP | `DABS`, `DNEGATE` |
|
||||
| `Q.LOG` `Q.EXP` `Q.SQRT` `Q.SIN` `Q.COS` | CAP | Algorithms ported from `q48_words.c`; the hosted C versions are the golden model. |
|
||||
| `Q.FROM-INT` | CAP | `S>D` shifted left 16. Negative values are no longer clamped to 0. |
|
||||
| `Q.TO-INT` | CAP | Shift right 16, take the low cell. |
|
||||
| `Q.1` `Q.0` `Q.SCALE` | IN | Double-cell constants. |
|
||||
| `Q.=` `Q.<` `Q.>` `Q.0=` `Q.MAX` `Q.MIN` | CAP | `D=`, `D<`, `SWAP D<` (for `Q.>`), `D0=`, `DMAX`, `DMIN`. Signed. |
|
||||
| `Q.PRINT` | CAP | Pictured output, five fractional digits. |
|
||||
|
||||
### 5.27 Inference engine
|
||||
|
||||
The runtime governor moves into hardware as the multi-level Rolling Window of Truth (see
|
||||
`JUSTIFICATION.md`). These words survive on the host node as analysis tools.
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `INFER-RUN` `INFER-WINDOW@` `INFER-DECAY@` `INFER-VARIANCE@` `INFER-FIT@` `INFER-EARLY-EXIT@` | CAP | Host node only. Ported from `inference_words.c`. |
|
||||
| `Q.VARIANCE` `INFER-DECAY-SLOPE` `INFER-WINDOW-WIDTH` `WINDOW-DIVERSITY` | CAP | Host node only. |
|
||||
| `L8-MODE` `L8-UPDATE` `L8-APPLY` `L8-TABLE-FORCE` | MM | Jacquard selector state becomes governor registers. `L8-TABLE-FORCE` remains the DoE override. |
|
||||
| `BAYES-*` (all six) | RET | Model the v3 hot-words cache and bucket search. |
|
||||
|
||||
### 5.28 DEFER and IS
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `DEFER` `IS` `DEFER@` | CC | A deferred word's runtime is `@p push ;` followed by the stored xt. |
|
||||
|
||||
### 5.29 – 5.32 Framebuffer, keyboard, TrueType, scrollback
|
||||
|
||||
| Word | Fate |
|
||||
| --- | --- |
|
||||
| `PLOT` `FB-WIDTH` `FB-HEIGHT` | DEV |
|
||||
| `KBD-SCAN` `KBD-DEBUG` `VKBD-EVENT` `VKBD-DEBUG` `KEY-EVENT` `ALT+TAB` | DEV |
|
||||
| `TTF-TEXT` | DEV |
|
||||
| `SCROLL-BACK` `SCROLL-FWD` | DEV |
|
||||
|
||||
### 5.33 Kernel REPL and DoE hooks
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `HB-ON` `HB-OFF` | MM | Recorder-enable register. The fabric pushes DoE rows into a FIFO; the ARM drains it to storage. |
|
||||
| `BLK-ATTACH-ACK` `KH-BLK-ATTACH-SEND` `KH-ELEVATE-SEND` | RET | Kernel-Hermes calls. Hermes is now the fabric; these become ordinary packets (§6). |
|
||||
|
||||
### 5.34 Hera and child-VM words
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `BIRTH` `KILL` `START` `STOP` `USE` `EXEC` `EJECT` `CONNECT-HERMES` `CONNECT-ARTEMIS` `BYE` | HERA | A VM becomes a node (or a group of nodes). `BIRTH` loads a capsule into a node and releases it. |
|
||||
| `VM-EXEC` `VM-CALL` `VM-STEP` | CAP | Built on `SEND` and `RECV` (§6). |
|
||||
| `VM-HEAT` `VM-ERROR?` `VM-COUNT` `VM-CONSERVED?` `VM-PHYSICS-STATUS` | MM + HERA | Per-node heat is a register; fleet totals are Hera's. |
|
||||
| `SWITCH-MARK-WORK` | RET | Nodes run concurrently; there is no context switch to mark. |
|
||||
| `MAMA-VM-ID` `NAME>XT` | HERA, CC | |
|
||||
| `CAPSULE-*` `WORKER-BIRTH` `UNATTENDED-BIRTH` `CONSOLE-ATTACH` | HERA | |
|
||||
| `MINT` `MINT-SCRATCH` `MINT-SCRATCH-EMIT` `ZUSE-ELIGIBILITY-ADD` `ZUSE-ELIGIBLE?` `ELEVATE-PUBKEY-UNPACK` | HERA | |
|
||||
| `RUNCAP-TEST` `PAIR-TEST` | HERA | Diagnostics, kept. |
|
||||
| `STADIUM-ADMIT` `STADIUM-EVICT` `STADIUM-RES-PULL` `STADIUM-RES-PUSH` | HERA | Admission and reservoir are Hera's. |
|
||||
| `STADIUM-HEAT@` `STADIUM-HEAT!` `STADIUM-RES@` `STADIUM-WORD-HEAT` | MM | |
|
||||
|
||||
### 5.35 Hosted lifecycle stubs
|
||||
|
||||
| Word | Fate |
|
||||
| --- | --- |
|
||||
| `BIRTH` `KILL` `PAUSE` `RESUME` `USE` (hosted) | RET — the hosted v4 golden model implements the real HERA messages. |
|
||||
|
||||
---
|
||||
|
||||
## 6. Messaging between nodes
|
||||
|
||||
Each node has four neighbour ports (`PORT-UP`, `PORT-DOWN`, `PORT-LEFT`, `PORT-RIGHT`) mapped into its
|
||||
address space. A read from a port blocks until the neighbour writes; a write blocks until the neighbour
|
||||
reads. This is the GA144 model. No instruction is added: a port is an address.
|
||||
|
||||
### 6.1 Packet format (proposal)
|
||||
|
||||
| Word | Contents |
|
||||
| --- | --- |
|
||||
| 0 | Header: destination node (8 bits), type (8), TTL/heat (8), payload length in words (8). |
|
||||
| 1 | ACL tag: sender identity fingerprint, checked by the router on every packet. |
|
||||
| 2 … | Payload. |
|
||||
|
||||
The router in each node forwards packets not addressed to it, decrements TTL, and drops a packet whose
|
||||
TTL reaches zero or whose ACL tag fails. This is v3 Hermes's per-message ACL check and unconditional TTL
|
||||
expiry, moved into logic. A packet type `SOS` is reserved for any node to emit.
|
||||
|
||||
### 6.2 Send and receive
|
||||
|
||||
```forth
|
||||
: SEND ( addr u port -- ) b! SWAP a! BEGIN dup WHILE 1- @+ !b REPEAT drop ;
|
||||
: RECV ( addr u port -- ) b! SWAP a! BEGIN dup WHILE 1- @b !+ REPEAT drop ;
|
||||
```
|
||||
|
||||
`A` walks the buffer and `B` holds the port, so each word moved costs one fetch and one store.
|
||||
|
||||
---
|
||||
|
||||
## 7. Memory-mapped registers
|
||||
|
||||
Addresses are assigned in the node memory map (D-4). Names only here.
|
||||
|
||||
| Register | Access | Contents |
|
||||
| --- | --- | --- |
|
||||
| `DSP` | R/W | Data stack pointer (D-2). |
|
||||
| `HEAT-OP[0..31]` | R | Per-opcode retirement heat. |
|
||||
| `HEAT-CALL[...]` | R/W | Per-call-target heat, with freeze bit (D-6). |
|
||||
| `ANTICLOCK` | R | Virtual tick: a pure function of the execution stream. |
|
||||
| `HEARTBEAT` | R | Adaptive heartbeat count. |
|
||||
| `GOV-*` | R/W | Governor parameters and Jacquard selector state (`L8-*`, decay rate). |
|
||||
| `REC-ENABLE` | R/W | DoE recorder on/off (`HB-ON` / `HB-OFF`). |
|
||||
| `PORT-STATUS` | R | Per-port ready flags, for non-blocking polls. |
|
||||
@@ -0,0 +1,226 @@
|
||||
# StarForth v4.0.0 — Justification
|
||||
|
||||
This document records why StarForth v4.0.0 exists, what it changes, and why each major decision was
|
||||
made. The specification is `DECOMPOSITION.md`. Per project practice, this document is written before
|
||||
any v4 code.
|
||||
|
||||
---
|
||||
|
||||
## 1. The problem with v3
|
||||
|
||||
StarForth v3 is a successful software machine. It boots on amd64, aarch64, and riscv64, runs the
|
||||
Tripod fleet on LithosAnanke, and has held K≡1.0 across 38,400+ experimental runs. But it was designed
|
||||
for a large host, and it shows:
|
||||
|
||||
- **More than 300 C primitives.** Most are not primitive in any hardware sense. Double-cell arithmetic,
|
||||
string handling, comparisons, pictured output, and Q48.16 transcendentals are all expressible in a
|
||||
handful of machine operations.
|
||||
- **64-bit cells and 5 MB of linear memory per VM.** Reasonable on a PC; far too large for a node in a
|
||||
fabric.
|
||||
- **Diagnostics of its own implementation.** A significant block of words (hot-words cache statistics,
|
||||
lookup strategies, pipelining metrics, Bayesian cache models) measures v3's software dictionary, not
|
||||
the computation the dictionary performs.
|
||||
- **Hermes in software.** Message routing, per-message ACL checks, and TTL expiry are C code executed by
|
||||
a CPU that is also doing everything else.
|
||||
|
||||
None of this is wrong for a hosted or bare-metal OS. It is wrong for silicon. The project's direction
|
||||
is now an FPGA embodiment, and eventually an ASIC, and v3 cannot be carried there by porting.
|
||||
|
||||
## 2. What v4 is
|
||||
|
||||
StarForth v4 is a Forth machine designed to be the same thing in software and in hardware:
|
||||
|
||||
1. **A 32-instruction core ISA** derived from Chuck Moore's F18, the node of the GA144. Every core word
|
||||
is a mnemonic; every mnemonic is one 5-bit opcode.
|
||||
2. **Everything else is capsule code**, compiled from those 32 instructions, or a message to a node that
|
||||
owns a service, or a memory-mapped register, or retired.
|
||||
3. **A mesh of small nodes** that talk to their four neighbours through blocking ports. Hermes becomes
|
||||
the network itself: routing, ACL checks, and TTL expiry move into logic in every node's router.
|
||||
4. **Compudynamics as a side effect of execution.** Heat counters, the anti-clock, and the heartbeat are
|
||||
driven by instruction retirement in hardware. They cost no instructions.
|
||||
5. **A power-aware governor** built from a multi-level Rolling Window of Truth, controlling timing only.
|
||||
|
||||
v4 is a new implementation, not a refactor. v3 remains the reference system for LithosAnanke until v4
|
||||
reaches parity.
|
||||
|
||||
## 3. Why Moore's F18 instruction set
|
||||
|
||||
**It is proven minimal.** Moore spent decades removing instructions from his stack machines. The F18's
|
||||
32 opcodes are the result: enough to build a complete Forth, nothing that can be composed from the
|
||||
rest. There is no multiply, no divide, no compare, and no `SWAP`; each is a short sequence (for example
|
||||
`SWAP` is `over push push drop pop pop`).
|
||||
|
||||
**It fits a 32-bit word exactly.** 32 opcodes need 5 bits. Six slots fill 30 bits of a 32-bit
|
||||
instruction word, with 2 spare. One fetch feeds six instructions.
|
||||
|
||||
**It matches the project's formal-verification plan.** Proving 32 instruction semantics in Isabelle/HOL
|
||||
is a bounded task. Proving 300 C primitives is not. Every higher word then inherits correctness from its
|
||||
definition, which is itself a checkable object.
|
||||
|
||||
**It matches the dictionary-shrink plan that was already underway.** The existing POST suite, which
|
||||
exercises every dictionary word, was to be used as a regression gate while C primitives were replaced by
|
||||
colon definitions. v4 carries that plan to its end point: the surviving primitives are the ISA.
|
||||
|
||||
**It comes with a mesh precedent.** The GA144 places 144 F18 nodes on one die, each talking to its
|
||||
neighbours through blocking ports. v4 adopts that topology directly.
|
||||
|
||||
## 4. Why a mesh, and why Hermes goes into the fabric
|
||||
|
||||
v3's Tripod is several VMs sharing one CPU, with Hermes arbitrating messages between them in software.
|
||||
The mesh replaces time-sharing with space: each VM role runs on its own node or group of nodes,
|
||||
concurrently.
|
||||
|
||||
Moving Hermes into the fabric has three consequences:
|
||||
|
||||
- **The message semantics become hardware.** Per-message ACL checks and unconditional TTL expiry, which
|
||||
v3 already treats as rules rather than options, become router logic that cannot be bypassed.
|
||||
- **Contention disappears as a scheduling problem.** A blocking port is flow control. There is no
|
||||
scheduler to write, which honours the existing design goal of avoiding one.
|
||||
- **The SOS mechanism generalises.** Any node can emit an `SOS` packet. A node whose router fails can
|
||||
only stop forwarding, which its neighbours detect as blocked ports; this is the hardware form of v3's
|
||||
"Hermes raises a semaphore while sinking" rule.
|
||||
|
||||
## 5. Why cell width becomes a parameter
|
||||
|
||||
The Zynq-7000's processing system is a Cortex-A9, a 32-bit ARMv7-A core. Rather than maintain a separate
|
||||
32-bit fork, v4 makes cell width a build parameter of one VM (32 or 64). This has three benefits:
|
||||
|
||||
1. **The ARM becomes a real StarForth host**, not just a bootloader, at 32 bits.
|
||||
2. **Mesh nodes use 32-bit cells**, roughly halving stack and ALU cost in the fabric.
|
||||
3. **It opens a second invariance axis.** K≡1.0 has been shown invariant across amd64, aarch64, and
|
||||
riscv64. If it also holds across cell widths, the conservation law is shown not to depend on word
|
||||
size either. That is a stronger claim than ISA invariance alone.
|
||||
|
||||
The physics does not shrink with the cell. Heat and K arithmetic remain 64-bit (`int64_t` in C99 on
|
||||
every host; double cells on a 32-bit node). Changing only the payload width keeps the experiment clean:
|
||||
any difference in K can be attributed to cell width and not to lost precision.
|
||||
|
||||
## 6. Why the physics splits into "what" and "when"
|
||||
|
||||
The fabric can measure real power: the Zynq's XADC reads on-die temperature and supply voltages, and a
|
||||
current sensor on the core rail gives true power draw. This makes "heat" a physical quantity rather than
|
||||
a metaphor.
|
||||
|
||||
Physical measurements are noisy and never reproducible run to run. If they controlled which code
|
||||
executes, parity hashes would break and formal proofs of behaviour would become impossible. v4
|
||||
therefore splits the physics:
|
||||
|
||||
| Layer | Driven by | Controls | Property |
|
||||
| --- | --- | --- | --- |
|
||||
| **Virtual heat** | Instruction retirement and call counts | What executes (selection, promotion, eviction) | Deterministic and provable |
|
||||
| **Physical power** | XADC and rail current | When things happen (clock gating, node sleep, message pacing) | Adaptive, never affects results |
|
||||
|
||||
This settles a question left open in the original FPGA concept: whether compudynamic feedback into the
|
||||
control unit should affect only timing or also the execution path. The answer is both, through separate
|
||||
channels: logic chooses *what*, physics chooses *when*.
|
||||
|
||||
## 7. Why the governor is a multi-level Rolling Window of Truth
|
||||
|
||||
The timing governor uses the project's own Rolling Window of Truth mechanism at three timescales:
|
||||
|
||||
| Window | Timescale | Governs |
|
||||
| --- | --- | --- |
|
||||
| Short | microseconds | Clock gating on one node |
|
||||
| Medium | milliseconds | Node sleep and wake |
|
||||
| Long | seconds | Thermal trend and mesh-wide message pacing |
|
||||
|
||||
Positive feedback (rising message load) wakes neighbouring nodes and raises the clock. Negative feedback
|
||||
(rising temperature or power) throttles pacing and puts cool nodes to sleep. Each level reacts much more
|
||||
slowly than the one below it, so the loops do not fight; hysteresis at each level prevents flapping at
|
||||
thresholds. Hard limits (thermal ceiling, minimum clock) sit outside the adaptive layer as fixed logic.
|
||||
|
||||
A small neural network is a later candidate. Because the governor only controls timing, a poor governor
|
||||
costs power or speed and never correctness, so it is a safe place to experiment. The DoE recorder
|
||||
(below) produces exactly the training data such a network would need, so the two approaches can be
|
||||
compared on identical workloads.
|
||||
|
||||
## 8. Division of labour on the Zynq
|
||||
|
||||
| Component | Runs on | Role |
|
||||
| --- | --- | --- |
|
||||
| Mesh nodes | Fabric | All StarForth execution, the anti-clock, heat counters, routers |
|
||||
| Governor | Fabric | Multi-level RWT, single clock domain, cycle-exact |
|
||||
| Host node | ARM (32-bit) | Boot and bitstream load, compiler capsule, console bridge, DoE recorder |
|
||||
|
||||
The anti-clock stays in the fabric because it is defined as a pure function of the execution stream and
|
||||
must live where execution happens. The heartbeat's adaptive loop stays in the fabric because a loop
|
||||
crossing the PS–PL boundary would inherit ARM-side jitter (caches, interrupts, bus latency).
|
||||
|
||||
The ARM's recorder role keeps measurement separate from the thing being measured: the fabric pushes
|
||||
DoE rows into a FIFO, the ARM drains them to storage, and if the ARM falls behind rows are dropped
|
||||
rather than execution stalled. This is the fabric form of the planned `HB-ON`/`HB-OFF` disk recording.
|
||||
|
||||
## 9. Why the compiler lives on the host node
|
||||
|
||||
GA144 nodes have 64 words of RAM and 64 of ROM, and arrayForth compiles on a host. v4 follows the same
|
||||
split. The outer interpreter, dictionary, vocabularies, and defining words form the compiler capsule,
|
||||
which runs on the host node. Mesh nodes receive compiled code. Large capsules stay in DDR and are
|
||||
streamed to nodes as needed, so capsule size is not limited by node memory.
|
||||
|
||||
This is also why so many v3 words become CC rather than CAP in `DECOMPOSITION.md`: they are compiler
|
||||
machinery, not computation.
|
||||
|
||||
## 10. Development path
|
||||
|
||||
Each stage is checked against the one before it. Nothing proceeds on trust.
|
||||
|
||||
1. **Hosted golden model.** A C99 implementation of the v4 ISA and node model, with cell width, node
|
||||
count, and node memory as parameters. The POST suite, rewritten against v4 capsules, must pass at
|
||||
both 32 and 64 bits, and K≡1.0 must hold.
|
||||
2. **Hosted mesh.** Several golden-model nodes wired through simulated ports, running the Tripod roles
|
||||
as nodes. The 144-node configuration is exercised here, since the host is not limited by fabric size.
|
||||
3. **Co-simulation.** The node RTL is compiled with Verilator and run in lockstep with the golden model.
|
||||
After every instruction, stacks, registers, and heat counters are compared. The first mismatch
|
||||
identifies the faulty mnemonic exactly.
|
||||
4. **FPGA.** A 2×2 mesh on the PZ7020, then the largest grid that fits. The bitstream only has to match
|
||||
the co-simulation.
|
||||
5. **ASIC.** A single v4 node, not the mesh, as a proof of silicon through an open-source shuttle
|
||||
(currently Tiny Tapeout on IHP's SG13G2 130 nm open PDK). The same RTL is reused; block RAM is
|
||||
replaced by the process's SRAM macros.
|
||||
|
||||
## 11. Scaling beyond the PZ7020
|
||||
|
||||
Node count, node memory, and cell width are parameters, and the mesh is generated by a loop over rows
|
||||
and columns, so a larger board changes numbers, not design.
|
||||
|
||||
| Part | Approximate resources | Estimated nodes |
|
||||
| --- | --- | --- |
|
||||
| Zynq-7020 | ~53K LUTs, 140 BRAM36 | ~8–16 |
|
||||
| Zynq-7045 | ~218K LUTs, 545 BRAM36 | ~50–70 |
|
||||
| Zynq UltraScale+ (e.g. Kria K26) | ~117K LUTs, 144 BRAM36, 64 UltraRAM | ~30–40, with much larger node memory |
|
||||
| Larger UltraScale+ / Versal | Several hundred K LUTs and up | A full 144 |
|
||||
|
||||
Node counts are estimates. The first hardware measurement to take is the LUT cost of one node plus its
|
||||
router on the 7020; every other board's capacity follows from that number.
|
||||
|
||||
UltraScale+ parts also change the host: their Cortex-A53 cores are aarch64, so the host node can run
|
||||
64-bit StarForth while the mesh runs 32-bit cells, which the cell-width parameter already supports.
|
||||
Larger meshes will need registered router-to-router links to close timing, and the free edition of
|
||||
Vivado supports only smaller devices, so tool licensing must be checked before choosing a board.
|
||||
|
||||
## 12. Risks
|
||||
|
||||
| Risk | Mitigation |
|
||||
| --- | --- |
|
||||
| Capsule-level arithmetic is much slower than v3's C primitives on a hosted build. | Accepted. v4's measure of performance is the fabric, where each instruction is one cycle. The hosted build is a correctness oracle. |
|
||||
| Word addressing makes byte and string operations expensive. | D-1 in `DECOMPOSITION.md` keeps the choice open; colorForth's packed, pre-parsed source is a proven alternative for text. |
|
||||
| K≡1.0 may behave differently at 32-bit cell width. | That is an experimental result either way, and the hosted golden model finds it before any hardware exists. |
|
||||
| Hand-traced definitions contain errors. | Every CAP definition is a POST target against the v3 C primitive it replaces. |
|
||||
| The mesh does not fit the 7020 at a useful size. | Measure one node first; the design scales to larger parts unchanged. |
|
||||
|
||||
## 13. Relationship to intellectual property
|
||||
|
||||
v4 strengthens rather than replaces the existing claims. The Jacquard Selector, the Rolling Window of
|
||||
Truth, and the Steady State Machine all survive, now as hardware structures. The new elements a filing
|
||||
could draw on are: compudynamic heat as a zero-cost side effect of instruction retirement; the split of
|
||||
deterministic virtual heat (selection) from physical power (timing); per-packet ACL and TTL enforcement
|
||||
in a mesh router; and conservation invariance across cell width. Whether any of these belong in the
|
||||
LithosAnanke filing is a question for counsel.
|
||||
|
||||
## 14. Definition of done for v4.0.0
|
||||
|
||||
- The 32-instruction ISA is specified, with every open decision in `DECOMPOSITION.md` §3 settled.
|
||||
- The hosted golden model passes the rewritten POST suite at 32-bit and 64-bit cell widths.
|
||||
- K≡1.0 holds on the golden model at both widths, on all three host ISAs.
|
||||
- A hosted mesh runs the Tripod roles as nodes, with Hermes as the network.
|
||||
- Verilator co-simulation of one node matches the golden model instruction for instruction.
|
||||
@@ -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
Reference in New Issue
Block a user