The stick, increment 2 (plan 2026-10-26-stick-2-gpt-reader; docs/v4.0.0/
STICK.md 3 and 4: GPT for boot media and installed disks). kernel/src/gpt.c:
a CRC-32; gpt_read(), which checks the protective MBR, the primary header and
the partition-entry array (both CRCs, the revision, the sizes, the geometry);
and a partition as a blkio device, refusing blocks past its end. The two
StarshipOS partition types: identity 23BEBFE1-4817-4CF3-A537-9069BF159788,
Artemis BCD7B586-1C8E-4EEF-86A3-273A8D8EE624.
The v4 drive path: a GPT disk is used only through its StarshipOS identity
partition, and that partition -- never the disk -- is given to the block
subsystem, in a raw identity drive's place; a GPT disk with no StarshipOS
partition, or a damaged table ("GPT: a USB drive has a damaged partition
table -- not used"), is not attached (Captain Bob's ruling on the plan); a
disk with no GPT is read raw, as always. Pulling the drive detaches the
partition and ends her session. Reads only.
Red (amd64): gpt_zuse 193158, gpt_hotplug 193804, gpt_foreign 194713,
gpt_bad_crc 194947. Green: 195409, 195627, 195854, 200136; gpt_zuse aarch64
200424, riscv64 200839 (the 64 MiB partition attached, 48724 user blocks,
not the 72 MiB disk); the identity gate's and increment 1's sessions,
201119-203403, all pass.
Accepted (with the KERNEL_ARGS fix that follows): suite EXIT 0; 214300,
214507, 214911, POST 538/538, dict_hash 0xfec8c47cfc6f437f; test-32, 39
modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob, 2026-10-26: sized for an off-the-shelf thumb drive, "a minimum
and then ... no max or reasonable max size"; "all to Artemis, identity stays
at 500 MiB". The image is 2 GiB (ESP 64 MiB, identity 500 MiB, Artemis the
rest); the minimum stick 8 GB; at first boot Artemis grows to fill the stick,
up to 2 TiB, writing metadata only (GPT, volume header, free map, fence); a
stick under 8 GB is not grown. With genesis, increment 5; the GPT writer is
INSTALL's too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob, 2026-10-26: "64 megabytes does not need to be an engraved in
stone size ... start maybe 500 megabytes." Sizes are set in kernel/Makefile
and are not fixed by the formats.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Approved by Captain Bob 2026-10-26, with his ruling on review: a GPT disk is
never attached whole -- the identity partition is attached in the raw
identity drive's place; a GPT disk with no StarshipOS partition, or a damaged
one, is not attached.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the fresh review of the stick's increment 1 (With fixes):
- Critical: after logout Zuse's last screen, her prompt included, could be
drawn back on a headless machine. The logout clear (ESC[2J) blanked the
pixels only: Alt+TAB, still read while headless, redrew the terminal
from its saved text; and if she had Alt+TABbed to the graphics view
before the pull, the clear did nothing and her session stayed on screen
(and the console did not draw at her next login). Now vt100_reset()
forgets everything the terminal has shown -- the on-screen text, the
scrollback and their boot snapshots -- makes it visible again and fills
the screen; and Alt+TAB does nothing while the screen is off (v3's never
is, so v3 is unchanged).
- Important: an EMERGENCY_CONSOLE_ENABLED build no longer clears the screen
when Zuse's drive is pulled: its console goes on running.
Red: alttab_after_logout 183308 (4515 lit), alttab_before_pull 183529
(4539 lit; the console not redrawn), emergency_pull 183759 (0 lit).
Green: 184115, 184328, 184552; regression 184805-185956 (screens,
keyboard, hotplug, emergency, v3 typed by keyboard) all pass.
Accepted: 190111, 190312, 190710, POST 538/538, dict_hash
0xfec8c47cfc6f437f; test-32, 39 modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stick, increment 1, task 2 (plan 2026-10-26-stick-1-screen-and-keyboard;
docs/v4.0.0/STICK.md 2, 5.3, 5.4). On the v4 path:
- the framebuffer is brought up after POST, cleared and dark: console text
goes to serial only ("splash only, log on serial") until Zuse logs in;
then the screen is the console (TTF, a blinking cursor, as v3's), and
when she logs out it is cleared and dark again (console_fb_mirror(),
console_fb_clear(); the mirror is on by default, so v3 is unchanged);
- the line editor and the node's KEY read every keyboard -- PS/2, USB, the
virtio keyboard -- through the shared bridge (sk_input_getc()); the
headless wait drops keyboard input as well as serial bytes;
- an EMERGENCY_CONSOLE_ENABLED build has the screen from the start.
The framebuffer setup is one helper both paths call (kernel_main.c).
Red (before): screen_dark_until_login 153051 (10835 lit), console/keys
153309, logout 153609, kbd_typeahead 153918, virtio_kbd aarch64 154245
and riscv64 154718; no_framebuffer 155546 passed before and after.
Green: 155926 (0 lit), 160156, 160409 (0 lit after logout), 160630,
virtio_kbd 161414 and 161820, no_framebuffer 161206; usb_kbd with the USB
keyboard the only one (-machine i8042=off) 164548, v3 control 164757;
the identity gate's sessions 162245-163802 all pass; v3 typed by keyboard
164009, 164115. (usb_kbd 160857 and 164313 failed in the harness:
input-send-event's device names a display, not a keyboard.)
Accepted: suite EXIT 0; three clean qemu boots, POST 538/538, dict_hash
0xfec8c47cfc6f437f unchanged (174704, 174911, 175315); test-32, 39
modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On riscv64 a system=v3 boot never reached its prompt: Artemis's writes
"timed out" and Zuse was never confirmed (logs/20261026-134850). vblk_io()
bounded its wait by ~1M polling iterations, which on riscv64 under TCG is
about one heartbeat tick of real time -- shorter than a write that allocates
space in a sparse host image. Instrumented, the request was seen completing
just after the give-up ("used idx=409 last=408"), and every later request
then took its predecessor's completion for its own and returned before its
own I/O was done (a stale used index at each later request), reusing the
descriptor chain while the device still owned it: silent read and write
corruption from that point on. FABRIC-3.md's 2026-09-09 "request that never
gets a used-ring completion" is this same early give-up.
Now: the wait is for this request's own completion (the used index
reaching the avail index it was given), bounded by 5 s of real time on the
CPU's counter (timer_now_ns(), which needs no interrupts); a request that
truly never completes takes the disk out of service instead of letting a
later request reuse the chain.
Red (riscv64 system=v3, with temporary instrumentation): 151003, 151100 --
a timeout then dozens of stale completions each. Green: 151238, 151332 --
none; Zuse confirmed; the keyboard line answered. system=v3 with the fix:
riscv64 151438, amd64 151528, aarch64 151610, no timeouts. Accepted (v4):
151722, 151916, 152247, POST 538/538, dict_hash 0xfec8c47cfc6f437f;
test-32, 39 modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stick, increment 1, task 1 (plan 2026-10-26-stick-1-screen-and-keyboard).
repl.c's keyboard bridge -- the key tables, Shift/Alt/Caps Lock/Num Lock and
their lights, the keypad, Alt+TAB, and the per-tick USB keyboard servicing --
moves unchanged to kernel/src/hal/kbd_input.c as sk_input_getc() (and
sk_input_drop()), so that the v4 boot's console reads the same keyboards
(docs/v4.0.0/STICK.md 5.4). v3's behaviour is unchanged.
scripts/qemu_session.py: the typed-QEMU-session harness, kept in the repo
from here on (the identity gate's sessions, and v3_keys: system=v3 typed on
QEMU's keyboard with send-key).
Yardstick, system=v3 typed by keyboard: before, amd64 PS/2 134805 PASS,
aarch64 virtio keyboard 135549 PASS; after, 135746 and 135835 PASS.
(riscv64 134850: v3 never reached its prompt -- Artemis virtio_blk writes
time out; v3's block path, before this change; being investigated.)
Accepted: suite EXIT 0; three clean qemu boots to [zuse@Hera] ok>, POST
538/538, dict_hash 0xfec8c47cfc6f437f (145722, 145859, 150231); test-32,
39 modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One GPT stick that is the whole OS: ESP, a StarshipOS identity partition and
a StarshipOS Artemis partition; a splash until Zuse logs in, automatically;
each stick mints its own Zuse on first boot; try-it writes persist on the
stick until INSTALL; pulling it goes headless. GPT comes back for boot media
and installed disks (overturns FABRIC-2.md F.8 for those); system=v3 is
refused on a stick; every clean qemu boot uses a GPT data stick over USB,
virtio Artemis leaves v4. Approved by Captain Bob 2026-10-26. First of three
designs (then INSTALL, then DOE/SDK/demos); ahead of ENGINE step 4 Part A.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the fresh whole-branch review of the identity gate (With fixes; no
Critical, four Important):
1. A drive pulled while a line ran: the drives are looked at before every
prompt (sk_v4_identity_check_now), so no prompt is shown once she is
gone and what was typed after the pull does not run as Zuse.
2. Pulled while a line WAITS: the wait is ended at logout, by an empty
line, and not carried into her next session (Captain Bob, 2026-10-26:
"end the waiting line at logout"); re-attaching brings the prompt back.
3. EMERGENCY_CONSOLE_ENABLED: v4 honours it as v3 does -- a bring-up build
has a prompt with no drive (boards/BRINGUP.md A2).
4. Keys typed at a headless machine are read and dropped, not run as
whoever logs in next. (v3 has the same gap, sk_repl_headless_wait;
reported, not changed.)
Each a QEMU session red then green (amd64): midpull 111650 -> 112953,
waitpull 111907 -> 113154, emergency 112524 -> 113609, typeahead
112248 -> 113359; headless 113800 and hotplug 114043 still pass.
Accepted: three clean qemu boots to [zuse@Hera] ok>, POST 538/538,
dict_hash 0xfec8c47cfc6f437f on all three; hotplug on aarch64 and
riscv64; make -C v4 test test-32 sanitize hosted-check EXIT 0;
make -C v4 test-32 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The identity gate on the v4 boot (plan 2026-10-26-engine-step4-identity-gate,
task G2; ENGINE.md 2, ruled 2026-10-20). As v3, by the kernel with no v3 VM:
after POST and the block chain, Zuse's public key from the genesis marker,
every xHCI controller brought up, the heartbeat started; then headless until
her drive is attached and checked (capsule_zuse_boot_check, G1). A drive that
arrives is given to the block subsystem by the kernel (Artemis is the
kernel's); her session is kept in the kernel for Hera, never in a node's
memory. The prompt is v3's, [zuse@Hera] ok>; pulling her drive ends the
session and the system goes headless; putting it back brings the prompt.
A blank pair stays headless: genesis writes Artemis's disk, Phase 5 (D2).
kernel/Makefile: ARTDISK and ZUSEDISK default to the minted pair,
disk/zuse-scratch/ (D4); .claude/CLAUDE.md's acceptance says so.
Fixed with it, at Captain Bob's word:
- kernel/Makefile: the ROM-and-map rule is a grouped target (&:). As two
targets of one plain rule its recipe ran twice at once under -j and the
copies met ("cp: cannot create regular file ... File exists"): 3 of 20
parallel builds failed, now 0 of 20.
- The v4 boot drops the logger to --log-level after POST, as v3 does
(sk_log_level_after_post, shared by both paths); INFO lines after POST,
3 before, 0 now.
Accepted: three clean qemu boots as built to [zuse@Hera] ok>, POST 538/538,
dict_hash 0xfec8c47cfc6f437f on all three (unchanged), 0 INFO after POST;
the hot-plug session (attach, line, detach, headless, re-attach) on amd64,
aarch64 and riscv64; headless with no drive; make -C v4 test test-32
sanitize hosted-check EXIT 0; make -C v4 test-32 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
capsule_zuse_boot_check() makes the check capsule_zuse_boot_try_attach()
made -- the genesis marker, the drive's identity record (magic, version,
CRC-64, public key) -- and says HERS, GENESIS or NOT_HERS, with no VM;
capsule_zuse_boot_root_pubkey() reads the marker's key. try_attach and
load_root_pubkey call them; their behaviour and messages are unchanged.
The v4 boot will make the same check (identity gate plan, D1).
Shown on v3 (system=v3, amd64): the minted pair, "Zuse: identity
confirmed" and [zuse@Hera] ok> (logs/20261026-083603); a blank pair,
"Zuse: genesis minted onto attached thumbdrive" (logs/20261026-084729).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob, 2026-10-26: "Gate first." Its own plan, with D1-D4 ruled as
recommended: the Zuse check split from the v3 VM; v4 recognises a minted
Zuse only (genesis with Artemis's writes, Phase 5); [zuse@Hera] ok> now;
the minted pair is QEMU's default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
disk/zuse-scratch/artemis.img and zuse-thumb-ident.img, minted from blank
by a system=v3 amd64 boot (genesis minted) and confirmed by a second
(identity confirmed); both logs included. The genesis marker is on the
Artemis disk, so the two are a pair. The committed artemis.img and
thumbdrives/zuse-thumb-ident.img are not touched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MACHINE.md stands: v3 goes after parity; Hera, Hermes, Artemis (and
Hestia) are kernel functions. ENGINE.md section 2 amended with the rulings,
section 6's step-3 rows struck (R2). The step 4 plan rewritten: Part A
(hook at call, called in-line words) and Phases 1-8 to parity. No identity
thumbdrive, headless; work goes ahead only with Zuse attached.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three boots through the top-level Makefile: POST 538/538, dict_hash
0xfec8c47cfc6f437f on amd64, aarch64, riscv64; '3 4 + .' answers 7.
make -C v4 test-32: 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Top-level 'qemu' fell through to v3/Makefile, which has no such rule.
qemu, qemu-esp and qemu-gdb now go to kernel/Makefile; with ARCH given on
the command line and no TARGET, 'clean' is the kernel's for that ISA.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three clean qemu boots to v4 ok>: POST 538/538, PARITY:OK,
word_count=317 dict_hash=0xfec8c47cfc6f437f on amd64, aarch64 and
riscv64; a typed line answered on each. make -C v4 test-32: 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruling 7 as amended: the kernel tells a node's going, so the system's
hand-on is not used. (GONE-HOOK), (DOWN) and (RUN) go from quit.f18, and
COLD's hook-clearing from system.f18; the cell is free again. The tests of
the hand-on go with it (mesh: the hand-on checks and the fourth disturbed
exchange; depth sweep: path 10, as before 529ba0fc). A believed GONE going
no further is still checked. test_host_unit.c's message for GONE down the
graph now says the kernel tells. MESH.md: 9a.6 items 5 and 7, and step 7's
record of both increments.
Suite EXIT 0; depth sweep 230 runs, 0 failures; mkcapsule lint 0
violations. Hosted and bare metal, all three ISAs: word_count=317
dict_hash=0xfec8c47cfc6f437f.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Suite (test test-32 sanitize hosted-check) EXIT 0. Three clean qemu boots
to v4 ok>: POST 538/538, PARITY:OK, dict_hash=0x248b4edc47f4357e on
amd64, aarch64 and riscv64. make -C v4 test-32: 0 failures. Also the
amd64 boot of 2026-10-19.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the final review of MESH step 7. NODE-KILL left children whose parent
was the dead number, so a node born later under it inherited authority over
them; they are re-parented to Hera. After UNIT-KILL Hera no longer lists the
removed centre, and a later KILL completes (shown to fail with GONE-DOWN's
unlisting taken out). test_manage 45/45 both widths; test_host_unit 127/127.
Acceptance: amd64, aarch64, riscv64 clean qemu: ok>, POST 538/538,
dict_hash=0x248b4edc47f4357e on all three; test-32 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MESH.md step 7: what was built, the tests, the (DOWN) mend, the traced
(LOST) finding; 9a.5: a centre killed mid-birth, and birth authority not
yet tied to identity. v4/README.md: births follow v3.
Acceptance at this commit's code: amd64, aarch64, riscv64 clean qemu, v4:
ok>, POST 538/538, dict_hash=0x248b4edc47f4357e on all three; test-32 0
failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amd64, aarch64, riscv64, clean qemu, v4 as built: ok>, POST 538/538,
PARITY:V4_SYSTEM word_count=318 dict_hash=0x248b4edc47f4357e on all three
(the same as the hosted build); Q./ answers 0 21845. make -C v4 test-32:
0 failures. BLOCK_MAP.md regenerated: centre.4th, hera.4th's new blocks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found by the depth sweep: a hook that sent a message about another node
overwrote (ONE), which AWAIT reads after believing a GONE, so the wait went
on. (DOWN) now calls the hook through (RUN) and restores (ONE).
AWAIT ended by a GONE that is handed on: works to 26 values and 21 calls
deep, then a stack error and nothing else, at both widths. Removal sweep:
node 11 or 12 removed, or the wire cut, at every step: 0 wrong. hosted
dict_hash=0x248b4edc47f4357e on all three ISAs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_host_unit: 125 checks. Shown to fail with the GONE hook taken out of
centre.4th, and with the Hera-only check taken out of manage.c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What a birthing node needs is centre.4th; KILL, PAUSE, RESUME, UNIT-KILL and
CENTRE are Hera's. An outer node births, as a v3 VM may, and may not kill.
A capsule is read by the node that opened it. test_host_unit: 93 checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
COLD takes out a hook it forgets. The system changed, so dict_hash did:
hosted, all three ISAs, word_count=318 dict_hash=0x1b5c633fd6bdd143.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any node may birth and wire its own; only Hera sleeps, wakes and kills, by
number. Requests have fixed numbers, -6 to -18. NODE-BORN takes the
number; NODE-KILL a number. test_manage.c: 41 checks at both widths.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixed request numbers; NODE-BORN takes the number; GONE handed on through
the system's (GONE-HOOK), so dict_hash changes; a reader per asker.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruled 2026-10-16: Hera births the second centre and it births its own unit;
hera.4th split into centre.4th (BIRTH-AS, BIRTH, UNIT) and Hera's own
(KILL, PAUSE, RESUME, UNIT-KILL, CENTRE); the kernel keeps the registry and
checks who may ask; centres face each other on port 6; GONE goes down the
birth graph.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MESH.md ruling 7 and section 9 said only Hera's requests are honoured.
Ruled 2026-10-16: v4 births behave as v3's (any VM may BIRTH, the child's
parent is its birther, its ACLs are copied from the parent's at birth,
KILL is Hera's alone).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DOE only types its name for now, as asked 2026-10-15; the runner is still to be
built. Not yet a system capsule (MACHINE.md 6, step 3). With it, the two board
boots, amd64-pc and aarch64-rpi5, that tried it: DOE is unknown until
STARSHIPOS is in the search order.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amd64, aarch64, riscv64: ok>, POST 538/538, dict_hash=0xfec8c47cfc6f437f,
rom_hash=0x87b23d3ae2643c8d (2372 words) on all three; Q./ answers 0 21845.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DATASHEET-F18.md lists all 19 entries of the host ROM, the six shared ones
with the registers they use. MACHINE.md 2.2: built; 277 words, not the
estimated 150-200; the system's words are address, push and ;.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MACHINE.md 2.2. Hera carries the host's ROM; the four outer nodes the
shared math only, and compute UM*, U/MOD and Q./ with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MACHINE.md 2.2. Each is its entry's address, push and ;. Every node the
tests make carries the host ROM (host_load, Hera's births, the depth and
mesh tests' own nodes), and a division by zero inside the ROM returns to
the prompt (hosted-check). test_host_quit's fetch outside memory moves
past the ROM's range: 16384 is the ROM's first word now the tests' system
has its ROM, as the product's always had. dict_hash 0xfec8c47cfc6f437f.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MACHINE.md 2.2. UM*, UM/MOD, D+, DNEGATE, Q.* and Q./ are entries 0-5
of the host ROM and of a mesh node's ROM, from one source (rom/math.f18)
and one entry list (v4/rom_entries.h). The host ROM starts at entry 18.
The mesh ROM is 277 words; the host ROM 2372.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared math in a small ROM for mesh nodes: UM*, UM/MOD, D+, DNEGATE,
Q.* and Q./ as entries 0-5 of both ROMs, from one source; the host
ROM's assembler entries follow, and its start moves from 12 to 18.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Text after start is refused, as text.c refuses it: before it jumps, the
ROM reads on to the end of the source; blanks, comments and the ends of
blobs may follow, a token is ERR-AFTER (26), "text after start".
- A token too long where a name, a target or a value is wanted is "name
too long", as text.c says: (MISSING) reports "missing" only when no error
came first. `", keeps "missing", which is text.c's word for both.
- text.c's "address out of range" names the address, not the value.
- The system's source files are one list, v4/sys_files.h: boot.c, the
harness and the nucleus test are made from it.
- The ROM's error codes and words are one list, v4/rom_errors.h: boot.c's
messages, host_map.h's ROM_ERR_* and mkmap's ERR-* are made from it.
- node.h says what v4_node_store does with a ROM address (nothing, as for
any address outside RAM, D-14); test_host_rom_range pins it.
ROM: 2095 words, rom_hash 0x06d0dcb7a0cb41a1. dict_hash unchanged,
0xe5a57f3eb72ff94a. make -C v4 test test-32 hosted-check pass. QEMU:
amd64, aarch64, riscv64 to ok>, POST 538/538, POST: PASSED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The boot left the source's last new line in the console input, and the
first KEY after the boot read it. What the ROM has not read when it
starts the system is taken back (boot.c, rom_harness.h). hosted-check:
KEY after the boot reads the key typed.
- A comment or macro left open at the end of a blob ran on into the next,
and the ROM accepted source text.c refuses. The loader ends each blob
with FS (V4_ROM_BLOB_END) after its new line; the ROM ends a blob there
as text.c ends a file: an open comment or macro is an error, and the word
being assembled ends. test_host_rom_asm: seven blob pairs against text.c.
- store to an address outside RAM faulted the ROM with no message. It is
now refused, as text.c refuses it: ERR-RANGE, "address out of range".
- The kernel build did not regenerate capsules/v4/sys/map-<w>.f18 before
packing the capsule directory; it now does.
ROM: 2084 words, rom_hash 0x4c458c6e48b35456. dict_hash unchanged,
0xe5a57f3eb72ff94a. make -C v4 test test-32 hosted-check pass. QEMU:
amd64, aarch64, riscv64 to ok>, POST 538/538, POST: PASSED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host node starts in its ROM (entry 12), and the boot feeds it the
system's source through the console: capsules/v4/sys/map-64.f18, the
fourteen .f18 blobs and end.f18, each found, hash-checked and
signature-checked as any capsule, then EOT. The ROM assembles the system
and starts it at (IDLE); the host reads the image record
(v4_image_from_node) for what only the assembled system knows. A ROM
error is reported with its blob, line and meaning, then PARITY:FAIL.
Deleted: v4/tools/mkimage.c, capsules/v4/nucleus-64.f18, v4/capsule/*.v4,
v4/tools/v4tof18.py. The .f18 files are the source now.
- text.c speaks the rest of the ROM's language (set, here, store, start;
v4_text_value, v4_text_start), so the oracle reads the same source:
test_host_rom_nucleus compares the ROM against text.c on the .f18 files,
word for word, image record included. Host tests load the .f18 files.
- mkmap image writes v4_map_image (the map's description of the system);
hosted and the kernel link the ROM and the map instead of v4_image_64.c.
- Hera (Captain Bob's ruling, option 1): births stream the system the ROM
assembled, as assembled code; hera.4th is unchanged.
test_host_unit's host builds the system with the ROM.
- New parity lines: PARITY:V4_F18 per blob, PARITY:V4_ROM words=2049
rom_hash=0xa6c792b5821010b7 instructions=60725216.
Acceptance: amd64, aarch64, riscv64 boot to ok> with PARITY:V4_POST
tests=538 pass=538 fail=0, POST: PASSED, and PARITY:V4_SYSTEM
word_count=317 dict_hash=0xe5a57f3eb72ff94a on all three -- the same hash
as the prebuilt nucleus gave. make -C v4 test test-32 hosted-check: all
pass. Logs: logs/20261015-141648, -141938, -142350.
Startup cost under QEMU TCG, the ROM's assembly (last V4_F18 line to
V4_ROM): amd64 26.7 s of 132 s to ok>; aarch64 41.0 s of 195 s; riscv64
20.5 s of 101 s. Hosted native: +0.85 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
capsules/v4/sys: the nucleus's fourteen sources as .f18 blobs (made once by
v4/tools/v4tof18.py: header becomes the ROM's directives, every other token
and line kept), the memory map as map-<width>.f18 (mkmap sys, from one
table in host_map.h that host_load reads too), and end.f18, the switch-on
state mkimage.c set in C, the image record, and start (IDLE).
test_host_rom_nucleus.c: the ROM, fed those blobs through the console,
builds RAM identical word for word to mkimage.c's, outside its own state
and the image record, and starts at (IDLE), at both widths. The cost:
60.7 million instructions, 1.5 s on the C model.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
word.f18: (NEXT-TOKEN) reads the console or a macro being expanded; labels,
branches by name (a label of the word, or a word, now or later), the
table of branches waiting, end of word, FOR/NEXT/UNEXT, macros, &NAME,
CONST+N, and (ONE), which dispatches a token. A forward branch to a name
not yet defined waits on a placeholder symbol, filled in by (DEFINE).
dir.f18: constant set here #, ", store, and start, which resolves, clears
the tables the ROM used and runs the word it names. main.f18: the ROM
itself, entry 12; on an error it stops at (ROM-FAILED) with the code and
line in its state, for the loader to report. sym.f18 generalized: any
counted string, placeholders, a hash of only a name's own cells.
test_host_rom_asm.c gives test_text.c's own texts (accepted and refused),
its four real definitions and the ROM's directives to text.c and to the
ROM: the same words, the same errors on the same lines, at both widths.
The ROM is 2036 words.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(OP) (LIT) (BRANCH) (BRANCH>) (RESOLVE) (LABEL), entries 6-11: the code
generator of any language built on the machine (MACHINE.md 2.1). asm.c's
layout rules with text.c's branch placement; 400 random sequences agree
word for word with asm.c at both widths, memory-full and out-of-reach are
refused on both sides, and a ref with no branch is refused, not looped on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(FIND) ( -- rec | 0 ), (DEFINE) ( value kind -- ) and (OPCODE) ( -- op | -1 ),
entries 3-5. Names are refused as text.c's define refuses them, compared
case by case with text.c; a set variable may be set again. 256 hash heads,
records growing up and names growing down in dictionary space, used only
while the ROM assembles. text.c gains the data directives #, and ", (the
ROM's language; its mnemonic and reserved-word tables are data); the
nucleus image is byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(NUMBER) ( -- n flag ), entry 2: decimal with a leading -, or hex after $;
1 a number, 0 not one, -1 one that does not fit a cell. Every case is also
given to text.c, the oracle, at both widths.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ROM's source is F18 code in capsules/v4/rom, assembled off the node by
v4/tools/mkrom.c with the memory map's constants from v4/tools/mkmap.c
(MACHINE.md 2). main.f18 is the entry table payloads call through (2.1);
in.f18 reads the console and splits it into tokens exactly as text.c does,
the token held packed as a counted string. The ROM's state is a reserved
area of the map (host_map.h ROM_*). text.c gains the constant directive,
so the off-node assembler and the ROM speak one language. The map also
names (NUMBER)'s state, for the next task.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A read-only range of V4_ROM_WORDS words at V4_ROM_BASE, above RAM
(MACHINE.md 2, DATASHEET-F18.md 5). Instruction fetch, @p and data fetches
read it; a running programme's store there is an address fault. Attached by
the owner like every device; a reset detaches it. The host node's range is
4096 words. text.c places branches by the whole address space. The
nucleus image is byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob, 2026-10-14: "change to PC, not SER5. it's not supposed to be
specific, but PC generic." boards/ser5 -> boards/pc, TARGET=PC,
lithos-pc.img; the image was never specific to one machine (the generic
UEFI/ACPI path, FABRIC-3 III). The Beelink SER5 stays named where the text
means the unit on the bench (its Secure Boot, BIOS, serial header) and in
the records. Built: lithos-pc.img, system=v4, with its SBOM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob, 2026-10-14: "v4 is the default build", "no, qemu to v4
too ... we are effectively trying to retire v3", "the 32 bit build needs
to go into the acceptance test too", "i don't care about v3".
- STARFORTH_V4 defaults on (Kconfig default y) and V4_DEFAULT=1
everywhere: every kernel carries v4 and v3 and boots v4; system=v3 boots
v3; STARFORTH_V4=0 builds v3 alone. Board images write system=v4.
- Acceptance (CLAUDE.md): the three ISAs as built (v4, POST passed,
V4_SYSTEM dict_hash equal) and make -C v4 test-32. v3 is not part of
it.
Acceptance run: amd64, aarch64, riscv64 -- PARITY:V4_POST 538/538,
dict_hash=0xe5a57f3eb72ff94a on all three, no unknown word; test-32: 30
suites, 0 failures. The SER5 image under OVMF boots v4 as built, v3 after
the one-word edit. README, BRINGUP, FABRIC-3 XLIII, the register updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
make boot_image now ends by writing build/boards/<board>/<image>.spdx(.json):
the image and every file copied off it, each with its SHA-256 -- the SBOM
of what is on the medium. It also refreshes sbom.spdx(.json), the source
SBOM: the tracked files the product is built from (kernel, v3, v4,
capsules, boards, tooling, proofs), staged to build/sbom/src so nothing
untracked in the working directory is swept in. Versioned as the kernel
version and git describe. mk/syft.yaml turns on file cataloging with
SHA-256 (a C tree has almost no packages for syft to find: the old SBOM
held one file with a zero checksum). No syft: the build stops.
syft 1.52.0 installed in ~/.local/bin from its GitHub release, checked
against the release's published SHA-256.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Captain Bob's rulings, 2026-10-14: "delete" -- the duplicates listed in
DELETE-CANDIDATES.md are removed (the list stays as the record; the
formal tier's provenance comments repointed at the maintained copies) --
and "rewrite" the README: v2.1.0, the Tripod as Hera/Artemis/Hestia,
kernel-Hermes, identities on thumbdrives, the corrected ACL overhead,
1052-test POST and the current parity line, keyboards and storage, board
images carrying both systems and how to switch, and docs/README.md as
the way in. The book is left as it is, to be reworked later.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/CLAUDE.md Phase 1 output, after the reorganisation.
- docs/README.md: rewritten as the map -- where each kind of document
lives, which one to believe (CLAUDE.md, FABRIC, v4.0.0, reference/,
BRINGUP, code), how to retire a document.
- docs/INDEX.md: regenerated from the tracked tree, 489 rows, every
document with a status (the 2026-06-16 snapshot was stale).
- docs/DEAD-AND-REVISED.md (new): what was abandoned (L4Re, the hal_*
contract, ACL RWT, the Hermes VM, elevation, the knowledge factor, ...)
and what was corrected (ACL overhead, versions, block rules, parity
baseline, ...), each with its date and record.
- docs/DELETE-CANDIDATES.md: 12 duplicates, awaiting a ruling; nothing
deleted.
- CLAUDE.md: versions corrected (3.2.0 / 2.1.0).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/CLAUDE.md Phase 2, 2026-10-14. All moves by git mv; every archived
file carries a header saying what it is, why, and where to look instead.
- docs/reference/ (new): roadmap and versioning policy, M7.1, word-ACL
design, kernel args, hosted acceptance test, dictionary, primitives,
ontology, L8 table -- previously spread over docs/, docs/lithosananke/
and docs/03-architecture/.
- docs/working/archive/historical/: finished work (session plan, test-gap
audit, birthing plan, fix write-ups, the January architecture draft).
- docs/working/archive/superseded/: the Hermes-VM Tripod docs and July
Hermes designs (-> FABRIC-3.5/3.6), the StarForth roadmap, every working
doc already flagged superseded or obsolete.
- docs/working/archive/dead/: the hal_* target contract (never adopted),
L4Re, metrics-and-knobs.
- Papers and proposals into docs/working/papers/.
- References rewritten across the repo (not logs/, not docs/patent/);
CLAUDE.md's documentation section rewritten.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md A6, FABRIC-3 SXLIII (ruled: one image, switch at boot).
A STARFORTH_V4 kernel carries v3 too; system= in the boot arguments
chooses, else the build's default (V4_DEFAULT: 1 for plain STARFORTH_V4
builds as before, 0 for board images). make boot_image builds both and
always writes starforth.cfg / cmdline.txt with system=v3 first, and cleans
its ISA's objects first -- that clean was removing build/<arch>/SER5, not
the kernel's objects, until fixed here.
Each ISA: v3 by default (hash unchanged), v4 with system=v4 (538/538).
The SER5 image under OVMF: v3 as built, v4 after a one-word edit on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md A1, FABRIC-3 SXLII. xhci.c keeps a table of controllers
(up to 8) and services each; kernel_main brings up index 0, 1, ... until
there is none. repl.c's and blkio_usb.c's per-slot state is per
controller now (a slot ID is a controller's own), and each USB keyboard
keeps its own last report and lights; an unplugged keyboard releases what
it held.
Test first: keyboard and identity on a second controller behind a bridge,
Zuse on the first -- before, only Zuse; after, all three, on all three
ISAs. Hot-plug and unplug on the second controller. Acceptance unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md A3 and S3, FABRIC-3 SXLI. A HID boot keyboard is
configured (interrupt IN endpoint, SET_PROTOCOL boot) and its reports
become the same Linux-keycode events as PS/2 and virtio (usb_kbd.c): the
full layout -- F-keys, navigation block, arrows, Num Lock, keypad. The
console treats Caps and Num Lock as toggles shown on the keyboard's
lights, and the keypad as digits or navigation. While a USB keyboard
runs, its event ring is serviced every tick, not once a second.
Found on the way: with no i8042 (port 0x64 reads 0xFF) the kernel hung at
boot in an endless drain -- a legacy-free PC would stop there. Detected
and skipped now; drains bounded.
QEMU, amd64 with the USB keyboard the only one: 1 2 + . on main keys and
keypad, Caps Lock, Num Lock all right; aarch64/riscv64 configure it too.
Acceptance on three ISAs unchanged; identities hot-plug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md A1, FABRIC-3 SXL. It was matched by QEMU's own IDs on
bus 0 alone, so no real board's was found. Now pci_find_class() reads
every bus/slot/function; pci_bar_size() sizes BAR0; the USB Legacy Support
capability hands the controller over from the BIOS, SMIs off; CSZ=1
contexts are placed 64 bytes apart instead of refused. XHCI_QEMU_ARGS
lets QEMU place the controller as real hardware does.
Test first: an NEC controller behind a PCIe root port -- no attach before,
Zuse minted after, on all three ISAs. Standard acceptance unchanged; five
hot-plugged identities attach. Not rehearsable: firmware handoff, CSZ=1.
Still open: only the first controller found is used.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md R2/R3, FABRIC-3 SXXXIX. The entry stub cleans the cache
over the image, builds an identity map (the image's GiB Normal, the rest
Device) and enables MMU and caches at EL2 (or EL1); rpi5_mmu.c makes the
devicetree's RAM Normal and the framebuffer uncached. Mailbox waits give
up after one second; the buffer is cleaned around the exchange; the
framebuffer address goes through dma-ranges, not a Pi 4 mask.
New rpi5-rehearsal target runs the native image on QEMU virt at EL2. It
found three more that would each have stopped the board: the PL011 shift
(mine, c9519173; the host test asserted it), the GIC address not carried
through /soc's ranges (new fdt_reg_address(), checked against the real
Pi 5 DTB), and no timer IRQ at EL2 (HCR_EL2.IMO/FMO/AMO).
Rehearsal: POST 1052 passed, same parity hash as UEFI. Standard acceptance
on three ISAs: POST 1052, hash 0x82f4ae7cb2e2d424.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FABRIC-3 SXXXII.4's deferred LOG-FLUSH, built to the 2026-10-14 rulings
(SXXXVIII): everything a VM logs, at or above the log level, goes into its
own buffer; it goes to Artemis on LOG-FLUSH, when full, and at once on an
ERROR, as one kernel-Hermes LOG_BATCH message she writes on her own turn,
the source being the sender the kernel stamped. Records that cannot go yet
are counted and reported with the next flush. LOG-SHOW (Hera only) reads
the ring back -- it had no reader.
Found by the first test that filled it: ring growth overwrote the oldest
record and put blank slots inside the live range. Fixed test first.
Three ISAs: POST 1052 passed; new parity baseline word_count=526
hash=0x82f4ae7cb2e2d424 (deliberate). CLAUDE.md: Phase 8 PKI closed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any identity could have arbitrary FORTH run as Zuse: KH-ELEVATE-SEND and
KH-BLK-ATTACH-SEND sent any text to Hera, from any VM (shown live). And the
drain popped a message after running it, so a payload calling a colon word
ran twice. Both fixed test first (FABRIC-3 SXXXVII):
- KH-BLK-ATTACH-SEND is ( dev-addr ok? -- sent? ), Artemis only; the kernel
writes the reply text. BLK-ATTACH-ACK is Hera's only.
- The drain pops before it runs.
- Elevation, ruled not needed: KH-ELEVATE-SEND, message type 8,
zuse-eligibility.4th, ZUSE-ELIGIBLE?/ZUSE-ELIGIBILITY-ADD/
ELEVATE-PUBKEY-UNPACK and the eligibility list removed; its disk area
stays reserved, unused. FABRIC-3.7 closed.
Three ISAs: POST 1052 passed; new parity baseline word_count=523
hash=0xb73b58052d591638 (deliberate).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FABRIC-3.5 SXXXII, closing FABRIC-3 SXXIX bug 2 (SXXXVI). A send marks the
receiver for the switch signal; the VM's own loop on its native stack takes
its messages and yields; Hera's idle beat makes the pending switch instead
of running other VMs' messages on her stack; every VM gets switcher turns
from birth; the drain refuses any call outside the VM's own context (the
test: it held every relayed line before, none now).
Found on the way: amd64's first-entry frame left rsp 8 bytes off the SysV
entry alignment (#GP on the first interpreter run on a VM's own stack), and
a VM yielding from its loop was marked SWITCHED_OUT, which stopped console
relay after one message and would have made KILL refuse it.
Relay of four lines to a WIREBIND identity on all three ISAs, five
hot-plugged identities, and standard acceptance (POST 1052, hash
0x08873e0f44b7cb2a) all pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checked against a scratch artemis.img, Zuse drive and five identity drives
minted together at a live prompt; the committed images are all blank since
e56974e0 and cannot show the gap either way. No code change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FABRIC-3.md XXXIV.1, traced and fixed. vm_interpret() copied each text
into the VM's one input buffer and reset the position. LOAD runs its
block by calling it, so the block replaced the line LOAD was on and
nothing after LOAD or THRU on that line was ever interpreted; the same
for -->, a capsule's EXEC and a message kernel-Hermes delivers.
vm_interpret() now keeps what the outer text had not yet read when it is
called from inside another, and puts it back after, as FORTH-79's LOAD
keeps the input stream it interrupts. In the kernel's VM and the hosted
one alike.
POST: LOAD.rest_of_line (1 LOAD 0 0 /) and THRU.rest_of_line
(1 2 THRU 0 0 /) failed without the fix (logs/20261014-061222) and pass
with it. Three-ISA acceptance: logs/20261014-061508 (amd64), -061624
(aarch64), -061837 (riscv64), 1052 tests, none failed, zuse prompt,
hash 0x08873e0f44b7cb2a unchanged. The hosted binary: 100 LOAD 1 + .
gives 8.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built with EMERGENCY_CONSOLE_ENABLED=1 and booted with no identity logged
in, the prompt printed "ok> ok" without end, 1.4 million times in 200
seconds (logs/20261013-210442). sk_console_readline() gave up at once
whenever no identity was present. The production build answers that by
going silent until a login; the bring-up build, which needs no login,
took it as an empty line and asked again. The give-up is now the
production build's only.
Found rehearsing boards/BRINGUP.md; it predates the console change of
c9519173 (the image built from the commit before that did the same).
The riscv64 bring-up build, no thumbdrive, three lines typed
(logs/20261013-235129): one prompt that waits, and 3, 56 and 81.
Acceptance of the production build, one QEMU at a time: amd64
(-235255), aarch64 (-235411), riscv64 (-235620) to the zuse prompt, no
unknown word, hash 0x08873e0f44b7cb2a on all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each board has one serial line that is its console, the lowest common
denominator beside the screen and keyboard. Its address was QEMU's,
fixed: on a Raspberry Pi 5 the aarch64 one is ordinary RAM, written to
with every character printed; on a Milk-V Mars the riscv64 one is the
board's UART with registers four bytes apart, and the UEFI loader would
have waited for ever on its first character; on a PC with no COM1 the
prompt read 0xFF for ever.
console_attach_serial(), called before anything prints: COM1 if a UART
answers there; elsewhere the UART that /chosen/stdout-path names
(fdt_uart.c: alias, path, the address carried up through each bus's
ranges, reg-shift and reg-io-width); with no devicetree, QEMU's. A
devicetree that names no usable console gives no line, not a guess. A
line that does not come ready is given up, not waited on. The riscv64
loader's early serial does the same.
tools/fdt_uart_test.c, run by hand, 19 checks plain and under the
sanitizers: devicetrees shaped like the Mars's, the Pi 5's and QEMU's,
what must find nothing, and a block cut short at every length; and the
Pi 5's real devicetree gives a PL011 at 0x107d001000.
Acceptance, one QEMU at a time: v3 on amd64 (logs/20261013-204436),
aarch64 (-204803) and riscv64 (-205001) to the zuse prompt, no unknown
word, hash 0x08873e0f44b7cb2a on all three as before. -204600 is an
aarch64 run during which the disk images were restored under it by a
script that had been refused a second QEMU; it passed and is kept, and
was run again. v4 on the three ISAs (-211149, -211444, -211857): POST
538 of 538, dict_hash 0xe5a57f3eb72ff94a, the typed session unchanged.
The Mars image through OpenSBI and U-Boot in QEMU took its line and its
interrupt controller from the devicetree and passed POST.
Found on the way and not mended (boards/BRINGUP.md 1.6): built with
EMERGENCY_CONSOLE_ENABLED=1 the prompt floods with empty lines. -210442
shows it; the commit before this does the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What to do on the day a board is on the bench: media, cabling, what to
watch for, what counts as a pass, what to keep. Written before any board
has been booted.
Section 1 lists what was found in the code while writing it, none of it
fixed: the USB controller driver matches QEMU's controller only; the
production build shows no prompt without a thumbdrive login; there is no
USB keyboard driver and no disk driver but virtio; on the Pi 5 the console
writes every character to QEMU's UART address, which is RAM there; on the
Mars the console's UART register layout is probably not the board's; the
board images cannot build the v4 node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The final review of step 6e, by a fresh reviewer told to break it, and
what was ruled: fix them all, test first. Each has a test that failed
before the mend.
- Two texts from one node could be begun in the wrong order when room
for their answers came between the node's look at the first and at the
second. Texts whose answers go by the same port are begun in the order
they came: (D-MASK), quit.v4. 102 of 700 timings were wrong before.
- A word written with PORT! to a node that speaks whole messages, or to
a console's port, blocked its writer for ever and cut off every node
beyond it. It is error 18 now, whether that node is asleep, running
or stuck: fabric.c, node.c.
- A node asleep for room on one wire is woken when another of its wires
is cut.
- A line there was no room for on the lone node's wire was reported as a
fault and ended the hosted program. It is Message refused, and the
prompt comes back: V4_BOOT_LINE_REFUSED. hosted-check has the case;
no bare-metal boot has typed it.
- Ruled: text behind held output for the same port is refused though it
would fit. MESH.md 7d.4 said otherwise and is corrected.
- The removal test also cuts and re-makes a wire, and has an exchange in
which output is held at a full wire: 26,814 disturbances in all.
- MESH.md and v4/README.md no longer say that a stuck node holds up no
other node, that only printing waits, or that no node is left waiting
on one that is gone; 7d.6 lists the limits and what the products do
that they did not before.
make -C v4 test and sanitize at both widths, hosted-check, lint. Three
bare-metal boots: logs/20261013-194827 (amd64), -195131 (aarch64),
-195518 (riscv64). POST 538 of 538, word_count=317,
dict_hash=0xe5a57f3eb72ff94a on all six; the three sessions are the same
character for character. The boots were built with the working tree's
uncommitted change to kernel/Makefile that adds the ISA to the kernel's
version line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_host_mesh.c, 220 checks: three exchanges on the row of three -- text
from the console for node 12 with what it prints and how it ended; node 11
SENDing node 12 text and waiting for its answer; a message node 12 has no
way for and its NACK to node 10 -- are each played once for every engine
step they take with node 11 removed at that step, and again with node 12:
17,642 removals at 64 bits. Every node left comes to rest asleep, blocked
at no port and in no operation, and answers. What is typed is a word
defined beforehand, so that the steps are the exchange's and not the
dictionary being searched.
Removed from the engine, nothing using them: v4_fabric_interrupt_error, a
device's pending hook, v4_node_words_since_look, V4_ERROR_INTERRUPTED.
MESH.md: 4.1's table has the addresses after the ports; 7a and 7b say what
of them still holds; 7b.7's limit is closed; step 6e is written up.
v4/README.md likewise.
make -C v4 test and sanitize at both widths, hosted-check, lint. Three
bare-metal boots with the typed session and a loop printing 400 numbers:
logs/20261013-165124 (amd64), -165428 (aarch64), -165818 (riscv64). POST
538 of 538, word_count=317, dict_hash=0x0951d7e02e251554 on all six, and
the three sessions are the same character for character. The boots were
built with the working tree's uncommitted change to kernel/Makefile that
adds the ISA to the kernel's version line; nothing else differs from this
commit.
The plan's final review is not done yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-root stale references to actual locations: (shared engine/hosted) and (LithosAnanke). Update source tree diagram accordingly, correct / counts, and remove the obsolete bullet. Also fix include paths (, ).
Surgical correction only; no behavioral changes.
- docs/lithosananke/README.md + ROADMAP.md: correct branch topology (no
lithosananke branch post-split; master is the sole line), mark M7.1 as
live, and fix build commands (kernel/Makefile, not Makefile.starkernel)
- docs/README.md: refresh current active work (Tripod = Hera/Artemis/Hestia,
M7.1 live, StarForth v4) and flag INDEX.md as stale
- docs/INDEX.md: add dated-snapshot staleness banner
- Add TARGET-HAL / OBSOLETE / SUPERSEDED banners to stale HAL, physics,
heartbeat, and DoE docs under docs/working/ (annotation only, no deletions)
- Engine: a wire keeps whether the message at its mark is the one last
looked at; a node's take, move and drop of any other answer 3 and write
nothing (MESH.md 7d.3). A wire cut and made again between a look and a
take no longer has a NACK done as text, or 256 cells written where one
was looked for.
- Engine: v4_fabric_wire_kernel wires a kernel to a port with no queues;
a message for it is refused at once, error 18, on a mesh as on the
products.
- The result of a drop is looked at; a take that does not take has the
message dropped, or gone past: nothing goes round.
- An answer nobody waits for is let go uncounted; (LOST) counts what should
have been delivered or acted on and was not. The flood's account is
exact.
- Error 18 from under a word that was printing empties the data stack, as
a fault does: that word's own values are not left there.
- Tests: the take and drop windows cut at every step, with and without
another message put; a refusal owed to a stuck node whose wire is full.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>