210 Commits
Author SHA1 Message Date
rajamesandClaude Opus 5.5 a73580e949 feat(v4): the machine boots from its ROM; the prebuilt nucleus is gone
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>
2026-10-15 14:26:02 -04:00
rajamesandClaude Opus 5.5 1bf19d6224 feat(v4): the ROM assembles the system's .f18 to the nucleus, word for word
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>
2026-10-15 12:27:50 -04:00
rajamesandClaude Opus 5.5 084c520a54 feat(v4): the ROM assembles text as text.c does -- words, labels, macros, FOR, directives, start
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>
2026-10-15 12:24:08 -04:00
rajamesandClaude Opus 5.5 c233cb6536 feat(v4): the ROM's slot packer, word for word with asm.c
(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>
2026-10-15 11:58:47 -04:00
rajamesandClaude Opus 5.5 07911dcf91 feat(v4): the ROM's symbol table
(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>
2026-10-15 11:54:15 -04:00
rajamesandClaude Opus 5.5 080811dbd2 feat(v4): the ROM reads numbers as text.c does
(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>
2026-10-15 11:49:46 -04:00
rajamesandClaude Opus 5.5 0f82d8c22a feat(v4): mkrom -- the ROM built off the node; it reads tokens
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>
2026-10-15 11:49:05 -04:00
rajamesandClaude Opus 5.5 32753f5479 feat(v4): the machine has a ROM -- read and run, never written
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>
2026-10-15 11:25:24 -04:00
rajamesandClaude Opus 5.5 42f8a13914 docs(v4.0.0): the ROM is shared code, GA144-style -- an entry table, a permanent state area
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:10:08 -04:00
rajamesandClaude Opus 5.5 1ed56b93b4 docs(v4.0.0): DATASHEET-F18.md -- the machine: registers, stacks, memory, instruction word, opcodes, control unit, faults, I/O
As built in the golden model (v4/src), with what is not yet as intended listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:20:25 -04:00
rajamesandClaude Opus 5.5 952df0f44a docs(v4.0.0): plan for MACHINE.md steps 1-2 -- the ROM, and the .f18 trailer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:01:54 -04:00
rajamesandClaude Opus 5.5 d0b0eee54b docs(v4.0.0): MACHINE.md -- what it is for: a multi-user, multitasking OS that init.4th brings up
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:52:47 -04:00
rajamesandClaude Opus 5.5 884721783a docs(v4.0.0): MACHINE.md -- forth79.4th names all 130 words; init.4th is the system's init
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:50:18 -04:00
rajamesandClaude Opus 5.5 528bed0874 docs(v4.0.0): MACHINE.md -- rulings: the VM is a machine; .f18 pretty-printed text; v3 deleted at parity; the whole system loads before POST
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:46:56 -04:00
rajamesandClaude Opus 5.5 3eca84e433 docs(v4.0.0): MACHINE.md -- the ROM is whatever size it takes; not a question
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:43:42 -04:00
rajamesandClaude Opus 5.5 e429d30a7e docs(v4.0.0): MACHINE.md -- the three .4th layers: forth79.4th (100 percent FORTH-79), starforth.4th, anything else
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:41:15 -04:00
rajamesandClaude Opus 5.5 58f3837498 docs(v4.0.0): MACHINE.md -- the machine, its ROM, and the capsule: one prebuilt F18 binary, the rest source
For review; nothing built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:35:38 -04:00
rajamesandClaude Opus 5.5 c7bf68fe13 build: source SBOM regenerated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:22:34 -04:00
rajamesandClaude Opus 5.5 3b49cb15a2 boards: the amd64 target is PC -- a generic x86-64 UEFI PC, not the SER5
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>
2026-10-14 17:22:32 -04:00
rajamesandClaude Opus 5.5 1ce8576b76 build: source SBOM regenerated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:21:14 -04:00
rajamesandClaude Opus 5.5 79db0e8d88 build: v4 is the default build -- every kernel boots v4; acceptance is v4 on three ISAs and the 32-bit build
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>
2026-10-14 17:21:13 -04:00
rajamesandClaude Opus 5.5 7bc658bb83 build: the source SBOM, regenerated -- 809 files with their SHA-256
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:58:11 -04:00
rajamesandClaude Opus 5.5 fcb89b0695 build: an SPDX SBOM with every board image, and of the source tree, by syft
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>
2026-10-14 16:58:10 -04:00
rajamesandClaude Opus 5.5 f8fbc37698 docs: the 12 duplicates deleted; README rewritten to the system as it is
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>
2026-10-14 16:45:39 -04:00
rajamesandClaude Opus 5.5 776c89457e docs: the map, a fresh index, and a register of dead ideas and revised claims
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>
2026-10-14 16:06:59 -04:00
rajamesandClaude Opus 5.5 7aed588f78 docs: reorganise -- current reference gathered, finished work archived, superseded and dead ideas marked as such
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>
2026-10-14 16:03:56 -04:00
rajamesandClaude Opus 5.5 1a4b163861 feat(boards): both systems on every board image, chosen at boot -- system=v3 or system=v4
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>
2026-10-14 15:11:47 -04:00
rajamesandClaude Opus 5.5 e729c64ba3 feat(usb): every xHCI controller is driven, not only the first
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>
2026-10-14 14:27:38 -04:00
rajamesandClaude Opus 5.5 739cb9c163 feat(usb): a USB keyboard -- a full one -- and no hang on a PC without PS/2
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>
2026-10-14 14:04:33 -04:00
rajamesandClaude Opus 5.5 080b7012ba fix(usb): the xHCI controller is found by class on any bus, sized, taken from the firmware, and 64-byte contexts laid out
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>
2026-10-14 13:30:50 -04:00
rajamesandClaude Opus 5.5 0e2c60dac3 fix(raspi): the Pi 5's native path turns the MMU and caches on before any C; bounded mailbox; framebuffer address from dma-ranges
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>
2026-10-14 12:58:35 -04:00
rajamesandClaude Opus 5.5 4da370f492 feat(log): LOG-FLUSH -- a VM's log records reach Artemis's log ring; and the ring keeps its order when it grows
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>
2026-10-14 12:10:01 -04:00
rajamesandClaude Opus 5.5 5e26fad30d fix(security): no VM but Artemis and Hera can make Hera run text; a message runs once; word-ACL elevation removed
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>
2026-10-14 11:38:23 -04:00
rajamesandClaude Opus 5.5 029a8ed9cf fix(hermes): one delivery path -- a VM takes its own messages on its own turn, never on another's stack
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>
2026-10-14 10:37:57 -04:00
rajamesandClaude Opus 5.5 b7e8e4b058 docs(fabric): §XIV no longer reproduces -- five minted drives attach at power-on and hot-plugged a second apart, all three ISAs
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>
2026-10-14 08:48:03 -04:00
rajamesandClaude Opus 5.5 c15589b39e fix(vm): a text run from inside a line no longer takes the line's place -- LOAD and THRU go on with the rest of it
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>
2026-10-14 06:19:54 -04:00
rajamesandClaude Opus 5.5 9772ee8b68 fix(repl): the bring-up build's prompt waits for a line instead of answering itself without end
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>
2026-10-13 23:57:29 -04:00
rajamesandClaude Opus 5.5 c95191736e fix(console): the serial line is found, not assumed -- from the devicetree on a board, COM1 by probe on a PC
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>
2026-10-13 21:21:32 -04:00
rajamesandClaude Opus 5.5 f4e359859a docs(boards): bring-up checklist for the four boards, and what stands between today and a first boot
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>
2026-10-13 20:22:30 -04:00
rajames 010cfc54e6 my shit 2026-10-13 20:20:49 -04:00
rajamesandClaude Opus 5.5 66b26f823c fix(v4.0.0): step 6e final review -- texts begun in order; a word no one will read lets its writer go; a cut wire wakes a wait for room; a full console wire is a refusal, not a fault
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>
2026-10-13 20:02:33 -04:00
rajamesandClaude Opus 5.5 06da5700bc feat(v4.0.0): step 6e -- a node removed at any step leaves the rest at rest; written up
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>
2026-10-13 17:47:05 -04:00
rajames ab96a9f2be docs: fix stale path references in .claude/CLAUDE.md
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.
2026-10-09 19:34:30 -04:00
rajames 2e6262c91f docs: update stale entry docs and deprecate superseded docs with annotations
- 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)
2026-10-09 18:21:10 -04:00
rajamesandClaude Opus 5.5 f1419e739c fix(v4.0.0): step 6e review round 2 -- only the message looked at is taken, moved or dropped; the kernel's port has no queue in a fabric; an answer nobody awaits is not a loss
- 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>
2026-10-08 22:36:59 -04:00
rajamesandClaude Opus 5.5 6a7d0aa27f fix(v4.0.0): step 6e review round 1 -- a take that does not take does nothing; output and answers wait at a middle node; no queue on the kernel's port; a printing wait is not interrupted
- The result of every take is looked at: a wire cut between the look and
  the take leaves nothing acted on (the text before run again, a refusal
  counted, a wait ended by an old answer, a way forgotten).
- A node with no room to pass on what another printed, or its word of how
  text ended, leaves it on the wire it came by and moves it when there is
  room; what is behind it for the same port waits too.  Sleep for room (9)
  is woken by room on any of the node's wires (engine; MESH.md 7d.3).
- The lone node's host keeps no queue for the kernel's port: a message to
  it is error 18.  The step limit is counted while the node waits for room.
- A text waiting for room to print is not interrupted by console text;
  AWAIT is, as before.  (BREAK?) is gone.
- A GONE is believed only by the centre's port; unawaited answers let go
  are counted; nothing past a message's last character goes on a wire;
  AWAIT sets (AWAIT-FROM) only once the stack has been tried.
- test_host_depth.c: ten paths, each run works or ends in one named stack
  error; it fails with (ROOM) or (ROOM-SERVE) taken out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:01:11 -04:00
rajamesandClaude Opus 5.5 b1d09af043 feat(v4.0.0): messages are whole and wait on the wire -- a node keeps none but the one it is doing
Step 6e, tasks 2 and 3 (docs/v4.0.0/MESH.md 7d).  The nucleus puts, looks
at, takes, moves and drops whole messages through the six addresses after
its ports; its own ring of messages waiting, the refusals owed, (GATE) and
the looking words' use are gone.  SEND, an answer, a NACK and a GONE go or
are refused at once; what a text prints waits for room; a text is not
begun until the wire its answer goes by has room for it, and that room is
kept.  The lone node's host (v4/system/boot.c) keeps its two wires and
does its operations; the test hosts' consoles put and take whole messages
through the fabric.  New: tests/test_host_depth.c, every message path of
a mesh node at every depth of both stacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:59:37 -04:00
rajamesandClaude Opus 5.5 83694b18be fix(v4.0.0): wire review round 1 -- tests for the wake-up order and for waking only on enough room; no overflow moving a message; sleep for impossible room answers at once
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:12:33 -04:00
rajamesandClaude Opus 5.5 d5cd64605d feat(v4.0.0): the wire in the engine -- whole messages, put and taken in one step
Queues of whole messages on the wires between nodes (v4/wire.h), the six
addresses and ten operations a node asks of the fabric (MESH.md 7d.3), and the
fabric's pool of queues. Engine only: the nucleus does not use any of it yet.
The ports in the host map move to BUF0_W - 140 so that the new addresses are
not among the nucleus variables, with a compile-time check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:50:15 -04:00
rajamesandClaude Opus 5.5 50be766e7b chore: ignore .directory; track the bare-metal run files of 3 to 8 October
One doe-<arch>-<time>.csv is written by each QEMU boot; the 96 from the
boots of steps 6 to 6d were untracked.  Committed so that the tree is
clean before step 6e begins: this commit is its rollback point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:13:48 -04:00
rajamesandClaude Opus 5.5 88554666d4 docs(v4.0.0): step 6e -- the plan; a mark on each wire, a sleep woken by a message coming, and the room probe
MESH.md 7d.3 amended while the plan was written: first and next in place
of find by type; sleep is woken by a message coming, not by one being
there; operation 10, room.  7d.4: room for a text's answer is kept on
the wire back.  7d.9: a ping across hops, thought about and not ruled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:58:13 -04:00
rajamesandClaude Opus 5.5 7eb545f387 docs(v4.0.0): step 6e -- messages on the wire: the second attempt at the wait
MESH.md 7d: the rulings, the wire, what a node asks of the fabric, the
nucleus, the products, the limits, the acceptance, and the later step of
keeping the wires in the system's blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:47:55 -04:00
rajamesandClaude Opus 5.5 8967c93241 docs(v4.0.0): the root causes behind the wait's faults, and the boots of the code that mends them
MESH.md 7c.7: the stacks doubled in scratch and each path measured -- the
size was never the cause; EMIT's overrun of the output buffer, and a
message's first word moving before there was room for the rest; what is
left for a second design; the depth sweep.

Three bare-metal boots of 0d91608f typing the deep-stack lines: POST 538
of 538, word_count=317, dict_hash=0x3629660aa2dc6823 on all six.  Three
earlier amd64 boots of the same code, whose typed session was wrong, are
kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:25:19 -04:00
rajamesandClaude Opus 5.5 0d91608f39 fix(v4.0.0): EMIT ran past the output buffer; a message's first word was read before there was room for the rest
The two root causes behind what the reviews of the wait found, both in
the code as it stands.  Each with a check that failed first.

EMIT stored its character and only then looked whether the buffer was
exactly full.  A flush that ended in a fault -- the stack too deep to
begin a message -- left the buffer full, and the fault's own message was
then put past its end, with (OUT^) never again at the end to be flushed.
The 28 cells after the buffer happen to be unused, so nothing showed;
the wait had put the ports there, and the node blocked writing to one.
EMIT now sends a buffer it finds full before it stores.

AWAIT, and (GATE) when a neighbour is writing, read a message's first
word and then used stack that was not known to be there.  With 27 or 28
values on the stack, or 28 or 29 calls deep, a line typed during AWAIT
was taken and never answered.  (ROOM) tries six cells and four return
entries first: if they are not there the text ends 'Stack overflow' with
nothing read.  (GATE) tries the three cells its writing needs before a
first word goes; it was safe before only by the order things were done.

v4/tools/depthsweep.py runs every message path of the hosted product at
every depth of both stacks: each line typed must be answered and the
node must come back.  hosted-check runs it.

make -C v4 test and sanitize at both widths, hosted-check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:46:05 -04:00
rajamesandClaude Opus 5.5 6015c87157 revert(v4.0.0): step 6d, the wait, is backed out -- two reviews found it unsound
Ruled 2026-10-08.  The engine, the nucleus and their tests are as they
were at dfabfa46, before step 6d; the code of the wait and its tests are
in history at 075385ab..2cf37aab.  The limit of MESH.md 7b.7 stands: a
node that is stuck can hold up its neighbours until Hera kills it.

MESH.md 7c is kept as the record of the design as approved, and 7c.6 says
what was built, what the two reviews found, the cause the findings share
-- a node's message machinery runs on the stacks its text is using, and a
fault abandons whatever was in progress -- and what a second attempt
must settle before anything is built.

Kept from it, in hosted-check: a line that leaves 29 values on the stack,
and WORDS with 26 values on it.  Both hung the products at some commit of
the wait.

make -C v4 test and sanitize at both widths, hosted-check, lint; three
bare-metal boots typing both.  POST 538 of 538, word_count=317,
dict_hash=0xc0769523a47b7dc3 on all six: the hash of step 6c's code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:31:40 -04:00
rajamesandClaude Opus 5.5 10f5ffd00b docs(v4.0.0): step 6d as mended after its review; the boots on that code
MESH.md 4.1, 7a, 7c.2, 7c.3, 7c.4 and step 6d say what the code now does,
what the review found and how each was mended, and what is small and not
mended.  The README no longer says the aim is unmet; it says the mended
code has not been reviewed again.

Three bare-metal boots on 2cf37aab, typing 29 values on a line: POST 538
of 538, word_count=317, dict_hash=0xd41a6ac9448fff60 on all six.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:44:12 -04:00
rajamesandClaude Opus 5.5 2cf37aab4f fix(v4.0.0): step 6d after its review -- no error in the middle of the messages waiting, no offer left standing
Ruled 2026-10-08: A, B, C, D and the guard for a half message.  Each with
a scene in test_host_mesh.c that failed first.

A. The words of a message after its first are written from the passes
   over the messages waiting by (!W): an offer and a wait for that offer
   only (a new engine address).  A reader removed in mid-message makes no
   error; the rest is let go and counted.  Before, the error left the
   messages waiting in pieces and the node going round for ever.
B. A store to the wait withdraws every offer; (GATE1) and (PAY-SET) do it
   first.  Before, text begun after a node went round without sleeping
   could go to the port of an older offer: text for one node was done by
   another.
C. What a finished text printed is put with the messages waiting, as how
   it ended is.  With no room either is let go and counted; neither is
   begun as a message from (FINISH) any more, where a stuck node on the
   way held the whole node.
D. Only what a sender is owed from an earlier text -- its output, how it
   ended -- holds that sender's next text back; a GONE does not; and what
   cannot be noted holds nothing.  A node's own messages keep the order
   they were made in.
-  A message half taken in when its writer is removed is let go
   ((MQ-MEND)), not kept as if whole.
-  Smaller: a refused line no longer ends a waiting text 'Interrupted';
   a node's own queued messages may be passed on by 16 nodes, not 15; no
   value is left on the stack when a port goes in mid-refusal.

make -C v4 test and sanitize at both widths, hosted-check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:34:15 -04:00
rajamesandClaude Opus 5.5 380f1cc6ec fix(v4.0.0): 29 values left on the stack hung the node; and what the review of step 6d found
The review of step 6d found it not sound.  Mended here, with a check
that failed first: a text that left 29 values on the stack hung the
node for ever, on the products too -- the passes over the messages
waiting that follow every text need four cells, and a stack fault in the
middle of one left the messages in pieces.  Such a text ends 'Stack
overflow', as before step 6d.  hosted-check types it.

The other findings are open and are written under step 6d in MESH.md
section 10; the README no longer says the aim is met.

make -C v4 test and sanitize at both widths, hosted-check.  The bare
metal boots have not been made again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:59:28 -04:00
rajamesandClaude Opus 5.5 2b587206ee feat(v4.0.0): the wait replaces looking and the console release; step 6d written up
The engine's console release (v4_fabric_interrupt_error), a device's
pending, and the count of words since a look are removed: nothing uses
them.  MESH.md 4.1, 7b and 7c say what was built, where it differs from
what was approved and why, and what is still a limit; step 6d is marked
built, with the defects found on the way.

make -C v4 test and sanitize at both widths, hosted-check, lint; three
bare-metal boots.  POST 538 of 538, word_count=317,
dict_hash=0x6a39c0bb9d183418 on all six.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:24:09 -04:00
rajamesandClaude Opus 5.5 ec817a8264 fix(v4.0.0): a waiting node goes on passing on and paying; KILL is not held by a stuck node
Found in the five-node test, each with a check that failed first:
- A node with answers it could not give to two stuck senders began no
  text at all.  It now holds back only text from a sender whose own
  answer is still with it.
- KILL waited to tell a stuck node, and a typed line that broke it left
  the nodes after it untold.  GONE is put with the messages waiting, as
  how text ended is, and goes when it can.
- So that 'tell, then wait' still works, AWAIT does what (IDLE) does but
  for beginning text: it looks through the messages waiting, offers what
  is to be passed on and what is owed, and sleeps in the wait.  A waiting
  node no longer keeps back what passes through it.
- A node in the wait with an offer on a port that turns out to have
  nothing on it is woken and told so (which port: 2 * V4_PORTS + k); no
  error is raised on it.  (GATE) makes it error 18; (IDLE) and AWAIT let
  the message go.  Before, removing a node raised 'No one on that port'
  on the unrelated text of a neighbour that had something queued for it.

make -C v4 test and sanitize at both widths, hosted-check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:00:33 -04:00
rajamesandClaude Opus 5.5 353783726d fix(v4.0.0): a node's answer goes before its sender's next text -- the last commit failed hosted-check
1c720ab2 was committed with hosted-check failing: with how text ended
queued, a line typed while the node waited was done before the earlier
line's answer had gone, and the pass that offers what is to be passed on
let go text that was for the node itself.

How text ended is put before the other messages waiting; a node does not
begin another text from a sender while its answer to that sender is
still with it; and what is for the node itself is not offered.

make -C v4 test and sanitize at both widths, hosted-check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 00:07:41 -04:00
rajamesandClaude Opus 5.5 1c720ab2c7 fix(v4.0.0): what a node passes on waits with it, offered -- a relay is not held by a stuck node
Found after the last commit: a message being passed on toward a node that
was stuck held the node passing it on in the wait, taking in what came
but serving none of it; text typed for a stuck node left Hera deaf.  And
a node that had done text for a sender that then stuck waited on it to
give its answer.

A node with nothing to do now deals first with what is for itself; then
offers at once the first message for each port and each refusal owed,
and sleeps in the wait.  What is taken is written and done with; the
rest stays with the messages waiting, in order.  How text ended is put
with the messages waiting, not written from (FINISH).  The stack is kept
as shallow between lines as it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:51:30 -04:00
rajamesandClaude Opus 5.5 482cc75faf feat(v4.0.0): every message begins through the wait -- a stuck node holds up no one
(GATE) offers a message's first word and sleeps until it is taken, taking
in whatever is written to the node meanwhile; (PAY) offers every refusal
owed at once, one to a port; a node that owes one sleeps in the wait.
Writing without looking, looking again and again, and the lower-number
rule are gone.  Text from the console for a node whose own text waits to
begin a message ends that text Interrupted.  The lone node's hosts serve
an offer as a write.  MESH.md 7c; plan step 6d task 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:38:07 -04:00
rajamesandClaude Opus 5.5 075385ab63 feat(v4.0.0): the wait in the engine -- a node offers a word and sleeps
A node stores a word to offer on any of its ports and fetches the wait: it
is blocked until a word comes for it or one of its offers is taken, and
the fabric does the handing over in one step.  The port block moves in
the nucleus's map to make room for the new addresses.  Nothing uses it
yet.  MESH.md 7c; plan step 6d task 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:15:11 -04:00
rajamesandClaude Opus 5.5 dfabfa46f6 docs(v4.0.0): step 6d -- the plan; and the wait offers on each port, not one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:27:21 -04:00
rajamesandClaude Opus 5.5 5150155281 docs(v4.0.0): step 6d -- the wait: rulings, engine, nucleus, limits and acceptance
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:24:12 -04:00
rajamesandClaude Opus 5.5 59727f762a fix(v4.0.0): step 6c mended after its review -- what a stuck or gone node can and cannot hold up
The review of step 6c found it did not keep its rule.  Ruled: fix them
all; 16 hops.

- Paying a NACK no longer waits on a lower-numbered neighbour; a node
  that owes one does not sleep, and goes on taking in what it is sent.
- AWAIT looks first through the messages already waiting.
- A node waiting to write to a removed neighbour gets error 18: the
  word that says who is reading also says which ports have anything on
  them.
- A console line lets Hera go when she is blocked on the first word of
  a message (v4_fabric_interrupt_error, a device's `pending`).
- A refused answer is told to the node that waits, not the one that
  answered; one owed to the node itself goes to its own queue.
- A message is passed on by at most 16 nodes, then refused.
- A GONE is believed only when it says it is from the node's centre.
- Tests: the check that tested nothing is replaced; no room for a
  waiting sender; the limit that remains is tested as a limit.
- MESH.md 7b's rule reworded to what holds, 7b.7 says where it falls
  short; README likewise.

make -C v4 test, sanitize, hosted-check; three bare-metal boots.  POST
538 of 538, word_count=317, dict_hash=0xc0769523a47b7dc3 on all six.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:18:06 -04:00
rajamesandClaude Opus 5.5 d343001dea feat(v4.0.0): refusals and waits on bare metal, and step 6c written up
The bare-metal host hands a waiting node the next line typed, as the
hosted one does: 5 AWAIT, then 7 8 * . -- Interrupted, then 56.

amd64, aarch64 and riscv64 boot, POST 538 of 538, word_count=317,
dict_hash 0x54520ade672566ad, the same as the three hosted programs:
logs/20261007-202737, -203230, -203616.

MESH.md step 6c: what was built, how it was verified, and two things
found on the way that are not mended and are for ruling: Hera blocked
writing to a stuck node, and a message that can go round for ever between
two nodes whose ways disagree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:38:20 -04:00
rajamesandClaude Opus 5.5 ee2bbf4ecf feat(v4.0.0): Hera kills a node by number and tells the others it is gone
Hera keeps a table of the nodes she has had born, number and place.
KILL ( n -- ): she asks the kernel to remove node n, forgets her own way
to it, and sends GONE about it to every other node in the table.  A node
she never had born, herself, or one she has killed already is an error
that says so, and nothing is removed.  v3's word and meaning; v3's takes
a name, and a mesh node has a number.

test_host_unit.c, 74 checks: Hera kills node 14 while node 12 is blocked
writing to it, and what 12 then sends there is refused; node 12 waits on
node 13, stuck in a loop and not its neighbour, and the wait ends Node
gone when Hera kills 13; Hera waits on node 12, stuck, and a line typed at
the console ends her wait Interrupted and then kills 12.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:27:06 -04:00
rajamesandClaude Opus 5.5 cbe1cd5e44 feat(v4.0.0): a line from the console breaks a wait
Text for a node from its console, arriving while the node waits for an
answer (AWAIT), is kept as any message is; the wait ends in error 21,
Interrupted; and the text is then done as usual.  Console text for
another node, passing through a node that is waiting, does not end its
wait.

On the hosted program 5 AWAIT ended the program with "the node stopped".
The boot now reports that the line is waiting, the host reads the next
line and hands it over, which breaks the wait, and then has the kept line
done.  The bare-metal host does the same; it is booted in the commit that
follows.

test_host_mesh.c: 76 checks, both widths and the sanitizers.  hosted-check
types 5 AWAIT and two more lines: Interrupted, then 3 and 56.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:16:58 -04:00
rajamesandClaude Opus 5.5 9efe8aad3a feat(v4.0.0): a refused message is told to its sender -- NACK and GONE
A node that has no room for a message, or no way to pass it on, lets it
go and counts it as before, and now notes that it owes its sender a NACK
(type 4: the node the message was for).  It sends what it owes when it
next has nothing else to do.  36 cells of the messages waiting are kept
for NACK and GONE, and nothing is owed for either.

A node sent a NACK counts it in (REFUSED); one waiting for an answer from
that node (AWAIT) stops, with error 19, Message refused.  A GONE (type 5)
from a node's centre makes it forget the way to the node named (NO-ROUTE,
new), and ends a wait on it with error 20, Node gone.  From anyone else
it is ignored.  GONE ( n node -- ) sends one.

test_host_mesh.c, three nodes: text for a node nobody has a way to comes
back to the console, and to a node two away, as a NACK; a waiting sender's
line ends Message refused; a node that is waiting keeps what it has room
for, owes eight refusals, counts the rest, and sends them when its wait is
ended by a GONE from its centre.  70 checks, both widths, sanitizers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:58:27 -04:00
rajamesandClaude Opus 5.5 6e1ac157c6 docs(v4.0.0): step 6c -- refusals and waits: rulings, design, acceptance and plan
MESH.md 7b: no message is lost without its sender being told, and no
node waits for ever.  What v3 does, from the code, and what could not be
established.  A refusal travels back as a NACK; Hera ends a wait on a
stuck node by killing it and tells the others it is gone; a line from the
console breaks a wait.  Step 6c has the acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 19:43:43 -04:00
rajamesandClaude Opus 5.5 a425f738a4 fix(kernel): the block chain's fast RAM is cleared on the v3 path
It came from kmalloc, which does not clear what it hands out; only the
ramdrive beside it was cleared.  A VM's BLOCK on blocks 0 to 2047 read
whatever had been in the kernel's heap.  The v4 path already cleared its
own.

Accepted on the v3 configuration: amd64, aarch64 and riscv64 reach the
zuse prompt, no UNKNOWN WORD, PARITY:M7.1a hash 0x08873e0f44b7cb2a on all
three, as before.  logs/20261007-140609, -140735, -140946.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:10:49 -04:00
rajamesandClaude Opus 5.5 193523d873 fix(v4.0.0): three defects -- a refused device write, a failed starting state, a case that QUITs
A block write the device refuses after the kernel has taken the node's
copy: the node was told "Storage refused" while the kernel's cache kept
the new data, to be read back and perhaps written later.  The kernel now
puts its own copy back as it was.  Tested with a device whose writes can
be made to fail; it failed first.

POST's runner: a case whose starting state could not be set says so, with
what the node said, where it showed nothing; and a case that ends with
QUIT fails, as it did when the cases were a capsule, where the runner had
taken it for a completed line.  Both tests failed first.

The v4 boot says "Artemis: virtio-blk attached" only when the attach
worked.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, dict_hash 0x5f0a949a6fc8ef2b on all six:
logs/20261007-135741, -140004, -140329.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:05:14 -04:00
rajamesandClaude Opus 5.5 bc6deab3f5 fix(v4.0.0): a node blocked at a port with no one on it is given an error, not left there
A node writing to a node that was stuck, and was then killed, stayed
blocked for ever: killing a stuck node could cost its neighbours.  And on
the hosted and bare-metal products a write to an empty port, 5 7 PORT!,
ended the program with "the node stopped".

Now a node that can take an error, blocked writing to or reading from one
port that nothing is wired to -- nothing ever was, or what was there has
been killed or the wire cut -- has error 18, No one on that port, raised
on it and goes on.  A bare node waits as on the fabric; so does a node
whose neighbour is asleep, and one reading "any port".

test_host_unit.c: Hera kills node 14 while node 12 is blocked writing to
it.  It failed first: 12 stayed blocked.  test_fabric.c: a bare node still
waits.  hosted-check types 5 7 PORT! and goes on; it failed first too.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, dict_hash 0x5f0a949a6fc8ef2b on all six:
logs/20261007-121743, -122008, -122337.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:25:35 -04:00
rajamesandClaude Opus 5.5 18adf59091 fix(v4.0.0): POST leaves nothing, as v3 really does; and what the review of step 6b found
Captain Bob was told that v3 leaves the words POST's cases define in the
dictionary, and ruled that v4 should.  That was false: v3's run_test_suite
puts the dictionary back after each word's cases (test_common.c:333,
:365).  Shown that, he ruled that POST leaves nothing.  The boot now
seals the system, runs POST, and has the node do COLD, whose printing is
not shown; PARITY:V4_SYSTEM is the system as sealed.

A case the node does not come back from ends POST there, named, with how
many were not run: it would have stalled the boot for hours, where the
capsule had ended it.  The runner's test of it now uses a word that
really never ends.

hosted-check also requires that RS1 and T{ are unknown after boot, and
boots a program whose POST has failing cases (tests/post_cases_fail.c):
PARITY:FAIL, POST: FAILED, no prompt, none of a case's printing shown.

Comments and documents that still named the POST capsule or its two
hooks are brought up to date; NUCLEUS.md 6.3 says what v3 does, with the
lines, and how the wrong ruling came about.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, word_count=314, dict_hash
0x220ab283a504a3b3 on all six: logs/20261007-112638, -112901, -113220.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:40:20 -04:00
rajamesandClaude Opus 5.5 eda6577a53 docs(v4.0.0): step 6a withdrawn -- drives that come and go are built as v3 has them
Captain Bob, 2026-10-07.  Rulings 6 and 8 of MESH.md 8.1 (a device
identity in the block header, a returning device's old numbers, release
by moving its blocks off, holes) were given without v3's design having
been shown.  MESH.md 8.7 sets v3's design beside them: a removable drive
is a person's, known by its signature; WIREBIND; it joins at the tail and
only the tail leaves; EJECT flushes to the drive and kills the user's VM.

ENGINE.md steps 7 and 8 now say that is where it is built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:06:33 -04:00
rajamesandClaude Opus 5.5 4bdb210a99 feat(v4.0.0): POST is the kernel's -- the boot feeds the cases, and nothing of the harness is on the node
The boot runs POST with the runner (v4/system/post.c) after the capsules:
it feeds the 538 cases to the node and judges them from outside.  A
case's printing no longer reaches the console.  What the cases define
stays in the dictionary, as in v3; the system is sealed after POST and
the boot prints PARITY:V4_SYSTEM word_count=N dict_hash=..., as v3 prints
its parity after POST.

Gone: capsules/v4/post79.4th and its blocks 7000 up; the harness words;
(CATCH) and (EMIT-HOOK), with what EMIT and the prompt loop did for them.

The generator runs v3 on the lines as the kernel sends them, without the
capsule's "T| ".  One expected result follows from that: >IN.initial
prints 6, not 9.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, word_count=411, dict_hash
0x6fb1d09418b189ee on all six: logs/20261007-105118, -105335, -105651.
T{ is unknown at the prompt; RS1 prints 42 42 before and after COLD.  A
scratch build with one expectation changed names the case and ends
PARITY:FAIL, POST: FAILED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:59:02 -04:00
rajamesandClaude Opus 5.5 2bf958ce3a feat(v4.0.0): the POST runner -- the kernel feeds a case and judges it from outside
v4/system/post.c: for each case it empties the node's data stack, sends
DECIMAL FORTH DEFINITIONS, sends the case's lines keeping what the node
prints, reads the stack, and judges: an error exactly if one is expected,
and otherwise the stack and every character printed.  A failing case is
named with what it printed and left.  Nothing of it is on the node.

Its tests are in test_host_quit.c, on that test's node: 29 checks of cases
that must pass and cases that must fail -- a wrong value, depth, order or
output, an error wanted or unwanted, a case of two lines, depth-only
cases, the starting state, more printing than is kept, and a line that
never comes back.  Both widths and the sanitizers.

The boot still runs the capsule; that is the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:36:36 -04:00
rajamesandClaude Opus 5.5 c2f4b9808a feat(v4.0.0): POST's cases as a table the kernel holds
mkpost.py writes v4/system/post_cases.c where it wrote the capsule: for
each case its name, its lines, and what it must do -- end in an error, or
leave v3's stack and print v3's output, which is now held in full where
the capsule held its length and a checksum.

The same 538 cases: checked against capsules/v4/post79.4th case by case --
names, lines, stacks, and the length and checksum of each output -- with
no difference.  The capsule is still what the boot runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:34:03 -04:00
rajamesandClaude Opus 5.5 b04ae55ec5 docs(v4.0.0): step 6b -- POST is the kernel's: design, acceptance and plan
NUCLEUS.md 6.3 and section 7 as approved 2026-10-07: the kernel holds the
cases as a table and feeds them to the node; a runner judges from outside;
what the cases define stays, as in v3; a PARITY:V4_SYSTEM line after POST.
The capsule harness and its two nucleus variables are withdrawn (6.3a
keeps what they were).  MESH.md step 6b has the acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 10:27:47 -04:00
rajamesandClaude Opus 5.5 9bfd5071d2 feat(v4.0.0): the block words are the kernel's -- v3's way in full
Ruled 2026-10-07.  BLOCK, BUFFER, UPDATE, SAVE-BUFFERS and EMPTY-BUFFERS
are each one kernel request on port 0, by block number only.  The node
has a window of four slots in its memory, as a v3 VM has; the kernel
copies blocks into it, keeps the record of which block is in which slot,
and decides when a block is written (v4/system/blocks.c).  The node keeps
no record and gives the kernel no address, so a request cannot overwrite
the node's code.  When a block is written stays FORTH-79's: UPDATE marks
it.  When the chain of devices changes the slots are let go, as in v3.

The window is 512 cells more than the two buffers were; the dictionary
space ends that much lower, at 13824.

MESH.md 8.5 had said, from the review, that a v3 VM's BLOCK is the
kernel's buffer.  It is not, and the section now says what was reported,
what v3 does, and what was ruled.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, the same hashes on all six:
logs/20261007-092835, -093112, -093456.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:37:30 -04:00
rajamesandClaude Opus 5.5 7f4d946d2e docs(v4.0.0): storage -- correct what MESH.md 8.5 said of v3's BLOCK
It said a v3 VM's BLOCK gives the kernel's buffer.  It does not: each v3
VM has a window of four slots in its own memory, and BLOCK copies the
kernel's block into one.  The entry now says what v3 does and where v4
differs from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:09:20 -04:00
rajamesandClaude Opus 5.5 bcfd6556a8 fix(v4.0.0): storage -- what the review of step 6 found
A block request with fewer than two values on the stack is refused; it
had acted on whatever the stack ring held and stopped the node.

Bare metal: when the kernel's chain takes the place of POST's block RAM
the node's two buffers are emptied, so it no longer holds POST's copy of
a block; and the chain's fast RAM is cleared, so a node cannot read what
was in the kernel's heap.

blocks.c is built with each test under that test's own warnings and
sanitizers; it had been left out of both.  The hosted link cleans its
object directory first: it had linked the withdrawn store_v3.o left there
from the day before.

node.h and DECOMPOSITION.md D-19 no longer describe the message device or
the four registers as current.  MESH.md 8.5 records two findings for
ruling: a node's own copy of a block, and a block read over a node's code.

From a clean build: make -C v4 test, sanitize and hosted-check pass;
amd64, aarch64 and riscv64 boot, POST 538 of 538, same hashes, blocks 1
and 2047 clean at the prompt: logs/20261007-085017, -085254, -085636.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:58:52 -04:00
rajamesandClaude Opus 5.5 6d90375da7 docs(v4.0.0): storage -- step 6 done
MESH.md step 6 as built, what is not as intended yet, and step 6b for
POST becoming the kernel's.  README and V3-PARITY.md brought up to date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:31:23 -04:00
rajamesandClaude Opus 5.5 7c06bdfdb6 refactor(v3): the block subsystem is one chain again
blk_chain_default, blk_chain_new and blk_chain_select (0e761cb1) were for
a node's own drive, which was withdrawn on 2026-10-07 (docs/v4.0.0/MESH.md
8.5).  They are taken out.  What remains of that change is that
blk_subsys_init takes no VM.

Accepted on the v3 configuration: amd64, aarch64 and riscv64 reach the
zuse prompt, no UNKNOWN WORD, PARITY:M7.1a hash 0x08873e0f44b7cb2a on all
three, as before.  logs/20261007-082647, -082752, -082938.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:30:38 -04:00
rajamesandClaude Opus 5.5 d5b7235464 feat(v4.0.0): every node asks the kernel for its blocks; a born node is not POSTed
A block is a kernel request, as ENGINE.md 3.3 has it: the node puts the
block's number and the address of 256 cells on its stack and writes the
request to port 0, and the kernel leaves the status there.  The requests
are -1, read, and -2, write, the same for every node.  v4/system/blocks.c
serves them from the kernel's block subsystem, which is v3's.  The four
storage registers are gone from the engine.

The device that spoke block messages (4a505a15) is withdrawn with its
test and its message types: Captain Bob ruled on 2026-10-07 that it, a
node's own drive, and nodes with no storage had left the OS as designed
(docs/v4.0.0/MESH.md 8.5).

Hera no longer sends POST to the nodes she births: POST is the kernel's,
once.  Every node has its kernel on port 0; it serves a node's blocks and,
for Hera alone, her requests for nodes and capsules.

Bare metal: the node boots and is POSTed against POST's own block RAM,
and the kernel's chain -- fast RAM, the ramdrive, the virtio disk -- is
set up after POST and before the prompt, as on the v3 path.  The disk is
read and not written: nothing in v4 yet gives the owner's word that it
may be formatted.  A hosted program has the chain's fast RAM, as hosted
v3 has with no disk.  Error 17 is Storage refused.

make -C v4 test and sanitize pass at both widths; hosted-check passes on
three ISAs; amd64, aarch64 and riscv64 boot, POST 538 of 538, with the
typed session: logs/20261007-081603, -081839, -082226.  The hashes are
the same on all six.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:24:47 -04:00
rajamesandClaude Opus 5.5 26a0748455 docs(v4.0.0): storage brought back to the OS as designed -- every node asks the kernel
Ruled 2026-10-07 (Captain Bob): POST on every node, nodes without
storage, and block requests passed from node to node had left v3's
design.  MESH.md section 8 is rewritten: a block is a kernel request, as
ENGINE.md 3.3 already had it; every node has blocks; there is one chain.
Private drives and the message device are withdrawn, and listed in 8.5
so that they are not proposed again.  Acceptance 1 and 3 change with it.
A born node is not POSTed, and the kernel is to hold POST's cases.

The plan for step 6 is revised to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 07:21:10 -04:00
rajamesandClaude Opus 5.5 4a505a154d feat(v4.0.0): storage speaks messages -- a device over v3's block chains, common and private
What is on a storage port (v4/system/storage.c): it takes Block read,
Block write and Block data and answers Block data or Block done.  It
holds a view of a common chain, a private chain, or both; private block k
is number 2^32 - 1 - k.  Behind it is v3's block subsystem, reached
through v4/system/store_v3.c, the one v4 file that includes v3's headers.

v3's block code links here with its two device back ends, its log and
its clock, and nothing else of v3.

v4/tests/test_store.c: 36 checks at 64 bits, 35 at 32, and under the
sanitizers.  docs/v4.0.0/MESH.md 8.3, 8.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:41:07 -04:00
rajamesandClaude Opus 5.5 0e761cb117 refactor(v3): the block subsystem's state is a chain there can be two of; blk_subsys_init takes no VM
The global state becomes struct blk_chain, reached through a current
pointer: blk_chain_default, blk_chain_new, blk_chain_select.  Nothing
that uses the one chain changes.  blk_subsys_init loses its VM argument,
which was stored and never used.  docs/v4.0.0/MESH.md 8.4.

Accepted on the v3 configuration: amd64, aarch64 and riscv64 reach the
zuse prompt, no UNKNOWN WORD, PARITY:M7.1a hash 0x08873e0f44b7cb2a on
all three, as on 2026-10-03.  logs/20261006-202918, -203036, -203230.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:33:32 -04:00
rajamesandClaude Opus 5.5 a7991f2757 docs(v4.0.0): storage -- the plan for step 6, and three details ruled into the spec
blk_subsys_init loses its unused VM argument (ruled).  Block done has a
fourth answer, no such block.  MESH.md 8.4 says which chain a number
means, that storage has a number like a node, and that a block number is
not signed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:12:23 -04:00
rajamesandClaude Opus 5.5 8cacfb663c docs(v4.0.0): storage -- ruled: a static view over a shifting chain, the kernel's mapper, private drives
MESH.md section 8 is no longer a proposal.  Ten rulings (Captain Bob,
2026-10-06), the design of step 6 as approved, what it leaves out, and
one case left open.  Step 6a is added for chains that change while
running; its acceptance is still to be approved.

V3-PARITY.md 1d stands: the mapper is the kernel's block subsystem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:04:51 -04:00
rajamesandClaude Opus 5.5 348eed7fa1 feat(v4.0.0): five nodes from nothing -- Hera asks for nodes, births and joins them
MESH.md step 5, in the fabric under test; the products are still one
node each until steps 8 and 9.

manage.c: what Hera asks of whoever holds the fabric, eleven requests by
KERNEL-WORD -- NODE-ME -BORN -WIRE -UNWIRE -SLEEP -WAKE -KILL -PARITY and
CAPSULE-OPEN -CELL -LINE. Nucleus: PORT!, SEND-ON, AWAIT, (SEAL).
capsules/v4/hera.4th: BIRTH and UNIT, the unit rule in FORTH and nowhere
else. The dictionary hash moves to the engine (v4_image_dict_hash).

test_host_unit.c, 34 checks, 64-bit: Hera is born empty, takes the
nucleus through her port, FORTH-79, POST and her capsule; 10 UNIT; four
nodes are born, each takes the nucleus and FORTH-79 through its port from
Hera and passes POST 538/538; four parities, one dictionary hash; they
talk, and a message between two corners not wired goes by Hera.

All v4 tests at both widths and under ASan+UBSan. hosted-check on three
ISAs. Bare metal: logs/20261006-143934 (amd64), -144204 (aarch64),
-144601 (riscv64).

Open, recorded in MESH.md: not run at 32 bits; a node that never answers
leaves Hera waiting; the capsules are read from files in the test, not
from the baked directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:48:23 -04:00
rajamesandClaude Opus 5.5 f9c034cadd feat(v4.0.0): a node looks before it writes; two neighbours no longer stop each other
MESH.md step 4, the fault found there, as ruled (section 7a): a node
writes only to a neighbour that is reading, keeps what it takes in
meanwhile, and loses and counts what it has no room for.

Engine: two more addresses after a node's ports -- which ports have a
neighbour waiting to write to it, which to read from it. Nucleus: (GATE)
before every message; the messages waiting, a ring of 400 cells, dealt
with when the node is idle. Of two neighbours the lower number may wait
to write (ruled after it was built); NEIGHBOUR tells a node who is on
each port.

test_host_mesh.c, 44 checks: the case that stopped the nodes passes; six
messages from each node to each at once all arrive; 800 at once, the
nodes come to rest and every message arrived or was counted (287 arrived,
714 of all kinds let go). test_fabric.c: the two looks. Both widths,
ASan+UBSan.

POST: twelve cases handed HERE, a cell address on v4, to words that take
a byte address, and so wrote into or read from the nucleus's code at cell
HERE/4. Ruled: left out, marked OPEN, until HERE and the byte words are
made to agree as its own step. POST is 538 cases.

hosted-check on three ISAs, 538/538. Bare metal: logs/20261006-134817
(amd64), -135044 (aarch64), -135440 (riscv64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:56:57 -04:00
rajamesandClaude Opus 5.5 630d03fa4e feat(v4.0.0): a node finds the way -- routes, passing on, SEND; one fault stands
MESH.md step 4. Each node has a table of destinations and the port toward
each, and a port for everything else (ROUTE, DEFAULT-ROUTE, NO-ROUTES). A
message not for this node is passed on whole; one with nowhere to go is
dropped and counted. What text prints and how it ended go back to the node
it came from by the same table. SEND sends text to another node.

test_host_mesh.c: three StarForth nodes in a row behind a console, 28
checks at both widths and under ASan+UBSan. hosted-check on three ISAs.
Bare metal: logs/20261006-115225 (amd64), -115501 (aarch64), -115849
(riscv64).

NOT DONE. Two neighbours that write to each other at once wait for ever:
a write blocks until the neighbour reads, and a node that is writing is
not reading. The last check in test_host_mesh.c shows it (KNOWN FAULT).
MESH.md section 7a sets out the ways out; none is chosen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:01:32 -04:00
rajamesandClaude Opus 5.5 a041b401ea feat(v4.0.0): a node is sent text as a message and sends back what it prints
MESH.md step 3.  The ports are the transport; the message is what is
transported: to, from, type, heat and TTL, ACL tag, sequence, length, then
text four characters to a word.

- quit.v4: a node with nothing to do is blocked reading "any port"; text
  for it is interpreted; (FINISH) sends what it printed and then how the
  text ended, and it waits again
- core.v4: EMIT keeps what is printed, (FLUSH-OUT) and (HDR) send it to the
  sender on the port the message came on.  EMIT still needs one free data
  cell and no more; it works on the return stack and in A and B
- message.h/.c: the same format for whatever is on a port and is not a node
- boot.c: the boot is the node's console on port 1 and its kernel on port 0
- the prompt tests are a console that speaks messages
- gone: v4_line_begin, v4_line_done, v4_line_status; writing a node's input
  buffer and setting its P from outside; any use of CONSOLE-TX

Verified: make -C v4 test (test_host_quit.c 1283 checks, the full-stack
figures unchanged) and make -C v4 sanitize pass; hosted-check passes on
three ISAs with POST 550 of 550; clean qemu with STARFORTH_V4=1 passes POST
and answers lines typed at each prompt on amd64, aarch64 and riscv64
(logs/20261006-110551, -111621, -111341).  -110837 is an aarch64 run ended
by the test wrapper's limit while still in UEFI firmware; it shows nothing
about v4.

Not done: KEY, EXPECT and QUERY still read the console's input registers;
a message not for this node is let go (step 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:19:46 -04:00
rajamesandClaude Opus 5.5 42610e844f feat(v4.0.0): the nucleus is a capsule, sent to a node born empty
MESH.md step 2.  A capsule of F18 code is the words a neighbour writes to a
node's port: for each stretch of memory, "@p a! @p push", the address and
count, "@p !+ unext" and the words; then a jump to the start.  A node born
empty executes that from its port, so it needs nothing in it beforehand.

- capsule.h/.c: v4_capsule_write, any node's memory as such a capsule
- mkimage writes the nucleus so, to capsules/v4/nucleus-64.f18, and the
  addresses a host needs as a C file; the memory image is no longer linked
  into either product
- mkcapsule is unchanged: the nucleus capsule is a built file kept under
  capsules/, as BLOCK_MAP.md is, and is baked, hashed and signed with the
  rest
- boot: the node is born empty (v4_image_born); the nucleus capsule is
  found, its hash and signature checked, and given to the node a word at a
  time as it reads its port; PARITY:V4_NUCLEUS carries its name and hash

Verified: test_fabric.c (59 checks, both widths, and under ASan and UBSan):
a memory with a programme and scattered words arrives word for word in an
empty node and runs.  The nucleus capsule rebuilds byte for byte.
hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64,
aarch64 and riscv64 takes the nucleus in, passes POST (550 of 550) and
answers lines typed at each prompt (logs/20261006-102421, -102706,
-103048).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:33:15 -04:00
rajamesandClaude Opus 5.5 9af442f793 feat(v4.0.0): nodes that talk -- ports, a node born empty, and the fabric
MESH.md step 1, in the engine, which knows nothing of StarForth or of any
kernel.

- node: V4_PORTS ports (8), a build parameter; "any port" and the port the
  last such read came from; a read blocks until the neighbour writes, as a
  write blocks until the neighbour reads; v4_node_born: empty, P at "any
  port"
- exec: a fetch from a port -- @ @b @+ @p, or of an instruction word when P
  is a port -- waits for a word; a node executes what arrives at a port
  without advancing P; a blocked node goes on from the slot it stopped at
- fabric: the nodes there are and the table of how their ports are wired,
  both changed while the nodes run; devices on a port; asleep and awake; a
  step is every unblocked node executing one instruction word, then every
  write with a reader waiting being handed over
- DECOMPOSITION.md section 6: four named ports withdrawn for V4_PORTS
  numbered ones and wiring as data, as ruled

Verified: tests/test_fabric.c, 53 checks at both widths: two nodes exchange
words; an empty node is filled through its port by a device, and by another
node, and runs what it was sent; a word is passed on by a node in between;
a waiting node executes nothing; the wiring is changed while they run; a
node is put to sleep, woken and removed while looping; a node is born while
others run; the fabric is given more room.  make -C v4 test and make -C v4
sanitize pass.  The single-node products are unchanged: hosted-check on
three ISAs, and clean qemu with STARFORTH_V4=1 on amd64, aarch64 and
riscv64 with lines typed at each prompt (logs/20261006-074907, -075150,
-075532).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:58:00 -04:00
rajamesandClaude Opus 5.5 2c5427d9c1 docs(v4.0.0): talking nodes -- design
From Captain Bob's rulings of 2026-10-05 and -06 (ENGINE.md 3d) and the
acceptance he approved.  Ports with blocking reads and writes, a node born
empty that executes what arrives at its port, a fabric of nodes and wiring
that change at run time, capsules of F18 code, messages, finding the way,
storage, birth and Hera; nine steps.  Marks which parts are rulings and
which are proposals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:21:43 -04:00
rajamesandClaude Opus 5.5 beb7ded96c docs(v4.0.0): talking nodes -- built in the shared engine, proven hosted first, then bare metal
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:17:29 -04:00
rajamesandClaude Opus 5.5 ae17a1ccf0 docs(v4.0.0): talking nodes -- a node is born empty and takes in its first capsule
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:15:19 -04:00
rajamesandClaude Opus 5.5 a68ea4841f docs(v4.0.0): talking nodes -- Hera decides which nodes exist and are awake, not whose turn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:13:01 -04:00
rajamesandClaude Opus 5.5 11e135a8c3 docs(v4.0.0): talking nodes -- the geometry is data: ports are a parameter, wiring a table
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:09:21 -04:00
rajamesandClaude Opus 5.5 c7b61b5680 docs(v4.0.0): talking nodes -- the geometry is not fixed to three dimensions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:40:15 -04:00
rajamesandClaude Opus 5.5 bd65b5b165 docs(v4.0.0): talking nodes -- units of five, joined centre to centre
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:38:34 -04:00
rajamesandClaude Opus 5.5 a02a7905cd docs(v4.0.0): talking nodes -- 2x2 + 1 central, six ports, scaling at run time
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:35:51 -04:00
rajamesandClaude Opus 5.5 7a8b528d3b docs(v4.0.0): where v4 is going; the next step is talking nodes
Captain Bob, 2026-10-05: F18 engines digesting capsules, 12x12 then 12^3;
the next step is nodes talking and sharing the common SSD, ahead of v4 = v3
on bare metal.  Rulings so far: ports are the transport and v3's message is
what is transported; some nodes have storage of their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:29:49 -04:00
rajamesandClaude Opus 5.5 25fc5fd5e3 feat(v4.0.0): the node tells its kernel of its words; the boot seals the system
ENGINE.md 3b, the node's side of ruling A (a word's code is the node's, its
accounts the kernel's).

- dict.v4, system.v4: (WORD-DEFINED) ( xt -- ) is run when an entry is
  made, (WORD-FORGOTTEN) ( w -- ) when FORGET or COLD removes entries; with
  0 there no one is told, as on the hosted product
- test_host_quit.c: a kernel that keeps the list of words and is checked to
  hold exactly the node's dictionary after definitions, a vocabulary, an
  abandoned definition, FORGET, a refused FORGET and COLD; KERNEL-WORD
  called from the prompt and from a definition

Fixed, found while writing that test: since the capsules moved from build
time to boot time (294e6946), what COLD returns to and FORGET protects was
still the nucleus alone, so COLD lost U*, U/MOD and BYE and FORGET U* was
allowed.  The boot now seals the system when it has loaded it
(v4_image_seal), and hosted-check checks COLD, the capsule word after it,
the refused FORGET and BYE.

Verified: make -C v4 test passes at both widths (1283 checks in
test_host_quit.c); hosted-check passes on three ISAs; clean qemu with
STARFORTH_V4=1 on amd64, aarch64 and riscv64 passes POST, and COLD, U*
after it, FORGET U* (refused), an unserved kernel word and BYE typed at
each prompt are answered correctly (logs/20261005-193045, -193307, -193636).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:38:40 -04:00
rajamesandClaude Opus 5.5 e8e8ea13ea docs(v4.0.0): what the two products share -- engine, FORTH-79 capsule, POST; separate nuclei
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:18:33 -04:00
rajamesandClaude Opus 5.5 ad3efdda65 docs(v4.0.0): the hosted and bare-metal products part here
Captain Bob, 2026-10-05.  Withdraws the claim that the hosted v4 product
should become v3's hosted program with the node as its interpreter.  The
bare-metal product is LithosAnanke with the node in the VM's place; the
hosted product is its own and need not follow it; the six builds no longer
have to print the same lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:14:24 -04:00
rajamesandClaude Opus 5.5 085d0881de docs(v4.0.0): ENGINE -- a word's two halves; what exactly is swapped in v3
Ruling A recorded as design.  Measured: each build has one interpreter file
(v3/src/vm.c hosted, kernel/src/vm/vm_core.c in the kernel) and the swap is
a third, answering the same functions with a node.  So the hosted v4
product is v3's hosted program with the node as its interpreter, not a
separate program.  Steps re-cut; two things in v3's C words that do not
carry over as they are (vm_ptr into packed bytes, direct stack fields).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:13:55 -04:00
rajamesandClaude Opus 5.5 d4b1b4ff91 docs(v4.0.0): ruling -- a v4 word's code is the node's, its accounts the kernel's
Captain Bob, 2026-10-05.  For each word on a node the kernel keeps v3's own
DictEntry record, joined by word ID; v3's physics, heartbeat, ACL words,
Stadium word layer and parity run on the records unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:12:41 -04:00
rajamesandClaude Opus 5.5 8df6c16766 feat(v4.0.0): a node asks its kernel by a blocking write to its port
ENGINE.md step 2, the carrier.  Ruled 2026-10-05 (V3-PARITY.md 1i), on
DECOMPOSITION.md section 6: a write to a port blocks until the neighbour
reads.

- node: v4_node_port_attach, v4_node_port_served; a store to the port keeps
  the value as the request and blocks the node
- exec: a blocked node executes nothing; served, it goes on from the opcode
  after the store, in the same instruction word; a fault meanwhile abandons
  the rest of the word
- compile.v4: n KERNEL-WORD name makes a word whose body writes n to the
  port; its arguments and results are on the data stack
- boot: the kernel's words are made by handing the node text, and requests
  are served between the node's opcodes; one no one serves is error 12
- BYE, the first kernel word: hosted it leaves the program, as hosted v3;
  on the lone node it is v3's cold restart
- ENGINE.md 3a: multiuser, multitasking, preemptive and cooperative, and
  what that asks of the engine

Verified: make -C v4 test passes at both widths, with tests/test_port.c;
hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64,
aarch64 and riscv64 passes POST with the same hashes as hosted, and a
kernel word no one serves and BYE typed at each prompt are answered
(logs/20261005-185506, -185734, -190101; -185234 is an amd64 run in which
those two lines were not typed).

Not done: v3's own C functions serving a node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:03:03 -04:00
rajamesandClaude Opus 5.5 5f1f60fc84 docs(v4.0.0): a node asks the kernel by a blocking port write; Hera manages processes
Ruled 2026-10-05.  Hera as process manager via compudynamics per node is
recorded as said and is not yet designed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 18:43:40 -04:00
rajamesandClaude Opus 5.5 01c447f9ab feat(v4.0.0): a node is handed a line -- ENGINE.md step 1
A v4 node no longer reads its own command line or prints a prompt.  Its
host puts a line of text in the node's input buffer and starts it at
(LINE); the node interprets it and stops at (IDLE), leaving in
(LINE-STATUS) how it ended: completed, an error, or QUIT.  The host says
" ok" or " ERROR" and prompts, as the kernel's REPL does for a v3 VM.  A
line may be 1024 characters, a block, as v3's.  Ruled 2026-10-05
(V3-PARITY.md 1b); design ENGINE.md 3.1.

- quit.v4: (REPL), the node's prompt loop, is gone; (LINE) (IDLE) (DONE)
- image.h/.c: v4_line_begin, v4_line_done, v4_line_status; the node is
  idle at switch-on
- boot.c: v4_boot_line, the one loop the hosted binary, the kernel and the
  capsule loader hand a line with; the code that took " ok" and the prompt
  back out of the node's output is gone
- hosted.c, sk_v4.c: the prompt and the line editing are the host's
- test_host_quit.c: the tests are the node's host; two tests of the old
  80-character prompt line now test a whole line, 1024 and 1025 characters

Verified: make -C v4 test passes at both widths; hosted-check passes on
three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64
passes POST (550 of 550) with the same hashes as hosted, and three lines
typed at each bare-metal prompt through the serial port are answered
correctly (logs/20261005-180922, -181152, -181541).

Still the lone node: kernel_main.c starts it before the fleet tables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 18:17:37 -04:00
rajamesandClaude Opus 5.5 ab7a9bf06f docs(v4.0.0): the F18 engine in the VM's place -- design
From the rulings of 2026-10-05 and v3's code.  The kernel stays untouched;
what is replaced is the part of a v3 VM that executes FORTH.  Sets out the
interface the kernel reaches a VM through (interpret this text, a
character out, asking the kernel, the stacks and dictionary, a word being
executed, an error, a tick, the dictionary hash), what a node needs for
each, what becomes of the lone-node work, seven steps, and what is open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:59:17 -04:00
rajamesandClaude Opus 5.5 ff53ec4bb4 docs(v4.0.0): the opcode's accounts are left unwired for now
Captain Bob, 2026-10-05: observe the opcode counts, build no opcode patron
layer yet; likely needed at the FPGA; keep it available.  Amends section
2.7: word patrons do not become opcode patrons now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:53:15 -04:00
rajamesandClaude Opus 5.5 e692759a96 docs(v4.0.0): correction -- each kind of patron keeps its own accounts
Captain Bob, 2026-10-05.  Records, from stadium.c and its layers, the
accounting rules of the VM, word, block and message patrons, that a v3
word already has more than one account, and withdraws two statements that
treated heat as one number per thing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:50:28 -04:00
rajamesandClaude Opus 5.5 bd996a1106 docs(v4.0.0): the ACL TTL stays adaptive -- a v4 node counts executions per word
Captain Bob, 2026-10-05: a fixed TTL makes no sense; the hotter the word,
the more often it is checked.  The node counts executions per word at the
call hook for ACL-TTL-COMPUTE, as v3, beside the per-opcode heat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:48:34 -04:00
rajamesandClaude Opus 5.5 0273308b78 docs(v4.0.0): ACL intent -- a runtime check of a word; TTL is how often
Captain Bob, 2026-10-05.  The countdown runs on every execution; the
permission check only when it reaches zero.  A compile-time check does not
meet the intent, so a word that is to be checked must be called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:46:04 -04:00
rajamesandClaude Opus 5.5 c80b4c8ed7 docs(v4.0.0): the word card stays as v3; where a v4 node can hook it
Captain Bob reversed the change the same day: leave the word card exactly
as v3, if a place to hook can be found.  Records that there is one -- the
call opcode, one place in the engine -- and what does not pass through it:
62 in-line words, EXECUTE, hand-written jumps, and call targets that are
not dictionary entries.  Notes that v3's TTL is computed from per-word
heat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:43:47 -04:00
rajamesandClaude Opus 5.5 6dc71758da docs(v4.0.0): ACLs -- the four cards as built; the word card is to change
Records the stack-of-cards model, that the block, message and VM cards
carry over, and Captain Bob's statement of 2026-10-05 that the word card
changes too, with the reason: the opcode level is the division point for
the machines to be built on the fabric.  What it becomes is not settled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:41:05 -04:00
rajamesandClaude Opus 5.5 b9b6f0c6fa docs(v4.0.0): messaging -- a v4 node is handed text and sends by asking
Records kernel-Hermes as built and the ruling of 2026-10-05; the open
question of a node's safe moment; and the stated intent to pull Artemis up
into the kernel later, as Hermes was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:36:21 -04:00
rajamesandClaude Opus 5.5 f6b3ec54f4 docs(v4.0.0): the Stadium as the frame; blocks -- a v4 node asks by number
Records that compudynamics is the kernel's Stadium (words, VMs, blocks,
messages and ACLs all patrons of one engine), v3's block subsystem as
built, and the ruling of 2026-10-05: a v4 node only asks for a block by
number; ownership, ACL, physics and devices stay on the kernel's side under
the VM's identity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:05:00 -04:00
rajamesandClaude Opus 5.5 b128a4d6db docs(v4.0.0): console -- the kernel hands a v4 node a line, as it does a v3 VM
Records v3's console as built (fabric, Hestia, proxies, the kernel's REPL
owning input and the prompt) and the ruling of 2026-10-05: for now a v4
node is handed a whole line and gives characters back; its own prompt loop
plays no part at that level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:58:55 -04:00
rajamesandClaude Opus 5.5 79db64c4e2 docs(v4.0.0): correct V3-PARITY -- the pieces are not missing, v4 is beside them
The table called rows 1 and 6-12 missing in v4.  They are all in this
kernel and run today.  kernel_main.c calls sk_v4_run() before the fleet
tables, VM bootstrap, devices, Mama birth, heartbeat and fleet birth, and it
never returns, so the v4 node comes up beside the system and skips it.
Records how v3's boot fits together around the VM interface, and that the
open question is how the F18 engine takes the VM's place behind it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:49:52 -04:00
rajamesandClaude Opus 5.5 e88032b7e8 docs(v4.0.0): ruling -- the unit of heat in v4 is the opcode, not the word
Captain Bob, 2026-10-05: v4 = v3 functionally; heat accumulates on the 32
opcodes; the opcode replaces the word as the smallest unit.  Answers D-6 and
the three conflicts of V3-PARITY.md 2.4.  Records what follows (the
per-call-target array goes; pipelining and the hot-words cache are not
retired; decomposition no longer waits) and what is still open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:44:57 -04:00
rajamesandClaude Opus 5.5 2abaf51aee docs(v4.0.0): v4 against v3 up to the first prompt; row 3, physics and heat
Measures v4 against the ruling of 2026-10-05: v4 is exactly like v3 in
functional requirements up to the first FORTH prompt.  Twelve things v3 does
before its prompt, and what v4 does of each.  Row 3 in full: what v3 does
for every executed word and on every heartbeat tick, what a v4 node has,
what the v4 design documents say instead, the three places they conflict
with the ruling, and what each answer would take.  Lists the stand-ins
found in v4.  Proposes; decides nothing; nothing in it has been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:40:41 -04:00
rajamesandClaude Opus 5.5 2930349bbf feat(v4.0.0): POST passes and is part of the boot; U* and U/MOD
The boot is now nucleus, forth79.4th, POST, prompt, on both products.

- forth79.4th: U* and U/MOD, the capsule's first colon definitions.  They
  are in the FORTH-79 Required Word Set and neither v3 nor v4 had them.
- post79.4th: 550 cases, 126 of the 130 required words.  443 are v3's with
  v3's result.  The rest follow three rulings (2026-10-05): address-
  dependent cases are checked for count, not value; where v3 departs from
  FORTH-79 the standard's result is expected; words v3 has no case for get
  cases written by hand.  v4/tools/post79_rules.py holds each exception
  with its reason and docs/v4.0.0/POST79.md lists them all.
- every case starts from an empty stack, DECIMAL and FORTH DEFINITIONS
- the boot requires POST's tally line with fail=0

Verified: tests=550 pass=550 fail=0 and identical PARITY lines on hosted
amd64, aarch64 and riscv64 (make -C v4 hosted-check) and on bare metal,
clean qemu with STARFORTH_V4=1, on the same three (logs/20261005-1619xx,
-1621xx, -1625xx).  A U/MOD broken on purpose fails five cases and stops
the boot.  make -C v4 test passes.

Not shown: all words but those two are still assembled, so POST has so far
tested the assembled words.  Nothing was typed at a bare-metal prompt.
Open: PAD 42 OVER ! faults on v4 (D-1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:28:01 -04:00
rajamesandClaude Opus 5.5 5d6043e37e feat(v4.0.0): POST for FORTH-79, from v3's cases; not passing yet
capsules/v4/post79.4th: 537 of v3's POST cases for the FORTH-79 Required
Word Set, each carrying what the hosted v3 binary did with the same line
(error or not, the stack, the length and checksum of what it printed).
Written by v4/tools/mkpost.py.  The harness is FORTH-79 plus the two
nucleus hooks.  docs/v4.0.0/NUCLEUS.md section 6.

- NODE-ERROR has a FORTH name: how a definition in FORTH raises an error
- the boot passes POST only on seeing its tally line with fail=0
- POST is not in the boot yet (V4_POST_AT_BOOT=0); make -C v4 post runs it

Result: tests=537 pass=439 fail=98.  The 98 are not yet sorted into v4
defects and differences needing a ruling; v4/README.md has a first reading.

Verified: make -C v4 test passes; hosted-check passes on three ISAs; clean
qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 reaches ok> with the
same hashes as hosted (logs/20261005-1601xx..1604xx).  Nothing was typed at
a bare-metal prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:04:48 -04:00
rajamesandClaude Opus 5.5 ed6b11ad88 feat(v4.0.0): (CATCH) and (EMIT-HOOK), the two nucleus hooks POST needs
(CATCH): while it is not zero, a line that ends in an error sets it to -1
and ends " ok" instead of " ERROR".  (EMIT-HOOK): the xt of a word that is
given each character EMIT would send to the console.  The prompt loop sets
(EMIT-HOOK) to 0 at the end of every line.  docs/v4.0.0/NUCLEUS.md 6.3,
amended: it said one nucleus word would do.

Verified: make -C v4 test passes at both widths; by hand at the hosted
prompt, an unknown word and a division by zero are caught, the output hook
receives every character, and an uncaught error still says ERROR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:49:43 -04:00
rajamesandClaude Opus 5.5 506b645726 test(v4.0.0): v4 boots on bare metal and loads its capsule, three ISAs
clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64, one at a
time.  Each prints the same PARITY:V4_NUCLEUS and PARITY:V4_CAPSULE lines as
the three hosted binaries (image_hash 0x60b74e4f87adb0ac, dict_hash
0x0baed67626b4fac4), then PARITY:OK and ok>.

Each run was ended once the prompt was in the log.  Nothing was typed at a
bare-metal prompt.  The capsules were unsigned: no signing key on this
machine.  The v3 boot (STARFORTH_V4=0) was not re-run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:42:40 -04:00
rajamesandClaude Opus 5.5 294e69463a feat(v4.0.0): the system boots from a nucleus and loads its capsules
One boot, v4/system/boot.c, for both products: it starts the nucleus image,
finds each capsule in the baked capsule directory, recomputes its hash,
checks its signature, gives its blocks to the node a line at a time, and
prints PARITY:V4_NUCLEUS, PARITY:V4_CAPSULE and PARITY:OK before the prompt.
A line the node does not accept ends the boot with the capsule, block and
line named.  docs/v4.0.0/NUCLEUS.md.

- hosted Linux product for amd64, aarch64 and riscv64 (make -C v4 hosted);
  make -C v4 hosted-check boots all three and requires identical output
- the kernel's v4 entry (STARFORTH_V4=1) calls the same boot
- capsules/v4/forth79.4th, block 6000: no definitions yet
- mkimage builds the nucleus only; no FORTH source is compiled at build time
- capsule_blocks.c: the Block-header parse, free of any VM, for every loader

Verified: make -C v4 test passes; hosted-check passes on the three ISAs with
the same hashes; the kernel compiles with STARFORTH_V4=1 on the three.
Not verified: no bare-metal boot of v4 has been run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:28:30 -04:00
rajamesandClaude Opus 5.5 903321e548 feat(mkcapsule): no upper bound on capsule block numbers
Blocks 0..2047, the VM's fast RAM, are the only ones a capsule may not
claim (docs/v4.0.0/NUCLEUS.md 5.2).  The ceiling of 5120 matched no device.
All 36 capsule files still lint clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:18:30 -04:00
rajamesandClaude Opus 5.5 d4bd6e9601 docs(v4.0.0): nucleus, FORTH-79 capsule and POST design
The assembled vocabulary shrinks to a nucleus; the FORTH-79 Required Word
Set is loaded at boot from a capsule as colon definitions, POST (v3's cases,
ported, comparing results) runs on it, and the node reaches ok> -- hosted
and bare metal, on amd64, aarch64 and riscv64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:16:00 -04:00
rajamesandClaude Opus 5.5 c1bbcaaba4 feat(v4.0.0): word-level access control at the prompt, as v3
- Each entry's flags cell also holds v3's four fields: denied, pinned,
  mode and a 16-bit TTL.
- compile.v4: INTERPRET checks every word it is about to execute or
  compile -- recheck at TTL 0, else count down; a denied word is refused
  with v3's line, the stack emptied and the line ended.
- capsule/acl.v4: ACL-MODE@ ACL-MODE! ACL-TTL@ ACL-TTL! ACL-ALLOW@
  ACL-ALLOW! ACL-PINNED? ACL-PIN ACL-INHERIT ACL-INIT-PRIMITIVES ACL-HEAT@
  ACL-WORD-ID, and ACL-HOOK.
- capsule/ACL.fth: v3's ACL.4th as FORTH source the node compiles; loading
  it switches access control on.
- v3 checks every execution, inside definitions too.  v4's code is native,
  so it checks a word when it is compiled as well as when interpreted; a
  call compiled while the word was allowed is not checked again.
  DECOMPOSITION.md 5.20 says so.
- ACL-HEAT@ is 0 until heat is readable (D-6).
- tests/test_host_quit.c: seven transcripts of the v3 binary; the policy
  file loaded and exercised; COLD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:58:43 -04:00
rajamesandClaude Opus 5.5 384a6c1cd2 feat(v4.0.0): logging, as v3
- capsule/log.v4: the level constants LOG-ERROR .. LOG-DEBUG, LOG-LEVEL!
  and LOG-LEVEL@, LOG-ERROR" .. LOG-DEBUG" and LOG-ERROR-STR ..
  LOG-DEBUG-STR.  A message is printed if its level is at or below
  LOG-LEVEL, as v3's line -- colour, level, text -- without the time of
  day, which a node has not got.
- LOG-xxx" compiles like ." : the level, a call to (LOG"), the text.  SEE
  shows it as text.  COLD puts LOG-LEVEL back to LOG-INFO.
- tests/test_host_quit.c: ten transcripts of the v3 binary, every level
  at every setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:31:32 -04:00
rajamesandClaude Opus 5.5 8c540b0305 feat(v4.0.0): SEE, a disassembler written in FORTH
- capsule/tools.fth: SEE as FORTH source the node compiles itself.  v4
  code is native, so it shows each instruction word of a definition: the
  opcodes by name, literals' values, the names of the words called or
  jumped to, and text compiled by ." S" and ABORT" as text.  A data word
  shows what it holds; an immediate word says so.
- quit.v4: the three string run-time words get names, compile-only, so
  that SEE can tell text from code.
- tests/test_host_quit.c: definitions with literals, text, IF and loops;
  the capsule's own words; SEE shown by SEE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:53:22 -04:00
rajamesandClaude Opus 5.5 a1afb44598 feat(v4.0.0): the editor, redone in FORTH; COLD WARM PAGE VERSION DEFER
- capsule/editor.fth: the block editor as FORTH source, which the node
  compiles itself.  It is a vocabulary, EDITOR, used at the ordinary
  prompt: n EDIT, then L N B T P E D S H R I WIPE DONE.  v3's EDIT, a
  shell of its own, is not carried over (ruled 2026-10-05); v3's L S and
  SHOW are kept in FORTH as they were, with COPY.
- system.v4: COLD (the system as the loader left it), WARM, PAGE,
  VERSION, 79-STANDARD (FORTH-79: silent), and DEFER IS DEFER@ as v3.
- input.v4: where words are split at blanks a zero byte reads as a blank,
  so a block never written, or filled a line at a time, loads cleanly.
- tests/test_host_quit.c: the editor's source fed to the prompt line by
  line, every command on empty and full screens, what reaches storage;
  the system words; deferred words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:25:20 -04:00
rajamesandClaude Opus 5.5 c8dc14897c feat(v4.0.0): block storage, LOAD and LIST (D-19)
- The golden model's host node gets a block storage device: four
  memory-mapped registers (number, address, command, status), 1024-byte
  blocks as 256 cells.  tests/test_node.c.
- capsule/blocks.v4: BLOCK BUFFER UPDATE SAVE-BUFFERS EMPTY-BUFFERS LIST
  LOAD SCR BLK (FORTH-79) and v3's FLUSH THRU and -->, over two buffers.
- The text being interpreted is at the address in (SRC), which QUERY makes
  the terminal's buffer and LOAD a block's; LOAD saves and restores it, so
  blocks nest and the rest of LOAD's line runs afterwards.  WORD makes
  sure a loading block is still in a buffer before it reads.
- In a block, \ skips to the next 64-character line.
- A block number that does not exist, and --> at the terminal, are errors
  with messages (D-18).
- tests/test_host_quit.c: ten transcripts of the v3 binary; nesting three
  deep on two buffers; what reaches the device and when.

v3's LOAD drops the rest of its line, and v3 has no BLK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 08:32:04 -04:00
rajamesandClaude Opus 5.5 0fbe1432b7 feat(v4.0.0): vocabularies, to FORTH-79
- VOCABULARY DEFINITIONS CONTEXT CURRENT FORTH, and v3's ORDER.  A name is
  looked up in the CONTEXT vocabulary and then in FORTH; a new entry goes
  into the CURRENT vocabulary; : makes the CURRENT vocabulary CONTEXT;
  FORTH is immediate.
- WORDS lists the CONTEXT vocabulary.  FORGET takes what was defined later
  out of every vocabulary, and a vocabulary that goes gives way to FORTH.
- v3's vocabularies separate nothing: a word defined in one is found from
  every other, and one redefined in a vocabulary replaces FORTH's for good.
- tests/test_host_quit.c: isolation, chaining to FORTH, two vocabularies
  with the same names, FORGET across them; and DUMP is now checked to put
  BASE back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 07:18:28 -04:00
rajamesandClaude Opus 5.5 ab272cc2ad feat(v4.0.0): the Q48.16 words and DUMP at the prompt
- capsule/qmath.v4: Q.FROM-INT Q.TO-INT Q.1 Q.0 Q.SCALE Q.+ Q.- Q.* Q./
  Q.ABS Q.NEG Q.= Q.< Q.> Q.0= Q.MAX Q.MIN Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS
  Q.PRINT -- the definitions test_foundation.c executes on the mesh node,
  now in the host node's vocabulary.
- numout.v4: DUMP.
- Q./ by zero, and Q.SQRT and Q.LOG outside their domain, leave the
  result D-11 and D-12 give and then raise an error (D-18): "Division by
  zero", "Argument out of range".  v3 returns 0 silently.
- tests/test_host_quit.c: 122 results printed by Q.PRINT are transcripts
  of the v3 binary, the same at both cell widths; signed values, the
  errors and DUMP's layout besides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 07:00:27 -04:00
rajamesandClaude Opus 5.5 e7d686c7a2 feat(v4.0.0): CASE, ['], S", WORDS, FORGET and FENCE
- compile.v4: CASE OF ENDOF ENDCASE, as v3 (they nest; a word out of
  place is a control structure mismatch); ['] and [LITERAL].
- quit.v4: S" and its run-time word; at the prompt the text is copied to
  PAD.
- capsule/system.v4: WORDS and VLIST; FORGET (FORTH-79), which gives the
  space back and will not remove a word below FENCE -- the capsule's own
  words -- where v3's FORGET DUP succeeds.
- tests/test_host_quit.c: ten more transcripts of the v3 binary, and
  nesting, the fence and the listing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:49:53 -04:00
rajamesandClaude Opus 5.5 c02505db69 feat(v4.0.0): 48 more words at the prompt (words.v4)
capsule/words.v4: the stack, comparison, shift, double, mixed and string
words whose definitions DECOMPOSITION.md already gives and the mesh-node
tests execute, now in the host node's vocabulary:

  2SWAP 2OVER 2ROT 2>R 2R> 2R@ 2@ 2! -! 0<> 0> <> <= >= U< U> ABS MAX MIN
  WITHIN LSHIFT RSHIFT D- DABS D0= D0< D= D2* D2/ D< DMAX DMIN M+ M-
  CMOVE> MOVE FILL ERASE BLANK -TRAILING COMPARE SEARCH SCAN SKIP
  ?TERMINAL TRUE FALSE INVERT NOP

- A shift count that is negative or as large as the cell is an error, as
  in v3 (code 9, "Shift count out of range").
- tests/test_host_quit.c: 36 sessions from the prompt that are
  transcripts of the v3 binary, and the cases where v4 keeps the standard
  (MOVE in cells; M+ and M- with the double low cell first).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:34:13 -04:00
rajamesandClaude Opus 5.5 dc7e37ba5c feat(v4.0.0): every error is raised and ends the line (D-18)
Ruled 2026-10-04: guard all errors.  The errors that set NODE-ERROR and
let the line run on now stop it at once, with a message.

- A store of a non-zero code to NODE-ERROR is a trap, a sixth kind of
  fault: nothing after it executes, the return stack is emptied, and the
  data stack is left as the word left it.  Not attached, NODE-ERROR is
  plain memory, as the tests below the prompt use it.
- The capsule's words store a code where they stored -1, and the prompt's
  (RAISED) prints its message: Negative count, Not a number, Number too
  long, Not a character, Dictionary full, Name missing, Control structure
  mismatch, Control structures too deep.
- ' and COMPILE and [COMPILE] of a word that is not there say
  UNKNOWN WORD: 'xxx', as the interpreter does.
- tests: the trap in test_exec.c; every message from the prompt, with the
  rest of the line not run and the stack kept, in test_host_quit.c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:13:23 -04:00
rajamesandClaude Opus 5.5 644bfc0a25 feat(v4.0.0): number output in the capsule, and .S
- capsule/numout.v4: <# # #S HOLD SIGN #>, . .R U. U.R D. D.R, ?, SPACES,
  DECIMAL HEX OCTAL -- the definitions DECOMPOSITION.md 5.8 gives and the
  mesh-node tests execute, now words of the host node's vocabulary.
- .S, which D-16 makes possible again: as v3, the depth, then every value
  from the deepest, then a new line.  It needs six cells of the stack
  free.
- tests/test_host_quit.c: printed from the prompt, with 14 more sessions
  that are transcripts of the v3 binary, and the ends of the number range
  at each cell width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 18:50:12 -04:00
rajamesandClaude Opus 5.5 ebffa6082d feat(v4.0.0): the host node's stacks are 32 deep (D-17)
With the stacks counted and guarded (D-16) their size is a parameter of
the node.  The host node, which runs the interpreter and the compiler
under the user's programme, gets 32 values and 32 return entries; a mesh
node keeps the F18's 10 and 9.  Nothing else about the mechanism or any
word's definition changes.

- stack.h: V4_DATA_RING and V4_RET_RING are build parameters; the
  Makefile sets them for the host-node tests.
- tests/test_host_quit.c no longer assumes a size: it fills the stacks to
  whatever they are, and takes every exit with the return stack full.
- Measured on the host node now: 28 values on a line, 29 waiting between
  lines, words 31 deep from the prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 18:29:10 -04:00
rajamesandClaude Opus 5.5 0da7e32a0b feat(v4.0.0): the stacks are guarded (D-16); DEPTH, PICK and ROLL
Ruled 2026-10-04, revising D-2: stack overflow and underflow are errors
that are shown and return to the prompt, not silent wrap-around.

- Each stack counts what it holds.  Before every opcode the executor
  checks that the stacks hold what it takes and have room for what it
  leaves; otherwise the opcode does nothing and the node faults, as for a
  bad address, to that kind's handler.  Every fault empties both stacks.
- The fault handler is now a table of five jumps: address, data overflow,
  data underflow, return overflow, return underflow.  The host node says
  "Stack overflow", "Stack underflow", "Return stack overflow",
  "Return stack underflow", then ERROR and the prompt.
- Two registers, DSTACK-DEPTH and RSTACK-DEPTH: a fetch reads the depth,
  a store empties the stack.  QUIT, ABORT and the error exits empty the
  return stack before they call anything; ABORT empties the data stack.
- capsule/forth.v4: DEPTH, PICK and ROLL, to FORTH-79 (counting from
  one).  PICK and ROLL set the values above the one wanted aside in
  memory, and work with the stack full.
- Division by zero now takes its operands off the stack, as v3 does.
- A colon with no room for its entry abandons the line.
- tests: every opcode at every depth of both stacks; the faults, the
  registers and the three words from the prompt.

The sizes are unchanged: ten values, nine return entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:31:18 -04:00
rajamesandClaude Opus 5.5 361dcd1148 feat(v4.0.0): division by zero is guarded (D-15); division words in the capsule
Ruled 2026-10-04: guarded, an error shown, back to the prompt.

- capsule/forth.v4: / MOD /MOD */ */MOD M/MOD, M* and S>D join the
  vocabulary.  Each dividing word tests its divisor first; zero prints
  v3's message ("/: Division by zero"), ends an open definition, prints
  ERROR and returns to the prompt from however deep.
- SM/REM here has UM/MOD written into it and keeps its signs in memory,
  and */MOD has M* written in, so that division can be used inside words
  that other words call: / from four words deep, */MOD from three.
- forth.v4 now loads after quit.v4, which the guard leaves through.
- tests: v3 transcripts for each message; /MOD, /, MOD and */MOD against
  C on every pair of edge values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:23:30 -04:00
rajamesandClaude Opus 5.5 b3d2d56d11 feat(v4.0.0): address faults -- an address outside memory is guarded (D-14)
Ruled 2026-10-04: guarded, an error shown, back to the prompt.

- The executor checks every address a programme uses (P, A, B) before
  using it.  Outside memory the opcode does nothing, the rest of its word
  is not executed, and P becomes the node's fault handler; a node with no
  handler stops.  v4_node_load/store never index outside memory.
- capsule/quit.v4: (FAULT), the host node's handler, prints
  "Address out of range", ends an open definition, prints ERROR and
  returns to the prompt.
- tests: every memory opcode and P in test_exec.c; from the prompt, from
  inside nested words and loops, in test_host_quit.c.

This closes the hole node.h described: a wild address used to index the
model's own memory gigabytes out of bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:04:59 -04:00
rajamesandClaude Opus 5.5 b5d644d498 feat(v4.0.0): the prompt -- QUIT, ABORT, ABORT" and ."
Layer 5 of the compiler capsule.  The host node is now started at QUIT and
left running: it prompts, reads a line from its console with QUERY,
interprets it, says " ok" or " ERROR", and goes round again.

- capsule/quit.v4: QUIT and ABORT (FORTH-79), ABORT" and (ABORT") as v3 has
  them, ." and (.") (FORTH-79).  Text is compiled as a counted string after
  the call; the run-time word returns to the cell after it.
- INTERPRET prints v3's messages before abandoning a line:
  UNKNOWN WORD: 'xxx' and xxx: compile-only.
- core.v4: CR SPACE COUNT TYPE, as DECOMPOSITION.md gives them.
- input.v4: WORD split so that (PARSE) can take text without skipping
  leading delimiters (." " is an empty string); EXPECT keeps its place in
  memory, so six values may wait on the stack while a line is typed.
- tests/test_host_quit.c: the node is fed characters and its output read;
  16 sessions are transcripts of the v3 binary.

QUIT stops the line from inside any word and says nothing; v3's goes on
with the line and cannot be compiled.  v3's compiled ABORT" crashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:49:44 -04:00
rajamesandClaude Opus 5.5 806f876ee0 fix(v4.0.0): shorter chains of calls in the compiler capsule
Measured, compiling a DO loop left one return entry spare under
INTERPRET and a defining word called from inside another word
overflowed the nine-entry return stack (D-2); the prompt loop will take
one more.

C@ and C! shift without a loop.  The code generator shifts each opcode
into the word being built, so nothing is placed by a counted shift, and
the address masks come from a table.  The dictionary search, the
in-liner, the end of a loop and the making of a data word are each one
word reached by a jump.

Every kind of line now leaves at least three return entries spare while
it compiles; a word run from the interpreter has six; and CREATE ...
DOES> works from the prompt, from a word, and from a word that calls
that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:17:58 -04:00
rajamesandClaude Opus 5.5 dac7ffac92 feat(v4.0.0): the defining and compiling words
The fourth layer of the compiler capsule.  compile.v4: INTERPRET's
loop, STATE [ ] : ; EXIT IMMEDIATE LITERAL COMPILE [COMPILE] ' EXECUTE,
CREATE VARIABLE CONSTANT DOES>, and IF ELSE THEN BEGIN UNTIL AGAIN
WHILE REPEAT DO ?DO LOOP +LOOP on a control-flow stack in memory.
forth.v4: the first words of the vocabulary, the in-line ones.

FORTH source now goes in and running code comes out.  49 programmes
were run through the v3 binary and through this; every result agrees,
bar COMPILE, which v3 cannot run.  The code laid down for each control
structure is word for word the expansion DECOMPOSITION.md gives.

A line may have six values on the stack while it is interpreted, and
words called from the interpreter may nest eight deep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:42:23 -04:00
rajamesandClaude Opus 5.5 bbd1b4047f refactor(v4.0.0): the capsule's inner words keep their state in memory
WORD, the dictionary words and the code generator run underneath
whatever the user has on the stacks, which are ten and nine deep (D-2).
Measured, they used five to seven data cells of their own, leaving a
line about three.  Each now keeps what it works on in its file's
scratch cells and has at most three cells on the data stack; , calls
nothing; and the longest chains of calls are shorter.

The public words of core.v4, input.v4 and dict.v4 get dictionary
headers.  NUMBER is split so the interpreter can have a flag instead of
NODE-ERROR.  The host-node tests share one memory map, host_map.h.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:41:50 -04:00
rajamesandClaude Opus 5.5 44ffd261bb feat(v4.0.0): the text assembler takes &NAME and CONST+N
&NAME is the address of a word as a literal; CONST+N is a loader
constant plus an offset as one literal, so that a capsule file can
address the cells of its scratch area without adding at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:41:50 -04:00
rajamesandClaude Opus 5.5 26a6a16537 feat(v4.0.0): the text assembler lays down dictionary headers
'header NAME [flags]' in front of a word gives it a dictionary entry in
the layout capsule/dict.v4 uses, linked to the header before it, so the
words of a capsule are in the dictionary as soon as it is assembled.
The name is taken as it stands (it may be ( or + or ;) and the
assembler's own name for the code may differ.

Tested in the assembler's own test, and by FIND and the field words
running over assembler-made entries beside ones (HEADER) made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 09:58:26 -04:00
rajamesandClaude Opus 5.5 880560fc00 feat(v4.0.0): the code generator
The third layer of the compiler capsule, v4/capsule/codegen.v4: opcodes,
literals and branches packed into instruction words at HERE, by the
rules of sections 1.2 and 2.  (OP,) (LIT,) (LABEL) (BRANCH,) (JUMP,)
(CALL,) (BRANCH>) (RESOLVE) (FLUSH) (CG-RESET).

Tested by laying the same programmes down with the text assembler on
one node and with the code generator, running, on another, and
comparing memory word for word: every opcode, literals and branches in
every slot position, and 600 random programmes.  What it lays down is
then run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 09:19:57 -04:00
rajamesandClaude Opus 5.5 c10d3a9cca feat(v4.0.0): the dictionary: its space, its entries, and FIND
The second layer of the compiler capsule, v4/capsule/dict.v4: HERE ALIGN
ALLOT , C, 2, PAD LATEST; an entry layout reached entirely from the xt,
with >LINK LFA LINK> >NAME NFA NAME> CFA PFA >BODY TRAVERSE SMUDGE
HIDDEN on it; and FIND and ' .

FIND is FORTH-79's and v3's.  ' is FORTH-79's: the parameter field
address, which for a code word is what FIND gives.  ALLOT counts cells
(D-1).  31 characters of a name are significant.

Executed at both cell widths against a list of 300 entries kept in C.
WORD no longer holds its length on the return stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:59:06 -04:00
rajamesandClaude Opus 5.5 01b5bbb23f fix(v4.0.0): .R U.R and D.R print no trailing space
FORTH-79's reference .R right-justifies the number in its field and
prints nothing after it; v3 printed a space.  . U. and D. still print
their one space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 b137678691 fix(v4.0.0): MOVE follows FORTH-79
MOVE moves n cells, the cell at addr1 first, and nothing for n <= 0.
v3's moved bytes like memmove; CMOVE and CMOVE> do that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 e178a76c36 fix(v4.0.0): LEAVE follows FORTH-79
LEAVE sets the limit equal to the index: the rest of the body runs with
the index unchanged and the loop ends at the next LOOP or +LOOP.  v3's
left the loop at once, which is FORTH-83's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 7b42a9b6c1 fix(v4.0.0): EXPECT, QUERY and WORD follow FORTH-79
Ruled 2026-10-04: standard words follow the standard where v3 did not.

EXPECT takes up to n characters (v3 took n-1) and does nothing for
n <= 0.  QUERY takes up to 80 (v3: 1024).  WORD stores the delimiter it
met, or a zero at the end of the text, after the word, and leaves >IN
just past that one delimiter (v3 skipped them all and stored a zero);
the word may be up to 255 characters (v3: 62).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:37:44 -04:00
rajamesandClaude Opus 5.5 443439c3d2 feat(v4.0.0): reading a line and splitting it into words and numbers
The first layer of the compiler capsule, on the host node: TIB >IN SPAN
SOURCE BL EXPECT QUERY WORD ENCLOSE CONVERT NUMBER and the comment
words.  The definitions are text, v4/capsule/core.v4 (the core words
they rest on) and v4/capsule/input.v4, assembled by the text assembler,
which can now read a file.

EXPECT, QUERY, WORD and ENCLOSE behave as v3's.  CONVERT and NUMBER are
FORTH-79 (ruled 2026-10-04): any BASE, a double in the standard order,
and NUMBER returns a signed double or sets NODE-ERROR.

Executed at both cell widths against C and against values recorded from
the v3 binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:30:32 -04:00
rajamesandClaude Opus 5.5 31fcdcd0a3 feat(v4.0.0): a 16384-word host node for the compiler tests
Node memory is a build parameter.  Tests named test_host_*.c are now
built with V4_NODE_WORDS=16384, the host node that will hold the
compiler, the dictionary and the text being compiled; every other test
keeps the 1024-word mesh node.

The first such test checks the node at that size and the text
assembler's branch placement, which only matters there: a branch slot
that cannot reach the whole node is not used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:18:38 -04:00
rajamesandClaude Opus 5.5 7b710aa322 feat(v4.0.0): assemble definitions written as text
Test support, beside the slot packer: reads definitions in the notation
DECOMPOSITION.md uses -- words, opcodes, literals, constants, labels,
branches, FOR NEXT and FOR UNEXT, in-line macros, comments -- and lays
them down through the slot packer, so they no longer have to be retyped
opcode by opcode in C.

Tested by assembling SWAP, UM/MOD, C@ and C! both ways on two nodes and
comparing memory word for word, by running what is assembled, and on
every error it reports, each with its line number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:13:32 -04:00
rajamesandClaude Opus 5.5 861f800b7f feat(v4.0.0): KEY and ?TERMINAL on the console registers
?TERMINAL reads CONSOLE-STATUS; KEY polls it until a character is
pending and then takes it from CONSOLE-RX.  Executed on the golden
model at both cell widths, including a transcript of the v3 binary, and
KEY shown still waiting after 5000 instruction words with no input.

v3's KEY returned -1 at the end of its input; here KEY waits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:53:56 -04:00
rajamesandClaude Opus 5.5 2c16183788 feat(v4.0.0): CONSOLE-RX and CONSOLE-STATUS on the single-node model
The console's receive side, standing in for the console node until the
mesh exists, as CONSOLE-TX does for output.  A data fetch (@, @+, @b)
from CONSOLE-STATUS gives -1 when a character is pending and 0 when
not; from CONSOLE-RX it gives the next character and takes it, or -1
with none pending.  The characters come from a queue the test feeds.

Instruction words and literals are still fetched with v4_node_load, so
code at a register's address is never taken for the register.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:53:56 -04:00
rajamesandClaude Opus 5.5 03d8d991ef feat(v4.0.0): the DO loop runtimes
(DO) (?DO) (LOOP) (+LOOP) (LEAVE) I J UNLOOP and (0BRANCH), laid down
in line by hand as the compiler will, executed on the golden model at
both cell widths against C on every pair of 14 loop ends and 11 steps,
and against sequences recorded from the v3 binary.

(LOOP) goes round again while index < limit, signed, as v3 does; the
document's equality test differed whenever start >= limit.  (+LOOP) is
now specified.  J keeps the outer index in A and needs no extra return
entry.

LEAVE discards the limit and index.  v3 left them on its return stack,
which made a LEAVE in an inner loop stop the outer one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:13:24 -04:00
rajamesandClaude Opus 5.5 481d484e93 feat(v4.0.0): the mixed and double leftovers
M- M* M/MOD MOD */ */MOD, D0< D2* D2/ 2ROT, 2DROP and 2>R 2R@ 2R>,
beside UM* and SM/REM in test_foundation.c.  Executed on the golden
model at both cell widths against C and results recorded from the v3
binary.

M- widens n before negating it, so the most negative n is right.
*/MOD goes through a full double product.  D2/ is one +* step.
M- and M/MOD take the double in the standard order ( lo hi ), as M+
does; v3 took its low cell on top.

The foundation test's node is now full: 958 of the 960 words below its
variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 18:37:53 -04:00
rajamesandClaude Opus 5.5 84c7711763 feat(v4.0.0): the small single-cell words
NIP SWAP ROT -ROT ?DUP 2DUP, >R R@ R>, @ ! +! -! 2@ 2! CELLS,
- NEGATE 1+ 1- 2+ 2- MIN MAX, OR NOT 0= 0< 0<> 0> = <> < > <= >= U<
WITHIN TRUE FALSE in a new test, and * and / beside UM* and /MOD in
test_foundation.c.  Executed on the golden model at both cell widths
against C on every combination of the edge values and against recorded
transcripts of the v3 binary.

WITHIN is low <= n < high with signed comparisons, which is what v3
computes; the document's circular form differed for low > high.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:49:30 -04:00
rajamesandClaude Opus 5.5 cb66db1107 feat(v4.0.0): the byte-string words
FILL ERASE MOVE, COUNT CMOVE CMOVE> BLANK -TRAILING COMPARE SEARCH SCAN
SKIP, as loops over the call-free C@ and C!, executed on the golden
model at both cell widths against C and five recorded transcripts of
the v3 binary.

A negative count reads as 0 where v3 read it so, and elsewhere writes
nothing and sets NODE-ERROR.  v3's counted-string auto-detection is not
kept in any of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:25:27 -04:00
rajamesandClaude Opus 5.5 7c5be22799 feat(v4.0.0): C@ is call-free
One case per byte position, like C!: the cell is shifted down with a
2/ loop and masked.  It replaces the version built on LSHIFT, RSHIFT
and SWAP calls.  C@ now leaves its caller 7 return entries (was 4), and
the words above it gain with it: TYPE 6 (was 3), DUMP 4, Q.PRINT, U.
and U.R 3 (were 2).  The signed number words stay at 2: their sign
waits on the return stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:15:57 -04:00
rajamesandClaude Opus 5.5 e50cc1f73a feat(v4.0.0): BASE, DECIMAL, HEX, OCTAL and HLD
BASE and HLD leave their variable's word address; DECIMAL, HEX and
OCTAL store 10, 16 and 8.  Executed on the golden model at both cell
widths, including a recorded transcript of the v3 binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:46:38 -04:00
rajamesandClaude Opus 5.5 030ca63639 feat(v4.0.0): ?, Q.PRINT and DUMP
Built on the number-output words and executed on the golden model at
both cell widths against a C reference and recorded transcripts of the
v3 binary (DUMP byte for byte at 64-bit cells).

Q.PRINT is signed (D-8) and always decimal; DUMP is always hex; both
put BASE back.  Each keeps its working state in a variable, (QP) and
(DP), so each leaves its caller 4 data cells and 2 return entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:33:19 -04:00
rajamesandClaude Opus 5.5 13335dcc9c feat(v4.0.0): . U. D. .R U.R D.R and SPACES
The number-printing words, on pictured output and TYPE, executed on the
golden model at both cell widths against a C reference (ten bases,
eleven field widths) and six recorded transcripts of the v3 binary.

Each plain word is its .R word with a width of 0; all six share one
tail.  The field width waits in a variable, (W), so the picture runs no
deeper than it does on its own: each word leaves its caller 4 data
cells and 2 return entries.

As v3, the .R words print a trailing space.  Unlike v3, D. takes
( lo hi ), prints the whole double, and printing honours BASE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:51:27 -04:00
rajamesandClaude Opus 5.5 40178098e9 feat(v4.0.0): EMIT, CR, SPACE and TYPE on the console register
: EMIT  ( c -- )        CONSOLE-TX b! !b ;
  : CR    ( -- )          10 jump EMIT
  : SPACE ( -- )          32 jump EMIT
  : TYPE  ( baddr u -- )
    -if OK  drop drop  NODE-ERROR b! -1 !b ;
    OK: if DONE  over C@ EMIT  push 1 + pop  -1 +  jump OK
    DONE: drop drop ;

They follow v3 (v3/src/word_source/io_words.c): EMIT prints the low byte
of the cell, CR character 10, SPACE a blank; TYPE prints u bytes,
nothing for u = 0, and for u < 0 nothing, with NODE-ERROR set where v3
raised its error flag. TYPE does not check the address range, which v3
does; out-of-range addressing is still an open question in node.h.

New test v4/tests/test_terminal.c, on a node of its own with the console
attached, 939 checks per width. Two transcripts of the real v3 binary
are recorded as expected output:
  65 EMIT 66 EMIT SPACE 67 EMIT CR 68 EMIT 321 EMIT  ->  "AB C\nDA"
  S" Hello, v3" TYPE 91 EMIT <text> 0 TYPE 93 EMIT   ->  "Hello, v3[]"
Also: EMIT of every byte and of wider values, CR, SPACE, TYPE from every
start within a cell at lengths 0..40, bytes with the top bit set and
zero bytes, negative counts, and that TYPE writes no memory. At 32- and
64-bit cells, optimised and ASan+UBSan (`make test`, `make sanitize`).
Five mutations each fail.

Headroom (data cells under args / return entries): EMIT 8/8, TYPE 4/3.
TYPE's depth is C@'s, which is still as written (C@ -> RSHIFT -> SWAP).

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 12:13:25 -04:00
rajamesandClaude Opus 5.5 7e3932a4ad feat(v4.0.0): CONSOLE-TX capture register on the single-node model
EMIT is a device service: a character sent to the console node. The
mesh and its ports are development step 2 and the memory map is open
(D-4), so the single-node model now stands in for the console with one
memory-mapped register, so that printing words can be run and their
output compared with v3's.

v4_node_console_attach(n, addr): after it, a store to word address
`addr` appends the low 8 bits of the value to a buffer on the node
(V4_CONSOLE_CAP characters, 4096 by default) and does not write memory;
a load from `addr` reads the memory word as before. Characters past the
capacity are counted in console_dropped and discarded. The hook is in
v4_node_store, which all four store opcodes use.

It is off by default: v4_node_reset detaches the console (address -1)
and empties the capture, so the ISA's behaviour and every existing test
are unchanged unless a console is attached. The address is the
caller's choice.

New test v4/tests/test_console.c, 22 checks per width: direct stores,
!b, ! and !+ through the executor printing "Hi!", memory at and around
the register untouched, the low byte only, overflow, detach, a console
at word 0, and reset. At 32- and 64-bit cells, optimised and ASan+UBSan
(`make test`, `make sanitize`); all other v4 tests still pass. Four
mutations of the hook each fail.

DECOMPOSITION.md section 7 gains the CONSOLE-TX row. No printing word is
defined here; EMIT and the words on it are still to do.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:57:49 -04:00
rajamesandClaude Opus 5.5 7a21f07ad5 feat(v4.0.0): # keeps its high quotient on the data stack
`#` held the high quotient on the return stack across its second
UM/MOD, which was the deepest point of pictured output once C! was made
call-free. It now rotates it under the division on the data stack
(-ROT in line: SWAP push SWAP pop).

Headroom, return entries: <# #S #> 2 -> 3, the signed picture 1 -> 2.
Data room is unchanged.

Same 4716 checks per width at 32- and 64-bit cells, optimised and
ASan+UBSan (`make test`, `make sanitize`); the headroom checks now
require the new figures.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:51:03 -04:00
rajamesandClaude Opus 5.5 638aeb6636 feat(v4.0.0): call-free C!
C! as written in 5.3 called RSHIFT and LSHIFT (which call SWAP) and OR.
It is now one straight-line case per byte position: the byte is shifted
up with a `2* unext` loop, that byte of the cell cleared with a constant
mask, and the two added. The word address is `2/ 2/` of the byte
address. The upper half of a 64-bit cell is still preserved.

Headroom (data cells under args / return entries): 5/4 -> 7/7.

Same checks as before (every byte of two adjacent words, eight values,
neighbours and the upper half untouched) at 32- and 64-bit cells,
optimised and ASan+UBSan (`make test`, `make sanitize`). Four mutations
fail, one of them only at 64-bit cells, where it differs.

test_pictured.c carries the same C!. The pictured words did not gain
return-stack room from this: <# #S #> still leaves 2 entries and the
signed picture 1. With C! shallow, the deepest point is now inside `#`,
which holds the high quotient on the return stack across its second
UM/MOD. Recorded in 5.8; `#` is unchanged.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:45:52 -04:00
rajamesandClaude Opus 5.5 6a019b8968 feat(v4.0.0): pictured output <# # #S HOLD SIGN #>; D-13
DECOMPOSITION.md 5.8 only named these as "standard pictured-output
definitions over UM/MOD and a hold buffer". They are now written out
(5.8) and run on the golden model.

D-13 (ruled 2026-10-03): the hold buffer takes 63 characters, as v3's;
HOLD of a value outside 0-255, or into a full buffer, stores nothing and
sets NODE-ERROR, which is what v3 did with its error flag.

Behaviour follows v3 otherwise: digits 0-9 then A-Z, BASE outside 2..36
reads as 10, SIGN ( n -- ). Stack effects are the standard ones, as 5.8
already ruled (v3 took its double low cell on top). The buffer is 64
bytes, filled backwards from its end through HLD; `#` divides by the
base in two UM/MOD steps. HOLD, SIGN and # end in a jump to the next
word instead of a call, which saves two return-stack entries: with
calls, the signed picture `.` needs overflowed the 9-deep return stack.

New test file v4/tests/test_pictured.c, on a node of its own:
test_foundation.c's hand-assembled words already fill 901 of a node's
1024 words. It re-assembles SWAP, OR, UM/MOD, LSHIFT, RSHIFT and C! as
they are in test_foundation.c.

Checked against a C reference (short division on 16-bit limbs) at 32-
and 64-bit cells, optimised and ASan+UBSan (`make test`, `make
sanitize`), 4716 checks per width: <# #S #>, <# # # 46 HOLD #S #> and
the signed picture, in bases 10, 16, 2, 8, 36, 3 and the invalid 0, 1,
37, -5, on every pair of 15 edge cells; HOLD of 12 values; and a base-2
number that overflows the buffer (63 characters kept, NODE-ERROR set,
nothing outside the buffer written). Six mutations all fail.

Headroom: <# #S #> leaves 3 data cells and 2 return entries; the signed
picture leaves 1 return entry. The depth is C!'s as written (C! ->
LSHIFT -> SWAP), which is unchanged.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:37:08 -04:00
rajamesandClaude Opus 5.5 2e4d1330ea test(v4.0.0): execute C@ and C! on the golden model
Both run exactly as written in DECOMPOSITION.md 5.3 and need no change:
four bytes to a cell, little-endian, byte address = 4 * word address +
byte index, at either cell width.

Checked at 32- and 64-bit cells, optimised and ASan+UBSan (`make test`,
`make sanitize`): every byte of two adjacent words, eight values
including ones wider than a byte, with the other bytes of the word, the
upper half of a 64-bit cell and the neighbouring words left untouched.
Breaking C!'s mask or C@'s mask fails.

Headroom (data under args / return): C@ 6/4, C! 5/4.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:16:16 -04:00
rajamesandClaude Opus 5.5 f030edcd08 test(v4.0.0): execute LSHIFT and RSHIFT on the golden model
Both run exactly as written in DECOMPOSITION.md 5.5 and need no change.
Checked against C on the edge vectors for every count 0 .. N (a count
of N gives 0), at 32- and 64-bit cells, optimised and ASan+UBSan
(`make test`, `make sanitize`). Removing RSHIFT's sign-bit mask fails.

Headroom (data under args / return): 7/5 each.

They are dependencies of C@ and C!, which the pictured-output hold
buffer needs.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:10:03 -04:00
rajamesandClaude Opus 5.5 13ec4b1b6c test(v4.0.0): execute the in-line constants Q.1, Q.0 and Q.SCALE
DECOMPOSITION.md 5.26 gives them fate IN: the compiler places two
literals, low cell first. Q.1 and Q.SCALE are `65536 0`, Q.0 is `0 0`;
v3's are 65536, 0 and 65536.

Each expansion is assembled and run, and checked against v3's value;
then in use: Q.1 Q.TO-INT is 1, 1 Q.FROM-INT is Q.1, and q Q.1 Q.* and
q Q.0 Q.+ return q for 2000 pseudo-random q plus 0, Q max and Q min.
At 32- and 64-bit cells, optimised and ASan+UBSan (`make test`,
`make sanitize`). A wrong value in any of the three fails.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:03:57 -04:00
rajamesandClaude Opus 5.5 8235078b3b feat(v4.0.0): Q.COS, bit for bit with v3
Q.COS is v3's q48_cos_approx: on |(Q.REDUCE) x|, the even Taylor series
to n = 10. It sets term and sum to 1.0, n to 2 and the sign cell to 0,
then jumps into Q.SIN's loop, so it adds no call level.

Checked bit for bit against v3's q48_cos_approx (ported into the test)
on the same 33 edge angles and 3000 pseudo-random angles as Q.SIN, at
32- and 64-bit cells, optimised and ASan+UBSan (`make test`,
`make sanitize`). Mutating the start index, the start sum, the
alternation or the sign cell each fails 2500+ cosine checks and no sine
checks.

Headroom (data under arg / return): Q.COS 3/2.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:53:52 -04:00
rajamesandClaude Opus 5.5 1ce705783c feat(v4.0.0): Q.SIN and (Q.REDUCE), bit for bit with v3
(Q.REDUCE) is v3's q48_reduce_angle: the angle as one cell in [-pi, pi].
x / 2pi does not fit a cell, but only the remainder is needed, and
|x| mod 2pi is two UM/MOD steps (high cell first, its remainder leading
the low cell); then the sign of x and one step of 2pi back into range.

Q.SIN is v3's q48_sin_approx on the reduced angle: the odd Taylor series
to n = 11, each term the last times x^2 over n(n-1), stopping below 10
ulp. After the reduction every value fits one cell, so the 6-cell
variable (QT) holds single cells. The loop is laid out for Q.COS to jump
into, so the pair share it without an extra call level.

Checked bit for bit against v3 (both functions ported into the test) on
33 edge angles -- around +-pi/2, +-pi, +-2pi, the 32-bit seam and both
64-bit extremes -- and 3000 pseudo-random angles of every size and sign,
at 32- and 64-bit cells, optimised and ASan+UBSan (`make test`,
`make sanitize`). Mutating either range boundary, the series length or
the sign alternation fails. Moving the 10-ulp stop to 11 fails nothing,
and a scan of all 205888 reduced angles in C shows why: no input's
result depends on it, for sine or cosine.

Headroom (data under arg / return): (Q.REDUCE) 5/5, Q.SIN 3/2.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:44:42 -04:00
rajamesandClaude Opus 5.5 e117333a87 feat(v4.0.0): Q.LOG, flattened, bit for bit with v3
Q.LOG is v3's q48_log_approx: x = 2^k * m with 1.0 <= m < 2.0, ln m by
up to 6 Newton rounds on e^y = m, result y + k * ln 2. As ruled, e^y is
Q.EXP's Taylor loop written in line rather than a call to Q.EXP, so
Q.LOG calls only Q.*, Q./ and UM*. After the reduction m, y, the Taylor
term and its sum each fit one cell, so the 7-cell variable (QL) holds
single cells. x <= 0 returns 0 and sets NODE-ERROR (D-12).

Checked bit for bit against v3's q48_log_approx (ported into the test)
on 22 positive edge values, 2000 pseudo-random x of every magnitude and
a sweep of every 17th reduced m, at 32- and 64-bit cells, optimised and
ASan+UBSan (`make test`, `make sanitize`). Mutating the round count, the
100-ulp stop, ln 2 or the Taylor length all fail.

v3's clamp y = max(y - corr, 0) is kept but cannot fire: a scan of all
65536 values of m in C never reaches it, and never needs more than 4
rounds. So no test covers it.

The test harness's per-call step limit is raised from 100000 to 4000000
instruction words: a 64-bit Q./ takes about 6500, and a mutant forcing
extra Newton rounds ran past the old limit and looked like a width
difference.

Headroom (data under arg / return): Q.LOG 3/2.

Test results on the amd64 host only. This is a development check, not
acceptance (JUSTIFICATION.md section 16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:29:59 -04:00
rajamesandClaude Opus 5.5 a2a4a85d38 docs(v4.0.0): record the three products and v4's acceptance criteria
Both ruled by Captain Bob, 2026-10-03.

Products (README.md, JUSTIFICATION.md section 15): Hosted StarForth F18
(native Linux, amd64/arm64/riscv64, on hardware); FPGA StarForth F18 (a
32-bit build loaded into the FPGA, the gateway and foundation); and
StarshipOS (bare metal, LithosAnanke on the v4 F18 engine). FORTH-79
recomposed on the F18 engine is stored as a capsule, as are the
StarshipOS portions; the tree will be reorganised around this.

Acceptance (JUSTIFICATION.md section 16, v4/README.md): v4 is equivalent
to v3 at any point in time -- same vocabularies, same behaviour, on the
F18-derived engine -- and every ISA, hosted and bare metal, must still
reach its ok prompt. `make -C v4 test` is a development check, not
acceptance. v4 had no acceptance criteria before this.

Documentation only; no code changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:13:58 -04:00
rajamesandClaude Opus 5.5 f4bfe7de02 logs: three-architecture kernel acceptance baseline at a2d21d5c
Baseline run for StarForth-v4.0.0 as it stands, before any further work.
`make -f kernel/Makefile ARCH=<arch> clean qemu` for amd64, aarch64 and
riscv64, one at a time, disk/artemis.img and
disk/thumbdrives/zuse-thumb-ident.img restored to their committed state
before each.

All three reach `[zuse@Hera] ok>`, with zero UNKNOWN WORD, PARITY:OK,
1050 POST tests run and ALL IMPLEMENTED TESTS PASSED,
stadium_conserved(Artemis)=true.

dict_hash is identical across the three:
  Hera (PARITY:M7.1a, word_count=530)  0x08873e0f44b7cb2a
  dict_hash                            0xe11082140cf86b05
  dict_hash                            0xb1256603f848e2b9
  dict_hash                            0xc791409ac1715690

QEMU was asked to quit over QMP once the prompt had appeared and the
serial log had been quiet for 10 seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:11:25 -04:00
rajamesandClaude Opus 5.5 a2d21d5cda feat(v4.0.0): Q.SQRT bit for bit with v3; D-12 domain errors
D-12 (ruled 2026-10-02): Q.SQRT of a negative value and Q.LOG of zero or
a negative value return 0 and set NODE-ERROR, as Q./ does on division by
zero.

Q.SQRT is v3's q48_sqrt_approx: Newton from x0 = q/2 + 0.25, up to 8
rounds of x' = (x + q/x) / 2, returning x once |x' - x| < 10 ulp;
sqrt(0) = 0 and sqrt(1.0) = 1.0. q, x and the rounds left live in a
5-cell variable (QR). Checked bit for bit against v3's q48_sqrt_approx
(ported into the test) on 19 edge values and 3000 pseudo-random q below
2^48, at both cell widths, optimised and ASan+UBSan. Above 2^48 v3's
q48_div saturates and v4 divides correctly, so there is no parity there.

Bug found and fixed on the way: the "< 10 ulp" test subtracted 10 from
the step's low cell as a signed number, so at 32-bit cells a step of
2^31 or more read as small and the iteration stopped early. It now
tests the low cell's top bit first, as Q.EXP does. The first test run
missed it because `make build/32-test_foundation.c` rebuilds nothing
(the Makefile's rules use absolute paths); the mutation runs, compiled
from source, exposed it. Only `make test` is used from here.

Headroom (data under arg / return): Q.SQRT 3/2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:07:30 -04:00
rajamesandClaude Opus 5.5 29cf2688d2 feat(v4.0.0): Q.EXP bit for bit with v3; lighter D2*C and (UQ/)
Q.EXP is v3's q48_exp_approx: the Taylor series to 10 terms on |q|,
stopping below 50 ulp, 1.0 Q./ e^|q| for q < 0, e^0 = 1.0, and for
|q| >= 16.0 either 0 or Q max (v3 returned all ones, which is -ulp read
signed under D-8). x, term, sum, sign and term index live in a new
8-cell variable (QE). Checked bit for bit against v3's q48_exp_approx
(ported into the test) on 23 edge values and 3000 pseudo-random q in
(-16.0, 16.0), at both cell widths, optimised and ASan+UBSan; dropping a
term, moving the 50-ulp stop or skipping the reciprocal all fail.

Q.EXP calls Q./, which calls (UQ/), which calls D2*C, and at first it
left its caller no return entries. Lightened along the chain:
- D2*C takes cin in A and builds 2hi+m with `over + +`: no ROT, no SWAP.
- (UQ/) parks the quotient bit instead of using ROT, stores q without
  SWAP, and does its full trial subtraction (with borrow) in line
  instead of calling DNEGATE D+.
- Q.EXP keeps its term index in (QE) instead of a FOR count.

Headroom (data under args / return): (UQ/) 4/3 -> 4/4, Q./ 3/2 -> 3/3,
Q.EXP 3/2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 00:26:36 -04:00
rajamesandClaude Opus 5.5 9e03bdab19 feat(v4.0.0): Q./ under D-11, with (UQ/), D2*C and the (Q/) variable
D-11 (ruled 2026-10-02): Q./ rounds toward zero, saturates to Q max /
Q min on overflow, and on division by zero returns Q max / Q min by the
dividend's sign (0 for 0/0) and sets the new NODE-ERROR register (7),
which VM-ERROR? reads.

- (UQ/): unsigned floor(a * 2^16 / b) for b != 0 and no overflow.
  Restoring division, 2N+16 steps, on one shifting register (quotient
  above remainder). Quotient register and divisor live in a 5-cell
  variable (Q/), like BASE and the hold buffer, so the stacks carry only
  the remainder, the quotient bit and the loop count. A first version
  kept the divisor on the return stack and overflowed it when called
  from Q./ (it never returned).
- D2*C: double shift left with carry in and out.
- Q./: zero-divisor handling, signs (kept in (Q/)), an overflow test
  that needs no division (|a| * 2^16 >= |b| * 2^(2N-1), possible only
  for |b| < 2^17), then (UQ/) and the sign.

Checked at 32- and 64-bit cells, optimised and ASan+UBSan, against an
independent limb-by-limb long division (including NODE-ERROR): every
pair of 18 edge Q values, 13 width-native edge values (true Q max/min at
either width), the overflow boundary, divisors in [2^(2N-2), 2^(2N-1)),
and pseudo-random cases; and against v3's q48_div for non-negative
a < 2^48. Q.* now also runs on the width-native edge values.
Mutations of the compare paths, the take path, the error flag and the
overflow mask are all caught (the mask matters only for Q min / -1.0).

Headroom (data under args / return): Q./ 3/2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 00:17:11 -04:00
rajamesandClaude Opus 5.5 8f37e15f8a feat(v4.0.0): repack Q.* so no UM* call holds all four inputs
Q.* now forms its products in the order a1*b1 (low cell), a0*b1, a1*b0,
a0*b0, dropping each input after its last use, with b0 waiting on the
return stack. Each sign correction, (b1<0 ? a0 : 0) and (a1<0 ? b0 : 0),
is folded into cell 2 as soon as its operands are adjacent, using -if
rather than 0< calls. At most four live values sit under any UM* call.

Headroom (data cells under args / return entries): 2/2 -> 3/3.

Same checks as before at 32- and 64-bit cells, optimised and ASan+UBSan;
dropping either sign correction fails about 9900 checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:33:57 -04:00
rajamesandClaude Opus 5.5 54e1cdafb1 feat(v4.0.0): UM* corrections after the loop; return headroom 4 -> 6
UM* parked its three corrections (c_hi, c_lo, t0) on the return stack
before the +* loop, leaving its caller 4 return entries. Now u1 and u2
wait on the data stack under the loop -- +* touches only T, S and A --
and the corrections are made after it, with -if in place of 0< calls.
The return stack holds the loop count, then at most two temporaries.
The loop count is pushed before s is made, so the data stack never holds
more than four cells: data headroom is unchanged at 6.

Headroom (data cells under args / return entries): 6/4 -> 6/6.
Q.*, which calls UM* four times, goes from 2/1 to 2/2.

Same checks as before at 32- and 64-bit cells, optimised and
ASan+UBSan; breaking any of the four corrections fails 4900+ checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:31:52 -04:00
rajamesandClaude Opus 5.5 ab3b708540 feat(v4.0.0): Q.* from four UM* cell products
Q.* is floor(a*b / 2^16), signed (D-8), cut to two cells. Cells 0..2 of
the product come from the unsigned cell products a0*b0, a0*b1, a1*b0 and
the low cell of a1*b1; reading a1 and b1 as signed takes
(a1<0 ? b0 : 0) + (b1<0 ? a0 : 0) off cell 2. The result is cells 0..2
shifted right 16 with Q.TO-INT twice. Clobbers A.

Checked at 32- and 64-bit cells, optimised and ASan+UBSan, on every pair
of 17 edge Q values plus 20000 pseudo-random pairs:
- against an independent reference (16-bit limbs, magnitudes multiplied
  schoolbook, negated, shifted), and
- against v3's q48_mul for non-negative operands.

The first draft applied only a1's sign correction; the reference caught
the missing b1 term (9860 failures at 32-bit cells).

v3 bug found, not fixed: q48_mul's portable branch (used where there is
no __int128) returns (result_hi << 16) | (result_lo >> 16); the high
part must move up 48, so it is wrong whenever the product passes bit
64, e.g. 0.5 * Q max gives 0000ffffffffffff instead of 3fffffffffffffff.
The parity reference here is that branch with the shift corrected,
which matches v3's __int128 branch.

Stack use is tight: Q.* leaves its caller 2 data cells and 1 return
entry, because UM* parks three values on the return stack. Recorded in
5.26; to be improved next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:27:57 -04:00
rajamesandClaude Opus 5.5 d0accdbb88 feat(v4.0.0): D< and Q comparisons; call-free (D<), DMAX, DMIN, 2SWAP
Executed on the golden model as written, and correct: <, =, D<, 2OVER,
and Q.=, Q.<, Q.0= (the D=, D<, D0= words).

Fixed, because they could not work under D-2 or were wrong:
- DMAX, DMIN: 2OVER 2OVER D< needs 8 data cells plus D<'s 2, the whole
  10-deep data stack, so both failed on every case once the caller held
  anything. Rewritten on a new call-free helper
    (D<) ( d1 d2 -- d1 d2 flag )
  which compares copies of the high cells, then the low cells unsigned
  on a tie, with in-line sign tests; DMAX and DMIN then drop the loser.
- 2SWAP: ROT and SWAP written in line. Return headroom 2 -> 4, which
  also lifts 2OVER 1 -> 3 and Q.> 1 -> 2.
- Q.>: section 5.26 gave SWAP D<, which swaps single cells; it was wrong
  in 11702 of 20169 cases. Now 2SWAP D<.

Checked at 32- and 64-bit cells, optimised and ASan+UBSan: every
edge-vector quadruple (50625) for D<, (D<), 2SWAP, 2OVER, DMAX and DMIN;
Q comparisons on every pair of 13 edge Q values plus 20000 pseudo-random
pairs weighted to ties and one-bit differences, signed (D-8) and against
v3's unsigned comparisons where both values have the same sign.
Mutating any (D<) branch or subtraction fails 700+ checks.

The new fatal-UBSan setting caught a test-side array overflow in the
headroom probe (results buffer sized 4, six needed); fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:06:25 -04:00
rajamesandClaude Opus 5.5 167fdc3973 build(v4): make UBSan reports fatal in make sanitize
Without -fno-sanitize-recover=all, UBSan prints a report and the run
carries on to "all v4 tests passed". The sanitize build now aborts on
the first report. Verified by rebuilding the test-side shift bug found
in 981f4180 with these flags: the run exits 1 at the report.

Both test binaries now also depend on v4/Makefile, so a flag change
rebuilds them instead of leaving stale binaries in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:59:50 -04:00
rajamesandClaude Opus 5.5 981f4180ce feat(v4.0.0): Q.FROM-INT and Q.TO-INT as +* double shifts
DECOMPOSITION.md 5.26 described both words in prose only. They are now
written out, call-free, on one observation: +* with S = 0 never adds, so
each step is an exact arithmetic right shift of the double T:A.

  : Q.FROM-INT ( n -- q )  push 0 a! 0 pop  15 FOR +* UNEXT  push drop a pop ;
      T:A = n:0 is n * 2^N; N-16 shifts leave n * 2^16 (count 15 at
      32-bit cells, 47 at 64).
  : Q.TO-INT ( q -- n )    push a! 0 pop  15 FOR +* UNEXT  drop drop a ;
      16 shifts at every width; the low cell is left in A. Rounds toward
      minus infinity, as v3's arithmetic shift does.

Both clobber A; added to the section 2 list.

Checked at 32- and 64-bit cells, optimised and ASan+UBSan:
- Q.FROM-INT against n * 2^16 for edge values and 20000 pseudo-random n,
  and against v3's q48_from_u64 for n >= 0 (low cell at 64-bit, D-10).
- Q.TO-INT against v3's (int64_t)q >> 16 on the edge Q values and 20000
  pseudo-random Q values, and against a C double shift on 20000
  arbitrary doubles.
- Round trip Q.TO-INT(Q.FROM-INT(n)) = n.
Mutating either shift count or the S = 0 setup fails 40000+ checks.

Note: make sanitize prints UBSan reports but does not fail on them. One
was found here, in the test's own random shift amount (fixed); a grep of
the full sanitize output now shows no runtime errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:58:04 -04:00
rajamesandClaude Opus 5.5 d948e0c1a3 test(v4.0.0): D-10 two-cell Q48.16; execute Q.ABS and Q.NEG against v3
D-10 (ruled 2026-10-02): a Q48.16 value is two cells at every cell
width, so every Q word is the same double word on 32- and 64-bit nodes.
Recorded in DECOMPOSITION.md section 3 and 5.26; the open note on the
Q.+/Q.- row is resolved by it.

Q.ABS and Q.NEG are the DABS and DNEGATE words. Checked against v3's
q48_abs and 0 - q on the 15 edge Q values and 20000 pseudo-random
values, at 32- and 64-bit cells, optimised and ASan+UBSan:
- 32-bit cells: bit-for-bit v3, including v3's wrap of Q min to itself.
- 64-bit cells: the low cell is v3's; the high cell is the true sign
  (so ABS and NEG of Q min give +2^63 rather than wrapping), per D-10.
Breaking DNEGATE's carry fails Q.NEG, Q.ABS and Q.- checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:54:40 -04:00
rajamesandClaude Opus 5.5 4f493fa317 test(v4.0.0): note Q.+/Q.- coverage in test_foundation.c header
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:52:54 -04:00
rajamesandClaude Opus 5.5 5ac52f19d6 test(v4.0.0): execute Q.+ and Q.- against v3 Q48.16
DECOMPOSITION.md 5.26 makes Q.+ and Q.- the D+ and D- words. They are
checked against v3's q48_add/q48_sub (uint64_t a + b, a - b, wrapping)
on every pair of 15 edge Q values (0, ulp, 0.5, 1.0, 1.5, -1.0, -ulp,
values across the 32-bit seam, Q max and min, +-12345.0) and 20000
pseudo-random pairs, 2682 of which overflow Q48.16.

- 32-bit cells: bit-for-bit v3's result, overflow wrap included.
- 64-bit cells, with a Q value as a sign-extended double: the low cell is
  v3's result; on overflow the high cell holds the true carry where v3
  wraps. Whether a Q value is one cell or two on a 64-bit node is not
  ruled; recorded as open in 5.26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:52:27 -04:00
rajamesandClaude Opus 5.5 6a371b850e test(v4.0.0): execute M+, D-, D0= and D= on the golden model
All four run exactly as written in DECOMPOSITION.md 5.6/5.7 and need no
change now that D+ and DNEGATE are call-free.

Checked against C at 32- and 64-bit cells, optimised and ASan+UBSan:
every edge-vector combination (M+ over all triples, D- and D= over all
50625 quadruples, D0= over all pairs) plus 20000 pseudo-random cases
weighted to equal low or high cells and low sums that wrap to 0.
Mutations of D0= and M+ are caught.

Headroom (data cells under args / return entries under return address):
  M+ 6/4, D- 5/4, D0= 7/7, D= 5/3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:50:30 -04:00
rajamesandClaude Opus 5.5 092036c97a feat(v4.0.0): call-free D+ (D-2 stack headroom)
D+ as written in 5.7 was exact but kept two cells on the return stack
while calling U> -> SWAP/U<, leaving its caller one return entry: any
word calling a word that calls D+ (M+, D-, D=, Q.+, Q.-) would have a
return address silently overwritten.

The new D+ makes no calls. Both high cells wait on the return stack; the
carry out of the low-cell add comes from sign tests -- if the low cells'
top bits differ, there is a carry exactly when the sum's top bit is
clear; if they match, exactly when both are set.

Headroom (data cells under args / return entries): 4/1 -> 6/5.
Checked against C over all 50625 edge-vector quadruples and 20000
pseudo-random pairs (weighted to top-bit cases and low sums wrapping to
0), at 32- and 64-bit cells, optimised and ASan+UBSan. Retargeting each
of the four carry branches fails more than 13000 checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:46:11 -04:00
rajamesandClaude Opus 5.5 93d09840da feat(v4.0.0): SM/REM and DNEGATE call-free; execute /MOD and its section 5 words
SM/REM as written in section 4 never returned correctly for a negative
dividend. It holds three entries on the return stack and then calls
DABS -> DNEGATE -> D+ -> U> -> SWAP/U<, which overflows the 9-deep
circular return stack (D-2). DABS itself could not run: DNEGATE as
written (inv SWAP inv SWAP 1 0 D+) left its caller no return entries.

- DNEGATE: inv over if L1 drop push inv 1 + pop ; L1: drop 1 + ;
  i.e. ~d + 1, carrying into the high cell exactly when lo = 0.
- SM/REM: sign tests are native -if (as in 0<) and NEGATE is in line;
  the only calls are DNEGATE and UM/MOD, both call-free inside.

Executed on the golden model at 32- and 64-bit cells, optimised and
under ASan+UBSan:
- SM/REM on dividends built as q*n + r with |r| < |n| and r signed as
  d: every edge-vector q, n with r = 0 and r = +-(|n|-1), plus 20000
  pseudo-random cases.
- /MOD, U>, ABS, S>D, D+ and DABS as written in section 5, against C
  (D+ over all 50625 edge-vector quadruples).
Mutations of DNEGATE's carry and of each SM/REM sign branch are caught.

Headroom (data cells under args / return entries under return address):
  SM/REM 5/3, /MOD 5/2, DNEGATE 7/7, DABS 7/6, ABS 8/7, U> 6/5.
D+ as written is exact but leaves only 1 return entry; recorded in
DECOMPOSITION.md 5.7 as not yet revised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:44:04 -04:00
rajamesandClaude Opus 5.5 3b9d1e4337 feat(v4.0.0): call-free UM/MOD loop for D-2 stack headroom
The first UM/MOD was exact but called 0<, U<, SWAP and OR inside its
loop, so it left its caller only 3 return-stack entries. SM/REM pushes
two signs before calling it, so under /MOD, M/MOD or */MOD the caller's
return address would be silently overwritten (D-2 circular stacks).

The loop now makes no calls. It branches on hi's top bit with -if, does
the unsigned hi' >= d test as U< does but with in-line sign tests,
subtracts with `inv a + inv`, and sets the quotient bit with `1 +` on an
even lo'. The final SWAP is in line.

Measured on the golden model at 32- and 64-bit cells:
  headroom   data 3 -> 6 cells under args, return 3 -> 6 entries
  speed      ~1355-1605 -> ~227-313 instruction words per call
Still exact for every uhi < ud (edge-vector triples and 20000 random
cases, optimised and ASan+UBSan). Retargeting each of the four in-loop
branches to the wrong label fails more than 12000 checks each.

DECOMPOSITION.md: section 4 UM/MOD replaced, with its derivation and
stack limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:35:49 -04:00
rajamesandClaude Opus 5.5 41f59afeb3 test(v4.0.0): execute UM/MOD on the golden model; measure stack headroom
UM/MOD is assembled exactly as DECOMPOSITION.md section 4 gives it and
needs no change: it is exact for every uhi < ud at 32- and 64-bit cells.
It is checked against q*d + r = uhi:ulo with r < d through v4_umul, so
no second C divider has to be trusted. Coverage: all edge-vector triples
with uhi < ud plus 20000 pseudo-random cases (top-bit, small and
near-maximum divisors), optimised and under ASan+UBSan. Two hand
mutations each fail more than 15000 checks.

New headroom probe: runs a word with marked cells under the canary and
under its return address and reports how many survive, since the D-2
circular stacks overwrite silently instead of faulting. Measured:
  UM*     6 data cells under its args, 4 return entries under its return
  UM/MOD  3 data cells under its args, 3 return entries under its return

DECOMPOSITION.md: UM/MOD marked executed, with its defined range and
stack limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:48:04 -04:00
rajamesandClaude Opus 5.5 9a391eb0ad feat(v4.0.0): full-range UM* under plain F18 +* (D-3)
UM* as first written in DECOMPOSITION.md section 4 was exact only while
u1 <= 2^(n-2): plain +* loses the carry out of T and its shift keeps T's
sign bit, so the loop is exact only while S and T stay in
[-2^(n-2), 2^(n-2)).

The rewrite multiplies by s = u1 2/, which always lies in that range,
starting T at t0 = u2 2/ when u1 is odd, so the loop yields
hi:lo = t0 + s*u2 exactly. Then
  u1*u2 = 2*(hi:lo) + c_lo + c_hi*2^n
  c_lo  = u1 & u2 & 1
  c_hi  = (u1<0 ? u2 : 0) + (u1 odd and u2<0 ? 1 : 0)
restores the halved-away bits and the unsigned reading of both top bits.

test_foundation.c runs the new definition against v4_umul over every
pair of the edge vectors plus 20000 pseudo-random pairs, at 32- and
64-bit cells, optimised and under ASan+UBSan. The two pinned failing
cases are now ordinary exactness checks. Two hand mutations of the
correction step each fail more than 10000 checks at both widths.

DECOMPOSITION.md: section 4 UM* replaced, D-3 ruling text updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:21:17 -04:00
rajamesandClaude Opus 5.5 067f317c47 feat(v4.0.0): hosted golden model, single node
First code for StarForth v4 (JUSTIFICATION.md section 10, step 1): one node
of the 32-instruction core as a C99 model, with cell width as a build
parameter.

- Node: P, A, B, F18 circular stacks (10 and 9 deep, D-2), word-addressed
  memory (D-1), 5% guard bands on every bounded list.
- Instruction word: six 5-bit slots in 32 bits at every cell width.
- Executor: all 32 opcodes of DECOMPOSITION.md 1.3. Cell arithmetic wraps
  explicitly; no signed overflow or implementation-defined shift.
- Heat: per-opcode and per-call-target counters and the anti-clock, driven
  by instruction retirement (1.4, D-6 interim).
- Slot packer and runner for tests, and a reference unsigned multiply in
  plain C99 with no 128-bit type.

Tests run at 32- and 64-bit cells, and under ASan and UBSan. They cover
every opcode and execute the first section 4 definitions (NIP SWAP OR
NEGATE ROT 0< 0= 2DUP - U<) against the C operation each stands for.

UM* as written in section 4 is exact only while u1 <= 2^(n-2). Two known
failing cases are pinned in test_foundation.c until it is rewritten.

DECOMPOSITION.md: record D-9, the instruction word is 32 bits at every
cell width (ruled 2026-10-02).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:38:27 -04:00
rajames 1f98034311 Merge remote-tracking branch 'origin/StarForth-v4.0.0' into StarForth-v4.0.0 2026-10-01 15:55:37 -04:00
rajamesandJunie a8b70e88d3 Reorganize source tree: kernel/, v3/, v4/ split and board infrastructure
Source tree reorganization:
- Move StarForth v3 engine to v3/ (src/, include/, Makefile)
- Move kernel to kernel/ (src/, include/, linker/, Makefile)
- Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md)
- Move FABRIC-0..4.md to docs/fabric/
- Move ONTOLOGY.md and ROADMAP.md to docs/

Board infrastructure:
- Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/
- Each board has board.mk (ISA, CPU flags, boot recipe) and README.md
- Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET
- make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board
- ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet)
- scripts/mkdiskimage.sh builds disk images for all boards

Docs pipeline:
- docs/book/ with LaTeX master (main.tex) and Makefile
- pandoc converts Markdown to LaTeX at build time
- Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks)
- make docs builds single PDF (754 pages, 0 missing characters)
- make docs TARGET=<board> adds board appendix
- build/docs/<book|board>/meta.tex stamps git commit into PDF

Bug fixes:
- 42 include paths that only worked by accident now use correct relative paths
- clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build)
- Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved
- Doxyfile, .clang-tidy, README.md, Kconfig paths updated

Verified:
- Hosted v3 build passes 1012 tests, 0 failures
- SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE)
- Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes
- make clean TARGET=<board> removes only that board and its ISA objects
- make all builds all boards, hosted v3, and docs in one run

Co-authored-by: Junie <junie@jetbrains.com>
2026-10-01 15:40:09 -04:00
Claude f238f02afa docs(v4.0.0): record D-1..D-8 rulings in DECOMPOSITION.md
D-1 word addressing; D-2 F18 circular stacks (10/9 deep), hidden, so
DEPTH/PICK/ROLL/.S/SP@/SP! are retired everywhere and the DSP register is
dropped; D-3 plain F18 +* (UM* flagged for revision); D-5 host width
matches the host CPU; D-7 moot; D-8 signed Q48.16; D-4 and D-6 deferred
to the hosted-mesh step. Adds a note that every CAP definition must be
re-checked against the 10/9 stack depths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BY9HMwK5Cetz3caBgHGyds
2026-10-01 00:55:20 +00:00
1321 changed files with 1009800 additions and 9096 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ Checks: >
WarningsAsErrors: [ ] WarningsAsErrors: [ ]
HeaderFilterRegex: '^src/.*|^include/.*' HeaderFilterRegex: '^v3/(src|include)/.*|^kernel/(src|include)/.*'
AnalyzeTemporaryDtors: false AnalyzeTemporaryDtors: false
FormatStyle: none FormatStyle: none
+28 -28
View File
@@ -6,8 +6,8 @@
# clang-tidy will ALWAYS false-positive them. Always. # clang-tidy will ALWAYS false-positive them. Always.
# --------------------------------------------------------- # ---------------------------------------------------------
src/platform/** v3/src/platform/**
src/platform/* v3/src/platform/*
# --------------------------------------------------------- # ---------------------------------------------------------
# Skip test infrastructure # Skip test infrastructure
@@ -15,8 +15,8 @@ src/platform/*
# and stress edge conditions clang-tidy will never grok. # and stress edge conditions clang-tidy will never grok.
# --------------------------------------------------------- # ---------------------------------------------------------
src/test_runner/** v3/src/test_runner/**
src/test_runner/* v3/src/test_runner/*
# --------------------------------------------------------- # ---------------------------------------------------------
# Skip word definitions generated or "mechanically patterned" # Skip word definitions generated or "mechanically patterned"
@@ -24,30 +24,30 @@ src/test_runner/*
# clang-tidy gives ZERO useful feedback on them. # clang-tidy gives ZERO useful feedback on them.
# --------------------------------------------------------- # ---------------------------------------------------------
src/word_source/string_words.c v3/src/word_source/string_words.c
src/word_source/block_words.c v3/src/word_source/block_words.c
src/word_source/arithmetic_words.c v3/src/word_source/arithmetic_words.c
src/word_source/mixed_arithmetic_words.c v3/src/word_source/mixed_arithmetic_words.c
src/word_source/return_stack_words.c v3/src/word_source/return_stack_words.c
src/word_source/defining_words.c v3/src/word_source/defining_words.c
src/word_source/stack_words.c v3/src/word_source/stack_words.c
src/word_source/logical_words.c v3/src/word_source/logical_words.c
src/word_source/memory_words.c v3/src/word_source/memory_words.c
src/word_source/io_words.c v3/src/word_source/io_words.c
src/word_source/dictionary_words.c v3/src/word_source/dictionary_words.c
src/word_source/dictionary_manipulation_words.c v3/src/word_source/dictionary_manipulation_words.c
src/word_source/vocabulary_words.c v3/src/word_source/vocabulary_words.c
src/word_source/system_words.c v3/src/word_source/system_words.c
src/word_source/starforth_words.c v3/src/word_source/starforth_words.c
src/word_source/editor_words.c v3/src/word_source/editor_words.c
src/word_source/format_words.c v3/src/word_source/format_words.c
# --------------------------------------------------------- # ---------------------------------------------------------
# Skip headers belonging to the word system # Skip headers belonging to the word system
# Same reason: no signal, infinite false positives. # Same reason: no signal, infinite false positives.
# --------------------------------------------------------- # ---------------------------------------------------------
src/word_source/include/* v3/src/word_source/include/*
# --------------------------------------------------------- # ---------------------------------------------------------
# Skip anything that implements performance knobs, # Skip anything that implements performance knobs,
@@ -55,15 +55,15 @@ src/word_source/include/*
# These are meant to be weird, and tidy can't reason about them. # These are meant to be weird, and tidy can't reason about them.
# --------------------------------------------------------- # ---------------------------------------------------------
src/stack_management.c v3/src/stack_management.c
src/profiler.c v3/src/profiler.c
src/vm_debug.c v3/src/vm_debug.c
src/physics_runtime.c v3/src/physics_runtime.c
# --------------------------------------------------------- # ---------------------------------------------------------
# Skip integration + stress torture-tests. # Skip integration + stress torture-tests.
# These *intentionally* do UB-like bullshit. # These *intentionally* do UB-like bullshit.
# --------------------------------------------------------- # ---------------------------------------------------------
src/test_runner/modules/*stress* v3/src/test_runner/modules/*stress*
src/test_runner/modules/*integration* v3/src/test_runner/modules/*integration*
+146 -110
View File
@@ -26,7 +26,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
> track a codebase it no longer describes would defeat its purpose as a record. > track a codebase it no longer describes would defeat its purpose as a record.
> **Tripod/kernel reshuffle — Phases 0–4 COMPLETE (2026-09-22); Phase 5 close-out in > **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_ > progress.** Hermes moved into the kernel as kernel-Hermes (`kernel/src/vm/kernel_
> hermes.c`); the Tripod is now **Hera / Artemis / Hestia** — **the Hermes VM, `capsules/ > 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.** > 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 > Design is complete and ruled in **`FABRIC-3.5.md`** (authoritative); execution is tracked in
@@ -39,10 +39,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
> **Scope:** This repo is LithosAnanke — the bare-metal UEFI kernel that boots StarForth > **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 > directly on hardware. StarForth (the hosted FORTH-79 VM) has its own separate repository
> now. This repo vendors a full copy of the shared VM source (`src/vm.c`, `src/word_source/`, > now. This repo vendors a full copy of the shared VM source (`v3/src/vm.c`,
> `capsules/`, `proof/`) because LithosAnanke embeds it as its execution engine — that vendored > `v3/src/word_source/`, `capsules/`, `proof/`) because LithosAnanke embeds it as its
> code is not a leftover or a second production target, it's load-bearing here. Kernel-specific > execution engine — that vendored code is not a leftover or a second production target, it's
> code lives in `src/starkernel/`. > load-bearing here. Kernel-specific code lives in `kernel/src/`.
--- ---
@@ -81,21 +81,24 @@ about "which line am I on."
- **`' BIRTH` in shared capsules breaks the hosted build** — BIRTH is kernel-only. `capsules/ACL.4th` itself documents this exclusion in a comment (line ~64) — it deliberately omits `BIRTH`/`CAPSULE-BIRTH` even though this IS the kernel repo, because `ACL.4th` is meant to stay portable/shared. - **`' BIRTH` in shared capsules breaks the hosted build** — BIRTH is kernel-only. `capsules/ACL.4th` itself documents this exclusion in a comment (line ~64) — it deliberately omits `BIRTH`/`CAPSULE-BIRTH` even though this IS the kernel repo, because `ACL.4th` is meant to stay portable/shared.
### On the Embedded VM vs. the Kernel ### On the Embedded VM vs. the Kernel
- **`src/vm.c`, `include/vm.h`, `capsules/`, `src/word_source/` are the shared/vendored VM - **`v3/src/vm.c`, `v3/include/vm.h`, `capsules/`, `v3/src/word_source/` are the
source.** They must compile and behave correctly both standalone (bare `make` here still shared/vendored VM source.** They must compile and behave correctly both standalone (bare
produces a plain hosted `starforth` binary for quick local sanity checks) and embedded in `make` here still produces a plain hosted `starforth` binary for quick local sanity checks)
the kernel build. Gate kernel-only code with `#ifdef __STARKERNEL__` or and embedded in the kernel build. Gate kernel-only code with `#ifdef __STARKERNEL__` or
`#ifdef STARFORTH_ENABLE_VM`. `#ifdef STARFORTH_ENABLE_VM`.
- **The vendored VM source has diverged from the standalone StarForth repo's copy** — it is - **The vendored VM source has diverged from the standalone StarForth repo's copy** — it is
not a byte-identical mirror. This repo's `src/word_source/` has 31 files (StarForth's has not a byte-identical mirror. This repo's `v3/src/word_source/` has 35 files (StarForth's
26); the extras (`defer_words.c`, `inference_words.c`, `lifecycle_words_hosted.c`, has 26; the count was 31 in an earlier revision of this file — corrected 2026-10-09); the
`log_words.c`, `q48_words.c`) are kernel-side-only additions. Don't assume a fix made in extras (`defer_words.c`, `inference_words.c`, `lifecycle_words_hosted.c`, `log_words.c`,
the StarForth repo needs to be, or even can be cleanly, ported here — check first. `q48_words.c`) are kernel-side-only additions, as are the console/input words
Similarly `src/starkernel/` here is real and load-bearing (~74 files across arch/boot/ (`framebuffer_words.c`, `keyboard_words.c`, `scroll_words.c`, `ttf_words.c`). Don't assume
a fix made in the StarForth repo needs to be, or even can be cleanly, ported here — check
first. Similarly `kernel/src/` here is real and load-bearing (~74 files across arch/boot/
capsule/hal/memory/math/hash/pci/virtio/vm subtrees) — much larger than older docs claimed. capsule/hal/memory/math/hash/pci/virtio/vm subtrees) — much larger than older docs claimed.
- **`src/*.c.bak` files (`vm.c.bak`, `doe_metrics.c.bak`, `inference_engine.c.bak`) are - **The `*.c.bak` files are gone.** `vm.c.bak`, `doe_metrics.c.bak`, and
tracked in git at the `src/` top level.** This looks like repo hygiene debt, not `inference_engine.c.bak` — previously tracked at the `v3/src/` top level per an older revision
intentional. Report it if it comes up; don't delete unprompted. of this file — no longer exist anywhere in the tree (verified 2026-10-09 via `git ls-files`
and a filesystem scan). The hygiene debt was cleaned up; nothing to report.
- **There is no `make test` target in this repo's hosted `Makefile`** (unlike the standalone - **There is no `make test` target in this repo's hosted `Makefile`** (unlike the standalone
StarForth repo, which has one). Don't invent one. The only acceptance authority for kernel StarForth repo, which has one). Don't invent one. The only acceptance authority for kernel
changes is the three-arch QEMU boot (see below); bare `make` here is for quick compile changes is the three-arch QEMU boot (see below); bare `make` here is for quick compile
@@ -116,9 +119,8 @@ about "which line am I on."
## Word-Level ACL System — Complete through Phase 7 (independently verified) ## Word-Level ACL System — Complete through Phase 7 (independently verified)
**Design doc:** `docs/03-architecture/word-acl/DESIGN.md` (this repo kept the old-style **Design doc:** `docs/reference/word-acl/DESIGN.md` (moved there from the old
`docs/03-architecture/` tree alongside the newer `docs/formal/`/`docs/working/` restructure — `docs/03-architecture/` tree in the 2026-10-14 docs reorganisation).
both exist here; this path is still current for ACL specifically).
The word-level ACL system is fully implemented, including kernel parity. Key constraints: The word-level ACL system is fully implemented, including kernel parity. Key constraints:
@@ -140,14 +142,17 @@ The word-level ACL system is fully implemented, including kernel parity. Key con
6. ✅ `EMERGENCY_CONSOLE_ENABLED` build flag + `vm_fault_handler` extension point 6. ✅ `EMERGENCY_CONSOLE_ENABLED` build flag + `vm_fault_handler` extension point
7. ✅ LithosAnanke kernel parity — **independently verified present in current `master`**: 7. ✅ LithosAnanke kernel parity — **independently verified present in current `master`**:
`acl_recheck()`/`zuse_session`/`emergency_console` wiring confirmed in `acl_recheck()`/`zuse_session`/`emergency_console` wiring confirmed in
`src/starkernel/vm/vm_core.c` (~lines 549, 608–633, 747–749, 906–908); the `kernel/src/vm/vm_core.c` (~lines 549, 608–633, 747–749, 906–908); the
per-iteration `emergency_console = zuse_session ? 0 : 1` assignment confirmed in per-iteration `emergency_console = zuse_session ? 0 : 1` assignment confirmed in
`src/starkernel/repl.c` (~lines 174, 219); the old `!vm->zuse_session` ACL-check bypass `kernel/src/repl.c` (~lines 174, 219); the old `!vm->zuse_session` ACL-check bypass
confirmed **absent** from `src/vm.c`. (The `feature/acl-rwt` branch this work was confirmed **absent** from `v3/src/vm.c`. (The `feature/acl-rwt` branch this work was
apparently done on is not traceable in `git log --all` — likely squash-merged without apparently done on is not traceable in `git log --all` — likely squash-merged without
preserving the ref. The code is real and verified; the branch name is not.) preserving the ref. The code is real and verified; the branch name is not.)
8. ⬜ PKI / thumbdrive — Ed25519 challenge-response; user minting by zuse. **This is the open 8. ✅ PKI / thumbdrive — closed 2026-10-14. User minting by Zuse is built (`MINT`, `MINT-SCRATCH`,
item — pick up here next.** WIREBIND cert verification). Challenge-response against a cloned drive was ruled out by design
("there's only the drive", `FABRIC-3.7.md`). Runtime word-ACL elevation (`ELEVATE-GRANT`, the
Zuse eligibility list) was ruled not needed and removed, with the hole it carried
(`FABRIC-3.md` §XXXVII).
**ACL-RWT DoE campaign (June 15–16 2026) — superseded, kept for historical record:** **ACL-RWT DoE campaign (June 15–16 2026) — superseded, kept for historical record:**
- 3×3 Latin square: 3 seeds × amd64/aarch64/riscv64, 30 reps each - 3×3 Latin square: 3 seeds × amd64/aarch64/riscv64, 30 reps each
@@ -176,7 +181,9 @@ capsule files — accurate):
previously described a 1024-byte-per-block budget — right by arithmetic, wrong as a rule): previously described a 1024-byte-per-block budget — right by arithmetic, wrong as a rule):
`validate_forth_blocks` enforces a **64-char × 16-line** format — `validate_forth_blocks` enforces a **64-char × 16-line** format —
**line length ≤ 64 chars, ≤ 16 content lines per block** (`mkcapsule.c:344-345`, `:430`) — and **line length ≤ 64 chars, ≤ 16 content lines per block** (`mkcapsule.c:344-345`, `:430`) — and
a block number in **`[2048, 5120)`** (`:408-409`). 64 × 16 = 1024, which is where the old a block number of **2048 or more, with no upper bound** (`:408-411`; ruled 2026-10-05,
`docs/v4.0.0/NUCLEUS.md` §5.2 — blocks 0–2047, the VM's fast RAM, are the only ones a capsule
may not claim; the check was `[2048, 5120)` before). 64 × 16 = 1024, which is where the old
figure came from, but the enforcement is per-line and per-line-count: **8 lines of 128 chars figure came from, but the enforcement is per-line and per-line-count: **8 lines of 128 chars
is 1024 bytes and still fails.** Verify with `mkcapsule --lint capsules/`, not `wc -c`. is 1024 bytes and still fails.** Verify with `mkcapsule --lint capsules/`, not `wc -c`.
@@ -194,8 +201,8 @@ removed as an active target.)
**Current status: M7.1** — capsule birth protocol, Mama FORTH vocabulary, Tripod multi-VM **Current status: M7.1** — capsule birth protocol, Mama FORTH vocabulary, Tripod multi-VM
fleet (Hera/Artemis/Hestia — Hermes moved into the kernel as kernel-Hermes, FABRIC-3.6.md 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 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 hash across amd64/aarch64/riscv64 with a 526-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 2026-10-14, `FABRIC-3.md` §XXXVIII, hash `0x82f4ae7cb2e2d424`; verify against a live `PARITY:M7.1a word_count=` line before citing, it
changes with any new C word registration). changes with any new C word registration).
**Key distinguishing features:** **Key distinguishing features:**
@@ -207,7 +214,7 @@ changes with any new C word registration).
produces a new capsule produces a new capsule
- **Tripod** — a named multi-VM fleet (Hera the Mama VM, Artemis, Hestia) that births, runs, - **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. 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 Hermes moved into the kernel as kernel-Hermes (`kernel/src/vm/kernel_hermes.c`) and is
no longer a Tripod VM — see `FABRIC-3.5.md`/`FABRIC-3.6.md`, not the archived 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`. `.claude/TRIPOD.md`/`.claude/HERMES.md`/`.claude/ARTEMIS.md`.
- Word-level ACL security system with kernel parity (see above) — measured overhead three - Word-level ACL security system with kernel parity (see above) — measured overhead three
@@ -224,43 +231,44 @@ changes with any new C word registration).
```bash ```bash
# Build kernel for a given architecture (amd64 default) # Build kernel for a given architecture (amd64 default)
make -f Makefile.starkernel ARCH=amd64 make -f kernel/Makefile ARCH=amd64
make -f Makefile.starkernel ARCH=aarch64 make -f kernel/Makefile ARCH=aarch64
make -f Makefile.starkernel ARCH=riscv64 make -f kernel/Makefile ARCH=riscv64
# Run in QEMU with OVMF # Run in QEMU with OVMF
make -f Makefile.starkernel qemu make -f kernel/Makefile qemu
make -f Makefile.starkernel ARCH=aarch64 qemu make -f kernel/Makefile ARCH=aarch64 qemu
make -f Makefile.starkernel ARCH=riscv64 qemu make -f kernel/Makefile ARCH=riscv64 qemu
# Clean # Clean
make -f Makefile.starkernel clean make -f kernel/Makefile clean
``` ```
Output: `build/<arch>/kernel/starkernel_loader.efi` + `build/<arch>/kernel/starkernel_kernel.elf`. Output: `build/<arch>/kernel/starkernel_loader.efi` + `build/<arch>/kernel/starkernel_kernel.elf`.
Two independently tracked version strings flow into the generated `include/version.h`: Two independently tracked version strings flow into the generated `include/version.h`:
`VERSION` (`Makefile.starkernel` — the embedded StarForth engine version, currently `3.1.0`; `VERSION` (`kernel/Makefile` — the embedded StarForth engine version, currently `3.2.0`;
note this does **not** auto-sync with the standalone StarForth repo's own version) and note this does **not** auto-sync with the standalone StarForth repo's own version) and
`LITHOS_VERSION` (`Makefile.starkernel` — the kernel version, currently **`2.0.0`**; `LITHOS_VERSION` (`kernel/Makefile` — the kernel version, currently **`2.1.0`**, bumped at
corrected 2026-09-19 — this file said `2.0.1`, but `FABRIC-3.md` §I.2 rolled it back to the `v2.1.0` tag that closed FABRIC-3.6; corrected 2026-10-14 -- this file said `3.1.0` /
`2.0.0` on 2026-09-04 because `2.0.1` names the SER5 hardware-track line and claims hardware `2.0.0`. History: it said `2.0.1` until 2026-09-19, but `FABRIC-3.md` §I.2 had rolled that
progress not yet verified. The versioning policy is **semantic, not sequential** — see the back to `2.0.0` on 2026-09-04 because `2.0.1` names the SER5 hardware-track line and claims
roadmap table in `Makefile.starkernel` before choosing any version). hardware progress not yet verified. The versioning policy is **semantic, not sequential** — see the
roadmap table in `kernel/Makefile` before choosing any version).
### Build configuration (Kconfig — real, wired, not vestigial) ### Build configuration (Kconfig — real, wired, not vestigial)
Every kernel-only knob (`STARFORTH_ENABLE_VM`, `PARITY_MODE`, the shared physics/heartbeat Every kernel-only knob (`STARFORTH_ENABLE_VM`, `PARITY_MODE`, the shared physics/heartbeat
family, etc.) is an optional Kconfig symbol defined across `Kconfig`, `Kconfig.arch`, family, etc.) is an optional Kconfig symbol defined across `Kconfig`, `Kconfig.arch`,
`Kconfig.heartbeat`, `Kconfig.kernel`, `Kconfig.physics`, `Kconfig.variant` (~40 symbols `Kconfig.heartbeat`, `Kconfig.kernel`, `Kconfig.physics`, `Kconfig.variant` (~40 symbols
total). `Makefile.starkernel` pulls its defaults from this system via a `kconfig_bool(...)` total). `kernel/Makefile` pulls its defaults from this system via a `kconfig_bool(...)`
mechanism — e.g. `STARFORTH_ENABLE_VM` defaults to **1** (confirmed at mechanism — e.g. `STARFORTH_ENABLE_VM` defaults to **1** (confirmed at
`Makefile.starkernel:61`), meaning a plain `make -f Makefile.starkernel` already builds with `kernel/Makefile:61`), meaning a plain `make -f kernel/Makefile` already builds with
VM + capsule-birth + ACL active. A bare invocation uses the defaults it always has: VM + capsule-birth + ACL active. A bare invocation uses the defaults it always has:
```bash ```bash
make -f Makefile.starkernel ARCH=amd64 menuconfig make -f kernel/Makefile ARCH=amd64 menuconfig
make -f Makefile.starkernel ARCH=amd64 kernel_amd64_defconfig make -f kernel/Makefile ARCH=amd64 kernel_amd64_defconfig
``` ```
### Hosted VM (vendored, for local sanity only) ### Hosted VM (vendored, for local sanity only)
@@ -277,7 +285,7 @@ StarForth repo) were removed 2026-08-15 — they referenced
in the actual generated `include/version.h` (which only has `STARFORTH_VERSION`, in the actual generated `include/version.h` (which only has `STARFORTH_VERSION`,
`STARFORTH_ARCH`, `STARFORTH_TARGET`, `STARFORTH_TIMESTAMP`, `STARFORTH_VERSION_FULL`, `STARFORTH_ARCH`, `STARFORTH_TARGET`, `STARFORTH_TIMESTAMP`, `STARFORTH_VERSION_FULL`,
`LITHOS_VERSION`, `LITHOS_VERSION_STR`), so they could never have worked. Bump versions by hand-editing the `VERSION`/ `LITHOS_VERSION`, `LITHOS_VERSION_STR`), so they could never have worked. Bump versions by hand-editing the `VERSION`/
`LITHOS_VERSION` variables in `Makefile.starkernel` instead. Report the broken targets if `LITHOS_VERSION` variables in `kernel/Makefile` instead. Report the broken targets if
asked, don't silently fix them. asked, don't silently fix them.
### Important: Linker Configuration ### Important: Linker Configuration
@@ -297,12 +305,23 @@ architectures in QEMU and capturing the serial log. There is no other test.
The vendored hosted `make` build (above) is NEVER used to validate kernel changes. The vendored hosted `make` build (above) is NEVER used to validate kernel changes.
```bash ```bash
# Run in this exact order for every kernel change: # Run in this exact order for every kernel change. v4 is the default (2026-10-14):
make -f Makefile.starkernel ARCH=amd64 clean qemu make -f kernel/Makefile ARCH=amd64 clean qemu
make -f Makefile.starkernel ARCH=aarch64 clean qemu make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f Makefile.starkernel ARCH=riscv64 clean qemu make -f kernel/Makefile ARCH=riscv64 clean qemu
# ...and the 32-bit build -- v4 with 32-bit cells, the F18/Zynq (FPGA) case: its nucleus
# image and every v4 test at that width (no QEMU; not a substitute for the boots above):
make -C v4 test-32
``` ```
**v4 is the default build (Captain Bob, 2026-10-14: "v4 is the default build ... no, qemu to v4
too ... we are effectively trying to retire v3").** Every kernel build carries v4 and v3 and
boots v4; `system=v3` in the boot arguments (`KERNEL_ARGS` for QEMU, `starforth.cfg` /
`cmdline.txt` on a board's medium) boots v3. `STARFORTH_V4=0` builds v3 alone. The boot prints
which system runs and why ("System: ..."). See `boards/BRINGUP.md` A6, `FABRIC-3.md` §XLIII.
**v3 is not part of acceptance** (Captain Bob, 2026-10-14: "i don't care about v3"). It is still
in the tree and `system=v3` still boots it, but nothing is accepted or refused on its account.
**QEMU rule — non-negotiable:** Only ONE QEMU instance may run at a time, always in the **QEMU rule — non-negotiable:** Only ONE QEMU instance may run at a time, always in the
foreground (never backgrounded). All three instances use `accel=tcg` (software emulation); foreground (never backgrounded). All three instances use `accel=tcg` (software emulation);
concurrent runs compete for host CPU and corrupt the timing signal the DoE measures. concurrent runs compete for host CPU and corrupt the timing signal the DoE measures.
@@ -322,8 +341,13 @@ audit artifacts — they are committed to the repo. Do not delete them. There is
timestamped convention (self-documented via its own README); not a contradiction, just a timestamped convention (self-documented via its own README); not a contradiction, just a
second, less-structured log location. second, less-structured log location.
Do not claim a change is accepted until all three architectures have booted Do not claim a change is accepted until all three architectures have booted, and their logs are
to `zuse)ok>` and their logs are present in `logs/`. present in `logs/`:
- **as built (v4)** to `ok> `, with `PARITY:V4_POST tests=538 pass=538 fail=0` (the count
grows with v4's POST) and `POST: PASSED`, and `PARITY:V4_SYSTEM ... dict_hash=` equal across
the three;
- **the 32-bit build** (Captain Bob, 2026-10-14: "the 32 bit build needs to go into the
acceptance test too"): `make -C v4 test-32` passes -- every test, `0 failures`.
### CI ### CI
@@ -340,41 +364,45 @@ it ships a raw disk image instead). No QEMU boot step in CI — artifact packagi
### Source Tree ### Source Tree
``` ```
src/ v3/ # hosted StarForth product AND the shared engine source
├── main.c, vm.c, vm_api.c, vm_bootstrap.c, vm_debug.c, vm_time.c # Vendored VM core (see below) ├── Makefile # hosted build (bare `make` at the repo root forwards here)
├── repl.c, cli.c, io.c, log.c # Vendored VM core ├── include/ # vm.h, version.h — the only VM headers (no top-level `include/`)
├── memory_management.c, dictionary_management.c, block_subsystem.c, blkio_*.c └── src/
├── stack_management.c, math_portable.c, profiler.c, compudynamics.c ├── main.c, vm.c, vm_api.c, vm_bootstrap.c, vm_debug.c, vm_time.c # Shared VM core (see below)
├── heartbeat_export.c, ssm_jacquard.c, doe_metrics.c ├── repl.c, cli.c, io.c, log.c # Shared VM core
├── physics_runtime.c, physics_hotwords_cache.c, physics_metadata.c, ├── memory_management.c, dictionary_management.c, block_subsystem.c, blkio_*.c
│ physics_pipelining_metrics.c, physics_execution_hooks.c, ├── stack_management.c, math_portable.c, profiler.c, compudynamics.c
│ rolling_window_of_truth.c, inference_engine.c # 7 feedback loops ├── heartbeat_export.c, ssm_jacquard.c, doe_metrics.c
├── vm.c.bak, doe_metrics.c.bak, inference_engine.c.bak # tracked but stale — flag, don't delete unprompted ├── physics_runtime.c, physics_hotwords_cache.c, physics_metadata.c,
│ │ physics_pipelining_metrics.c, physics_execution_hooks.c,
├── word_source/ # 31 files (vendored StarForth word_source PLUS │ rolling_window_of_truth.c, inference_engine.c # 7 feedback loops
│ │ # kernel-side-only additions) ├── word_source/ # 35 files (StarForth word_source PLUS
│ ├── (all of StarForth's 26: arithmetic, stack, control, defining, memory, │ │ # kernel-side-only additions)
│ │ return_stack, double, logical, io, string, block, editor, format, system, │ ├── (StarForth's ~26: arithmetic, stack, control, defining, memory,
│ │ dictionary, dictionary_manipulation, dictionary_heat_diagnostic, vocabulary, │ │ return_stack, double, logical, io, string, block, editor, format, system,
│ │ q48_16, starforth, acl, physics_benchmark, physics_diagnostic, │ │ dictionary, dictionary_manipulation, dictionary_heat_diagnostic, vocabulary,
│ │ physics_freeze, physics_pipelining_diagnostic, mixed_arithmetic) │ │ q48_16, starforth, acl, physics_benchmark, physics_diagnostic,
│ └── kernel-only additions: defer_words.c, inference_words.c, │ │ physics_freeze, physics_pipelining_diagnostic, mixed_arithmetic)
│ lifecycle_words_hosted.c, log_words.c, q48_words.c │ ├── kernel-side-only additions: defer_words.c, inference_words.c,
│ │ │ lifecycle_words_hosted.c, log_words.c, q48_words.c
├── test_runner/ # 23 test module files (matches StarForth's count) │ └── console/input words: framebuffer_words.c, keyboard_words.c,
│ │ scroll_words.c, ttf_words.c
├── platform/ # Platform abstraction (hosted build) ├── test_runner/ # 26 test module files
│ └── platform/ # Platform abstraction (hosted build)
└── starkernel/ # ~74 files — the real, load-bearing kernel tree
├── kernel_main.c # Kernel entry point (M0–M9 milestones) kernel/ # LithosAnanke — the real, load-bearing kernel tree
│ # NOTE: this file's own header comment claims ├── Makefile # UEFI loader + kernel ELF + QEMU; embeds a subset of v3/src
│ # "M7: Not started" — that comment is STALE; ├── include/starkernel/ # kernel-only headers
│ # M7/M7.1/M7.pre logic is present and functional └── src/
│ # (kernel_main.c ~lines 481–517). Don't propagate ├── kernel_main.c # Kernel entry point (M0–M9 milestones)
│ # the stale comment. │ # NOTE: this file's own header comment claims
│ # "M7: Not started" — that comment is STALE;
│ # M7/M7.1/M7.pre logic is present and functional
│ # (kernel_main.c ~lines 481–517). Don't propagate
│ # the stale comment.
├── repl.c # Kernel REPL ├── repl.c # Kernel REPL
├── arch/{amd64,aarch64,riscv64}/ # Per-arch: arch.c apic.c timer.c interrupts.c boot.S isr.S ├── arch/{amd64,aarch64,riscv64}/ # Per-arch: arch.c apic.c timer.c interrupts.c boot.S isr.S
├── boot/ # uefi_loader.c elf_loader.c reloc_stub.c reloc.S ├── boot/ # uefi_loader.c elf_loader.c cmdline.c reloc_stub.c reloc.S
├── capsule/ # capsule_birth.c capsule_run.c capsule_loader.c ├── capsule/ # capsule_birth.c capsule_run.c capsule_loader.c
│ # capsule_find.c capsule_validate.c capsule_vm_hooks.c │ # capsule_find.c capsule_validate.c capsule_vm_hooks.c
│ # capsule_vm_physics.c mama_forth_words.c │ # capsule_vm_physics.c mama_forth_words.c
@@ -389,10 +417,15 @@ src/
├── math/q48_16.c # Q48.16 fixed-point (kernel build) ├── math/q48_16.c # Q48.16 fixed-point (kernel build)
├── hash/xxhash64.c # XXHash64 (content addressing) ├── hash/xxhash64.c # XXHash64 (content addressing)
├── doe_log.c ├── doe_log.c
├── artemis_sig.c homeblocks_sig.c heartbeat.c log_region.c # kernel services
├── crypto/ rng/ usb/ # PKI (Ed25519), entropy, USB
├── v4/sk_v4.c # bare-metal embed of the v4 engine (STARFORTH_V4=1)
└── vm/ # Kernel VM subsystem └── vm/ # Kernel VM subsystem
├── bootstrap/sk_vm_bootstrap.c ├── bootstrap/sk_vm_bootstrap.c
├── host/shim.c ├── host/shim.c
├── vm_core.c vm_runtime.c vm_bootstrap.c q48_stubs.c ├── vm_core.c vm_runtime.c vm_bootstrap.c q48_stubs.c
├── kernel_hermes.c # kernel-Hermes (post-reshuffle)
├── session.c stadium.c stadium_blocks.c stadium_words.c switch.c
├── parity.c # Birth/execution parity logging ├── parity.c # Birth/execution parity logging
├── arena.c # Capsule arena allocator ├── arena.c # Capsule arena allocator
└── alloc_kernel.c └── alloc_kernel.c
@@ -419,7 +452,7 @@ UEFI Firmware → uefi_loader.c (BOOTX64.EFI / BOOTAA64.EFI / BOOTRISCV64.EFI)
- ✅ M0–M6: complete, v1.5.1-FINAL - ✅ M0–M6: complete, v1.5.1-FINAL
- ✅ M7: StarForth VM integration + parity validation, complete - ✅ M7: StarForth VM integration + parity validation, complete
- 🔄 M7.1: capsule birth protocol · Mama FORTH vocabulary · Tripod fleet · word-level ACL — - 🔄 M7.1: capsule birth protocol · Mama FORTH vocabulary · Tripod fleet · word-level ACL —
in progress (Phase 8 PKI is the open item, see ACL section above) in progress (Phase 8 PKI closed 2026-10-14, see ACL section above)
- Planned: M8 (REPL keyboard input), M9 (block storage — see the virtio note above; source - Planned: M8 (REPL keyboard input), M9 (block storage — see the virtio note above; source
exists but milestone-complete status not independently verified here) exists but milestone-complete status not independently verified here)
@@ -475,7 +508,7 @@ listed in `proof/ROOT` (corrected 2026-09-19; this file said 23, and `proof/COVE
said 52 all along). **Read `proof/COVERAGE.md` first**: its stated goal is not a green build but said 52 all along). **Read `proof/COVERAGE.md` first**: its stated goal is not a green build but
"identify precisely what cannot be proven and why — the boundary between 'formally verified' "identify precisely what cannot be proven and why — the boundary between 'formally verified'
and 'not, for this specific reason'." Run `isabelle build -D proof/` and 'not, for this specific reason'." Run `isabelle build -D proof/`
directly; neither `Makefile` nor `Makefile.starkernel` in this repo defines an directly; neither `Makefile` nor `kernel/Makefile` in this repo defines an
`isabelle-build`/`isabelle-check` target (unlike the standalone StarForth repo, which has a `isabelle-build`/`isabelle-check` target (unlike the standalone StarForth repo, which has a
broken one — this repo simply doesn't have the target at all, so there's nothing to broken one — this repo simply doesn't have the target at all, so there's nothing to
mistakenly invoke). mistakenly invoke).
@@ -484,7 +517,7 @@ mistakenly invoke).
## Roadmap ## Roadmap
`ROADMAP.md` and `docs/lithosananke/ROADMAP.md` contain real, LithosAnanke-specific phase `ROADMAP.md` and `docs/reference/ROADMAP.md` contain real, LithosAnanke-specific phase
content (e.g. "PHASE 2: STARKERNEL (Months 3-5)", "StarKernel boots to 'ok' on QEMU ✅") — content (e.g. "PHASE 2: STARKERNEL (Months 3-5)", "StarKernel boots to 'ok' on QEMU ✅") —
not a copy of the standalone StarForth repo's roadmap. Prefer these when citing roadmap not a copy of the standalone StarForth repo's roadmap. Prefer these when citing roadmap
status for kernel work. status for kernel work.
@@ -495,13 +528,13 @@ status for kernel work.
- **Strict ANSI C99** — No GNU extensions, no C++ features - **Strict ANSI C99** — No GNU extensions, no C++ features
- **Zero warnings target, with four explicit exceptions — corrected 2026-08-18, previous - **Zero warnings target, with four explicit exceptions — corrected 2026-08-18, previous
claim was wrong.** Build with `-Wall -Wextra -Werror`, but `Makefile.starkernel` carries claim was wrong.** Build with `-Wall -Wextra -Werror`, but `kernel/Makefile` carries
`-Wno-error=unused-parameter -Wno-error=shift-negative-value -Wno-error=sign-compare `-Wno-error=unused-parameter -Wno-error=shift-negative-value -Wno-error=sign-compare
-Wno-error=missing-field-initializers` — those four classes are enabled (still visible as -Wno-error=missing-field-initializers` — those four classes are enabled (still visible as
warnings) but deliberately downgraded from fatal, everything else is. The previous version warnings) but deliberately downgraded from fatal, everything else is. The previous version
of this line claimed `-Wmissing-field-initializers` was isolated to one file of this line claimed `-Wmissing-field-initializers` was isolated to one file
(`vocabulary_words_test.c`) — that was never accurate; a full audit found it systemic (`vocabulary_words_test.c`) — that was never accurate; a full audit found it systemic
across 20 files in `src/test_runner/modules/` (all missing the same later-added across 20 files in `v3/src/test_runner/modules/` (all missing the same later-added
`TestCase.contract`/`WordTestSuite.suite_contract` trailing field, ~3,010 instances). Fixed `TestCase.contract`/`WordTestSuite.suite_contract` trailing field, ~3,010 instances). Fixed
in place across all 20 files (mechanical: added the missing `{0}` initializer, semantically in place across all 20 files (mechanical: added the missing `{0}` initializer, semantically
a no-op since C99 already zero-fills unlisted trailing fields — the fix only silences the a no-op since C99 already zero-fills unlisted trailing fields — the fix only silences the
@@ -533,14 +566,14 @@ status for kernel work.
### DoE CSV Output Suppression ### DoE CSV Output Suppression
Intentionally suppressed as of 2025-12-08. See `src/main.c:390-396`: Intentionally suppressed as of 2025-12-08. See `v3/src/main.c:390-396`:
- Metrics still collected via `metrics_from_vm()` - Metrics still collected via `metrics_from_vm()`
- CSV row was redundant with internal VM metrics - CSV row was redundant with internal VM metrics
- To re-enable: add a `--csv-export` flag or write to a file - To re-enable: add a `--csv-export` flag or write to a file
### Heartbeat Instrumentation (Planned) ### Heartbeat Instrumentation (Planned)
`HeartbeatTickSnapshot` and `tick_buffer` are declared in `include/vm.h`, `HeartbeatTickSnapshot` and `tick_buffer` are declared in `v3/include/vm.h`,
but `heartbeat_export_csv()` is **not yet implemented**. but `heartbeat_export_csv()` is **not yet implemented**.
### Word Statistics Output ### Word Statistics Output
@@ -558,25 +591,28 @@ capsule and compare dict hashes. Zero-deviation means 0% algorithmic variance.
## Documentation ## Documentation
Key files (this repo has both the older `docs/03-architecture/` tree — still current for **Start at `docs/README.md`** -- the map: where each kind of document lives and which one is
ACL/Tripod specifically — and the newer restructured `docs/formal/`/`docs/working/`/ authoritative for what. `docs/INDEX.md` lists every document with its status;
`docs/patent/` trees, plus a repo-specific `docs/lithosananke/` tree): `docs/DEAD-AND-REVISED.md` is the register of abandoned ideas and revised claims. (Reorganised
2026-10-14: the old `docs/03-architecture/` and `docs/lithosananke/` trees are gone -- their
current parts are in `docs/reference/`, the rest in `docs/working/archive/`.)
- `README.md` — project overview and quick start - `README.md` -- project overview and quick start
- `docs/lithosananke/SYSTEM_ARCHITECTURE.md` — full kernel + VM design - `docs/fabric/` -- the design and work record (`FABRIC-3.md` living; the others closed)
- `docs/lithosananke/hal/` — HAL reference - `docs/v4.0.0/` -- StarForth v4 design
- `docs/lithosananke/M7.1.md` — capsule birth protocol design - `docs/reference/` -- current reference: `ROADMAP.md` (roadmap and versioning policy),
- `docs/lithosananke/ROADMAP.md` — milestone plan through self-hosting `M7.1.md` (capsule birth protocol), `word-acl/DESIGN.md` (word-level ACL), `kernel-args/`,
- `docs/lithosananke/hosted-acceptance-test/README.md` — the hosted-VM acceptance test `hosted-acceptance-test/`, `DICTIONARY.md`, `STARFORTH_PRIMITIVES.md`, `ONTOLOGY.md`
writeup referenced from the standalone StarForth repo's own docs - `boards/BRINGUP.md` -- bare-metal bring-up checklist and blockers
- `docs/03-architecture/tripod/`, `docs/03-architecture/word-acl/DESIGN.md` - `kernel/src/hal/README.md` -- the HAL as built (the proposed `hal_*` contract was never
- `docs/working/architecture/VM-FLEET-ATTRACTOR-DESIGN-20260705.md` — Tripod/Hermes/Artemis adopted; it is archived as dead)
physics + build-system history - `docs/working/architecture/VM-FLEET-ATTRACTOR-DESIGN-20260705.md` -- fleet physics and
- `docs/working/architecture/getting-started/DEVELOPER.md` — dev setup, Kconfig reference build-system history (pre-reshuffle: it still names the Hermes VM)
- `ROADMAP.md`, `CHANGELOG.md` - `docs/working/architecture/getting-started/DEVELOPER.md` -- dev setup, Kconfig reference
- `experiments/bare_metal/README.md` — **mandatory read before touching capsules** (block - `CHANGELOG.md`
- `experiments/bare_metal/README.md` -- **mandatory read before touching capsules** (block
namespace rules, see ACL section above) namespace rules, see ACL section above)
- `experiments/bare_metal/analysis/report/bare_metal_doe_report.pdf` — DoE campaign report - `experiments/bare_metal/analysis/report/bare_metal_doe_report.pdf` -- DoE campaign report
- `sbom.spdx` / `sbom.spdx.json` - `sbom.spdx` / `sbom.spdx.json`
--- ---
+3
View File
@@ -74,3 +74,6 @@ tools/kconfig/.qconf.*
# tools/capsule-reserved.txt (human-authored) and tools/patches/ (decision # tools/capsule-reserved.txt (human-authored) and tools/patches/ (decision
# record) are NOT ignored — those are tracked deliberately. # record) are NOT ignored — those are tracked deliberately.
/tools/capsule-claims.txt /tools/capsule-claims.txt
/.directory
# Agent worktrees are never to be used in this repo (Captain Bob's Law); ignored so a stray one is never tracked.
/.claude/worktrees/
+5 -1
View File
@@ -1,5 +1,9 @@
# Changelog # Changelog
## 2026-10-09 — StarForth v4.0.0 Step 6e review and wire refinement
Implemented whole-message handling on the engine wire (`d5cd6460`), ensured nodes only process one message at a time (`b1d09af0`), and refined message processing logic (`6a7d0aa2`, `f1419e73`). Fixed wake-up order, room checks, and overflow issues during message transit (`83694b18`).
Milestone-level achievements only — not a commit log. For full history see Milestone-level achievements only — not a commit log. For full history see
`git log` on the relevant branch. Two products share this file: `git log` on the relevant branch. Two products share this file:
**StarForth** (hosted FORTH-79 VM, `master`) and **LithosAnanke** (bare-metal **StarForth** (hosted FORTH-79 VM, `master`) and **LithosAnanke** (bare-metal
@@ -100,7 +104,7 @@ on both branches, plus the now-orphaned `scripts/pgo-workload.sh`. Verified
Also proved out and documented, for the first time, that the hosted VM Also proved out and documented, for the first time, that the hosted VM
starts cleanly not just on amd64 but on aarch64 and riscv64 too (cross-built, starts cleanly not just on amd64 but on aarch64 and riscv64 too (cross-built,
run under `qemu-{aarch64,riscv64}-static` user-mode emulation) — run under `qemu-{aarch64,riscv64}-static` user-mode emulation) —
`docs/lithosananke/hosted-acceptance-test/README.md`. This is what surfaced `docs/reference/hosted-acceptance-test/README.md`. This is what surfaced
the `blk_ram` sizing bug above. the `blk_ram` sizing bug above.
## 2026-07-07 – 2026-07-08 — Kconfig build-configuration system (both, committed on `lithosananke`) ## 2026-07-07 – 2026-07-08 — Kconfig build-configuration system (both, committed on `lithosananke`)
+2 -2
View File
@@ -9,7 +9,7 @@ Thank you for your interest in contributing to StarForth! This document provides
3. **Run tests**: `make test` (all 780+ tests must pass) 3. **Run tests**: `make test` (all 780+ tests must pass)
4. **Read** [ONTOLOGY.md](ONTOLOGY.md) for formal definitions and terminology 4. **Read** [ONTOLOGY.md](ONTOLOGY.md) for formal definitions and terminology
5. **Read** `docs/CLAUDE.md` for project overview 5. **Read** `docs/CLAUDE.md` for project overview
6. **Explore** `docs/03-architecture/` for architecture details 6. **Explore** `docs/README.md` (the documentation map) for architecture details
**Important:** All contributors must use terminology from [ONTOLOGY.md](ONTOLOGY.md) in code comments and documentation. This ensures precise, academically rigorous language throughout the project. **Important:** All contributors must use terminology from [ONTOLOGY.md](ONTOLOGY.md) in code comments and documentation. This ensures precise, academically rigorous language throughout the project.
@@ -36,7 +36,7 @@ void function_name(VM *vm) {
### Platform Abstraction ### Platform Abstraction
- **Never** call platform-specific APIs directly from VM code - **Never** call platform-specific APIs directly from VM code
- **Always** use HAL interfaces (`hal_time.h`, `hal_memory.h`, etc.) - **Always** use HAL interfaces (`hal_time.h`, `hal_memory.h`, etc.)
- See `docs/03-architecture/hal/` for HAL documentation - See `kernel/src/hal/README.md` for the HAL as built
### Memory Safety ### Memory Safety
- Use `vaddr_t` for VM addresses (not C pointers) - Use `vaddr_t` for VM addresses (not C pointers)
+10 -7
View File
@@ -933,10 +933,12 @@ WARN_LOGFILE = docs/api/doxygen_warnings.log
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = include \ INPUT = v3/include \
src \ v3/src \
src/word_source \ v3/src/word_source \
src/test_runner \ v3/src/test_runner \
kernel/include \
kernel/src \
README.md README.md
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
@@ -2366,9 +2368,10 @@ SEARCH_INCLUDES = YES
# RECURSIVE has no effect here. # RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES. # This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = include \ INCLUDE_PATH = v3/include \
src/word_source/include \ kernel/include \
src/test_runner/include v3/src/word_source/include \
v3/src/test_runner/include
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the # patterns (like *.h and *.hpp) to filter out the header-files in the
+1 -1
View File
@@ -5,7 +5,7 @@ choice
default ARCH_AMD64 default ARCH_AMD64
help help
Selects the value passed as ARCH= to whichever Makefile Selects the value passed as ARCH= to whichever Makefile
(Makefile or Makefile.starkernel) is driven from this config. (Makefile or kernel/Makefile) is driven from this config.
Both Makefiles already accept "amd64"/"aarch64"/"riscv64" as Both Makefiles already accept "amd64"/"aarch64"/"riscv64" as
canonical spellings (each has its own alias-normalizing logic canonical spellings (each has its own alias-normalizing logic
for other spellings like x86_64/arm64/riscv), so this choice for other spellings like x86_64/arm64/riscv), so this choice
+1 -1
View File
@@ -17,7 +17,7 @@ config HEARTBEAT_THREAD_ENABLED
builds without needing a special case. This is UI/model builds without needing a special case. This is UI/model
correctness (menuconfig can't offer a choice LithosAnanke has no correctness (menuconfig can't offer a choice LithosAnanke has no
way to honor -- there are no pthreads in a freestanding kernel), way to honor -- there are no pthreads in a freestanding kernel),
not the sole enforcement mechanism: Makefile.starkernel additionally not the sole enforcement mechanism: kernel/Makefile additionally
keeps its own unconditional `VM_FEATURE_OVERRIDES += keeps its own unconditional `VM_FEATURE_OVERRIDES +=
-DHEARTBEAT_THREAD_ENABLED=0` post-override exactly as it was -DHEARTBEAT_THREAD_ENABLED=0` post-override exactly as it was
before this migration. Deliberately redundant with the `depends before this migration. Deliberately redundant with the `depends
+14 -1
View File
@@ -11,7 +11,20 @@ config STARFORTH_ENABLE_VM
kernel that only reaches the M0-M6 hardware milestones (console, kernel that only reaches the M0-M6 hardware milestones (console,
PMM, VMM, interrupts, timers, kmalloc) with no FORTH interpreter, PMM, VMM, interrupts, timers, kmalloc) with no FORTH interpreter,
no capsules, no "ok" REPL. Gates a large source-file selection no capsules, no "ok" REPL. Gates a large source-file selection
block in Makefile.starkernel, not just a handful of -D flags. block in kernel/Makefile, not just a handful of -D flags.
config STARFORTH_V4
bool "Build StarForth v4, the F18-derived engine, in -- and boot it (STARFORTH_V4)"
default y
help
The kernel carries StarForth v4 as well as v3 and boots v4: one
host node, after the M0-M6 hardware milestones, of the golden model
of the 32-opcode engine (v4/src) running the capsule image built
from v4/capsule, with its console on the kernel's serial console;
it reaches v4's "ok> " prompt. `system=v3` in the boot arguments
boots the v3 VM and its fleet instead. On by default since
2026-10-14: v3 is being retired. Off builds v3 alone. See
docs/v4.0.0/DECOMPOSITION.md and boards/BRINGUP.md A6.
config PARITY_MODE config PARITY_MODE
bool "Deterministic parity harness mode (PARITY_MODE)" bool "Deterministic parity harness mode (PARITY_MODE)"
+194 -1313
View File
File diff suppressed because it is too large Load Diff
+97 -54
View File
@@ -1,95 +1,138 @@
# LithosAnanke v2.0.1 # LithosAnanke v2.1.0
**UEFI-bootable FORTH microkernel.** Boots from firmware, initialises memory and interrupts, then runs the StarForth VM as its sole userspace runtime. No libc. No OS. Just stone and necessity. **UEFI-bootable FORTH microkernel.** Boots from firmware, initialises memory and interrupts, then
runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and necessity.
*Lithos* (foundation) + *Ananke* (necessity) — the kernel under StarshipOS. *Lithos* (foundation) + *Ananke* (necessity) — the kernel under StarshipOS.
--- ---
## Status — M7.1 (Capsule System · Multi-VM Fleet) ## Products
StarForth v4 moves the engine onto a 32-instruction core derived from Chuck Moore's F18
(`docs/v4.0.0/`). With it, this repository carries three products, not one:
| Product | What it is |
|---|---|
| **Hosted StarForth F18** | The v4 engine as a native Linux build, for amd64, arm64 and riscv64. |
| **FPGA StarForth F18** | A 32-bit build of the same engine loaded into the FPGA: the gateway to the rest, the foundation everything else is built up from. |
| **StarshipOS** | The bare-metal product: LithosAnanke running StarForth. |
FORTH-79 is recomposed on the F18 engine and stored as a capsule; the StarshipOS-specific
vocabulary gets the same treatment. v3 remains the reference system until v4 meets its
acceptance criteria (`docs/v4.0.0/JUSTIFICATION.md` §16). **Both run on bare metal now:** every
board image carries v4 and v3, boots v4 as built, and one word in its boot configuration
chooses (see below).
---
## Status
| Milestone | | Status | | Milestone | | Status |
|---|---|---| |---|---|---|
| M0–M6 | UEFI boot · PMM · VMM · IDT · APIC · heap · framebuffer VT100 console (v1.5.1-FINAL) | ✅ Complete | | M0–M6 | UEFI boot · PMM · VMM · IDT · APIC · heap · framebuffer VT100 console | ✅ Complete |
| M7 | StarForth VM integration + parity validation | ✅ Complete | | M7 | StarForth VM integration + parity validation | ✅ Complete |
| **M7.1** | **Capsule birth protocol · Mama FORTH vocabulary · Tripod multi-VM fleet (Hermes/Artemis) · Word-level ACL (Phases 1–7)** | 🔄 **In Progress** | | M7.1 | Capsule birth · Mama FORTH vocabulary · the Tripod fleet · kernel-Hermes · word-level ACL | ✅ Live |
| M8 | REPL — keyboard input, interactive Forth | Planned | | M8 | Keyboard input to the REPL — PS/2, virtio and **USB** keyboards (a full keyboard: Caps/Num Lock, keypad) | ✅ In QEMU, all three ISAs |
| M9 | Block storage — AHCI driver | Planned | | M9 | Block storage — Artemis's disk on virtio-blk; identity thumbdrives on USB mass storage | ✅ In QEMU · real disks: no driver yet (`boards/BRINGUP.md` A4) |
| Bare metal | a generic PC (amd64; first on the bench: a Beelink SER5), Raspberry Pi 5 (aarch64), Milk-V Mars (riscv64); Zynq-7020 (ARMv7) not yet ported | Images build; first boots on the bench — `boards/BRINGUP.md` |
POST at boot: **parity hash verified across amd64/aarch64/riscv64 · Mama capsule dictionary: 453 words** **v4 is the default build, and v3 is being retired**: every kernel boots v4 unless its boot
arguments say `system=v3`. POST at boot, on all three ISAs: v4 — **538 tests**,
`PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a`; v3 — **1052 tests**,
`PARITY:M7.1a word_count=526 hash=0x82f4ae7cb2e2d424`.
### What's live in M7.1 ### What's live
- **Tripod** — a named multi-VM fleet (Hera the Mama VM, Artemis, two Hermes - **The Tripod** — a named multi-VM fleet: **Hera** (the Mama VM, the governor), **Artemis**
instances) births, runs, and re-births independently, verified booting (block storage: a Block Allocation Map with Q48.16 block heat, cooldown and reclamation) and
live pre-REPL on all three architectures. **Hestia**, birthed, run and re-birthed independently on all three architectures.
- **Hermes** — a 17-block inter-VM messaging/channel layer between fleet - **kernel-Hermes** — messaging moved into the kernel (the Hermes VM is gone,
members, with async delivery and channel negotiation. `docs/fabric/FABRIC-3.5.md`): every VM takes its own messages on its own turn, under a
- **Artemis** — a Block Allocation Map (BAM) storage subsystem with Q48.16 cooperative switcher that every VM takes part in.
block-heat tracking and cooldown/reclamation (`ART-COOL`/`ART-REAP`). - **Identities on thumbdrives** — Zuse, the superuser, and every user is a minted USB
- **Word-level ACL** — every dictionary entry carries a TTL/allow/mode/pin thumbdrive (Ed25519, Zuse-signed); plugging one in births that user's VMs, pulling it out
access-control record. Strict, TTL, and pinned modes; two console layers ends them. There is only the drive: no password, no PIN.
(emergency `ok>` and superuser `zuse)ok>`). Phases 1–7 complete (C - **Word-level ACL** — every dictionary entry carries a TTL/allow/mode/pin access-control
infrastructure, FORTH policy layer, `zuse` bootstrap superuser, Isabelle record; strict, TTL and pinned modes; two console layers (emergency `ok>` and superuser
proof stubs, kernel parity); Phase 8 (Ed25519 PKI / thumbdrive `zuse)ok>`). Measured overhead of the live ACL-TTL mechanism: **+0.0603%**, CV 0.000%,
challenge-response) is the only item remaining. Measured overhead once architecture-independent (`docs/fabric/FABRIC-1.md` §T).
active on every check: **+0.0054%–+0.0088%**, CV = **0.000%**, across a - **Logs that persist** — every VM's log records go to a ring on Artemis's disk (`LOG-FLUSH`,
3×3 Latin-square DoE campaign (architecture × seed × 30 replicates) — `LOG-SHOW`).
three orders of magnitude below the measurement floor. - **The physics-driven runtime** — seven feedback loops and the L8 Jacquard mode selector, with
- **VM Fleet Attractor physics** — the L8 Jacquard mode selector now has a a per-VM heat channel into fleet-wide tuning (VM Fleet Attractor).
real per-VM heat channel into fleet-wide tuning, replacing hardcoded - **Kconfig build configuration** — about 40 physics, heartbeat, pipelining and kernel-only
compudynamics constants with a dynamically-inferred rate. knobs, shared with the hosted build.
- **Kconfig build configuration** — every physics/heartbeat/pipelining/
kernel-only tuning knob (~40 total) is now a discoverable, optional
Kconfig symbol shared with the hosted VM build. See **Quick Start** below.
--- ---
## Quick Start ## Quick Start
```bash ```bash
# Build kernel (requires cross-compilation toolchain, or native gcc) # One boot image per physical target (output: build/boards/<board>/)
make -f Makefile.starkernel ARCH=amd64 make boot_image TARGET=PC # any x86-64 UEFI PC -- GPT/ESP, BOOTX64.EFI
make boot_image TARGET=RASPI # Raspberry Pi 5 -- FAT, config.txt + kernel_2712.img + DTB
make boot_image TARGET=MILKV # Milk-V Mars -- GPT/ESP, BOOTRISCV64.EFI (U-Boot bootefi)
make boards # list boards (the Zynq-7020 has no ARMv7 port yet)
# Run in QEMU with OVMF # Each image carries v4 and v3. As built it boots v4; to boot v3, change the one word
make -f Makefile.starkernel qemu # system=v4 -> system=v3
# in starforth.cfg on the PC's stick or the Mars's card, or cmdline.txt on the Pi 5's card.
# Other architectures # The same TARGET drives all, docs and clean (make help)
make -f Makefile.starkernel ARCH=aarch64 qemu make # every board with a kernel port + hosted v3 + the book
make -f Makefile.starkernel ARCH=riscv64 qemu make docs # build/docs/LithosAnanke.pdf (LaTeX master: docs/book/main.tex)
make clean TARGET=RASPI # that board's outputs and build/aarch64/kernel
# The kernel in QEMU (OVMF / AAVMF / EDK2), one architecture at a time -- boots v4
make -f kernel/Makefile ARCH=amd64 clean qemu
make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f kernel/Makefile ARCH=riscv64 clean qemu
make -f kernel/Makefile ARCH=amd64 KERNEL_ARGS=system=v3 clean qemu # v3, while it remains
# The Pi 5's native boot path, rehearsed on QEMU's virt machine at EL2
make -f kernel/Makefile ARCH=aarch64 RPI5_NATIVE_BASE=0x40080000 rpi5-rehearsal
``` ```
Artifacts: `build/amd64/kernel/starkernel_loader.efi` · `build/amd64/kernel/starkernel_kernel.elf` Artifacts: `build/<arch>/kernel/starkernel_loader.efi` · `build/<arch>/kernel/starkernel_kernel.elf`
For the hosted VM by itself (Linux, no cross-compiler needed, no bare-metal tooling): see Tree: `kernel/` (LithosAnanke: `Makefile`, `src/`, `include/starkernel/`, `linker/`),
the separate **StarForth** repository — LithosAnanke used to be a branch inside that repo, `v3/` (StarForth v3 engine and hosted build), `v4/` (StarForth v4, see `docs/v4.0.0/`),
now it's its own project with its own `master`. `boards/<board>/` (`board.mk` + boot files), `capsules/` (the FORTH capsules). Every makefile
runs from the repo root; the root `Makefile` forwards any other goal to `v3/Makefile`.
For the hosted v3 VM by itself, see the separate **StarForth** repository — LithosAnanke used to
be a branch inside it, and is now its own project.
### Build configuration (optional) ### Build configuration (optional)
Every kernel-only knob (`STARFORTH_ENABLE_VM`, `PARITY_MODE`, the shared Every kernel-only knob is an optional Kconfig symbol; a plain `make -f kernel/Makefile` uses
physics/heartbeat family, etc.) is an optional Kconfig symbol — a plain the defaults unless you opt in:
`make -f Makefile.starkernel` uses the same defaults it always has unless
you opt in:
```bash ```bash
make -f Makefile.starkernel ARCH=amd64 menuconfig make -f kernel/Makefile ARCH=amd64 menuconfig
make -f Makefile.starkernel ARCH=amd64 kernel_amd64_defconfig make -f kernel/Makefile ARCH=amd64 kernel_amd64_defconfig
``` ```
--- ---
## Documentation ## Documentation
**Start at [docs/README.md](docs/README.md)** — the map: where each kind of document lives and
which to believe. Among them:
| | | | | |
|---|---| |---|---|
| [System Architecture](docs/lithosananke/SYSTEM_ARCHITECTURE.md) | Full kernel + VM design | | [The FABRIC record](docs/fabric/) | Every design decision and the work as it happened (`FABRIC-3.md` is the living one) |
| [HAL Reference](docs/lithosananke/hal/) | Hardware abstraction layer interfaces | | [StarForth v4](docs/v4.0.0/) | The F18-derived engine |
| [Capsule System — M7.1](docs/lithosananke/M7.1.md) | Capsule birth protocol design | | [Board bring-up](boards/BRINGUP.md) | Getting onto a PC, the Pi 5 and the Mars |
| [VM Fleet Attractor design log](docs/working/architecture/VM-FLEET-ATTRACTOR-DESIGN-20260705.md) | Tripod/Hermes/Artemis physics + build-system history | | [Roadmap and versioning](docs/reference/ROADMAP.md) | Milestone plan and release-versioning policy |
| [Getting Started / Kconfig reference](docs/working/architecture/getting-started/DEVELOPER.md#build-configuration-kconfig) | Full symbol reference for both build targets | | [Capsule System — M7.1](docs/reference/M7.1.md) | Capsule birth protocol |
| [Word-level ACL](docs/reference/word-acl/DESIGN.md) | The access-control design |
| [HAL, as built](kernel/src/hal/README.md) | Hardware abstraction layer |
| [Developer guide / Kconfig reference](docs/working/architecture/getting-started/DEVELOPER.md#build-configuration-kconfig) | Full symbol reference for both builds |
| [Dead ideas and revised claims](docs/DEAD-AND-REVISED.md) | What is no longer true, and since when |
| [Changelog](CHANGELOG.md) | Milestone-level history | | [Changelog](CHANGELOG.md) | Milestone-level history |
| [Roadmap](docs/lithosananke/ROADMAP.md) | Milestone plan through self-hosting |
--- ---
+292
View File
@@ -0,0 +1,292 @@
# Board bring-up checklist
Written 2026-10-13, before any of the four boards has been booted. It is what to do on the day
a board is on the bench, and what has to be true before that day is worth having.
Nothing here has been done on hardware. Every statement about the code was checked in the code
on the date above; where it comes from a document instead, the document is named. When a board
has been booted, its results go in `docs/fabric/FABRIC-3.md` (sections III, IV, V) and its
`README.md` here, and this file is corrected.
The four boards: `PC` (amd64, any x86-64 UEFI PC; the one on the bench is a Beelink SER5 -- the target was named `SER5` until 2026-10-14), `RASPI` (Pi 5, aarch64), `MILKV` (Mars, riscv64), `ZYNQ7020`
(ARMv7, no port yet). See `boards/README.md` for what each image is.
---
## 1. What stands between today and a first boot
Found while writing this checklist. Items marked **blocks first boot** will stop a board
showing anything, or stop it being typed to; they are worth closing before the bench day.
None has been fixed: each needs your word.
### 1.1 All boards
| # | What | Where | Effect on hardware |
|---|---|---|---|
| A1 | **Fixed 2026-10-14.** The USB controller was matched by QEMU's own IDs (`1B36:000D`) on PCI bus 0 alone. Now: found by its PCI class (`0C/03/30`) on any bus, slot and function; its register window mapped at the size its BAR reports; taken from the firmware through the USB Legacy Support capability (SMIs off); and 64-byte contexts (`CSZ=1`, common on real controllers) laid out instead of refused. Every controller is driven, up to 8 (since 2026-10-14, `FABRIC-3.md` XLII): a stick or keyboard may be in any port. | `kernel/src/usb/xhci.c`, `kernel/src/pci/pci.c`; `FABRIC-3.md` XL | Rehearsed in QEMU with another vendor's controller behind a bridge, all three ISAs. Not rehearsable: the firmware handoff and 64-byte contexts (QEMU's controller has neither). |
| A2 | **No prompt without a login.** The production default, `EMERGENCY_CONSOLE_ENABLED=n`, keeps the system headless until an identity logs in by thumbdrive. | `Kconfig.heartbeat:68`; `FABRIC-3.md` VIII.1 | With A1, the v3 system never shows a prompt on hardware. A bring-up build must set `EMERGENCY_CONSOLE_ENABLED=1`. |
| A3 | **Fixed 2026-10-14.** A USB boot-protocol keyboard is driven (xHCI interrupt endpoint, `SET_PROTOCOL(boot)`), its reports become the same key events as the PS/2 and virtio keyboards, and the console treats a full keyboard as one: Caps Lock and Num Lock as toggles shown on the keyboard's lights, the keypad as digits or navigation, the arrows and navigation block mapped (the line editor itself still has no cursor movement). While a USB keyboard runs, the console services its reports every timer tick. | `kernel/src/usb/usb_kbd.c`, `kernel/src/usb/xhci.c`, `kernel/src/repl.c`; `FABRIC-3.md` XLI | Rehearsed in QEMU on all three ISAs; on amd64 with the USB keyboard the only keyboard. Limits: a keyboard whose first interface is not the keyboard is not used; no key repeat. Several keyboards, on any controllers, each its own. |
| A4 | **The only disk driver is virtio.** | `kernel/src/virtio/virtio_blk.c`; `kernel_main.c:493` | On hardware Artemis finds no disk ("Artemis: no virtio-blk disk"). What the fleet then does has not been tried even in QEMU: see step 3.3. |
| A5 | **Entropy:** RDRAND on amd64 only. aarch64 and riscv64 have virtio-rng alone. | `kernel/src/rng/rng.c` | Pi 5 and Mars print the "no entropy backend available" warning; anything that needs random bytes is refused. Minting needs them. |
| A6 | **Fixed 2026-10-14.** Every board image carries both systems, v3 and v4, and the boot arguments choose: `system=v4` (as built: v4 is the default) or `system=v3` -- one word in `starforth.cfg` on the SER5's and the Mars's stick or card, in `cmdline.txt` on the Pi 5's card. No rebuild to switch. | root `Makefile`, `kernel/Makefile`, `kernel/src/kernel_main.c`, `kernel/src/boot/cmdline.c`; `FABRIC-3.md` XLIII | The SER5 image itself, booted under OVMF: v3 as built, v4 after the one-word edit. The boot says which system runs and why ("System: ..."). |
### 1.2 PC (the SER5 on the bench)
| # | What | Where | Effect |
|---|---|---|---|
| S1 | HPET address fixed at `0xFED00000`, not read from ACPI. | `FABRIC-3.md` III item 6, finding 1 | Wrong only on a machine that puts it elsewhere. Most do not. |
| S2 | Local APIC address fixed at `0xFEE00000`; the MADT's override entry is not parsed. | finding 2 | The same. |
| S3 | **Half fixed 2026-10-14.** The i8042: a PC without one (port 0x64 reads 0xFF) hung the kernel at boot, in a drain loop that never ended -- found rehearsing A3 with QEMU's `i8042=off`. Now detected and skipped, every drain bounded. Still open: the legacy PIC is written to with no check that it exists. | `kernel/src/arch/amd64/i8042.c`; finding 3; `FABRIC-3.md` XLI | A legacy-free SER5 no longer stops at the I/O APIC. The PIC: unknown on a machine without one. |
| S4 | `BYE` resets through the i8042, not the ACPI reset register. | finding 4 | `BYE` may do nothing. It does not hang. |
| S5 | Whether the SER5 has a serial header is not known. | `FABRIC-3.md` III | Without one, and with A3, the SER5 can be watched over HDMI and not typed to. |
The loader probes COM1 before using it, and since 2026-10-13 so does the kernel's console.
Before that, on a board with no COM1 the status port read all ones: writes went nowhere, and
the prompt was told a key was waiting on every poll and read `0xFF` for ever.
### 1.3 Raspberry Pi 5
| # | What | Where | Effect |
|---|---|---|---|
| R1 | **Fixed 2026-10-13.** Every character the console printed was also written to a PL011 at `0x09000000`, QEMU's address, which on a Pi 5 is ordinary RAM. The console now finds its serial line from the devicetree's `/chosen/stdout-path`: on the Pi 5 that is `serial10`, the debug connector, a PL011 at `0x107d001000`. | `kernel/src/hal/console.c`, `kernel/src/hal/fdt_uart.c`; `tools/fdt_uart_test.c` reads the board's real devicetree | Checked off the board only. The first run is the board's. |
| R2 | **Fixed 2026-10-14.** Entry is at EL2 with the MMU off, where every access is Device memory: unaligned accesses and atomics fault, nothing is cached. The entry stub now cleans the cache over the image, turns the MMU and caches on before any C (identity map: the image's GiB Normal in 2 MiB blocks, the rest Device), and routes interrupts to EL2; C then makes the rest of the devicetree's RAM Normal. Rehearsing it found and fixed three more: the PL011 register shift, the GIC address (not carried through `/soc`'s `ranges`), and the EL2 timer interrupt never being taken. | `native_rpi5_entry.S`, `rpi5_mmu.c`, `fdt.c` (`fdt_reg_address`), `apic.c`; `FABRIC-3.md` XXXIX | Rehearsed on QEMU virt at EL2 (section 3.2): POST passes, same parity hash. Not yet on the board. |
| R3 | **Partly fixed 2026-10-14.** The address returned is now carried through the devicetree's `dma-ranges` (on the Pi 5 it is already physical; the old `& 0x3FFFFFFF` was the Pi 4's rule), every mailbox wait gives up after one second, the request buffer is cleaned to RAM and back around the exchange, and the framebuffer is mapped uncached. Still unverified: the size field of the allocate tag. The mode is fixed at 1920x1080x32. | `rpi5_mailbox.c`, `rpi5_mmu.c`; `FABRIC-3.md` IV.3 item 3, XXXIX | QEMU virt has no mailbox: none of this runs before the board. No picture shows as no framebuffer, not a hang. |
| R4 | USB, Ethernet and GPIO are behind the RP1 chip on PCIe, which needs a Broadcom-specific driver that is not written. | `FABRIC-3.md` IV.3 item 5 | No USB on the Pi 5 whatever is done about A1. |
| R5 | No hardware entropy source is known for the BCM2712. | `FABRIC-3.md` IV.2 | A5 stands. |
### 1.4 Milk-V Mars
| # | What | Where | Effect |
|---|---|---|---|
| M1 | **Fixed 2026-10-13.** The console, and the UEFI loader before it, wrote to a 16550 at `0x10000000` with registers one byte apart. The JH7110's UART is at that address with `reg-shift = <2>` and `reg-io-width = <4>` (mainline `jh7110.dtsi`): the loader would have waited for ever on its first character. Both now take the layout from the devicetree. | `kernel/src/hal/console.c`, `kernel/src/boot/uefi_loader.c` | Rehearsed in QEMU through U-Boot, which hands over a devicetree: "serial line is a 16550 at 0x10000000 (named by the devicetree)". QEMU's UART is byte-spaced, so the four-byte layout itself is checked by the host test only. |
| M2 | The display depends on U-Boot offering a framebuffer to the EFI loader. | `boards/milkv/README.md` | Unknown. With M1 unfixed there is then no channel at all. |
| M3 | USB is behind the JH7110's PCIe controller; whether that is plain ECAM has not been looked up. | `FABRIC-3.md` V.3 item 5 | No USB until it is. |
| M4 | `FABRIC-3.md` V describes a native entry at `0x40000000`; the image built today is the UEFI loader run by U-Boot's `bootefi`. The README here is the newer and is what the build does. | `boards/milkv/README.md` | None; noted so the two are not confused on the day. |
| M5 | Whether the U74 has the entropy instruction is not known. | `FABRIC-3.md` V.2 | A5 stands. |
### 1.5 Zynq-7020
No image can be built. Needed first, in order: the board chosen (it fixes `BOOT.BIN`); an ARMv7
port, `kernel/src/arch/armv7` (entry, MMU, GIC, private timer); and the four files that use
`__int128` or have no ARMv7 branch (`boards/zynq7020/README.md` names them). It is the host for
the v4 mesh, so it also waits on A6.
### 1.6 Found in rehearsal, and fixed, 2026-10-13: the bring-up build flooded its prompt
Built with `EMERGENCY_CONSOLE_ENABLED=1` and booted with no thumbdrive, the prompt printed
`ok> ok` without end: 1.4 million times in 200 seconds. The line reader
(`kernel/src/repl.c`, `sk_console_readline()`) gave up at once whenever no identity was logged
in, which the production build answers by going silent; the bring-up build took it as an
empty line and asked again. It now gives up only in the production build. Rehearsed on
riscv64 (`logs/20261013-235129`): one prompt, which waits, and three typed lines answered.
### 1.7 What I would close before the bench day
In this order, each as a design for approval first:
1. ~~R1 and M1: a console that finds its UART from the devicetree, and does nothing when
there is none.~~ Done 2026-10-13, and 1.6, the flood.
2. A6: the v4 switch in the board images. The v4 node needs only a console to reach a prompt;
it has no login, no fleet and no disk to wait for, so it is the shorter road to a first
prompt on each board.
3. A1: find the USB controller by its class code, not one vendor's number. That gives the SER5
thumbdrives. The Pi 5 and the Mars need R4 and M3 as well.
4. A serial cable for every board (section 2).
---
## 2. Before the day
**To have on the bench**
- [ ] A USB-to-serial adapter with 3.3 V logic levels, and jumper wires. It is the one channel
that survives a framebuffer failure, and with A3 it is the one way to type. FABRIC-3
decided HDMI only for the Pi 5 and the Mars because no adapter was to hand; that
decision is worth revisiting before the day.
- [ ] HDMI display and cable (micro-HDMI for the Pi 5).
- [ ] A USB stick for the SER5; a microSD card each for the Pi 5 and the Mars; a card reader.
- [ ] A PS/2 keyboard if the SER5 turns out to have a PS/2 port; otherwise serial.
- [ ] A camera, for the screen: when there is no serial log, photographs are the record.
- [ ] The identity thumbdrives (`disk/README.md`), once A1 is closed.
**To know before starting**
- [ ] SER5: Secure Boot is off (`FABRIC-3.md` III says it is on this unit); which key opens
the firmware's boot menu; whether there is a serial header.
- [ ] Pi 5: the EEPROM firmware is recent enough to honour `kernel_address` and `os_check`
(boot Raspberry Pi OS once and note the version).
- [ ] Mars: the SPI flash holds a U-Boot that scans the SD card for an EFI loader; the boot
switches select SPI flash. Stop U-Boot at its prompt once and save `printenv`, then
`fdt addr ${fdtcontroladdr}` and the output of `fdt print /soc/serial@10000000`: that
settles M1.
---
## 3. Build, and rehearse in QEMU
### 3.1 Build
```
make boot_image TARGET=PC EMERGENCY_CONSOLE_ENABLED=1
make boot_image TARGET=RASPI EMERGENCY_CONSOLE_ENABLED=1
make boot_image TARGET=MILKV EMERGENCY_CONSOLE_ENABLED=1
```
- [ ] ~~`make clean TARGET=<board>` first.~~ `make boot_image` now cleans its ISA's kernel
objects itself (2026-10-14): make does not see a change of compile flags, and an image
built over old objects booted headless (2026-10-13) or would have lacked v4.
- [ ] The images boot v4. To boot v3 instead: change `system=v4` to `system=v3` in
`starforth.cfg` (PC, Mars) or `cmdline.txt` (Pi 5) on the medium. The boot prints "System: ..." with the choice.
- [ ] Each ends with its image in `build/boards/<board>/`. Record `sha256sum` of each.
- [ ] Confirm the switch took: the image booted in QEMU (3.2) shows a prompt with no
thumbdrive attached. After a clean build it does (tried on `MILKV`).
- [ ] The Pi 5 build fetches the board's DTB once from the pinned firmware release; with no
network, pass `RPI5_DTB=/path/to/bcm2712-rpi-5-b.dtb`.
- [ ] Put back `v3/include/version.h` and `capsules/BLOCK_MAP.md` afterwards: the build
rewrites both.
### 3.2 Rehearse each image as its own disk
One QEMU at a time. Use a copy of the image: the kernel writes to its disk.
- [ ] **PC:** q35 with OVMF, the image as the only disk, no `-cdrom`, no virtio disk, no
thumbdrive. This is the machine the README's "booted in QEMU" refers to.
- [ ] **MILKV:** the command in `boards/milkv/README.md` (OpenSBI, U-Boot, `bootefi`).
- [ ] **RASPI:** there is no QEMU model of the Pi 5, but its native path -- raw image, entry
at EL2 with the MMU off, devicetree in x0 -- is rehearsed on QEMU virt:
`make -f kernel/Makefile ARCH=aarch64 RPI5_NATIVE_BASE=0x40080000 rpi5-rehearsal`
(log under `logs/<TS>/aarch64-rpi5/`). Not rehearsed: the mailbox and framebuffer, the
Pi 5's own UART and GIC addresses (checked against its real devicetree by
`tools/fdt_uart_test.c` instead), and PCI (virt's needs ACPI, the Pi 5's is R4).
### 3.3 What to settle in the rehearsal
- [ ] With no virtio disk and no thumbdrive, how far does the v3 system get, and what does it
print? (A4. Not tried.)
- [ ] Note the verdict lines of that boot (section 5). They are what the board is compared
with.
- [ ] Type a line over the serial port. If it is not taken in QEMU it will not be on the
board.
---
## 4. On the bench
Do one board at a time, in this order: SER5, then the Mars, then the Pi 5. The SER5's path is
the one QEMU exercises most closely, and the Pi 5's can be rehearsed only in part (3.2).
### 4.1 Writing the media, every board
- [ ] `lsblk` before and after inserting the stick or card. Write down the device name and its
size. **`dd` to the wrong device destroys a disk.**
- [ ] `sudo dd if=build/boards/<board>/<image> of=/dev/sdX bs=4M conv=fsync status=progress`
- [ ] Read it back and compare: `sudo cmp -n $(stat -c %s <image>) <image> /dev/sdX`.
### 4.2 PC (the SER5)
- [ ] Serial, if there is a header: 115200 8N1, logged to a file from before power-on.
- [ ] HDMI and keyboard connected. Stick in a rear port.
- [ ] Power on, open the boot menu, choose the stick.
- [ ] Watch for, in order: `StarKernel UEFI Loader`; `GOP: linear framebuffer found`;
`LithosAnanke v...`; `PMM initialized.`; `VMM initialized`; `APIC: init done`;
`Timer: init done`; `Kernel heap initialized.`; `Stadium: ...`; POST; the verdict lines.
- [ ] `rng: backend = rdrand`. In QEMU it says `virtio-rng`; this line is new on hardware.
- [ ] The timer lines differ from QEMU's by design: no hypervisor, so the HPET path runs for
the first time. S1 is the finding to remember if it stops there.
### 4.3 Milk-V Mars
- [ ] Serial on the 40-pin header's UART, 115200 8N1, logged from before power-on. U-Boot
talks on it, so it shows whether the board reached U-Boot even if the kernel prints
nothing.
- [ ] Card in, HDMI connected, power on.
- [ ] U-Boot finds `EFI/BOOT/BOOTRISCV64.EFI` and starts it. If it does not, at its prompt:
`load mmc 1:1 ${kernel_addr_r} EFI/BOOT/BOOTRISCV64.EFI` then
`bootefi ${kernel_addr_r} ${fdtcontroladdr}` (the device number may differ: `mmc list`).
- [ ] The lines of 4.2, with `PLIC:` in place of `APIC:`. For the first time the interrupt
controller's address and the timer's frequency should come from the devicetree: the
QEMU lines "no DTB PLIC node" and "FALLBACK, no devicetree" should **not** appear.
- [ ] `satp.MODE` is printed at entry. Under U-Boot it may be 0 where QEMU shows `0xa`.
### 4.4 Raspberry Pi 5
- [ ] Serial on the debug connector between the HDMI ports (needs the Pi debug probe or a
matching cable), 115200 8N1. The firmware prints there before the kernel runs.
- [ ] Card in, HDMI in the port nearest the USB-C socket, power on.
- [ ] The firmware loads `kernel_2712.img` at `0x80000`. If the screen stays on the firmware's
diagnostic page, the firmware did not accept the image: note what it says.
- [ ] Then the lines of 4.2 from `LithosAnanke v...` on (there is no UEFI loader), with
`GICv2:` in place of `APIC:`. The line "no DTB GIC node -- using QEMU virt-machine
defaults" should **not** appear.
- [ ] Expect `PCI: MCFG parse failed on aarch64 -- no ECAM`: that is R4 and is not a failure
of the boot.
---
## 5. What counts as a pass
Record which level each board reached. A board is not "booted" on the strength of level 1.
| Level | What was seen | Compared with |
|---|---|---|
| 1 | The kernel's first line, on any channel | - |
| 2 | Every milestone line through `Kernel heap initialized.` | The QEMU log of the same build |
| 3 | `POST: PASSED` and `PARITY:OK` | The same test count as QEMU |
| 4 | The `PARITY:M7.1a` line's `word_count` and `hash` equal QEMU's for the same ISA | The rehearsal boot of 3.2 |
| 5 | A prompt, and a typed line answered: `1 2 + .` gives `3` | - |
| 6 | Entropy from hardware; an identity minted on a thumbdrive and attached again after a power cycle | The gates of `FABRIC-3.md` III, IV, V |
Level 4 is the one that says the board runs the same system as QEMU. Levels 5 and 6 wait on
section 1: today no board can reach 6, and only the SER5 with a serial header can reach 5.
For the v4 node, once A6 is built, the lines are `PARITY:V4_POST tests=538 pass=538 fail=0`,
`PARITY:V4_SYSTEM word_count=... dict_hash=...` equal to the hosted programs', `PARITY:OK`,
`POST: PASSED`, and the prompt `ok> `.
---
## 6. If it stops
| What is seen | Look at |
|---|---|
| Nothing at all, any board | Is the firmware reaching the image? Serial shows the firmware's own output on the Mars and the Pi 5. On the SER5, try the UEFI shell: `startup.nsh` is in the image. |
| Pi 5: firmware runs, then nothing | R1, then R2, then R3. |
| Mars: U-Boot starts the loader, then nothing on serial | M1. HDMI may still show the boot if M2 holds. |
| SER5: stops in the `Timer:` lines | S1. |
| Stops at `APIC` / `GICv2` / `PLIC` | The controller's address: S2 on the SER5; on the others, whether the devicetree node was found (the line says). |
| Runs through POST, then silence | A2: the build is headless. Rebuild with `EMERGENCY_CONSOLE_ENABLED=1`. |
| A prompt that takes no keys | A3. Type over serial. |
| `Artemis: no virtio-blk disk` | A4. Expected on every board today. |
| `rng: WARNING -- no entropy backend available` | A5. Expected on the Pi 5 and the Mars today. |
Write down the last line shown, exactly, and photograph the screen. Do not change two things
between attempts.
---
## 7. What to keep
- [ ] The serial transcript of every attempt, passed or failed, under `logs/` with the date,
the board and the image's `sha256` in its name. Logs are kept and committed, as QEMU's
are.
- [ ] Photographs of the screen where there was no serial.
- [ ] The firmware versions: SER5 BIOS, Pi 5 EEPROM, Mars U-Boot and OpenSBI.
- [ ] The Mars's `printenv` and devicetree, and the Pi 5's DTB as used.
- [ ] The results written into `FABRIC-3.md` (each section ends with "update this section with
results") and each board's `README.md` status line.
---
## 8. Before the builds are cut
The administrative work that is yours to call, listed so it is not found on the day:
- [ ] The kernel's release number. `kernel/Makefile` holds a table that gives each hardware
gate its own number (SER5, then the Pi 5, then the Mars); it is still to be ruled.
- [ ] The uncommitted change to `kernel/Makefile` that adds the ISA to the version line: it
needs a three-ISA acceptance run in the v3 configuration before it is committed.
- [ ] `CHANGELOG.md`: nothing between 2026-08-18 and the uncommitted entry of 2026-10-09.
- [ ] `sbom.spdx` and `sbom.spdx.json` brought up to date.
- [ ] The merge of `StarForth-v4.0.0` to `master`, and the tags `LithosAnanke v2.0.0` and
`StarForth v4.0.0`: only when you say.
- [ ] `.claude/CLAUDE.md` still describes the build before `boards/` existed.
+30
View File
@@ -0,0 +1,30 @@
# boards/
One directory per physical target. `make boot_image TARGET=<NAME>` (repo root) maps the
name to a directory here, reads its `board.mk`, and builds the single file that goes on
that board's boot medium into `build/boards/<board>/`.
| TARGET | Directory | ISA | Boot path | Image |
|---|---|---|---|---|
| `PC` | `pc/` | amd64 | UEFI firmware, removable-media path -- any x86-64 PC | GPT + FAT32 ESP: `EFI/BOOT/BOOTX64.EFI` |
| `RASPI` | `raspi/` | aarch64 | Pi 5 EEPROM firmware, native | MBR + FAT32: `config.txt`, `kernel_2712.img`, `bcm2712-rpi-5-b.dtb` |
| `MILKV` | `milkv/` | riscv64 | SPI-flash U-Boot + OpenSBI, `bootefi` | GPT + FAT32 ESP: `EFI/BOOT/BOOTRISCV64.EFI` |
| `ZYNQ7020` | `zynq7020/` | armv7 | BootROM, `BOOT.BIN`, U-Boot | not yet: needs `kernel/src/arch/armv7` |
`board.mk` sets:
- `BOARD_DESC`: one-line description (`make boards`)
- `BOARD_ARCH`: kernel ISA (`kernel/src/arch/<arch>`)
- `BOARD_BOOT`: image recipe in `kernel/Makefile` (`uefi-esp`, `rpi-native`, ...)
- `BOARD_IMAGE`: output file name
Disk images are assembled by `scripts/mkdiskimage.sh`, which needs no root access and no loop
devices. `KERNEL_ARGS="..."` is written as `starforth.cfg` (UEFI boards) or `cmdline.txt`
(Pi 5, where the firmware copies it into `/chosen/bootargs`). `BOOT_IMAGE_SIZE_MIB` sets the
image size; the default is 128.
Hardware status: none of these images has been booted on real silicon from this build. The
PC image has been booted in QEMU (q35 + OVMF, from its own disk) through POST. (`PC` was named
`SER5` until 2026-10-14, after the first PC on the bench; the image was never specific to it.) The Pi 5
native path (`raspi/README.md`) and the JH7110 peripherals have still only been checked by
compiling.
+30
View File
@@ -0,0 +1,30 @@
# Milk-V Mars boot media
`make boot_image TARGET=MILKV` builds `build/boards/milkv/lithos-milkv.img`: a GPT disk with one
FAT32 EFI System Partition. Write it to an SD card with `dd`. The partition holds:
- `EFI/BOOT/BOOTRISCV64.EFI`: the riscv64 monolithic loader, the same one QEMU boots.
- `startup.nsh`: for a UEFI shell, if one is used.
- `starforth.cfg`: only present when `KERNEL_ARGS="..."` is given.
The board's own SPI-flash U-Boot, with OpenSBI underneath, finds the loader through its standard
`bootefi` scan of the removable-media path. U-Boot passes its devicetree to the loader through the
EFI configuration table.
Status: booted in QEMU through the same chain the board uses: OpenSBI, then U-Boot
`qemu-riscv64_smode`, then `bootefi` from this image's ESP, then the loader and the kernel. POST
passed, Stadium conservation was exact (resident 43691 + reservoir 21845 = 65536 = `Q48_ONE`), and
Hestia and Artemis came up. Not yet booted on the Mars itself. The JH7110 peripherals
(framebuffer, RNG) have only been checked by compiling.
To repeat the QEMU boot (`qemu-system-riscv64` is in Ubuntu 26.04's `qemu-system-riscv` package;
OpenSBI and U-Boot come from `opensbi` and `u-boot-qemu`). Use a copy, because the kernel writes
to its disk:
```
cp build/boards/milkv/lithos-milkv.img /tmp/mv.img
qemu-system-riscv64 -machine virt -cpu rv64 -m 2048 -nographic \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.bin \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin \
-drive if=none,format=raw,file=/tmp/mv.img,id=d0 -device virtio-blk-device,drive=d0
```
+11
View File
@@ -0,0 +1,11 @@
# boards/milkv/board.mk -- Milk-V Mars (StarFive JH7110, SiFive U74, RV64GC).
#
# The board's own SPI-flash U-Boot (OpenSBI underneath) runs the EFI
# application through its standard distro/bootefi scan: the SD card is a GPT
# disk with one FAT32 EFI System Partition holding EFI/BOOT/BOOTRISCV64.EFI,
# the same riscv64 monolithic loader QEMU boots. U-Boot passes its own
# devicetree through the EFI configuration table.
BOARD_DESC := Milk-V Mars (StarFive JH7110, RV64GC, U-Boot bootefi)
BOARD_ARCH := riscv64
BOARD_BOOT := uefi-esp
BOARD_IMAGE := lithos-milkv.img
+20
View File
@@ -0,0 +1,20 @@
# PC boot media (generic x86-64, UEFI)
`make boot_image TARGET=PC` builds `build/boards/pc/lithos-pc.img`: a GPT disk with one FAT32
EFI System Partition, for any x86-64 PC whose UEFI firmware boots a removable medium. Write it to
a USB stick with `dd`. The partition holds:
- `EFI/BOOT/BOOTX64.EFI`: the amd64 monolithic loader, with the whole kernel embedded. Firmware
finds it through the UEFI removable-media path, so no boot entry has to be created.
- `startup.nsh`: runs the loader if the firmware drops into the UEFI shell.
- `starforth.cfg`: the boot arguments -- `system=v4` as built; change the word to `system=v3` to
boot v3 (and `KERNEL_ARGS="..."` adds to it).
Beside the image, `lithos-pc.spdx` / `.spdx.json`: its SBOM, every file on it with its SHA-256.
Nothing in the image is specific to one machine: it follows the generic UEFI/ACPI path in
FABRIC-3.md §III. Until 2026-10-14 this target was named `SER5`, after the first PC to be brought
up -- a Beelink SER5 (AMD Ryzen), which is still the one on the bench (`boards/BRINGUP.md`).
Status: booted in QEMU (q35 + OVMF, from this image as its own disk): v4 as built, v3 with
`system=v3`. Not yet booted on real hardware.
+12
View File
@@ -0,0 +1,12 @@
# boards/pc/board.mk -- a generic PC: x86-64, UEFI firmware, ACPI.
#
# Not one machine: the standards-compliant UEFI path (FABRIC-3.md §III), so
# any x86-64 PC whose firmware boots a UEFI removable medium. (The first to be
# brought up on the bench is a Beelink SER5, an AMD Ryzen mini-PC -- see
# boards/BRINGUP.md.) The monolithic loader embeds the whole kernel, so the
# image is a GPT disk with one FAT32 EFI System Partition holding
# EFI/BOOT/BOOTX64.EFI. Write it to a USB stick with dd.
BOARD_DESC := Generic PC (x86-64, UEFI, ACPI)
BOARD_ARCH := amd64
BOARD_BOOT := uefi-esp
BOARD_IMAGE := lithos-pc.img
+20
View File
@@ -0,0 +1,20 @@
# Raspberry Pi 5 native boot media
`make boot_image TARGET=RASPI` builds `build/boards/raspi/lithos-raspi.img`: an MBR disk
with one FAT32 (LBA) partition. Write it to an SD card with `dd`. The partition holds:
- `config.txt`: checked in here (FABRIC-3.md §IV.3 item 6). It pins `kernel_address=0x80000`
because Pi 5 firmware loads `kernel_2712.img` at 0x200000 by default.
- `kernel_2712.img`: the aarch64 kernel objects relinked at 0x80000 by
`kernel/linker/starkernel-native-rpi5.ld`, entered at `rpi5_native_start`
(`kernel/src/arch/aarch64/native_rpi5_entry.S`, which zeroes `.bss` first), and flattened
with `objcopy -O binary`.
- `bcm2712-rpi-5-b.dtb`: the Raspberry Pi firmware's own stock DTB. It is not built by this
project; it is fetched once from the firmware release pinned in `board.mk`
(`RPI_FIRMWARE_TAG`) into `build/cache/`. To use a local copy, pass `RPI5_DTB=/path/to/dtb`.
- `cmdline.txt`: only present when `KERNEL_ARGS="..."` is given. The firmware copies it into
`/chosen/bootargs`, which `rpi5_native_boot()` parses.
Not yet verified on hardware. The native path still assumes everything `kernel_main()`
needs after a UEFI handoff. The firmware enters at EL2 with the MMU off, which is not what
UEFI hands over, and that difference has not been exercised.
+18
View File
@@ -0,0 +1,18 @@
# boards/raspi/board.mk -- Raspberry Pi 5 (BCM2712, Cortex-A76, aarch64).
#
# Native firmware boot, no UEFI (FABRIC-3.md §IV): the Pi 5 bootloader
# lives in EEPROM and reads config.txt, kernel_2712.img and the board DTB
# from the first FAT partition of the SD card. kernel_2712.img is the
# aarch64 kernel relinked at 0x80000 (kernel/linker/starkernel-native-rpi5.ld)
# and flattened to a raw binary.
#
# The DTB is the Raspberry Pi firmware's own stock file, not built here. It
# is fetched once from the pinned firmware release below into build/cache/
# unless RPI5_DTB points at a local copy.
BOARD_DESC := Raspberry Pi 5 (BCM2712, Cortex-A76, native firmware boot)
BOARD_ARCH := aarch64
BOARD_BOOT := rpi-native
BOARD_IMAGE := lithos-raspi.img
RPI_FIRMWARE_TAG ?= 1.20260915
RPI5_DTB_URL ?= https://raw.githubusercontent.com/raspberrypi/firmware/$(RPI_FIRMWARE_TAG)/boot/bcm2712-rpi-5-b.dtb
RPI5_DTB ?= build/cache/raspi-$(RPI_FIRMWARE_TAG)/bcm2712-rpi-5-b.dtb
@@ -12,6 +12,13 @@
# firmware picks up. # firmware picks up.
kernel=kernel_2712.img kernel=kernel_2712.img
# Pin the load address to the one the image is linked at
# (kernel/linker/starkernel-native-rpi5.ld). Pi 5 firmware's own default
# for kernel_2712.img is 0x200000, not the classic 0x80000 -- leaving it
# implicit would load a 0x80000-linked flat image 1.5 MiB away from where
# every absolute address in it points.
kernel_address=0x80000
# Disable the firmware's Linux-compatible-image sanity check. Without # Disable the firmware's Linux-compatible-image sanity check. Without
# this, official docs describe it as checking for "a compatible Device # this, official docs describe it as checking for "a compatible Device
# Tree file before attempting to boot" and warn that "older non-compatible # Tree file before attempting to boot" and warn that "older non-compatible
+17
View File
@@ -0,0 +1,17 @@
# Xilinx Zynq-7020 boot media
The Zynq-7020's processing system is a dual Cortex-A9: ARMv7-A, 32-bit. It is the host for the
StarForth v4 mesh (`docs/v4.0.0/JUSTIFICATION.md` §5, §8).
Boot chain: BootROM, then `BOOT.BIN` (U-Boot SPL with the board's `ps7_init` DDR and clock setup),
then U-Boot, then LithosAnanke. Everything is read from the SD card's FAT partition.
Status: no image yet. `make boot_image TARGET=ZYNQ7020` stops with an error, because there is no
ARMv7 kernel port (`kernel/src/arch/armv7`: entry code, MMU, GIC, private timer). A trial
compile for Cortex-A9 built 147 of the 151 kernel and engine sources. The four that failed use
`__int128` or have no ARMv7 branch: `kernel/src/crypto/fe25519.c`,
`kernel/src/crypto/scalar25519.c`, `kernel/src/hal/hal.c` and
`v3/src/word_source/mixed_arithmetic_words.c`.
`BOOT.BIN` depends on the exact board (Zybo Z7-20, PYNQ-Z2, Arty Z7-20, ZedBoard, ...), because
`ps7_init` holds that board's DDR timing. The board has not been chosen yet.
+11
View File
@@ -0,0 +1,11 @@
# boards/zynq7020/board.mk -- Xilinx Zynq-7020 (dual Cortex-A9, ARMv7-A, 32-bit).
#
# Boot chain: BootROM -> BOOT.BIN (U-Boot SPL with the board's ps7_init DDR/
# clock setup) -> U-Boot -> LithosAnanke, all from the SD card's FAT
# partition. Needs the ARMv7 kernel port (kernel/src/arch/armv7), which is
# in progress: until it exists, boot_image stops with an explicit error
# rather than producing an image that cannot run.
BOARD_DESC := Xilinx Zynq-7020 (Cortex-A9, ARMv7-A, BOOT.BIN) -- ARMv7 port in progress
BOARD_ARCH := armv7
BOARD_BOOT := zynq-bootbin
BOARD_IMAGE := lithos-zynq7020.img
-12
View File
@@ -1,12 +0,0 @@
# Raspberry Pi 5 native boot media
What goes on the SD card for the native (non-UEFI) boot path (FABRIC-3.md §IV):
- `config.txt` — checked in here, done (§IV.3 item 6).
- `bcm2712-rpi-5-b.dtb` — Raspberry Pi firmware's own stock DTB; not built by this
project, copied from the firmware release the card is otherwise built from.
- `kernel_2712.img` — **does not exist yet.** `config.txt` names it, but no build target
in `Makefile.starkernel` currently emits a raw image by this name at load address
0x80000 — item 1 (entry stub) explicitly scoped a separate-image build target as future
work, not part of that item. Building this file is the remaining prerequisite before
item 7 (assembling the card) is possible.
+105 -96
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated # Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-22T22:29:26Z --> <!-- Generated by mkcapsule --manifest 2026-10-14T16:07:07Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. --> <!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live --> <!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. --> <!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -8,50 +8,53 @@
| Capsule | Blocks claimed | xxHash64 | Signed | | Capsule | Blocks claimed | xxHash64 | Signed |
|---------|----------------|----------|--------| |---------|----------------|----------|--------|
| `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4015 | `0xf8890c05c0d8f921` | yes | | `ACL.4th` | 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4015 | `0xf8890c05c0d8f921` | n/a |
| `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 | | `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` | n/a |
| `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 | | `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, 4860 | `0x486772c973d0d087` | n/a |
| `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | yes | | `block-acl.4th` | 4019, 4020 | `0xf6cc2a59e3a6734e` | n/a |
| `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x26fb485e5c9dc6ff` | yes | | `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x26fb485e5c9dc6ff` | n/a |
| `doe.4th` | 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107 | `0xf154616d248e861f` | yes | | `doe.4th` | 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107 | `0xf154616d248e861f` | n/a |
| `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 | | `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` | n/a |
| `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 | | `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` | n/a |
| `hestia:init.4th` | 4986, 4987, 4988 | `0x64e111990fbc45ff` | yes | | `hestia:init.4th` | 4986, 4987, 4988 | `0x64e111990fbc45ff` | n/a |
| `init-l8-diverse.4th` | 4820, 4821, 4822 | `0xaa293201a6c91838` | yes | | `init-l8-diverse.4th` | 4820, 4821, 4822 | `0xaa293201a6c91838` | n/a |
| `init-l8-omni.4th` | 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079 | `0x5979e314d6452045` | yes | | `init-l8-omni.4th` | 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079 | `0x5979e314d6452045` | n/a |
| `init-l8-stable.4th` | 4806 | `0xdc3830f189063a9a` | yes | | `init-l8-stable.4th` | 4806 | `0xdc3830f189063a9a` | n/a |
| `init-l8-temporal.4th` | 4830, 4831 | `0x51abd4c138246651` | yes | | `init-l8-temporal.4th` | 4830, 4831 | `0x51abd4c138246651` | n/a |
| `init-l8-transition.4th` | 4840, 4841, 4842 | `0xbcc1a81976f0a4c9` | yes | | `init-l8-transition.4th` | 4840, 4841, 4842 | `0xbcc1a81976f0a4c9` | n/a |
| `init-l8-volatile.4th` | 4810, 4811, 4812, 4813 | `0x98caabbbd92abac4` | yes | | `init-l8-volatile.4th` | 4810, 4811, 4812, 4813 | `0x98caabbbd92abac4` | n/a |
| `init.4th` | 2049, 2050, 2057 | `0xea038ba684c53443` | yes | | `init.4th` | 2049, 2050, 2057 | `0xd09db9461b336431` | n/a |
| `lib.4th` | 4050 | `0x4b216635c359ef73` | yes | | `lib.4th` | 4050 | `0x4b216635c359ef73` | n/a |
| `multiuser-doe.4th` | 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055 | `0x22140588ee7c39e6` | yes | | `multiuser-doe.4th` | 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055 | `0x22140588ee7c39e6` | n/a |
| `sdk.4th` | 5109, 5110, 5111, 5112, 5113, 5114, 5115 | `0x008fdbbb62c94a3a` | yes | | `sdk.4th` | 5109, 5110, 5111, 5112, 5113, 5114, 5115 | `0x008fdbbb62c94a3a` | n/a |
| `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | yes | | `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | n/a |
| `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | yes | | `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | n/a |
| `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | yes | | `v4:forth79.4th` | 6000, 6001, 6002 | `0x4055641ee17d176b` | n/a |
| `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | yes | | `v4:hera.4th` | 8000, 8001, 8002, 8003, 8004, 8005, 8006 | `0x1c5ea12a9341e796` | n/a |
| `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | yes | | `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | n/a |
| `workload-2.4th` | 4506, 4515, 4525, 4535, 4545 | `0xf113b3d0bcccae47` | yes | | `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | n/a |
| `workload-3.4th` | 4606, 4615, 4625, 4635, 4645, 4655, 4665 | `0x62b7a71576ad1041` | yes | | `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | n/a |
| `workload-4.4th` | 2130, 2131, 2132 | `0x099619264e650b1c` | yes | | `workload-2.4th` | 4506, 4515, 4525, 4535, 4545 | `0xf113b3d0bcccae47` | n/a |
| `workload-5-lite.4th` | 5056, 5057 | `0xea0303f38824f254` | yes | | `workload-3.4th` | 4606, 4615, 4625, 4635, 4645, 4655, 4665 | `0x62b7a71576ad1041` | n/a |
| `workload-5.4th` | *(none — raw code capsule)* | `0x526964c7c9506a11` | yes | | `workload-4.4th` | 2130, 2131, 2132 | `0x099619264e650b1c` | n/a |
| `workload-6.4th` | 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095 | `0x06fc0ce1e369ef5a` | yes | | `workload-5-lite.4th` | 5056, 5057 | `0xea0303f38824f254` | n/a |
| `workload-7.4th` | 2150 | `0x02862291387eb7ac` | yes | | `workload-5.4th` | *(none — raw code capsule)* | `0x526964c7c9506a11` | n/a |
| `workload-8.4th` | 2160 | `0x56b7f2f0efa000df` | yes | | `workload-6.4th` | 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095 | `0x06fc0ce1e369ef5a` | n/a |
| `workload-9.4th` | 4706, 4715, 4725, 4735, 4745 | `0x3f2bec73142aa424` | yes | | `workload-7.4th` | 2150 | `0x02862291387eb7ac` | n/a |
| `workload-calib1.4th` | 5043 | `0x3b9f2d17b554fabc` | yes | | `workload-8.4th` | 2160 | `0x56b7f2f0efa000df` | n/a |
| `zuse-eligibility.4th` | 4021, 4022 | `0x7b28f4776a32e0b7` | yes | | `workload-9.4th` | 4706, 4715, 4725, 4735, 4745 | `0x3f2bec73142aa424` | n/a |
| `zuse.4th` | 4016, 4017, 4018 | `0x490ded9be257a90b` | yes | | `workload-calib1.4th` | 5043 | `0x3b9f2d17b554fabc` | n/a |
| `zuse.4th` | 4016, 4017, 4018 | `0x490ded9be257a90b` | n/a |
*Signed column is `n/a`: this manifest run had no `--sign-key`. Re-run with `--sign-key <path>` to check signing status (does not modify or require rebuilding capsule_generated.c).*
## Block Map (sorted by LBN) ## Block Map (sorted by LBN)
| LBN | Capsule | xxHash64 | Status | | LBN | Capsule | xxHash64 | Status |
|-----|---------|----------|--------| |-----|---------|----------|--------|
| 2049 | `init.4th` | `0xea038ba684c53443` | ok | | 2049 | `init.4th` | `0xd09db9461b336431` | ok |
| 2050 | `init.4th` | `0xea038ba684c53443` | ok | | 2050 | `init.4th` | `0xd09db9461b336431` | ok |
| 2057 | `init.4th` | `0xea038ba684c53443` | ok | | 2057 | `init.4th` | `0xd09db9461b336431` | ok |
| 2064 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok | | 2064 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2065 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok | | 2065 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2066 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok | | 2066 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
@@ -114,8 +117,6 @@
| 4018 | `zuse.4th` | `0x490ded9be257a90b` | ok | | 4018 | `zuse.4th` | `0x490ded9be257a90b` | ok |
| 4019 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok | | 4019 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok |
| 4020 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok | | 4020 | `block-acl.4th` | `0xf6cc2a59e3a6734e` | ok |
| 4021 | `zuse-eligibility.4th` | `0x7b28f4776a32e0b7` | ok |
| 4022 | `zuse-eligibility.4th` | `0x7b28f4776a32e0b7` | ok |
| 4023 | `acl-std79.4th` | `0x773bf9209df191d1` | ok | | 4023 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4024 | `acl-std79.4th` | `0x773bf9209df191d1` | ok | | 4024 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
| 4025 | `acl-std79.4th` | `0x773bf9209df191d1` | ok | | 4025 | `acl-std79.4th` | `0x773bf9209df191d1` | ok |
@@ -149,51 +150,51 @@
| 4063 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok | | 4063 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4064 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok | | 4064 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4065 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok | | 4065 | `doe-campaign.4th` | `0x26fb485e5c9dc6ff` | ok |
| 4110 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4110 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4111 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4111 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4112 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4112 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4113 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4113 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4122 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4122 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4123 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4123 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4124 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4124 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4125 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4125 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4126 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4126 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4127 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4127 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4128 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4128 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4129 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4129 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4130 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4130 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4131 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4131 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4132 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4132 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4133 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4133 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4134 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4134 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4135 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4135 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4136 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4136 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4137 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4137 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4138 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4138 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4139 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4139 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4140 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4140 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4141 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4141 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4160 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4160 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4161 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4161 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4162 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4162 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4163 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4163 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4164 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4164 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4165 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4165 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4166 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4166 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4167 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4167 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4168 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4168 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4169 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4169 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4170 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4170 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4171 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4171 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4172 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4172 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4173 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4173 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4174 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4174 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4177 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4177 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4178 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4178 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4179 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4179 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4180 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4180 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4181 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4181 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4182 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4182 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4200 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok | | 4200 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
| 4201 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok | | 4201 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
| 4202 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok | | 4202 | `user-font-demo.4th` | `0xce1fd7d1b581a56d` | ok |
@@ -231,14 +232,12 @@
| 4840 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok | | 4840 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4841 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok | | 4841 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4842 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok | | 4842 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4851 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4851 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4852 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4852 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4853 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4853 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4854 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4854 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4856 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4856 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4857 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok | | 4860 | `artemis:init.4th` | `0x486772c973d0d087` | ok |
| 4858 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4860 | `artemis:init.4th` | `0xe6fba9ae56e1c916` | ok |
| 4900 | `fabric.4th` | `0x9d9489cbeca4099b` | ok | | 4900 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 4901 | `fabric.4th` | `0x9d9489cbeca4099b` | ok | | 4901 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 4902 | `fabric.4th` | `0x9d9489cbeca4099b` | ok | | 4902 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
@@ -364,10 +363,20 @@
| 5113 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5113 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 6000 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
| 6001 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
| 6002 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
| 8000 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8001 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8002 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8003 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8004 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8005 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
| 8006 | `v4:hera.4th` | `0x1c5ea12a9341e796` | ok |
## Conflicts ## Conflicts
None. None.
--- ---
*36 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.* *37 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
+2 -2
View File
@@ -49,7 +49,7 @@ Blocks: **2049–2052, 2057**
| Block | Immutable | Justification | | Block | Immutable | Justification |
|-------|-----------|---------------| |-------|-----------|---------------|
| 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) | | 2049 | No | Hera VM init: `VM-TREE`/`VM-PARENT`/`VM-CHILDREN`; loads `ACL.4th`, `block-acl.4th`, `lib.4th` (`zuse-eligibility.4th` removed 2026-10-14 with word-ACL elevation — FABRIC-3.md §XXXVII). **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 | | 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`) | | 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 | | 2052 | No | TRIPOD-TEST invocation block |
@@ -350,7 +350,7 @@ three-architecture acceptance for the deletion: `logs/20260922-181141/amd64/`,
Phase 4 entry for the full account, including one found-not-fixed collateral Phase 4 entry for the full account, including one found-not-fixed collateral
defect (`SEND-ELEVATE-REQUEST`, this file's own former caller into defect (`SEND-ELEVATE-REQUEST`, this file's own former caller into
`zuse-eligibility.4th`'s `ELEVATE-GRANT`, is now unreachable — Captain Bob's `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). 2026-09-22 decision: leave it, Phase 8 PKI will build its own entrypoint). Removed 2026-10-14: elevation was ruled not needed, and `zuse-eligibility.4th` (blocks 4021–4022), its C words and the eligibility list went with it (FABRIC-3.md §XXXVII).
Former blocks 4100–4153 (ex-Artemis-gaps) are now UNASSIGNED — see Unassigned Former blocks 4100–4153 (ex-Artemis-gaps) are now UNASSIGNED — see Unassigned
Ranges below. The per-block justification table this section used to carry Ranges below. The per-block justification table this section used to carry
(arena allocator ABI, message/channel field accessors, the VM-name routing (arena allocator ABI, message/channel field accessors, the VM-name routing
+1 -1
View File
@@ -34,6 +34,6 @@ Each block is limited to 1024 bytes. Verify with `wc -c` before committing.
## See also ## See also
- [`experiments/bare_metal/README.md`](../experiments/bare_metal/README.md) — DoE protocols and block namespace rules - [`experiments/bare_metal/README.md`](../experiments/bare_metal/README.md) — DoE protocols and block namespace rules
- [`docs/03-architecture/word-acl/DESIGN.md`](../docs/03-architecture/word-acl/DESIGN.md) — ACL system design - [`docs/reference/word-acl/DESIGN.md`](../docs/reference/word-acl/DESIGN.md) — ACL system design
- [`tools/mkcapsule.c`](../tools/mkcapsule.c) — assembles capsules into `capsule_generated.c` - [`tools/mkcapsule.c`](../tools/mkcapsule.c) — assembles capsules into `capsule_generated.c`
- [Project root](../README.md) - [Project root](../README.md)
+12 -36
View File
@@ -498,47 +498,23 @@ Block 4854
STARTUP-BANNER STARTUP-BANNER
Block 4856 Block 4856
( Storage-attach ack builder. Hera sends "<dev-addr> ) ( HERA-BLK-ATTACH-REQ, dev-addr -- : Hera's storage-attach )
( HERA-BLK-ATTACH-REQ"; reply is "<dev-addr> <ok?> ) ( request, VM-EXEC'd into Artemis. Runs BLK-ATTACH here, then )
( BLK-ATTACH-ACK" so identity birth only proceeds once ) ( replies with KH-BLK-ATTACH-SEND, dev-addr ok? -- sent? : )
( storage is confirmed (repl.c's BLK-ATTACH-ACK). Bob, ) ( the kernel writes the reply text for Hera itself, from the )
( 2026-09-07. ) ( two numbers, for Artemis only -- so identity birth only )
CREATE ATTACH-ACK-BUF 64 ALLOT ( proceeds once storage is confirmed. Until 2026-10-14 )
VARIABLE ATTACH-ACK-LEN ( Artemis built that text here and the word sent any text )
: ACK-APPEND ( src-addr len -- ) ( from any VM, which Hera ran as Zuse: FABRIC-3.md SXXXVII. )
DUP >R
ATTACH-ACK-BUF ATTACH-ACK-LEN @ +
SWAP CMOVE
ATTACH-ACK-LEN @ R> + ATTACH-ACK-LEN ! ;
Block 4857
: ACK-APPEND-CHAR ( char -- )
ATTACH-ACK-BUF ATTACH-ACK-LEN @ + C!
ATTACH-ACK-LEN @ 1+ ATTACH-ACK-LEN ! ;
: ACK-APPEND-NUM ( n -- )
0 SWAP <# #S #> ACK-APPEND ;
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, 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 -- ) : HERA-BLK-ATTACH-REQ ( dev-addr -- )
0 ATTACH-ACK-LEN ! DUP BLK-ATTACH KH-BLK-ATTACH-SEND DROP ;
DUP ACK-APPEND-NUM
BL ACK-APPEND-CHAR
DUP BLK-ATTACH ACK-APPEND-NUM
DROP
BL ACK-APPEND-CHAR
S" BLK-ATTACH-ACK" ACK-APPEND
ATTACH-ACK-BUF ATTACH-ACK-LEN @ KH-BLK-ATTACH-SEND DROP ;
Block 4860 Block 4860
( LOG-APPEND ( level ts msg-addr msg-u -- ) ) ( LOG-APPEND ( level ts msg-addr msg-u -- ) )
( FABRIC-3.md SXXVI follow-on Step 4, 2026-09-13: real per-VM ) ( FABRIC-3.md SXXVI follow-on Step 4, 2026-09-13: real per-VM )
( log persistence, reached via a sender's LOG-FLUSH/MSG-SEND ) ( log persistence, by hand at the console for a smoke test. )
( round trip, or by hand at the console for a smoke test. ) ( LOG-FLUSH does not come through here: since 2026-10-14 a )
( VM's records reach the ring in C, vm_log_buffer.c. )
( Thin wrapper -- kernel-only (LOG-APPEND-RAW) (log_words.c/ ) ( Thin wrapper -- kernel-only (LOG-APPEND-RAW) (log_words.c/ )
( log_region.c) does the real disk write; never calls ) ( log_region.c) does the real disk write; never calls )
( log_message() (see log_region.c's own doc comment on why). ) ( log_message() (see log_region.c's own doc comment on why). )
-1
View File
@@ -15,7 +15,6 @@ Block 2049
: VM-CHILDREN ( -- ) ." (none)" CR ; : VM-CHILDREN ( -- ) ." (none)" CR ;
S" ACL.4th" EXEC S" ACL.4th" EXEC
S" block-acl.4th" EXEC S" block-acl.4th" EXEC
S" zuse-eligibility.4th" EXEC
S" lib.4th" EXEC S" lib.4th" EXEC
( FABRIC-3.6.md Phase 4, Stage E: common:messaging.4th/ ) ( FABRIC-3.6.md Phase 4, Stage E: common:messaging.4th/ )
( MSG-CD-INIT removed -- no longer exists, no longer needed. ) ( MSG-CD-INIT removed -- no longer exists, no longer needed. )
+28
View File
@@ -0,0 +1,28 @@
Block 6000
( forth79.4th -- the FORTH-79 Required Word Set for v4, )
( as colon definitions, loaded when the system boots. )
( docs/v4.0.0/NUCLEUS.md. Blocks 6000 up. )
( A word moves here from the assembled nucleus, v4/capsule, )
( once its colon definition passes POST. )
Block 6001
( U* U/MOD -- FORTH-79 unsigned multiply and divide. )
( Neither v3 nor the v4 nucleus had them. )
( The first two words count the bits in a cell. )
: (BITS) ( -- n )
0 1 BEGIN DUP WHILE 2* SWAP 1+ SWAP REPEAT DROP ;
(BITS) CONSTANT (NB)
VARIABLE (UD)
( u1 u2 -- ud the unsigned double product )
: U* UM* ;
Block 6002
( ud u1 -- u2 u3 unsigned: u2 the remainder, u3 the quotient )
( One bit a step: shift ud left, and take u1 from its high )
( cell whenever it goes, counting that in the low cell. )
( A zero divisor is error 11, Division by zero. )
: U/MOD
DUP 0= IF DROP DROP DROP 11 NODE-ERROR ! THEN (UD) !
(NB) 0 DO
DUP 0< >R 2* OVER 0< IF 1+ THEN SWAP 2* SWAP
R> IF (UD) @ - SWAP 1+ SWAP
ELSE DUP (UD) @ U< 0= IF (UD) @ - SWAP 1+ SWAP THEN THEN
LOOP SWAP ;
+111
View File
@@ -0,0 +1,111 @@
Block 8000
( hera.4th -- Hera: the node that has the others born and )
( manages them. docs/v4.0.0/MESH.md sections 9 and 10. )
( She asks whoever holds the fabric for a node, wires it, )
( and sends it its capsules through the port that joins )
( them. The unit rule is here and nowhere else: four outer )
( nodes round a centre, an outer node wired only inside its )
( unit. )
( Text for another node is built in PAD. )
VARIABLE (T#)
: (T0) ( -- ) 0 (T#) ! ;
: (TC) ( c -- ) PAD (T#) @ + C! 1 (T#) +! ;
: (TS) ( baddr u -- )
DUP IF 0 DO DUP I + C@ (TC) LOOP DROP ELSE DROP DROP THEN ;
: (TN) ( n -- ) 0 <# #S #> (TS) 32 (TC) ;
: (T) ( -- baddr u ) PAD (T#) @ ;
Block 8001
( The node being born: its place in the fabric, the number )
( it is to have, and the port of this node that leads to it. )
VARIABLE (KID) VARIABLE (KID#) VARIABLE (KIDP)
: (FAIL) ( -- )
." BIRTH: node " (KID#) @ . ." did not do as it was told" CR
-1 NODE-ERROR ! ;
: (TOLD) ( how -- ) 1 - IF (FAIL) THEN ;
: (TELL) ( baddr u -- ) (KID#) @ SEND (KID#) @ AWAIT (TOLD) ;
( the nucleus, a capsule of F18 code, cell by cell to its port )
: (NUCLEUS) ( -- )
S" v4:nucleus-64.f18" CAPSULE-OPEN 0= IF (FAIL) THEN
BEGIN CAPSULE-CELL WHILE (KIDP) @ PORT! REPEAT DROP ;
( a capsule of FORTH blocks, a line at a time )
: (LINES) ( baddr u -- ) CAPSULE-OPEN 0= IF (FAIL) THEN
BEGIN PAD CAPSULE-LINE DUP 0< 0= WHILE PAD SWAP (TELL) REPEAT
DROP ;
Block 8002
( The nodes this one has had born: for each its number and )
( its place in the fabric. Sixteen at most. )
CREATE (KIDS) 32 ALLOT VARIABLE (KIDS#) 0 (KIDS#) !
: (KID@) ( i -- addr ) 2 * (KIDS) + ;
: (NOTE) ( number place -- )
(KIDS#) @ 16 < IF
(KIDS#) @ (KID@) SWAP OVER 1+ ! ! 1 (KIDS#) +!
ELSE DROP DROP THEN ;
( which of them has that number: its place in the list, or -1 )
: (WHICH) ( number -- i | -1 )
-1 SWAP (KIDS#) @ DUP IF 0 DO
DUP I (KID@) @ = IF SWAP DROP I SWAP THEN
LOOP ELSE DROP THEN DROP ;
Block 8003
( who it is, where its printing goes, and that everything )
( not told of goes by its port 2, where this node is )
: (WHO) ( -- )
(T0) (KID#) @ (TN) S" (ME) ! " (TS)
(CONSOLE) @ (TN) S" (CONSOLE) ! 2 DEFAULT-ROUTE " (TS)
(ME) @ (TN) S" 2 NEIGHBOUR" (TS)
(T) 0 (KIDP) @ SEND-ON (KID#) @ AWAIT (TOLD) ;
( number port -- place A NODE IS BORN on that port of )
( this one: empty, then the nucleus, then FORTH-79. )
: BIRTH ( number port -- place )
(KIDP) ! (KID#) !
NODE-BORN DUP 0< IF (FAIL) THEN (KID) !
NODE-ME (KIDP) @ (KID) @ 2 NODE-WIRE 0= IF (FAIL) THEN
(NUCLEUS)
(KID#) @ (KIDP) @ ROUTE (KID#) @ (KIDP) @ NEIGHBOUR (WHO)
S" v4:forth79.4th" (LINES)
Block 8004
S" (SEAL)" (TELL)
(KID) @ (KID#) @ NODE-PARITY
(KID#) @ (KID) @ (NOTE)
(KID) @ ;
( Two outer nodes are joined: port 3 of X to port 4 of Y, )
( and each is told the other is there. )
VARIABLE (XP) VARIABLE (XN) VARIABLE (YP) VARIABLE (YN)
: (X) ( place number -- ) (XN) ! (XP) ! ;
: (Y) ( place number -- ) (YN) ! (YP) ! ;
: (SAY) ( them port me -- ) (KID#) !
(T0) OVER (TN) DUP (TN) S" ROUTE " (TS)
SWAP (TN) (TN) S" NEIGHBOUR" (TS) (T) (TELL) ;
: (JOIN) ( -- )
(XP) @ 3 (YP) @ 4 NODE-WIRE 0= IF (FAIL) THEN
(YN) @ 3 (XN) @ (SAY) (XN) @ 4 (YN) @ (SAY) ;
Block 8005
( n -- A UNIT: four outer nodes, n+1 to n+4, on ports 2 )
( to 5 of this one, and joined in a square: 1-2, 2-4, 4-3, )
( 3-1. The corners across from each other are not wired: )
( what one sends the other goes by this node. )
VARIABLE (U)
VARIABLE (P1) VARIABLE (P2) VARIABLE (P3) VARIABLE (P4)
: (N) ( k -- number ) (U) @ + ;
: UNIT ( n -- ) (U) !
1 (N) 2 BIRTH (P1) ! 2 (N) 3 BIRTH (P2) !
3 (N) 4 BIRTH (P3) ! 4 (N) 5 BIRTH (P4) !
(P1) @ 1 (N) (X) (P2) @ 2 (N) (Y) (JOIN)
(P2) @ 2 (N) (X) (P4) @ 4 (N) (Y) (JOIN)
(P4) @ 4 (N) (X) (P3) @ 3 (N) (Y) (JOIN)
(P3) @ 3 (N) (X) (P1) @ 1 (N) (Y) (JOIN) ;
Block 8006
( n -- KILL: node n is removed, whatever it was doing. )
( This node forgets the way to it, and every other node it )
( has had born is told that n is gone: each forgets its way )
( to n, and one that is waiting for n's answer stops. )
( docs/v4.0.0/MESH.md 7b.5. As v3's KILL, by number. )
: (UNLIST) ( i -- )
(KIDS#) @ 1- DUP (KIDS#) ! (KID@) DUP @ SWAP 1+ @
ROT (KID@) SWAP OVER 1+ ! ! ;
: KILL ( n -- )
DUP (WHICH) DUP 0< IF
DROP DROP ." KILL: no such node" CR -1 NODE-ERROR ! THEN
DUP (KID@) 1+ @ NODE-KILL (UNLIST)
DUP NO-ROUTE
(KIDS#) @ DUP IF 0 DO DUP I (KID@) @ GONE LOOP ELSE DROP THEN
DROP ;
+133
View File
@@ -0,0 +1,133 @@
\ dir.f18 -- the ROM's directives, and the end of the system's source.
\
\ What the prebuilt nucleus's mkimage.c (gone) and text.c's header did in C
\ is said in the source with
\ these (MACHINE.md, the ROM's language). Each is a machine notion -- an
\ address, a cell, a value -- and none is FORTH.
\ constant NAME VALUE NAME is the number VALUE
\ set NAME VALUE an assembler variable: may be set again
\ #, VALUE one cell of data at the next word address
\ ", TOKEN TOKEN, whatever its characters, as a counted string
\ store ADDR VALUE ADDR := VALUE, anywhere in RAM
\ start NAME the end: every branch must have its target; the
\ tables the ROM used are cleared; then NAME runs
\ A VALUE is a number, a constant, a set variable, CONST+N, here (the next
\ word address) or &NAME of a word already defined.
\ ( -- v 1 | 0 0 ) the token as a VALUE; "not a value" if it is none
: (VALUE)
(NUMBER) if NN
-if NUMOK drop drop ERR-BIG (FAIL) 0 0 ;
NUMOK: drop 1 ;
NN: drop drop
&(RESERVED) (WALK) 8 xor if HR drop
0 (CHAR@) 38 xor if AMPV drop
(FIND) if NOSYM
dup 2 + a! @ 2 xor if CV drop
dup 2 + a! @ 4 xor if CV drop
drop jump BAD
CV: drop 3 + a! @ 1 ;
NOSYM: drop
(CONST+N) if BAD0 ;
BAD0: drop drop
BAD: ERR-VALUE (FAIL) 0 0 ;
HR: drop (LABEL) 1 ;
AMPV: drop (TOKN) a! @ -1 + if ONEV drop
(TOK-SAVE) 1 (MLEN) a! @ -1 + (TOK-SUB)
(FIND) if BADA
dup 2 + a! @ 1 xor if OKA drop drop jump BADA0
OKA: drop 3 + a! @ 1 ;
BADA: drop
BADA0: ERR-AMP (FAIL) 0 0 ;
ONEV: drop jump BAD
\ ( -- v 1 | 0 0 ) the next token as a VALUE
: (NEXT-VALUE)
(NEXT-TOKEN) if MISS drop jump (VALUE)
MISS: drop ERR-MISSING (FAIL) 0 0 ;
: (H-CONSTANT)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-TOKEN) if MISS drop
(TOK) (TSAVE) 16 (COPY)
(NEXT-TOKEN) if MISS drop
(NUMBER) if NAN
-if NUM drop drop ERR-BIG jump (FAIL)
NUM: drop (NAME-BACK) 2 jump (DEFINE)
NAN: drop drop ERR-VALUE jump (FAIL)
MISS: drop ERR-MISSING jump (FAIL)
: (H-SET)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-TOKEN) if MISS drop
(TOK) (TSAVE) 16 (COPY)
(NEXT-VALUE) if BADV drop
(NAME-BACK) 4 jump (DEFINE)
BADV: drop drop ;
MISS: drop ERR-MISSING jump (FAIL)
\ here alone is not something to assemble: only a VALUE
: (H-HERE) ERR-TARGET jump (FAIL)
: (H-CELL)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-VALUE) if BADV drop
(LABEL) drop jump (EMIT)
BADV: drop drop ;
: (H-STRING)
(IN-MACRO?) if OK drop ;
OK: drop
(RAW-TOKEN) if MISS drop
(LABEL) drop
(TOKN) a! @ 4 + 2/ 2/ (T1) a! ! 0 (T2) a! !
L: (T2) a! @ (T1) a! @ xor if D drop
(T2) a! @ (TOK) + a! @ (EMIT)
(T2) a! @ 1 + ! jump L
D: drop ;
MISS: drop ERR-MISSING jump (FAIL)
: (H-STORE)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-VALUE) if BADV drop (T1) a! !
(NEXT-VALUE) if BADV drop
(T1) a! @ b! !b ;
BADV: drop drop ;
\ ( -- ) clear the tables the ROM uses only while it assembles: the symbol
\ table in dictionary space, the branches, labels and names in the block
\ window, the saved token and macro body in the text input buffer
: (CLEAR)
DICT-W a! DICT-END DICT-W inv 1 + + -1 + FOR 0 !+ NEXT
BUF0 a! 1023 FOR 0 !+ NEXT
TIB-W a! 259 FOR 0 !+ NEXT
0 (RECN) a! ! 0 (POOLN) a! ! 0 (NREF) a! ! 0 (NLAB) a! !
0 (WNP) a! ! 0 (NFOR) a! ! 0 (RDEPTH) a! ! ;
\ start NAME: the system's source has ended
: (H-START)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-TOKEN) if MISS drop
(TOK) (TSAVE) 16 (COPY)
(END-WORD)
(FAILED) a! @ if F0 drop ;
F0: drop
(NREF) a! @ if NOREF drop
ERR-UNDEFINED (FAIL) (REFS) 1 + a! @ (ERRLINE) a! ! ;
NOREF: drop
(LABEL) drop
(NAME-BACK)
(FIND) if NOTW
dup 2 + a! @ 1 xor if ISW drop drop jump NOTW0
ISW: drop 3 + a! @ (T1) a! !
(CLEAR)
0 DSTACK-REG a! ! 0 RSTACK-REG a! !
(T1) a! @ push ;
NOTW: drop
NOTW0: ERR-START jump (FAIL)
MISS: drop ERR-MISSING jump (FAIL)
+111
View File
@@ -0,0 +1,111 @@
\ in.f18 -- the ROM's input: characters from the console, and tokens.
\
\ The text the ROM assembles arrives at the console's receive registers,
\ a character at a time. The end of it is EOT (4), which the loader sends
\ after the last blob. A token is what v4/src/text.c's next_token makes
\ of the same text: blanks are space, tab, CR and LF; a token is at most 63
\ characters; `\` as a whole token skips to the end of the line, and `(` as a
\ whole token to the next `)`.
\
\ State, in the ROM's area of the memory map (MACHINE.md 2.1):
\ (TOK) the token, as a counted string: its count byte, then its
\ characters, four to a cell, low byte first, zero-padded --
\ the form `",` lays down and (FIND) compares; 16 cells
\ (TOKN) its length
\ (PEEK) a character put back, plus one; 0: none
\ (LINE) how many new lines have been read
\ (EOF) non-zero once EOT has been read
\ (FAILED) 0, or the code of the error that stopped the ROM
\ (ERRLINE) (LINE) when it failed
\ (RAW) 1 while a token is read raw: ( and \ are then names
\ Every routine here uses A.
\ ( -- c ) wait for a character, then take it
: (KEY)
W: CONSOLE-STATUS a! @ if Z drop CONSOLE-RX a! @ ;
Z: drop jump W
\ ( -- c ) the character put back, if there is one; else the next
: (GETC)
(PEEK) a! @ if NONE 0 ! -1 + ;
NONE: drop jump (KEY)
\ ( c -- ) put a character back, to be the next one read
: (BACK) 1 + (PEEK) a! ! ;
\ ( -- ) one more new line
: (LF+) (LINE) a! @ 1 + ! ;
\ ( code -- ) stop with an error, noting the line
: (FAIL) (FAILED) a! ! (LINE) a! @ (ERRLINE) a! ! ;
\ ( c -- ) one more character of the token: byte (TOKN)+1 of (TOK), into
\ a cell whose byte there is still zero
: (PUT)
(TOKN) a! @ 1 +
dup 2/ 2/ (TOK) + push
3 and
S: if SD push 2* 2* 2* 2* 2* 2* 2* 2* pop -1 + jump S
SD: drop pop a! @ xor !
(TOKN) a! @ 1 + ! ;
\ ( i -- c ) character i of the token, from 0
: (CHAR@)
1 + dup 2/ 2/ (TOK) + a! @
push 3 and
S: if SD -1 + pop 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ push jump S
SD: drop pop 255 and ;
\ ( -- len ) the next token into (TOK), its length into (TOKN). 0: the end,
\ or an error, which is in (FAILED).
: (TOKEN)
(EOF) a! @ if GO drop 0 ;
GO: drop
SKIP: (GETC)
dup 4 xor if END
drop dup 10 xor if NL
drop dup 32 xor if SP
drop dup 9 xor if SP
drop dup 13 xor if SP
drop 0 (TOKN) a! !
(TOK) a! 15 FOR 0 !+ NEXT
READ: (TOKN) a! @ 63 xor if LONG
drop (PUT) (GETC)
dup 4 xor if TEND
drop dup 10 xor if TEND
drop dup 32 xor if TEND
drop dup 9 xor if TEND
drop dup 13 xor if TEND
drop jump READ
TEND: drop (BACK)
(TOKN) a! @ (TOK) a! @ xor !
(RAW) a! @ if COOKED drop (TOKN) a! @ ;
COOKED: drop
(TOKN) a! @ 1 xor if ONE
drop (TOKN) a! @ ;
ONE: drop 0 (CHAR@)
dup 92 xor if BSL
drop dup 40 xor if PAREN
drop drop 1 ;
BSL: drop drop
B1: (GETC)
dup 10 xor if BEND
drop dup 4 xor if BEND
drop drop jump B1
BEND: drop (BACK) jump SKIP
PAREN: drop drop
P1: (GETC)
dup 41 xor if PCLOSE
drop dup 10 xor if PNL
drop dup 4 xor if PEOF
drop drop jump P1
PNL: drop drop (LF+) jump P1
PCLOSE: drop drop jump SKIP
PEOF: drop drop ERR-COMMENT (FAIL) 0 ;
END: drop drop 1 (EOF) a! ! 0 ;
NL: drop drop (LF+) jump SKIP
SP: drop drop jump SKIP
LONG: drop drop ERR-TOO-LONG (FAIL) 0 ;
\ ( -- len ) the next token, raw: ( and \ are names, not comments
: (RAW-TOKEN) 1 (RAW) a! ! (TOKEN) 0 (RAW) a! ! ;
+47
View File
@@ -0,0 +1,47 @@
\ main.f18 -- the ROM's entry table.
\
\ docs/v4.0.0/MACHINE.md 2.1. The ROM is shared code: a payload calls its
\ routines through this table and never to an address inside the ROM, so a
\ rebuilt ROM breaks no payload. It is at the ROM's base, one jump a word,
\ in a fixed order that only ever grows at its end. Entry i is at the ROM's
\ base plus i. DATASHEET-F18.md lists each routine's stack effect.
: (ENTRIES)
jump (KEY) \ 0 ( -- c )
jump (TOKEN) \ 1 ( -- len )
jump (NUMBER) \ 2 ( -- n flag )
jump (FIND) \ 3 ( -- rec | 0 )
jump (DEFINE) \ 4 ( value kind -- )
jump (OPCODE) \ 5 ( -- op | -1 )
jump (OP) \ 6 ( op -- )
jump (LIT) \ 7 ( v -- )
jump (BRANCH) \ 8 ( op target -- )
jump (BRANCH>) \ 9 ( op -- ref )
jump (RESOLVE) \ 10 ( ref target -- )
jump (LABEL) \ 11 ( -- addr )
jump (ROM) \ 12 the ROM itself: where the machine starts
\ ( -- ) the state the ROM begins from: code goes to ORIGIN, nothing read,
\ nothing defined
: (INIT)
(CLEAR)
ORIGIN (HERE) a! ! 0 (CUR) a! ! 0 (SLOT) a! ! 0 (NLIT) a! !
0 (FAILED) a! ! 0 (ERRLINE) a! ! 0 (LINE) a! ! 0 (EOF) a! !
0 (PEEK) a! ! 0 (RAW) a! ! ;
\ the ROM: assemble the system's source from the console until its start
\ runs it; on an error, stop at (ROM-FAILED) with the error's code in
\ (FAILED) and its line in (ERRLINE), for the loader to report
: (ROM)
(INIT)
L: (NEXT-TOKEN) if END drop
(ONE)
(FAILED) a! @ if L0 drop jump (ROM-FAILED)
L0: drop jump L
END: drop
(FAILED) a! @ if NS drop jump (ROM-FAILED)
NS: drop ERR-NO-START (FAIL) jump (ROM-FAILED)
: (ROM-FAILED)
H: jump H
+67
View File
@@ -0,0 +1,67 @@
\ num.f18 -- the ROM reads numbers.
\
\ (NUMBER) ( -- n flag ) looks at the token (TOKEN) read, as v4/src/text.c's
\ number_of does: decimal with an optional leading `-`, or hexadecimal after
\ `$` (a-f in either case). flag 1: the whole token is a number, n its
\ value; 0: it is not one; -1: it is one, and does not fit a cell, read as
\ signed or as unsigned. A token that has a character that is not a digit
\ is not a number, even when its digits so far did not fit.
\
\ State, in the ROM's area (MACHINE.md 2.1): (NBASE) 10 or 16, (NNEG) 1 after
\ a `-`, (NI) the next character, (NU) the value so far, unsigned, (NBIG) 1
\ once it has not fitted. Width constants from the map: MSB, the cell's top
\ bit; DEC-LIMIT, the largest unsigned cell over 10; DEC-NLAST, minus one
\ more than its remainder; HEX-HIGH, the top four bits. Uses A. The
\ token's characters are read with in.f18's (CHAR@).
\ ( c -- d | -1 ) the digit c is in the base, or -1
: (DIGIT)
dup -48 + -if D1 drop drop -1 ; \ below '0'
D1: dup -10 + -if D2 drop push drop pop ; \ '0' .. '9'
D2: drop drop
(NBASE) a! @ 16 xor if HEXL drop drop -1 ;
HEXL: drop
dup -97 + -if LOW drop
dup -65 + -if UP drop drop -1 ; \ below 'A'
UP: dup -6 + -if BAD drop push drop pop 10 + ;
LOW: dup -6 + -if BAD drop push drop pop 10 + ;
BAD: drop drop drop -1 ;
\ ( d -- ) (NU) := (NU) * base + d, or (NBIG) := 1 if that does not fit
: (ACC)
(NU) a! @
(NBASE) a! @ 16 xor if X16 drop
dup -if DPOS drop jump DBIG \ the top bit is set
DPOS: drop
dup inv 1 + DEC-LIMIT + -if DLE drop jump DBIG
DLE: if DEQ drop jump MUL10
DEQ: drop over DEC-NLAST + -if DBIG3 drop jump MUL10
DBIG3: drop
DBIG: 1 (NBIG) a! ! drop drop ;
MUL10: 2* dup 2* 2* + + (NU) a! ! ;
X16: drop
dup HEX-HIGH and if HOK drop jump DBIG
HOK: drop 2* 2* 2* 2* + (NU) a! ! ;
\ ( -- n flag )
: (NUMBER)
0 (NBIG) a! ! 0 (NNEG) a! ! 0 (NU) a! ! 0 (NI) a! ! 10 (NBASE) a! !
0 (CHAR@)
dup 36 xor if HEX drop
dup 45 xor if NEG drop drop jump DIGITS
HEX: drop drop 16 (NBASE) a! ! 1 (NI) a! ! jump DIGITS
NEG: drop drop 1 (NNEG) a! ! 1 (NI) a! !
DIGITS: (NI) a! @ (TOKN) a! @ xor if NONE drop
L: (NI) a! @ (CHAR@) (DIGIT)
-if OK drop 0 0 ;
OK: (ACC)
(NI) a! @ 1 + dup ! (TOKN) a! @ xor if DONE drop jump L
DONE: drop
(NBIG) a! @ if FITS drop 0 -1 ;
FITS: drop (NNEG) a! @ if POS drop
(NU) a! @ -if NEGOK
MSB xor if EXACT drop 0 -1 ;
EXACT: drop MSB 1 ;
NEGOK: inv 1 + 1 ;
POS: drop (NU) a! @ 1 ;
NONE: drop 0 0 ;
+140
View File
@@ -0,0 +1,140 @@
\ pack.f18 -- the ROM's slot packer: how code is laid down.
\
\ The rules are v4/src/asm.c's, with text.c's branch placement
\ (DATASHEET-F18.md section 6):
\ - opcodes fill slots 0 .. 5 left to right; a full word is written out and
\ a new one begun, unused slots padded with nop
\ - a literal is @p in a slot and its value in the word after the
\ instruction word, several in the order they were given
\ - ; and ex end the word: nothing after them executes
\ - a branch ends the word, the bits to its right being its address; it is
\ put only in a slot that reaches the whole address space (ADDR-TOP),
\ otherwise in a new word; a target it cannot reach is "does not fit"
\ This is the code generator of whatever language is built on the machine
\ (MACHINE.md 2.1). State, in the ROM's area: (HERE) the next word address,
\ (CUR) the word being built, (SLOT) its next slot, (LITS) the (NLIT)
\ literals it owes. (PI) (RS) (RN) are working cells. Uses A and B.
\ ( op -- f ) 1 if op is a branch: jump call next if -if
: (BRANCH-OP?)
dup -2 + if Y drop dup -3 + if Y drop dup -5 + if Y drop
dup -6 + if Y drop dup -7 + if Y drop drop 0 ;
Y: drop drop 1 ;
\ ( s -- m ) the address bits a branch in slot s replaces
: (MASK)
if S0 -1 + if S1 -1 + if S2 -1 + if S3 -1 + if S4 drop 3 ;
S0: drop $7FFFFFF ;
S1: drop $3FFFFF ;
S2: drop $1FFFF ;
S3: drop $FFF ;
S4: drop $7F ;
\ ( w s -- op ) the opcode in slot s of the instruction word w
: (SLOT-OP)
dup 2* 2* + inv 1 + 27 +
S: if SD push 2/ pop -1 + jump S
SD: drop 31 and ;
\ ( op -- ) op into the next slot
: (PUT-OP)
(SLOT) a! @ dup 2* 2* + inv 1 + 27 +
S: if SD push 2* pop -1 + jump S
SD: drop (CUR) a! @ xor !
(SLOT) a! @ 1 + ! ;
\ ( v -- ) v at (HERE), which then moves on; past RAM, "does not fit"
: (EMIT)
(HERE) a! @ dup RAM-WORDS inv 1 + + -if FULL
drop b! !b (HERE) a! @ 1 + ! ;
FULL: drop drop drop ERR-FIT jump (FAIL)
\ ( -- ) write out the word being built, padded with nop, then its literals
: (FLUSH)
(SLOT) a! @ if NONE drop
P: (SLOT) a! @ 6 xor if PADDED drop 28 (PUT-OP) jump P
PADDED: drop
(CUR) a! @ (EMIT)
0 (PI) a! !
L: (PI) a! @ (NLIT) a! @ xor if LD drop
(PI) a! @ (LITS) + a! @ (EMIT)
(PI) a! @ 1 + ! jump L
LD: drop
0 (CUR) a! ! 0 (SLOT) a! ! 0 (NLIT) a! ! ;
NONE: drop ;
\ ( op -- ) an opcode that is neither a branch nor @p
: (OP)
dup -32 + -if BAD
drop dup 8 xor if BAD
drop dup (BRANCH-OP?) if GOOD
BAD: drop drop ERR-OPCODE jump (FAIL)
GOOD: drop
dup (PUT-OP)
if CLOSE
-1 + if CLOSE
drop (SLOT) a! @ 6 xor if CLOSE drop ;
CLOSE: drop jump (FLUSH)
\ ( v -- ) @p and its value
: (LIT)
(NLIT) a! @ (LITS) + b! !b
(NLIT) a! @ 1 + !
8 (PUT-OP)
(SLOT) a! @ 6 xor if FL drop ;
FL: drop jump (FLUSH)
\ ( -- ) text.c's place_branch: begin a new word unless the next slot
\ reaches the whole address space
: (PLACE)
(SLOT) a! @ if NONE
dup -4 + -if NEW drop
(MASK) ADDR-TOP inv 1 + + -if KEEP drop jump (FLUSH)
KEEP: drop ;
NEW: drop drop jump (FLUSH)
NONE: drop ;
\ ( -- addr ) end the word being built; the next word address
: (LABEL) (FLUSH) (HERE) a! @ ;
\ ( op -- ref ) a branch whose target comes later: ref is the word it is in
: (BRANCH>)
dup (BRANCH-OP?) if BAD drop
(PLACE)
(SLOT) a! @ -4 + -if FL drop jump GO
FL: drop (FLUSH)
GO: (HERE) a! @ push
(PUT-OP)
6 (SLOT) a! !
(FLUSH) pop ;
BAD: drop drop ERR-OPCODE (FAIL) 0 ;
\ ( ref target -- ) give the branch in the word at ref its target. The
\ branch is the first branch opcode in the word; the literals before it are
\ what P has passed when it executes. A word with no branch in slots
\ 0 .. 3 is not a ref, and is refused.
: (RESOLVE)
(FAILED) a! @ if GO drop drop drop ;
GO: drop
0 (RS) a! ! 0 (RN) a! !
L: (RS) a! @ -4 + -if BADREF drop
over a! @ (RS) a! @ (SLOT-OP)
dup (BRANCH-OP?) if NB drop drop jump FOUND
NB: drop 8 xor if ISLIT drop jump NXT
ISLIT: drop (RN) a! @ 1 + !
NXT: (RS) a! @ 1 + ! jump L
BADREF: jump (NOB)
FOUND:
over 1 + (RN) a! @ +
over xor (RS) a! @ (MASK) inv and
if OKR drop drop drop ERR-FIT jump (FAIL)
OKR: drop
(RS) a! @ (MASK) and
over a! @ (RS) a! @ (MASK) inv and
xor over a! ! drop ;
\ (a word with no branch in slots 0 .. 3 is not a ref: refused)
: (NOB) drop drop drop ERR-FIT jump (FAIL)
\ ( op target -- ) a branch to a known target
: (BRANCH) push (BRANCH>) pop jump (RESOLVE)
+158
View File
@@ -0,0 +1,158 @@
\ sym.f18 -- the ROM's symbol table.
\
\ A name the ROM assembles is given a kind and a value: 1 a word (its
\ address), 2 a constant, 3 a macro, 4 a set variable. Kind 0 is a name
\ only branched to so far: a placeholder that the forward branches to it
\ wait on (word.f18), which (DEFINE) fills in. The rules are
\ v4/src/text.c's define: a name may not be an opcode, a reserved word, a
\ label (NAME:), a number or start with &; nothing is defined twice, except
\ that a set variable may be set again and a placeholder be defined.
\
\ The table is used only while the ROM assembles, and lives in dictionary
\ space: 256 hash heads at (SYMH); records of four cells -- link, name,
\ kind, value -- growing up from SYMREC; names and macro bodies, growing
\ down from POOLTOP. When the two would meet, "too many names". (RECN) and
\ (POOLN) count the cells used, so an empty table is all zeroes. Names are
\ counted strings, the form the token is held in, compared a cell at a time.
\ (REC) (CNT) (PTR) (I) (WI) are working cells. Every routine uses A; some B.
\ ( p q -- f ) 1 if the counted strings at p and q are the same
: (SAME2?)
(I) a! ! (PTR) a! !
(PTR) a! @ a! @ 255 and 4 + 2/ 2/
L: (PTR) a! @ b! @b (I) a! @ a! @ xor if EQ drop drop 0 ;
EQ: drop (PTR) a! @ 1 + ! (I) a! @ 1 + !
-1 + if DONE jump L
DONE: drop 1 ;
\ ( addr -- f ) 1 if the counted string at addr is the token
: (SAME?) (TOK) jump (SAME2?)
\ ( table -- i | -1 ) which counted string of a table the token is; the
\ table ends with a zero cell
: (WALK)
0 (WI) a! !
L: dup a! @ if END
drop dup (SAME?) if NO
drop drop (WI) a! @ ;
NO: drop dup a! @ 255 and 4 + 2/ 2/ +
(WI) a! @ 1 + ! jump L
END: drop drop -1 ;
\ the opcodes' names, in the order of their numbers
: (MNEMONICS)
", ; ", ex ", jump ", call ", unext ", next ", if ", -if
", @p ", @+ ", @b ", @ ", !p ", !+ ", !b ", !
", +* ", 2* ", 2/ ", inv ", + ", and ", xor ", drop
", dup ", pop ", over ", a ", nop ", push ", b! ", a!
#, 0
\ the ROM's reserved words: its notation and its directives
: (RESERVED)
", : ", macro ", endmacro ", FOR ", NEXT ", UNEXT
", constant ", set ", here ", #, ", ", ", store
", start
#, 0
\ ( -- op | -1 ) which opcode the token names
: (OPCODE) &(MNEMONICS) jump (WALK)
\ ( -- f ) 1 if the token is a reserved word
: (RESERVED?) &(RESERVED) (WALK) -if Y drop 0 ;
Y: drop 1 ;
\ ( p -- h ) the hash, 0 .. 255, of the counted string at p, from its
\ first cell, and its second if the name runs into it (4 characters or more:
\ the cell after a shorter name is not its own)
: (HASH-AT)
a! @+ dup 255 and -4 + -if TWO drop jump MIX
TWO: drop @ xor
MIX: dup 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ +
dup 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ +
255 and ;
\ ( p -- rec | 0 ) the newest record whose name is the counted string at p,
\ placeholders included
: (FIND-AT)
dup (T3) a! ! (HASH-AT) (SYMH) + a! @
L: if NONE
dup (REC) a! ! 1 + a! @ (T3) a! @ (SAME2?) if NO
drop (REC) a! @ ;
NO: drop (REC) a! @ a! @ jump L
NONE: ;
\ ( -- rec | 0 ) the token's record, placeholders included
: (FIND0) (TOK) jump (FIND-AT)
\ ( -- rec | 0 ) the token's record, if it has been defined
: (FIND)
(FIND0) if NONE
dup 2 + a! @ if PH drop ;
PH: drop drop 0 ;
NONE: ;
\ ( n -- addr | 0 ) n cells of the pool, below what it holds; 0 if they
\ would meet the records ("too many names")
: (ALLOC)
dup (CNT) a! !
POOLTOP (POOLN) a! @ inv 1 + + (CNT) a! @ inv 1 + +
dup SYMREC (RECN) a! @ + 4 + inv 1 + +
-if ROOM drop drop drop ERR-NAMES (FAIL) 0 ;
ROOM: drop push drop
(POOLN) a! @ (CNT) a! @ + (POOLN) a! !
pop ;
\ ( from to n -- ) copy n cells, n at least 1
: (COPY)
(CN) a! ! (CTO) a! ! (CFROM) a! !
L: (CN) a! @ if D drop
(CFROM) a! @ a! @ (CTO) a! @ b! !b
(CFROM) a! @ 1 + ! (CTO) a! @ 1 + ! (CN) a! @ -1 + ! jump L
D: drop ;
\ ( value kind p -- rec | 0 ) a new record for the counted string at p,
\ the name copied into the pool; 0 if there is no room
: (NEW-REC)
dup (T3) a! !
a! @ 255 and 4 + 2/ 2/ (ALLOC)
if FULL
dup (T4) a! !
push (T3) a! @ pop (T3) a! @ a! @ 255 and 4 + 2/ 2/ (COPY)
SYMREC (RECN) a! @ + (REC) a! !
(T4) a! @ (REC) a! @ 1 + a! !
(REC) a! @ 2 + a! !
(REC) a! @ 3 + a! !
(T4) a! @ (HASH-AT) (SYMH) + dup a! @ (REC) a! @ a! !
(REC) a! @ over a! ! drop
(RECN) a! @ 4 + !
(REC) a! @ ;
FULL: drop drop drop 0 ;
\ ( -- f ) 1 if the token cannot be a name
: (BADNAME?)
(OPCODE) -if BAD
drop (RESERVED?) if NOTRES drop 1 ;
NOTRES: drop (NUMBER) push drop pop if NOTNUM drop 1 ;
NOTNUM: drop 0 (CHAR@) 38 xor if AMP
drop (TOKN) a! @ -1 + if ONE
(CHAR@) 58 xor if COLON drop 0 ;
COLON: drop 1 ;
ONE: drop 0 ;
AMP: drop 1 ;
BAD: drop 1 ;
\ ( value kind -- ) give the token a kind and a value. A placeholder is
\ filled in, and the branches waiting on it are told (word.f18, (DEFINED)).
: (DEFINE)
(BADNAME?) if OKNAME drop drop drop ERR-BAD-NAME jump (FAIL)
OKNAME: drop
(FIND0) if NEW
dup 2 + a! @ if FILL drop
over 4 xor if K4 drop drop drop drop ERR-DEFINED jump (FAIL)
K4: drop 2 + a! @ 4 xor if BOTH drop drop drop ERR-DEFINED jump (FAIL)
BOTH: drop drop (REC) a! @ 3 + a! ! ;
FILL: drop dup (REC) a! !
2 + a! !
(REC) a! @ 3 + a! !
(REC) a! @ jump (DEFINED)
NEW: drop (TOK) (NEW-REC) drop ;
+390
View File
@@ -0,0 +1,390 @@
\ word.f18 -- the ROM assembles words: names, labels, branches, macros, FOR.
\
\ The rules are v4/src/text.c's one_token, end_word and branch:
\ : NAME a word begins at the next instruction word
\ NAME: a label of the word being assembled
\ jump X call X if X -if X next X
\ a branch to X: a label of this word, before or after the
\ branch, if it has one of that name; otherwise a word
\ X a call to the word X, defined already or later
\ &X the address of the word X, already defined, as a literal
\ 123 $FF CONST CONST+N a literal
\ a macro its tokens, read in its place
\ FOR ... NEXT FOR ... UNEXT
\ A branch to a label not yet seen waits, local to its word, in the table
\ of branches (REFS); when the word ends, a name that is not a label of it
\ must be a word, and the branch then waits on that name's symbol -- a
\ placeholder if it has none yet (sym.f18) -- until it is defined.
\
\ State, in the ROM's area: (NREF) (NLAB) (WNP) (NFOR) (FORS) (RDEPTH)
\ (RPTRS). Tables, used only while assembling: (REFS) four cells an entry
\ -- the word, the line, a symbol record (or, while local, a name), 1 if
\ local; (LABELS) a name and an address; (WNAMES) the word's names. Uses
\ A and B, and the working cells (T1) .. (T6), (MLEN).
\ ---- reading: the console, or a macro being expanded ----------------------
\ ( -- len ) the next token, from the innermost macro being expanded, or
\ from the console. A macro's body is its tokens as counted strings, then
\ a zero cell.
: (NEXT-TOKEN)
L: (RDEPTH) a! @ if SRC
-1 + (RPTRS) + dup (T1) a! ! a! @
dup a! @ if EOM
255 and dup (TOKN) a! !
4 + 2/ 2/ dup (T2) a! !
push (TOK) pop (COPY)
(T1) a! @ a! @ (T2) a! @ + (T1) a! @ a! !
(TOKN) a! @ ;
EOM: drop drop (RDEPTH) a! @ -1 + ! jump L
SRC: drop jump (TOKEN)
\ ---- the token, taken apart ------------------------------------------------
\ ( -- ) save the token's characters, a character to a cell, in (MTEMP)
: (TOK-SAVE)
(TOKN) a! @ (MLEN) a! ! 0 (T5) a! !
L: (T5) a! @ (MLEN) a! @ xor if D drop
(T5) a! @ (CHAR@) (T5) a! @ (MTEMP) + b! !b
(T5) a! @ 1 + ! jump L
D: drop ;
\ ( start len -- ) the token becomes characters start .. start+len-1 of
\ the one saved by (TOK-SAVE)
: (TOK-SUB)
(T6) a! ! (T5) a! !
(TOK) a! 15 FOR 0 !+ NEXT
0 (TOKN) a! !
L: (T6) a! @ if D drop
(T5) a! @ (MTEMP) + a! @ (PUT)
(T5) a! @ 1 + ! (T6) a! @ -1 + ! jump L
D: drop (TOKN) a! @ (TOK) a! @ xor ! ;
\ ( -- f ) 1 if the token is a label's definition: NAME:
: (LABELFORM?)
(TOKN) a! @ -1 + if NO
(CHAR@) 58 xor if YES drop 0 ;
YES: drop 1 ;
NO: drop 0 ;
\ ---- the word's names: labels, and names branched to before they are seen --
\ ( -- p | 0 ) the token, copied into the word's name area
: (WNAME)
(TOKN) a! @ 4 + 2/ 2/ (T6) a! !
(WNP) a! @ (T6) a! @ + WN-SIZE inv 1 + + -1 + -if FULL drop
(WNAMES) (WNP) a! @ +
(TOK) over (T6) a! @ (COPY)
(WNP) a! @ (T6) a! @ + (WNP) a! ! ;
FULL: drop ERR-NAMES (FAIL) 0 ;
\ ( -- addr | -1 ) the address of the word's label named by the token
: (LAB-FIND)
0 (T5) a! !
L: (T5) a! @ (NLAB) a! @ xor if NONE drop
(T5) a! @ 2* (LABELS) + a! @ (SAME?) if NO
drop (T5) a! @ 2* (LABELS) + 1 + a! @ ;
NO: drop (T5) a! @ 1 + ! jump L
NONE: drop -1 ;
\ ---- the branches waiting for a target -------------------------------------
\ ( word sym local -- ) one more branch waiting
: (REF-ADD)
(NREF) a! @ REFS-MAX inv 1 + + -if FULL drop
(NREF) a! @ 2* 2* (REFS) + (T5) a! !
(T5) a! @ 3 + a! !
(T5) a! @ 2 + a! !
(T5) a! @ a! !
(LINE) a! @ (T5) a! @ 1 + a! !
(NREF) a! @ 1 + ! ;
FULL: drop drop drop drop ERR-REFS jump (FAIL)
\ ( i target -- ) the waiting branch i gets its target, and stops waiting:
\ the last entry takes its place. A branch that cannot reach is reported
\ at the line it was written on.
: (REF-RESOLVE)
(T4) a! !
2* 2* (REFS) + dup (T3) a! !
a! @ (T4) a! @ (RESOLVE)
(FAILED) a! @ if OK drop
(T3) a! @ 1 + a! @ (ERRLINE) a! ! ;
OK: drop
(NREF) a! @ -1 + dup (NREF) a! !
2* 2* (REFS) + (T3) a! @ 4 (COPY) ;
\ ( addr -- ) a label has been defined at addr: the branches in this word
\ waiting on its name, the token, get it
: (LOCAL-RESOLVE)
(T1) a! ! 0 (T2) a! !
L: (T2) a! @ (NREF) a! @ xor if DONE drop
(FAILED) a! @ if GO drop ;
GO: drop
(T2) a! @ 2* 2* (REFS) +
dup 3 + a! @ if SKIP drop
2 + a! @ (SAME?) if NX
drop (T2) a! @ (T1) a! @ (REF-RESOLVE) jump L
SKIP: drop drop jump NX1
NX: drop
NX1: (T2) a! @ 1 + ! jump L
DONE: drop ;
\ ( rec -- ) the symbol rec has been defined (sym.f18, (DEFINE)): if it is
\ a word, the branches waiting on it get its address
: (DEFINED)
dup 2 + a! @ 1 xor if W drop drop ;
W: drop (T1) a! ! 0 (T2) a! !
L: (T2) a! @ (NREF) a! @ xor if DONE drop
(FAILED) a! @ if GO drop ;
GO: drop
(T2) a! @ 2* 2* (REFS) +
dup 3 + a! @ if NL drop drop jump NX
NL: drop 2 + a! @ (T1) a! @ xor if MATCH drop jump NX
MATCH: drop (T2) a! @ (T1) a! @ 3 + a! @ (REF-RESOLVE) jump L
NX: (T2) a! @ 1 + ! jump L
DONE: drop ;
\ ( -- ) the word being assembled ends: a FOR left open is an error; the
\ branches still local to it wait on their names' symbols, unless the name
\ is a word, which they then get; its labels and names go.
: (END-WORD)
(NFOR) a! @ if F0 drop 0 (NFOR) a! ! ERR-FOR jump (FAIL)
F0: drop
0 (T1) a! !
L: (T1) a! @ (NREF) a! @ xor if DONE drop
(FAILED) a! @ if GO drop ;
GO: drop
(T1) a! @ 2* 2* (REFS) +
dup 3 + a! @ if SKIP drop
0 over 3 + a! !
dup 2 + a! @ (FIND-AT)
if MK
dup 2 + a! @ 1 xor if RES drop
over 2 + a! ! drop jump NX
RES: drop push drop (T1) a! @ pop 3 + a! @ (REF-RESOLVE) jump L
MK: drop dup 2 + a! @ push 0 0 pop (NEW-REC)
over 2 + a! ! drop jump NX
SKIP: drop drop
NX: (T1) a! @ 1 + ! jump L
DONE: drop
0 (NLAB) a! ! 0 (WNP) a! ! ;
\ ---- branches by name ------------------------------------------------------
\ ( op local -- ) a branch to the name in the token. local: written after
\ a branch mnemonic, so it may be a label of this word, before or after.
: (BRANCH-NAME)
(T6) a! !
(T6) a! @ if CHK
drop (LAB-FIND) -if TOLAB drop jump CHK1
TOLAB: jump (BRANCH)
CHK: drop
(FIND) if CHK0
dup 2 + a! @ 1 xor if NOW drop drop jump BAD
NOW: drop 3 + a! @ jump (BRANCH)
CHK0: drop
CHK1:
(FIND) if C2
2 + a! @ 1 xor if C3 drop jump BAD
C3: drop jump C4
C2: drop
C4: (OPCODE) -if BAD1 drop
(RESERVED?) if C5 drop jump BAD
C5: drop (LABELFORM?) if C6 drop jump BAD
C6: drop (NUMBER) push drop pop if C7 drop jump BAD
C7: drop
(T6) a! @ if GLOBAL drop
(BRANCH>) (WNAME) 1 jump (REF-ADD)
GLOBAL: drop
(BRANCH>) (FIND0) if NEWPH
0 jump (REF-ADD)
NEWPH: drop 0 0 (TOK) (NEW-REC) 0 jump (REF-ADD)
BAD1: drop
BAD: drop ERR-TARGET jump (FAIL)
\ ---- labels ----------------------------------------------------------------
\ ( addr -- ) a label of this word, named by the token, at addr; the
\ branches already waiting on it get it
: (LAB-ADD)
(LAB-FIND) -if DUP drop
(NLAB) a! @ -64 + -if FULL drop
(WNAME) if FAILP
(NLAB) a! @ 2* (LABELS) + a! !
dup (NLAB) a! @ 2* (LABELS) + 1 + a! !
(NLAB) a! @ 1 + !
jump (LOCAL-RESOLVE)
DUP: drop drop ERR-LABEL-DUP jump (FAIL)
FULL: drop drop ERR-LABELS jump (FAIL)
FAILP: drop drop ;
\ ( -- ) NAME: -- a label at the next instruction word
: (LABEL-DEF)
(TOK-SAVE) 0 (MLEN) a! @ -1 + (TOK-SUB)
(LABEL) jump (LAB-ADD)
\ ---- FOR ... NEXT, FOR ... UNEXT --------------------------------------------
: (H-FOR)
(NFOR) a! @ -8 + -if DEEP drop
29 (OP) (LABEL) (NFOR) a! @ (FORS) + a! !
(NFOR) a! @ 1 + ! ;
DEEP: drop ERR-FOR jump (FAIL)
: (H-NEXT)
(NFOR) a! @ if NONE
-1 + dup (NFOR) a! ! (FORS) + a! @
push 5 pop jump (BRANCH)
NONE: drop ERR-FOR jump (FAIL)
\ unext repeats the word it is in: it must still be the word the body
\ began, with a slot left, owing no literal
: (H-UNEXT)
(NFOR) a! @ if NONE
-1 + dup (NFOR) a! ! (FORS) + a! @
(HERE) a! @ xor if SAMEW drop jump BAD
SAMEW: drop
(SLOT) a! @ if BAD0
-6 + -if BAD0 drop
(NLIT) a! @ if OK drop jump BAD
OK: drop 4 jump (OP)
BAD0: drop
BAD: ERR-UNEXT jump (FAIL)
NONE: drop ERR-FOR jump (FAIL)
\ ---- macros ----------------------------------------------------------------
\ ( -- ) restore the name (TSAVE) holds into the token
: (NAME-BACK) (TSAVE) (TOK) 16 (COPY) (TOK) a! @ 255 and (TOKN) a! ! ;
\ ( -- f ) 0 if not in a macro; else "not allowed in a macro", and 1
: (IN-MACRO?)
(RDEPTH) a! @ if NO drop ERR-IN-MACRO (FAIL) 1 ;
NO: ;
\ macro NAME ... endmacro: the tokens between, as counted strings, then a
\ zero cell, into the pool; NAME the macro, its value where they are. One
\ left open is reported at the line it began on, as text.c reports it.
: (H-MACRO)
(IN-MACRO?) if OK drop ;
OK: drop
(LINE) a! @ (T4) a! !
(NEXT-TOKEN) if NONAME drop
(TOK) (TSAVE) 16 (COPY)
0 (T1) a! !
L: (NEXT-TOKEN) if EOF drop
&(RESERVED) (WALK)
dup -2 + if END drop
dup if BAD2 drop
-1 + if BAD1 drop
(LABELFORM?) if APP drop jump BAD
APP: drop
(TOKN) a! @ 4 + 2/ 2/ dup (T2) a! !
(T1) a! @ + 1 + MBODY-SIZE inv 1 + + -1 + -if FULLM drop
(TOK) (MBODY) (T1) a! @ + (T2) a! @ (COPY)
(T1) a! @ (T2) a! @ + (T1) a! !
jump L
END: drop drop
0 (MBODY) (T1) a! @ + b! !b
(T1) a! @ 1 + (ALLOC) if FAILP
(MBODY) over (T1) a! @ 1 + (COPY)
(NAME-BACK)
3 jump (DEFINE)
FAILP: drop ;
BAD2: drop
BAD1: drop
BAD: ERR-IN-MACRO jump (FAIL)
FULLM: drop ERR-NAMES jump (FAIL)
EOF: drop ERR-MACRO (FAIL) (T4) a! @ (ERRLINE) a! ! ;
NONAME: drop ERR-MACRO jump (FAIL)
: (H-ENDMACRO) ERR-MACRO jump (FAIL)
\ ( body -- ) read a macro's tokens in its place
: (USE-MACRO)
(RDEPTH) a! @ -8 + -if DEEP drop
(RDEPTH) a! @ (RPTRS) + a! !
(RDEPTH) a! @ 1 + ! ;
DEEP: drop drop ERR-DEEP jump (FAIL)
\ ---- CONST+N ---------------------------------------------------------------
\ ( -- v 1 | 0 0 ) the token as a constant and a number after its last +;
\ if it is not one, the token is left as it was
: (CONST+N)
(TOK-SAVE)
(MLEN) a! @ -1 + (T1) a! !
L: (T1) a! @ -if GO drop jump NOPE
GO: (MTEMP) + a! @ 43 xor if FOUND drop
(T1) a! @ -1 + ! jump L
FOUND: drop
(T1) a! @ if NOPE0 drop
(T1) a! @ (MLEN) a! @ -1 + xor if NOPE0 drop
0 (T1) a! @ (TOK-SUB)
(FIND) if NOPE0
dup 2 + a! @ 2 xor if ISC drop drop jump NOPE
ISC: drop 3 + a! @ (T2) a! !
(T1) a! @ 1 + (MLEN) a! @ (T1) a! @ inv 1 + + -1 + (TOK-SUB)
(NUMBER) 1 xor if OKN drop drop jump NOPE
OKN: drop (T2) a! @ + 1 ;
NOPE0: drop
NOPE: 0 (MLEN) a! @ (TOK-SUB) 0 0 ;
\ ---- one token -------------------------------------------------------------
\ the reserved words' handlers, in (RESERVED)'s order
: (DISPATCH)
jump (H-COLON) jump (H-MACRO) jump (H-ENDMACRO)
jump (H-FOR) jump (H-NEXT) jump (H-UNEXT)
jump (H-CONSTANT) jump (H-SET) jump (H-HERE)
jump (H-CELL) jump (H-STRING) jump (H-STORE)
jump (H-START)
\ : NAME end the word before, and begin NAME at the next instruction word
: (H-COLON)
(IN-MACRO?) if OK drop ;
OK: drop
(NEXT-TOKEN) if NONAME drop
(END-WORD) (LABEL) 1 jump (DEFINE)
NONAME: drop ERR-MISSING jump (FAIL)
\ ( -- ) assemble the token
: (ONE)
&(RESERVED) (WALK) -if RES drop
(LABELFORM?) if NLD drop jump (LABEL-DEF)
NLD: drop
(OPCODE) -if OPC drop
0 (CHAR@) 38 xor if AMP drop
AFTERAMP:
(NUMBER) if NN
-if NUMOK drop drop ERR-BIG jump (FAIL)
NUMOK: drop jump (LIT)
NN: drop drop
(FIND) if NOSYM
dup 2 + a! @
dup 3 xor if MAC drop
dup 2 xor if CV drop
4 xor if CV0
drop drop 3 0 jump (BRANCH-NAME)
MAC: drop drop 3 + a! @ jump (USE-MACRO)
CV: drop drop 3 + a! @ jump (LIT)
CV0: drop 3 + a! @ jump (LIT)
NOSYM: drop
(CONST+N) if CALL drop jump (LIT)
CALL: drop drop 3 0 jump (BRANCH-NAME)
RES: &(DISPATCH) + push ;
OPC: dup 8 xor if FP drop
dup (BRANCH-OP?) if PLAIN drop
(NEXT-TOKEN) if NOTGT drop
1 jump (BRANCH-NAME)
PLAIN: drop jump (OP)
FP: drop drop ERR-FETCH-P jump (FAIL)
NOTGT: drop drop ERR-MISSING jump (FAIL)
AMP: drop (TOKN) a! @ -1 + if ONECH drop
(TOK-SAVE) 1 (MLEN) a! @ -1 + (TOK-SUB)
(FIND) if BADA
dup 2 + a! @ 1 xor if OKA drop drop jump BADA0
OKA: drop 3 + a! @ jump (LIT)
BADA: drop
BADA0: ERR-AMP jump (FAIL)
ONECH: drop jump AFTERAMP
+83
View File
@@ -0,0 +1,83 @@
\ acl.f18 -- word-level access control: the fields of an entry.
\
\ DECOMPOSITION.md 5.20, as v3: ACL-MODE@ ACL-MODE! ACL-TTL@ ACL-TTL! ACL-ALLOW@
\ ACL-ALLOW! ACL-PINNED? ACL-PIN ACL-INHERIT ACL-INIT-PRIMITIVES ACL-HEAT@
\ ACL-WORD-ID. These are all the capsule does itself; the policy -- what is
\ strict, how long a TTL is, what is pinned -- is FORTH source, ACL.fth, as
\ it is ACL.4th in v3. The fields and the check are described in
\ compile.f18. Rests on compile.f18, quit.f18 and system.f18.
\
\ An xt of 0 is an error (code 16, "Not a word"). A pinned word's fields are
\ not changed by the ! words: they do nothing, as in v3.
\
\ Constants the loader supplies:
\ (ACL-HOOK) word address of the variable: the xt of the recheck word, or 0
\ ( xt -- xt ) refuse 0
: (ACL-XT) if NULL ; NULL: drop NODE-ERROR b! 16 !b 0 ;
\ ( xt -- flag ) non-zero if it is pinned. A holds the flags' address.
: (PINNED) -3 + a! @ 64 and ;
set HDR-NFA here ", ACL-HOOK #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : ACL-HOOK' (ACL-HOOK) ;
set HDR-NFA here ", ACL-MODE@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-MODE@ ( xt -- mode ) (ACL-XT) -3 + a! @ 8/ 255 and ;
set HDR-NFA here ", ACL-TTL@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-TTL@ ( xt -- n ) (ACL-XT) -3 + a! @ 8/ 8/ 65535 and ;
set HDR-NFA here ", ACL-ALLOW@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-ALLOW@ ( xt -- flag ) (ACL-XT) -3 + a! @ 32 and if YES drop 0 ; YES: drop -1 ;
set HDR-NFA here ", ACL-PINNED? #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-PINNED? ( xt -- flag ) (ACL-XT) (PINNED) if NO drop -1 ; NO: ;
set HDR-NFA here ", ACL-PIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-PIN ( xt -- ) (ACL-XT) -3 + a! @ 64 OR ! ;
set HDR-NFA here ", ACL-MODE! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-MODE! ( mode xt -- )
(ACL-XT) (PINNED) if FREE drop drop ;
FREE: drop 255 and 8* @ -65281 and + ! ;
\ as v3: below 0 is 0. The TTL is sixteen bits here: above 65535 is 65535.
set HDR-NFA here ", ACL-TTL! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-TTL! ( n xt -- )
(ACL-XT) (PINNED) if FREE drop drop ;
FREE: drop
-if POS drop 0 jump SET
POS: dup -65536 and if SMALL drop drop 65535 jump SET
SMALL: drop
SET: 8* 8* @ 65535 and + ! ;
set HDR-NFA here ", ACL-ALLOW! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-ALLOW! ( flag xt -- )
(ACL-XT) (PINNED) if FREE drop drop ;
FREE: drop if DENY drop @ -33 and ! ;
DENY: drop @ 32 OR ! ;
\ ( src dst -- ) as v3: dst takes src's mode; it is not pinned, its TTL
\ is 0 and it is allowed. This is the one word that unpins.
set HDR-NFA here ", ACL-INHERIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-INHERIT
(ACL-XT) SWAP (ACL-XT) \ dst src
-3 + a! @ $FF00 and \ dst mode
SWAP -3 + a! @ 255 and -97 and + ! ; \ the five flags, nothing else
\ ( xt -- ) every entry from xt back that is not pinned: TTL mode, TTL 0,
\ allowed
: (ACL-INIT)
L: if DONE
dup (PINNED) if FREE drop jump NXT
FREE: drop @ 31 and !
NXT: -1 + a! @ jump L
DONE: drop ;
\ ( -- ) as v3: do that to every word in the dictionary, in every vocabulary
set HDR-NFA here ", ACL-INIT-PRIMITIVES #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-INIT-PRIMITIVES
(LATEST) a! @ (ACL-INIT)
VOC-LINK a! @
V: if DONE dup a! @ (ACL-INIT) 1 + a! @ jump V
DONE: drop ;
\ ( xt -- heat ) how often the word has been used. The node's heat
\ counters are not readable from a programme yet (D-6): 0.
set HDR-NFA here ", ACL-HEAT@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-HEAT@ (ACL-XT) drop 0 ;
\ ( xt -- n ) a number for the word that never changes: its address
set HDR-NFA here ", ACL-WORD-ID #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ACL-WORD-ID (ACL-XT) ;
+127
View File
@@ -0,0 +1,127 @@
\ blocks.f18 -- mass storage: blocks of 1024 characters, and text loaded from them.
\
\ DECOMPOSITION.md 5.11, FORTH-79: BLOCK BUFFER UPDATE SAVE-BUFFERS
\ EMPTY-BUFFERS LIST LOAD SCR BLK, and v3's FLUSH THRU and --> . Part of the
\ compiler capsule; rests on everything before it.
\
\ STORAGE IS THE KERNEL'S (docs/v4.0.0/MESH.md section 8, ENGINE.md 3.3), as
\ it is for a v3 VM. A node only ever asks for a block by number, and it
\ asks its kernel: it writes a request to port 0, where its kernel is, and
\ when the write has been served the answer is on the data stack. The
\ node has a window in its memory, four slots of 256 cells; the kernel
\ keeps the record of which block is in which slot, does the copying, and
\ decides when a block is written. The requests (v4/include/v4/blocks.h):
\ BLOCK# ( n -- waddr status ) the slot holding block n
\ BUFFER# ( n -- waddr status ) a slot for block n, not read
\ UPDATE# ( -- status ) the block last asked for is changed
\ SAVE-BUFFERS# ( -- status ) every changed block is written
\ EMPTY-BUFFERS# ( -- ) every slot is let go
\ The status is 0, or 2 storage refused (error 17), or 3 there is no such
\ block (error 13). BLOCK and BUFFER give a byte address, as PAD and TIB
\ are: what C@ CMOVE and TYPE take.
\
\ Constants the loader supplies:
\ BLOCK# BUFFER# UPDATE# SAVE-BUFFERS# EMPTY-BUFFERS# the requests' numbers
\ SCR word address of the variable: the block LIST showed last
\ BLK (SRC) (SRC-HOOK) see input.f18
set HDR-NFA here ", SCR #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : SCR' SCR ;
set HDR-NFA here ", BLK #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : BLK' BLK ;
\ ( status -- ) a request that did not work is an error
: (B-ERR)
if FINE -2 + if E17 drop NODE-ERROR b! 13 !b ;
E17: drop NODE-ERROR b! 17 !b ;
FINE: drop ;
\ ( waddr status -- baddr ) the slot's byte address, or the error
: (B-GOT)
if OK SWAP drop jump (B-ERR)
OK: drop 2* 2* ;
\ ( n -- baddr ) FORTH-79: the address of a buffer assigned to block n.
\ What the buffer holds is not read from storage.
set HDR-NFA here ", BUFFER #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BUFFER BUFFER# (PORT) b! !b jump (B-GOT)
\ ( n -- baddr ) FORTH-79: the address of a buffer that holds block n,
\ read from storage if it is not already in one.
set HDR-NFA here ", BLOCK #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BLOCK BLOCK# (PORT) b! !b jump (B-GOT)
\ FORTH-79: mark the block most recently asked for as changed, so that it is
\ written before its buffer is used for another.
set HDR-NFA here ", UPDATE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: UPDATE UPDATE# (PORT) b! !b jump (B-ERR)
\ FORTH-79: write every block that has been UPDATEd.
set HDR-NFA here ", SAVE-BUFFERS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SAVE-BUFFERS SAVE-BUFFERS# (PORT) b! !b jump (B-ERR)
\ As v3: the same.
set HDR-NFA here ", FLUSH #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: FLUSH jump SAVE-BUFFERS
\ FORTH-79: forget what is in the buffers; nothing is written.
set HDR-NFA here ", EMPTY-BUFFERS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: EMPTY-BUFFERS EMPTY-BUFFERS# (PORT) b! !b ;
\ ---- LIST ----------------------------------------------------------------------
\ ( n -- ) as v3: a new line, "Block n", then sixteen lines of 64
\ characters, each after its number, and an empty line. SCR is left holding n. A character
\ that is not printable is shown as a blank. (Q)+0 is the line, (Q)+1 the
\ column, (Q)+2 the block's number.
set HDR-NFA here ", LIST #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LIST
dup (Q)+2 a! ! BLOCK drop \ an error here leaves nothing behind
(Q)+2 a! @ dup SCR a! !
CR $636F6C42 (EMIT4) $206B (EMIT4) 0 DOT-R CR \ "Block "
0 (Q) a! !
LN: (Q) a! @ 0 <# # # #> TYPE 58 EMIT SPACE
0 (Q)+1 a! !
CH: SCR a! @ BLOCK (Q) a! @ 2* 2* 2* 2* 2* 2* + (Q)+1 a! @ + C@
dup -32 + -if GE drop drop 32 jump EM
GE: drop dup -127 + -if BIG drop jump EM
BIG: drop drop 32
EM: EMIT
(Q)+1 a! @ 1 + dup ! -64 + if EOL drop jump CH
EOL: drop CR
(Q) a! @ 1 + dup ! -16 + if DONE drop jump LN
DONE: drop jump CR
\ ---- LOAD ----------------------------------------------------------------------
\ The text being interpreted is at (SRC), SPAN characters of it, >IN the
\ place in it. LOAD saves those and BLK on the return stack, points them at
\ the block, interprets it, and puts them back; so a block may LOAD another,
\ and the rest of the line LOAD was on is interpreted afterwards. (v3's
\ LOAD loses the rest of its line.)
\ ( -- ) what WORD calls before it reads: while a block is being loaded,
\ make sure it is in a buffer and (SRC) is that buffer.
: (BLK-SRC)
BLK a! @ if TERM BLOCK (SRC) a! ! ;
TERM: drop ;
\ ( n -- ) FORTH-79: interpret block n, then go on with what follows.
set HDR-NFA here ", LOAD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LOAD
-if POS jump BAD
POS: if BAD
BLK a! @ push >IN a! @ push SPAN a! @ push (SRC) a! @ push
BLK a! ! 0 >IN a! ! 1024 SPAN a! !
&(BLK-SRC) (SRC-HOOK) a! !
INTERPRET
pop (SRC) a! ! pop SPAN a! ! pop >IN a! ! pop BLK a! ! ;
BAD: drop NODE-ERROR b! 13 !b ;
\ ( -- ) go on with the next block. Only in a block being loaded: at the
\ terminal it is an error (code 14).
set HDR-NFA here ", --> #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NEXT-BLOCK
BLK a! @ if TERM 1 + ! 0 >IN a! ! ;
TERM: drop NODE-ERROR b! 14 !b ;
\ ( first last -- ) as v3: LOAD each block from first to last.
set HDR-NFA here ", THRU #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: THRU
push
L: dup inv pop dup push + 1 + -if GO drop drop pop drop ; \ last - first
GO: drop dup push LOAD pop 1 + jump L
+119
View File
@@ -0,0 +1,119 @@
\ codegen.f18 -- the code generator: opcodes, literals and branches packed into
\ instruction words at HERE.
\
\ This is what the compiling words ( : ; IF LOOP LITERAL ... ) are built on.
\ It lays code down exactly as DECOMPOSITION.md 1.2 and 2 require and as the
\ test harness's own packers do (v4/include/v4/asm.h, text.h):
\
\ - opcodes fill slots 0 .. 5 of a word left to right; a full word is
\ appended to the dictionary and a new one started; unused slots are nop
\ - a literal is @p in a slot and its value in the cell after the word;
\ several in one word follow it in order
\ - ; and ex close the word, since nothing after them runs
\ - a branch closes the word: the bits to its right are its address
\ - a branch goes only in a slot whose address field reaches all of the
\ node's memory; otherwise the word is closed first and the branch starts
\ the next one. So no branch ever needs a reach check.
\
\ An instruction word is 32 bits at every cell width (D-9): slot k is the five
\ bits whose lowest is bit 27 - 5k, and a branch there has 27 - 5k address bits.
\
\ Rests on core.f18 and dict.f18. Constants the loader supplies:
\ (CG) word address of fourteen cells of scratch for this file
\ CG-BSLOTS how many slots, counted from slot 0, may hold a branch
\ Like WORD, these run under whatever the user has on the stacks, so what they
\ work on is in (CG), they keep at most three cells of their own on the data
\ stack, and they call each other as little as they can (D-2):
\ (CG)+0 the word being built (CG)+1 its next free slot
\ (CG)+2 how many literals it owes, and (CG)+3 .. (CG)+8 the literals
\ (CG)+9 the opcode (OP,) was given (CG)+10 the ref (BRANCH0) made
\ (CG)+11 the target a branch is to reach (CG)+12 which literal (FLUSH) is at
\ (CG)+13 what (FLUSH) fills unused slots with: nop, or 0 after a branch
\
\ The word being built is kept right-justified: each opcode is shifted in
\ below the ones before it, and (FLUSH) shifts in what fills the rest and the
\ two spare bits. So nothing is ever shifted by a counted loop, which would
\ want a return-stack entry for its count.
\ ( k -- mask ) the address bits of a branch in slot k: 2^(27-5k) - 1
: (MASK)
if K0 -1 + if K1 -1 + if K2
drop 4095 ;
K2: drop 131071 ;
K1: drop 4194303 ;
K0: drop 134217727 ;
\ ( -- ) forget the word being built
: (CG-RESET) 0 (CG) a! ! 0 (CG)+1 a! ! 0 (CG)+2 a! ! 28 (CG)+13 a! ! ;
\ ( x -- ) five bits into the next free slot, which must be free
: (PUT)
(CG) a! @ 2* 2* 2* 2* 2* + !
(CG)+1 a! @ 1 + ! ;
\ ( -- ) append the word being built, its unused slots filled, then the
\ literals it owes; nothing if no slot is in use
: (FLUSH)
(CG)+1 a! @ if EMPTY drop
P: (CG)+1 a! @ -6 + if FULL drop (CG)+13 a! @ (PUT) jump P
FULL: drop
(CG) a! @ 2* 2* , \ the two spare bits
0 (CG)+12 a! !
L: (CG)+12 a! @ (CG)+2 a! @ xor if DONE
drop (CG)+12 a! @ dup 1 + ! (CG)+3 + a! @ ,
jump L
DONE: drop
jump (CG-RESET)
EMPTY: drop ;
\ ( op -- ) any opcode that is neither a branch nor @p
: (OP,)
dup (CG)+9 a! ! (PUT)
(CG)+9 a! @ if ENDS -1 + if ENDS \ ; and ex end the word
drop (CG)+1 a! @ -6 + if ENDS drop ; \ and so does its last slot
ENDS: drop jump (FLUSH)
\ ( x -- ) @p and its value
: (LIT,)
(CG)+2 a! @ dup 1 + ! \ x n
(CG)+3 + a! !
8 (PUT)
(CG)+1 a! @ -6 + if FULL drop ;
FULL: drop jump (FLUSH)
\ ( -- addr ) where the next word will go: a branch target
: (LABEL) (FLUSH) HERE ;
\ ( op -- ) a branch (jump 2, call 3, next 5, if 6, -if 7) whose address is
\ not filled in yet. Its ref -- the branch's word address times 8, plus its
\ slot -- is left in (CG)+10. The rest of its word is filled with 0, which
\ is its address field. It ends by jumping to (FLUSH), so that the chain of
\ calls under it is one shorter.
: (BRANCH0)
(CG)+1 a! @ CG-BSLOTS inv + 1 + -if MOVE drop jump PLACED \ slot - CG-BSLOTS
MOVE: drop (FLUSH)
PLACED:
\ the word will be appended at HERE; its literals, if any, come after it
HERE 2* 2* 2* (CG)+1 a! @ + (CG)+10 a! !
(PUT)
0 (CG)+13 a! ! jump (FLUSH)
\ ( op -- ref ) the same, leaving the ref, for (RESOLVE) to fill in later
: (BRANCH>) (BRANCH0) (CG)+10 a! @ ;
\ ( ref -- ) put the address in (CG)+11 into the branch at ref
: (RESOLVE1)
dup 7 and (MASK) push \ ref R: mask
2/ 2/ 2/ a! \ A: the branch's word
(CG)+11 b! @b pop dup push and \ the address bits
@ pop inv and + ! ;
\ ( target ref -- ) put the address into the branch at ref
: (RESOLVE) SWAP (CG)+11 a! ! jump (RESOLVE1)
\ ( target op -- ) a branch to a known address
: (BRANCH,) SWAP (CG)+11 a! ! (BRANCH0) (CG)+10 a! @ jump (RESOLVE1)
: (JUMP,) ( addr -- ) 2 jump (BRANCH,)
: (CALL,) ( addr -- ) 3 jump (BRANCH,)
+466
View File
@@ -0,0 +1,466 @@
\ compile.f18 -- the interpreter's inner loop, and the defining and compiling
\ words.
\
\ DECOMPOSITION.md 5.17 and 5.18: STATE [ ] : ; EXIT IMMEDIATE LITERAL COMPILE
\ [COMPILE] ' EXECUTE CREATE VARIABLE CONSTANT DOES>, the control structures
\ IF ELSE THEN BEGIN UNTIL AGAIN WHILE REPEAT DO ?DO LOOP +LOOP, and INTERPRET,
\ which they cannot be run without. Part of the compiler capsule. Rests on
\ core.f18, input.f18, dict.f18 and codegen.f18.
\
\ HOW A WORD IS COMPILED. v4 code is native: a colon definition is
\ instruction words, and compiling a word into one lays down a call to it.
\ Two flags on an entry (dict.f18) change that:
\ inline its code is a straight run of opcodes and literals ending
\ in ; -- that run is copied in place of a call. Everything
\ that touches the return stack must be, since a call would
\ bury what it works on (DECOMPOSITION.md 0, fate IN).
\ compile-only it may not be executed by the interpreter.
\ An immediate word is executed even when compiling.
\
\ THE STACKS ARE SHORT: written for ten cells of data and nine return entries
\ (D-2; the host node now has 32 of each, D-17), and one more of either is a
\ fault (D-16). The interpreter and compiler run on the same
\ stacks as the user's words, with the user's values beneath them, so:
\ - every word here keeps what it works on in (C), and has at most three
\ cells of its own on the data stack at any moment;
\ - what an IF or a DO leaves for its THEN or LOOP goes on a control-flow
\ stack in memory, not on the data stack, so structures may nest as
\ deep as that stack (32 cells) allows whatever the user has stacked.
\
\ Constants the loader supplies:
\ STATE word address of the variable: non-zero while compiling
\ (C) word address of ten cells of scratch for this file:
\ (C)+0 (C)+1 (C)+4 the in-liner's word, literal pointer and slot
\ (C)+2 LATEST before a header is made (C)+3 a data word's routine
\ (C)+5 what a loop's end lays after its test
\ (C)+6 (C)+7 a branch and a tag a control word is holding
\ (C)+8 whether a data word's entry was made
\ (C)+9 the error code a line is being abandoned with
\ (CFP) word address of the control-flow stack's pointer
\ CFBASE CFEND word addresses of its first cell and of the cell past its last
macro ROT push SWAP pop SWAP endmacro
\ ---- errors ------------------------------------------------------------------
\ ( -- ) give up the line: stop compiling, forget the word being built and
\ whatever control structures were open, skip the rest of the input, and set
\ NODE-ERROR. A definition that was under way stays hidden. It returns to
\ whatever called INTERPRET, which is QUIT (quit.f18): QUIT sees NODE-ERROR
\ and prints ERROR.
\ (ABANDON-AS) is the same with an error code (core.f18) for the prompt to
\ print the message of.
: (ABANDON-AS) ( code -- )
(C)+9 a! !
0 STATE a! ! (CG-RESET)
CFBASE (CFP) a! !
SPAN a! @ >IN a! !
(C)+9 a! @ NODE-ERROR b! !b ;
: (ABANDON) -1 jump (ABANDON-AS)
\ ---- the control-flow stack ----------------------------------------------------
\ ( x -- ) push; a full stack abandons the line
: >CF
(CFP) a! @ CFEND xor if FULL
drop (CFP) a! @ dup 1 + ! a! ! ;
FULL: drop drop 8 jump (ABANDON-AS) \ control structures too deep
\ ( -- x ) pop; 0 from an empty stack, which no opening word leaves
: CF>
(CFP) a! @ CFBASE xor if EMPTY
drop (CFP) a! @ -1 + dup ! a! @ ;
EMPTY: ;
\ ---- compiling one word ------------------------------------------------------
\ ( w -- op ) the opcode in slot 0 of the instruction word w
: (TOP5) 8/ 8/ 8/ 2/ 2/ 2/ 31 and ;
\ ( xt -- ) copy the in-line word at xt into the definition being built.
\ Each slot is read from the top of the word in (C)+0, which is then moved
\ up five bits for the next.
: (INLINE,)
W: dup a! @ (C) a! ! 1 + (C)+1 a! ! \ the word, and its literals after it
0 (C)+4 a! ! \ slot
S: (C) a! @ dup 2* 2* 2* 2* 2* ! (TOP5) \ op
if END \ ; ends the copy
dup -8 + if LIT
drop dup -28 + if NOP \ nop is padding
drop (OP,)
NXT: (C)+4 a! @ 1 + dup ! -6 + if NEXTW drop jump S
NEXTW: drop (C)+1 a! @ jump W \ the next instruction word follows the literals
LIT: drop drop (C)+1 a! @ dup 1 + ! a! @ (LIT,) jump NXT
NOP: drop drop jump NXT
END: drop ;
\ ( xt -- ) compile the word at xt: in line if it is flagged so, else a call
: (COMPILE,)
dup -3 + a! @ 8 and if CALL drop jump (INLINE,)
CALL: drop jump (CALL,)
\ ---- access control (5.20) -------------------------------------------------------
\ Each entry's flags cell also holds its access control fields:
\ bit 5 (32) denied: the word may not be used
\ bit 6 (64) pinned: the fields cannot be changed
\ bits 8 .. 15 the mode: 0 TTL, 1 STRICT
\ bits 16 .. 31 the TTL, a count of uses left before the next recheck
\ A new entry has all of them zero: allowed, not pinned, TTL mode, TTL 0.
\
\ (ACL?) is run by INTERPRET for every word it is about to execute or
\ compile. As v3: if the TTL is 0 the word is rechecked, otherwise the TTL
\ is counted down; then a denied word is refused. The recheck is the word
\ whose address is in (ACL-HOOK) -- ACL-RECHECK, once ACL.fth has loaded --
\ and with none there the word is allowed and given the longest TTL.
\
\ v3 checks every execution, inside definitions too. v4 code is native: a
\ compiled call goes straight to its word. So v4 checks a word when it is
\ compiled as well as when it is interpreted -- a denied word cannot be
\ built into anything new -- but a call compiled while the word was allowed
\ is not checked again.
\ ( xt -- ) recheck
: (ACL-RECHECK)
(ACL-HOOK) a! @ if NONE push ex \ call it with the xt
;
NONE: drop -3 + a! @ 65535 and -33 and $FFFF0000 + ! ;
\ ( xt -- xt ) as above; a denied word ends the line
: (ACL?)
dup -3 + a! @ \ xt flags
dup $FFFF0000 and if ZERO
drop -65536 + ! jump TEST \ one use fewer
ZERO: drop drop dup (ACL-RECHECK)
TEST: dup -3 + a! @ 32 and if OK
drop drop
$33335B1B (EMIT4) $6D (EMIT4) $4E524157 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) \ v3's line: WARN: in yellow
$3A4C4341 (EMIT4) $6E656420 (EMIT4) $20646569 (EMIT4) $27 (EMIT4)
(.WORD) 39 EMIT CR
DSTACK-DEPTH b! a !b \ as v3, the stack is emptied
pop drop jump (ABANDON)
OK: drop ;
\ ( -- ) print the word WORD has just left
: (.WORD) WBUF COUNT jump TYPE
set HDR-NFA here ", EXECUTE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: EXECUTE ( xt -- ) push ;
\ ---- the interpreter's inner loop ---------------------------------------------
\ ( -- n flag ) the word WORD has just left, as a single-cell number in the
\ current BASE, and -1; or 0 0 if it is not one. A leading minus sign is
\ allowed. This is what the interpreter uses: NUMBER (input.f18) makes a
\ double and needs more of the stack than can be spared here.
\ (P)+2 the number so far, (P)+3 where it is in the word, (P)+4 the word's
\ length, (P)+5 the sign, (P)+6 the base.
: (NUM?)
WBUF C@ if EMPTY
(P)+4 a! ! 0 (P)+2 a! ! 1 (P)+3 a! ! 0 (P)+5 a! !
(BASE) (P)+6 a! !
WBUF+1 C@ -45 + if NEG drop jump DIGITS
NEG: drop -1 (P)+5 a! ! 2 (P)+3 a! !
(P)+4 a! @ -1 + if EMPTY drop \ a sign alone
DIGITS:
L: (P)+4 a! @ (P)+3 a! @ - -if MORE
drop (P)+2 a! @ (P)+5 a! @ if POS drop NEGATE -1 ;
POS: drop -1 ;
MORE: drop
(P)+3 a! @ dup 1 + ! WBUF + C@ (DIGIT) \ d
-if DIGIT jump BAD1
DIGIT: dup (P)+6 a! @ - -if BAD2 drop
(P)+2 a! @ (P)+6 a! @ STAR + (P)+2 a! !
jump L
BAD2: drop
BAD1: drop 0 0 ;
EMPTY: drop 0 0 ;
\ ( -- ) FORTH-79: take words from the input stream until it is exhausted.
\ A word in the dictionary is executed, or, when compiling and not immediate,
\ compiled. Anything else must be a number in the current BASE: it is left
\ on the stack, or compiled as a literal. What is neither, or a compile-only
\ word met while interpreting, abandons the line, with v3's message:
\ UNKNOWN WORD: 'xxx' xxx: compile-only
set HDR-NFA here ", INTERPRET #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: INTERPRET
L: 32 WORD dup C@ if EOL
drop (LOOKUP) if NUM
dup -3 + a! @ \ xt flags
STATE a! @ if INTERP
drop 1 and if COMP \ compiling: immediate words still run
drop (ACL?) EXECUTE jump L
COMP: drop (ACL?) (COMPILE,) jump L
INTERP: drop 16 and if RUN
drop drop (.WORD) \ ": compile-only"
$6F63203A (EMIT4) $6C69706D (EMIT4) $6E6F2D65 (EMIT4) $796C (EMIT4) CR
jump (ABANDON)
RUN: drop (ACL?) EXECUTE jump L
NUM: drop (NUM?) if BAD
drop
STATE a! @ if KEEP drop (LIT,) jump L
KEEP: drop jump L
BAD: drop drop (UNKNOWN) drop jump (ABANDON)
EOL: drop drop ;
\ ---- state ---------------------------------------------------------------------
set HDR-NFA here ", [ #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LEFT-BRACKET 0 STATE a! ! ;
set HDR-NFA here ", ] #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: RIGHT-BRACKET -1 STATE a! ! ;
\ ( x -- ) FORTH-79: if compiling, compile x as a literal
set HDR-NFA here ", LITERAL #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LITERAL STATE a! @ if NO drop jump (LIT,) NO: drop ;
\ ( -- addr ) FORTH-79: the next word's parameter field address; if
\ compiling, compiled as a literal
set HDR-NFA here ", ' #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: TICK (') jump LITERAL
\ ['] xxx the same inside a definition, whatever STATE is; and [LITERAL],
\ which v3 has as another name for LITERAL.
set HDR-NFA here ", ['] #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BRACKET-TICK (') jump (LIT,)
set HDR-NFA here ", [LITERAL] #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BRACKET-LITERAL jump LITERAL
\ ---- colon definitions -----------------------------------------------------------
\ FORTH-79: start a definition; it cannot be found until ; ends it. The
\ CONTEXT vocabulary is set to the CURRENT one.
\ (C)+2 holds LATEST while the entry is made, to tell whether one was.
set HDR-NFA here ", : #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COLON
CURRENT a! @ CONTEXT a! !
LATEST (C)+2 a! !
32 WORD (HEADER)
LATEST (C)+2 a! @ xor if NONE drop
HIDDEN (CG-RESET) CFBASE (CFP) a! ! jump RIGHT-BRACKET
NONE: drop jump (ABANDON) \ no entry: the rest of the line is not a definition
\ FORTH-79: compile the return, let the word be found, stop compiling
set HDR-NFA here ", ; #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SEMICOLON
0 (OP,)
LATEST (FLAGS) a! @ -3 and !
jump LEFT-BRACKET
\ ( n -- ) KERNEL-WORD xxx A WORD THAT ASKS THE KERNEL (docs/v4.0.0/
\ ENGINE.md 3.3). xxx is made a word whose whole body is "write n to the
\ port": n is the number of a request, the port is the node's way to its
\ kernel, and the write blocks the node until the kernel has served it
\ (DECOMPOSITION.md section 6). xxx's arguments are whatever it finds on
\ the data stack and its results are what the kernel leaves there. This is
\ what a word that is a C function in v3 -- BIRTH, BLOCK, BYE -- is on a
\ node. Not FORTH-79 and not in v3, where such a word is registered from C.
\ The constant (PORT) is the port's word address.
set HDR-NFA here ", KERNEL-WORD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: KERNEL-WORD
COLON (LIT,) (PORT) (LIT,) 30 (OP,) 14 (OP,) \ n port b! !b
jump SEMICOLON
\ FORTH-79: return from the definition at this point
set HDR-NFA here ", EXIT #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: EXIT 0 jump (OP,)
set HDR-NFA here ", IMMEDIATE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: IMMEDIATE LATEST if NONE (FLAGS) a! @ 1 OR ! ; NONE: drop ;
\ COMPILE xxx FORTH-79: when the word this is in runs, xxx is compiled
set HDR-NFA here ", COMPILE #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COMPILE
32 WORD (LOOKUP) if MISSING
(LIT,) &(COMPILE,) jump (CALL,)
MISSING: drop (UNKNOWN) drop jump (ABANDON)
\ [COMPILE] xxx FORTH-79: compile xxx even though it is immediate
set HDR-NFA here ", [COMPILE] #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BRACKET-COMPILE
32 WORD (LOOKUP) if MISSING jump (COMPILE,)
MISSING: drop (UNKNOWN) drop jump (ABANDON)
\ ---- data words ---------------------------------------------------------------------
\ A data word's code is one call to its run-time routine; the call leaves the
\ address of the cell after it -- the parameter field -- on the return stack.
: (DOVAR) pop ; \ leave the parameter field address
: (DOCON) pop a! @ ; \ leave what it holds
\ ( -- ) an entry for the next word, flagged data, its code a call to the
\ routine whose address is in (C)+3. (C)+8 is left -1 if one was made, else
\ 0. It ends by jumping, and CREATE jumps to it, so that a defining word
\ has as few return entries under it as can be.
: (DATA)
0 (C)+8 a! !
LATEST (C)+2 a! !
32 WORD (HEADER)
LATEST (C)+2 a! @ xor if NONE drop
(CG-RESET)
LATEST (FLAGS) a! @ 4 OR !
-1 (C)+8 a! !
(C)+3 a! @ jump (CALL,)
NONE: drop ;
\ FORTH-79: an entry whose word leaves the address of its parameter field
set HDR-NFA here ", CREATE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CREATE &(DOVAR) (C)+3 a! ! jump (DATA)
\ FORTH-79: CREATE and one cell. The standard leaves its first value to the
\ programme; here it is 0.
set HDR-NFA here ", VARIABLE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: VARIABLE &(DOVAR) (C)+3 a! ! (DATA) (C)+8 a! @ if NONE drop 0 jump , NONE: drop ;
\ ( n -- ) FORTH-79: an entry whose word leaves n
set HDR-NFA here ", CONSTANT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CONSTANT &(DOCON) (C)+3 a! ! (DATA) (C)+8 a! @ if NONE drop jump , NONE: drop drop ;
\ FORTH-79: in : DEFINER CREATE ... DOES> ... ; the words after DOES> become
\ what each word DEFINER makes does, starting with its parameter field address
\ on the stack. (DOES), run by DEFINER, turns the newest entry's code into a
\ call to the code after it and leaves DEFINER; that code starts with pop,
\ which fetches the parameter field address the call left.
: (DOES) pop 402653184 + LATEST a! ! ; \ 402653184 is `call` in slot 0
set HDR-NFA here ", DOES> #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DOES> &(DOES) (CALL,) 25 jump (OP,)
\ ---- control structures (5.18, section 2) ---------------------------------------------
\ All immediate and compile-only. Each puts what the word that closes it
\ needs on the control-flow stack, with a number on top saying which word put
\ it there: 1 IF, 2 ELSE, 3 BEGIN, 4 WHILE, 5 DO, 6 ?DO, 7 CASE, 8 OF. A closing word that
\ finds the wrong number abandons the line.
\ ( tag wanted -- ) if they differ, abandon the line and leave the control
\ word that called this as well: its return address is dropped, so the
\ abandoning returns to the interpreter and nothing more is laid down.
: (PAIR) xor if OK drop pop drop 7 jump (ABANDON-AS) OK: drop ;
\ ( ref -- ) the branch at ref lands here
: (HERE!) (FLUSH) HERE SWAP jump (RESOLVE)
\ Native if leaves the flag, so both ways out of it drop it (section 2):
\ IF a THEN if L1 drop a jump L2 L1: drop L2:
\ IF a ELSE b THEN if L1 drop a jump L2 L1: drop b L2:
set HDR-NFA here ", IF #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: IF 6 (BRANCH>) >CF 23 (OP,) 1 jump >CF
set HDR-NFA here ", ELSE #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ELSE
CF> 1 (PAIR) CF> (C)+6 a! ! \ the if
2 (BRANCH>) >CF \ the jump over the else part
(C)+6 a! @ (HERE!) 23 (OP,)
2 jump >CF
set HDR-NFA here ", THEN #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: THEN
CF> dup -1 + if PLAIN
drop 2 (PAIR) CF> jump (HERE!)
PLAIN: drop drop
CF> (C)+6 a! ! \ the if
2 (BRANCH>) >CF
(C)+6 a! @ (HERE!) 23 (OP,)
CF> jump (HERE!)
\ A loop that tests at its end jumps back with the flag still there, so it
\ jumps back to a drop laid just ahead of the body:
\ BEGIN a UNTIL jump L0 Ld: drop L0: a if Ld drop
\ BEGIN a WHILE b REPEAT jump L0 Ld: drop L0: a if Lx drop b jump L0 Lx: drop
\ BEGIN a AGAIN jump L0 Ld: drop L0: a jump L0
\ The control-flow stack holds Ld, L0 and 3.
set HDR-NFA here ", BEGIN #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BEGIN
2 (BRANCH>) (C)+6 a! !
(LABEL) >CF 23 (OP,)
(LABEL) dup >CF (C)+6 a! @ (RESOLVE)
3 jump >CF
set HDR-NFA here ", UNTIL #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: UNTIL CF> 3 (PAIR) CF> drop CF> 6 (BRANCH,) 23 jump (OP,)
set HDR-NFA here ", AGAIN #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: AGAIN CF> 3 (PAIR) CF> (JUMP,) CF> drop ;
set HDR-NFA here ", WHILE #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: WHILE CF> 3 (PAIR) 3 >CF 6 (BRANCH>) >CF 23 (OP,) 4 jump >CF
set HDR-NFA here ", REPEAT #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: REPEAT
CF> 4 (PAIR) CF> (C)+6 a! ! \ the while
CF> 3 (PAIR) CF> (JUMP,) CF> drop
(C)+6 a! @ (HERE!) 23 jump (OP,)
\ CASE: the value being chosen on stays on the stack through the clauses.
\ CASE x1 OF a ENDOF x2 OF b ENDOF c ENDCASE
\ lays, for each clause,
\ over xor if M drop jump N M: drop drop a jump END N:
\ and ENDCASE lays the drop that the part after the last ENDOF leaves the
\ value for, with END after it. The control-flow stack holds the jumps to
\ END, how many there are, and 7; inside a clause, the jump to N and 8.
: (of) over xor ;
set HDR-NFA here ", CASE #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CASE 0 >CF 7 jump >CF
set HDR-NFA here ", OF #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: OF
CF> 7 (PAIR)
&(of) (INLINE,) 6 (BRANCH>) (C)+6 a! ! \ if M
23 (OP,) 2 (BRANCH>) >CF \ drop, jump N
(C)+6 a! @ (HERE!) 23 (OP,) 23 (OP,) \ M: drop drop
8 jump >CF
set HDR-NFA here ", ENDOF #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ENDOF
CF> 8 (PAIR) CF> (C)+6 a! ! \ the jump to N
CF> (C)+7 a! ! \ how many jumps to END so far
2 (BRANCH>) >CF \ one more
(C)+7 a! @ 1 + >CF
(C)+6 a! @ (HERE!) \ N:
7 jump >CF
set HDR-NFA here ", ENDCASE #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ENDCASE
CF> 7 (PAIR) CF> (C)+7 a! !
23 (OP,)
L: (C)+7 a! @ if DONE -1 + !
CF> (HERE!) jump L
DONE: drop ;
\ DO loops: the limit and index are on the return stack, limit below (5.18).
: (do) over push push drop ;
: (?do) over over xor ;
: (inc) pop 1 + pop ; \ index' limit
: (+inc) dup a! pop + pop ; \ index' limit A: the step
: (differ) drop over ;
: (same) drop over over - ;
: (a-xor) a xor ;
: (again) drop push push ;
: (3drop) drop drop drop ;
\ The end of a loop. The control-flow stack holds the body's address and 5,
\ or for ?DO its skip, the body and 6; (C)+5 holds the xt of in-line code to
\ lay after the test, or 0. Laid down, in order:
\ <less> ( i' lim -- i' lim s ), the top bit of s set when i' < lim:
\ over over xor -if SAME drop over jump T SAME: drop over over - T:
\ the code in (C)+5, if any
\ -if EXIT drop push push jump BODY EXIT: drop drop drop
\ and for ?DO the landing of its skip: jump PAST SKIP: drop drop drop PAST:
\ It is one word, jumped to by LOOP and +LOOP, so that laying a loop's end
\ takes as few return entries as laying anything else.
: (LOOPS)
&(?do) (INLINE,) 7 (BRANCH>) >CF
&(differ) (INLINE,) 2 (BRANCH>) (C)+6 a! !
CF> (HERE!) &(same) (INLINE,)
(C)+6 a! @ (HERE!)
(C)+5 a! @ if NOMORE (INLINE,) jump TESTED
NOMORE: drop
TESTED:
CF> (C)+7 a! ! \ the tag
7 (BRANCH>) (C)+6 a! !
&(again) (INLINE,) CF> (JUMP,)
(C)+6 a! @ (HERE!) &(3drop) (INLINE,)
(C)+7 a! @ -5 + if PLAIN
drop (C)+7 a! @ 6 (PAIR)
2 (BRANCH>) (C)+6 a! !
CF> (HERE!) &(3drop) (INLINE,)
(C)+6 a! @ jump (HERE!)
PLAIN: drop ;
set HDR-NFA here ", DO #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DO &(do) (INLINE,) (LABEL) >CF 5 jump >CF
set HDR-NFA here ", ?DO #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ?DO &(?do) (INLINE,) 6 (BRANCH>) >CF 23 (OP,) &(do) (INLINE,) (LABEL) >CF 6 jump >CF
set HDR-NFA here ", LOOP #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LOOP &(inc) (INLINE,) 0 (C)+5 a! ! jump (LOOPS)
set HDR-NFA here ", +LOOP #, 17 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: +LOOP &(+inc) (INLINE,) &(a-xor) (C)+5 a! ! jump (LOOPS)
+480
View File
@@ -0,0 +1,480 @@
set HDR-LINK 0 \ the newest dictionary entry: none yet
\ core.f18 -- the core words the host-node capsules rest on.
\
\ Each is the definition DECOMPOSITION.md gives and the golden-model tests
\ execute (test_foundation.c, test_strings.c, test_terminal.c, test_pictured.c),
\ written here as text for the text assembler (v4/include/v4/text.h).
\
\ Constants the loader supplies: N-1 (cell bits - 1), NODE-ERROR, CONSOLE-TX,
\ CONSOLE-RX, CONSOLE-STATUS, BASE, (MSG), (REPLY), (ME), (OUT),
\ (OUT^), (CONSOLE), (ROUTES), (ROUTE#), (ROUTE-DEFAULT), (PRINT-TO),
\ (PRINT-PORT).
\
\ ERRORS (D-18). A word that finds an error takes its arguments off the stack
\ and stores a code in NODE-ERROR. On a node with a prompt that store is a
\ trap: the word goes no further, and the prompt prints the message for the
\ code and ERROR (quit.f18, (RAISED)). The codes:
\ 1 Negative count 2 Not a number 3 Number too long
\ 4 Not a character 5 Dictionary full 6 Name missing
\ 7 Control structure mismatch 8 Control structures too deep
\ 9 Shift count out of range 10 Protected word
\ 11 Division by zero (Q./) 12 Argument out of range
\ 13 Block out of range 14 No block is being loaded
\ 15 Deferred word not set 16 Not a word
\ 17 Storage refused 18 No one on that port
\ 19 Message refused 20 Node gone
\ 21 Interrupted
\ -1 the word has printed its own message
macro SWAP over push push drop pop pop endmacro
macro - push inv pop + inv endmacro \ x y -- x-y
macro NEGATE inv 1 + endmacro
macro NIP push drop pop endmacro
\ ---- section 4: multiply ------------------------------------------------
set HDR-NFA here ", UM* #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: UM* ( u1 u2 -- ulo uhi )
over 1 and inv 1 + over 2/ and \ u1 u2 t0 t0 = u2 2/ if u1 odd
over a! N-1 push \ A: u2 R: loop count
push over 2/ pop \ u1 u2 s t0 s = u1 2/
L: +* unext \ u1 u2 s hi A: lo
push drop pop \ u1 u2 hi
2* a -if L0 drop 1 + jump L1 L0: drop L1: push
over -if L2 drop dup jump L3 L2: drop 0 L3: push
dup -if L4 drop over 1 and jump L5 L4: drop 0 L5:
pop + pop + push
and 1 and a 2* + pop ;
\ ---- section 5.7: doubles ------------------------------------------------
set HDR-NFA here ", D+ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D+ ( d1 d2 -- d3 )
push over push push drop pop \ al bl R: bh ah
over over xor -if L1
drop + -if C1 jump C0
L1: drop over -if L2
drop + jump C1
L2: drop +
C0: pop pop + ;
C1: pop pop + 1 + ;
set HDR-NFA here ", DNEGATE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DNEGATE ( d -- -d )
inv over if L1 drop push inv 1 + pop ;
L1: drop 1 + ;
\ ---- section 5.3: bytes --------------------------------------------------
\ The shifts are written out, eight to a line, where DECOMPOSITION.md 5.3 has
\ a FOR ... UNEXT loop: a loop keeps its count on the return stack, and C@ and
\ C! are at the bottom of every chain of calls in the compiler capsule, where
\ there is not an entry to spare (D-2). The result is the same.
macro 8/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ endmacro
macro 8* 2* 2* 2* 2* 2* 2* 2* 2* endmacro
set HDR-NFA here ", C@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: C@ ( baddr -- c )
dup 2/ 2/ a! 3 and
if K0 -1 + if K1 -1 + if K2
drop @ 8/ 8/ 8/ 255 and ;
K2: drop @ 8/ 8/ 255 and ;
K1: drop @ 8/ 255 and ;
K0: drop @ 255 and ;
set HDR-NFA here ", C! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: C! ( c baddr -- )
dup 2/ 2/ a! 3 and
if K0 -1 + if K1 -1 + if K2
drop 8* 8* 8* 4278190080 and @ 4278190080 inv and + ! ;
K2: drop 8* 8* 16711680 and @ -16711681 and + ! ;
K1: drop 8* 65280 and @ -65281 and + ! ;
K0: drop 255 and @ -256 and + ! ;
\ ---- section 5.9: strings ------------------------------------------------
set HDR-NFA here ", CMOVE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CMOVE ( src dst u -- )
-if OK drop drop drop NODE-ERROR b! 1 !b ;
OK: if DONE push
over C@ over C! 1 + push 1 + pop pop -1 + jump OK
DONE: drop drop drop ;
\ ---- section 5.10: the console -------------------------------------------
\ ---- what a node prints (docs/v4.0.0/MESH.md section 6) ------------------------
\ A node has no console of its own. It does what a message asks, and what
\ it prints while doing it is sent as a message: to the node in (CONSOLE), or
\ if that is 0 to whoever sent the text; by the port that leads there, or if
\ this node knows of none, by the port the text came on. A message is seven words and then its text, four
\ characters to a word:
\ to, from, type, heat and TTL, ACL tag, sequence, length in characters
\ The types: 1 text to be interpreted 2 what a node printed 3 how the
\ text ended (one word of text: 0 QUIT, 1 completed, 2 an error).
\ The header of the text being served is in the seven cells (MSG); (REPLY)
\ is the port it came on, by its number; (ME) is this node's number.
\
\ Characters are kept in (OUT), 256 of them, a character to a cell, and sent
\ when it is full and when the text has been done with (quit.f18). (OUT^)
\ is where the next goes.
\
\ THE STACK. What prints may be run with the data stack all but full: EMIT
\ has always needed one free cell and no more, and still does -- it keeps
\ the character and A on the return stack while it works. Sending needs
\ three.
\ FINDING THE WAY (MESH.md section 7). A node knows its ports and nothing of
\ the shape they are wired in. Whoever wires it tells it, for a node, which
\ port leads toward that node: the table (ROUTES), (ROUTE#) entries of a
\ node's number and a port's address; and (ROUTE-DEFAULT), the port for any
\ node that is not in the table, or 0.
\ ( node -- port | -1 ) the port, by its number, that leads toward the node
: (WAY)
(ROUTE#) a! @ if NONE -1 + (ROUTES) a!
FOR dup @+ xor if HIT drop @+ drop NEXT
0
NONE: drop drop (ROUTE-DEFAULT) a! @ if NOWAY (PORT) - ;
NOWAY: drop -1 ;
HIT: drop drop @+ pop drop (PORT) - ;
\ WHOLE MESSAGES (MESH.md section 7d). A message waits on a wire, in the
\ fabric, and not in a node: each wire has a queue of whole messages each
\ way. A node asks the fabric to look at one, take it, move it to another
\ wire, drop it, or put one on, by the six addresses after its ports:
\ (WIRE) the port, by its number, that what follows is about
\ (WIRE-A) (WIRE-B) what the operation needs
\ (WIRE-DO) the operation: a store here is the asking
\ (WIRE-HOW) how it went: 0 done, 1 no room, 2 no one on that port,
\ 3 no such message, 4 not a message
\ (WIRE-HAVE) which wires have a message waiting, a bit to a port
\ The operations: 1 look 2 take 3 move 4 drop 5 put 6 first 7 next
\ 8 sleep 9 sleep for room 10 room. Each is whole: all of a message
\ moves or none of it. So a fault or an error in the middle of anything
\ here leaves no message half moved; and nothing here keeps, from one
\ operation to the next, anything a later pass does not set again for
\ itself: every pass over a wire begins by naming the wire and putting its
\ mark at its first message.
\ This replaced a ring of messages waiting in the node's own memory, a
\ list of refusals owed, and messages written and read a word at a time
\ (MESH.md 7a, 7b, 7c.6). The ports themselves are still written a word at
\ a time for the two things that are not messages: a newborn node's
\ nucleus (PORT!, quit.f18) and a node's requests to its kernel.
\
\ THE STACKS. All of this runs on the stacks the node's text is using.
\ (SERVE) and what it calls keep to four cells of the data stack and four
\ entries of the return stack, its own call among them; what they need
\ from one operation to the next is in cells. (ROOM-SERVE) tries that much.
\ ( op -- how ) ask the fabric for the operation, and say how it went
: (DO) (WIRE-DO) b! !b (WIRE-HOW) b! @b ;
\ ( port -- ) what is asked next is about that port's wire, by its number.
\ A number that is no port's is no wire: every operation then answers 2.
: (WIRE!) (WIRE) b! !b ;
\ ( cells port -- how ) has the port's wire that many cells free? 0: it
\ has; 1: it has not; 2: no one is on that port. Only this node puts
\ messages on the wires that lead from it, so room found stays until it
\ uses it.
: (ROOM?) (WIRE!) (WIRE-A) b! !b 10 jump (DO)
\ ( -- ) ROOM FOR WHAT A WAIT DOES. A node that waits within text -- for
\ an answer, or for room to print -- passes on meanwhile what comes for
\ other nodes, on the stacks the text has left it: four cells of the data
\ stack and four entries of the return stack, (SERVE)'s. They are tried
\ before anything is taken off a wire or put on one: if they are not there
\ the fault comes here, and the text ends "Stack overflow" with nothing
\ half done (MESH.md 7c.7, 7d.4).
\ (ROOM-SERVE) tries just those, and is what a wait for room does each time
\ a message wakes it. (ROOM), which AWAIT does once before it waits, tries
\ six cells, as it did when a message was read a word at a time: the wait
\ ends in an error that leaves the stack as it is, and the line from the
\ console that broke it is then done on that stack, where printing needs
\ six (MESH.md 7c.7).
: (ROOM-SERVE)
0 0 0 0 drop drop drop drop
0 push 0 push 0 push 0 push pop drop pop drop pop drop pop drop ;
: (ROOM)
0 0 0 0 0 0 drop drop drop drop drop drop
0 push 0 push 0 push 0 push pop drop pop drop pop drop pop drop ;
\ ( to type -- ) the first six words of a message this node puts, in
\ (OUT-HDR): to, from, type, and the three that are carried: how many nodes
\ may pass it on, sixteen (the TTL: MESH.md 7b.3); ACL tag; sequence.
: (HDR)
push (OUT-HDR) a! !+ (ME) b! @b !+ pop !+ 16 !+ 0 !+ 0 !+ ;
\ ( text port -- how ) put the message whose seven words are in (OUT-HDR)
\ and whose text is at the word address given on the wire of the port, by
\ its number. How it went is the fabric's answer: 0 it is on the wire.
\ THE ROOM KEPT FOR AN ANSWER. While this node does text, (KEEP) is the
\ port its word of how the text ended will go by, and nothing else it puts
\ on that wire may take the last 8 cells: a message that would is refused
\ here, 1, as if the wire were full. With no text being done (KEEP) is -1.
: (PUT-ON)
push (WIRE-B) b! !b pop
dup (WIRE!)
(KEEP) a! @ xor if KEPT
GO: drop (OUT-HDR) (WIRE-A) b! !b 5 jump (DO)
KEPT: drop (OUT-HDR)+6 a! @ 3 + 2/ 2/ 15 + (WIRE-A) b! !b 10 (DO) if GO ;
\ REFUSALS (MESH.md 7b, 7d.4). A message this node cannot pass on is
\ dropped and counted in (LOST), and whoever waits on it is told, by a
\ message of type 4, a NACK, whose one word is the node the refused message
\ was for: its sender; or, for a node's answer (type 3), the node the
\ answer was for, which is the one that waits, about the node that
\ answered. The NACK is put at once. If it cannot go -- no way, no one on
\ the port, no room -- it is counted in (LOST) too, and that is the end of
\ it. Nothing is told for a NACK or for a GONE, type 5: there is no NACK
\ for a NACK.
\ ( -- ) the message the mark of the wire in (WIRE) is at, whose seven
\ words are in (IN), is refused. A refusal for this node itself -- its own
\ message came back to it -- is counted in (REFUSED) as one that came by a
\ wire would be; or, if it is about the node this one is waiting on,
\ (A-SELF) is set for AWAIT to find (quit.f18).
\ (WIRE) is not what it was afterwards: the NACK went by another.
\ If the drop does not drop -- the wire was cut after the message was looked
\ at, which let it go already -- nothing is counted and no one is told.
: (REFUSE)
4 (DO) if DROPPED drop ; \ it was not there to drop -- its wire has been cut: nothing is counted or told
DROPPED: drop
(LOST) a! @ 1 + !
(IN)+2 a! @ -4 + if NOT -1 + if NOT 2 + if ANSWER
drop (IN) a! @ (ONE) a! ! (IN)+1 a! @ jump TELL \ about whom it was for; to its sender
ANSWER: drop (IN)+1 a! @ (ONE) a! ! (IN) a! @ \ about the node that answered; to whom the answer was for
TELL: dup (ME) a! @ xor if SELF drop
dup 4 (HDR) 4 (OUT-HDR)+6 a! !
(WAY) (ONE) SWAP (PUT-ON) if SENT
drop (LOST) a! @ 1 + ! ;
SENT: drop ;
SELF: drop drop
(AWAIT-FROM) a! @ if COUNT (ONE) a! @ xor if MINE
COUNT: drop (REFUSED) a! @ 1 + ! ;
MINE: drop 1 (A-SELF) a! ! ;
NOT: drop ;
\ ( port -- bit ) the bit for a port, by its number, in a word of a bit to a port
: (WBIT)
push 1 pop if Z -1 + FOR 2* NEXT ;
Z: drop ;
\ ( -- ) A MESSAGE FOR ANOTHER NODE is passed on (MESH.md section 7): the
\ one the mark of the wire in (WIRE) is at, whose seven words are in (IN),
\ is moved, whole, to the wire that leads toward that node. It is refused
\ instead if it has been passed on as often as a message may be; or if
\ there is no way, or no one on the port.
\ WITH NO ROOM on that wire -- or none but the room kept on it, (KEEP) --
\ text, a NACK and a GONE are refused, at once. But what a node printed
\ (type 2) and its word of how text ended (type 3) are NOT let go for want
\ of room: the message is left where it is, on the wire it came by, and
\ gone past; what is behind it is served; and it is moved on a later pass,
\ when there is room. Printing waits; it is not lost (MESH.md 7d.1,
\ ruling 3). (H-PORT) and (H-NEED) are the port of the first message left
\ so on this pass and the cells it needs there: a node that then sleeps,
\ sleeps for that room, (SLEEP), and is woken by room on any wire.
\ (H-MASK) has a bit for each port something was left for: what is behind
\ it for the same port is left too, though it be shorter and would fit, so
\ that what a node printed goes on in the order it came.
\ HOW OFTEN. A message's fourth word is how many more nodes may pass it
\ on; a node sends it with 16, and a move takes one off. The node that
\ finds 1 there refuses it. A device sends it with 0, which is taken for
\ 16: so 0 down to -14 are passed on and -15 is refused. Anything else is
\ nothing a node or a device sent, and is refused.
: (PASS)
(IN)+3 a! @ -if POS
14 + -if OK jump SPENT
POS: if OK -1 + if SPENT -16 + -if SPENT
OK: drop
(IN) a! @ (WAY) (P-WAY) a! !
(IN)+6 a! @ 3 + 2/ 2/ 7 + \ the cells it takes,
(P-WAY) a! @ (KEEP) a! @ xor if KEPT drop jump NEED
KEPT: drop 8 + \ and the room kept, if it is that wire
NEED: (P-NEED) a! !
(P-WAY) a! @ -if WAY \ no way: refused
SPENT: drop jump (REFUSE)
WAY: (WBIT) (H-MASK) a! @ and if CLEAR \ something is left for that port already?
FULL: drop (IN)+2 a! @ -2 + if HOLD -1 + if HOLD jump SPENT \ no room: only output and answers wait
CLEAR: drop
(P-NEED) a! @ (P-WAY) a! @ (ROOM?) (S-WIRE) a! @ (WIRE!)
if GO -1 + if FULL jump SPENT \ no one on that port: refused
GO: drop (P-WAY) a! @ (WIRE-A) b! !b 3 (DO) if MOVED jump SPENT
MOVED: drop ;
HOLD: drop
(P-WAY) a! @ (WBIT) dup inv (H-MASK) a! @ and + !
(H-PORT) a! @ -if HELD drop (P-WAY) a! @ (H-PORT) a! ! (P-NEED) a! @ (H-NEED) a! ! 7 (DO) drop ;
HELD: drop 7 (DO) drop ;
\ ( -- ) SLEEP until a message comes -- or, if (SERVE) left a message
\ on a wire for want of room, until there is that room or a message comes
\ or any wire of this node's gains room (operation 9, MESH.md 7d.3).
: (SLEEP)
(H-PORT) a! @ -if ROOM drop 8 (DO) drop ;
ROOM: (WIRE!) (H-NEED) a! @ (WIRE-A) b! !b 9 (DO) drop ;
\ ( -- ) ONE PASS OVER EVERY WIRE THAT HAS A MESSAGE. What is for another
\ node is passed on, or refused; what is for this node is left where it
\ is. Fetching (WIRE-HAVE) is what tells the fabric this node has seen
\ what had come: a sleep after this is woken only by what comes later
\ (MESH.md 7d.3). (S-HAVE) keeps which wires they were, for whoever then
\ looks for what is this node's own, (MINE).
: (SERVE)
(WIRE-HAVE) b! @b dup (S-HAVE) a! ! (S-MASK) a! !
0 (S-WIRE) a! ! -1 (H-PORT) a! ! 0 (H-MASK) a! !
W: (S-MASK) a! @ if END
dup 2/ ! 1 and if NEXTW
drop (S-WIRE) a! @ (WIRE!) 6 (DO) drop
M: (S-WIRE) a! @ (WIRE!) (IN) (WIRE-A) b! !b 1 (DO) if LOOKED jump NEXTW
LOOKED: drop
(IN) a! @ (ME) a! @ xor if MINE drop (PASS) jump M
MINE: drop 7 (DO) drop jump M
NEXTW: drop (S-WIRE) a! @ 1 + ! jump W
END: drop ;
\ WHAT IS FOR THIS NODE is gone through after (SERVE), a message at a time:
\ (MINE0) begins, and each (MINE) puts the mark of a wire at the next
\ message for this node and its seven words in (IN). Whoever asked then
\ takes or drops that message -- the mark is then at the one that followed
\ -- or leaves it and goes past it, (SKIP). The wire is (S-WIRE).
\ ( -- ) begin with the wires (SERVE) found a message on
: (MINE0) (S-HAVE) a! @ (S-MASK) a! ! -1 (S-WIRE) a! ! 0 (S-ON) a! ! ;
\ ( -- flag ) the next message for this node; 0: there are no more
: (MINE)
L: (S-ON) a! @ if WIRE
drop (S-WIRE) a! @ (WIRE!) (IN) (WIRE-A) b! !b 1 (DO) if LOOKED
drop 0 (S-ON) a! ! jump L \ this wire has no more
LOOKED: drop (IN) a! @ (ME) a! @ xor if HIT
drop 7 (DO) drop jump L
HIT: drop -1 ;
WIRE: drop (S-WIRE) a! @ 1 + ! \ the next wire that had one
(S-MASK) a! @ if NONE
dup 2/ ! 1 and if NOT
drop (S-WIRE) a! @ (WIRE!) 6 (DO) drop 1 (S-ON) a! ! jump L
NOT: drop jump L
NONE: ;
\ ( -- ) go past the message (MINE) found: it stays on its wire
: (SKIP) (S-WIRE) a! @ (WIRE!) 7 (DO) drop ;
\ ( -- ) A TAKE DID NOT TAKE the message (MINE) found. The fabric takes
\ only the message last looked at (MESH.md 7d.3), so either the wire has
\ been cut -- and there is nothing there, or another message that has not
\ been looked at -- or the message cannot be taken at all. It is dropped,
\ and counted in (LOST); if it cannot be dropped either it is gone past.
\ Either way whoever goes through the messages next is at another one:
\ nothing goes round on one that will not be taken.
: (UNTAKEN)
(S-WIRE) a! @ (WIRE!) 4 (DO) if GONE drop jump (SKIP)
GONE: drop (LOST) a! @ 1 + ! ;
\ ( -- how ) take the message (MINE) found, which has one word of text:
\ its seven words stay in (IN), and its word goes to (ONE). 0: it is
\ taken. Anything else: it is not -- the wire was cut after the message
\ was looked at -- and (ONE) is not its word: nothing is to be done for it.
: (TAKE1) (S-WIRE) a! @ (WIRE!) (IN) (WIRE-A) b! !b (ONE) (WIRE-B) b! !b 2 jump (DO)
\ ( -- how ) WAIT UNTIL THE WIRE of the port (W-PORT) has (W-NEED) cells
\ free. 0: it has. 2: no one is on that port. The node sleeps until
\ there is room, or a message comes, or another wire of its own gains
\ room; woken with no room yet, it passes on what is for other nodes,
\ (SERVE), and sleeps again. It is the one thing a node waits to put:
\ what a text prints (MESH.md 7d.1, ruling 3).
\ NOTHING BREAKS THIS WAIT but the room coming or the wire being cut
\ (ruled 2026-10-08): text for this node that comes meanwhile, from its
\ console or anyone, stays on its wire and is done when this text has been
\ finished with. A text whose printing can never go, because a stuck node
\ is on the way, waits until that node is killed (MESH.md 7d.6).
: (WAIT-ROOM)
L: (W-PORT) a! @ (WIRE!) (W-NEED) a! @ (WIRE-A) b! !b 9 (DO)
if DONE -1 + if WOKEN drop 2 ;
WOKEN: drop (WIRE-HAVE) b! @b if QUIET \ no wire has a message: there is nothing to pass on,
drop (ROOM-SERVE) (SERVE) jump L \ and no more of the stacks is asked for than a wait needs
QUIET: drop jump L
DONE: ;
\ ( -- ) send what has been printed, to where (PRINT-TO) says, by the port
\ (PRINT-PORT): a message of type 2, its characters four to a word, the
\ first lowest. quit.f18 sets those two when text for this node arrives.
\ It waits for room on the wire, and for the 8 cells kept as well when the
\ wire is the one the answer goes by. The characters are made ready in
\ (OUT-TEXT), not where they are: until the message is on the wire the
\ buffer is as it was, and a fault on the way leaves it to be sent again.
\ The three cells after the last character are made zero first, so that
\ nothing printed earlier goes on the wire in the last word (they are in
\ the buffer, or the four free cells after it).
\ The three cells and two return entries this needs are tried first.
\ WITH NO ONE ON THE PORT -- when it waits for room, or when it comes to
\ put -- what was printed cannot be sent. While the text is being done
\ that is its error, 18; and the data stack is emptied first, as a fault
\ empties it. A word that raises an error has taken its own arguments
\ off; this one comes from under whatever word was printing, in the
\ middle of its work, and what that word had on the stack is nothing its
\ caller can use (as first built those values were left there). Once it has been finished with, what it printed
\ is let go and counted in (LOST), and the text is said to have ended in
\ an error: (LINE-STATUS), which is the word then sent of how it ended.
: (FLUSH-OUT)
(OUT^) a! @ (OUT) xor if NONE drop
0 0 0 drop drop drop 0 push 0 push pop drop pop drop
(OUT^) a! @ (OUT) - 3 + 2/ 2/ 7 +
(PRINT-PORT) a! @ (KEEP) a! @ xor if SAME drop jump NEED
SAME: drop 8 +
NEED: (W-NEED) a! ! (PRINT-PORT) a! @ (W-PORT) a! !
(WAIT-ROOM) if ROOM
NOONE: drop (QUIET) a! @ if TELL
drop (OUT) (OUT^) a! ! (LOST) a! @ 1 + ! 2 (LINE-STATUS) a! ! ;
TELL: drop DSTACK-DEPTH b! a !b NODE-ERROR b! 18 !b ; \ the data stack is emptied, as by a fault: see below
ROOM: drop
(PRINT-TO) a! @ 2 (HDR)
(OUT^) a! @ a! 0 !+ 0 !+ 0 !
(OUT^) a! @ (OUT) - dup (OUT-HDR)+6 a! !
3 + 2/ 2/ -1 + push (OUT-TEXT) pop (OUT) a!
FOR @+ @+ 8* + @+ 8* 8* + @+ 8* 8* 8* + over b! !b 1 + NEXT
drop
(OUT-TEXT) (PRINT-PORT) a! @ (PUT-ON) if SENT jump NOONE
SENT: drop (OUT) (OUT^) a! ! ;
NONE: drop ;
\ EMIT puts the character with what has been printed. Everything the node
\ prints goes through EMIT. A is kept: the words that print have always
\ been free to use it across an EMIT. As v3, only the low 8 bits of the
\ character are printed.
\ A BUFFER FOUND FULL is sent first. It is full when a flush of it ended
\ in a fault -- the stack too deep to begin a message -- and what is printed
\ next is that fault's own message: put where (OUT^) points, it would go
\ past the buffer's end, and (OUT^) would never again be at the end to be
\ flushed (MESH.md 7c.6).
set HDR-NFA here ", EMIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: EMIT ( c -- )
255 and a push push \ A, and then the character, to the return stack
(OUT^) b! @b (OUT)+256 xor if STALE drop jump PUT
STALE: drop (FLUSH-OUT)
PUT:
(OUT^) b! @b a! pop !+ a !b \ the character goes where (OUT^) points, which moves on
a (OUT)+256 xor if FULL drop pop a! ;
FULL: drop (FLUSH-OUT) pop a! ;
set HDR-NFA here ", KEY #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: KEY ( -- c )
L: CONSOLE-STATUS b! @b if WAIT drop CONSOLE-RX b! @b ;
WAIT: drop jump L
set HDR-NFA here ", CR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CR ( -- ) 10 jump EMIT
set HDR-NFA here ", SPACE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SPACE ( -- ) 32 jump EMIT
set HDR-NFA here ", COUNT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COUNT ( baddr -- baddr+1 c ) dup C@ push 1 + pop ;
set HDR-NFA here ", TYPE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: TYPE ( baddr u -- )
-if OK drop drop NODE-ERROR b! 1 !b ;
OK: if DONE over C@ EMIT push 1 + pop -1 + jump OK
DONE: drop drop ;
\ ( x -- ) up to four characters packed in one cell, the first in the low
\ byte: how the capsule prints its own short messages, a literal at a time.
: (EMIT4)
L: if DONE dup EMIT 8/ jump L
DONE: drop ;
\ ---- section 5.8: the number base ----------------------------------------
: (BASE) ( -- b ) \ BASE, or 10 when it is outside 2 .. 36
BASE b! @b dup -2 + -if L1 drop drop 10 ;
L1: drop dup -37 + -if L2 drop ;
L2: drop drop 10 ;
+233
View File
@@ -0,0 +1,233 @@
\ dict.f18 -- the dictionary: its space, its entries, and looking a name up.
\
\ DECOMPOSITION.md 5.12 and 5.13: HERE ALIGN ALLOT , C, 2, PAD LATEST, FIND ' ,
\ and the entry-field words >LINK LFA LINK> >NAME NFA NAME> CFA PFA >BODY
\ TRAVERSE SMUDGE HIDDEN. Part of the compiler capsule: it runs on the host
\ node. Rests on core.f18 and input.f18.
\
\ AN ENTRY. A word's execution address (xt) is the address of its code, and
\ everything else is found from it:
\
\ name the count byte, then the characters, four bytes to a cell,
\ padded with zeros to a whole cell
\ xt - 3 flags: 1 immediate, 2 hidden, 4 data
\ xt - 2 the word address of the name
\ xt - 1 the link: the xt of the entry before this one, 0 for the first
\ xt the code
\
\ A name holds at most 31 characters; longer ones are cut to 31 both when
\ defined and when looked up, so 31 characters are significant (FORTH-79).
\ A "data" word is one whose code is a single call to its run-time routine,
\ with its parameter field in the cell after it: xt + 1. For any other word
\ the parameter field is the code itself.
\
\ THE SPACE. DP is a byte address, so that C, can pack characters; HERE is
\ the next whole cell. An address unit is a cell (D-1): ALLOT counts cells.
\
\ Constants the loader supplies:
\ DP word address of the variable: the next free byte
\ (LATEST) word address of the variable: the xt of the newest entry of the
\ FORTH vocabulary, or 0
\ CONTEXT CURRENT word addresses of the variables: each holds the address
\ of a vocabulary's head cell -- the cell that holds the xt of
\ that vocabulary's newest entry. FORTH's head cell is (LATEST).
\
\ VOCABULARIES (FORTH-79). A name is looked up in the CONTEXT vocabulary and
\ then, if that is not FORTH, in FORTH. A new entry goes into the CURRENT
\ vocabulary: it is linked to that vocabulary's newest entry and becomes it.
\ DBASE DLIMIT byte addresses of the start and end of dictionary space
\ PAD byte address of the scratch area for strings, 84 bytes or more
\ (D) word address of five cells of scratch for this file
\ (WORD-DEFINED) (WORD-FORGOTTEN) word addresses of two variables: see
\ "telling the kernel" below
\ PAD is in line.
macro 4* 2* 2* endmacro
macro 4/ 2/ 2/ endmacro
macro OR over inv and xor endmacro
\ ---- the space (5.12) ------------------------------------------------------
\ These reach DP through B and leave A alone, so that , and C, can keep what
\ they are storing in A while the space is taken: nothing of theirs is then
\ on the data stack under (DP+), which itself needs three cells (D-2).
: (DERR) ( -- 0 ) NODE-ERROR b! 5 !b 0 ; \ dictionary full
\ ( n -- flag ) move DP by n bytes if it stays inside the dictionary space
\ and say -1; otherwise leave it, set NODE-ERROR and say 0. The two
\ subtractions are x + ~y + 1, which unlike the in-line - needs no return
\ entry: these words are called at the bottom of long chains of calls.
: (DP+)
DP b! @b +
dup DBASE inv + 1 + -if LOW drop drop jump (DERR) \ new - DBASE
LOW: drop dup inv DLIMIT + 1 + -if HIGH drop drop jump (DERR) \ DLIMIT - new
HIGH: drop DP b! !b -1 ;
set HDR-NFA here ", HERE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: HERE ( -- addr ) DP b! @b 3 + 4/ ;
set HDR-NFA here ", ALIGN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ALIGN ( -- ) DP b! @b 3 + -4 and !b ;
set HDR-NFA here ", ALLOT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ALLOT ( n -- ) ALIGN 4* (DP+) drop ;
\ , calls nothing: the code generator calls it from as deep as anything goes.
set HDR-NFA here ", , #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: , ( x -- )
a!
DP b! @b 3 + -4 and \ the next whole cell, as a byte address
dup inv DLIMIT + -3 + -if ROOM \ DLIMIT - (it + 4)
drop drop NODE-ERROR b! 5 !b ;
ROOM: drop dup 4 + !b \ DP is past it
4/ b! a !b ;
set HDR-NFA here ", C, #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: C, ( c -- )
a! 1 (DP+) if FULL
drop a DP b! @b -1 + jump C!
FULL: drop ;
set HDR-NFA here ", 2, #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2, ( lo hi -- ) SWAP , , ; \ the low cell first, as v3
set HDR-NFA here ", LATEST #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LATEST ( -- xt ) CURRENT a! @ a! @ ; \ the newest entry of the CURRENT vocabulary
\ ---- the fields of an entry (5.13) -----------------------------------------
: (FLAGS) ( xt -- addr ) -3 + ;
set HDR-NFA here ", >LINK #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: >LINK ( xt -- addr ) -1 + ;
set HDR-NFA here ", LFA #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LFA ( xt -- addr ) jump >LINK
set HDR-NFA here ", LINK> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LINK> ( addr -- xt ) a! @ ;
set HDR-NFA here ", >NAME #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: >NAME ( xt -- baddr ) -2 + a! @ 4* ;
set HDR-NFA here ", NFA #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NFA ( xt -- baddr ) jump >NAME
set HDR-NFA here ", NAME> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NAME> ( baddr -- xt ) dup C@ 31 and 4 + 4/ push 4/ pop + 3 + ;
set HDR-NFA here ", CFA #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CFA ( xt -- xt ) ;
set HDR-NFA here ", PFA #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: PFA ( xt -- addr ) dup (FLAGS) a! @ 4 and if CODE drop 1 + ; CODE: drop ;
set HDR-NFA here ", >BODY #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: >BODY ( xt -- addr ) jump PFA
\ ( baddr n -- baddr' ) as v3: for n > 0, from a name's count byte to the
\ byte after its last character; otherwise the address unchanged.
set HDR-NFA here ", TRAVERSE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: TRAVERSE
-if NN drop ;
NN: if ZERO drop dup C@ 31 and + 1 + ;
ZERO: drop ;
set HDR-NFA here ", SMUDGE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SMUDGE ( -- ) LATEST if NONE (FLAGS) a! @ 2 xor ! ; NONE: drop ;
set HDR-NFA here ", HIDDEN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: HIDDEN ( -- ) LATEST if NONE (FLAGS) a! @ 2 OR ! ; NONE: drop ;
\ ---- telling the kernel (docs/v4.0.0/ENGINE.md 3b) ------------------------------
\ A word's code is here on the node; its accounts are a record its kernel
\ keeps. So the kernel has to be told of every entry that is made and of
\ every entry that goes. An entry is made in one place, (HEADER); entries go
\ in two, FORGET and COLD (system.f18). Each tells through a variable that
\ holds the xt of a word to run, or 0 for a node whose host keeps no records:
\ (WORD-DEFINED) ( xt -- ) an entry has been made; its code will be at xt
\ (WORD-FORGOTTEN) ( w -- ) every entry at word address w or above is gone
\ On the bare-metal system the kernel puts words of its own there.
\ ( -- ) tell of the entry just made, whose code starts at HERE
: (DEFINED)
(WORD-DEFINED) b! @b if NONE HERE SWAP push ;
NONE: drop ;
\ ( w -- ) tell that the entries from word address w up have gone
: (FORGOTTEN)
(WORD-FORGOTTEN) b! @b if NONE push ;
NONE: drop drop ;
\ ---- making an entry -------------------------------------------------------
\ (D)+0 where the name starts (D)+1 the name being looked up
\ (D)+2 the name being copied, or the entry being looked at
\ (D)+3 a count (D)+4 whether a lookup has gone on to FORTH
\ ( -- bytes ) what an entry for a name of (D)+3 characters takes: its name
\ cells and three more
: (NEED) (D)+3 a! @ 4 + -4 and 12 + ;
\ ( baddr -- ) an entry for the counted string at baddr; its code starts at
\ HERE afterwards. An empty name, or no room, makes nothing and sets
\ NODE-ERROR.
: (HEADER)
dup (D)+2 a! ! \ (CLIP), in line
C@ -32 + -if LONG drop jump CLIPPED
LONG: drop 31 (D)+2 a! @ C!
CLIPPED:
(D)+2 a! @ C@ if EMPTY \ len
(D)+3 a! !
ALIGN
(NEED) (DP+) if FULL drop \ there is room;
(NEED) NEGATE (DP+) drop \ DP back where it was
HERE (D) a! ! \ where the name starts
(D)+3 a! @ C,
L: (D)+3 a! @ if DONE -1 + !
(D)+2 a! @ 1 + dup ! C@ C,
jump L
DONE: drop
P: DP b! @b 3 and if ALIGNED drop 0 C, jump P
ALIGNED: drop
0 , (D) a! @ , LATEST ,
HERE CURRENT a! @ a! !
jump (DEFINED)
FULL: drop ; \ (DP+) has set NODE-ERROR
EMPTY: drop NODE-ERROR b! 6 !b ; \ name missing
\ ---- looking a name up -----------------------------------------------------
\ ( baddr -- xt | 0 ) the newest visible entry named by the counted string.
\ Written out in one piece -- the string cut to 31, each entry's flags and
\ name fetched, the two names compared byte by byte -- so that the only call
\ it makes is C@: it is called from the interpreter for every word of every
\ line, with the user's return stack beneath it.
: (LOOKUP)
dup (D)+1 a! ! \ cut the string to 31 characters
C@ -32 + -if LONG drop jump CUT
LONG: drop 31 (D)+1 a! @ C!
CUT:
0 (D)+4 a! ! \ not yet on to FORTH
CONTEXT a! @ a! @
L: if END
(D)+2 a! !
(D)+2 a! @ -3 + a! @ 2 and if VISIBLE drop jump OLDER
VISIBLE: drop
(D)+2 a! @ -2 + a! @ 4* (D) a! ! \ its name
(D)+1 a! @ C@ 1 + (D)+3 a! ! \ the count byte and the characters
C: (D)+3 a! @ if SAME -1 + dup ! \ k
dup (D) a! @ + C@ \ k c1
SWAP (D)+1 a! @ + C@ \ c1 c2
xor if EQ drop jump OLDER
EQ: drop jump C
SAME: drop (D)+2 a! @ ;
OLDER: (D)+2 a! @ -1 + a! @ jump L
END: (D)+4 a! @ if FIRST drop ; \ FORTH has been searched: not found
FIRST: drop -1 (D)+4 a! !
CONTEXT a! @ (LATEST) xor if ISFORTH \ CONTEXT is FORTH: that was it
drop drop (LATEST) a! @ jump L
ISFORTH: drop ;
\ ( -- xt | 0 ) FORTH-79: the compilation address of the next word in the
\ input stream, or 0 if it is not in the dictionary.
set HDR-NFA here ", FIND #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: FIND 32 WORD jump (LOOKUP)
\ ( -- addr ) FORTH-79: the parameter field address of the next word in the
\ input stream. Not found is an error: 0, and NODE-ERROR is set. This is '
\ when interpreting; compile.f18 adds what ' does when compiling.
\ ( -- 0 ) say that the word WORD has just left is not known, as v3 does:
\ UNKNOWN WORD: 'xxx'
: (UNKNOWN)
$4E4B4E55 (EMIT4) $204E574F (EMIT4) $44524F57 (EMIT4) $27203A (EMIT4)
WBUF COUNT TYPE 39 EMIT CR
NODE-ERROR b! -1 !b 0 ;
: (') 32 WORD (LOOKUP) if MISSING jump PFA
MISSING: drop jump (UNKNOWN)
+36
View File
@@ -0,0 +1,36 @@
\ end.f18 -- the end of the system's source: the state it is switched on in.
\
\ What was set in C when the nucleus was prebuilt (v4/tools/mkimage.c, gone
\ since the machine's ROM assembles the system), said with the
\ ROM's directives (MACHINE.md, the ROM's language). RAM is all zeroes
\ when the machine starts, so only what is not zero is stored. Then the
\ image record (map: (IMG)), the addresses a host needs (v4/image.h), and
\ start: the ROM clears what it used and the node waits for a message.
\ the dictionary: empty, at DBASE; the newest entry, the nucleus's last
store DP DBASE
store (LATEST) HDR-LINK
\ the control-flow stack, the number base, the log level
store (CFP) CFBASE
store BASE 10
store (LOG-LEVEL) 2
\ one vocabulary, FORTH, whose head cell is LATEST; new words go into it
store CONTEXT (LATEST)
store CURRENT (LATEST)
\ the text interpreted is the terminal's
store (SRC) TIB
\ what COLD comes back to, and the lowest FORGET goes: the nucleus as it is
store (BOOT) DBASE
store (BOOT)+1 HDR-LINK
store FENCE DICT-W
\ nothing has ended badly; nothing has been printed
store (LINE-STATUS) 1
store (OUT^) (OUT)
\ the image record: where the node waits, its fault table, KEY's code
store (IMG) &(IDLE)
store (IMG)+1 &(FAULTS)
store (IMG)+2 &KEY
store (IMG)+3 &CR
start (IDLE)
+229
View File
@@ -0,0 +1,229 @@
\ forth.f18 -- the first words of the FORTH vocabulary: the ones that are
\ opcodes or short runs of them, and the variables that are in-line addresses.
\
\ Each is the definition DECOMPOSITION.md gives (sections 4, 5.1 - 5.5, 5.18).
\ A word flagged inline is copied into a definition in place of a call; the
\ ones that touch the return stack are compile-only as well. Rests on core.f18,
\ compile.f18's loader constants, and quit.f18, which the division words leave
\ through when the divisor is zero. (F) is seven cells of scratch for
\ this file.
\ ---- stack ----
set HDR-NFA here ", DUP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : DUP dup ;
set HDR-NFA here ", DROP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : DROP drop ;
set HDR-NFA here ", OVER #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : OVER over ;
set HDR-NFA here ", SWAP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : SWAP' SWAP ;
set HDR-NFA here ", ROT #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : ROT' ROT ;
set HDR-NFA here ", -ROT #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : -ROT SWAP push SWAP pop ;
set HDR-NFA here ", ?DUP #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : ?DUP if Z dup ; Z: ;
set HDR-NFA here ", 2DUP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2DUP over over ;
set HDR-NFA here ", 2DROP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2DROP drop drop ;
\ ---- the stack as a whole (D-16) ----
\ DEPTH reads the stack register. PICK and ROLL reach under the top of a
\ stack that has no addresses: the values above the one wanted are set aside
\ in (S), and put back. (F)+3 how many are still to set aside, (F)+4 where
\ the next goes, (F)+5 the value wanted, (F)+6 how many are set aside. With n on top of a stack that is
\ otherwise one short of full there is no room at all, so until a value has been set aside nothing here pushes
\ anything while n is still there, and never more than one cell after.
\ FORTH-79: how many values were on the stack before DEPTH
set HDR-NFA here ", DEPTH #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DEPTH DSTACK-DEPTH b! @b ;
\ ( name -- ) "xxxx: Invalid index", and the line ends with ERROR
: (INDEX)
R-CLEAR (EMIT4) $6E49203A (EMIT4) $696C6176 (EMIT4) $6E692064 (EMIT4) $786564 (EMIT4) CR
2 jump (DONE)
\ ( x1 .. xn-1 -- ) A: n, which is 2 or more. Set the n-1 values above
\ the n-th aside. If there are not that many, the pop that finds the stack
\ empty is a fault: "Stack underflow". The count is taken down only after a
\ value has been set aside, when there is room to do the arithmetic.
: (DIG)
(F)+3 b! a !b
(F)+4 b! (S) !b
(F)+6 b! 0 !b
L: (F)+4 b! @b a! !+
a (F)+4 b! !b
(F)+6 b! @b 1 + !b
(F)+3 b! @b -1 + dup !b
-1 + if DONE drop jump L
DONE: drop ;
\ ( -- x1 .. xk ) put them back. The test that ends it pushes one cell:
\ after the last value is back the stack may be one short of full.
: (BURY)
L: (F)+6 b! @b if DONE -1 + !b
(F)+4 a! @ -1 + dup ! a! @
jump L
DONE: drop ;
\ ( n -- x ) FORTH-79: a copy of the n-th value, not counting n itself.
\ 1 PICK is DUP, 2 PICK is OVER. n less than one is an error.
set HDR-NFA here ", PICK #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: PICK
-if POS jump BAD
POS: if BAD
a! a 2/ if ONE drop \ n is 1 when half of it is 0
(DIG) dup (F)+5 a! ! (BURY) (F)+5 a! @ ;
ONE: drop dup ;
BAD: drop $4B434950 jump (INDEX)
\ ( n -- ) FORTH-79: the n-th value, not counting n itself, is taken out
\ and put on top. 3 ROLL is ROT, 2 ROLL is SWAP, 1 ROLL does nothing. n
\ less than one is an error.
set HDR-NFA here ", ROLL #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ROLL
-if POS jump BAD
POS: if BAD
a! a 2/ if ONE drop
(DIG) (F)+5 a! ! (BURY) (F)+5 a! @ ;
ONE: drop ;
BAD: drop $4C4C4F52 jump (INDEX)
\ ---- return stack: in line, and only inside a definition ----
set HDR-NFA here ", >R #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : >R push ;
set HDR-NFA here ", R> #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : R> pop ;
set HDR-NFA here ", R@ #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : R@ pop dup push ;
set HDR-NFA here ", I #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : I pop dup push ;
set HDR-NFA here ", J #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : J pop pop pop dup push a! push push a ;
set HDR-NFA here ", LEAVE #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LEAVE pop pop drop dup push push ;
set HDR-NFA here ", UNLOOP #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : UNLOOP pop drop pop drop ;
\ ---- memory ----
set HDR-NFA here ", @ #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : FETCH a! @ ;
set HDR-NFA here ", ! #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : STORE a! ! ;
set HDR-NFA here ", +! #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : +! a! @ + ! ;
set HDR-NFA here ", CELLS #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : CELLS ; \ an address unit is a cell (D-1)
\ ---- arithmetic ----
set HDR-NFA here ", + #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : PLUS + ;
set HDR-NFA here ", - #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : MINUS - ;
\ The low cell of the product, by N steps of +* with nothing but the count on
\ the return stack. UM* drop gives the same cell but needs two more return
\ entries, which a word inside two DO loops does not have (D-2). The low
\ cell is exact: what +* loses at the top of T (D-3) takes N shifts to reach
\ the bit that moves into A, and the loop ends first.
set HDR-NFA here ", * #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : STAR a! 0 N-1 FOR +* UNEXT drop drop a ;
set HDR-NFA here ", NEGATE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : NEGATE' NEGATE ;
set HDR-NFA here ", 1+ #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 1+ 1 + ;
set HDR-NFA here ", 1- #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 1- -1 + ;
set HDR-NFA here ", 2+ #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2+ 2 + ;
set HDR-NFA here ", 2- #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2- -2 + ;
set HDR-NFA here ", 2* #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : TWO* 2* ;
set HDR-NFA here ", 2/ #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : TWO/ 2/ ;
\ ---- division (sections 4 and 5.6) ----
\ Division by zero is guarded (D-15): each word tests its divisor before it
\ does anything else, and a zero divisor prints v3's message --
\ /: Division by zero
\ -- and ends the line with ERROR, from however deep, as an address fault
\ does. The word's operands are taken off the stack, as v3 takes them, and
\ its caller is not returned to.
\ ( name2 name1 -- ) the word's name: its first four characters, and the
\ rest or 0 (EMIT4). The return stack is emptied before anything is called:
\ the word may have been run with it full.
: (DIV0)
R-CLEAR (EMIT4) (EMIT4) $6944203A (EMIT4) $69736976 (EMIT4) $62206E6F (EMIT4) \ ": Division b"
$657A2079 (EMIT4) $6F72 (EMIT4) CR \ "y zero"
2 jump (DONE)
\ ( d n -- rem quot ) truncating toward zero: the quotient has the sign of
\ d xor n, the remainder the sign of d. This is section 4's SM/REM with its
\ UM/MOD -- restoring division, one step a bit, the divisor in A -- written
\ into it, and the two signs kept in (F) where section 4 has them on the
\ return stack. A word that divides is then four return entries deep, not
\ eight, so division can be used inside words that other words call (D-2).
\ The answer is the same. Exact when the quotient fits a cell; its callers
\ have seen to it that n is not zero.
: SM/REM
over over xor (F) a! ! \ the quotient's sign, in its top bit
over (F)+1 a! ! \ the remainder's
-if L0 inv 1 + L0: a! \ A: |n|
-if L1 DNEGATE L1: \ |d|
N-1 FOR
-if S0
2* over -if S1 drop 1 + jump S2
S1: drop S2: push 2* pop
jump SUB
S0:
2* over -if S3 drop 1 + jump S4
S3: drop S4: push 2* pop
dup a xor -if S5
drop -if NOSUB jump SUB
S5: drop dup inv a + inv -if S6
drop jump NOSUB
S6: push drop pop jump SETBIT
SUB: inv a + inv
SETBIT: push 1 + pop
NOSUB:
NEXT
over push push drop pop pop \ urem uquot
(F)+1 a! @ -if L2 drop push inv 1 + pop jump L3 L2: drop L3:
(F) a! @ -if L4 drop inv 1 + ; L4: drop ;
set HDR-NFA here ", S>D #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: S>D ( n -- d ) dup -if P drop -1 ; P: drop 0 ;
\ The product's sign waits in (F), not on the return stack, for the same
\ reason as SM/REM's.
set HDR-NFA here ", M* #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: M* ( n1 n2 -- d )
over over xor (F) a! ! -if A inv 1 + A: push -if B inv 1 + B: pop UM*
(F) a! @ -if P drop jump DNEGATE P: drop ;
\ ( n1 n2 n3 -- rem quot ) n1 * n2 as a double, divided by n3, which is
\ not zero. M* is written in, and n3 waits in (F)+2, so that the multiply
\ is as few return entries down as it can be.
: (*/MOD)
(F)+2 a! !
over over xor (F) a! ! -if A inv 1 + A: push -if B inv 1 + B: pop UM*
(F) a! @ -if P drop DNEGATE jump Q P: drop Q:
(F)+2 a! @ jump SM/REM
set HDR-NFA here ", /MOD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: /MOD ( n1 n2 -- rem quot )
if Z push S>D pop jump SM/REM
Z: drop drop 0 $444F4D2F jump (DIV0)
set HDR-NFA here ", / #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: / ( n1 n2 -- quot )
if Z push S>D pop SM/REM NIP ;
Z: drop drop 0 $2F jump (DIV0)
set HDR-NFA here ", MOD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: MOD ( n1 n2 -- rem )
if Z push S>D pop SM/REM drop ;
Z: drop drop 0 $444F4D jump (DIV0)
set HDR-NFA here ", */MOD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: */MOD ( n1 n2 n3 -- rem quot )
if Z jump (*/MOD)
Z: drop drop drop $44 $4F4D2F2A jump (DIV0)
set HDR-NFA here ", */ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: */ ( n1 n2 n3 -- quot )
if Z (*/MOD) NIP ;
Z: drop drop drop 0 $2F2A jump (DIV0)
set HDR-NFA here ", M/MOD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: M/MOD ( d n -- rem quot )
if Z jump SM/REM
Z: drop drop drop $44 $4F4D2F4D jump (DIV0)
\ ---- logic and comparison ----
set HDR-NFA here ", AND #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : AND and ;
set HDR-NFA here ", XOR #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : XOR xor ;
set HDR-NFA here ", OR #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : OR' OR ;
set HDR-NFA here ", 0= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 0= if L1 drop 0 ; L1: drop -1 ;
set HDR-NFA here ", 0< #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 0< -if L1 drop -1 ; L1: drop 0 ;
set HDR-NFA here ", NOT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : NOT jump 0=
set HDR-NFA here ", = #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : EQUALS xor jump 0=
set HDR-NFA here ", < #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LESS
over over xor -if SAME drop drop jump 0<
SAME: drop - jump 0<
set HDR-NFA here ", > #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : GREATER SWAP jump LESS
\ ---- in-line addresses and constants ----
set HDR-NFA here ", BL #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : BL' BL ;
set HDR-NFA here ", TIB #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : TIB' TIB ;
set HDR-NFA here ", >IN #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : >IN' >IN ;
set HDR-NFA here ", SPAN #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : SPAN' SPAN ;
set HDR-NFA here ", BASE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : BASE' BASE ;
set HDR-NFA here ", PAD #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : PAD' PAD ;
set HDR-NFA here ", STATE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : STATE' STATE ;
+217
View File
@@ -0,0 +1,217 @@
\ input.f18 -- reading a line and splitting it into words and numbers.
\
\ DECOMPOSITION.md 5.9: TIB >IN SPAN SOURCE BL EXPECT QUERY WORD ENCLOSE
\ CONVERT NUMBER, and the comment words ( and \ of 5.15 (named PAREN and
\ BACKSLASH here, since the text assembler reads those two characters as its
\ own comments; the dictionary will give them their names). Part of the compiler
\ capsule: it runs on the host node. Rests on core.f18.
\
\ Constants the loader supplies:
\ TIB byte address of the text input buffer; QUERY fills at most 81 bytes
\ >IN word address of the variable: offset in TIB of the next character
\ SPAN word address of the variable: how many characters the last
\ EXPECT or QUERY read
\ WBUF byte address of WORD's buffer, 257 bytes
\ (P) word address of eight cells of scratch for this file
\ (SRC) word address of the variable: the byte address of the text being
\ interpreted. QUERY makes it TIB; LOAD (blocks.f18) makes it a
\ block buffer. >IN is an offset from it and SPAN its length.
\ (SRC-HOOK) word address of a variable: 0, or the address of a word
\ that WORD calls before it looks at the text, to make sure (SRC)
\ is right. LOAD puts one there: a block buffer can be given to
\ another block between one word of the text and the next.
\ BLK word address of the variable: the block being interpreted, or
\ 0 for the terminal (FORTH-79)
\ TIB >IN SPAN and BL are in-line: written in a definition they are literals.
macro BL 32 endmacro
\ ( -- baddr u ) the input buffer and how much of it is in use
set HDR-NFA here ", SOURCE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SOURCE (SRC) a! @ SPAN a! @ -if P drop 0 P: ;
\ ( baddr n -- ) FORTH-79: characters from the terminal are stored from
\ baddr upward until a new-line or until n have been received; the new-line
\ is taken but not stored. A zero is added after the text, so the buffer
\ must hold n + 1 bytes. No action for n <= 0. SPAN is how many characters
\ were stored (SPAN is not FORTH-79; v3 has it). A line longer than n leaves
\ the rest, its new-line included, to be read next.
\ It is what the prompt reads every line with, with whatever the user has left
\ on the stack beneath it, so it works in (P) -- (P)+0 where the next
\ character goes, (P)+1 how many more may come, (P)+2 where the first went --
\ and has at most three cells of its own on the data stack (D-2).
set HDR-NFA here ", EXPECT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: EXPECT
-if NN drop drop ; \ n < 0
NN: if ZERO
(P)+1 a! ! dup (P)+2 a! ! (P) a! !
L: (P)+1 a! @ if END drop
KEY dup -10 + if NL drop \ c
(P) a! @ C!
(P) a! @ 1 + ! (P)+1 a! @ -1 + !
jump L
NL: drop drop jump FIN
END: drop
FIN: 0 (P) a! @ C!
(P) a! @ (P)+2 a! @ - SPAN a! ! ;
ZERO: drop drop ;
\ ( -- ) FORTH-79: up to 80 characters, or a line, into TIB; >IN to 0.
set HDR-NFA here ", QUERY #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: QUERY TIB (SRC) a! ! TIB 80 EXPECT 0 >IN a! ! ;
\ ---- WORD ------------------------------------------------------------------
\ WORD is called from deep inside the interpreter and compiler, with whatever
\ the user has on the stacks beneath it, and the stacks are ten and nine deep
\ (D-2). So everything it works on is in (P), and it never has more than
\ three cells of its own on the data stack:
\ (P)+0 the delimiter (P)+1 the length of the text in TIB
\ (P)+2 the word's length (P)+3 how much of it is still to be copied
\ (P)+6 where it is in TIB (P)+7 where the word starts
\ (CONVERT and NUMBER use (P)+2 .. (P)+5; they and WORD never run inside
\ each other.)
\ ( -- c ) the character WORD is at. A zero reads as a blank when words
\ are being split at blanks: a block that has never been written is all
\ zeros, and so is the end of one whose lines were put there one at a time.
: (SRC@)
(P)+6 a! @ (SRC) a! @ + C@ if Z ;
Z: drop (P) a! @ -32 + if B drop 0 ;
B: drop 32 ;
\ In line, not called: WORD may have only a few return entries to spare.
macro (LEFT) (P)+6 a! @ (P)+1 a! @ - endmacro \ ( -- d ) d < 0 while inside the text
macro (CH) (SRC@) (P) a! @ xor endmacro \ ( -- x ) x = 0 at a delimiter
macro (STEP) (P)+6 a! @ 1 + ! endmacro
\ ( c -- baddr ) FORTH-79: characters are taken from TIB until the
\ delimiter c or the end of the text, leading delimiters ignored, and stored
\ in WBUF as a counted string. The delimiter met -- c, or a zero if the text
\ ran out -- is stored after them and is not counted. >IN is left just past
\ that delimiter. With nothing left the count is 0. The count is a byte,
\ so a word longer than 255 characters is cut to 255.
\ The three parts of WORD. The first is called and returns before anything
\ else is; the last is jumped to; so WORD's calls of C@ and C! are no deeper
\ than if it were written in one piece.
: (WORD-SET) ( c -- )
255 and (P) a! !
(SRC-HOOK) a! @ if NONE push ex \ call it: ex comes back to the next word
jump HOOKED
NONE: drop
HOOKED:
SPAN a! @ -if A drop 0 A: (P)+1 a! !
>IN a! @ -if B drop 0 B: (P)+6 a! ! ;
: (WORD-TAKE) ( -- baddr )
(P)+6 a! @ (P)+7 a! ! \ where it starts
SC: (LEFT) -if SCE drop (CH) if SCE drop (STEP) jump SC \ up to a delimiter
SCE: drop
(P)+6 a! @ (P)+7 a! @ - \ its length
dup -256 + -if CAP drop jump FITS CAP: drop drop 255 FITS:
dup (P)+2 a! ! (P)+3 a! !
(P)+2 a! @ WBUF C!
\ copy it, last character first
CP: (P)+3 a! @ if COPIED -1 + dup ! \ k
dup (P)+7 a! @ + (SRC) a! @ + C@ \ k c
SWAP WBUF+1 + C!
jump CP
COPIED: drop
(LEFT) -if RANOUT
drop (P) a! @ (P)+2 a! @ WBUF+1 + C! \ the delimiter after the text
(P)+6 a! @ 1 + >IN a! ! WBUF ;
RANOUT: drop 0 (P)+2 a! @ WBUF+1 + C!
(P)+6 a! @ >IN a! ! WBUF ;
set HDR-NFA here ", WORD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: WORD
(WORD-SET)
SK: (LEFT) -if SKE drop (CH) if SKS drop jump (WORD-TAKE) \ past delimiters
SKS: drop (STEP) jump SK
SKE: drop jump (WORD-TAKE)
\ ( c -- baddr ) as WORD, but leading delimiters are not ignored: the text
\ starts at >IN, and may be empty. This is what ." needs: ." " is an
\ empty string, where WORD would step over its closing quote.
: (PARSE) (WORD-SET) jump (WORD-TAKE)
\ ---- ENCLOSE ---------------------------------------------------------------
\ (P)+0 the delimiter, (P)+1 the string's address.
: (E?) ( i -- i k ) \ k: 0 at the end of the string, 1 at a delimiter, else 2
dup (P)+1 a! @ + C@ if END (P) a! @ xor if DEL drop 2 ;
DEL: drop 1 ;
END: drop 0 ;
: (ESKIP) ( i -- i' ) L: (E?) -1 + if S drop ; S: drop 1 + jump L
: (ESCAN) ( i -- i' ) L: (E?) -2 + if S drop ; S: drop 1 + jump L
\ ( baddr c -- baddr n1 n2 n3 ) in the zero-terminated string at baddr:
\ n1 the offset of the first character that is not c, n2 the offset of the
\ first c after it, n3 the offset of the first character after that run of c.
set HDR-NFA here ", ENCLOSE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ENCLOSE
255 and (P) a! ! dup (P)+1 a! !
0 (ESKIP) dup (ESCAN) dup (ESKIP) ;
\ ---- CONVERT and NUMBER ----------------------------------------------------
\ ( c -- n ) the value of the digit c, 0 .. 35, in either case; -1 if none
: (DIGIT)
dup -48 + -if GE0 drop drop -1 ;
GE0: drop dup -58 + -if GT9 drop -48 + ;
GT9: drop dup -65 + -if GEA drop drop -1 ;
GEA: drop dup -91 + -if GTZ drop -55 + ;
GTZ: drop dup -97 + -if GEa drop drop -1 ;
GEa: drop dup -123 + -if GTz drop -87 + ;
GTz: drop drop -1 ;
\ ( d1 baddr1 -- d2 baddr2 ) FORTH-79: the characters from baddr1 + 1 on are
\ taken as digits in the current BASE, each accumulated into the double after
\ it is multiplied by BASE, until one is not a digit; baddr2 is its address.
\ (P)+2 holds the digit while the double is multiplied and (P)+5 the address,
\ so nothing waits on the return stack across the calls.
set HDR-NFA here ", CONVERT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CONVERT
L: 1 + dup (P)+5 a! ! C@ (DIGIT) \ lo hi n
-if DIG drop (P)+5 a! @ ;
DIG: dup (BASE) - -if BIG
drop (P)+2 a! ! \ lo hi
(BASE) UM* drop \ lo hi*base
SWAP (BASE) UM* \ hi*base plo phi
push SWAP pop + \ plo hi'
(P)+2 a! @ 0 D+
(P)+5 a! @ jump L
BIG: drop drop (P)+5 a! @ ;
\ ( baddr -- d flag ) the counted string at baddr as a signed double in the
\ current BASE, and -1; it may begin with a minus sign. If it is empty, is
\ only a sign, or holds anything that is not a digit: 0 0 and 0. The character after the string must not be a digit
\ (WORD puts the delimiter or a zero there); if it is, that too is reported
\ as an error. (P)+3 the address of its last character, (P)+4 the sign.
: (NUMBER?)
dup C@ if ERR2
over + (P)+3 a! ! \ baddr
dup 1 + C@ -45 + if NEG
drop 0 (P)+4 a! ! jump GO
NEG: drop -1 (P)+4 a! ! 1 +
dup (P)+3 a! @ xor if ERR2 drop
GO: push 0 0 pop CONVERT \ lo hi baddr2
(P)+3 a! @ 1 + xor if FINE
drop drop drop jump ERR0
FINE: drop (P)+4 a! @ if POS drop DNEGATE -1 ;
POS: drop -1 ;
ERR2: drop drop
ERR0: 0 0 0 ;
\ ( baddr -- d ) FORTH-79. What is not a number gives 0 and sets NODE-ERROR.
set HDR-NFA here ", NUMBER #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NUMBER
(NUMBER?) if BAD drop ;
BAD: drop NODE-ERROR b! 2 !b ;
\ ---- comments (5.15) -------------------------------------------------------
\ PAREN skips to the closing parenthesis; BACKSLASH skips the rest of the line.
set HDR-NFA here ", ( #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: PAREN 41 WORD drop ;
set HDR-NFA here ", \ #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BACKSLASH
BLK a! @ if TERM drop >IN a! @ -64 and 64 + ! ;
TERM: drop SPAN a! @ >IN a! ! ;
+72
View File
@@ -0,0 +1,72 @@
\ log.f18 -- logging, as v3: a message has a level, and is printed if the
\ level is at or below LOG-LEVEL.
\
\ DECOMPOSITION.md 5.25: the level constants LOG-ERROR LOG-WARN LOG-INFO
\ LOG-TEST LOG-DEBUG (0 .. 4), LOG-LEVEL! LOG-LEVEL@, LOG-ERROR" ... LOG-DEBUG"
\ and LOG-ERROR-STR ... LOG-DEBUG-STR. Part of the compiler capsule; rests
\ on core.f18, codegen.f18 and quit.f18.
\
\ WHAT IS PRINTED is v3's line without its time of day, which a node has
\ not got: the level's colour, the level's name and a colon, the colour off,
\ the text, a new line --
\ ESC [32m INFO: ESC [0m text
\ On the mesh a message will go to the recorder's log ring (5.25); until
\ then it goes to the console.
\
\ Constants the loader supplies:
\ (LOG-LEVEL) word address of the variable: 2, LOG-INFO, at switch-on
set HDR-NFA here ", LOG-ERROR #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-ERROR 0 ;
set HDR-NFA here ", LOG-WARN #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-WARN 1 ;
set HDR-NFA here ", LOG-INFO #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-INFO 2 ;
set HDR-NFA here ", LOG-TEST #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-TEST 3 ;
set HDR-NFA here ", LOG-DEBUG #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-DEBUG 4 ;
set HDR-NFA here ", LOG-LEVEL@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LOG-LEVEL@ ( -- n ) (LOG-LEVEL) a! @ ;
\ ( n -- ) as v3: a level below 0 is 0, one above 4 is 4
set HDR-NFA here ", LOG-LEVEL! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LOG-LEVEL!
-if POS drop 0 jump SET
POS: dup -5 + -if BIG drop jump SET
BIG: drop drop 4
SET: (LOG-LEVEL) a! ! ;
\ ( baddr u level -- ) the message, if the level is at or below LOG-LEVEL
: (LOG)
dup inv (LOG-LEVEL) a! @ + 1 + -if SHOW drop drop drop drop ; \ LOG-LEVEL - level
SHOW: drop
if P0 -1 + if P1 -1 + if P2 -1 + if P3 -1 + if P4
drop jump OUT
P0: drop $31335B1B (EMIT4) $6D (EMIT4) $4F525245 (EMIT4) $203A52 (EMIT4) $6D305B1B (EMIT4) jump OUT
P1: drop $33335B1B (EMIT4) $6D (EMIT4) $4E524157 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
P2: drop $32335B1B (EMIT4) $6D (EMIT4) $4F464E49 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
P3: drop $35335B1B (EMIT4) $6D (EMIT4) $54534554 (EMIT4) $203A (EMIT4) $6D305B1B (EMIT4) jump OUT
P4: drop $34335B1B (EMIT4) $6D (EMIT4) $55424544 (EMIT4) $203A47 (EMIT4) $6D305B1B (EMIT4) jump OUT
OUT: TYPE jump CR
set HDR-NFA here ", LOG-ERROR-STR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-ERROR-STR ( baddr u -- ) 0 jump (LOG)
set HDR-NFA here ", LOG-WARN-STR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-WARN-STR ( baddr u -- ) 1 jump (LOG)
set HDR-NFA here ", LOG-INFO-STR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-INFO-STR ( baddr u -- ) 2 jump (LOG)
set HDR-NFA here ", LOG-TEST-STR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-TEST-STR ( baddr u -- ) 3 jump (LOG)
set HDR-NFA here ", LOG-DEBUG-STR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-DEBUG-STR ( baddr u -- ) 4 jump (LOG)
\ ( level -- ) the run time of LOG-xxx" : the text is after the call, as
\ for ." ; log it at that level and go on after it.
set HDR-NFA here ", (LOG") #, 16 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: (LOG")
pop 4* dup C@ over + 4/ 1 + push \ level baddr R: the cell after the text
COUNT ROT jump (LOG)
\ ( level -- ) LOG-xxx" text" logs the text -- now, if interpreting; when
\ the word it is compiled into runs, if compiling. (Q)+3 holds the level.
: (LOG-QUOTE)
(Q)+3 a! ! 34 (PARSE) drop
STATE a! @ if NOW
drop (Q)+3 a! @ (LIT,) &(LOG") (CALL,) jump (STRING,)
NOW: drop WBUF COUNT (Q)+3 a! @ jump (LOG)
set HDR-NFA here ", LOG-ERROR" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-ERROR-QUOTE 0 jump (LOG-QUOTE)
set HDR-NFA here ", LOG-WARN" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-WARN-QUOTE 1 jump (LOG-QUOTE)
set HDR-NFA here ", LOG-INFO" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-INFO-QUOTE 2 jump (LOG-QUOTE)
set HDR-NFA here ", LOG-TEST" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-TEST-QUOTE 3 jump (LOG-QUOTE)
set HDR-NFA here ", LOG-DEBUG" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here : LOG-DEBUG-QUOTE 4 jump (LOG-QUOTE)
+118
View File
@@ -0,0 +1,118 @@
\ map-32.f18 -- the memory map the system's source is assembled with, 32-bit cells.
\ Generated by v4/tools/mkmap.c (mkmap sys) from v4/tests/host_map.h -- do not edit.
constant N-1 31
constant NODE-ERROR 16382
constant CONSOLE-TX 16380
constant CONSOLE-RX 16378
constant CONSOLE-STATUS 16377
constant BASE 16376
constant TIB 63776
constant >IN 16375
constant SPAN 16374
constant WBUF 64856
constant (P) 16360
constant DP 16373
constant (LATEST) 16372
constant DBASE 32768
constant DLIMIT 55296
constant PAD 63656
constant (D) 16352
constant (CG) 16336
constant CG-BSLOTS 3
constant STATE 16371
constant (C) 16322
constant (CFP) 16370
constant (Q) 14708
constant (F) 16279
constant (S) 15812
constant (W) 16285
constant (X) 15792
constant (BOOT) 15750
constant (LOG-LEVEL) 14707
constant (ACL-HOOK) 14706
constant SCR 15742
constant BLK 15743
constant (SRC) 15744
constant (SRC-HOOK) 15745
constant (LINE-STATUS) 14703
constant (PORT) 14572
constant (ME) 14699
constant (CONSOLE) 14696
constant (ROUTE#) 14695
constant (ROUTE-DEFAULT) 14694
constant (LOST) 14693
constant (PRINT-TO) 14692
constant (PRINT-PORT) 14679
constant (DONE-PORT) 14678
constant (ROUTES) 14616
constant -PORTS -8
constant (NEAR) 14648
constant (AWAIT-FROM) 14673
constant (WIRE) 14584
constant (WIRE-A) 14585
constant (WIRE-B) 14586
constant (WIRE-DO) 14587
constant (WIRE-HOW) 14588
constant (WIRE-HAVE) 14589
constant (S-HAVE) 14677
constant (S-MASK) 14676
constant (S-WIRE) 14675
constant (S-ON) 14674
constant (KEEP) 14672
constant (DEFER) 14671
constant (D-MASK) 14704
constant (IN) 14656
constant (ONE) 14663
constant (OUT-HDR) 14600
constant (W-NEED) 14607
constant (W-PORT) 14608
constant (P-WAY) 14609
constant (P-NEED) 14612
constant (H-PORT) 14613
constant (H-NEED) 14614
constant (H-MASK) 14615
constant (A-SELF) 14610
constant (SEND^) 14611
constant (OUT-TEXT) 14248
constant (SEND-TEXT) 13912
constant (QUIET) 14702
constant (REFUSED) 14705
constant (OUT^) 14698
constant (REPLY) 14697
constant (MSG) 14664
constant (OUT) 14312
constant (WORD-DEFINED) 14701
constant (WORD-FORGOTTEN) 14700
constant BLOCK# -1
constant BUFFER# -2
constant UPDATE# -3
constant SAVE-BUFFERS# -4
constant EMPTY-BUFFERS# -5
constant (Q/) 15752
constant (QE) 15757
constant (QR) 15765
constant (QL) 15770
constant (QT) 15777
constant (QP) 15783
constant (DP) 15787
constant ADDR-DIGITS 8
constant MSB -2147483648
constant MAXHI 2147483647
constant HIMASK 65535
constant 2N+15 79
constant N-18 14
constant N-17 15
constant MAX-INT 2147483647
constant HLD 16359
constant FENCE 16358
constant CONTEXT 16320
constant CURRENT 16321
constant VOC-LINK 16334
constant HEND 63248
constant -HFLOOR -63186
constant DSTACK-DEPTH 16369
constant RSTACK-DEPTH 16368
constant CFBASE 16288
constant CFEND 16320
constant DICT-W 8192
constant (IMG) 14593
+118
View File
@@ -0,0 +1,118 @@
\ map-64.f18 -- the memory map the system's source is assembled with, 64-bit cells.
\ Generated by v4/tools/mkmap.c (mkmap sys) from v4/tests/host_map.h -- do not edit.
constant N-1 63
constant NODE-ERROR 16382
constant CONSOLE-TX 16380
constant CONSOLE-RX 16378
constant CONSOLE-STATUS 16377
constant BASE 16376
constant TIB 63776
constant >IN 16375
constant SPAN 16374
constant WBUF 64856
constant (P) 16360
constant DP 16373
constant (LATEST) 16372
constant DBASE 32768
constant DLIMIT 55296
constant PAD 63656
constant (D) 16352
constant (CG) 16336
constant CG-BSLOTS 3
constant STATE 16371
constant (C) 16322
constant (CFP) 16370
constant (Q) 14708
constant (F) 16279
constant (S) 15812
constant (W) 16285
constant (X) 15792
constant (BOOT) 15750
constant (LOG-LEVEL) 14707
constant (ACL-HOOK) 14706
constant SCR 15742
constant BLK 15743
constant (SRC) 15744
constant (SRC-HOOK) 15745
constant (LINE-STATUS) 14703
constant (PORT) 14572
constant (ME) 14699
constant (CONSOLE) 14696
constant (ROUTE#) 14695
constant (ROUTE-DEFAULT) 14694
constant (LOST) 14693
constant (PRINT-TO) 14692
constant (PRINT-PORT) 14679
constant (DONE-PORT) 14678
constant (ROUTES) 14616
constant -PORTS -8
constant (NEAR) 14648
constant (AWAIT-FROM) 14673
constant (WIRE) 14584
constant (WIRE-A) 14585
constant (WIRE-B) 14586
constant (WIRE-DO) 14587
constant (WIRE-HOW) 14588
constant (WIRE-HAVE) 14589
constant (S-HAVE) 14677
constant (S-MASK) 14676
constant (S-WIRE) 14675
constant (S-ON) 14674
constant (KEEP) 14672
constant (DEFER) 14671
constant (D-MASK) 14704
constant (IN) 14656
constant (ONE) 14663
constant (OUT-HDR) 14600
constant (W-NEED) 14607
constant (W-PORT) 14608
constant (P-WAY) 14609
constant (P-NEED) 14612
constant (H-PORT) 14613
constant (H-NEED) 14614
constant (H-MASK) 14615
constant (A-SELF) 14610
constant (SEND^) 14611
constant (OUT-TEXT) 14248
constant (SEND-TEXT) 13912
constant (QUIET) 14702
constant (REFUSED) 14705
constant (OUT^) 14698
constant (REPLY) 14697
constant (MSG) 14664
constant (OUT) 14312
constant (WORD-DEFINED) 14701
constant (WORD-FORGOTTEN) 14700
constant BLOCK# -1
constant BUFFER# -2
constant UPDATE# -3
constant SAVE-BUFFERS# -4
constant EMPTY-BUFFERS# -5
constant (Q/) 15752
constant (QE) 15757
constant (QR) 15765
constant (QL) 15770
constant (QT) 15777
constant (QP) 15783
constant (DP) 15787
constant ADDR-DIGITS 16
constant MSB -9223372036854775808
constant MAXHI 9223372036854775807
constant HIMASK 281474976710655
constant 2N+15 143
constant N-18 46
constant N-17 47
constant MAX-INT 9223372036854775807
constant HLD 16359
constant FENCE 16358
constant CONTEXT 16320
constant CURRENT 16321
constant VOC-LINK 16334
constant HEND 63248
constant -HFLOOR -63186
constant DSTACK-DEPTH 16369
constant RSTACK-DEPTH 16368
constant CFBASE 16288
constant CFEND 16320
constant DICT-W 8192
constant (IMG) 14593
+153
View File
@@ -0,0 +1,153 @@
\ numout.f18 -- printing numbers: pictured output, the . words, and .S
\
\ DECOMPOSITION.md 5.8: <# # #S HOLD SIGN #> . .R U. U.R D. D.R ? SPACES
\ DECIMAL HEX OCTAL, each the definition given there and executed on the mesh
\ node by test_pictured.c, test_numout.c and test_printing.c; and .S, which
\ D-16 makes possible again. Part of the compiler capsule. Rests on core.f18
\ and forth.f18.
\
\ Constants the loader supplies:
\ HEND byte address just past the hold buffer, which is 64 bytes
\ -HFLOOR minus the lowest address HOLD may store at: -(HEND - 62)
\ HLD word address of the variable: where the picture has got to
\ (W) word address of three cells of scratch for this file:
\ (W)+0 the width a number is to be printed in
\ (W)+1 whether a blank follows it (W)+2 .S's count
macro (-ROT) SWAP push SWAP pop endmacro
\ ---- unsigned division (section 4) ----
\ One step a bit, the divisor in A. Exact for uhi < ud.
: UM/MOD ( ulo uhi ud -- urem uquot )
a! N-1 FOR
-if L0
2* over -if L1 drop 1 + jump L2
L1: drop L2: push 2* pop
jump SUB
L0:
2* over -if L3 drop 1 + jump L4
L3: drop L4: push 2* pop
dup a xor -if L5
drop -if NOSUB jump SUB
L5: drop dup inv a + inv -if L6
drop jump NOSUB
L6: push drop pop jump SETBIT
SUB: inv a + inv
SETBIT: push 1 + pop
NOSUB:
NEXT
over push push drop pop pop ;
\ ---- pictured output ----
set HDR-NFA here ", <# #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: <# ( -- ) HEND HLD b! !b ;
set HDR-NFA here ", HOLD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: HOLD ( c -- )
dup -256 and if OKC drop drop NODE-ERROR b! 4 !b ; \ not a character
OKC: drop HLD b! @b -HFLOOR + -if ROOM
drop drop NODE-ERROR b! 3 !b ; \ the buffer is full
ROOM: drop HLD b! @b -1 + dup !b jump C!
set HDR-NFA here ", SIGN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SIGN ( n -- ) -if L1 drop 45 jump HOLD L1: drop ;
set HDR-NFA here ", # #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: # ( ud1 -- ud2 )
0 (BASE) UM/MOD (-ROT) \ qhi lo rem1
(BASE) UM/MOD (-ROT) \ qlo qhi rem
dup -10 + -if L1 drop 48 + jump L2 L1: drop 55 + L2: jump HOLD
set HDR-NFA here ", #S #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: #S ( ud -- 0 0 ) L: # over over OR if L1 drop jump L L1: drop ;
set HDR-NFA here ", #> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: #> ( ud -- baddr u ) drop drop HLD b! @b HEND over push inv pop + inv ;
\ ---- spaces and the number base ----
set HDR-NFA here ", SPACES #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SPACES ( n -- ) -if L drop ; L: if DONE SPACE -1 + jump L DONE: drop ;
set HDR-NFA here ", DECIMAL #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DECIMAL 10 BASE a! ! ;
set HDR-NFA here ", HEX #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: HEX 16 BASE a! ! ;
set HDR-NFA here ", OCTAL #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: OCTAL 8 BASE a! ! ;
\ ---- numbers ----
\ One picture for signed singles, one for unsigned, one for doubles. Each
\ plain word is its .R word with a width of 0 and the blank flag set, and all
\ six share one tail, which prints the blank only when the flag is set.
\ ( baddr u -- ) right-justified in the width, then the blank if wanted
: (.TAIL)
(W) b! @b -if POS drop jump OUT \ width < 0
POS: over - SPACES \ width - u spaces
OUT: TYPE (W)+1 b! @b if DONE drop jump SPACE
DONE: drop ;
: (.BODY) ( n width -- )
(W) b! !b dup push -if A inv 1 + A: 0 <# #S pop SIGN #> jump (.TAIL)
: (U.BODY) ( u width -- )
(W) b! !b 0 <# #S #> jump (.TAIL)
: (D.BODY) ( d width -- )
(W) b! !b dup push -if A DNEGATE A: <# #S pop SIGN #> jump (.TAIL)
set HDR-NFA here ", .R #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DOT-R ( n width -- ) 0 (W)+1 b! !b jump (.BODY)
set HDR-NFA here ", . #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DOT ( n -- ) -1 (W)+1 b! !b 0 jump (.BODY)
set HDR-NFA here ", U.R #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: U-DOT-R ( u width -- ) 0 (W)+1 b! !b jump (U.BODY)
set HDR-NFA here ", U. #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: U-DOT ( u -- ) -1 (W)+1 b! !b 0 jump (U.BODY)
set HDR-NFA here ", D.R #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D-DOT-R ( d width -- ) 0 (W)+1 b! !b jump (D.BODY)
set HDR-NFA here ", D. #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D-DOT ( d -- ) -1 (W)+1 b! !b 0 jump (D.BODY)
\ ( addr -- ) print what the cell holds
set HDR-NFA here ", ? #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: QUESTION a! @ jump DOT
\ ( -- ) as v3: the depth between < and >, then every value on the stack,
\ the deepest first, each followed by a blank; then a new line. The stack is
\ left as it was. It reads each value with PICK, so it needs a few cells of
\ the stack free to work in.
set HDR-NFA here ", .S #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DOT-S
60 EMIT DEPTH 0 U-DOT-R 62 EMIT SPACE
DEPTH (W)+2 b! !b
L: (W)+2 b! @b if DONE
PICK DOT
(W)+2 b! @b -1 + !b jump L
DONE: drop jump CR
\ ---- DUMP ----
\ ( baddr u -- ) u bytes from the byte address baddr, sixteen to a line: the
\ address, the bytes in hex, and the bytes as characters between bars.
\ Everything it keeps between words is in (DP): the saved BASE, the address,
\ the count and the column. ADDR-DIGITS is two for each byte of a cell.
: (DB) ( -- c ) (DP)+1 b! @b (DP)+3 b! @b + jump C@
set HDR-NFA here ", DUMP #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DUMP
-if OK drop drop NODE-ERROR b! 1 !b ;
OK: (DP)+2 b! !b (DP)+1 b! !b
BASE b! @b (DP) b! !b 16 BASE b! !b
LINE: (DP)+2 b! @b if DONE drop
(DP)+1 b! @b 0 <# ADDR-DIGITS (DP)+3 b! !b
AD: # (DP)+3 b! @b -1 + dup !b if ADX drop jump AD
ADX: drop #> TYPE 58 EMIT SPACE
0 (DP)+3 b! !b
HX: (DP)+2 b! @b (DP)+3 b! @b inv + -if HAVE
drop SPACE SPACE SPACE jump HN
HAVE: drop (DB) 0 <# # # #> TYPE SPACE
HN: (DP)+3 b! @b 1 + dup !b -16 + -if HXX drop jump HX
HXX: drop SPACE 124 EMIT
0 (DP)+3 b! !b
CH: (DP)+2 b! @b (DP)+3 b! @b inv + -if HAVC jump CHX
HAVC: drop (DB)
dup -32 + -if GE drop drop 46 jump EM
GE: drop dup -127 + -if BIG drop jump EM
BIG: drop drop 46
EM: EMIT
(DP)+3 b! @b 1 + dup !b -16 + -if CHX drop jump CH
CHX: drop 124 EMIT CR
(DP)+1 b! @b 16 + !b
(DP)+2 b! @b -16 + -if MORE jump DONE
MORE: !b jump LINE
DONE: drop (DP) b! @b BASE b! !b ;
+247
View File
@@ -0,0 +1,247 @@
\ qmath.f18 -- Q48.16 fixed point: a signed double with sixteen bits of
\ fraction (D-8, D-10).
\
\ DECOMPOSITION.md 5.26. Each word is the definition given there and
\ executed on the mesh node by test_foundation.c and test_printing.c, here in
\ the host node's vocabulary. Rests on core.f18, forth.f18, numout.f18 and
\ words.f18.
\
\ ERRORS. Q./ by zero, and Q.SQRT and Q.LOG outside their domain, leave the
\ result D-11 and D-12 give and then raise an error (D-18): codes 11,
\ "Division by zero", and 12, "Argument out of range".
\
\ Constants the loader supplies:
\ MSB MAXHI the high cells of Q min and Q max
\ HIMASK every bit but the top sixteen
\ 2N+15 N-18 N-17 loop counts, N the cell width in bits
\ (Q/) (QE) (QR) (QL) (QT) (QP) word addresses of the words' scratch
\ cells: 5, 8, 5, 7, 6 and 4 of them
\ the logical double shift right: one +* step with S = 0, the top bit cleared
macro (UD2/) push a! 0 pop +* MAXHI and push drop a pop endmacro
: (QERR11) NODE-ERROR b! 11 !b ;
: (QERR12) NODE-ERROR b! 12 !b ;
\ ---- conversion and constants ----
set HDR-NFA here ", Q.FROM-INT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.FROM-INT ( n -- q ) push 0 a! 0 pop N-17 FOR +* UNEXT push drop a pop ;
set HDR-NFA here ", Q.TO-INT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.TO-INT ( q -- n ) push a! 0 pop 15 FOR +* UNEXT drop drop a ;
set HDR-NFA here ", Q.1 #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.1 65536 0 ;
set HDR-NFA here ", Q.0 #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.0 0 0 ;
set HDR-NFA here ", Q.SCALE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.SCALE 65536 0 ;
\ ---- the double words under other names ----
set HDR-NFA here ", Q.+ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.+ jump D+
set HDR-NFA here ", Q.- #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.- jump D-
set HDR-NFA here ", Q.ABS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.ABS jump DABS
set HDR-NFA here ", Q.NEG #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.NEG jump DNEGATE
set HDR-NFA here ", Q.= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.= jump D=
set HDR-NFA here ", Q.< #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.< jump D<
set HDR-NFA here ", Q.> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.> 2SWAP jump D<
set HDR-NFA here ", Q.0= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.0= jump D0=
set HDR-NFA here ", Q.MAX #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.MAX jump DMAX
set HDR-NFA here ", Q.MIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here : Q.MIN jump DMIN
\ ---- multiply ----
set HDR-NFA here ", Q.* #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.* ( a b -- c )
SWAP push over over UM* drop
push push over pop
-if L1 SWAP jump L2 L1: SWAP drop 0 L2:
pop SWAP - push
push over pop UM* pop +
ROT pop dup push
over -if L3 drop dup jump L4 L3: drop 0 L4:
push UM* pop - D+
ROT pop UM*
SWAP push 0 D+ pop
push over pop SWAP Q.TO-INT push Q.TO-INT pop SWAP ;
\ ---- divide ----
: D2*C ( lo hi cin -- lo' hi' cout )
a! dup -if L1 drop 1 jump L2 L1: drop 0 L2: push
over -if L3 drop 1 jump L4 L3: drop 0 L4:
over + +
push 2* a + pop pop ;
: (UQ/) ( a0 a1 b0 b1 -- q0 q1 )
(Q/)+2 a! SWAP !+ ! (Q/) a! SWAP !+ ! 0 0 0
2N+15 FOR
push (Q/) a! @+ @ pop D2*C
push (Q/)+1 a! ! (Q/) a! ! pop D2*C
if CMP drop jump TAKE
CMP: drop (Q/)+3 b! @b
over over xor if EQH -if SAMEH
drop drop -if NT1 jump TAKE NT1: jump NOTAKE
SAMEH: drop over SWAP push inv pop + inv
-if T2 drop jump NOTAKE T2: drop jump TAKE
EQH: drop drop over (Q/)+2 b! @b
over over xor -if SAMEL
drop drop -if NT3 drop jump TAKEL NT3: drop jump NOTAKEL
SAMEL: drop push inv pop + inv
-if T4 drop jump NOTAKEL T4: drop jump TAKEL
TAKEL: drop (Q/)+2 b! @b push inv pop + inv 0 1 jump END
NOTAKEL: 0 jump END
TAKE: push (Q/)+2 b! @b over over push inv pop + inv push
over over xor -if SB drop NIP -if NB drop 1 jump BD NB: drop 0 jump BD
SB: drop push inv pop + inv -if NB2 drop 1 jump BD NB2: drop 0
BD: pop pop (Q/)+3 b! @b push inv pop + inv
push SWAP pop SWAP - 1 jump END
NOTAKE: 0
END:
NEXT
push (Q/) a! @+ @ pop D2*C drop push push drop drop pop pop ;
set HDR-NFA here ", Q./ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q./ ( a b -- q )
over over OR if ZERO drop
push over pop SWAP over xor (Q/)+4 b! !b
-if L1 DNEGATE L1: push push -if L2 DNEGATE L2: pop pop
dup if CHK drop jump DIV
CHK: drop over -131072 and if CHK2 drop jump DIV
CHK2: drop push push dup pop dup push N-18 FOR 2* UNEXT
over over xor -if SAME drop drop -if NOOV jump OV
SAME: drop push inv pop + inv -if OV
NOOV: drop pop pop jump DIV
OV: drop drop drop pop pop drop drop
(Q/)+4 b! @b -if OVP drop 0 MSB ; OVP: drop -1 MAXHI ;
DIV: (UQ/) (Q/)+4 b! @b -if L3 drop DNEGATE ; L3: drop ;
ZERO: drop drop drop
over over OR if Z0 drop -if ZP drop drop 0 MSB jump (QERR11)
ZP: drop drop -1 MAXHI jump (QERR11)
Z0: drop jump (QERR11)
\ ---- e to the x ----
set HDR-NFA here ", Q.EXP #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.EXP ( q -- e )
over over OR if ONE drop
dup (QE)+6 b! !b -if L1 DNEGATE L1:
over over -1048576 -1 D+ push drop pop -if BIG drop
over over (QE)+2 a! SWAP !+ ! over over (QE) a! SWAP !+ !
65536 0 D+ (QE)+4 a! SWAP !+ !
2 (QE)+7 b! !b
LOOP:
(QE)+2 a! @+ @ (QE) a! @+ @ Q.*
(QE)+7 b! @b Q.FROM-INT Q./
over over (QE)+2 a! SWAP !+ !
(QE)+4 a! @+ @ D+ (QE)+4 a! SWAP !+ !
(QE)+2 a! @+ @ if HI0 drop drop jump CONT
HI0: drop -if SM drop jump CONT
SM: -50 + -if CONT1 drop jump DONE
CONT1: drop
CONT: (QE)+7 b! @b 1 + dup !b -11 + -if DONE1 drop jump LOOP
DONE1: drop
DONE: (QE)+4 a! @+ @ (QE)+6 b! @b -if POS drop 65536 0 2SWAP jump Q./
POS: drop ;
BIG: drop drop drop (QE)+6 b! @b -if BIGP drop 0 0 ; BIGP: drop -1 MAXHI ;
ONE: drop drop drop 65536 0 ;
\ ---- square root ----
set HDR-NFA here ", Q.SQRT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.SQRT ( q -- r )
dup -if POS drop drop drop 0 0 jump (QERR12)
POS: drop over over OR if ZERO drop
over 65536 xor over OR if ONE drop
over over (QR) a! SWAP !+ ! (UD2/) 16384 0 D+ (QR)+2 a! SWAP !+ !
8 (QR)+4 b! !b
LOOP: (QR) a! @+ @ (QR)+2 a! @+ @ Q./ (QR)+2 a! @+ @ D+ (UD2/)
over over (QR)+2 a! @+ @ DNEGATE D+ -if L1 DNEGATE L1:
if HI0 drop drop jump NXT
HI0: drop -if SM drop jump NXT
SM: -10 + -if NXT1 drop drop drop (QR)+2 a! @+ @ ;
NXT1: drop
NXT: (QR)+2 a! SWAP !+ !
(QR)+4 b! @b -1 + dup !b if DONE drop jump LOOP
DONE: drop (QR)+2 a! @+ @ ;
ZERO: drop ;
ONE: drop ;
\ ---- natural logarithm ----
set HDR-NFA here ", Q.LOG #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.LOG ( x -- ln x )
dup -if POS drop jump ERR
POS: drop over over OR if ZERO drop 0 (QL)+2 b! !b
DOWN: dup if CHKLO drop jump SHR
CHKLO: drop over -131072 and if DOWNDONE drop
SHR: (UD2/) (QL)+2 b! @b 1 + !b jump DOWN
DOWNDONE: drop drop
UP: dup -65536 and if UPSHIFT drop jump NORM
UPSHIFT: drop 2* (QL)+2 b! @b -1 + !b jump UP
NORM: dup (QL) b! !b -65536 + (QL)+1 b! !b 6 (QL)+3 b! !b
NEWTON: (QL)+1 b! @b dup (QL)+4 b! !b 65536 + (QL)+5 b! !b
131072 (QL)+6 b! !b
EXPL: (QL)+4 b! @b 0 (QL)+1 b! @b 0 Q.* drop
0 (QL)+6 b! @b 0 Q./ drop dup (QL)+4 b! !b
dup (QL)+5 b! @b + !b
-50 + -if EXPC drop jump EXPD
EXPC: drop (QL)+6 b! @b 65536 + dup !b -720896 + -if EXPD2 drop jump EXPL
EXPD2: drop
EXPD: (QL) b! @b (QL)+5 b! @b push inv pop + inv
dup (QL)+4 b! !b
if DZ -if DPOS
inv 1 + 0 (QL)+5 b! @b 0 Q./ drop
(QL)+1 b! @b SWAP push inv pop + inv -if KEEP drop 0 KEEP: (QL)+1 b! !b
jump TEST
DPOS: 0 (QL)+5 b! @b 0 Q./ drop (QL)+1 b! @b + !b jump TEST
DZ: drop
TEST: (QL)+4 b! @b -if AP inv 1 + AP: -100 + -if CONT drop jump FIN
CONT: drop (QL)+3 b! @b -1 + dup !b if FIN0 drop jump NEWTON
FIN0: drop
FIN: (QL)+1 b! @b (QL)+2 b! @b
-if KP inv 1 + 45426 UM* drop inv 1 + jump KS KP: 45426 UM* drop
KS: + dup -if SP drop -1 ; SP: drop 0 ;
ZERO: drop
ERR: drop drop 0 0 jump (QERR12)
\ ---- sine and cosine ----
: (Q.REDUCE) ( x -- r )
dup (QT) b! !b -if L1 DNEGATE L1:
0 411774 UM/MOD drop 411774 UM/MOD drop
(QT) b! @b -if P1 drop inv 1 + jump J1 P1: drop J1:
dup -205888 + -if BIG drop
dup 205887 + -if OK drop 411774 + ;
OK: drop ;
BIG: drop -411774 + ;
\ The Taylor loop both use; each sets (QT) up and jumps here.
: (TRIG)
T: (QT)+2 b! @b 0 (QT)+1 b! @b 0 Q.* drop
0 (QT)+4 b! @b dup -1 + UM* drop 65536 UM* drop 0 Q./ drop
dup (QT)+2 b! !b
(QT)+5 b! @b if ADDT drop inv 1 + jump ACC ADDT: drop
ACC: (QT)+3 b! @b + !b (QT)+5 b! @b inv !b
(QT)+2 b! @b -10 + -if CONT drop jump END
CONT: drop (QT)+4 b! @b 2 + dup !b -12 + -if END2 drop jump T
END2: drop
END: (QT)+3 b! @b (QT) b! @b -if PR drop inv 1 + jump SD PR: drop
SD: dup -if SP drop -1 ; SP: drop 0 ;
set HDR-NFA here ", Q.SIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.SIN ( x -- sin x )
(Q.REDUCE) dup (QT) b! !b -if A1 inv 1 + A1:
dup (QT)+2 b! !b dup (QT)+3 b! !b
0 over 0 Q.* drop (QT)+1 b! !b
3 (QT)+4 b! !b -1 (QT)+5 b! !b jump (TRIG)
set HDR-NFA here ", Q.COS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.COS ( x -- cos x )
(Q.REDUCE) -if A1 inv 1 + A1:
0 (QT) b! !b 0 over 0 Q.* drop (QT)+1 b! !b
65536 (QT)+2 b! !b 65536 (QT)+3 b! !b
2 (QT)+4 b! !b -1 (QT)+5 b! !b jump (TRIG)
\ ---- printing ----
\ The integer part, a point, five digits, a blank; always in decimal.
set HDR-NFA here ", Q.PRINT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: Q.PRINT ( q -- )
dup (QP)+3 b! !b -if A DNEGATE A: (QP)+2 b! !b dup (QP)+1 b! !b
BASE b! @b (QP) b! !b 10 BASE b! !b
65535 and 4 FOR dup 2* 2* + UNEXT 10 FOR 2/ UNEXT
0 <# # # # # # drop drop 46 HOLD
(QP)+1 b! @b (QP)+2 b! @b dup push
push a! 0 pop 15 FOR +* UNEXT drop drop a
pop 15 FOR 2/ UNEXT HIMASK and
#S (QP)+3 b! @b SIGN #>
(QP) b! @b BASE b! !b
TYPE jump SPACE
+585
View File
@@ -0,0 +1,585 @@
\ quit.f18 -- a line of text, interpreted; how it ends; and the words that
\ print text written in the source.
\
\ DECOMPOSITION.md 5.15 and 5.10: QUIT ABORT ABORT" (ABORT") ." (."). Part of
\ the compiler capsule. Rests on all the files before it.
\
\ A NODE IS SENT TEXT (docs/v4.0.0/MESH.md section 6). It does not read its
\ own command line and prints no prompt. A node with nothing to do sleeps;
\ a message comes to one of its wires; if that is text for this node it is
\ taken and interpreted; what it printed goes back as a message, and then
\ a message saying how the text ended:
\ 1 it completed a console says " ok"
\ 2 it ended in an error the message is already printed; " ERROR"
\ 0 QUIT nothing is said
\ What a console then shows is v3's:
\ ok> 65 EMIT the console's prompt, and the line
\ A ok what the line printed, then " ok"
\ ok> NOSUCH
\ UNKNOWN WORD: 'NOSUCH'
\ ERROR
\ ok> -1 @
\ Address out of range an address fault (D-14), from any depth
\ ERROR
\ KEY, EXPECT and QUERY are FORTH-79 words that read characters, as before;
\ they are not how text reaches the node. They still read the console's
\ registers, CONSOLE-RX and CONSOLE-STATUS, and not a message.
\
\ THE STACKS are guarded (D-16): each counts what it holds, and a push onto
\ a full one or a pop from an empty one is a fault. So QUIT and ABORT, which
\ never return to whatever ran them, must empty the return stack, and ABORT
\ the data stack too. A store to RSTACK-DEPTH or DSTACK-DEPTH does that.
\
\ Constants the loader supplies:
\ (LINE-STATUS) word address of the variable: how the last text ended
\ (MSG) (REPLY) (ME) (OUT) (OUT^) see core.f18, "what a node prints"
\ (PORT) word address of the node's port 0
\ (Q) word address of four cells of scratch, which system.f18 and
\ blocks.f18 use too
\ DSTACK-DEPTH RSTACK-DEPTH word addresses of the stack registers
\ ( -- ) empty the return stack. `a` is only something to store: any
\ store to the register empties the stack, and `a` needs nothing to be on
\ the data stack. One cell of the data stack is used for a moment.
macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
\ ( -- ) stop compiling; forget the word being built and any open control
\ structures. A definition that was under way stays hidden.
: (RESET) 0 STATE a! ! (CG-RESET) CFBASE (CFP) a! ! ;
\ ( s -- ) the text is done with. What it printed is sent, then a message
\ saying how it ended -- 0 QUIT, 1 completed, 2 an error -- and the node waits
\ for the next. (DONE) is entered with the same number and, for an error,
\ stops compiling first; it is always jumped to, never called, by
\ something that has emptied the return stack (or by a fault, which empties
\ it). (LINE-STATUS) keeps how the last text ended, and is the one word of
\ the message's text.
\ THE ANSWER IS NOT REFUSED HERE: the text was not begun until the wire it
\ goes by had room for it, and that room has been kept, (KEEP), which is
\ let go only now (MESH.md 7d.4). If no one is on that port any more it
\ is counted in (LOST).
\ FOUR CELLS OF THE DATA STACK are tried first: what a node does between
\ texts -- this, passing messages on, taking the next text in -- and the
\ interpreter need that many, so text may leave 28 values on a stack of 32
\ and no more. Text that leaves more ends here, "Stack overflow", with
\ the stack emptied, and not later, in the middle of the text after it.
: (FINISH) ( s -- )
1 (QUIET) a! ! \ from here nothing is this text's doing
(LINE-STATUS) b! !b
0 0 0 0 drop drop drop drop
(FLUSH-OUT)
-1 (KEEP) a! !
(MSG)+1 a! @ 3 (HDR) 4 (OUT-HDR)+6 a! ! \ to whoever sent the text: type 3, four characters
(LINE-STATUS) (DONE-PORT) a! @ (PUT-ON) if SENT
drop (LOST) a! @ 1 + ! jump (IDLE)
SENT: drop jump (IDLE)
: (DONE)
if GO -1 + if OK
drop (RESET) 2 jump (FINISH)
OK: drop 1 jump (FINISH)
GO: drop 0 jump (FINISH)
\ ( -- flag ) A GONE has been taken: its seven words are in (IN), the
\ node it is about in (ONE), and (S-WIRE) is the wire it came by. It is
\ believed only if it came by the port that leads to this node's centre
\ and says it is from the centre (MESH.md 7b.4): the way to the node is
\ then forgotten, and the flag is -1. Otherwise nothing is done, and 0.
\ (As first built only what it said it was from was looked at, and one
\ that came by another port was believed.)
: (GONE?)
(CENTRE) if NOT (IN)+1 a! @ xor if FROM drop 0 ;
NOT: ;
FROM: drop (ROUTE-DEFAULT) a! @ (PORT) - (S-WIRE) a! @ xor if YES drop 0 ;
YES: drop (ONE) a! @ NO-ROUTE -1 ;
\ ( -- ) WAITING (MESH.md 7d.4). A node with nothing to do passes on
\ what has come for other nodes, (SERVE), and then goes through what has
\ come for itself, the lowest port first and each wire from its front:
\ text is taken, into TIB, and done: (LINE), and then (FINISH) says
\ how it ended. But not unless the wire its answer goes by --
\ the way to whoever sent it; with none known, or no one on
\ that port, the wire it came on -- has room for the answer,
\ 8 cells. If it has not, the text stays on its wire and the
\ node looks further: there may be several such, on wires
\ whose answers go different ways, and each is begun when
\ its own has the room. That room is kept from then until
\ the answer has gone.
\ TEXTS WHOSE ANSWERS GO THE SAME WAY ARE BEGUN IN THE ORDER
\ THEY CAME. Once one has been left for want of room, every
\ text behind it on this pass whose answer goes by that port
\ is left too, though the room has come since: (D-MASK) has
\ a bit for each such port. (As first built only the room
\ was asked, each time; room that came between the look at
\ one text and at the next began the second first. Found
\ by the final review of step 6e.)
\ a NACK is taken and counted in (REFUSED)
\ a GONE is taken, and believed if this node's centre sent it
\ an answer no one is waiting for is dropped: a SEND that is not waited
\ on is ordinary use, and its answer is not a loss.
\ any other is dropped, and counted in (LOST): what a node printed
\ that came here, a type there is none of, or a NACK or GONE
\ that is not as long as one is. (LOST) counts what should
\ have been delivered or acted on and was not.
\ A TAKE THAT DOES NOT TAKE -- the wire was cut after the message was
\ looked at -- leaves nothing to act on: no text is done and nothing is
\ believed for it, (UNTAKEN). The same for a drop that does not drop.
\ With nothing to begin it sleeps, executing nothing, until a message
\ comes; or, if text is waiting for room for its answer, or (SERVE) left a
\ message for want of room, until there is room on any wire that leads
\ from it or a message comes. Then it does all of this again.
\ It has fetched which wires have a message before it looks at any, and
\ sleeps after: a message that comes while it looks wakes it at once, and
\ one it left on a wire does not keep it awake (MESH.md 7d.3).
\ (KEEP) and (AWAIT-FROM) are put back here every time: whatever was
\ abandoned on the way, a node with nothing to do keeps no room and waits
\ for no one.
: (IDLE)
L: 1 (QUIET) a! ! \ nothing here is any text's doing: see (RAISED)
-1 (KEEP) a! ! 0 (AWAIT-FROM) a! ! -1 (DEFER) a! ! 0 (D-MASK) a! !
(SERVE) (MINE0)
M: (MINE) if REST
drop (IN)+2 a! @ -1 + if TEXT -3 + if NACK -1 + if GONE
OTHER: drop 4 (DO) if LETGO drop (SKIP) jump M \ it was not there to drop: nothing is counted
LETGO: drop (IN)+2 a! @ -3 + if ANSWER \ let go. An answer no one waits for is ordinary:
drop (LOST) a! @ 1 + ! jump M \ anything else should not have come here, and is counted
ANSWER: drop jump M
NACK: drop (IN)+6 a! @ -4 + if N1 jump OTHER
N1: drop (TAKE1) if N2 drop (UNTAKEN) jump M \ not taken: nothing is done for it
N2: drop (REFUSED) a! @ 1 + ! jump M \ a message of this node's was refused: counted
GONE: drop (IN)+6 a! @ -4 + if G1 jump OTHER
G1: drop (TAKE1) if G2 drop (UNTAKEN) jump M
G2: drop (GONE?) drop jump M
TEXT: drop
(IN)+1 a! @ (WAY) -if T1 drop (S-WIRE) a! @ \ the way back; with none known, the wire it came on
T1: (DONE-PORT) a! !
(DONE-PORT) a! @ (WBIT) (D-MASK) a! @ and if FREE1 jump FULL \ text ahead of it waits for room on that wire
FREE1: drop
8 (DONE-PORT) a! @ (ROOM?) if START -1 + if FULL
drop (S-WIRE) a! @ (DONE-PORT) a! ! \ no one is on that port: back by the wire it came on,
(S-WIRE) a! @ (WBIT) (D-MASK) a! @ and if FREE2 jump FULL
FREE2: drop
8 (S-WIRE) a! @ (ROOM?) -1 + if FULL jump START \ if that has the room -- or has no one on it either
FULL: drop (DONE-PORT) a! @ (WBIT) dup inv (D-MASK) a! @ and + !
(DEFER) a! @ -if LATER drop (DONE-PORT) a! @ (DEFER) a! ! (SKIP) jump M
LATER: drop (SKIP) jump M
REST: drop
(DEFER) a! @ -if ROOM drop (SLEEP) jump L
ROOM: (WIRE!) 8 (WIRE-A) b! !b 9 (DO) drop jump L
START: drop
(S-WIRE) a! @ dup (REPLY) a! ! (WIRE!)
(MSG) (WIRE-A) b! !b TIB 2/ 2/ (WIRE-B) b! !b 2 (DO) \ its seven words, and its text
if TAKEN drop (UNTAKEN) jump M \ not taken: the wire was cut since it was looked at
TAKEN: drop
0 (MSG)+6 a! @ TIB + C! \ a zero after the text
(MSG)+6 a! @ SPAN a! !
(DONE-PORT) a! @ (KEEP) a! ! \ the room for its answer is kept from here
(CONSOLE) a! @ if P0 jump P1 \ where what it prints goes: the console,
P0: drop (MSG)+1 a! @ \ or whoever sent it;
P1: dup (PRINT-TO) a! !
(WAY) -if Q1 drop (REPLY) a! @ \ by the way there, or the wire the text came on
Q1: (PRINT-PORT) a! !
jump (LINE)
\ ( -- ) THE TEXT, INTERPRETED. It is in TIB with a zero after it and its
\ length in SPAN, and the return stack is empty. It is interpreted with one
\ return entry under it, this word's call of INTERPRET; whatever is on the
\ data stack stays there.
: (LINE)
0 (QUIET) a! ! \ an error from here on is this text's
0 BLK a! ! \ the terminal, whatever was being loaded
TIB (SRC) a! ! 0 >IN a! !
0 NODE-ERROR b! !b
INTERPRET
NODE-ERROR b! @b if GOOD
drop 2 jump (DONE)
GOOD: drop 1 jump (DONE)
\ ---- the node among others (MESH.md sections 6 and 7) ---------------------------
\ Not FORTH-79 and not in v3: v3's VMs are sent to through the kernel.
\ ( node port -- ) the port, by its number, leads toward that node
set HDR-NFA here ", ROUTE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ROUTE
(ROUTE#) a! @ -16 + if FULL drop
(PORT) + (ROUTE#) a! @ 2* (ROUTES) + a!
push !+ pop !+
(ROUTE#) a! @ 1 + ! ;
FULL: drop drop drop NODE-ERROR b! 12 !b ;
\ ( node port -- ) the node on the other end of the port, by its number;
\ 0: none, or a device. Whoever wires the node tells it, and tells it again
\ when the wiring changes. It is how a node knows who its centre is, the
\ one node whose GONE it believes: (CENTRE).
set HDR-NFA here ", NEIGHBOUR #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NEIGHBOUR
dup -if POS jump BAD
POS: -PORTS + -if BAD drop (NEAR) + a! ! ;
BAD: drop drop drop NODE-ERROR b! 12 !b ;
\ ( port -- ) the port, by its number, leads toward every node not told of
set HDR-NFA here ", DEFAULT-ROUTE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DEFAULT-ROUTE (PORT) + (ROUTE-DEFAULT) a! ! ;
\ ( node -- ) forget the way to that node, if one is known: what is for it
\ then goes by the way for every node not told of, if there is one. The
\ last way in the table takes its place.
set HDR-NFA here ", NO-ROUTE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NO-ROUTE
(ROUTE#) a! @ if NONE -1 + (ROUTES) a!
FOR dup @+ xor if HIT drop @+ drop NEXT
drop ;
NONE: drop drop ;
HIT: drop drop pop drop
a -1 + push \ where its entry is
(ROUTE#) a! @ -1 + dup ! \ one way fewer
2* (ROUTES) + a! @+ @ \ the last entry: node port
pop a! SWAP !+ ! ;
\ ( about node type -- ) send the node a message of one word, `about`:
\ a GONE is type 5 (MESH.md 7b). With no way to the node it is error 12.
\ It goes or is refused at once; refused -- no one on the port, or no room
\ on the wire -- it is counted in (LOST) (MESH.md 7d.4).
: (SEND1)
push dup (WAY) -if GO
drop drop drop pop drop NODE-ERROR b! 12 !b ;
GO: (W-PORT) a! ! SWAP (ONE) a! !
pop (HDR) 4 (OUT-HDR)+6 a! !
(ONE) (W-PORT) a! @ (PUT-ON) if SENT
drop (LOST) a! @ 1 + ! ;
SENT: drop ;
\ ( n node -- ) tell the node that node n is gone. It acts on that only
\ if this node is its centre: it forgets the way to n, and if it is waiting
\ for n's answer the wait ends.
set HDR-NFA here ", GONE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: GONE 5 jump (SEND1)
\ ( -- ) forget every way: for when the wiring has changed
set HDR-NFA here ", NO-ROUTES #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: NO-ROUTES 0 (ROUTE#) a! ! 0 (ROUTE-DEFAULT) a! ! ;
\ ( baddr u node port -- ) send the node u characters of text to
\ interpret, by the port given, by its number. The text is made ready in
\ (SEND-TEXT), four characters to a word, the message is put on the wire
\ whole, and it is on its way when this returns. IT GOES OR IS REFUSED AT
\ ONCE (MESH.md 7d.1, ruling 3): with no room on the wire it is counted in
\ (REFUSED), as a refusal that came back would be, and is error 19, Message
\ refused; with no one on the port, error 18. Nothing is on a
\ wire until the put, the last thing done. More characters than a message
\ carries, or fewer than none, is error 12. What lies after the text in
\ this node's memory does not go with it: the last word is made zero past
\ the last character.
: (SEND-ON)
push 1 (HDR)
-if POS
BAD: drop drop pop drop NODE-ERROR b! 12 !b ;
LONG: drop jump BAD
POS: dup -1025 + -if LONG
drop dup (OUT-HDR)+6 a! !
(SEND-TEXT) (SEND^) a! !
3 + 2/ 2/ if NONE -1 +
FOR dup C@ over 1 + C@ 8* + over 2 + C@ 8* 8* + over 3 + C@ 8* 8* 8* +
(SEND^) b! @b a! !+ a !b 4 + NEXT
drop
(OUT-HDR)+6 a! @ 3 and if PUT \ the last word: nothing in it past the last character
(SEND^) b! @b -1 + a!
-1 + if M1 -1 + if M2
drop @ 16777215 and ! jump PUT0
M2: drop @ 65535 and ! jump PUT0
M1: drop @ 255 and ! jump PUT0
NONE: drop
PUT: drop
PUT0: (SEND-TEXT) pop (PUT-ON)
if SENT -1 + if FULL drop NODE-ERROR b! 18 !b ;
FULL: drop (REFUSED) a! @ 1 + ! NODE-ERROR b! 19 !b ;
SENT: drop ;
\ ( baddr u node -- ) send the node u characters of text to interpret,
\ by the way this node knows to it. What it prints there goes to that
\ node's console. With no way to the node it is error 12.
set HDR-NFA here ", SEND #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SEND
dup (WAY) -if GO drop drop drop drop NODE-ERROR b! 12 !b ;
GO: jump (SEND-ON)
\ ( baddr u node port -- ) the same by a port this node names, by its
\ number, whatever ways it knows: for a neighbour that has no number of
\ its own yet, to which text is sent as to node 0.
set HDR-NFA here ", SEND-ON #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SEND-ON
dup -if POS jump BAD
POS: -PORTS + -if BAD drop jump (SEND-ON)
BAD: drop drop drop drop drop NODE-ERROR b! 12 !b ;
\ ( -- n ) the number of this node's centre: the node on the port that
\ leads to everything it has no other way to. 0: it has none, or has not
\ been told who is there (NEIGHBOUR).
: (CENTRE)
(ROUTE-DEFAULT) a! @ if NONE (PORT) - (NEAR) + a! @ ;
NONE: ;
\ ( -- n ) the number of this node's console: the one it was told of, or
\ with none told of, whoever sent the text it is doing
: (A-CONSOLE)
(CONSOLE) a! @ if C0 ;
C0: drop (MSG)+1 a! @ ;
\ ( what -- how | ) the wait is over: 1 the answer has come, and its
\ word, in (ONE), is left; 2 refused, error 19; 3 the node is gone, error
\ 20; 4 a line from the console, error 21
: (A-END)
0 (AWAIT-FROM) a! !
-1 + if ANS -1 + if REF -1 + if LEFT drop NODE-ERROR b! 21 !b ;
ANS: drop (ONE) a! @ ;
REF: drop NODE-ERROR b! 19 !b ;
LEFT: drop NODE-ERROR b! 20 !b ;
\ ( node -- how ) WAIT FOR THE NODE'S WORD OF HOW TEXT ENDED: 0 QUIT,
\ 1 completed, 2 an error. (AWAIT-FROM) holds the node while this node
\ waits, and 0 otherwise. It sleeps, executing nothing, until a message
\ comes; then it passes on what is for other nodes, (SERVE), and goes
\ through what is for itself (MESH.md 7d.4):
\ the answer -- a message of type 3 from that node -- is taken, and the
\ wait is over;
\ a NACK is taken: about that node, the wait ends in error 19, Message
\ refused; about another it is counted, as at any time;
\ a GONE is taken: believed (its centre sent it: (GONE?)) and about that
\ node, the wait ends in error 20, Node gone;
\ text from its console ends the wait in error 21, Interrupted (7b.6).
\ The text is not taken: it stays on its wire and is done when this
\ text has been finished with. It is the one way to end a wait on
\ a node that is alive and never answers, short of Hera's killing
\ that node;
\ anything else stays on its wire, in its order, for when this node has
\ nothing to do.
\ WHAT HAS COME ALREADY is on the wires and is found the first time
\ through: the node looks before it sleeps. A message it left on a wire
\ does not keep it awake.
\ The stack what it does needs is tried first, (ROOM), core.f18: text that
\ has left too little ends "Stack overflow" with nothing taken off a wire.
set HDR-NFA here ", AWAIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: AWAIT
(ONE) a! ! (ROOM) \ if this faults, no one is waited for:
(ONE) a! @ (AWAIT-FROM) a! ! 0 (A-SELF) a! ! \ (AWAIT-FROM) is set only when the stack has been tried
L: (SERVE)
(A-SELF) a! @ if SCAN drop 2 jump (A-END) \ this node's own message for that node came back to it
SCAN: drop (MINE0)
M: (MINE) if SLEEP
drop (IN)+2 a! @ -1 + if TEXT -2 + if ANSWER -1 + if NACK -1 + if GONE
KEEP: drop (SKIP) jump M
TEXT: drop (A-CONSOLE) (IN)+1 a! @ xor if BREAK jump KEEP \ text: from the console?
BREAK: drop 4 jump (A-END)
ANSWER: drop (IN)+1 a! @ (AWAIT-FROM) a! @ xor if A1 jump KEEP
A1: drop (IN)+6 a! @ -4 + if A2 jump KEEP
A2: drop (TAKE1) if A3 drop (UNTAKEN) jump M \ not taken: nothing is done for it
A3: drop 1 jump (A-END)
NACK: drop (IN)+6 a! @ -4 + if N1 jump KEEP
N1: drop (TAKE1) if N0 drop (UNTAKEN) jump M
N0: drop (ONE) a! @ (AWAIT-FROM) a! @ xor if N2 \ about the node waited for?
drop (REFUSED) a! @ 1 + ! jump M \ another: counted
N2: drop 2 jump (A-END)
GONE: drop (IN)+6 a! @ -4 + if G1 jump KEEP
G1: drop (TAKE1) if G0 drop (UNTAKEN) jump M
G0: drop (GONE?) if M0 \ only its centre is believed
drop (ONE) a! @ (AWAIT-FROM) a! @ xor if G2 drop jump M
G2: drop 3 jump (A-END)
M0: drop jump M
SLEEP: drop (SLEEP) jump L
\ ( w port -- ) write a cell to the port, by its number. It waits until
\ the neighbour has taken it. This is how a node is sent a capsule of F18
\ code (docs/v4.0.0/MESH.md section 5): the cells go as they are, not as a
\ message, to a node that is executing from its ports.
set HDR-NFA here ", PORT! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: PORT!
dup -if POS jump BAD
POS: -PORTS + -if BAD drop (PORT) + b! !b ;
BAD: drop drop drop NODE-ERROR b! 12 !b ;
\ ( -- ) WHAT IS IN THE DICTIONARY NOW IS THE SYSTEM: COLD comes back to
\ it and FORGET will not go below it. Whoever has loaded a node's capsules
\ has it do this (system.f18, (BOOT) and FENCE).
set HDR-NFA here ", (SEAL) #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: (SEAL)
DP a! @ (BOOT) a! !
(LATEST) a! @ (BOOT)+1 a! !
DP a! @ 3 + 2/ 2/ FENCE a! ! ;
\ FORTH-79: clear the return stack, set execution mode, return control to
\ the terminal; no message is given. The data stack is left as it is.
\ NODE-ERROR, by name: how a definition written in FORTH raises an error.
\ A store of a code that is not zero is the trap of D-18 -- the word goes no
\ further, the message for the code is printed (-1: the word has printed
\ its own) and the line ends with ERROR. The codes are listed in core.f18.
set HDR-NFA here ", NODE-ERROR #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : NODE-ERROR' NODE-ERROR ;
set HDR-NFA here ", (ME) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (ME)' (ME) ;
set HDR-NFA here ", (CONSOLE) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (CONSOLE)' (CONSOLE) ;
set HDR-NFA here ", (LOST) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (LOST)' (LOST) ;
set HDR-NFA here ", (REFUSED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (REFUSED)' (REFUSED) ;
set HDR-NFA here ", (WORD-DEFINED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-DEFINED)' (WORD-DEFINED) ;
set HDR-NFA here ", (WORD-FORGOTTEN) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-FORGOTTEN)' (WORD-FORGOTTEN) ;
set HDR-NFA here ", QUIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: QUIT R-CLEAR (RESET) CR 0 jump (DONE)
\ FORTH-79: clear the data and return stacks, set execution mode, return
\ control to the terminal. As v3, the line it stops ends with " ok".
\ Both are emptied before anything is called: ABORT may be run with the
\ return stack full.
set HDR-NFA here ", ABORT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ABORT R-CLEAR DSTACK-DEPTH b! a !b (RESET) 1 jump (DONE)
\ ---- faults (D-14, D-16) -------------------------------------------------------
\ Where the node goes when a programme uses an address outside its memory,
\ pushes onto a full stack or pops an empty one. The opcode that faulted did
\ nothing, and both stacks have been emptied. Each handler says what happened;
\ whatever was running is abandoned, as by ABORT, and the line ends with
\ ERROR.
: (FAULT) \ "Address out of range"
$72646441 (EMIT4) $20737365 (EMIT4) $2074756F (EMIT4) $7220666F (EMIT4) $65676E61 (EMIT4) CR
2 jump (DONE)
: (D-OVER) \ "Stack overflow"
$63617453 (EMIT4) $766F206B (EMIT4) $6C667265 (EMIT4) $776F (EMIT4) CR
2 jump (DONE)
: (D-UNDER) \ "Stack underflow"
$63617453 (EMIT4) $6E75206B (EMIT4) $66726564 (EMIT4) $776F6C (EMIT4) CR
2 jump (DONE)
: (R-OVER) \ "Return stack overflow"
$75746552 (EMIT4) $73206E72 (EMIT4) $6B636174 (EMIT4) $65766F20 (EMIT4) $6F6C6672 (EMIT4) $77 (EMIT4) CR
2 jump (DONE)
: (R-UNDER) \ "Return stack underflow"
$75746552 (EMIT4) $73206E72 (EMIT4) $6B636174 (EMIT4) $646E7520 (EMIT4) $6C667265 (EMIT4) $776F (EMIT4) CR
2 jump (DONE)
\ A word has stored an error code in NODE-ERROR (D-18; the codes are listed
\ in core.f18). Print its message -- a negative code means the word printed
\ its own -- and end the line with ERROR. The return stack has been
\ emptied; the data stack is as the word left it.
\ (QUIET) is 1 while the node is doing something that is no text's doing:
\ passing a message on, or sending what a text printed and word of how it
\ ended. An error then has nobody to be told to, and telling it would
\ begin another message for a text that is over. Nothing the nucleus does
\ there raises one as it stands -- with no one on a port it counts what it
\ could not send, and goes on -- so this is a guard: if one is raised, what
\ was being sent is let go and counted, and the node goes back to waiting.
: (RAISED)
(QUIET) a! @ if SPEAK
drop (OUT) (OUT^) a! ! (LOST) a! @ 1 + ! jump (IDLE)
SPEAK: drop
NODE-ERROR b! @b
-if POS drop 2 jump (DONE)
POS: -1 + if M1 -1 + if M2 -1 + if M3 -1 + if M4
-1 + if M5 -1 + if M6 -1 + if M7 -1 + if M8 -1 + if M9
-1 + if M10 -1 + if M11 -1 + if M12 -1 + if M13 -1 + if M14
-1 + if M15 -1 + if M16 -1 + if M17 -1 + if M18
-1 + if M19 -1 + if M20 -1 + if M21
drop 2 jump (DONE)
M1: drop $6167654E (EMIT4) $65766974 (EMIT4) $756F6320 (EMIT4) $746E (EMIT4) CR 2 jump (DONE)
M2: drop $20746F4E (EMIT4) $756E2061 (EMIT4) $7265626D (EMIT4) CR 2 jump (DONE)
M3: drop $626D754E (EMIT4) $74207265 (EMIT4) $6C206F6F (EMIT4) $676E6F (EMIT4) CR 2 jump (DONE)
M4: drop $20746F4E (EMIT4) $68632061 (EMIT4) $63617261 (EMIT4) $726574 (EMIT4) CR 2 jump (DONE)
M5: drop $74636944 (EMIT4) $616E6F69 (EMIT4) $66207972 (EMIT4) $6C6C75 (EMIT4) CR 2 jump (DONE)
M6: drop $656D614E (EMIT4) $73696D20 (EMIT4) $676E6973 (EMIT4) CR 2 jump (DONE)
M7: drop $746E6F43 (EMIT4) $206C6F72 (EMIT4) $75727473 (EMIT4) $72757463 (EMIT4) $696D2065 (EMIT4) $74616D73 (EMIT4) $6863 (EMIT4) CR 2 jump (DONE)
M8: drop $746E6F43 (EMIT4) $206C6F72 (EMIT4) $75727473 (EMIT4) $72757463 (EMIT4) $74207365 (EMIT4) $64206F6F (EMIT4) $706565 (EMIT4) CR 2 jump (DONE)
M9: drop $66696853 (EMIT4) $6F632074 (EMIT4) $20746E75 (EMIT4) $2074756F (EMIT4) $7220666F (EMIT4) $65676E61 (EMIT4) CR 2 jump (DONE)
M10: drop $746F7250 (EMIT4) $65746365 (EMIT4) $6F772064 (EMIT4) $6472 (EMIT4) CR 2 jump (DONE)
M11: drop $69766944 (EMIT4) $6E6F6973 (EMIT4) $20796220 (EMIT4) $6F72657A (EMIT4) CR 2 jump (DONE)
M12: drop $75677241 (EMIT4) $746E656D (EMIT4) $74756F20 (EMIT4) $20666F20 (EMIT4) $676E6172 (EMIT4) $65 (EMIT4) CR 2 jump (DONE)
M13: drop $636F6C42 (EMIT4) $756F206B (EMIT4) $666F2074 (EMIT4) $6E617220 (EMIT4) $6567 (EMIT4) CR 2 jump (DONE)
M14: drop $62206F4E (EMIT4) $6B636F6C (EMIT4) $20736920 (EMIT4) $6E696562 (EMIT4) $6F6C2067 (EMIT4) $64656461 (EMIT4) CR 2 jump (DONE)
M15: drop $65666544 (EMIT4) $64657272 (EMIT4) $726F7720 (EMIT4) $6F6E2064 (EMIT4) $65732074 (EMIT4) $74 (EMIT4) CR 2 jump (DONE)
M16: drop $20746F4E (EMIT4) $6F772061 (EMIT4) $6472 (EMIT4) CR 2 jump (DONE)
M17: drop $726F7453 (EMIT4) $20656761 (EMIT4) $75666572 (EMIT4) $646573 (EMIT4) CR 2 jump (DONE)
M18: drop (OUT) (OUT^) a! ! \ what was printed and not sent cannot be sent: it is let go
$6F206F4E (EMIT4) $6F20656E (EMIT4) $6874206E (EMIT4) $70207461 (EMIT4) $74726F (EMIT4) CR 2 jump (DONE)
M19: drop $7373654D (EMIT4) $20656761 (EMIT4) $75666572 (EMIT4) $646573 (EMIT4) CR 2 jump (DONE)
M20: drop $65646F4E (EMIT4) $6E6F6720 (EMIT4) $65 (EMIT4) CR 2 jump (DONE)
M21: drop $65746E49 (EMIT4) $70757272 (EMIT4) $646574 (EMIT4) CR 2 jump (DONE)
\ The table the loader gives the node: six words, one for each kind of
\ fault in the node's order, each a jump. A jump fills its word, so they
\ are one after another.
: (FAULTS)
jump (FAULT) jump (D-OVER) jump (D-UNDER) jump (R-OVER) jump (R-UNDER) jump (RAISED)
\ ---- text in the source ---------------------------------------------------------
\ The three run-time words have names, as v3's have, so that SEE can tell a
\ string in a definition from code; they cannot be used from the prompt.
\ ." and ABORT" take the text up to the next " , which may be none at all
\ (input.f18's (PARSE)); with no closing " it is the rest of the line. Inside a definition they lay
\ down a call to their run-time word and, after it, the text as a counted
\ string: the count byte and the characters, four to a cell, the last cell
\ filled with zeros. The run-time word finds the string by the return
\ address the call left, and returns to the cell after the string.
\ ( -- ) lay the counted string in WBUF into the dictionary, as above.
\ (Q)+0 how many bytes are still to go, (Q)+1 which is next.
: (STRING,)
(FLUSH)
WBUF C@ 1 + (Q) a! ! 0 (Q)+1 a! !
L: (Q) a! @ if DONE -1 + !
(Q)+1 a! @ dup 1 + ! WBUF + C@ C,
jump L
DONE: drop
P: DP b! @b 3 and if ALIGNED drop 0 C, jump P
ALIGNED: drop ;
\ The run time of ." : print the string after the call, go on after it.
\ It takes the return address off before it calls anything and keeps the
\ count there instead, so a word that prints text goes no deeper than one
\ that calls any other word.
set HDR-NFA here ", (.") #, 16 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: (.")
pop 4* dup C@ \ baddr n
L: if DONE
push 1 + dup C@ EMIT pop -1 + jump L
DONE: drop 4/ 1 + push ; \ the cell after the last character
\ FORTH-79: ." text" prints the text -- now, if interpreting; when the word
\ it is compiled into runs, if compiling.
set HDR-NFA here ", ." #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DOT-QUOTE
34 (PARSE) drop
STATE a! @ if NOW
drop &(.") (CALL,) jump (STRING,)
NOW: drop WBUF COUNT jump TYPE
\ ( flag -- ) the run time of ABORT" : if the flag is not zero print the
\ string after the call, start a new line and ABORT; otherwise go on after
\ the string.
set HDR-NFA here ", (ABORT") #, 16 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: (ABORT")
if NO
drop pop 4* R-CLEAR COUNT TYPE CR jump ABORT
NO: drop pop 4* dup C@ + 4/ 1 + push ;
\ ( flag -- ) ABORT" text" as v3 (it is FORTH-83's, not FORTH-79's): if
\ the flag is not zero, print the text and ABORT.
set HDR-NFA here ", ABORT" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ABORT-QUOTE
34 (PARSE) drop
STATE a! @ if NOW
drop &(ABORT") (CALL,) jump (STRING,)
NOW: drop if NO
drop WBUF COUNT TYPE CR jump ABORT
NO: drop ;
\ The run time of S" : leave the address and length of the string after the
\ call, and go on after it.
set HDR-NFA here ", (S") #, 16 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: (S")
pop 4* dup C@ \ baddr n
over over + 4/ 1 + push \ the cell after the last character
push 1 + pop ; \ baddr+1 n
\ ( -- baddr u ) S" text" as v3. In a definition the text is compiled
\ into it. At the prompt it is copied to PAD, where it stays until PAD is
\ used again: WORD's buffer is overwritten by the very next word of the line.
set HDR-NFA here ", S" #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: S-QUOTE
34 (PARSE) drop
STATE a! @ if NOW
drop &(S") (CALL,) jump (STRING,)
NOW: drop WBUF+1 PAD WBUF C@ CMOVE PAD WBUF jump C@
+170
View File
@@ -0,0 +1,170 @@
\ system.f18 -- words about the dictionary as a whole: WORDS, FORGET, FENCE.
\
\ DECOMPOSITION.md 5.13 and 5.15. Part of the compiler capsule; rests on
\ dict.f18, quit.f18 and forth.f18.
\
\ Constants the loader supplies:
\ FENCE word address of the variable: FORGET will not remove an entry
\ that starts below the address it holds
\ VOC-LINK word address of the variable: the newest vocabulary, or 0
\ (BOOT) word address of two cells: DP and (LATEST) as the loader left them
set HDR-NFA here ", FENCE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : FENCE' FENCE ;
\ ---- vocabularies (FORTH-79) ----------------------------------------------------
\ A vocabulary is two cells: its head -- the xt of its newest entry, or 0 --
\ and the address of the vocabulary defined before it, or 0. VOC-LINK holds
\ the newest one's address. FORTH's head is (LATEST) and it is in no chain.
set HDR-NFA here ", CONTEXT #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : CONTEXT' CONTEXT ;
set HDR-NFA here ", CURRENT #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : CURRENT' CURRENT ;
\ FORTH-79: the primary vocabulary; it becomes the CONTEXT vocabulary.
set HDR-NFA here ", FORTH #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: FORTH (LATEST) CONTEXT a! ! ;
\ FORTH-79: new definitions go into the CONTEXT vocabulary from now on.
set HDR-NFA here ", DEFINITIONS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DEFINITIONS CONTEXT a! @ CURRENT a! ! ;
\ VOCABULARY xxx FORTH-79: xxx is a new, empty list of words; executing
\ xxx makes it the CONTEXT vocabulary. When a search of it finds nothing,
\ FORTH is searched.
: (DOVOC) pop CONTEXT a! ! ;
set HDR-NFA here ", VOCABULARY #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: VOCABULARY
&(DOVOC) (C)+3 a! ! (DATA) (C)+8 a! @ if NONE drop
0 , VOC-LINK a! @ , HERE -2 + VOC-LINK a! ! ;
NONE: drop ;
\ ( cell -- ) print the name of the vocabulary whose head cell this is
: (.VOC)
dup (LATEST) xor if F drop -1 + -2 + a! @ 4* COUNT 31 and jump TYPE
F: drop drop $54524F46 (EMIT4) $48 (EMIT4) ;
\ ( -- ) as v3's, but true: where names are looked for, and where new ones go
set HDR-NFA here ", ORDER #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ORDER
$72616553 (EMIT4) $6F206863 (EMIT4) $72656472 (EMIT4) $203A (EMIT4)
CONTEXT a! @ dup (.VOC) SPACE
(LATEST) xor if ONLY drop (LATEST) (.VOC) jump TWO
ONLY: drop
TWO: CR
$72727543 (EMIT4) $3A746E65 (EMIT4) $20 (EMIT4)
CURRENT a! @ (.VOC) jump CR
\ ( -- ) the names in the CONTEXT vocabulary, the newest first, a blank after
\ each, a new line whenever one has passed column 64. Hidden entries -- a
\ definition under way -- are not shown. (Q)+0 is the column.
set HDR-NFA here ", WORDS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: WORDS
0 (Q) a! !
CONTEXT a! @ a! @
L: if DONE
dup -3 + a! @ 2 and if SHOW drop jump NXT
SHOW: drop
dup -2 + a! @ 4* COUNT 31 and \ xt baddr u
dup (Q) a! @ + 1 + !
TYPE SPACE
(Q) a! @ -64 + -if WRAP drop jump NXT
WRAP: drop CR 0 (Q) a! !
NXT: -1 + a! @ jump L
DONE: drop jump CR
set HDR-NFA here ", VLIST #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: VLIST jump WORDS
\ ( cell -- ) take off a vocabulary's list every entry at or above the
\ address in (Q)+0. The newest are first, so it stops at the first one below.
: (PRUNE)
(Q)+1 a! !
L: (Q)+1 a! @ a! @ if DONE
dup (Q) a! @ inv + 1 + -if CUT drop drop ;
CUT: drop -1 + a! @ (Q)+1 a! @ a! ! jump L
DONE: drop ;
\ FORGET xxx FORTH-79: remove xxx and every word defined after it, in
\ whatever vocabulary; the space they took is free again. A vocabulary that
\ goes is no longer CONTEXT or CURRENT: FORTH is. A word that is not there
\ is an error, and so is one below FENCE, which is where the capsule's own
\ words are (code 10, "Protected word").
set HDR-NFA here ", FORGET #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: FORGET
32 WORD (LOOKUP) if MISSING
-2 + a! @ \ where its name starts
dup FENCE a! @ inv + 1 + -if OK \ name - fence
drop drop NODE-ERROR b! 10 !b ;
OK: drop
dup (Q) a! ! 4* DP a! ! \ the space from its name on
(LATEST) (PRUNE)
V: VOC-LINK a! @ if PRUNED \ vocabularies that go
dup (Q) a! @ inv + 1 + -if GONE drop jump KEPT
GONE: drop 1 + a! @ VOC-LINK a! ! jump V
KEPT: P: if PRUNED \ the lists of those that stay
dup (PRUNE) 1 + a! @ jump P
PRUNED: drop
CONTEXT a! @ (Q) a! @ inv + 1 + -if C1 drop jump C2
C1: drop (LATEST) CONTEXT a! !
C2: CURRENT a! @ (Q) a! @ inv + 1 + -if C3 drop jump TOLD
C3: drop (LATEST) CURRENT a! !
TOLD: (Q) a! @ jump (FORGOTTEN) \ the kernel's records of them go too (dict.f18)
MISSING: drop (UNKNOWN) drop ;
\ ---- the system as a whole -------------------------------------------------------
\ (BOOT) is two cells the loader fills when the capsule is in place: DP and
\ the newest FORTH entry as they then are. COLD goes back to them.
\ FORTH-79: execute to be sure a FORTH-79 system is there. It is: nothing
\ happens. (v3's prints two lines and leaves a flag.)
set HDR-NFA here ", 79-STANDARD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 79-STANDARD ;
\ ( -- ) which system this is, and its cell width
set HDR-NFA here ", VERSION #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: VERSION
$72617453 (EMIT4) $74726F46 (EMIT4) $34762068 (EMIT4) $302E302E (EMIT4) $38314620 (EMIT4) $20 (EMIT4)
N-1 1 + 0 U-DOT-R $7469622D (EMIT4) CR ;
\ ( -- ) clear the screen and put the cursor at the top, as v3: ESC [2J ESC [H
set HDR-NFA here ", PAGE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: PAGE 27 EMIT 91 EMIT 50 EMIT 74 EMIT 27 EMIT 91 EMIT 72 jump EMIT
\ ( -- ) as v3's message, and then ABORT: both stacks emptied, the prompt
set HDR-NFA here ", WARM #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: WARM
$54524F46 (EMIT4) $39372D48 (EMIT4) $72615720 (EMIT4) $7453206D (EMIT4) $747261 (EMIT4) CR
$74737953 (EMIT4) $72206D65 (EMIT4) $61747365 (EMIT4) $64657472 (EMIT4) $2E (EMIT4) CR
jump ABORT
\ ( -- ) the system as it was when the capsule had just been loaded:
\ everything defined since is gone, there is one vocabulary, numbers are
\ decimal, the block buffers are empty. Then as WARM.
set HDR-NFA here ", COLD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COLD
(BOOT) a! @ DP a! !
(BOOT)+1 a! @ (LATEST) a! !
(BOOT) a! @ 2/ 2/ FENCE a! !
(LATEST) CONTEXT a! ! (LATEST) CURRENT a! ! 0 VOC-LINK a! !
10 BASE a! ! 0 SCR a! ! 2 (LOG-LEVEL) a! ! 0 (ACL-HOOK) a! ! EMPTY-BUFFERS
(BOOT) a! @ 2/ 2/ (FORGOTTEN) \ the kernel's records of what has gone go too (dict.f18)
$54524F46 (EMIT4) $39372D48 (EMIT4) $6C6F4320 (EMIT4) $74532064 (EMIT4) $747261 (EMIT4) CR
$74737953 (EMIT4) $69206D65 (EMIT4) $6974696E (EMIT4) $7A696C61 (EMIT4) $2E6465 (EMIT4) CR
jump ABORT
\ ---- deferred words (as v3) -------------------------------------------------------
\ DEFER xxx makes xxx, which does whatever word it has been given:
\ ' yyy IS xxx gives it one; DEFER@ xxx leaves the one it has. A deferred
\ word with none is an error (code 15, "Deferred word not set").
: (DODEFER)
pop a! @ if UNSET push ; \ go to it: it returns to xxx's caller
UNSET: drop NODE-ERROR b! 15 !b ;
set HDR-NFA here ", DEFER #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DEFER &(DODEFER) (C)+3 a! ! (DATA) (C)+8 a! @ if NONE drop 0 jump , NONE: drop ;
: (is!) a! ! ;
: (defer@) a! @ ;
set HDR-NFA here ", IS #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: IS
(') STATE a! @ if NOW drop (LIT,) &(is!) jump (CALL,)
NOW: drop jump (is!)
set HDR-NFA here ", DEFER@ #, 1 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DEFER@
(') STATE a! @ if NOW drop (LIT,) &(defer@) jump (CALL,)
NOW: drop jump (defer@)
+201
View File
@@ -0,0 +1,201 @@
\ words.f18 -- more of the FORTH vocabulary: the stack, comparison, double,
\ mixed, shift and string words that are short runs of opcodes or small loops.
\
\ Each is the definition DECOMPOSITION.md gives (sections 4, 5.1 - 5.7, 5.9)
\ and the mesh-node tests execute (test_cells.c, test_foundation.c,
\ test_strings.c), here as words of the host node's vocabulary. Rests on
\ core.f18, forth.f18 and numout.f18.
\
\ Constants the loader supplies:
\ MAX-INT the largest positive number: every bit but the top one
\ (X) word address of four cells of scratch for COMPARE and SEARCH
\ ---- stack ----
set HDR-NFA here ", 2SWAP #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2SWAP ( a b c d -- c d a b ) ROT push ROT pop ;
set HDR-NFA here ", 2OVER #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2OVER ( a b c d -- a b c d a b ) push push over over pop pop jump 2SWAP
set HDR-NFA here ", 2ROT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2ROT ( a b c d e f -- c d e f a b ) push push 2SWAP pop pop jump 2SWAP
set HDR-NFA here ", 2>R #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2>R SWAP push push ;
set HDR-NFA here ", 2R> #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2R> pop pop SWAP ;
set HDR-NFA here ", 2R@ #, 24 #, HDR-NFA #, HDR-LINK set HDR-LINK here : 2R@ pop pop over over push push SWAP ;
set HDR-NFA here ", NOP #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : NOP' nop ;
set HDR-NFA here ", TRUE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : TRUE -1 ;
set HDR-NFA here ", FALSE #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : FALSE 0 ;
set HDR-NFA here ", INVERT #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : INVERT inv ;
\ ---- memory ----
set HDR-NFA here ", 2@ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2@ ( addr -- lo hi ) a! @+ @ ;
set HDR-NFA here ", 2! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 2! ( lo hi addr -- ) a! SWAP !+ ! ;
set HDR-NFA here ", -! #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: -! ( n addr -- ) a! NEGATE @ + ! ;
\ ---- comparison ----
set HDR-NFA here ", 0<> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 0<> if Z drop -1 ; Z: ;
set HDR-NFA here ", 0> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: 0> -if NN drop 0 ; NN: if Z drop -1 ; Z: ;
set HDR-NFA here ", <> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: <> xor jump 0<>
set HDR-NFA here ", <= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: <= GREATER jump 0=
set HDR-NFA here ", >= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: >= LESS jump 0=
set HDR-NFA here ", U< #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: U< over over xor -if SAME drop NIP jump 0<
SAME: drop - jump 0<
set HDR-NFA here ", U> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: U> SWAP jump U<
set HDR-NFA here ", ABS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ABS -if P inv 1 + P: ;
set HDR-NFA here ", MAX #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: MAX over over LESS if A drop push drop pop ; A: drop drop ;
set HDR-NFA here ", MIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: MIN over over LESS if B drop drop ; B: drop push drop pop ;
set HDR-NFA here ", WITHIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: WITHIN ( n low high -- flag ) push over pop LESS push LESS inv pop and ;
\ ---- shifts ----
\ As v3, a count that is negative or as large as the cell is wide is an
\ error (code 9, "Shift count out of range").
set HDR-NFA here ", LSHIFT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: LSHIFT ( x n -- x' )
-if NN jump BAD
NN: dup N-1 inv + -if BAD2 drop
L: if DONE -1 + push 2* pop jump L
DONE: drop ;
BAD2: drop
BAD: drop drop NODE-ERROR b! 9 !b ;
set HDR-NFA here ", RSHIFT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: RSHIFT ( x n -- x' ) \ zeros come in at the top
-if NN jump BAD
NN: dup N-1 inv + -if BAD2 drop
L: if DONE -1 + push 2/ MAX-INT and pop jump L
DONE: drop ;
BAD2: drop
BAD: drop drop NODE-ERROR b! 9 !b ;
\ ---- doubles and mixed ----
set HDR-NFA here ", D- #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D- DNEGATE jump D+
set HDR-NFA here ", DABS #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DABS -if P jump DNEGATE P: ;
set HDR-NFA here ", D0= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D0= OR jump 0=
set HDR-NFA here ", D0< #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D0< push drop pop jump 0<
set HDR-NFA here ", D= #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D= D- jump D0=
set HDR-NFA here ", D2* #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D2* 2* over -if P drop 1 + jump J P: drop J: push 2* pop ;
set HDR-NFA here ", D2/ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D2/ push a! 0 pop +* push drop a pop ;
set HDR-NFA here ", M+ #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: M+ S>D jump D+
set HDR-NFA here ", M- #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: M- S>D DNEGATE jump D+
\ ( d1 d2 -- d1 d2 flag ) the flag's top bit is set exactly when d1 < d2
: (D<)
dup push push over pop over over xor if TIE
drop over over xor -if HS drop drop jump S1
HS: drop push inv pop + inv
S1: -if N1 drop -1 jump D1 N1: drop 0
D1: pop SWAP ;
TIE: drop drop drop dup push push over pop
over over xor -if LS drop NIP jump S2
LS: drop push inv pop + inv
S2: -if N2 drop -1 jump D2 N2: drop 0
D2: pop pop ROT ;
set HDR-NFA here ", D< #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: D< (D<) push drop drop drop drop pop ;
set HDR-NFA here ", DMAX #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DMAX (D<) if L drop push push drop drop pop pop ; L: drop drop drop ;
set HDR-NFA here ", DMIN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: DMIN (D<) if L drop drop drop ; L: drop push push drop drop pop pop ;
\ ---- strings and memory ----
set HDR-NFA here ", ?TERMINAL #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ?TERMINAL ( -- flag ) CONSOLE-STATUS b! @b ;
set HDR-NFA here ", CMOVE> #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: CMOVE> ( src dst u -- )
-if OK drop drop drop NODE-ERROR b! 1 !b ;
OK: if DONE -1 + push
over pop dup push + C@
over pop dup push + C!
pop jump OK
DONE: drop drop drop ;
\ FORTH-79: n cells from addr1 to addr2, the cell at addr1 first.
set HDR-NFA here ", MOVE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: MOVE ( addr1 addr2 n -- )
-if OK drop drop drop ;
OK: if DONE push over a! @ over a! ! 1 + push 1 + pop pop -1 + jump OK
DONE: drop drop drop ;
set HDR-NFA here ", FILL #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: FILL ( baddr u c -- )
SWAP push SWAP pop \ c baddr u
-if OK drop drop drop NODE-ERROR b! 1 !b ;
OK: if DONE push over over C! 1 + pop -1 + jump OK
DONE: drop drop drop ;
set HDR-NFA here ", ERASE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: ERASE ( baddr u -- ) 0 jump FILL
set HDR-NFA here ", BLANK #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: BLANK ( baddr u -- ) 32 jump FILL
set HDR-NFA here ", -TRAILING #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: -TRAILING ( baddr u -- baddr u' )
-if L drop 0 ;
L: if DONE over over + -1 + C@ -32 + if SP drop ;
SP: drop -1 + jump L
DONE: ;
set HDR-NFA here ", COMPARE #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COMPARE ( a1 u1 a2 u2 -- n )
-if A drop 0 A: (X)+1 b! !b
SWAP -if B drop 0 B: dup (X) b! !b
(X)+1 b! @b
over over - -if GE drop drop jump M
GE: drop push drop pop
M:
L: if EQ push
over C@ over C@ - if SAME
-if GT drop drop drop pop drop -1 ;
GT: drop drop drop pop drop 1 ;
SAME: drop 1 + push 1 + pop pop -1 + jump L
EQ: drop drop drop (X) b! @b (X)+1 b! @b -
-if NN drop -1 ;
NN: if ZZ drop 1 ;
ZZ: ;
set HDR-NFA here ", SEARCH #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SEARCH ( a1 u1 a2 u2 -- a3 u3 flag )
-if A drop 0 A: (X)+1 b! !b (X) b! !b
-if B drop 0 B: dup (X)+3 b! !b over (X)+2 b! !b
L: dup (X)+1 b! @b - -if TRY
drop drop drop (X)+2 b! @b (X)+3 b! @b 0 ;
TRY: drop over (X) b! @b (X)+1 b! @b
I: if MATCH push
over C@ over C@ xor if SAME
drop drop drop pop drop push 1 + pop -1 + jump L
SAME: drop 1 + push 1 + pop pop -1 + jump I
MATCH: drop drop drop -1 ;
set HDR-NFA here ", SCAN #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SCAN ( baddr u c -- baddr' u' )
255 and push -if L drop 0
L: if DONE over C@ pop dup push xor if FOUND
drop push 1 + pop -1 + jump L
FOUND: drop
DONE: pop drop ;
set HDR-NFA here ", SKIP #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: SKIP ( baddr u c -- baddr' u' )
255 and push -if L drop 0
L: if DONE over C@ pop dup push xor if SAME drop jump DONE
SAME: drop push 1 + pop -1 + jump L
DONE: pop drop ;
-26
View File
@@ -1,26 +0,0 @@
Block 4021
( zuse-eligibility.4th - H.5/H.8 elevation grant )
( 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 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
Block 4022
( ELEVATE-GRANT ( waddr wu pk0 pk1 pk2 pk3 -- ) )
( Reconstructs the caller's pubkey, checks Zuse's )
( eligibility list, and on match grants the named )
( word ACL-ALLOW!/ACL-TTL! via the same reused )
( ACL-TTL mechanism H.5 decided on. No grant, no )
( error, on any mismatch -- silent refusal. )
: ELEVATE-GRANT ( waddr wu pk0 pk1 pk2 pk3 -- )
ELEVATE-PK-BUF ELEVATE-PUBKEY-UNPACK
ELEVATE-PK-BUF ZUSE-ELIGIBLE? IF
NAME>XT DUP IF
1 OVER ACL-ALLOW!
ACL-BASE-TTL SWAP ACL-TTL!
ELSE DROP THEN
ELSE 2DROP THEN ;
-4
View File
@@ -12,8 +12,6 @@ Block 4016
( >BODY-then-store, so a pinned CONSTANT isn't tamper-proof. ) ( >BODY-then-store, so a pinned CONSTANT isn't tamper-proof. )
( Read with ZUSE-PUBKEY@ / ZUSE-CERT-INSTALLED? -- both C ) ( Read with ZUSE-PUBKEY@ / ZUSE-CERT-INSTALLED? -- both C )
( primitives, read-only; the seed has no FORTH access at all. ) ( 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 Block 4017
( ACL-ZUSE-BOOT ( -- ) re-invokable: capsule_zuse_boot.c ) ( ACL-ZUSE-BOOT ( -- ) re-invokable: capsule_zuse_boot.c )
@@ -25,8 +23,6 @@ Block 4017
: ACL-ZUSE-BOOT ( -- ) : ACL-ZUSE-BOOT ( -- )
ZUSE-CERT-INSTALLED? IF ZUSE-CERT-INSTALLED? IF
ZUSE-AUTHENTICATE ZUSE-AUTHENTICATE
1 ['] ZUSE-ELIGIBILITY-ADD ACL-ALLOW!
['] ZUSE-ELIGIBILITY-ADD ACL-PIN
LOG-INFO" zuse: activated" LOG-INFO" zuse: activated"
ELSE ELSE
LOG-INFO" zuse: NOT activated -- no cert installed" LOG-INFO" zuse: NOT activated -- no cert installed"
+1 -1
View File
@@ -1,7 +1,7 @@
# configs/ # configs/
Example Kconfig `defconfig` files — starting points for `make -f Example Kconfig `defconfig` files — starting points for `make -f
Makefile.starkernel ARCH=<arch> defconfig` (kernel) or the equivalent kernel/Makefile ARCH=<arch> defconfig` (kernel) or the equivalent
hosted target, matching the current committed default build behavior for hosted target, matching the current committed default build behavior for
each profile. Loaded via `tools/kconfig/conf`. each profile. Loaded via `tools/kconfig/conf`.
+50
View File
@@ -0,0 +1,50 @@
# Dead ideas and revised claims
A register, started 2026-10-14 by the docs triage. An idea that was abandoned, or a claim that
turned out wrong, keeps its documents (archived, with a header) — this page says, in one place,
what is no longer true, since when, and where the decision is recorded. Add to it whenever a
document is superseded or a claim corrected.
## Dead — abandoned, removed, or never adopted
| Idea | Since | What happened | Recorded in |
|---|---|---|---|
| L4Re / Fiasco.OC as a platform target | mid-2026 | Removed as an active target; LithosAnanke is its own kernel. | `.claude/CLAUDE.md` (Project Overview); docs archived in `working/archive/dead/l4re/` |
| The `hal_*` interface contract and its migration plan | flagged 2026-10-09 | Never adopted; the kernel grew its own HAL. | `working/archive/dead/hal-target-contract/`; the HAL as built: `kernel/src/hal/README.md` |
| ACL "Rolling Window of Truth" (`ACL-RECHECK-RW`) | removed 2026-07-08 | Dead code from the start: `acl_recheck()` only ever looked up `ACL-RECHECK`. | `fabric/FABRIC-1.md` §M–T |
| The Hermes VM and FORTH messaging (`messaging.4th`, `MSG-TICK`) | 2026-09-22 | Messaging moved into the kernel as kernel-Hermes; the Tripod is Hera / Artemis / Hestia. | `fabric/FABRIC-3.5.md`, `FABRIC-3.6.md`; old docs in `working/archive/superseded/2026-08-tripod/` and `.claude/HERMES.md` (frozen) |
| Running a VM's messages from Hera's idle loop (a second delivery path) | 2026-10-14 | One path: a VM takes its own messages on its own turn. | `fabric/FABRIC-3.md` §XXXVI |
| Word-ACL elevation on request (`ELEVATE-GRANT`, `KH-ELEVATE-SEND`) and Zuse's eligibility list | 2026-10-14 | Ruled not needed: privilege comes from the drive. Removed, with the hole it carried; the list's disk area is reserved, unused. | `fabric/FABRIC-3.md` §XXXVII; `fabric/FABRIC-3.7.md` (closed) |
| A knowledge factor for identity (PIN, passphrase) | 2026-09-23 | Built, tested, reverted: "there's only the drive." | `fabric/FABRIC-3.7.md` §4 |
| Defending against a byte-for-byte cloned identity drive | 2026-09-23 | Accepted by design, not a gap. (Copying from *within* StarshipOS is blocked.) | `fabric/FABRIC-3.7.md` §4 |
| The StarForth-era roadmap (VM -> kernel -> OS -> FPGA, 2025-12) | flagged 2026-08-26 | Overtaken; the architecture and terms it uses no longer exist. | `working/archive/superseded/2025-12-14-starforth-roadmap.md`; now `reference/ROADMAP.md` |
| The complete 2^6 factorial DoE | flagged 2026-10-09 | Obsolete. | `working/archive/superseded/factorial-doe/` |
| "Everything is a VM" system architecture, draft 0.1 | 2026-01-27 | A vision draft; what was built is in the FABRIC record. | `working/archive/historical/2026-01-27-system-architecture-draft.md` |
**Deferred, not dead:**
- **The multiuser/multitasking DoE campaign** (`fabric/FABRIC-3.md` §XXXIII–XXXV). Deferred past
bare metal, 2026-10-14. Its original 30-reps-per-cell design (about 10.3 days) had already been
replaced, in §XXXIV.4, by a segmented per-ISA design.
- **Keyboard VMs.** A concept only (2026-10-14), not designed.
## Revised — claims that were corrected
| Was | Is | Since | Recorded in |
|---|---|---|---|
| ACL overhead "+0.0054%–+0.0088%" (the "ACL-RWT" campaign) | **+0.0603%**, the live ACL-TTL mechanism, CV 0.000% | 2026-08-21 | `fabric/FABRIC-1.md` §T |
| Kernel version 2.0.1 | rolled back to 2.0.0 on 2026-09-04 (2.0.1 names the SER5 hardware line), now **2.1.0** (tag `v2.1.0`) | 2026-09-22 | `fabric/FABRIC-3.md` §I.2; `kernel/Makefile` |
| Capsule blocks must be in `[2048, 5120)` | **2048 or more**, no upper bound | 2026-10-05 | `v4.0.0/NUCLEUS.md` §5.2 |
| A capsule block is a 1024-byte budget | **64 characters x 16 lines** (`mkcapsule --lint`) | 2026-09-19 | `.claude/CLAUDE.md` (block format) |
| Parity baseline: 530 words, hash `0x08873e0f44b7cb2a` | **526 words, `0x82f4ae7cb2e2d424`** (elevation words out, `LOG-FLUSH`/`LOG-SHOW` in) | 2026-10-14 | `fabric/FABRIC-3.md` §XXXVII, §XXXVIII |
| Identity drives attached together are dropped (§XIV) | **no longer reproduces**, all three ISAs | 2026-10-14 | `fabric/FABRIC-3.md` §XIV |
| `THRU`/`LOAD` lose the rest of their line | **fixed** | 2026-10-14 | `fabric/FABRIC-3.md` §XXXIV.1 |
| The log ring's growth is "safe regardless of wrap state" | **it was not**; fixed | 2026-10-14 | `fabric/FABRIC-3.md` §XXXVIII |
| The Pi 5's GIC is under `/axi` with two-cell addresses; its framebuffer address needs `& 0x3FFFFFFF` | **under `/soc`, one cell**, read through `ranges`; the address **goes through `dma-ranges`** | 2026-10-14 | `fabric/FABRIC-3.md` §XXXIX |
| The old elevation path passed a raw cross-VM address | **it copied text** (the narrower real gap was a `"` in a name) | 2026-09-22 | `fabric/FABRIC-3.7.md` (its own correction) |
| Kernel builds boot v3 (v4 only with `STARFORTH_V4=1`, then v3 not at all; board images v3 unless `system=v4`) | **every build carries both and boots v4** unless `system=v3` -- v3 is being retired | 2026-10-14 | `fabric/FABRIC-3.md` XLIII (revised) |
| `.claude/ARTEMIS.md`, `HERMES.md`, `TRIPOD.md`, `CONSOLE.md` describe the system | **frozen as record**, superseded by FABRIC-3.5/3.6 | 2026-09-22 | `.claude/CLAUDE.md` (top) |
**Resolved 2026-10-14:** the top-level `README.md` was titled "LithosAnanke v2.0.1" (the SER5
hardware line's version) while the kernel is 2.1.0; Captain Bob ruled it rewritten -- it now
describes the system as it is (Tripod Hera/Artemis/Hestia, kernel-Hermes, 1052-test POST, both
systems on every board image, v4 the default).
+23 -15
View File
@@ -1,20 +1,28 @@
# docs/DELETE-CANDIDATES.md # docs/DELETE-CANDIDATES.md
**Generated:** 2026-06-16 (docs reorg Phase 2) **Listed:** 2026-10-14 (docs triage). **Status: deleted 2026-10-14 on Captain Bob's ruling
**Status:** Awaiting Bob's explicit confirmation. Nothing here has been deleted. ("delete").** The list is kept as the record of what was removed and why; nothing is awaiting a
ruling now. The formal tier's `%% SOURCE:` comments that named two of these were repointed at
the maintained copies.
These files were tagged `DELETE` during Phase 1 triage (see `docs/INDEX.md`). Every one is a duplicate: either byte-identical to another file in the same archive, or an older
Per the ground rules in `docs/CLAUDE.md`, they are listed here and left in place copy of a document whose maintained copy is named in the reason. Deleting them loses nothing.
until Bob confirms removal. They were relocated with their parent trees during
the Phase 2 reorganization but otherwise left unmodified (no provenance header
was inserted into them).
| Path (current) | Original path | Reason | (The four candidates listed 2026-06-16 -- an empty break-me report, two GitHub issue templates and
|----------------|---------------|--------| an AI session note -- are no longer in the tree: they were removed at some point since.)
| docs/working/archive/quality/validation/break-me-report.md | docs/04-quality/validation/break-me-report.md | Empty (0 bytes); never written despite `break_me_tests.c` existing. |
| docs/working/scratch/src/bug_report.adoc | docs/src/bug_report.adoc | Generic GitHub bug-report template (smartphone/browser/OS fields) auto-converted to AsciiDoc; irrelevant to a CLI FORTH VM. | | Path | Why |
| docs/working/scratch/src/feature_request.adoc | docs/src/feature_request.adoc | Generic GitHub feature-request template, garbled by AsciiDoc conversion; no project-specific content. | |---|---|
| docs/working/scratch/src/internal/SHARED_CLAUDE.adoc | docs/src/internal/SHARED_CLAUDE.adoc | Dated 2025-10-19 ad-hoc AI session notes/chat log; pure transient working notes. | | `docs/lithosananke/hal/README.md` | Duplicate of docs/working/archive/dead/hal-target-contract/README.md, without that copy's 2026-10-09 "never adopted" flags. |
| `docs/lithosananke/hal/interfaces.md` | Duplicate (older, unflagged) of docs/working/archive/dead/hal-target-contract/interfaces.md. |
| `docs/lithosananke/hal/lithosananke-integration.md` | The same document as docs/working/archive/dead/hal-target-contract/starkernel-integration.md under the kernel's newer name, without its "obsolete" flag. |
| `docs/lithosananke/hal/migration-plan.md` | Duplicate (older, unflagged) of docs/working/archive/dead/hal-target-contract/migration-plan.md. |
| `docs/lithosananke/hal/overview.md` | Duplicate (older) of docs/working/archive/dead/hal-target-contract/overview.md. |
| `docs/lithosananke/hal/platform-implementations.md` | Duplicate (older, unflagged) of docs/working/archive/dead/hal-target-contract/platform-implementations.md. |
| `docs/working/architecture/03-architecture/word-acl/DESIGN.md` | Older copy (2026-06) of docs/reference/word-acl/DESIGN.md, which is the maintained one (status through Phase 7). |
| `docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/FORMAL_CLAIMS_FOR_REVIEWERS.txt` | Byte-identical to ../../FORMAL_CLAIMS_FOR_REVIEWERS.txt in the same archive. |
| `docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/QUICK_REFERENCE.txt` | Byte-identical to ../../QUICK_REFERENCE.txt in the same archive. |
| `docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/03_EXPERIMENTAL_DATA/full_90_run_comprehensive/experiment_summary.txt` | Byte-identical to ../../../full_90_run_comprehensive/experiment_summary.txt in the same archive. |
| `docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/03_EXPERIMENTAL_DATA/full_90_run_comprehensive/run_logs/test_matrix.txt` | Byte-identical to the same file in ../../../full_90_run_comprehensive/run_logs/. |
| `docs/working/papers/ONTOLOGY.md` | Older copy (v1.0) of docs/reference/ONTOLOGY.md (v1.1, 2026-08-13). |
To approve deletion, tell Claude "delete the DELETE candidates" (or list specific
ones to keep).
+636 -324
View File
@@ -1,331 +1,643 @@
# docs/INDEX.md — Documentation Triage # docs/INDEX.md — every document, and its status
**Phase 1 triage:** 2026-06-16 · **Phase 2 reorg:** 2026-06-16 · **Phase 3 stubs:** 2026-06-16 Generated 2026-10-14 by the docs triage (docs/CLAUDE.md, Phase 1), from the tracked tree
**Total files inventoried:** 328 after the reorganisation. Start at **[README.md](README.md)** for the map; abandoned ideas and
**Status tags:** CURRENT · WORKING · HISTORICAL · SUPERSEDED · OBSOLETE · DELETE revised claims are in **[DEAD-AND-REVISED.md](DEAD-AND-REVISED.md)**; files awaiting a delete
ruling are in **[DELETE-CANDIDATES.md](DELETE-CANDIDATES.md)**. Logs (`logs/`) and DoE run
CSVs are not listed. Bulk data folders, and the formal LaTeX tree (governed by
`docs/formal/CLAUDE.md`), are listed one row per folder.
--- | Status | Meaning | Rows |
|---|---|---|
| CURRENT | Accurate; reflects the system as it is | 96 |
| WORKING | Living draft or record, still edited | 128 |
| HISTORICAL | Accurate for its time; kept as record | 90 |
| SUPERSEDED | Replaced -- its header says by what | 26 |
| DEAD | An idea or design that was abandoned or never adopted | 12 |
| DELETE | Proposed for deletion, awaiting a ruling | 0 |
| RECORD | Experiment data and results | 50 |
| FORMAL | The press-ready LaTeX tier | 19 |
| LEGAL HOLD | Patent-adjacent; not touched without Captain Bob | 57 |
## Status Key ## .claude
| Tag | Meaning | | Path | Title | Status | Notes |
|-----|---------| |---|---|---|---|
| CURRENT | Accurate and up-to-date; reflects present architecture | | .claude/ARTEMIS.md | ARTEMIS.md — Artemis VM Architecture | SUPERSEDED | Frozen 2026-08-15 by ruling (archive as-is); see FABRIC-3.5/3.6. |
| WORKING | Active draft or living document; still being edited | | .claude/CLAUDE.md | CLAUDE.md | CURRENT | Project instructions and status; authoritative. |
| HISTORICAL | Accurate for its time; kept as a record | | .claude/CONSOLE.md | CONSOLE.md — Console VM Architecture (DRAFT) | SUPERSEDED | Frozen 2026-08-15; see FABRIC-3.5/3.6. |
| SUPERSEDED | Replaced by a specific newer document | | .claude/HERMES.md | HERMES.md — Hermes VM Architecture | SUPERSEDED | Frozen 2026-08-15; describes a VM that no longer exists. See FABRIC-3.5/3.6. |
| OBSOLETE | Describes architecture or processes that no longer exist | | .claude/README.md | .claude/ | CURRENT | |
| DELETE | No value (empty, duplicate, pure noise) | | .claude/TRIPOD.md | TRIPOD.md — Architectural Constraints for the Tripod VMs | SUPERSEDED | Frozen 2026-08-15; see FABRIC-3.5/3.6. |
--- ## (root)
## Full File Index | Path | Title | Status | Notes |
|---|---|---|---|
| CHANGELOG.md | Changelog | CURRENT | |
| CODE_OF_CONDUCT.md | Contributor Covenant Code of Conduct | CURRENT | |
| CONTRIBUTING.md | Contributing to StarForth | CURRENT | |
| NOTICE.md | NOTICE.md | CURRENT | |
| README.md | LithosAnanke v2.1.0 | CURRENT | |
| Path | Topic | Status | Notes | ## boards
|------|-------|--------|-------|
| ./.claude/CLAUDE.md | Authoritative architecture/status reference | CURRENT | Self-declared authoritative reference; internally consistent (v3.0.3, LithosAnanke v1.0.8, ACL phases 1-6 done/7-8 pending); used as ground truth for this audit. | | Path | Title | Status | Notes |
| ./CODE_OF_CONDUCT.md | Community conduct standards | CURRENT | Standard Contributor Covenant boilerplate, not version/architecture-dependent. | |---|---|---|---|
| ./CONTRIBUTING.md | Contribution guidelines, build/test workflow | WORKING | References "780+ tests" and points to `docs/CLAUDE.md` as project overview, while authoritative CLAUDE.md cites 936+ tests and itself (`.claude/CLAUDE.md`) as authoritative — minor staleness, but actively-useful living doc. | | boards/BRINGUP.md | Board bring-up checklist | WORKING | Bare-metal bring-up checklist and blockers. |
| ./NOTICE.md | License attribution notice | CURRENT | Static legal/attribution text tied to Starship License 1.0, consistent with CLAUDE.md license section. | | boards/README.md | boards/ | CURRENT | |
| ./ONTOLOGY.md | Formal taxonomy/thermodynamic lexicon | CURRENT | Dated 2025-12-13; explicitly referenced as canonical lexicon by CLAUDE.md and README; conceptual framework, not version-dependent. | | boards/milkv/README.md | Milk-V Mars boot media | CURRENT | |
| ./README.md | Project overview/quick start | SUPERSEDED | Cites release tag v1.5.0-RELEASE, "800+ test suite", "21 theory files" vs CLAUDE.md's current v3.0.3, 936+ tests, 24 theory files — predates several version bumps; superseded by `.claude/CLAUDE.md`. | | boards/pc/README.md | PC boot media (generic x86-64, UEFI) | CURRENT | |
| ./ROADMAP.md | VM→Kernel→OS→FPGA phased roadmap | SUPERSEDED | Dated 2025-12-14, describes StarKernel/HAL as not yet begun, but CLAUDE.md shows LithosAnanke v1.0.8 with M0–M6 complete and M7 in progress — overtaken by progress; CLAUDE.md's embedded roadmap summary is now current. | | boards/raspi/README.md | Raspberry Pi 5 native boot media | CURRENT | |
| docs/working/experiments/campaigns/doe_2x7/README.md | 2^7 factorial DoE methodology guide | CURRENT | Reusable how-to-run guide for the DoE experiment class, not tied to one run; matches current 7-loop architecture. | | boards/raspi/config.txt | LithosAnanke native (non-UEFI) boot config for Raspberry Pi 5 (BCM2712). | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/SESSION_REPORT_2025-12-10.md | Narrative session report on L8 attractor debugging | HISTORICAL | Dated first-person account of one specific debugging/analysis session; accurate record of its time. | | boards/zynq7020/README.md | Xilinx Zynq-7020 boot media | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/TIDBITS.md | Informal findings notes from L8 attractor analysis | HISTORICAL | Informal commentary tied to one specific dataset/run (2025-12-09); a snapshot artifact. |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/comprehensive_report.md | Statistical report on L8 heartbeat across 180 runs | HISTORICAL | Dated analysis report of one specific experiment run's results. | ## capsules
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/comprehensive_report.md.pdf | Rendered PDF of comprehensive_report.md | HISTORICAL | Rendered artifact of the same dated run's report; same status as its .md source. |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/heartbeat_analysis.md | Heartbeat statistical analysis (ANOVA, workload effects) | HISTORICAL | Dated 2025-12-09, tied to this specific 180-run dataset; a results record. | | Path | Title | Status | Notes |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/mathematical_framework.md | Oscillator-inspired equations fit to heartbeat data | HISTORICAL | Speculative modeling derived from this one dataset's measured frequencies; dated analysis artifact. | |---|---|---|---|
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/report/mathematical_framework.md.pdf | Rendered PDF of mathematical_framework.md | HISTORICAL | Rendered artifact of the same dated analysis. | | capsules/BLOCK_MAP.md | Capsule Block Manifest — Auto-generated | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/tables/NOTES.md | Notes accompanying generated data tables | HISTORICAL | Supporting notes for one run's generated tables; tied to that dated results directory. | | capsules/MANIFEST.md | capsules/MANIFEST.md — Block Ownership Registry (justifications) | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/analysis_output/tables/anova_results.txt | Raw ANOVA output (tick count/duration vs workload) | HISTORICAL | Raw statistical output specific to the 2025-12-09 run. | | capsules/MANIFEST_AUTO.md | Capsule Block Manifest — Auto-generated | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/binary_2cycle_analysis_report.md | Binary 2-cycle clustering analysis of heartbeat phase space | HISTORICAL | Dated (2025-12-11) follow-on analysis of the same 180-run dataset. | | capsules/README.md | capsules/ | CURRENT | |
| docs/working/experiments/campaigns/l8_attractor_map/run_log.txt | Raw execution log of L8 attractor experiment run | HISTORICAL | Raw run transcript referencing a specific results directory; record of one execution session. | | capsules/contrib/README.md | capsules/contrib/ | CURRENT | |
| docs/working/experiments/campaigns/l8_validation/EXPERIMENT_SUMMARY.txt | L8 Jacquard validation experiment design summary | HISTORICAL | Fixed summary of one validation campaign ("IMPLEMENTED: 2025-11-26"), not a reusable guide (README fills that role). | | capsules/fonts/README.md | capsules/fonts/ | CURRENT | |
| docs/working/experiments/campaigns/l8_validation/README.md | L8 Jacquard validation methodology guide | CURRENT | Reusable how-to/experimental-design guide for re-running this class of experiment; matches current L8 Jacquard architecture. |
| docs/working/experiments/campaigns/l8_validation/l8_validation_20251208_102205/conditions_randomized.txt | Randomized condition matrix for one validation run | HISTORICAL | Raw generated condition list timestamped 2025-12-08; specific run's input data. | ## configs
| docs/working/experiments/campaigns/l8_validation/l8_validation_20251208_102205/conditions_raw.txt | Unrandomized condition matrix for one validation run | HISTORICAL | Companion raw matrix for the same dated run. |
| docs/working/experiments/campaigns/l8_validation/l8_validation_30reps_20251126_135128/conditions_randomized.txt | Randomized condition matrix, 30-rep run | HISTORICAL | Dated 2025-11-26 run's input matrix; an earlier run in the same family. | | Path | Title | Status | Notes |
| docs/working/experiments/campaigns/l8_validation/l8_validation_30reps_20251126_135128/conditions_raw.txt | Unrandomized condition matrix, 30-rep run | HISTORICAL | Companion raw matrix for the same 2025-11-26 run. | |---|---|---|---|
| docs/working/experiments/campaigns/shape_validation/README.md | Workload shape validation methodology guide | CURRENT | Reusable quick-start guide for re-running the shape-validation experiment class; architecture-consistent with CLAUDE.md. | | configs/README.md | configs/ | CURRENT | |
| docs/working/experiments/campaigns/shape_validation/shape_RAJ_run_20251127_093208/conditions_randomized.txt | Randomized condition matrix for one shape-validation run | HISTORICAL | Specific dated (2025-11-27) run's randomized input data. |
| docs/working/experiments/campaigns/shape_validation/shape_RAJ_run_20251127_093208/conditions_raw.txt | Unrandomized condition matrix for one shape-validation run | HISTORICAL | Companion raw matrix for the same 2025-11-27 run. | ## disk
| docs/working/experiments/campaigns/shape_validation/shape_run_20251123_083147/conditions_randomized.txt | Randomized condition matrix, earlier shape-validation run | HISTORICAL | Dated 2025-11-23, earlier run in same family. |
| docs/working/experiments/campaigns/shape_validation/shape_run_20251123_083147/conditions_raw.txt | Unrandomized condition matrix, earlier shape-validation run | HISTORICAL | Companion raw matrix for the 2025-11-23 run. | | Path | Title | Status | Notes |
| docs/working/experiments/campaigns/window_scaling/QUICK_START.md | Window-scaling (James Law) experiment quick-start steps | CURRENT | Reusable step-by-step workflow for re-running the experiment; procedural, not tied to a single completed run. | |---|---|---|---|
| docs/working/experiments/campaigns/window_scaling/README.md | Window-scaling experiment design / James Law hypothesis | CURRENT | Reusable experimental-design overview (hypothesis, expected outcomes) for the experiment class. | | disk/README.md | disk/ | CURRENT | |
| docs/working/papers/published/James_Steady-State_Convergence_Adaptive_Runtime.pdf | Published SSRN academic paper | CURRENT | Confirmed present; explicitly named as the published SSRN paper in CLAUDE.md; a citable finished artifact. |
| ./scripts/SCRIPT_REPAIR_LOG.md | Bug-fix log for run_ablation_study.sh | HISTORICAL | Documents specific fixes made 2025-11-20 to a script that still exists; valuable as a record but not living guidance. | ## docs
| docs/working/papers/ACADEMIC_WORDING_GUIDELINES.md | Academic language rules for physics-metaphor claims | CURRENT | Active style guide for SSRN paper and derivatives; referenced by authors/contributors. |
| docs/working/scratch/AGENTS.md | Repo structure and contribution rules for AI/human contributors | CURRENT | Accurate description of build, test, naming, and PR conventions; matches current codebase layout. | | Path | Title | Status | Notes |
| docs/working/scratch/AI_AGENT_MANDATORY_README.md | Mandatory AI-agent pre-read for physics runtime changes | CURRENT | Governance document; rules are evergreen; references live subsystem names. | |---|---|---|---|
| docs/working/papers/ANTI_CLAIMS.md | Explicit boundary statements for SSRN/peer-review defensibility | CURRENT | Directly supports published SSRN paper; no code references that have drifted. | | docs/CLAUDE.md | CLAUDE.md — StarshipOS Documentation Root | CURRENT | Rules for documentation work. |
| ./docs/CLAUDE.md | Docs-root instructions for Claude Code; two-tier doc model plan | WORKING | Describes a `docs/formal/` + `docs/working/` restructure not yet executed; active planning doc, not authoritative state ref (`.claude/CLAUDE.md` is). | | docs/DEAD-AND-REVISED.md | Dead ideas and revised claims | CURRENT | Register of abandoned ideas and revised claims. |
| docs/working/archive/COMPUTATIONAL_PHYSICS_FRAMEWORK.md | Expansive "physics of computation" claims framework | HISTORICAL | Contains strong over-claims ("This is not metaphor") that contradict `ANTI_CLAIMS.md` and `ACADEMIC_WORDING_GUIDELINES.md`; dates from earlier draft thinking (2025-12-10). | | docs/DELETE-CANDIDATES.md | docs/DELETE-CANDIDATES.md | CURRENT | Record of the duplicates deleted 2026-10-14. |
| ./docs/DARPA_SSM_Proposal_James.docx | DARPA SSM grant proposal (Word format) | WORKING | Active proposal document; companion to the PDF version. | | docs/INDEX.md | docs/INDEX.md — every document, and its status | CURRENT | This index. |
| ./docs/DARPA_SSM_Proposal_James.pdf | DARPA SSM grant proposal (PDF) | WORKING | Active funding proposal; filename indicates a working/submission-ready draft. | | docs/README.md | StarForth / LithosAnanke documentation — the map | CURRENT | The map: start here. |
| docs/working/archive/DOCUMENTATION_AUDIT.md | Docs audit from 2025-12-14; gap/inconsistency findings | HISTORICAL | Audit from a past triage pass; most findings have since changed; useful historical record. | | docs/SSM_DARPA_Summary_Slide.pptx | SSM_DARPA_Summary_Slide.pptx | CURRENT | |
| docs/working/papers/EXECUTIVE_SUMMARY.md | Plain-English summary of StarForth results for non-specialists | CURRENT | Accurate, well-calibrated summary with correct metaphor framing; audience: journalists, admins, reviewers. |
| docs/working/papers/FINAL_REPORT/appendix_glossary.adoc | AsciiDoc glossary appendix for multi-chapter report | CURRENT | Formal, math-precise definitions consistent with current ontology; intended for book/report compilation. | ## docs/book
| docs/working/papers/FORMAL_CLAIM_TABLE.md | Structured claim–evidence–reproducibility table for peer review | CURRENT | Core scientific accountability doc; tied to SSRN paper claims; still valid. |
| docs/working/archive/GAP_ANALYSIS.md | Gap analysis: StarForth → StarKernel → StarshipOS → FPGA | SUPERSEDED | Written when StarKernel had "zero implementation"; LithosAnanke v1.0.8 has M0-M6 complete — the kernel gaps section is stale. | | Path | Title | Status | Notes |
| docs/working/papers/NEGATIVE_RESULTS.md | Documented failure modes and limitations | CURRENT | Honest failure-mode catalog; still accurate and academically valuable. | |---|---|---|---|
| docs/working/papers/NULL_HYPOTHESIS.md | Formal null hypothesis and falsification criteria | CURRENT | Rigorous statistical framing for SSRN claims; no stale references. | | docs/book/README.md | docs/book/ | CURRENT | |
| docs/working/papers/ONTOLOGY.md | Master ontology/taxonomy/lexicon for adaptive runtime concepts | CURRENT | Authoritative term definitions; referenced by root ONTOLOGY.md and docs/README.md; actively used. | | docs/book/main.tex | LithosAnanke and StarForth | CURRENT | |
| docs/working/papers/ONTOLOGY_README.md | Index/guide to ontology file set (md, tex, adoc) | CURRENT | Accurate pointer document for ontology artifacts; still valid. |
| ./docs/README.md | Top-level docs directory README and navigation | WORKING | Navigation is broadly accurate but mentions HAL migration as "current active work" which is further along now. | ## docs/fabric
| docs/working/papers/REPLICATION_INVITE.md | Formal open invitation to independent replication | CURRENT | Evergreen scientific openness statement; expected output values still match claimed results. |
| docs/working/papers/REPRODUCIBILITY.md | One-command reproduction protocol with exact expected output | CURRENT | References valid build commands and `--doe` flag; expected output values consistent with published claims. | | Path | Title | Status | Notes |
| docs/working/papers/SCIENTIFIC_DEFENSE_CHECKLIST.md | Checklist of attack vectors and defenses for peer review | WORKING | Many "missing defenses" (GPG signing, Zenodo DOI, R/Python scripts) not yet addressed; still actively relevant. | |---|---|---|---|
| docs/working/papers/SENSITIVITY_ANALYSIS.md | Parameter sweep design: robustness of 0% CV claim | CURRENT | Documents planned sensitivity experiments; scientifically sound framing; supports SSRN defensibility. | | docs/fabric/FABRIC-0.md | FABRIC-0.md — the Stadium | HISTORICAL | Closed design record (the Stadium). |
| ./docs/SSM_DARPA_Complete_Proposal_James_FINAL.docx | DARPA SSM complete/final proposal (Word, FINAL) | WORKING | "FINAL" in name suggests submission-ready; likely supersedes `DARPA_SSM_Proposal_James.docx` but keep both until confirmed. | | docs/fabric/FABRIC-1.md | FABRIC-1.md — the Stadium, continued | HISTORICAL | Closed design record. |
| docs/working/papers/SSRN_companion/Math_Companion_SSRN.pdf | Compiled PDF of math companion to SSRN paper | CURRENT | Rendered output of the `.tex` source; companion to the published SSRN paper. | | docs/fabric/FABRIC-2.md | FABRIC-2.md — the Stadium, continued again | HISTORICAL | Closed design record. |
| docs/working/papers/SSRN_companion/Math_Companion_SSRN.tex | LaTeX source for math companion document | CURRENT | Source of record for comprehensive math/engineering structures reference; cross-references implementation. | | docs/fabric/FABRIC-3.5.md | FABRIC-3.5.md — the Tripod/kernel reshuffle | HISTORICAL | Closed at v2.1.0: the Tripod/kernel reshuffle, design. Authoritative for what it ruled. |
| docs/working/papers/SSRN_companion/figures/fig1_snake_trajectory.pdf | Figure asset: snake/phase trajectory | CURRENT | Figure asset for the SSRN math companion. | | docs/fabric/FABRIC-3.6.md | FABRIC-3.6.md — the Tripod/kernel reshuffle: execution log | HISTORICAL | Closed at v2.1.0: the reshuffle, execution. |
| docs/working/papers/SSRN_companion/figures/fig2_K_vs_window.pdf | Figure asset: K vs window width | CURRENT | Figure asset for the SSRN math companion. | | docs/fabric/FABRIC-3.7.md | FABRIC-3.7.md — Phase 8 PKI: the elevation entrypoint | DEAD | Closed 2026-10-14: elevation ruled not needed and removed (FABRIC-3 XXXVII). |
| docs/working/papers/SSRN_companion/figures/fig3_FFT_spectrum.pdf | Figure asset: FFT spectrum | CURRENT | Figure asset for the SSRN math companion. | | docs/fabric/FABRIC-3.md | FABRIC-3.md — bare metal boot | WORKING | The living record: bare metal boot and everything since. Authoritative. |
| docs/working/papers/SSRN_companion/figures/fig4_golden_ratio_penalties.pdf | Figure asset: golden ratio penalties | CURRENT | Figure asset for the SSRN math companion. | | docs/fabric/FABRIC-4.md | FABRIC-4.md — forward-looking design notes | WORKING | Ideas caught early, not yet scoped. |
| docs/working/papers/SSRN_companion/figures/fig5_bimodal_distributions.pdf | Figure asset: bimodal distributions | CURRENT | Figure asset for the SSRN math companion. |
| docs/working/papers/SSRN_companion/figures/fig6_performance_vs_k.pdf | Figure asset: performance vs K | CURRENT | Figure asset for the SSRN math companion. | ## docs/formal
| docs/working/papers/SSRN_companion/figures/fig7_performance_by_regime.pdf | Figure asset: performance by regime | CURRENT | Figure asset for the SSRN math companion. |
| ./docs/SYSTEM_NARRATIVE.pdf | Compiled PDF of system narrative | CURRENT | Rendered output of `SYSTEM_NARRATIVE.tex`; technical story for patent counsel and reviewers. | | Path | Title | Status | Notes |
| ./docs/SYSTEM_NARRATIVE.tex | LaTeX source: technical narrative for patent/research review | CURRENT | Well-framed, correctly calibrated narrative; accurate description of the adaptive runtime and 90-run experiment. | |---|---|---|---|
| docs/working/scratch/TASK_LIST.md | AI/human task list with working rules and incremental tasks | WORKING | All tasks are unchecked; likely predates recent physics work; rules section is evergreen but specific tasks may be stale or partially done. | | docs/formal/CLAUDE.md | docs/formal/CLAUDE.md — Authoring Conventions for the Formal Documentation Tier | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/archive/artifacts/kanban-workflow/MANIFEST.adoc | Artifact manifest for kanban workflow validation scripts | HISTORICAL | Tracks process-tooling artifacts from a past workflow setup session; no ongoing relevance to VM or kernel. | | docs/formal/README.md | docs/formal/ | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/scratch/assets/README.md | Binary assets holding area README | WORKING | Correctly flags `book-FIXED.docx` etc. as misplaced; the guidance (move to LFS/external) is still actionable. | | docs/formal/common/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/scratch/assets/book-FIXED.docx | Book/report Word document | WORKING | Binary asset misplaced in docs/assets; should move to LFS per assets/README.md guidance. | | docs/formal/cookbook/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/architecture/heartbeat_csv_export.md | Heartbeat CSV export design: format, columns, TODO status | WORKING | Several columns marked `⚠️ TODO`; matches CLAUDE.md note that `heartbeat_export_csv()` is not yet implemented; active design/tracking doc. | | docs/formal/dev-guide/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| ./docs/ontology.pdf | Compiled PDF of `ontology.tex` | CURRENT | Rendered output of `ontology.tex`; self-contained reference for academic inclusion. | | docs/formal/experiments/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| ./docs/ontology.tex | LaTeX source for formal ontology | CURRENT | Source of record matching `ONTOLOGY.md` content; used for journal/conference paper inclusion. | | docs/formal/patent/ | 1 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/archive/prog-prove.pdf | Unknown — likely Isabelle/HOL or proof-assistant tutorial PDF | HISTORICAL | Filename suggests a proof-programming reference; not authored by this project; reference material only. | | docs/formal/proofs/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/architecture/getting-started/DEVELOPER.md | Dev environment setup, Isabelle install | CURRENT | Generic setup instructions still match current build system. | | docs/formal/scraps/ | 1 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/architecture/getting-started/README.md | Getting-started index/TOC | CURRENT | Navigation page; links resolve to existing files. | | docs/formal/scraps/architecture/ | 49 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/architecture/getting-started/quick-start/factorial-doe.md | Quick-start for 2^6 per-loop factorial DoE | OBSOLETE | Describes retired `ENABLE_LOOP_1..6` compile-time toggles; replaced by L8 Jacquard runtime mode selector. Hardcoded `/home/rajames/...` paths. | | docs/formal/scraps/archive/ | 81 files | SUPERSEDED | Flagged obsolete in its own header. |
| docs/working/architecture/getting-started/quick-start/heartbeat-doe.md | Quick-start for heartbeat DoE run | HISTORICAL | Dated 2025-11-20, references a specific completed run directory and hardcoded user paths. | | docs/formal/scraps/experiments/ | 31 files | HISTORICAL | Flagged in its own header. |
| docs/working/architecture/getting-started/quick-start/optimization-doe.md | Quick-start for 5-opportunity optimization DoE | HISTORICAL | References dated result dirs from a completed tuning campaign; superseded conceptually by L8's data-driven design. | | docs/formal/scraps/hardware/ | 10 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/L8_WIRING_CODE_REVIEW_GUIDE.md | Code review guide for L8 wiring (L2/L3/L5/L6) | HISTORICAL | Dated 2025-12-05; matches current `physics_metadata.c` — completed, accurate review record. | | docs/formal/scraps/legal/ | 1 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/L8_WIRING_IMPLEMENTATION_SUMMARY.md | Summary of L8 gating implementation | HISTORICAL | Dated 2025-12-05, marked complete; verified consistent with current source. | | docs/formal/scraps/papers/ | 13 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/L8_WIRING_PLAN.md | Plan for wiring loops to L8 mode selector | SUPERSEDED | Superseded by L8_WIRING_IMPLEMENTATION_SUMMARY.md and L8_WIRING_CODE_REVIEW_GUIDE.md (plan was executed and reviewed). | | docs/formal/scraps/scratch/ | 23 files | HISTORICAL | Flagged in its own header. |
| docs/working/experiments/02-experiments/README.md | Experiments directory index | CURRENT | Accurately lists existing subdirectories. | | docs/formal/scraps/specifications/ | 1 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/factorial-doe/guide.md | Full 2^6 factorial DoE guide | OBSOLETE | Describes retired per-loop Makefile-toggle architecture, replaced by L8 Jacquard. | | docs/formal/ssrn/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/factorial-doe/incompatible-configs.md | Handling incompatible factorial loop configs | OBSOLETE | Build-time incompatibility handling for the retired 2^6 toggle experiment. | | docs/formal/user-guide/ | 2 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/factorial-doe/index.md | Index for factorial DoE docs | OBSOLETE | Points to stale doc paths; describes retired architecture. | | docs/formal/vol1-vm-physics/ | 9 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/factorial-doe/workflow.md | Factorial DoE data pipeline workflow | HISTORICAL | Documents completed 2025-11-19 factorial campaign that produced data behind current L8 design; toggle architecture retired. | | docs/formal/vol2-kernel/ | 8 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/heartbeat-doe/corrected-design.md | Heartbeat DoE corrected metric design | SUPERSEDED | Superseded by phase2-corrected.md ("corrected and finalized" version). | | docs/formal/vol3-research/ | 11 files | FORMAL | Press tier; see docs/formal/CLAUDE.md. |
| docs/working/experiments/02-experiments/heartbeat-doe/design.md | Original Phase 2 heartbeat DoE design | SUPERSEDED | Pre-correction draft; superseded by corrected-design.md / phase2-corrected.md. |
| docs/working/experiments/02-experiments/heartbeat-doe/execution-guide.md | How to run Phase 2 heartbeat DoE | HISTORICAL | Dated 2025-11-20, hardcoded stale path; describes running the now-superseded design. | ## docs/patent
| docs/working/experiments/02-experiments/heartbeat-doe/implementation-summary.md | Deliverables summary for heartbeat DoE | HISTORICAL | Point-in-time "complete" status snapshot dated 2025-11-20 for pre-correction design. |
| docs/working/experiments/02-experiments/heartbeat-doe/phase2-corrected.md | Final corrected heartbeat DoE design | WORKING | Latest version in the revision chain; still describes not-yet-fully-implemented work. | | Path | Title | Status | Notes |
| docs/working/experiments/02-experiments/james-law/protocol.md | SSM gravitational-collapse threshold hypothesis/protocol | WORKING | Forward-looking theoretical experiment protocol, no completion markers. | |---|---|---|---|
| docs/working/experiments/02-experiments/physics-optimization/doe-guide.md | Guide for 5-opportunity progressive optimization DoE | CURRENT | Generic script-driven methodology still consistent with current physics engine. | | docs/patent/CHANGES_SUMMARY.md | Patent Application Review and Changes | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/experiments/02-experiments/physics-optimization/execution-guide.md | Guide for 90-run comprehensive physics validation | CURRENT | Underlies the "0% variance across 90 runs" claim in CLAUDE.md. | | docs/patent/JARGON_CHANGES.md | Jargon Removal and Precision Language Changes | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/experiments/02-experiments/physics-optimization/hotwords-cache.md | Hot-words cache experiment results (1.78x speedup) | HISTORICAL | Completed-experiment results report with fixed numbers. | | docs/patent/README_V3.md | StarForth Patent Application Version 3.0 | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/experiments/02-experiments/physics-optimization/proposals.md | 9 proposed future optimization opportunities | WORKING | Living forward-looking proposal doc built on hotwords-cache result. | | docs/patent/USPTO_COVER_LETTER.md | USPTO PROVISIONAL PATENT APPLICATION | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/experiments/02-experiments/physics-optimization/reproduce.md | Reproduction recipe for hotwords-cache result | CURRENT | Narrow, still-valid step-by-step reproduction guide. | | docs/patent/bibliography/bibliography.tex | bibliography.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/OVERVIEW.md | Top-level architecture overview (3-layer model, physics loops, boot sequence) | WORKING | Header says "Status: Complete, 2025-12-14" but roadmap still frames StarKernel as "PLANNED"/HAL migration "IN PROGRESS," lagging CLAUDE.md's actual M0-M6-done/M7-in-progress state; needs a refresh pass. | | docs/patent/figures/fig1_snake_trajectory.pdf | fig1_snake_trajectory.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/README.md | Directory index/landing page for 03-architecture/ | WORKING | Shorter duplicate of OVERVIEW.md's roadmap; same staleness (treats StarKernel as not-yet-started); functions as nav index, content needs sync with CLAUDE.md. | | docs/patent/figures/fig2_K_vs_window.pdf | fig2_K_vs_window.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/adaptive-systems/adaptive-window-and-decay.md | Root-cause investigation: rolling-window shrink + decay_slope placeholder bugs | HISTORICAL | Dated 2025-11-08, "Root Cause Analysis Complete." Diagnostic/incident report; trigger doc for window-inference-redesign.md. | | docs/patent/figures/fig3_FFT_spectrum.pdf | fig3_FFT_spectrum.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/adaptive-systems/loop-5-sketch.md | Alternate Loop #5 proposal: prefetch-accuracy-driven binary-chop window tuning | SUPERSEDED | Superseded by window-inference-redesign.md. Undated draft ending in an open question to the user (never approved); the shipped Loop #5 uses Levene's test, not this mechanism. | | docs/patent/figures/fig4_golden_ratio_penalties.pdf | fig4_golden_ratio_penalties.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/adaptive-systems/multivariate-dynamics.md | Phase 2 DoE experiment design: multivariate stability fingerprinting across 7 metrics | WORKING | Dated 2025-11-20, "Status: Design Phase." Forward-looking proposal tied to still-unimplemented heartbeat instrumentation. | | docs/patent/figures/fig5_bimodal_distributions.pdf | fig5_bimodal_distributions.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/adaptive-systems/window-inference-redesign.md | Redesign of window-width inference using Levene's test on disjoint chunks | CURRENT | Dated 2025-11-19, "DESIGN (approved for implementation)." Matches the Loop #5/#6 mechanism CLAUDE.md/OVERVIEW.md describe as actually implemented (inference_engine.c). | | docs/patent/figures/fig6_performance_vs_k.pdf | fig6_performance_vs_k.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/README.md | Index/reading-order guide for HAL doc set | WORKING | Status table claims all 5 HAL docs "Complete, 2025-12-14," but describes target architecture per overview.md's own disclaimer, not built code; misleading without that caveat. | | docs/patent/figures/fig7_performance_by_regime.pdf | fig7_performance_by_regime.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/interfaces.md | hal_* C interface contract spec (time, interrupt, memory, console, cpu, panic) | WORKING | Normative target API design; current codebase uses sf_time_backend_t-style naming per overview.md — this HAL layer is not yet built as specified. | | docs/patent/final_provisional/cover_letter.txt | cover_letter.txt | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/migration-plan.md | 7-phase plan to migrate codebase to hal_* interfaces | WORKING | Forward plan ("Phase 2 IN PROGRESS" per roadmap); CLAUDE.md's current source tree shows this migration not yet executed. | | docs/patent/final_provisional/sb0015a.pdf | sb0015a.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/overview.md | HAL rationale/design-principles doc | WORKING | Contains the key disclaimer: "current codebase uses sf_time_backend_t... different naming" — explicitly flags the whole HAL doc family as target/aspirational, not current. | | docs/patent/final_provisional/sb0016.pdf | sb0016.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/platform-implementations.md | Example hal_* implementations for Linux and kernel platforms | OBSOLETE | Assumes src/platform/<platform>/hal_*.c layout; actual built StarKernel tree (per CLAUDE.md) uses src/starkernel/{arch,boot,capsule,hal,memory,...} — a different, already-implemented structure. | | docs/patent/final_provisional/ssm_RAJ_v1_patent_application.pdf | ssm_RAJ_v1_patent_application.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/hal/starkernel-integration.md | Kernel HAL integration guide, src/platform/kernel/ layout, milestone roadmap to "ok" prompt | OBSOLETE | Describes Milestone 1 "Boot + Serial Output" as a starting point; LithosAnanke is actually at v1.0.8 with M0-M6 complete, M7 in progress, using a wholly different src/starkernel/ directory structure. | | docs/patent/macros/commands.tex | commands.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/heartbeat-system/architecture.md | Proposes vm_tick() dispatcher centralizing Loop #3/#5 heartbeat logic | HISTORICAL | No date; ends in an open question, never confirmed adopted. Foundational rationale doc; superseded in specifics by instrumentation-plan.md's HeartbeatTickSnapshot design. | | docs/patent/main.pdf | main.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/heartbeat-system/critical-insight.md | Discovery memo: heartbeat tick rate is variable, not fixed; Stage 1 DoE baseline was flawed | HISTORICAL | Dated 2025-11-20, "Game-changer for Phase 2 DoE." Point-in-time investigation memo that directly motivated implementation-plan.md. | | docs/patent/main.tex | main.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/heartbeat-system/implementation-plan.md | Plan for HeartbeatRateSample logging to capture variable tick rate | SUPERSEDED | Superseded by instrumentation-plan.md. Same date (2025-11-20) and goal, but proposes an earlier/different struct (HeartbeatRateSample) than the HeartbeatTickSnapshot design CLAUDE.md cites as the live target. | | docs/patent/sb0015a.pdf | sb0015a.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/heartbeat-system/instrumentation-plan.md | Per-tick instrumentation plan: HeartbeatTickSnapshot, tick_buffer, heartbeat_export_csv() | WORKING | Explicitly the doc CLAUDE.md cites as current ("declared in include/vm.h, but heartbeat_export_csv() is not yet implemented"). Checklist entirely unchecked. | | docs/patent/sb0016.pdf | sb0016.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/heartbeat-system/segfault-analysis.md | Root-cause analysis of heartbeat-thread/main-thread race on RollingWindowOfTruth | HISTORICAL | Dated 2025-11-19, "Identified & Ready for Fix," includes a past-tense commit-message template implying the tuning_lock fix was applied. No current doc mentions this race as open. | | docs/patent/sections/00_claims_validation_v3.tex | 00_claims_validation_v3.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/feedback-loops-analysis.md | Investigative bug-hunt audit of 6 feedback loops (precursor to the 7-loop model) | SUPERSEDED | Superseded by feedback-loops.md. Dated 2025-11-08, full of strikethrough "FIXED" headers; covers only 6 loops, unlike the polished current 7-loop reference. | | docs/patent/sections/00_complete_patent_v3.tex | 00_complete_patent_v3.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/feedback-loops.md | Canonical reference: all 7 feedback loops, tuning knobs, related source files | CURRENT | Matches CLAUDE.md's explicit citation ("all 7 loops detailed") verbatim; clean finished reference table covering Loops #1-7 including #5/#6 inference. | | docs/patent/sections/01_title.tex | 01_title.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/metrics-and-knobs.md | Gap-analysis backlog of metrics not yet collected (stack depth, bucket histograms, etc.) | WORKING | Explicitly self-titled "GAPS ONLY"; prioritized TODO backlog, not a current-state description; some gaps may have since been filled. | | docs/patent/sections/01_title_v2.tex | 01_title_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/monitoring-principles.md | Doctrinal rules for non-perturbative monitoring instrumentation | CURRENT | Presents itself as binding/evergreen ("canonical rules for ALL AI assistants"); uses an older "four core loops (FL1-FL4)" framing that should be reconciled with the current 7-loop model, but the doctrine itself remains in force. | | docs/patent/sections/02_field.tex | 02_field.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/ssm-equations.md | Exploratory mathematical modeling of SSM via physics analogies for patent/DARPA strategy | HISTORICAL | Dated 2025-11-29, self-labeled "Status: Research Analysis - Exploratory." Predates Jacquard naming; speculates generically about future "L8" without Jacquard/attractor-bucket/mode-name vocabulary. | | docs/patent/sections/02_field_v2.tex | 02_field_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/ssm-raw-data-analysis.md | Raw experimental data analysis from a specific Nov 22-27 2025 DoE campaign (51,840 runs) | HISTORICAL | Dated 2025-11-29; tied to specific named CSV files and a calendar-based "Next Steps" plan. Uses "L8" and 4 of 6 Jacquard mode names but never "Jacquard" — an early/transitional naming stage. | | docs/patent/sections/03_background.tex | 03_background.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/physics-engine/steady-state-machine.md | Formal theoretical definition of SSM as a computational model (attractor basins, axioms) | OBSOLETE | Zero mentions of "Jacquard," "L8," "attractor bucket," or the six named modes from CLAUDE.md; reads as a conceptual precursor never reconciled with the concrete ssm_jacquard.c system. | | docs/patent/sections/03_background_v2.tex | 03_background_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/pipelining/context-window-and-binary-chop.md | Context-window infrastructure (Knob #6) + planned binary-chop tuning for Loop #4 | WORKING | Dated 2025-11-06, "Phase 1 Extension Complete," but binary-chop decision logic explicitly a doubling-rule stub with "Phase 2 (Next session)" unchecked; corroborated as still-unutilized by wired-not-utilized.md. | | docs/patent/sections/04_summary.tex | 04_summary.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/pipelining/design.md | Master architectural design for pipelining/speculative execution (Loop #4) | HISTORICAL | No date/status stamp; entirely aspirational ("Goal:", "Hypothesis"); Phase 3+ (actual prefetching/speculation) roadmap items remain unchecked and appear unrealized per wired-not-utilized.md. | | docs/patent/sections/04_summary_v2.tex | 04_summary_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/pipelining/phase-1-instrumentation.md | Completed-checkpoint record of Phase 1 transition-tracking instrumentation | HISTORICAL | Dated 2025-11-06, "Phase 1 Complete," 731 tests passing — accurate closed record of one sub-phase; its Phase 2-4 TODOs were never closed per wired-not-utilized.md. | | docs/patent/sections/05_drawings.tex | 05_drawings.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/pipelining/wired-not-utilized.md | Critical-issue report: pipelining decision/speculation logic defined but never called | WORKING | No date/commit stamp; ends on an unactioned recommendation ("Option A: Disable") with no resolution language. Indicates Loop #4's prediction/speculation half may still be inactive in code. | | docs/patent/sections/06_detailed_description.tex | 06_detailed_description.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/architecture/03-architecture/word-acl/DESIGN.md | Full design spec for word-level ACL system (C fields, ACL.4th, zuse.4th, two-console model) | CURRENT | Explicitly the doc CLAUDE.md designates authoritative; internal 8-phase punch list (Phases 1-6 done, 7-8 remaining) matches CLAUDE.md's summary exactly. | | docs/patent/sections/06_detailed_description_v2.tex | 06_detailed_description_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/README.md | Quality directory index | OBSOLETE | States "18 modules"; current is 22 categories/936+ tests per CLAUDE.md. | | docs/patent/sections/07_embodiments.tex | 07_embodiments.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/audits/codebase-audit-report.md | Full codebase audit | HISTORICAL | Dated 2025-12-03; point-in-time snapshot, paired with corrective-actions.md. | | docs/patent/sections/08_claims.tex | 08_claims.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/audits/corrective-actions.md | Resolution log for codebase audit | HISTORICAL | Dated 2025-12-03, v3.0.1, "COMPLETE" — 21/22 issues resolved; companion to codebase-audit-report.md. | | docs/patent/sections/08_claims_REAL.tex | 08_claims_REAL.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/audits/implementation-audit.md | Adaptive tuning implementation audit | HISTORICAL | Dated 2025-11-19, references 787/840 tests (now 936+); overtaken by later OPP reports. | | docs/patent/sections/08_claims_v2.tex | 08_claims_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/audits/section-2-audit.md | Physics subsystem safety audit (full) | HISTORICAL | Dated 2025-11-20; paired with section-2-executive-summary.md. | | docs/patent/sections/09_validation.tex | 09_validation.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/audits/section-2-executive-summary.md | Physics safety audit executive summary | HISTORICAL | Dated 2025-11-20, "complete - awaiting final approval"; summary counterpart to section-2-audit.md. | | docs/patent/sections/09_validation_v2.tex | 09_validation_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/phase-tracking/phase-2-implementation-checklist.md | Checklist for heartbeat instrumentation (tick_buffer/snapshot) | WORKING | CLAUDE.md confirms struct exists but heartbeat_export_csv() still not implemented — open, unrealized plan. | | docs/patent/sections/10_implementation.tex | 10_implementation.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/phase-tracking/phase-2-issues-identified.md | Float/double violations root-cause list in physics code | HISTORICAL | Dated 2025-11-08, "in progress" at the time; precedes implementation-checklist. | | docs/patent/sections/11_abstract.tex | 11_abstract.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/phase-tracking/phase-2a-session-summary.md | Session summary: WORD_FROZEN flag + linear decay | HISTORICAL | Dated 2025-11-07, "complete & validated"; distinct earlier "Phase 2a" thread. | | docs/patent/sections/11_abstract_REAL.tex | 11_abstract_REAL.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/regression/detection-framework.md | Regression detection framework design (for OPP #2+) | HISTORICAL | Dated 2025-11-19, design doc later used in opp-02-report.md. | | docs/patent/sections/11_abstract_v2.tex | 11_abstract_v2.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/regression/opp-02-report.md | OPP #2 window-width tuning experiment report | HISTORICAL | Dated 2025-11-19, "complete"; recommends a config for OPP #3 — completed dated report. | | docs/patent/sections/11_appendix.tex | 11_appendix.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/validation/break-me-report.md | Adversarial/fuzz testing report (intended) | DELETE | File is empty (0 bytes); never written despite break_me_tests.c existing. | | docs/patent/sections/12_appendix.tex | 12_appendix.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/validation/comprehensive-physics-validation.md | Triple-blind 90-run DoE physics validation protocol | HISTORICAL | Dated 2025-11-06; source protocol behind the "0% variance across 90 runs" figure cited in CLAUDE.md. | | docs/patent/sections/RAJ_v1_01_background.tex | RAJ_v1_01_background.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/validation/phase-1-protocol.md | GitHub governance/document-routing validation protocol | OBSOLETE | Dated 2025-11-03; describes a governance/vault repo system absent from current architecture, unrelated to physics DoE. | | docs/patent/sections/RAJ_v1_02_summary.tex | RAJ_v1_02_summary.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/quality/validation/phase-2-executive-summary.md | DoE paradigm shift: factorial to multivariate dynamics (750-run plan) | HISTORICAL | Dated 2025-11-20, "design complete, ready for implementation." | | docs/patent/sections/RAJ_v1_03_drawings.tex | RAJ_v1_03_drawings.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/README.md | Ops directory index / build & CI overview | CURRENT | Build/test commands match current Makefile; honestly labels CI/CD section "(Future)". | | docs/patent/sections/RAJ_v1_04_detailed_description.tex | RAJ_v1_04_detailed_description.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/backlog-gatekeeper.md | Backlog governance (ECO/CAPA gatekeeper) | OBSOLETE | References a `.github/workflows/...` file that doesn't exist; no `.github/` directory in repo at all. | | docs/patent/sections/RAJ_v1_05_claims.tex | RAJ_v1_05_claims.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/jenkins-pipeline-guide.adoc | Jenkins CI pipeline architecture | OBSOLETE | No Jenkinsfile or CI config exists anywhere in the repo. | | docs/patent/sections/RAJ_v1_06_abstract.tex | RAJ_v1_06_abstract.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/qa-intake-workflow.adoc | QA defect intake / CAPA process | OBSOLETE | Cites stale version v2.0.2 (current v3.0.3); references nonexistent GitHub issue templates and Jenkins automation. | | docs/patent/sections/architecture_diagram_clean.tex | architecture_diagram_clean.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/refinement/annotations.adoc | C/Isabelle refinement annotation guide | WORKING | "Phase 1 in-progress" header; active methodology guide for ongoing refinement work. | | docs/patent/ssm_RAJ_v1_patent_application.pdf | ssm_RAJ_v1_patent_application.pdf | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/refinement/capa.adoc | C/Isabelle refinement defect tracking log | WORKING | All phases "not started," currently empty live tracking doc. | | docs/patent/ssm_RAJ_v1_patent_application.tex | ssm_RAJ_v1_patent_application.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/refinement/roadmap.adoc | C/Isabelle refinement roadmap | WORKING | All key functions listed "OPEN"; active planning doc with 6-8 month estimate. | | docs/patent/ssm_provisional_patent.tex | ssm_provisional_patent.tex | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/archive/operations/workflow.md | CI/CD trunk-based branch workflow (devl/test/qual/prod) | OBSOLETE | Describes branches/Jenkins triggers that don't exist; repo only has master and feature branches. |
| docs/working/archive/research/README.md | Research directory index | SUPERSEDED | References a patent-filing placeholder/submission package now superseded by the published SSRN paper. | ## docs/pptx
| docs/working/archive/research/doe-metrics-schema.md | DoE CSV metrics schema (35 columns) | HISTORICAL | Dated 2025-11-19, predates the 2025-12-08 CSV-export suppression noted in CLAUDE.md. |
| docs/working/archive/research/literature-review.md | Literature positioning for the optimization paper | SUPERSEDED | Draft feeder material for the now-published SSRN paper. | | Path | Title | Status | Notes |
| docs/working/archive/research/research-outline.md | Paper outline draft ("working title" + alternatives) | SUPERSEDED | Pre-publication draft outline; paper has since been published. | |---|---|---|---|
| docs/working/archive/research/results-for-publication.md | Draft abstract targeting PLDI/ASPLOS | SUPERSEDED | Draft abstracts for venues other than where it was ultimately published (SSRN). | | docs/pptx/01-technical-elevator-pitch.pptx | 01-technical-elevator-pitch.pptx | CURRENT | |
| docs/working/archive/session-logs/2025-11-20-recap.md | Dated session recap (DoE multivariate dynamics pivot) | HISTORICAL | Explicitly dated point-in-time design discussion record. | | docs/pptx/02-nontechnical-elevator-pitch.pptx | 02-nontechnical-elevator-pitch.pptx | CURRENT | |
| docs/working/archive/session-logs/2025-11-26-worklog.md | Dated work log (L8 Jacquard integration) | HISTORICAL | Explicitly dated; documents the l8-final-integration milestone. | | docs/pptx/03-academic-overview.pptx | 03-academic-overview.pptx | CURRENT | |
| docs/working/archive/session-logs/README.md | Session-logs directory index | CURRENT | Accurately describes folder purpose; explicitly warns logs may be outdated. | | docs/pptx/04-phd-deep-dive.pptx | 04-phd-deep-dive.pptx | CURRENT | |
| docs/working/archive/session-logs/experimental-addendum.md | Mislabeled: actually a "StarForth to StarshipOS Hybrid Kernel Transformation Plan" | OBSOLETE | Early kernel design plan superseded by the actually-implemented LithosAnanke v1.0.8 architecture (M0-M7). | | docs/pptx/README.md | docs/pptx/ | CURRENT | |
| docs/working/archive/session-logs/experimental-iteration-usage.md | Usage guide for run_doe.sh / run_experimental_iteration.sh | WORKING | Matching scripts still exist in scripts/; living usage guide, not a dated log. |
| docs/working/archive/session-logs/serialized-questing-pike.md | Informal narrative on physics-analogy overclaiming risk | HISTORICAL | Captured point-in-time exploratory discussion, not a guide. | ## docs/reference
| ./docs/patent/CHANGES_SUMMARY.md | Patent revision log (title, James Law language, claim changes) dated 2025-12-10 | HISTORICAL | Records decisions made during v2 revisions; accurate for its time but describes edits already applied — not a live working document. |
| ./docs/patent/JARGON_CHANGES.md | Term-replacement log (e.g. "Execution Heat" → "Execution Frequency Counters") dated 2025-12-10 | HISTORICAL | Records terminology decisions already baked into _v2 section files; useful audit trail but not a living document. | | Path | Title | Status | Notes |
| ./docs/patent/Makefile | LaTeX build rules for `main.tex` | CURRENT | Minimal but functional; drives `pdflatex main.tex` double-pass build. | |---|---|---|---|
| ./docs/patent/README_V3.md | Overview claiming `patent_v3_complete.tex` is the master document | OBSOLETE | Describes a master file (`patent_v3_complete.tex`) that does not exist; structure does not match the actual `main.tex`-based layout. | | docs/reference/DICTIONARY.md | LithosAnanke / StarForth — Word Dictionary Reference | CURRENT | |
| ./docs/patent/USPTO_COVER_LETTER.md | Draft USPTO provisional cover letter with placeholder contact fields | WORKING | Contact fields (`[Your email]`, `[Your phone]`) still blank; needs completion before filing. | | docs/reference/L8_ADAPTIVE_CONFIG_TABLE.md | L8 Jacquard: Adaptive 128-Config Heat-Ranked Selector | CURRENT | |
| ./docs/patent/main.tex | Master LaTeX patent document; inputs _v2 section files | CURRENT | This is the live build root; actual `\input` order confirmed. | | docs/reference/M7.1.md | M7.1: Init Capsule Architecture | CURRENT | |
| ./docs/patent/sb0015a.pdf | USPTO form SB0015a (Provisional Application cover sheet) | CURRENT | Byte-identical to `final_provisional/sb0015a.pdf` (205016 bytes both); root copy is authoritative working copy. | | docs/reference/ONTOLOGY.md | StarForth Ontology, Taxonomy, and Lexicon | CURRENT | |
| ./docs/patent/sb0016.pdf | USPTO form SB0016 (fee transmittal or declaration) | WORKING | Differs from `final_provisional/sb0016.pdf` (557654 vs 577171 bytes); root copy is smaller — likely a prior draft; the larger `final_provisional/` copy appears to be the filed version. | | docs/reference/ROADMAP.md | LithosAnanke Roadmap | CURRENT | Roadmap and the ratified release-versioning policy. |
| ./docs/patent/ssm_RAJ_v1_patent_application.pdf | Compiled patent application PDF | CURRENT | Byte-identical to `final_provisional/ssm_RAJ_v1_patent_application.pdf` (1735085 bytes both); root copy is authoritative working copy. | | docs/reference/STARFORTH_PRIMITIVES.md | StarForth Primitive Word Reference | CURRENT | |
| ./docs/patent/ssm_provisional_patent.tex | Standalone monolithic provisional patent LaTeX document | SUPERSEDED | Self-contained single-file precursor; superseded by the modular `main.tex` + sections/ architecture. | | docs/reference/hosted-acceptance-test/README.md | Hosted StarForth — 3-Architecture Acceptance Test | CURRENT | |
| ./docs/patent/sections/01_title_inventors.tex | Section file — title/inventors | OBSOLETE | Does not exist on disk; name never appears in any `\input` in main.tex. | | docs/reference/kernel-args/DESIGN.md | Kernel Command-Line Arguments (KernelArgs) | CURRENT | |
| ./docs/patent/sections/02_cross_reference.tex | Section file — cross-references | OBSOLETE | Does not exist on disk; the 02_* slot in main.tex is `02_field_v2`, not a cross-reference section. | | docs/reference/kernel-args/README.md | docs/reference/kernel-args/ | CURRENT | |
| ./docs/patent/sections/02_cross_reference_v2.tex | Section file — cross-references v2 | OBSOLETE | Does not exist on disk; main.tex uses `02_field_v2`, not a cross-reference section. | | docs/reference/word-acl/DESIGN.md | Word-Level ACL System | CURRENT | |
| ./docs/patent/sections/03_background.tex | Background of the Invention — original draft | SUPERSEDED | Exists on disk; superseded by `03_background_v2.tex` which main.tex actually inputs. | | docs/reference/word-acl/README.md | docs/reference/word-acl/ | CURRENT | |
| ./docs/patent/sections/03_background_v2.tex | Background of the Invention — revised | CURRENT | Inputted by main.tex. |
| ./docs/patent/sections/04_summary.tex | Summary of the Invention — original draft | SUPERSEDED | Exists on disk; superseded by `04_summary_v2.tex` which main.tex actually inputs. | ## docs/v4.0.0
| ./docs/patent/sections/04_summary_v2.tex | Summary of the Invention — revised | CURRENT | Inputted by main.tex. |
| ./docs/patent/sections/05_brief_description.tex | Brief Description of Drawings — original | OBSOLETE | Does not exist on disk; the 05_* slot in main.tex is `05_drawings`. | | Path | Title | Status | Notes |
| ./docs/patent/sections/05_brief_description_v2.tex | Brief Description of Drawings — v2 | OBSOLETE | Does not exist on disk; main.tex uses `05_drawings`, not this name. | |---|---|---|---|
| ./docs/patent/sections/06_detailed_description.tex | Detailed Description — original draft | SUPERSEDED | Exists on disk; superseded by `06_detailed_description_v2.tex` which main.tex actually inputs. | | docs/v4.0.0/DECOMPOSITION.md | StarForth v4.0.0 — Primitive Decomposition | CURRENT | |
| ./docs/patent/sections/06_detailed_description_v2.tex | Detailed Description — revised | CURRENT | Inputted by main.tex. | | docs/v4.0.0/ENGINE.md | StarForth v4.0.0 — The F18 engine in the VM's place | CURRENT | |
| ./docs/patent/sections/07_claims.tex | Claims section — original | OBSOLETE | Does not exist on disk; the 07_* slot in main.tex is `07_embodiments`, not claims. | | docs/v4.0.0/JUSTIFICATION.md | StarForth v4.0.0 — Justification | CURRENT | |
| ./docs/patent/sections/07_claims_v2.tex | Claims section — v2 | OBSOLETE | Does not exist on disk; main.tex uses `07_embodiments` and `08_claims_v2` for claims. | | docs/v4.0.0/MESH.md | StarForth v4.0.0 — Talking nodes | CURRENT | |
| ./docs/patent/sections/08_abstract.tex | Abstract section | OBSOLETE | Does not exist on disk; main.tex uses `11_abstract_v2` for the abstract. | | docs/v4.0.0/NUCLEUS.md | StarForth v4.0.0 — Nucleus, FORTH-79 Capsule and POST | CURRENT | |
| ./docs/patent/sections/RAJ_v1_01_title_inventors.tex | RAJ v1 title/inventors section | OBSOLETE | Does not exist on disk; entire RAJ_v1_* naming scheme not referenced in main.tex. | | docs/v4.0.0/POST79.md | POST for the FORTH-79 Required Word Set: where it departs from v3 | CURRENT | |
| ./docs/patent/sections/RAJ_v1_02_cross_reference.tex | RAJ v1 cross-reference section | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/V3-PARITY.md | StarForth v4.0.0 — Parity with v3 up to the first prompt | CURRENT | |
| ./docs/patent/sections/RAJ_v1_03_background.tex | RAJ v1 background section | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/plans/2026-10-06-step6-storage.md | Step 6: Storage Implementation Plan (revised 2026-10-07) | HISTORICAL | An executed step plan. |
| ./docs/patent/sections/RAJ_v1_04_summary.tex | RAJ v1 summary section | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/plans/2026-10-07-step6b-post.md | Step 6b: POST Is the Kernel's — Implementation Plan | HISTORICAL | An executed step plan. |
| ./docs/patent/sections/RAJ_v1_05_brief_description.tex | RAJ v1 brief description section | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/plans/2026-10-07-step6c-refusals-and-waits.md | Step 6c: Refusals and Waits — Implementation Plan | HISTORICAL | An executed step plan. |
| ./docs/patent/sections/RAJ_v1_06_detailed_description.tex | RAJ v1 detailed description section | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/plans/2026-10-07-step6d-the-wait.md | Step 6d: The Wait — Implementation Plan | HISTORICAL | An executed step plan. |
| ./docs/patent/final_provisional/README.md | README for the final_provisional/ subdirectory | OBSOLETE | Does not exist on disk. | | docs/v4.0.0/plans/2026-10-08-step6e-messages-on-the-wire.md | Step 6e: Messages on the Wire — Implementation Plan | HISTORICAL | An executed step plan. |
| ./docs/patent/final_provisional/sb0015a.pdf | USPTO form SB0015a — filed copy | SUPERSEDED | Byte-identical to root `sb0015a.pdf` (205016 bytes); root copy is the working canonical version. |
| ./docs/patent/final_provisional/sb0016.pdf | USPTO form SB0016 — filed copy | CURRENT | Differs from root `sb0016.pdf` (577171 vs 557654 bytes); this larger copy is the filed/submitted version and is the more complete document. | ## docs/working
| ./docs/patent/final_provisional/ssm_RAJ_v1_patent_application.pdf | Compiled patent application PDF — filed copy | SUPERSEDED | Byte-identical to root `ssm_RAJ_v1_patent_application.pdf` (1735085 bytes); root copy is the working canonical version. |
| docs/working/scratch/src/INTEGRATION_NOTES.adoc | StarForth↔StarshipOS sync scripts (integrator.sh) | HISTORICAL | Describes ad-hoc integrator.sh scripts and one-day debugging session; superseded by formal capsule/build pipeline in current CLAUDE.md. Worth keeping as record of integration approach. | | Path | Title | Status | Notes |
| docs/working/scratch/src/L4RE_INTEGRATION_TODO.adoc | L4Re integration checklist, hardcoded local paths | OBSOLETE | References absolute local dev paths (`/home/rajames/CLionProjects/...`) and a TODO checklist for copying platform files; current architecture has moved on. | |---|---|---|---|
| docs/working/scratch/src-index.adoc | docs/src documentation index | WORKING | Active index/TOC for the docs/src tree, but contains multiple dead links (ABI.adoc, BLOCK_STORAGE_GUIDE.adoc, WORD_DEVELOPMENT.adoc, TESTING.adoc, BREAK_ME_REPORT.adoc, GAP_ANALYSIS.adoc) — needs pruning/repair. | | docs/working/README.md | docs/working/ — Living Documentation | WORKING | |
| docs/working/architecture/architecture-internals/INIT_SYSTEM.adoc | INIT system / conf/init.4th boot mechanism | CURRENT | Describes init.4th, INIT word, dictionary fence — matches current capsule/init architecture described in CLAUDE.md. | | docs/working/architecture/03-architecture/OVERVIEW.md | StarForth Architecture Overview | WORKING | |
| docs/working/architecture/architecture-internals/MESSAGING.adoc | Thermodynamic "Message Field" model for StarshipOS IPC | WORKING | Forward-looking design doc for a not-yet-implemented StarshipOS messaging subsystem; consistent with physics/thermodynamic metaphor language. | | docs/working/architecture/03-architecture/README.md | Architecture | WORKING | |
| docs/working/scratch/src/bug_report.adoc | GitHub issue template (bug report) converted to AsciiDoc | DELETE | Generic GitHub bug-report template with smartphone/browser/OS fields irrelevant to a CLI FORTH VM; auto-converted from `.github/ISSUE_TEMPLATE`; no project-specific value. | | docs/working/architecture/03-architecture/adaptive-systems/adaptive-window-and-decay.md | Adaptive Window Shrinking & Decay Slope Investigation | WORKING | |
| docs/working/architecture/build-and-tooling/BUILD_OPTIONS.adoc | Build-time flags/defines reference | CURRENT | Cross-checked flag names against Makefile; consistent catalog of build options, actively useful reference. | | docs/working/architecture/03-architecture/adaptive-systems/multivariate-dynamics.md | StarForth Multivariate Coupled Dynamics Experiment | WORKING | |
| docs/working/architecture/build-and-tooling/DOCUMENTATION_README.adoc | How docs/API docs are generated (make docs, Doxygen→AsciiDoc) | CURRENT | Describes `docs/src/appendix/` generation via `scripts/generate-doxygen-appendix.sh`, directly wired into Makefile. | | docs/working/architecture/03-architecture/adaptive-systems/window-inference-redesign.md | Window Width Inference Redesign - Statistically Valid Approach | WORKING | |
| docs/working/architecture/build-and-tooling/INIT_TOOLS.adoc | tools/extract-init and init.4th↔disk image sync tooling | WORKING | Describes `tools/extract-init`; tool binary not confirmed in current `tools/` directory — may have been renamed; treat as living doc needing verification. | | docs/working/architecture/03-architecture/heartbeat-system/architecture.md | VM Heartbeat Architecture: Centralized Time-Based Tuning | WORKING | |
| docs/working/hardware/PGO_GUIDE.adoc | Profile-Guided Optimization guide | WORKING | Content matches current Makefile `pgo`/`pgo-build`/`pgo-perf`/`pgo-valgrind` targets exactly, but the document's own title line literally reads "QUARANTiNE ME MOTHERFUCKER" — self-flagged for review before being trusted as polished. | | docs/working/architecture/03-architecture/heartbeat-system/critical-insight.md | CRITICAL INSIGHT: Heartbeat Rate is Variable, Not Fixed | WORKING | |
| docs/working/hardware/PLATFORM_BUILD_GUIDE.adoc | Cross-compilation / platform build matrix (POSIX, L4Re) | CURRENT | Matches Makefile `L4RE=1` flag and platform/time_posix.c, platform/time_l4re.c files in src/platform/. | | docs/working/architecture/03-architecture/heartbeat-system/instrumentation-plan.md | Heartbeat Per-Tick Instrumentation Plan | WORKING | |
| docs/working/scratch/ci-cd/FMEA_BLOCKING_GATES.adoc | FMEA gating for CAPA/ECR/ECO governance workflow | CURRENT | Dated 2025-11-03, describes active GitHub Workflows + pending Jenkins governance gate; consistent with other governance docs. | | docs/working/architecture/03-architecture/heartbeat-system/segfault-analysis.md | Heartbeat Segfault Root Cause Analysis & Repair | WORKING | |
| docs/working/scratch/ci-cd/GITHUB_ISSUES_GOVERNANCE_FLOW.adoc | Relationship between GitHub Issues and governance in_basket | CURRENT | Same governance doc set, dated 2025-11-03, internally consistent. | | docs/working/architecture/03-architecture/physics-engine/feedback-loops.md | StarForth Physics Feedback Loops | WORKING | The seven feedback loops. |
| docs/working/scratch/ci-cd/GOVERNANCE_INPUT_AUDIT.adoc | Audit/compliance checklist for governance input routing | CURRENT | Dated 2025-11-03, "COMPLIANT" audit result; part of active governance documentation set. | | docs/working/architecture/03-architecture/physics-engine/monitoring-principles.md | StarForth Physics Runtime | WORKING | |
| docs/working/scratch/ci-cd/JENKINS_GOVERNANCE_INTEGRATION.adoc | Jenkins pipeline → governance in_basket integration spec | CURRENT | Same active governance doc set, dated 2025-11-03. | | docs/working/architecture/03-architecture/physics-engine/ssm-equations.md | Mathematical Analysis of the Steady-State Machine | WORKING | |
| docs/working/scratch/src/development/AGENTS.adoc | Repository guidelines / coding conventions | DELETE | Duplicate of docs/working/scratch/AGENTS.md (the live version); older AsciiDoc precursor with stale binary path (`./build/starforth`). Archived in docs/trash/duplicates-pass4.tar.gz. | | docs/working/architecture/03-architecture/physics-engine/ssm-raw-data-analysis.md | Steady-State Machine (SSM): Raw Experimental Data Analysis | WORKING | |
| docs/working/scratch/src/development/CONTRIBUTING.adoc | Generic contribution guide for "StarshipOS" | OBSOLETE | Boilerplate/templated contribution guide (placeholder `coc-contact@example.org`, generic Conventional Commits advice) not tailored to actual StarForth workflow or governance process; contradicts more specific and current ci-cd governance docs. | | docs/working/architecture/03-architecture/pipelining/context-window-and-binary-chop.md | Phase 1 Extension: Context Window & Phase 2 Binary Chop Tuning | WORKING | |
| docs/working/architecture/doxygen/DOXYGEN_QUICK_REFERENCE.adoc | Doxygen comment cheat-sheet | CURRENT | Matches `make docs`/`make docs-html` targets and Doxygen pipeline; straightforward reference card still applicable. | | docs/working/architecture/03-architecture/pipelining/design.md | FORTH VM Pipelining & Speculative Execution Design | WORKING | |
| docs/working/architecture/doxygen/DOXYGEN_STYLE_GUIDE.adoc | Doxygen documentation style guide | CURRENT | Companion to quick-reference; consistent with active Doxygen→AsciiDoc/HTML/PDF pipeline. | | docs/working/architecture/03-architecture/pipelining/phase-1-instrumentation.md | Phase 1: Pipelining Instrumentation | WORKING | |
| docs/working/scratch/src/feature_request.adoc | GitHub issue template (feature request) converted to AsciiDoc | DELETE | Generic GitHub feature-request template, garbled by adoc conversion; no project-specific content. | | docs/working/architecture/03-architecture/pipelining/wired-not-utilized.md | Pipelining Feedback Loop: WIRED BUT NOT UTILIZED (Critical Issue) | WORKING | |
| docs/working/architecture/getting-started/INSTALL.adoc | Installation guide (prerequisites, build/install) | WORKING | References `./build/starforth` run path rather than current `./build/amd64/<profile>/starforth` convention; otherwise generally accurate. | | docs/working/architecture/ARTEMIS-BAM-ACCEPTANCE-20260703.md | Artemis BAM — Phase 1 Acceptance Report | WORKING | |
| docs/working/architecture/getting-started/QUICKSTART.adoc | Quick-start build/run guide | WORKING | Same stale-path issue (`./build/starforth` instead of `./build/amd64/standard/starforth`); otherwise build command list matches current Makefile targets. | | docs/working/architecture/ARTEMIS-BLOCK-PHYSICS-DESIGN-20260708.md | Artemis Block Heat Physics — Design Doc | WORKING | |
| docs/working/scratch/governance/index.adoc | Pointer/redirect to external StarForth-Governance repo | CURRENT | Tiny stub file that redirects to the external governance repository README; still valid as a redirect. | | docs/working/architecture/ARTEMIS-FREEMAP-CAPSULE-RESERVATION-GAP-20260710.md | Artemis Free-Map Doesn't Reserve Capsule-Claimed Blocks | WORKING | |
| docs/working/scratch/COMMUNICATION_GUIDE.adoc | "Analogy cheat sheet" for explaining physics-driven OS concept to various audiences | WORKING | Internal communications/marketing aid; not tied to specific code, ages well, still usable living document. | | docs/working/architecture/CAPSULE-BLOCK-PERSISTENCE-BOUNDARY-FINDING-20260709.md | Capsule Loader — Missing Persistence Boundary Check | WORKING | |
| docs/working/scratch/GOVERNANCE_EXPORT_NOTES.adoc | Checklist of Phase 1 physics artifacts to mirror into governance repo | WORKING | Dated 2025-10-23; references HOLA_PROTOCOL.adoc and formal/Physics_*.thy files which still exist — consistent and current as an internal checklist. | | docs/working/architecture/CAPSULE-LOADER-DEFINITIONS-ONLY-DESIGN-20260709.md | Capsules Load Definitions Only — Design Doc | WORKING | |
| docs/working/specifications/HOLA_PROTOCOL.adoc | HOLA shared-memory analytics protocol spec | CURRENT | Cross-checked against `include/physics_runtime.h`: HOLA_SHARED_MAGIC, HOLA_PROTOCOL_MAJOR/MINOR, and the analytics header struct all exist verbatim in current source — accurate technical reference. | | docs/working/architecture/DOE-LIBRARY-HOWTO-20260819.md | DoE Library HOWTO — `capsules/doe.4th` | CURRENT | HOWTO for capsules/doe.4th. |
| docs/working/architecture/MAMA_FORTH_SUPERVISOR_ARCHITECTURE.adoc | Multi-VM supervisor architecture ("Mama Forth") | WORKING | Concept is alive in current code — `src/starkernel/capsule/mama_forth_words.c` exists and capsule birth protocol (MAMA_INIT capsule type) matches CLAUDE.md; this doc appears to be the design precursor to the now-partially-implemented capsule system. | | docs/working/architecture/K-PUSH-DICTIONARY-SHADOWING-BUG-20260704.md | K-PUSH Dictionary Shadowing Bug — Full Report | WORKING | |
| docs/working/scratch/src/internal/PHASE_2A_COMPLETION_REPORT.adoc | Completion report: Freeze flag + linear decay (Phase 2a) | HISTORICAL | Accurate closed record dated 2025-11-07; feature is shipped and stable — downgraded from CURRENT as a completion record, not a living doc. | | docs/working/architecture/MAMA_FORTH_SUPERVISOR_ARCHITECTURE.adoc | Mama Forth: Multi-VM Supervisor Architecture | WORKING | |
| docs/working/scratch/src/internal/PHASE_2_IMPLEMENTATION_SUMMARY.adoc | Phase 2 action-item summary pointing to design + completion docs | HISTORICAL | Companion index to PHASE_2A_COMPLETION_REPORT; both docs describe a completed, closed phase — downgraded from CURRENT. | | docs/working/architecture/PHYSICS_CONE_OF_INFLUENCE_DESIGN.adoc | Physics Engine: Cone of Influence Design | WORKING | |
| docs/working/scratch/src/internal/PHASE_2_PHYSICS_DECAY_AND_FREEZE.adoc | Design spec for decay/freeze mechanisms | HISTORICAL | Marked "Design Phase" as of 2025-11-07, but the corresponding PHASE_2A_COMPLETION_REPORT.adoc shows this has since been implemented and validated — spec is now historical record of the design rationale behind the now-shipped feature. | | docs/working/architecture/PHYSICS_CONTROL_SYSTEM_DESIGN.adoc | Physics Control System: Observables → Scheduling & Memory Management | WORKING | |
| docs/working/architecture/PHYSICS_CONE_OF_INFLUENCE_DESIGN.adoc | Feedback-control architecture design ("cone of influence") | WORKING | Forward-looking architectural design note for scheduling/control; consistent with physics engine terminology still in active use. | | docs/working/architecture/PHYSICS_SIGNAL_MAP.adoc | Physics Signal Inventory | WORKING | |
| docs/working/architecture/PHYSICS_CONTROL_SYSTEM_DESIGN.adoc | Physics observables → scheduling/memory management integration design | WORKING | Design-stage architecture note, not yet fully realized; scheduling/memory integration is still aspirational per current CLAUDE.md roadmap. | | docs/working/architecture/README.md | docs/working/architecture/ | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_HOTWORDS_CACHE_INTEGRATION.adoc | Hot-words cache integration implementation checklist | SUPERSEDED | Describes a step-by-step plan to add hot-words caching; this feature is now implemented and documented as "Loop #1 — Execution Heat" / `ENABLE_HOTWORDS_CACHE=1` / `dictionary_heat_optimization.c` in current CLAUDE.md. | | docs/working/architecture/SDK-HOWTO-20260819.md | SDK HOWTO — `capsules/sdk.4th` | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_IMPLEMENTATION_OPTIONS.adoc | Three implementation-path options for physics engine | HISTORICAL | "Phase 1 complete" framing with options for next steps; physics engine has since progressed well past this decision point (7 loops, L8 Jacquard). | | docs/working/architecture/TURTLE-GRAPHICS-HOWTO-20260819.md | Turtle Graphics HOWTO — `capsules/turtle.4th` | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_IMPLEMENTATION_STATUS.adoc | POSIX vs L4Re porting strategy status for physics hooks | HISTORICAL | Describes early wiring state of `physics_metadata_touch()` calls; physics engine has since matured substantially — status snapshot now outdated. | | docs/working/architecture/VM-FLEET-ATTRACTOR-DESIGN-20260705.md | VM Fleet Attractor Experiment — Design Doc | WORKING | Fleet physics; pre-reshuffle (names the Hermes VM) but still the source for the attractor design. |
| docs/working/scratch/src/internal/PHYSICS_SCHEDULING_PLAN.adoc | Planning note for physics-inspired scheduling metadata | HISTORICAL | Describes `DictPhysics` struct fields as stub/unpopulated placeholders; current `DictPhysics` is now populated and actively used — doc predates that implementation. | | docs/working/architecture/VM-PHYSICS-DYNAMIC-FLEET-DESIGN-20260705.md | Dynamic VM Fleet Physics — Design Doc | WORKING | |
| docs/working/architecture/PHYSICS_SIGNAL_MAP.adoc | Telemetry signal inventory (L4Re KIP signals + VM-internal counters) | WORKING | Useful living reference of available L4Re kernel telemetry signals for future physics/scheduler work; L4Re remains a supported platform. | | docs/working/architecture/VM_FORMALIZATION_PLAN.adoc | VM Formalization Roadmap | WORKING | |
| docs/working/scratch/src/internal/SHARED_CLAUDE.adoc | Cross-project Claude-instance shared notepad (StarForth↔StarshipOS) | DELETE | Dated 2025-10-19 ad-hoc session notes/chat log between AI instances about integrator script status; pure transient working notes with no lasting reference value. | | docs/working/architecture/architecture-internals/INIT_SYSTEM.adoc | L4RE_TARGET | WORKING | |
| docs/working/architecture/VM_FORMALIZATION_PLAN.adoc | Isabelle/HOL formalization roadmap for `docs/src/internal/formal/` theories | CURRENT | Directly describes the `docs/src/internal/formal/*.thy` files which exist on disk and are wired into the Makefile's Isabelle build targets. | | docs/working/architecture/architecture-internals/MESSAGING.adoc | SFM_THERMO_H | WORKING | |
| docs/working/hardware/performance-profiling/ARM64_OPTIMIZATIONS.adoc | ARM64 assembly optimization summary | CURRENT | Referenced headers (`include/vm_asm_opt_arm64.h`, `vm_inner_interp_arm64.h`, `arch_detect.h`) all confirmed present in current `include/` tree. | | docs/working/architecture/build-and-tooling/BUILD_OPTIONS.adoc | defined(__x86_64__) // defined(_M_X64) // defined(__amd64__) | WORKING | |
| docs/working/hardware/performance-profiling/ASM_OPTIMIZATIONS.adoc | x86_64 assembly optimization guide | CURRENT | Referenced headers (`vm_asm_opt.h`, `vm_inner_interp_asm.h`) confirmed present; consistent with `USE_ASM_OPT=1` build flag in current CLAUDE.md. | | docs/working/architecture/build-and-tooling/DOCUMENTATION_README.adoc | Generate the AsciiDoc API documentation | WORKING | |
| docs/working/hardware/performance-profiling/PROFILER.adoc | Built-in word-execution profiler guide | CURRENT | Describes profiler integrated with PGO pipeline; consistent with `make test PROFILE=1` and `profiler.c` present in current src tree. | | docs/working/architecture/build-and-tooling/INIT_TOOLS.adoc | 1. Work in disk (using StarForth REPL) | WORKING | |
| docs/working/hardware/platform-integration/L4RE_DICTIONARY_ALLOCATION.adoc | Dictionary allocation strategy proposal for L4Re | WORKING | References `src/dictionary_management.c:228` (`vm_create_word()` malloc) and `defining_words.c:554` (`FORGET` free) — both locations exist; malloc/free dependency has likely not yet been replaced with L4Re-native allocator. | | docs/working/architecture/doxygen/DOXYGEN_QUICK_REFERENCE.adoc | MACRO_NAME value | WORKING | |
| docs/working/hardware/platform-integration/L4RE_INTEGRATION.adoc | General L4Re integration guide (IPC, dataspaces, package structure) | WORKING | Broad integration guide; L4Re remains a supported platform per CLAUDE.md tech stack diagram. | | docs/working/architecture/doxygen/DOXYGEN_STYLE_GUIDE.adoc | STACK_SIZE 1024 | WORKING | |
| docs/working/hardware/platform-integration/PLATFORM_ABSTRACTION.adoc | Platform abstraction layer (vtable pattern for POSIX/L4Re) | CURRENT | Matches actual `platform/linux/time.c` and `platform/l4re/time.c` files present in current src tree per CLAUDE.md source tree listing. | | docs/working/architecture/getting-started/DEVELOPER.md | StarForth Developer Guide | WORKING | |
| docs/working/hardware/platform-integration/RASPBERRY_PI_BUILD.adoc | Raspberry Pi 4 / ARM64 build guide | CURRENT | Matches `rpi4-cross` Makefile target and ARM64 architecture support (`ARCH=raspi`) listed in current CLAUDE.md build targets. | | docs/working/architecture/getting-started/INSTALL.adoc | Build package | WORKING | |
| docs/working/hardware/platform-integration/l_4_re_blkio_endpoints.adoc | Block I/O L4Re porting endpoints (blkio vtable mapping) | CURRENT | Describes `blkio_open/close/read` vtable API; matches `blkio_*.c` backend files listed in current CLAUDE.md source tree. | | docs/working/architecture/getting-started/QUICKSTART.adoc | Build the fastest version for your platform | WORKING | |
| docs/working/scratch/testing-quality/KANBAN-WORKFLOW-VALIDATION.adoc | Validation procedure for GitHub Projects Kanban automation (CAPA-032) | CURRENT | Dated 2025-11-02 with explicit source commit hash; references `.github/workflows/capa-kanban-sync.yml` which is a concrete CI artifact. | | docs/working/architecture/getting-started/README.md | Getting Started with StarForth | WORKING | |
| docs/working/archive/legacy/OPTIMIZATION_OPPORTUNITIES.md | Physics engine optimization opportunity ranking dated 2025-11-19 | SUPERSEDED | Superseded by docs/03-architecture/physics-engine/ and Loop #5/#6 implementations | | docs/working/architecture/getting-started/quick-start/heartbeat-doe.md | StarForth Heartbeat DoE – Quick Start | WORKING | |
| docs/working/archive/legacy/README.md | Index and usage guide for the docs/archive directory | CURRENT | Self-referential; accurately describes the archive's purpose and sub-structure | | docs/working/architecture/getting-started/quick-start/optimization-doe.md | Quick Start: Optimization DoE | WORKING | |
| docs/working/archive/legacy/START_HERE_HEARTBEAT_DOE.md | Phase 2 heartbeat DoE launch guide (250 runs, 5 elite configs) | SUPERSEDED | README notes this is superseded by docs/02-experiments/heartbeat-doe/ | | docs/working/architecture/heartbeat_csv_export.md | Heartbeat CSV Export - Real-Time VM Metrics | WORKING | |
| docs/working/archive/legacy/phase-1/Reference/BACKLOG_INJECTION_ANALYSIS.md | Governance model analysis of GitHub issue injection points | HISTORICAL | Nov 2025 snapshot of CI/process governance state | | docs/working/archive/COMPUTATIONAL_PHYSICS_FRAMEWORK.md | The Physics of Adaptive Computation | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/EXPERIMENT_QUICK_REFERENCE.txt | Quick-reference ops card for the 90-run A/B/C physics validation experiment | HISTORICAL | Raw ops card tied to a specific pre-publication experiment run | | docs/working/archive/DOCUMENTATION_AUDIT.md | StarForth Documentation Audit | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/IMPLEMENTATION_SUMMARY.md | Phase 1 CI/Kanban automation implementation summary | HISTORICAL | Records CI automation decisions made during project Phase 1 | | docs/working/archive/GAP_ANALYSIS.md | Gap Analysis: Missing Evolutionary Links | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/JENKINS_USER_GUIDE.md | Jenkins CI user guide | HISTORICAL | Jenkins may no longer be the active CI system; check .github/workflows/ | | docs/working/archive/README.md | docs/working/archive/ | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/KANBAN-TESTING-GUIDE.md | Guide for testing GitHub Projects Kanban automation | HISTORICAL | Companion to CAPA-032 Kanban work; superseded by live workflow | | docs/working/archive/artifacts/kanban-workflow/MANIFEST.adoc | Kanban Workflow Artifacts Manifest | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/KANBAN-WORKFLOW-TEST.md | Kanban workflow test procedures | HISTORICAL | Point-in-time test doc for Kanban automation validation | | docs/working/archive/dead/hal-target-contract/README.md | Hardware Abstraction Layer (HAL) Documentation | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/PHASE_1_FINAL_STATUS.md | Final status report for project Phase 1 | HISTORICAL | Closed-loop status report; accurately captures Phase 1 completion state | | docs/working/archive/dead/hal-target-contract/interfaces.md | HAL Interface Specifications | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/PHASE_1_IMPLEMENTATION_COMPLETE.md | Phase 1 implementation completion announcement | HISTORICAL | Records the Phase 1 done-condition at time of writing | | docs/working/archive/dead/hal-target-contract/migration-plan.md | HAL Migration Plan | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/PHASE_1_TESTING_RESULTS.md | Phase 1 testing results summary | HISTORICAL | Test results from Phase 1 CI/governance work | | docs/working/archive/dead/hal-target-contract/overview.md | Hardware Abstraction Layer (HAL) Architecture | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/PHYSICS_EXPERIMENT_README.md | README for the 90-run physics validation experiment | HISTORICAL | Companion README to the experiment data in physics_experiment/ | | docs/working/archive/dead/hal-target-contract/platform-implementations.md | HAL Platform Implementation Guide | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/RULE_1_GATES_IMPLEMENTATION.md | Implementation notes for Rule 1 CI gating | HISTORICAL | CI gate design decisions from Phase 1 | | docs/working/archive/dead/hal-target-contract/starkernel-integration.md | StarKernel HAL Integration Guide | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/SECURITY.md | Security notes predating the ACL system | HISTORICAL | Pre-ACL security model; superseded by docs/03-architecture/word-acl/DESIGN.md | | docs/working/archive/dead/l4re/L4RE_DICTIONARY_ALLOCATION.adoc | STARFORTH_VM_DICT_ALLOC | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/SESSION_SUMMARY.md | Transient AI session summary | HISTORICAL | Session-level notes; limited long-term value | | docs/working/archive/dead/l4re/L4RE_INTEGRATION.adoc | Subdirectories to build | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/TEST-CAPA-TEMPLATE.md | CAPA test case template | HISTORICAL | Template used during Phase 1 CAPA process | | docs/working/archive/dead/l4re/L4RE_INTEGRATION_TODO.adoc | Note: Do NOT copy time_posix.c - not needed in L4Re build | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/codex_audit_report.md | Codex audit report of the codebase | HISTORICAL | Point-in-time static analysis or review; may be stale | | docs/working/archive/dead/l4re/l_4_re_blkio_endpoints.adoc | l_4_re_blkio_endpoints.adoc | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/codex_capa_list.md | CAPA action items derived from Codex audit | HISTORICAL | Action items from Phase 1 audit cycle | | docs/working/archive/dead/metrics-and-knobs.md | StarForth Metrics & Knobs: GAPS ONLY | DEAD | See the file's own header. |
| docs/working/archive/legacy/phase-1/Reference/github_backlog_items.md | GitHub backlog items list | HISTORICAL | Snapshot of backlog at Phase 1; likely stale | | docs/working/archive/historical/2026-01-27-system-architecture-draft.md | LithosAnanke System Architecture | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/DEVIATION_REPORT_CSV_FORMATTING.md | CSV formatting deviation report for experiment output | HISTORICAL | Experiment data-hygiene note for the 90-run run | | docs/working/archive/historical/2026-06-03-test-gap-audit.md | StarForth Dictionary Test Coverage — Gap Audit | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/FORMAL_CLAIMS_FOR_REVIEWERS.txt | Formal claims document prepared for peer reviewers | HISTORICAL | Pre-publication version; superseded by published SSRN paper | | docs/working/archive/historical/2026-06-10-next-session-plan.md | Next Session Plan | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/01_MAIN_PAPER/PAPER_KEY_CONTRIBUTIONS_SUMMARY.md | Key contributions summary for peer review submission | HISTORICAL | Pre-SSRN draft; superseded by papers/James_Steady-State_Convergence_Adaptive_Runtime.pdf | | docs/working/archive/historical/2026-06-30-break-me-report.md | 🔥 STARFORTH BREAK-ME DIAGNOSTIC REPORT 🔥 | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/01_MAIN_PAPER/PEER_REVIEW_PAPER_DRAFT.md | Full paper draft submitted for peer review | HISTORICAL | Pre-SSRN draft; superseded by published SSRN paper | | docs/working/archive/historical/2026-07-amd64-isr-fix/README.md | APIC Timer ISR Fix — amd64 | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/FORMAL_CLAIMS_FOR_REVIEWERS.txt | Formal claims for reviewers (supporting docs copy) | HISTORICAL | Duplicate of physics_experiment/FORMAL_CLAIMS_FOR_REVIEWERS.txt | | docs/working/archive/historical/2026-07-birthing/PLAN.md | Birthing Plan: Child VMs Born of Hera | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/FORMAL_VERIFICATION_INTERPRETATION.md | Interpretation guide for Isabelle/HOL proofs for reviewers | HISTORICAL | Pre-publication; proof/ directory is the live source | | docs/working/archive/historical/2026-07-birthing/README.md | docs/working/archive/historical/2026-07-birthing/ | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/PEER_REVIEW_SUBMISSION_PACKAGE.md | Cover doc for the full peer review submission package | HISTORICAL | Submission metadata; superseded by SSRN publication | | docs/working/archive/historical/2026-07-birthing/STATUS.md | Birthing — Work Status and Context | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/QUICK_REFERENCE.txt | Quick reference for reviewers | HISTORICAL | Reviewer-facing summary; superseded by published abstract | | docs/working/archive/historical/2026-07-birthing/acceptance-logs/README.md | docs/working/archive/historical/2026-07-birthing/acceptance-logs/ | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/02_SUPPORTING_DOCS/VARIANCE_ANALYSIS_SUMMARY.md | Variance analysis summary for the 90-run experiment | HISTORICAL | Source data for SSRN paper; keep as experimental record | | docs/working/archive/historical/2026-07-birthing/acceptance-logs/SUMMARY.md | Birthing — Kernel QEMU Acceptance Test Summary | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/03_EXPERIMENTAL_DATA/full_90_run_comprehensive/experiment_summary.txt | Comprehensive 90-run experiment summary | HISTORICAL | Primary experimental record; source data for SSRN paper | | docs/working/archive/historical/2026-08-riscv64-stack-fix/README.md | Kernel Stack Trampoline Fix — riscv64 | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/03_EXPERIMENTAL_DATA/full_90_run_comprehensive/run_logs/test_matrix.txt | Test matrix for full 90-run experiment | HISTORICAL | Experimental record; run configuration matrix | | docs/working/archive/historical/2026-10-lithosananke-orientation.md | LithosAnanke — StarForth Kernel Branch | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/05_SUPPLEMENTARY/PEER_REVIEW_PAPER_OUTLINE.md | Outline used to structure the peer review paper | HISTORICAL | Pre-publication outline; superseded by final SSRN paper | | docs/working/archive/legacy/OPTIMIZATION_OPPORTUNITIES.md | StarForth Optimization Opportunities | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/05_SUPPLEMENTARY/WORK_COMPLETION_STATUS.md | Work completion checklist for peer review submission | HISTORICAL | Point-in-time submission checklist | | docs/working/archive/legacy/README.md | Archived Documentation | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/00-abstract.adoc | AsciiDoc abstract section for peer review paper | HISTORICAL | Pre-publication AsciiDoc draft; superseded by SSRN PDF | | docs/working/archive/legacy/START_HERE_HEARTBEAT_DOE.md | START HERE – Heartbeat DoE Phase 2 | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/01-introduction.adoc | AsciiDoc introduction section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/BACKLOG_INJECTION_ANALYSIS.md | Backlog Injection Points Analysis | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/01-summary.adoc | AsciiDoc summary section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/EXPERIMENT_QUICK_REFERENCE.txt | Watch CSV grow in real-time | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/02-formal-theorems.adoc | AsciiDoc formal theorems section | HISTORICAL | Pre-publication; proof/ directory is live source | | docs/working/archive/legacy/phase-1/Reference/IMPLEMENTATION_SUMMARY.md | Physics Engine Comprehensive Validation - Complete Implementation Summary | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/02-related-work.adoc | AsciiDoc related-work section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/JENKINS_USER_GUIDE.md | Jenkins User Guide | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/03-experimental-methodology.adoc | AsciiDoc experimental methodology section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/KANBAN-TESTING-GUIDE.md | Kanban Workflow Testing Guide | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/03-methodology.adoc | AsciiDoc methodology section (alternate) | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/KANBAN-WORKFLOW-TEST.md | Kanban Workflow Test Guide (Phase 3) | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/04-results.adoc | AsciiDoc results section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/PHASE_1_FINAL_STATUS.md | Phase 1 Final Status & Completion Report | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/04-variance-analysis.adoc | AsciiDoc variance analysis section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/PHASE_1_IMPLEMENTATION_COMPLETE.md | Phase 1 Implementation Complete ✅ | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/05-convergence-proof.adoc | AsciiDoc convergence proof section | HISTORICAL | Pre-publication; proof/ directory is live source | | docs/working/archive/legacy/phase-1/Reference/PHASE_1_TESTING_RESULTS.md | Phase 1 Testing Results | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/05-discussion.adoc | AsciiDoc discussion section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/PHYSICS_EXPERIMENT_README.md | StarForth Physics Engine Validation Experiment | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/06-stability-proof.adoc | AsciiDoc stability proof section | HISTORICAL | Pre-publication; proof/ directory is live source | | docs/working/archive/legacy/phase-1/Reference/RULE_1_GATES_IMPLEMENTATION.md | Rule 1: Governance-First Backlog Injection Gates Implementation | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/07-predictability-bounds.adoc | AsciiDoc predictability bounds section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/SECURITY.md | Security Policy | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/08-peer-review-defense.adoc | AsciiDoc peer-review defense section | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/SESSION_SUMMARY.md | Session Summary: Governance Workflow Implementation Complete ✅ | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/index.adoc | AsciiDoc index/master file for the peer review paper | HISTORICAL | Pre-publication AsciiDoc draft | | docs/working/archive/legacy/phase-1/Reference/StarForth_Complete_Presentation.pptx | StarForth_Complete_Presentation.pptx | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/06_ASCIIDOC/paper.adoc | AsciiDoc combined paper source | HISTORICAL | Pre-publication; superseded by SSRN PDF | | docs/working/archive/legacy/phase-1/Reference/TEST-CAPA-TEMPLATE.md | Test CAPA Issue Template | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/PEER_REVIEW_SUBMISSION/README.md | README for the peer review submission package | HISTORICAL | Submission index; superseded by SSRN publication | | docs/working/archive/legacy/phase-1/Reference/codex_audit_report.md | StarForth Governance – Fresh Audit Report | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/QUICK_REFERENCE.txt | Quick reference for the 90-run experiment | HISTORICAL | Ops-level quick card; raw experiment record | | docs/working/archive/legacy/phase-1/Reference/codex_capa_list.md | StarForth Governance – CAPA Register (Fresh Audit) | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/experiment_summary.txt | Top-level experiment summary | HISTORICAL | Primary experimental record; source data for SSRN paper | | docs/working/archive/legacy/phase-1/Reference/github_backlog_items.md | GitHub Project Backlog Prep | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/full_90_run_comprehensive/experiment_summary.txt | Full 90-run comprehensive experiment summary | HISTORICAL | Experimental record (duplicate path from submission tree) | | docs/working/archive/legacy/phase-1/Reference/physics_experiment/ | 35 files | HISTORICAL | Grouped: bulk data or a self-governed tree. |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/full_90_run_comprehensive/run_logs/test_matrix.txt | Test matrix for full 90-run experiment | HISTORICAL | Run configuration matrix | | docs/working/archive/legacy/phase-1/Reference/toolchain/ | 2 files | HISTORICAL | Grouped: bulk data or a self-governed tree. |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/run_logs/test_matrix.txt | Run logs test matrix (top-level) | HISTORICAL | Raw run log; experimental record | | docs/working/archive/operations/README.md | Operations | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/test_run/experiment_summary.txt | Test run experiment summary | HISTORICAL | Pre-full-run trial; experimental record | | docs/working/archive/operations/backlog-gatekeeper.md | Backlog Gatekeeper Procedures | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/test_run/run_logs/test_matrix.txt | Test run matrix | HISTORICAL | Raw test matrix for trial run | | docs/working/archive/operations/jenkins-pipeline-guide.adoc | StarForth Jenkins Pipeline Guide | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/test_run2/experiment_summary.txt | Second test run experiment summary | HISTORICAL | Pre-full-run trial #2; experimental record | | docs/working/archive/operations/qa-intake-workflow.adoc | QA Intake & CAPA Backlog Population Workflow | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/physics_experiment/test_run2/run_logs/test_matrix.txt | Second test run matrix | HISTORICAL | Raw test matrix for trial run #2 | | docs/working/archive/operations/refinement/annotations.adoc | StarForth Refinement Code Annotation Guide | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/toolchain/gcc.txt | GCC toolchain version/configuration notes | HISTORICAL | Point-in-time toolchain pinning record | | docs/working/archive/operations/refinement/capa.adoc | StarForth C↔Isabelle Refinement Defect Tracking | HISTORICAL | |
| docs/working/archive/legacy/phase-1/Reference/toolchain/make.txt | Make version/configuration notes | HISTORICAL | Point-in-time toolchain pinning record | | docs/working/archive/operations/refinement/roadmap.adoc | StarForth C↔Isabelle Refinement Implementation Roadmap | HISTORICAL | |
| docs/working/archive/operations/workflow.md | StarForth CI/CD Workflow | HISTORICAL | |
| docs/working/archive/prog-prove.pdf | prog-prove.pdf | HISTORICAL | |
| docs/working/archive/quality/README.md | Quality Assurance | HISTORICAL | |
| docs/working/archive/quality/audits/codebase-audit-report.md | StarForth Codebase Audit Report | HISTORICAL | |
| docs/working/archive/quality/audits/corrective-actions.md | StarForth Codebase Audit: Corrective Actions Report | HISTORICAL | |
| docs/working/archive/quality/audits/implementation-audit.md | StarForth Adaptive Tuning: Implementation Audit | HISTORICAL | |
| docs/working/archive/quality/audits/section-2-audit.md | SECTION 2 AUDIT REPORT | HISTORICAL | |
| docs/working/archive/quality/audits/section-2-executive-summary.md | SECTION 2 EXECUTIVE SUMMARY | HISTORICAL | |
| docs/working/archive/quality/phase-tracking/phase-2-implementation-checklist.md | Phase 2 Implementation Checklist | HISTORICAL | |
| docs/working/archive/quality/phase-tracking/phase-2-issues-identified.md | Phase 2 Issues: Shrink/Grow, Decay Slope, Fixed-Point Violations | HISTORICAL | |
| docs/working/archive/quality/phase-tracking/phase-2a-session-summary.md | Phase 2a Session Summary: Linear Decay & Freeze Flag Implementation | HISTORICAL | |
| docs/working/archive/quality/regression/detection-framework.md | Optimization Regression Detection Framework | HISTORICAL | |
| docs/working/archive/quality/regression/opp-02-report.md | OPP #2: VARIANCE-BASED WINDOW WIDTH TUNING | HISTORICAL | |
| docs/working/archive/quality/validation/comprehensive-physics-validation.md | Comprehensive Physics Engine Validation Protocol | HISTORICAL | |
| docs/working/archive/quality/validation/phase-1-protocol.md | Phase 1 Governance Validation Protocol | HISTORICAL | |
| docs/working/archive/quality/validation/phase-2-executive-summary.md | Phase 2 Experiment: Executive Summary | HISTORICAL | |
| docs/working/archive/research/README.md | Research | HISTORICAL | |
| docs/working/archive/research/doe-metrics-schema.md | StarForth Design of Experiments (DoE) Metrics Schema | HISTORICAL | |
| docs/working/archive/research/literature-review.md | Literature Review: Physics-Driven VM Optimization | HISTORICAL | |
| docs/working/archive/research/research-outline.md | Research Paper Outline: Physics-Driven VM Optimization | HISTORICAL | |
| docs/working/archive/research/results-for-publication.md | Results for Publication: Physics-Driven VM Optimization | HISTORICAL | |
| docs/working/archive/session-logs/2025-11-20-recap.md | Session Recap: 2025-11-20 | HISTORICAL | |
| docs/working/archive/session-logs/2025-11-26-worklog.md | Work Log: November 26, 2025 | HISTORICAL | |
| docs/working/archive/session-logs/2026-07-05-worklog.md | Work Log: July 5, 2026 | HISTORICAL | |
| docs/working/archive/session-logs/2026-07-24-punch-list.md | Punch List: Gaps from 2026-07-24 Session | HISTORICAL | |
| docs/working/archive/session-logs/README.md | Session Logs | HISTORICAL | |
| docs/working/archive/session-logs/experimental-addendum.md | Window Scaling Experiment — Validation of the James Law of Computational Dynamic | HISTORICAL | |
| docs/working/archive/session-logs/experimental-iteration-usage.md | Experimental Iteration Runner - Usage Guide | HISTORICAL | |
| docs/working/archive/session-logs/serialized-questing-pike.md | StarForth → StarshipOS Hybrid Kernel Transformation Plan | HISTORICAL | |
| docs/working/archive/superseded/2025-12-14-starforth-roadmap.md | StarForth Roadmap: VM → Kernel → OS → FPGA | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-07-08-hermes-message-block-storage-design.md | Hermes Message/Channel Block-Backed Storage — Design Doc | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-07-08-hermes-message-channel-physics-design.md | Hermes Message/Channel Heat Physics — Design Doc | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-02-artemis-hermes-compudynamics-plan.md | Artemis (and Hermes) Compudynamics — Implementation Plan | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-tripod/03-architecture-README.md | docs/03-architecture/ | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-tripod/ARTEMIS.md | ARTEMIS.md — Artemis VM Architecture | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-tripod/HERMES.md | HERMES.md — Hermes VM Architecture | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-tripod/README.md | docs/working/archive/superseded/2026-08-tripod/ | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/2026-08-tripod/TRIPOD.md | TRIPOD.md — Architectural Constraints for the Tripod VMs | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/L8_WIRING_PLAN.md | L8 Control Wiring Implementation Plan | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/factorial-doe/guide.md | StarForth Complete 2^6 Factorial Design of Experiments | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/factorial-doe/incompatible-configs.md | Handling Incompatible Configurations in Factorial DoE | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/factorial-doe/index.md | StarForth Complete 2^6 Factorial DoE - Documentation Index | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/factorial-doe/quick-start.md | Quick Start: Complete 2^6 Factorial DoE | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/factorial-doe/workflow.md | Factorial DoE Analysis Workflow | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/feedback-loops-analysis.md | StarForth Feedback Loops & Self-Optimization Analysis | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/heartbeat-doe-corrected-design.md | StarForth Heartbeat DoE – CORRECTED Design (Heartrate Focus) | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/heartbeat-doe-design.md | StarForth Factorial DoE with Heartbeat Integration | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/heartbeat-rate-logging-plan.md | Implementation Plan: Heartbeat Rate Logging | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/loop-5-sketch.md | Loop #5: Context-Aware Window Tuning - Design Sketch | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/archive/superseded/steady-state-machine.md | 1. Introduction | SUPERSEDED | See the file's own header for what replaces it. |
| docs/working/experiments/02-experiments/L8_WIRING_CODE_REVIEW_GUIDE.md | L8 Wiring Code Review Guide | WORKING | |
| docs/working/experiments/02-experiments/L8_WIRING_IMPLEMENTATION_SUMMARY.md | L8 Control Wiring Implementation Summary | WORKING | |
| docs/working/experiments/02-experiments/README.md | Experiments | WORKING | |
| docs/working/experiments/02-experiments/heartbeat-doe/execution-guide.md | StarForth Heartbeat DoE Experiment – Execution Guide | WORKING | |
| docs/working/experiments/02-experiments/heartbeat-doe/implementation-summary.md | StarForth Heartbeat DoE – Implementation Summary | WORKING | |
| docs/working/experiments/02-experiments/heartbeat-doe/phase2-corrected.md | StarForth Phase 2 Heartbeat DoE – CORRECTED AND FINALIZED | WORKING | |
| docs/working/experiments/02-experiments/james-law/protocol.md | Critical Window Scaling Experiment | WORKING | |
| docs/working/experiments/02-experiments/physics-optimization/doe-guide.md | StarForth Optimization DoE Guide | WORKING | |
| docs/working/experiments/02-experiments/physics-optimization/execution-guide.md | StarForth Physics Engine - Comprehensive Validation Experiment | WORKING | |
| docs/working/experiments/02-experiments/physics-optimization/hotwords-cache.md | Physics Engine Experiment: Hot-Words Cache Performance Analysis | WORKING | |
| docs/working/experiments/02-experiments/physics-optimization/proposals.md | Physics-Driven Optimization Proposals for StarForth | WORKING | |
| docs/working/experiments/02-experiments/physics-optimization/reproduce.md | Reproducing the Physics Engine Hot-Words Cache Experiment | WORKING | |
| docs/working/experiments/README.md | docs/working/experiments/ | WORKING | |
| docs/working/experiments/campaigns/doe_2x7/README.md | 2^7 Factorial Design of Experiments (DoE) | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_attractor_map/SESSION_REPORT_2025-12-10.md | L8 Attractor Map: From Crashes to Computational Physics | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_attractor_map/results_20251209_145907/ | 9 files | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_attractor_map/run_log.txt | run_log.txt | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_validation/EXPERIMENT_SUMMARY.txt | Quick test (10 reps, ~8 min) | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_validation/README.md | L8 Jacquard Mode Selector Validation Experiment | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_validation/l8_validation_20251208_102205/ | 2 files | RECORD | Campaign data. |
| docs/working/experiments/campaigns/l8_validation/l8_validation_30reps_20251126_135128/ | 2 files | RECORD | Campaign data. |
| docs/working/experiments/campaigns/shape_validation/README.md | Workload Shape Validation Experiment | RECORD | Campaign data. |
| docs/working/experiments/campaigns/shape_validation/shape_RAJ_run_20251127_093208/ | 2 files | RECORD | Campaign data. |
| docs/working/experiments/campaigns/shape_validation/shape_run_20251123_083147/ | 2 files | RECORD | Campaign data. |
| docs/working/experiments/campaigns/window_scaling/QUICK_START.md | Window Scaling Experiment - Quick Start Guide | RECORD | Campaign data. |
| docs/working/experiments/campaigns/window_scaling/README.md | Window Scaling Experiment — James Law Validation | RECORD | Campaign data. |
| docs/working/hardware/PGO_GUIDE.adoc | Interactive TUI | WORKING | |
| docs/working/hardware/PLATFORM_BUILD_GUIDE.adoc | POSIX Build (Linux/macOS/BSD) - DEFAULT | WORKING | |
| docs/working/hardware/README.md | docs/working/hardware/ | HISTORICAL | Flagged in its own header. |
| docs/working/hardware/performance-profiling/ARM64_OPTIMIZATIONS.adoc | Detect architecture | WORKING | |
| docs/working/hardware/performance-profiling/ASM_OPTIMIZATIONS.adoc | Add to CFLAGS | WORKING | |
| docs/working/hardware/performance-profiling/PROFILER.adoc | Run your typical Forth program with profiling | WORKING | |
| docs/working/hardware/platform-integration/PLATFORM_ABSTRACTION.adoc | POSIX build (default - Linux/macOS/BSD) | WORKING | |
| docs/working/hardware/platform-integration/RASPBERRY_PI_BUILD.adoc | Install dependencies | WORKING | |
| docs/working/legal/README.md | docs/working/legal/ — Patent-Adjacent Material (HOLD) | LEGAL HOLD | Not touched without Captain Bob. |
| docs/working/papers/ACADEMIC_WORDING_GUIDELINES.md | Academic Wording Guidelines for StarForth | WORKING | |
| docs/working/papers/ANTI_CLAIMS.md | Anti-Claims: What This Work Does NOT Claim | WORKING | |
| docs/working/papers/EXECUTIVE_SUMMARY.md | Executive Summary: StarForth in Plain English | WORKING | |
| docs/working/papers/FINAL_REPORT/appendix_glossary.adoc | appendix_glossary.adoc | WORKING | |
| docs/working/papers/FORMAL_CLAIM_TABLE.md | Formal Claim Table: StarForth Adaptive Runtime | WORKING | |
| docs/working/papers/NEGATIVE_RESULTS.md | Negative Results: Where StarForth Fails | WORKING | |
| docs/working/papers/NULL_HYPOTHESIS.md | Null Hypothesis and Falsification Criteria | WORKING | |
| docs/working/papers/ONTOLOGY_README.md | StarForth Ontology Documentation | WORKING | |
| docs/working/papers/README.md | docs/working/papers/ | WORKING | |
| docs/working/papers/REPLICATION_INVITE.md | Invitation to Independent Replication | WORKING | |
| docs/working/papers/REPRODUCIBILITY.md | Reproducibility: One-Command Experiment Reproduction | WORKING | |
| docs/working/papers/SCIENTIFIC_DEFENSE_CHECKLIST.md | Scientific Defense Checklist | WORKING | |
| docs/working/papers/SENSITIVITY_ANALYSIS.md | Sensitivity Analysis: Parameter Robustness | WORKING | |
| docs/working/papers/SSRN_companion/Math_Companion_SSRN.pdf | Math_Companion_SSRN.pdf | WORKING | |
| docs/working/papers/SSRN_companion/Math_Companion_SSRN.tex | | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig1_snake_trajectory.pdf | fig1_snake_trajectory.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig2_K_vs_window.pdf | fig2_K_vs_window.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig3_FFT_spectrum.pdf | fig3_FFT_spectrum.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig4_golden_ratio_penalties.pdf | fig4_golden_ratio_penalties.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig5_bimodal_distributions.pdf | fig5_bimodal_distributions.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig6_performance_vs_k.pdf | fig6_performance_vs_k.pdf | WORKING | |
| docs/working/papers/SSRN_companion/figures/fig7_performance_by_regime.pdf | fig7_performance_by_regime.pdf | WORKING | |
| docs/working/papers/SYSTEM_NARRATIVE.pdf | SYSTEM_NARRATIVE.pdf | WORKING | |
| docs/working/papers/SYSTEM_NARRATIVE.tex | StarForth System Narrative}\\ | WORKING | |
| docs/working/papers/ontology.pdf | ontology.pdf | WORKING | |
| docs/working/papers/ontology.tex | StarForth Ontology: Formal Conceptual Framework for\\ | WORKING | |
| docs/working/papers/proposals/DARPA_SSM_Proposal_James.docx | DARPA_SSM_Proposal_James.docx | WORKING | |
| docs/working/papers/proposals/DARPA_SSM_Proposal_James.pdf | DARPA_SSM_Proposal_James.pdf | WORKING | |
| docs/working/papers/proposals/SSM_DARPA_Complete_Proposal_James_FINAL.docx | SSM_DARPA_Complete_Proposal_James_FINAL.docx | WORKING | |
| docs/working/papers/published/James_ACL_Security_Invariant_TTL_Mitigation.tex | % | WORKING | |
| docs/working/papers/published/James_Steady-State_Convergence_Adaptive_Runtime.pdf | James_Steady-State_Convergence_Adaptive_Runtime.pdf | WORKING | |
| docs/working/scratch/AGENTS.md | Repository Guidelines | WORKING | |
| docs/working/scratch/AI_AGENT_MANDATORY_README.md | AI_AGENT_MANDATORY_README.md | WORKING | |
| docs/working/scratch/COMMUNICATION_GUIDE.adoc | StarshipOS Analogy Cheat Sheet | WORKING | |
| docs/working/scratch/GOVERNANCE_EXPORT_NOTES.adoc | Governance Export Notes (Physics Phase 1) | WORKING | |
| docs/working/scratch/README.md | docs/working/scratch/ | WORKING | |
| docs/working/scratch/TASK_LIST.md | StarForth Physics Runtime — TASK_LIST.md | WORKING | |
| docs/working/scratch/assets/README.md | Binary Assets | WORKING | |
| docs/working/scratch/assets/book-FIXED.docx | book-FIXED.docx | WORKING | |
| docs/working/scratch/ci-cd/FMEA_BLOCKING_GATES.adoc | FMEA Blocking Gates Implementation | WORKING | |
| docs/working/scratch/ci-cd/GITHUB_ISSUES_GOVERNANCE_FLOW.adoc | GitHub Issues & Governance Integration | WORKING | |
| docs/working/scratch/ci-cd/GOVERNANCE_INPUT_AUDIT.adoc | Governance Input Audit & Compliance Checklist | WORKING | |
| docs/working/scratch/ci-cd/JENKINS_GOVERNANCE_INTEGRATION.adoc | Jenkins Governance Integration Guide | WORKING | |
| docs/working/scratch/governance/index.adoc | Governance | WORKING | |
| docs/working/scratch/src-index.adoc | StarForth Documentation Index | WORKING | |
| docs/working/scratch/src/INTEGRATION_NOTES.adoc | This blocks EVERYTHING because of empty line: | WORKING | |
| docs/working/scratch/src/development/CONTRIBUTING.adoc | 1) Fork and clone | WORKING | |
| docs/working/scratch/src/internal/PHASE_2A_COMPLETION_REPORT.adoc | Phase 2a Completion Report: Freeze Flag & Linear Decay | WORKING | |
| docs/working/scratch/src/internal/PHASE_2_IMPLEMENTATION_SUMMARY.adoc | Phase 2 Implementation Summary & Action Items | WORKING | |
| docs/working/scratch/src/internal/PHASE_2_PHYSICS_DECAY_AND_FREEZE.adoc | Phase 2: Physics Model Extensions — Decay & Freeze Mechanisms | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_HOTWORDS_CACHE_INTEGRATION.adoc | Hot-Words Cache Integration Guide | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_IMPLEMENTATION_OPTIONS.adoc | Physics Engine Implementation Options: Three Paths Forward | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_IMPLEMENTATION_STATUS.adoc | Physics Engine Implementation Status: POSIX vs L4Re Porting Strategy | WORKING | |
| docs/working/scratch/src/internal/PHYSICS_SCHEDULING_PLAN.adoc | Physics-Driven Scheduling Metadata Plan | WORKING | |
| docs/working/scratch/testing-quality/KANBAN-WORKFLOW-VALIDATION.adoc | Kanban Workflow Validation Procedure | WORKING | |
| docs/working/specifications/HOLA_PROTOCOL.adoc | HOLA Shared Memory Protocol (Phase 1) | WORKING | |
| docs/working/specifications/README.md | docs/working/specifications/ | WORKING | |
## experiments
| Path | Title | Status | Notes |
|---|---|---|---|
| experiments/README.md | experiments/ | RECORD | Experiment design, data or result. |
## experiments/artemis_stress
| Path | Title | Status | Notes |
|---|---|---|---|
| experiments/artemis_stress/analysis/ | 6 files | RECORD | Experiment design, data or result. |
## experiments/bare_metal
| Path | Title | Status | Notes |
|---|---|---|---|
| experiments/bare_metal/README.md | Bare-Metal DoE Experiment | RECORD | Experiment design, data or result. |
| experiments/bare_metal/analysis/ | 130 files | RECORD | Experiment design, data or result. |
## experiments/std79-doe
| Path | Title | Status | Notes |
|---|---|---|---|
| experiments/std79-doe/README.md | std79 DoE — 3(architecture) × 9(identity) × 3(replicate) randomized full-factori | RECORD | Experiment design, data or result. |
| experiments/std79-doe/analysis-20260912/ | 2 files | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/README.md | std79-doe LaTeX report: the fleet conservation invariant K | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/actual_window_size_dark.pdf | actual_window_size_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/actual_window_size_light.pdf | actual_window_size_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/apic_delta_dark.pdf | apic_delta_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/apic_delta_light.pdf | apic_delta_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/artemis_heat_dark.pdf | artemis_heat_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/artemis_heat_light.pdf | artemis_heat_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/avg_word_heat_dark.pdf | avg_word_heat_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/avg_word_heat_light.pdf | avg_word_heat_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/fleet_k_dark.pdf | fleet_k_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/fleet_k_light.pdf | fleet_k_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hera_heat_dark.pdf | hera_heat_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hera_heat_light.pdf | hera_heat_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hermes_heat_dark.pdf | hermes_heat_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hermes_heat_light.pdf | hermes_heat_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hot_word_count_dark.pdf | hot_word_count_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/hot_word_count_light.pdf | hot_word_count_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/jitter_ns_dark.pdf | jitter_ns_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/jitter_ns_light.pdf | jitter_ns_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/time_trust_dark.pdf | time_trust_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/time_trust_light.pdf | time_trust_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/variance_dark.pdf | variance_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/variance_light.pdf | variance_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/vm_call_depth_max_dark.pdf | vm_call_depth_max_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/vm_call_depth_max_light.pdf | vm_call_depth_max_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/window_width_dark.pdf | window_width_dark.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/figures/window_width_light.pdf | window_width_light.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/std79_doe_report.pdf | std79_doe_report.pdf | RECORD | Experiment design, data or result. |
| experiments/std79-doe/report-20260912/report/std79_doe_report.tex | % | RECORD | Experiment design, data or result. |
## experiments/std79-exerciser
| Path | Title | Status | Notes |
|---|---|---|---|
| experiments/std79-exerciser/README.md | FORTH-79 Standard-Dictionary Cross-ISA Exerciser | RECORD | Experiment design, data or result. |
| experiments/std79-exerciser/results-20260910/ | 27 files | RECORD | Experiment design, data or result. |
## img
| Path | Title | Status | Notes |
|---|---|---|---|
| img/README.md | img/ | CURRENT | |
## kernel
| Path | Title | Status | Notes |
|---|---|---|---|
| kernel/include/starkernel/README.md | include/starkernel/ | CURRENT | |
| kernel/include/starkernel/freestanding/README.md | include/starkernel/freestanding/ | CURRENT | |
| kernel/include/starkernel/freestanding/sys/README.md | include/starkernel/freestanding/sys/ | CURRENT | |
| kernel/include/starkernel/hal/README.md | include/starkernel/hal/ | CURRENT | |
| kernel/include/starkernel/vm/README.md | include/starkernel/vm/ | CURRENT | |
| kernel/include/starkernel/vm/bootstrap/README.md | include/starkernel/vm/bootstrap/ | CURRENT | |
| kernel/linker/README.md | linker/ | CURRENT | |
| kernel/src/README.md | src/starkernel/ | CURRENT | |
| kernel/src/arch/aarch64/README.md | src/starkernel/arch/aarch64/ | CURRENT | |
| kernel/src/arch/amd64/README.md | src/starkernel/arch/amd64/ | CURRENT | |
| kernel/src/arch/riscv64/README.md | src/starkernel/arch/riscv64/ | CURRENT | |
| kernel/src/boot/README.md | src/starkernel/boot/ | CURRENT | |
| kernel/src/capsule/README.md | src/starkernel/capsule/ | CURRENT | |
| kernel/src/hal/README.md | src/starkernel/hal/ | CURRENT | |
| kernel/src/hash/README.md | src/starkernel/hash/ | CURRENT | |
| kernel/src/math/README.md | src/starkernel/math/ | CURRENT | |
| kernel/src/memory/README.md | src/starkernel/memory/ | CURRENT | |
| kernel/src/pci/README.md | src/starkernel/pci/ | CURRENT | |
| kernel/src/virtio/README.md | src/starkernel/virtio/ | CURRENT | |
| kernel/src/vm/README.md | src/starkernel/vm/ | CURRENT | |
| kernel/src/vm/bootstrap/README.md | src/starkernel/vm/bootstrap/ | CURRENT | |
| kernel/src/vm/host/README.md | src/starkernel/vm/host/ | CURRENT | |
## lfs
| Path | Title | Status | Notes |
|---|---|---|---|
| lfs/README.md | lfs/ | CURRENT | |
## mk
| Path | Title | Status | Notes |
|---|---|---|---|
| mk/README.md | mk/ | CURRENT | |
## proof
| Path | Title | Status | Notes |
|---|---|---|---|
| proof/COVERAGE.md | Isabelle/HOL Proof Suite — Coverage & Purpose | CURRENT | |
| proof/FINDINGS.md | Isabelle/HOL Word-Source Sweep — Aggregated Architectural Findings | CURRENT | |
| proof/README.md | proof/ | CURRENT | |
## scripts
| Path | Title | Status | Notes |
|---|---|---|---|
| scripts/README.md | scripts/ | CURRENT | |
| scripts/SCRIPT_REPAIR_LOG.md | Ablation Study Script Repair Log | CURRENT | |
## tools
| Path | Title | Status | Notes |
|---|---|---|---|
| tools/README.md | tools/ | CURRENT | |
| tools/capsule-reserved.txt | capsule-reserved.txt — human-authored, git-tracked block ranges NOT | CURRENT | |
| tools/kconfig/README.md | tools/kconfig — vendored Linux kernel Kconfig tooling | CURRENT | |
## v3
| Path | Title | Status | Notes |
|---|---|---|---|
| v3/include/README.md | include/ | CURRENT | |
| v3/src/README.md | src/ | CURRENT | |
| v3/src/platform/README.md | src/platform/ | CURRENT | |
| v3/src/platform/l4re/README.md | src/platform/l4re/ | HISTORICAL | Flagged in its own header. |
| v3/src/platform/linux/README.md | src/platform/linux/ | CURRENT | |
| v3/src/test_runner/README.md | src/test_runner/ | CURRENT | |
| v3/src/test_runner/include/README.md | src/test_runner/include/ | CURRENT | |
| v3/src/test_runner/modules/README.md | src/test_runner/modules/ | CURRENT | |
| v3/src/word_source/README.md | src/word_source/ | CURRENT | |
| v3/src/word_source/include/README.md | src/word_source/include/ | CURRENT | |
## v4
| Path | Title | Status | Notes |
|---|---|---|---|
| v4/README.md | v4/ | CURRENT | |
+65 -44
View File
@@ -1,50 +1,71 @@
# StarForth / LithosAnanke Documentation # StarForth / LithosAnanke documentation — the map
This is the `lithosananke` branch: the bare-metal StarKernel side of the project Start here. This page says where each kind of document lives and which one to believe.
(contrast `master`, which is the hosted-VM-only side). Documentation follows the Reorganised 2026-10-14 (the docs triage): one place for current reference, one archive for
two-tier model described in `docs/CLAUDE.md`: **`formal/`** is the polished, everything kept as record, and every superseded or abandoned document labelled as such in
citable LaTeX tier; **`working/`** is living design notes and drafts that feed it. its own header.
Everything else in this directory is branch- or subsystem-specific material that
doesn't fit either tier. - **[INDEX.md](INDEX.md)** — every document in the repository, with its status.
- **[DEAD-AND-REVISED.md](DEAD-AND-REVISED.md)** — the ideas that were abandoned, and the claims
that were revised, each with the date and where the decision is recorded.
- **[DELETE-CANDIDATES.md](DELETE-CANDIDATES.md)** — what was deleted as duplicate, and why
(2026-10-14).
## What to believe
| For | Authoritative | Where |
|---|---|---|
| How to work in this repo, and current status | `.claude/CLAUDE.md` | repo root |
| What was decided, and why; work as it happened | the FABRIC record | [fabric/](fabric/) — `FABRIC-3.md` is the living one |
| StarForth v4 (the F18-derived engine) | the v4 design | [v4.0.0/](v4.0.0/) and `../v4/README.md` |
| Roadmap and release-versioning policy | `ROADMAP.md` | [reference/](reference/) |
| Getting onto the boards | the bring-up checklist | `../boards/BRINGUP.md` |
| A word, a primitive, a term | the dictionaries and the ontology | [reference/](reference/) |
| What the code does | the code, and its folder's `README.md` | `../kernel/`, `../v3/`, `../v4/` |
Where two documents disagree, the one higher in this table wins, and code wins over all.
## Layout ## Layout
- **[formal/](formal/)** — Three-volume LaTeX documentation set (research volumes, - **[fabric/](fabric/)** — the design and work record, numbered in order. `FABRIC-3.md`
practitioner books, standalone reports) plus the `scraps/` fragment library it's (bare-metal boot and everything since) is open; the others are closed:
assembled from. Audience: patent counsel, SSRN reviewers, licensees, hobbyists - FABRIC-0, -1 and -2 are history;
with hardware in hand. See `formal/CLAUDE.md` for authoring conventions. - FABRIC-3.5 and -3.6 are the Tripod/kernel reshuffle, still authoritative for what they ruled;
- **[working/](working/)** — Living documents: architecture design notes, DoE - FABRIC-3.7 (elevation) is closed as not needed;
experiment logs, hardware/platform notes, draft specs, academic-paper source - FABRIC-4 holds ideas caught early, not yet scoped.
material, and an archive of superseded docs. Source material for `formal/`. - **[v4.0.0/](v4.0.0/)** — StarForth v4: justification, engine, decomposition, nucleus, mesh,
- **[03-architecture/](03-architecture/)** — Tripod VM architecture constraints parity with v3. `plans/` holds the step plans, all executed.
(Hera/Hermes/Artemis) and the word-level ACL system design. - **[reference/](reference/)** — current reference material:
- **[lithosananke/](lithosananke/)** — LithosAnanke kernel branch documentation: - `ROADMAP.md` (roadmap and the ratified versioning policy);
milestone roadmap, system architecture, HAL reference, kernel command-line - `M7.1.md` (init capsules and birth);
argument design, and the amd64 APIC-timer ISR postmortem. - `word-acl/` (the word-level ACL design);
- **[birthing/](birthing/)** — VM birthing plan and status for the Hera-spawns- - `kernel-args/` (the boot command line);
Hermes/Artemis constellation, plus three-architecture QEMU acceptance logs. - `hosted-acceptance-test/`;
- **[patent/](patent/)** — Provisional patent application source. **Legal hold — - `DICTIONARY.md` and `STARFORTH_PRIMITIVES.md` (the words);
ask Bob before touching anything in this directory.** - `ONTOLOGY.md` (the lexicon);
- **[api/](api/)** — Generated Doxygen tag file and warnings log (gitignored; - `L8_ADAPTIVE_CONFIG_TABLE.md`.
not part of the tracked doc tree). - **[working/](working/)** — living material and the source for `formal/`:
- **[pptx/](pptx/)** — Elevator-pitch and deep-dive slide decks for different - `architecture/` (design notes and HOWTOs);
audiences (technical, non-technical, academic, PhD-level). - `experiments/` (DoE designs and campaign data);
- `papers/` (academic sources, the system narrative, proposals);
- `hardware/`, `specifications/` and `scratch/`;
- **`archive/`**, which has four parts:
- `historical/`: finished work, kept as record;
- `superseded/`: replaced, and each file's header names what replaced it;
- `dead/`: abandoned or never adopted;
- the older `legacy/`, `quality/`, `operations/`, `research/` and `session-logs/`.
- **[formal/](formal/)** — the press-ready LaTeX tier (three volumes, books, standalone
reports). Governed by `formal/CLAUDE.md`.
- **[book/](book/)** — the LithosAnanke and StarForth book build.
- **[pptx/](pptx/)** — slide decks for different audiences.
- **[patent/](patent/)** — provisional patent material. **Legal hold: ask Captain Bob before
touching anything here** (also `formal/patent/`, `formal/scraps/legal/`, `working/legal/`).
## Current Active Work ## Adding a document
- **LithosAnanke M7/M7.1** — VM parity validation and init capsule architecture. - Draft in `working/`; promote to `formal/` when it is ready to be cited (`formal/CLAUDE.md`).
See `lithosananke/README.md` and `lithosananke/M7.1.md`. Reference material that describes the system as it is goes in `reference/`.
- **Word-level ACL system** — Phase 6 complete on `master`; Phase 7 (LithosAnanke - When a document is overtaken, do not delete it: `git mv` it into `working/archive/superseded/`
parity) is the next step. See `03-architecture/word-acl/README.md`. or `dead/` with a header saying why and what replaces it, and add a line to
- **Tripod VMs** — Hera (governor), Hermes (messenger), Artemis (memory/block `DEAD-AND-REVISED.md`.
storage). See `03-architecture/tripod/README.md` and `birthing/`. - Rules for documentation work: [CLAUDE.md](CLAUDE.md).
## Contributing
- Place new material in `working/` first; promote to `formal/` only when it's
ready to be cited (see `formal/CLAUDE.md` for promotion criteria).
- Never touch `patent/`, `formal/patent/`, `formal/scraps/legal/`, or
`working/legal/` without Bob's explicit instruction.
- Add a `README.md` to any new category-level subdirectory, following the
format used throughout this tree: orientation paragraph + bullet list of
real files with one-line descriptions.
+112
View File
@@ -0,0 +1,112 @@
# docs/book/Makefile -- the single LithosAnanke book, built from LaTeX.
#
# Run from the repo root (the root Makefile does this):
# make docs -> build/docs/LithosAnanke.pdf
# make docs TARGET=<board> -> build/docs/LithosAnanke-<board>.pdf
# (same book + that board's appendix)
#
# docs/book/main.tex is the master. Markdown sources are converted by pandoc
# into LaTeX fragments under build/docs/gen/ and \input from main.tex; the
# Markdown stays the source of truth until a chapter is rewritten in LaTeX.
# Figures and tables that present data read the CSV directly at LaTeX time
# (pgfplots / pgfplotstable) and cite it with \datasource{path}; see
# docs/book/README.md.
BOOK_DIR := docs/book
OUT := build/docs
GEN := $(OUT)/gen
BOARD ?=
BOARD_NAME ?=
VARIANT := $(if $(BOARD),$(BOARD),book)
VAR_DIR := $(OUT)/$(VARIANT)
PDF := $(OUT)/LithosAnanke$(if $(BOARD),-$(BOARD)).pdf
PANDOC ?= pandoc
LATEXMK ?= latexmk
PANDOC_FILTERS := $(BOOK_DIR)/pandoc/table-widths.lua $(BOOK_DIR)/pandoc/code-breaks.lua
PANDOC_FLAGS := -f gfm -t latex --top-level-division=chapter --wrap=preserve \
$(foreach f,$(PANDOC_FILTERS),--lua-filter=$(f))
# fragment name : Markdown source. The order of \input lines is main.tex's.
CHAPTERS := \
ontology:docs/reference/ONTOLOGY.md \
roadmap:docs/working/archive/superseded/2025-12-14-starforth-roadmap.md \
boards:boards/README.md \
justification:docs/v4.0.0/JUSTIFICATION.md \
decomposition:docs/v4.0.0/DECOMPOSITION.md \
fabric-0:docs/fabric/FABRIC-0.md \
fabric-1:docs/fabric/FABRIC-1.md \
fabric-2:docs/fabric/FABRIC-2.md \
fabric-3:docs/fabric/FABRIC-3.md \
fabric-3-5:docs/fabric/FABRIC-3.5.md \
fabric-3-6:docs/fabric/FABRIC-3.6.md \
fabric-3-7:docs/fabric/FABRIC-3.7.md \
fabric-4:docs/fabric/FABRIC-4.md
ifneq ($(BOARD),)
ifeq ($(wildcard boards/$(BOARD)/README.md),)
$(error boards/$(BOARD)/README.md is missing: it is the board's appendix)
endif
CHAPTERS += board-$(BOARD):boards/$(BOARD)/README.md
endif
chapter_name = $(word 1,$(subst :, ,$(1)))
chapter_src = $(word 2,$(subst :, ,$(1)))
FRAGMENTS := $(foreach c,$(CHAPTERS),$(GEN)/$(call chapter_name,$(c)).tex)
.PHONY: all tools FORCE
all: $(PDF)
tools:
@missing=""; \
for t in $(PANDOC) $(LATEXMK) xelatex; do command -v $$t >/dev/null 2>&1 || missing="$$missing $$t"; done; \
if [ -n "$$missing" ]; then \
echo "Error: make docs needs:$$missing"; \
echo " sudo apt-get install -y pandoc latexmk texlive-xetex texlive-latex-extra texlive-pictures texlive-fonts-recommended fonts-dejavu fonts-dejavu-extra"; \
echo " (or a user-local TinyTeX + pandoc in ~/.local; see docs/book/README.md)"; \
exit 1; \
fi
# --id-prefix keeps heading labels unique across documents that reuse
# section names ("Summary", "Open questions", ...).
define chapter_rule
$(GEN)/$(call chapter_name,$(1)).tex: $(call chapter_src,$(1)) $(PANDOC_FILTERS) | tools
@mkdir -p $(GEN)
@echo " PANDOC $$< -> $$@"
@$(PANDOC) $(PANDOC_FLAGS) --id-prefix=$(call chapter_name,$(1))- $$< -o $$@
endef
$(foreach c,$(CHAPTERS),$(eval $(call chapter_rule,$(c))))
# Pandoc's syntax-highlighting macros, taken from the installed pandoc so the
# fragments and their macros always come from the same version.
$(GEN)/pandoc-highlighting.tex: $(BOOK_DIR)/pandoc/highlighting.latex | tools
@mkdir -p $(GEN)
@printf '```c\nx\n```\n' | $(PANDOC) -f gfm -t latex -s --template=$< -o $@
# Per-build facts the book prints: the commit every \datasource refers to,
# and which board appendix (if any) is included.
$(VAR_DIR)/meta.tex: FORCE
@mkdir -p $(VAR_DIR)
@{ \
c=$$(git rev-parse --short=12 HEAD 2>/dev/null || echo unknown); \
git diff --quiet HEAD -- 2>/dev/null || c="$$c (+ uncommitted changes)"; \
printf '\\newcommand{\\bookcommit}{%s}\n' "$$c"; \
printf '\\newcommand{\\bookdate}{%s}\n' "$$(date -u +%Y-%m-%d)"; \
printf '\\def\\bookboard{%s}\n' "$(BOARD_NAME)"; \
$(if $(BOARD),printf '\\newcommand{\\bookboardappendix}{board-%s}\n' "$(BOARD)";) \
} > $@.tmp
@cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
FORCE:
TEXINPUTS_BOOK := $(abspath $(VAR_DIR)):$(abspath $(GEN)):$(abspath $(BOOK_DIR)):
$(PDF): $(BOOK_DIR)/main.tex $(FRAGMENTS) $(GEN)/pandoc-highlighting.tex $(VAR_DIR)/meta.tex | tools
@echo " LATEXMK $(BOOK_DIR)/main.tex -> $@"
@TEXINPUTS=$(TEXINPUTS_BOOK) $(LATEXMK) -xelatex -interaction=nonstopmode -halt-on-error \
-file-line-error -outdir=$(VAR_DIR) $(BOOK_DIR)/main.tex > $(VAR_DIR)/latexmk.log 2>&1 || { \
grep -A4 -E '^(.*:[0-9]+:|!)' $(VAR_DIR)/main.log | head -40; \
echo "Error: LaTeX failed; full log: $(VAR_DIR)/main.log"; exit 1; }
@cp $(VAR_DIR)/main.pdf $@
@echo " PDF $@"
+66
View File
@@ -0,0 +1,66 @@
# docs/book/
`make docs` builds one PDF, `build/docs/LithosAnanke.pdf`, from `main.tex` with xelatex.
`make docs TARGET=<board>` builds `build/docs/LithosAnanke-<board>.pdf`: the same book with
`boards/<board>/README.md` added as an appendix.
Tools: `sudo apt-get install -y pandoc latexmk texlive-xetex texlive-latex-extra texlive-pictures texlive-fonts-recommended fonts-dejavu fonts-dejavu-extra`
Without root, a user-local TeX Live works too (this is how the book was first built):
TinyTeX (`curl -sL https://yihui.org/tinytex/install-bin-unix.sh | sh`) plus
`tlmgr install latexmk xetex fontspec pgf pgfplots booktabs multirow fancyvrb fvextra lineno upquote ulem enumitem newunicodechar bookmark hyperref geometry xcolor graphics tools etoolbox fancyhdr truncate amsfonts`,
and the pandoc release tarball unpacked into `~/.local`.
The installed DejaVu decides italics: `fonts-dejavu-core` alone has no serif italic, so
`main.tex` falls back to a slanted upright face; `fonts-dejavu-extra` gives real italics.
## How it fits together
- `main.tex` is the master file. It sets the parts and the chapter order.
- Chapters that are still Markdown are listed in `Makefile` (`CHAPTERS`, as `name:source.md`).
At build time pandoc converts each one into `build/docs/gen/<name>.tex`, and `main.tex`
includes it with `\input{<name>}`. The Markdown stays the source until the chapter is
rewritten in LaTeX. At that point the `.tex` moves into this directory and the `CHAPTERS`
entry is removed.
- `pandoc/highlighting.latex` extracts the code-highlighting macros from the installed pandoc,
so the macros and the fragments always come from the same pandoc version.
- Two Lua filters run on every chapter. `pandoc/table-widths.lua` gives wide tables
proportional wrapping columns, because pandoc's gfm reader leaves column widths unset.
`pandoc/code-breaks.lua` lets long inline identifiers and paths break after `_ / . - :`.
Code blocks wrap through fvextra (`breaklines`).
- `build/docs/<book|board>/meta.tex` is written on every build. It records the commit (and
whether there were uncommitted changes), the date, and the board.
## Rule for data
Any figure or table that shows measured numbers is generated from the CSV when the book is
built. Numbers are never typed in by hand:
```latex
\begin{tikzpicture}
\begin{axis}[xlabel=run, ylabel=K]
\addplot table[col sep=comma, x=run, y=K]{experiments/<campaign>/results.csv};
\end{axis}
\end{tikzpicture}
\datasource{experiments/<campaign>/results.csv}
```
Use `\pgfplotstabletypeset[col sep=comma]{...}` for tables. `\datasource` prints the CSV path
and the commit, so a reader can find the exact file the figure was drawn from. CSV paths are
repo-relative, because xelatex runs from the repo root.
## Older pipelines to fold in or retire
These still exist and still have their own targets. Each one needs a decision during the
curation pass: move it into this book, or retire it.
| Source | Current target | Produces |
|---|---|---|
| `docs/formal/vol1-vm-physics`, `vol2-kernel`, `vol3-research` | `make -C docs/formal vols` | three volume PDFs |
| `docs/formal/dev-guide`, `user-guide`, `cookbook` | `make -C docs/formal books` | three practitioner PDFs |
| `docs/formal/experiments`, `proofs`, `ssrn`, `patent` | `make -C docs/formal standalone` | four standalone PDFs |
| Doxygen (`Doxyfile`) | `make -C docs/formal doxygen` | API reference PDF |
| `scripts/generate-doxygen-appendix.sh` | `make -f v3/Makefile api-docs` | AsciiDoc API appendix |
| `docs/src/internal/formal/*.thy` | `make -f v3/Makefile docs-isabelle` | Isabelle report |
| `scripts/asciidoc-to-latex.sh` | `make -f v3/Makefile docs-latex` | `docs/latex/` |
| `docs/SSRN_companion/Math_Companion_SSRN.tex` | `make -f v3/Makefile math-companion` | SSRN math companion |
+161
View File
@@ -0,0 +1,161 @@
% docs/book/main.tex -- master file of the single LithosAnanke book.
%
% Built by `make docs [TARGET=<board>]` (docs/book/Makefile) with xelatex.
% Fragments named below (ontology, fabric-0, ...) are generated by pandoc
% from the Markdown listed in docs/book/Makefile's CHAPTERS into
% build/docs/gen/; meta.tex is generated per build. Neither is committed.
\documentclass[11pt,openany]{book}
\usepackage{amsmath,amssymb}
\usepackage{fontspec}
% fonts-dejavu-core has no serif/sans italics (fonts-dejavu-extra does); when a
% shape is missing, slant the upright one rather than silently drop emphasis.
\setmainfont{DejaVu Serif}[AutoFakeSlant=0.2]
\setsansfont{DejaVu Sans}[AutoFakeSlant=0.2]
\setmonofont{DejaVu Sans Mono}[Scale=0.85]
\newfontfamily\symbolfont{DejaVu Sans}
\usepackage[letterpaper,margin=1in]{geometry}
\usepackage{xcolor}
\usepackage{graphicx}
\usepackage{longtable,booktabs,array,calc,multirow}
\usepackage{fancyvrb}
\usepackage[normalem]{ulem}
\usepackage{enumitem}
\usepackage{newunicodechar}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
\usepackage[hidelinks]{hyperref}
\usepackage{bookmark}
% --- what pandoc's LaTeX fragments expect (normally from its own template)
\providecommand{\tightlist}{\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\providecommand{\pandocbounded}[1]{#1}
\providecommand{\st}[1]{\sout{#1}}
\newcounter{none} % pandoc: {\def\LTcaptype{none} ...} marks unnumbered tables
\usepackage{etoolbox}
\makeatletter
\def\fnum@table{\tablename~\thetable}
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
\makeatother
\usepackage{fvextra}
\input{pandoc-highlighting}
% Code and diagrams are wider than the page in places: wrap, never overflow.
\RecustomVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},breaklines,breakanywhere,fontsize=\small}
\RecustomVerbatimEnvironment{verbatim}{Verbatim}{breaklines,breakanywhere,fontsize=\small}
\setlistdepth{9}
\renewlist{itemize}{itemize}{9}
\setlist[itemize]{label=\textbullet}
\renewlist{enumerate}{enumerate}{9}
\setlist[enumerate]{label=\arabic*.}
% Running heads: chapter on the left page, section on the right, both cut to
% the page width (several design-record titles are a full sentence long).
\usepackage{fancyhdr}
\usepackage[fit]{truncate}
\pagestyle{fancy}
\fancyhf{}
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
\renewcommand{\sectionmark}[1]{\markright{#1}}
\fancyhead[LE]{\small\truncate{\dimexpr\headwidth-3em}{\leftmark}}
\fancyhead[RO]{\small\truncate{\dimexpr\headwidth-3em}{\rightmark}}
\fancyhead[RE,LO]{\small\thepage}
\renewcommand{\headrulewidth}{0.4pt}
\setlength{\headheight}{14pt}
\fancypagestyle{plain}{\fancyhf{}\fancyfoot[C]{\small\thepage}\renewcommand{\headrulewidth}{0pt}}
\setlength{\emergencystretch}{3em}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0.5em}
% --- glyphs DejaVu Serif lacks: the status marks used across the docs
\newunicodechar{✅}{{\symbolfont ✔}}
\newunicodechar{✓}{{\symbolfont ✓}}
\newunicodechar{❌}{{\symbolfont ✘}}
\newunicodechar{✗}{{\symbolfont ✗}}
\newunicodechar{⬜}{{\symbolfont ☐}}
\newunicodechar{⭐}{{\symbolfont ★}}
\newunicodechar{🔶}{{\symbolfont ◆}}
\newunicodechar{⚠}{{\symbolfont ⚠}}
\newunicodechar{📋}{}
\newunicodechar{🐛}{[bug]}
\newunicodechar{🎯}{[goal]}
\newunicodechar{🟡}{{\symbolfont ●}}
\newunicodechar{📍}{{\symbolfont ▸}}
\newunicodechar{🔓}{[unlocked]}
\newunicodechar{❓}{?}
\newunicodechar{⟺}{\ensuremath{\Longleftrightarrow}}
\newunicodechar{⋯}{\ensuremath{\cdots}}
\newunicodechar{^^^^fe0f}{}
% --- the documents number their own sections (§III.1, D-3, ...)
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{1}
\input{meta}
% \datasource{path/to/data.csv}: cite the data behind a figure or table.
% Every figure or table of measured numbers reads its CSV at build time
% (\addplot table / \pgfplotstabletypeset) and is followed by this line, so
% the reader can find the exact file at the exact commit.
\newcommand{\datasource}[1]{%
\par{\small Data: \texttt{\detokenize{#1}} at commit \texttt{\bookcommit}.}\par}
\title{LithosAnanke and StarForth}
\author{}
\date{Built \bookdate{} from commit \texttt{\bookcommit}%
\ifx\bookboard\empty\else\\Board appendix: \bookboard\fi}
\begin{document}
\frontmatter
\maketitle
\tableofcontents
\chapter{About this book}
This book is generated from the repository by \texttt{make docs}. Each
chapter below is still maintained as the Markdown file named in the table and
converted at build time; a chapter moves into LaTeX source when it is
rewritten. Part~III is the design record: those documents are archival and
are reproduced as written, including their struck-through corrections.
\begin{longtable}{@{}ll@{}}
\toprule
Chapter & Source \\
\midrule
\endhead
Ontology & \texttt{docs/reference/ONTOLOGY.md} \\
Roadmap & \texttt{docs/working/archive/superseded/2025-12-14-starforth-roadmap.md} \\
Boot targets & \texttt{boards/README.md} \\
v4 justification & \texttt{docs/v4.0.0/JUSTIFICATION.md} \\
v4 decomposition & \texttt{docs/v4.0.0/DECOMPOSITION.md} \\
FABRIC-0 \dots{} FABRIC-4 & \texttt{docs/fabric/FABRIC-*.md} \\
Board appendix (\texttt{TARGET=}) & \texttt{boards/<board>/README.md} \\
\bottomrule
\end{longtable}
\mainmatter
\part{The system}
\input{ontology}
\input{roadmap}
\input{boards}
\part{StarForth v4}
\input{justification}
\input{decomposition}
\part{Design record (FABRIC series)}
\input{fabric-0}
\input{fabric-1}
\input{fabric-2}
\input{fabric-3}
\input{fabric-3-5}
\input{fabric-3-6}
\input{fabric-3-7}
\input{fabric-4}
\ifdefined\bookboardappendix
\appendix
\input{\bookboardappendix}
\fi
\end{document}
+29
View File
@@ -0,0 +1,29 @@
-- docs/book/pandoc/code-breaks.lua
--
-- Inline code in the design record is full of long identifiers and paths
-- (g_wirebind_attached_username, kernel/src/arch/riscv64/...), which LaTeX
-- cannot break, so they run into the margin. Emit inline code as \texttt
-- ourselves, escaped the same way pandoc does, with a break opportunity
-- after each separator character.
local BREAK_AFTER = { ["_"] = true, ["/"] = true, ["."] = true, ["-"] = true,
[":"] = true, [","] = true, ["("] = true, ["="] = true }
local ESCAPE = {
["\\"] = "\\textbackslash{}", ["{"] = "\\{", ["}"] = "\\}",
["$"] = "\\$", ["&"] = "\\&", ["#"] = "\\#", ["%"] = "\\%", ["_"] = "\\_",
["^"] = "\\textasciicircum{}", ["~"] = "\\textasciitilde{}",
["'"] = "\\textquotesingle{}", ["`"] = "\\textasciigrave{}",
[" "] = "\\ ",
}
function Code(el)
if not FORMAT:match("latex") then return nil end
local out = {}
for _, cp in utf8.codes(el.text) do
local ch = utf8.char(cp)
out[#out + 1] = ESCAPE[ch] or ch
if BREAK_AFTER[ch] then out[#out + 1] = "\\allowbreak{}" end
end
return pandoc.RawInline("latex", "\\texttt{" .. table.concat(out) .. "}")
end
+3
View File
@@ -0,0 +1,3 @@
$if(highlighting-macros)$
$highlighting-macros$
$endif$
+55
View File
@@ -0,0 +1,55 @@
-- docs/book/pandoc/table-widths.lua
--
-- pandoc's gfm reader leaves every column width unset, so the LaTeX writer
-- emits `l` columns and a table with long cells runs off the page. For any
-- table wider than WIDE characters, give each column a width proportional
-- to its longest cell (clamped to [MIN_COL, MAX_COL] characters); the
-- writer then emits wrapping p{} columns that together fill \linewidth.
local WIDE = 72
local MIN_COL = 6
local MAX_COL = 60
local stringify = pandoc.utils.stringify
local function measure(rows, widths)
for _, row in ipairs(rows) do
local col = 1
for _, cell in ipairs(row.cells) do
local span = cell.col_span or 1
local len = utf8.len(stringify(cell.contents)) or #stringify(cell.contents)
local per = len / span
for c = col, col + span - 1 do
if per > (widths[c] or 0) then widths[c] = per end
end
col = col + span
end
end
end
function Table(tbl)
local n = #tbl.colspecs
local widths = {}
for i = 1, n do widths[i] = 0 end
measure(tbl.head.rows, widths)
for _, body in ipairs(tbl.bodies) do
measure(body.head, widths)
measure(body.body, widths)
end
measure(tbl.foot.rows, widths)
local total = 0
for i = 1, n do total = total + widths[i] end
if total <= WIDE then return nil end
local sum = 0
for i = 1, n do
widths[i] = math.max(MIN_COL, math.min(MAX_COL, widths[i]))
sum = sum + widths[i]
end
for i = 1, n do
tbl.colspecs[i] = { tbl.colspecs[i][1], widths[i] / sum }
end
return tbl
end
+6 -6
View File
@@ -34,7 +34,7 @@ an unrelated structure. The document has been swept; "arena" now survives only i
quotes that reproduce an earlier section verbatim, and in §12's preserved question list, quotes that reproduce an earlier section verbatim, and in §12's preserved question list,
which several sections quote. which several sections quote.
**On `docs/lithosananke/ROADMAP.md`.** As of 2026-08-11, Captain Bob stated this document **On `docs/reference/ROADMAP.md`.** As of 2026-08-11, Captain Bob stated this document
superseded ROADMAP.md entirely. That still holds, transitively, through `FABRIC-1.md` now. superseded ROADMAP.md entirely. That still holds, transitively, through `FABRIC-1.md` now.
--- ---
@@ -4425,7 +4425,7 @@ document and committing that amendment as its own item.*
> `#ifdef __STARKERNEL__`, or elsewhere is an open question for that later item, not > `#ifdef __STARKERNEL__`, or elsewhere is an open question for that later item, not
> decided here. > decided here.
> >
> **Now scoped, 2026-08-11 — resolved in `docs/lithosananke/ROADMAP.md`'s M8 section, > **Now scoped, 2026-08-11 — resolved in `docs/reference/ROADMAP.md`'s M8 section,
> not here.** M8 is "tracked outside Stadium" per §27.5, and its console-facing pieces > not here.** M8 is "tracked outside Stadium" per §27.5, and its console-facing pieces
> don't change this document's own scope, so the resolution lives there rather than as > don't change this document's own scope, so the resolution lives there rather than as
> new 4.3.x items. Short answer to the open question above: `io_words.c` under > new 4.3.x items. Short answer to the open question above: `io_words.c` under
@@ -4999,7 +4999,7 @@ document and committing that amendment as its own item.*
> decision #4 -- both text paths coexist. Per this item's own posture (matching 4.3.6g), > decision #4 -- both text paths coexist. Per this item's own posture (matching 4.3.6g),
> stopping here before scoping REPL wiring (M8). > stopping here before scoping REPL wiring (M8).
> >
> **M8 scoped 2026-08-11 in `docs/lithosananke/ROADMAP.md`, not here** -- per §27.5, M8 is > **M8 scoped 2026-08-11 in `docs/reference/ROADMAP.md`, not here** -- per §27.5, M8 is
> tracked outside Stadium, so its design decisions live in that roadmap's own M8 section > tracked outside Stadium, so its design decisions live in that roadmap's own M8 section
> rather than as new 4.3.x items. Key finding from that scoping pass, worth recording in > rather than as new 4.3.x items. Key finding from that scoping pass, worth recording in
> this document too since it bears on §27.6's CANVAS/REPL-strip framing: the REPL's > this document too since it bears on §27.6's CANVAS/REPL-strip framing: the REPL's
@@ -5939,7 +5939,7 @@ document and committing that amendment as its own item.*
exactly that — no scancode-to-ASCII translation table exists, and no code path connects the exactly that — no scancode-to-ASCII translation table exists, and no code path connects the
keyboard ring buffer to the REPL's line-read loop. The hardware/interrupt layer is done; the keyboard ring buffer to the REPL's line-read loop. The hardware/interrupt layer is done; the
bridge from that layer into text the REPL can act on is not. This is the same conclusion bridge from that layer into text the REPL can act on is not. This is the same conclusion
`docs/lithosananke/ROADMAP.md`'s M8 section and this document's own 4.3.5-series entries `docs/reference/ROADMAP.md`'s M8 section and this document's own 4.3.5-series entries
already recorded ("no keyboard path into the VM on any architecture, confirmed by reading already recorded ("no keyboard path into the VM on any architecture, confirmed by reading
the code") — restated here specifically so 4.4u's TAB-toggle has an accurate prerequisite, the code") — restated here specifically so 4.4u's TAB-toggle has an accurate prerequisite,
not because the earlier conclusion was in doubt. not because the earlier conclusion was in doubt.
@@ -5957,7 +5957,7 @@ document and committing that amendment as its own item.*
keyboard event injected via QEMU's own input-send-event monitor command (not socat/serial), keyboard event injected via QEMU's own input-send-event monitor command (not socat/serial),
screendump showing the typed text landed in the REPL strip; three-arch QEMU boot + logs per screendump showing the typed text landed in the REPL strip; three-arch QEMU boot + logs per
CLAUDE.md. CLAUDE.md.
*Refs:* §27.8, 4.3.5 series, 4.4r, 4.4u, `docs/lithosananke/ROADMAP.md` M8 section. *Refs:* §27.8, 4.3.5 series, 4.4r, 4.4u, `docs/reference/ROADMAP.md` M8 section.
> **DONE 2026-08-12.** Reused item 4.3.5f's `KEY-EVENT` convergence work rather than building > **DONE 2026-08-12.** Reused item 4.3.5f's `KEY-EVENT` convergence work rather than building
> two per-arch tables from scratch (`kbw_key_event`'s FORTH-word logic was refactored into a > two per-arch tables from scratch (`kbw_key_event`'s FORTH-word logic was refactored into a
@@ -7549,7 +7549,7 @@ direct-arena reference — 4.3.7b's own call) behind that lookup.
### 27.8 REPL: prompt, text path, CANVAS geometry (4.4–4.4s) ### 27.8 REPL: prompt, text path, CANVAS geometry (4.4–4.4s)
Scoped 2026-08-11, in conversation with Captain Bob, replacing `docs/lithosananke/ROADMAP.md`'s Scoped 2026-08-11, in conversation with Captain Bob, replacing `docs/reference/ROADMAP.md`'s
M8 section entirely (marked OBSOLETE there, kept for history only). Original visual reference: M8 section entirely (marked OBSOLETE there, kept for history only). Original visual reference:
[`repl-mockup.png`](repl-mockup.png). [`repl-mockup.png`](repl-mockup.png).
+2 -2
View File
@@ -1425,14 +1425,14 @@ evidence nothing regressed.
`docs/CLAUDE.md`'s own correction, made in the same pass, for the doc-toolchain findings — `docs/CLAUDE.md`'s own correction, made in the same pass, for the doc-toolchain findings —
`doxygen` installed, `docs/Makefile` pointer corrected — and this section's own proof-count `doxygen` installed, `docs/Makefile` pointer corrected — and this section's own proof-count
reconciliation above for the Isabelle/HOL findings): reconciliation above for the Isabelle/HOL findings):
- [ ] `docs/lithosananke/ROADMAP.md` and `M7.1.md` — stale `Branch: lithosananke` (no such - [ ] `docs/reference/ROADMAP.md` and `M7.1.md` — stale `Branch: lithosananke` (no such
branch exists post-split), `M7.1.md`'s "Status: Design Complete" (shipped and live, not branch exists post-split), `M7.1.md`'s "Status: Design Complete" (shipped and live, not
just designed), `ROADMAP.md`'s self-contradiction (M8 marked OBSOLETE in one place, just designed), `ROADMAP.md`'s self-contradiction (M8 marked OBSOLETE in one place,
still a live success criterion in another), and its stale "AHCI driver" claim for M9 still a live success criterion in another), and its stale "AHCI driver" claim for M9
(real implementation is `virtio_blk.c`) — not fixed this pass, flagged. (real implementation is `virtio_blk.c`) — not fixed this pass, flagged.
- [ ] Top-level `ROADMAP.md` (StarForth-era, "Phase 0 Complete... Phase 1 Starting," dated - [ ] Top-level `ROADMAP.md` (StarForth-era, "Phase 0 Complete... Phase 1 Starting," dated
2025-12-14) — badly stale, no historical/superseded banner to warn a reader. Not fixed. 2025-12-14) — badly stale, no historical/superseded banner to warn a reader. Not fixed.
- [ ] `docs/03-architecture/word-acl/DESIGN.md` says ACL Phase 7 (LithosAnanke kernel parity) - [ ] `docs/reference/word-acl/DESIGN.md` says ACL Phase 7 (LithosAnanke kernel parity)
is still "remaining" — direct contradiction with `.claude/CLAUDE.md`, which states is still "remaining" — direct contradiction with `.claude/CLAUDE.md`, which states
Phase 7 is independently verified complete. Not fixed. Phase 7 is independently verified complete. Not fixed.
- [ ] `VM-FLEET-ATTRACTOR-DESIGN-20260705.md` claims `doe-campaign.4th` is "broken and being - [ ] `VM-FLEET-ATTRACTOR-DESIGN-20260705.md` claims `doe-campaign.4th` is "broken and being
+4 -4
View File
@@ -102,7 +102,7 @@ decisions get added here, not to `FABRIC-1.md`. Follow the same discipline `FABR
### From FABRIC-1.md §J — Maintainability sweep (2026-08-18) ### From FABRIC-1.md §J — Maintainability sweep (2026-08-18)
- [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.** - [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.**
`docs/lithosananke/ROADMAP.md` and `M7.1.md` — stale `Branch: lithosananke` (no such `docs/reference/ROADMAP.md` and `M7.1.md` — stale `Branch: lithosananke` (no such
branch exists post-split), `M7.1.md`'s "Status: Design Complete" (shipped and live, not branch exists post-split), `M7.1.md`'s "Status: Design Complete" (shipped and live, not
just designed), `ROADMAP.md`'s self-contradiction (M8 marked OBSOLETE in one place, still just designed), `ROADMAP.md`'s self-contradiction (M8 marked OBSOLETE in one place, still
a live success criterion in another), and its stale "AHCI driver" claim for M9 (real a live success criterion in another), and its stale "AHCI driver" claim for M9 (real
@@ -112,10 +112,10 @@ decisions get added here, not to `FABRIC-1.md`. Follow the same discipline `FABR
- [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.** Top-level - [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.** Top-level
`ROADMAP.md` (StarForth-era, "Phase 0 Complete... Phase 1 Starting," dated `ROADMAP.md` (StarForth-era, "Phase 0 Complete... Phase 1 Starting," dated
2025-12-14) — marked OBSOLETE by `cbe7b49` (Captain Bob's call: more than stale), pointing 2025-12-14) — marked OBSOLETE by `cbe7b49` (Captain Bob's call: more than stale), pointing
to `docs/lithosananke/ROADMAP.md` and `FABRIC*.md` for current status. to `docs/reference/ROADMAP.md` and `FABRIC*.md` for current status.
- [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.** - [x] **Fixed 2026-08-26 (commit `cbe7b49`), stale carry-forward closed 2026-08-28.**
`docs/03-architecture/word-acl/DESIGN.md` says ACL Phase 7 (LithosAnanke kernel parity) `docs/reference/word-acl/DESIGN.md` says ACL Phase 7 (LithosAnanke kernel parity)
is still "remaining" — direct contradiction with `.claude/CLAUDE.md`, which states Phase 7 is still "remaining" — direct contradiction with `.claude/CLAUDE.md`, which states Phase 7
is independently verified complete. Phase 7 restated as independently-verified complete and is independently verified complete. Phase 7 restated as independently-verified complete and
the stale lithosananke-branch-parity framing removed by `cbe7b49`. the stale lithosananke-branch-parity framing removed by `cbe7b49`.
@@ -3434,7 +3434,7 @@ hardware), the **release-gate recommendation**, and the **punch lists to complet
each. each.
**The versioning split, decided 2026-08-28 — now standing policy, see **The versioning split, decided 2026-08-28 — now standing policy, see
`docs/lithosananke/ROADMAP.md` "Release Versioning Policy" for the authoritative form.** `docs/reference/ROADMAP.md` "Release Versioning Policy" for the authoritative form.**
v2.0.0 is the **QEMU release** — the point v2.0.0 is the **QEMU release** — the point
where the QEMU-only story is complete and defensible on its own terms. v2.5.0 is the where the QEMU-only story is complete and defensible on its own terms. v2.5.0 is the
**real-hardware release** — the point where the same story transfers to bare metal on a real **real-hardware release** — the point where the same story transfers to bare metal on a real
+6 -6
View File
@@ -2489,13 +2489,13 @@ describe are stripped** (§XXII.5), so the manifest never describes a file that
**Superseded subsystem docs** — `.claude/TRIPOD.md`, `HERMES.md`, `ARTEMIS.md`, `CONSOLE.md` **Superseded subsystem docs** — `.claude/TRIPOD.md`, `HERMES.md`, `ARTEMIS.md`, `CONSOLE.md`
already carry superseded headers, but after this reshuffle they describe a fleet that no longer already carry superseded headers, but after this reshuffle they describe a fleet that no longer
exists. Same for `docs/03-architecture/tripod/{TRIPOD,HERMES,ARTEMIS,README}.md`, which exists. Same for `docs/working/archive/superseded/2026-08-tripod/{TRIPOD,HERMES,ARTEMIS,README}.md`, which
`.claude/CLAUDE.md` still lists as current for Tripod. **Decide deliberately: update, or mark `.claude/CLAUDE.md` still lists as current for Tripod. **Decide deliberately: update, or mark
archival and point at `FABRIC-3.5.md`.** Not a silent edit either way. archival and point at `FABRIC-3.5.md`.** Not a silent edit either way.
**Also in scope:** `capsules/README.md` (lists `hermes/init.4th` as a live personality), **Also in scope:** `capsules/README.md` (lists `hermes/init.4th` as a live personality),
`ROADMAP.md` / `docs/lithosananke/ROADMAP.md`, `CHANGELOG.md`, `README.md`, `ROADMAP.md` / `docs/reference/ROADMAP.md`, `CHANGELOG.md`, `README.md`,
`docs/lithosananke/SYSTEM_ARCHITECTURE.md` and `M7.1.md`, and `proof/COVERAGE.md` (after the `docs/working/archive/historical/2026-01-27-system-architecture-draft.md` and `M7.1.md`, and `proof/COVERAGE.md` (after the
§XXV pass — and per §XXV.3 its *boundary* statement matters more than its file count). §XXV pass — and per §XXV.3 its *boundary* statement matters more than its file count).
`capsules/BLOCK_MAP.md` is a generated artifact; regenerate, don't hand-edit. `capsules/BLOCK_MAP.md` is a generated artifact; regenerate, don't hand-edit.
@@ -2705,7 +2705,7 @@ the version number (§XXVI.3).** No code is authorized.
table in `Makefile.starkernel` itself (lines ~74–82), which is more specific: table in `Makefile.starkernel` itself (lines ~74–82), which is more specific:
``` ```
# Roadmap (per docs/lithosananke/ROADMAP.md "Release Versioning Policy" and # Roadmap (per docs/reference/ROADMAP.md "Release Versioning Policy" and
# FABRIC-2.md §G — X.0.0 = QEMU release, X.5.0 = hardware bare-metal release): # FABRIC-2.md §G — X.0.0 = QEMU release, X.5.0 = hardware bare-metal release):
# v1.0.x — serial-only production (released) # v1.0.x — serial-only production (released)
# v1.5.x — framebuffer VT100 terminal/console milestone (released) # v1.5.x — framebuffer VT100 terminal/console milestone (released)
@@ -2736,7 +2736,7 @@ will step 2.0.1 → 2.2.0 with a released `v2.1.0` tag sitting in a gap the tabl
mention. **Add the line wherever the table lives:** mention. **Add the line wherever the table lives:**
1. `Makefile.starkernel` (the copy above, beside the `LITHOS_VERSION` edit itself). 1. `Makefile.starkernel` (the copy above, beside the `LITHOS_VERSION` edit itself).
2. `docs/lithosananke/ROADMAP.md`, "Release Versioning Policy" — the comment names it as the 2. `docs/reference/ROADMAP.md`, "Release Versioning Policy" — the comment names it as the
upstream source. upstream source.
3. `FABRIC-2.md` §G is the origin of the scheme but is **CLOSED/ARCHIVAL** — **cite it, do not 3. `FABRIC-2.md` §G is the origin of the scheme but is **CLOSED/ARCHIVAL** — **cite it, do not
edit it.** Amending a closed document to match a later decision is exactly what this series' edit it.** Amending a closed document to match a later decision is exactly what this series'
@@ -3011,7 +3011,7 @@ removed 2026-08-15 as non-functional and must not be resurrected.
- ✅ **Versioning policy — CLOSED** (§XXX). All three §XXIX.3 conflicts resolved; LTS criteria - ✅ **Versioning policy — CLOSED** (§XXX). All three §XXIX.3 conflicts resolved; LTS criteria
ratified; engine `VERSION` closed as a rule. ratified; engine `VERSION` closed as a rule.
- ✅ **This release is `2.1.0`** (§XXVIII), even major, working line. - ✅ **This release is `2.1.0`** (§XXVIII), even major, working line.
- ⬜ **Carry §XXX.1–XXX.6 into `Makefile.starkernel` and `docs/lithosananke/ROADMAP.md`** - ⬜ **Carry §XXX.1–XXX.6 into `Makefile.starkernel` and `docs/reference/ROADMAP.md`**
(§XXVIII.2), replacing the old roadmap table. `FABRIC-2.md` §G is cited, never edited. (§XXVIII.2), replacing the old roadmap table. `FABRIC-2.md` §G is cited, never edited.
- ⬜ Engine `VERSION` applied at tag time per §XXX.6's rule. - ⬜ Engine `VERSION` applied at tag time per §XXX.6's rule.
+1 -1
View File
@@ -1484,7 +1484,7 @@ opposite of what per-task commits are for. Tasks 5.5–5.7 return to one-commit-
`PLOT`/`FB-*` relocated to Hestia; no FORTH-79 word semantics changed). The stale `PLOT`/`FB-*` relocated to Hestia; no FORTH-79 word semantics changed). The stale
version-comment block in `Makefile.starkernel` (which still said "even major = LTS" — version-comment block in `Makefile.starkernel` (which still said "even major = LTS" —
backwards relative to the ratified §XXX.1 odd/even rule — and had no `v2.1.0` entry) backwards relative to the ratified §XXX.1 odd/even rule — and had no `v2.1.0` entry)
replaced with the real ladder. `docs/lithosananke/ROADMAP.md`'s own "Release Versioning replaced with the real ladder. `docs/reference/ROADMAP.md`'s own "Release Versioning
Policy" section (the second of the two live places) was still the full retired Policy" section (the second of the two live places) was still the full retired
2026-08-28 policy, not just a stale table — replaced with the ratified §XXX policy text, 2026-08-28 policy, not just a stale table — replaced with the ratified §XXX policy text,
the old text kept struck-through in a `<details>` block for traceability, and the the old text kept struck-through in a `<details>` block for traceability, and the
+13 -1
View File
@@ -1,6 +1,18 @@
# FABRIC-3.7.md — Phase 8 PKI: the elevation entrypoint # FABRIC-3.7.md — Phase 8 PKI: the elevation entrypoint
**Status: OPEN — design only, no code written or authorized.** **Status: CLOSED 2026-10-14 — not needed; elevation removed, not built.** Captain Bob, asked
"is it even a necessary capability?": privilege comes from the drive (Zuse's drive, or the
personality an identity is minted with), so a runtime request-and-grant channel only adds attack
surface — and the old one was a live hole: `KH-ELEVATE-SEND` let any identity have arbitrary
FORTH run as Zuse. `ELEVATE-GRANT` granted automatically on eligibility-list membership (no
human approves), into Hera's own dictionary (never the requester's), and could never reach a
FORTH-79-locked identity's words (pinned, and pins are one-way). Removed: `KH-ELEVATE-SEND`,
message type 8, `zuse-eligibility.4th`, `ZUSE-ELIGIBLE?`/`ZUSE-ELIGIBILITY-ADD`/
`ELEVATE-PUBKEY-UNPACK`, the eligibility list itself and Part B's gate in `zuse.4th`;
`devblock_from_top` 1–63 on Artemis's disk stay reserved, unused (his ruling). See
`FABRIC-3.md` §XXXVII. Everything below is kept as the record of the design.
**Former status: OPEN — design only, no code written or authorized.**
**CORRECTION (2026-09-22, before any code was written against this document): §2's central **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 claim — that the old `SEND-ELEVATE-REQUEST` passed a raw cross-VM address into `ELEVATE-GRANT`'s
+414 -5
View File
@@ -2461,6 +2461,29 @@ the existing xHCI multi-device history (§VII, and the 2026-09-05/06/07 fixes re
-- possibly a recurrence or a related gap in the same per-slot attach-pending scan, given the -- possibly a recurrence or a related gap in the same per-slot attach-pending scan, given the
similar shape ("several ports become pending at once, only some get serviced"). similar shape ("several ports become pending at once, only some get serviced").
**No longer reproduces, 2026-10-14 -- checked on all three ISAs, closed.** Both reproductions
above were rerun against a freshly minted, matched set: a scratch `artemis.img` and Zuse drive,
and five identity drives (`00`-`04`) minted at a live `zuse@Hera` prompt by `MINT`, one hot-plug
at a time (`logs/20261014-082526`). Not against the committed images: every image under
`disk/thumbdrives/`, and `disk/artemis.img`, is all zeros since `e56974e0` bleached them ahead of
§XXXV.6's re-mint, which has not been done. A blank drive is correctly passed over in silence
(its home-blocks check reads BLANK, logged at debug level only), so a first attempt today with
copies of the committed images (`logs/20261014-062249`) showed no WIREBIND lines and proved
nothing either way.
| ISA | five drives present at power-on | five drives hot-plugged ~1 s apart over QMP |
|---|---|---|
| amd64 | 5/5 attached (`logs/20261014-082755`) | 5/5 attached (`logs/20261014-083236`) |
| aarch64 | 5/5 attached (`logs/20261014-083415`) | 5/5 attached (`logs/20261014-083917`) |
| riscv64 | 5/5 attached (`logs/20261014-084134`) | 5/5 attached (`logs/20261014-084624`) |
Zuse's own drive was confirmed in every boot as well. No code changed for this. What closed the
gap is most likely the xHCI driver's per-port connect queue (`kernel/src/usb/xhci.c`,
`dev->pending_events[]`: a connect event that arrives while a command is in flight is held and
handled once the command ring is idle, not dropped); when that landed cannot be traced past the
source-tree reorganisation (`a8b70e88`), so this is inference, not proven. The one-at-a-time
attach rule of §XV and §XXXI is no longer needed.
## XV. 3(architecture) × 9(identity) × 3(replicate) randomized full-factorial DoE — self-contained ## XV. 3(architecture) × 9(identity) × 3(replicate) randomized full-factorial DoE — self-contained
FORTH capsule, replacing the ad hoc exerciser-feeding process (2026-09-11) FORTH capsule, replacing the ad hoc exerciser-feeding process (2026-09-11)
@@ -3969,7 +3992,7 @@ are attached reliably in the first place, including under the "already plugged i
case §XIV's own second reproduction showed failing. case §XIV's own second reproduction showed failing.
**Bug 2 -- the MSG-TICK/Stage-3-switch dual-ownership rough edge (§XXVIII's own admission, **Bug 2 -- the MSG-TICK/Stage-3-switch dual-ownership rough edge (§XXVIII's own admission,
never revisited).** Both MSG-TICK's idle-pump dispatch and the Stage 3 timer-driven switcher can never revisited).** *Closed 2026-10-14: one delivery path, built -- §XXXVI.* Both MSG-TICK's idle-pump dispatch and the Stage 3 timer-driven switcher can
independently move control between the same VMs; not reconciled, not observed to interact badly independently move control between the same VMs; not reconciled, not observed to interact badly
so far, but never proven safe under all interleavings either. Directly relevant to Stage 4 for so far, but never proven safe under all interleavings either. Directly relevant to Stage 4 for
the same reason as Bug 1: WIREBIND VMs bring a second population of dynamically-birthed contexts the same reason as Bug 1: WIREBIND VMs bring a second population of dynamically-birthed contexts
@@ -4579,7 +4602,7 @@ call sites (`repl.c` has 18); most are direct interactive replies already correc
this rule -- reclassifying the specific sites that aren't is Stage D's job (the same files Stage this rule -- reclassifying the specific sites that aren't is Stage D's job (the same files Stage
C's triage already walks), not repeated here. C's triage already walks), not repeated here.
**Decision on the two §XXVII gaps: fix eviction now, defer `LOG-FLUSH` again.** **Decision on the two §XXVII gaps: fix eviction now, defer `LOG-FLUSH` again.** *`LOG-FLUSH` built 2026-10-14 -- §XXXVIII.*
`LOG-FLUSH` needs real new machinery first -- the per-VM log buffer its own doc comment already `LOG-FLUSH` needs real new machinery first -- the per-VM log buffer its own doc comment already
presumes (`vm_log_buffer.h`) does not exist anywhere in the tree, confirmed by grep; building it presumes (`vm_log_buffer.h`) does not exist anywhere in the tree, confirmed by grep; building it
means designing that buffer format and the flush word together, genuine feature work deserving means designing that buffer format and the flush word together, genuine feature work deserving
@@ -5197,6 +5220,19 @@ sequence at all until/unless this is fixed at the source -- the interactive two-
(typed live over the serial socket) sidesteps the bug, it does not fix it. Flagged here as a (typed live over the serial socket) sidesteps the bug, it does not fix it. Flagged here as a
real, reproducible defect worth its own fix later, out of scope for this section. real, reproducible defect worth its own fix later, out of scope for this section.
**Fixed 2026-10-14.** The mechanism, traced: `vm_interpret()` (`kernel/src/vm/vm_core.c`, and
the hosted `v3/src/vm.c`) copies each text it runs into the VM's one `input_buffer` and resets
`input_pos`. `LOAD` runs its block by calling it, so the block took the place of the line `LOAD`
was on, and when the block was done the outer loop found nothing left to read. The same held
for every word that runs text from inside a line: `-->`, a capsule's `EXEC`, 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 afterwards, as FORTH-79's `LOAD` keeps the
input stream it interrupts. Two POST cases, `LOAD.rest_of_line` (`1 LOAD 0 0 /`) and
`THRU.rest_of_line` (`1 2 THRU 0 0 /`), fail 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, hash `0x08873e0f44b7cb2a` unchanged. So a `THRU`-then-call
line now works as one `SK_CMD`; that use itself was not re-run.
### XXXIV.2 -- A cross-session QEMU collision killed the first real relaunch at 0 trials ### XXXIV.2 -- A cross-session QEMU collision killed the first real relaunch at 0 trials
Once running for real (via the two-line workaround), the campaign was silently killed a fourth Once running for real (via the two-line workaround), the campaign was silently killed a fourth
@@ -5463,7 +5499,7 @@ device it was minted on.
- Build a **new, blank 1 GiB `disk/artemis.img`** from scratch -- not a resize of the current - Build a **new, blank 1 GiB `disk/artemis.img`** from scratch -- not a resize of the current
file. No migration code written or needed. file. No migration code written or needed.
- **Zuse re-minted fresh** on the new image (genesis marker, root CA placement, per - **Zuse re-minted fresh** on the new image (genesis marker, root CA placement, per
`docs/03-architecture/word-acl/DESIGN.md`'s Phase 8 design and `docs/reference/word-acl/DESIGN.md`'s Phase 8 design and
`project_phase8_milestone6_complete.md`'s already-verified entropy/signing/block-fence chain -- `project_phase8_milestone6_complete.md`'s already-verified entropy/signing/block-fence chain --
same mechanism, new device, not new code). same mechanism, new device, not new code).
- **All 8 thumbdrive identities re-minted** (`project_thumbdrive_identities_minted_20260906.md`: - **All 8 thumbdrive identities re-minted** (`project_thumbdrive_identities_minted_20260906.md`:
@@ -5476,8 +5512,8 @@ device it was minted on.
### XXXV.7 -- Genuinely open, not decided here ### XXXV.7 -- Genuinely open, not decided here
- **Exact v2 decimation factor**, if/when v2 is built at all (§XXXV.4). - **Exact v2 decimation factor**, if/when v2 is built at all (§XXXV.4).
- Whether `THRU`'s own line-swallowing defect (§XXXIV.1, still un-root-caused at the C level) gets - ~~Whether `THRU`'s own line-swallowing defect (§XXXIV.1, still un-root-caused at the C level) gets
fixed before or after this work -- it blocks true single-command `SK_STARTUP_FORTH` autolaunch fixed before or after this work~~ Fixed 2026-10-14, before it (§XXXIV.1) -- it blocks true single-command `SK_STARTUP_FORTH` autolaunch
of the campaign regardless of persistence format; the two-line interactive workaround still of the campaign regardless of persistence format; the two-line interactive workaround still
applies either way. applies either way.
- Disposal of the two stale partial amd64 runs' data (§XXXIV.5's own still-open item) is unrelated - Disposal of the two stale partial amd64 runs' data (§XXXIV.5's own still-open item) is unrelated
@@ -5488,3 +5524,376 @@ device it was minted on.
design/decision only, no capsule/C code, no new disk image, and no re-mint actually performed design/decision only, no capsule/C code, no new disk image, and no re-mint actually performed
or committed for the drive resize, the persistence region, or the N=2 campaign shape. or committed for the drive resize, the persistence region, or the N=2 campaign shape.
## XXXVI. One delivery path: a VM takes its own messages, on its own turn -- built (2026-10-14)
Closes the MSG-TICK/Stage-3 dual-ownership item (§XXVIII, §XXIX bug 2, §XXXI), as ruled in
`FABRIC-3.5.md` §XXXII ("one mover"); Captain Bob, 2026-10-14: collapse it before the bare-metal
builds. **The state before:** the MSG-TICK pump was gone (FABRIC-3.6 Stage E), but two paths
still ran a VM's kernel-Hermes messages -- the VM's own outermost colon-word checkpoint, and
Hera's idle beat, which walked every live VM and ran each one's messages *for* it, on Hera's
stack. The second was the only path for a VM nothing else drives (a WIREBIND identity's `~user`
VM, FABRIC-3.6 task 3.9). It was guarded (parked VMs are not LIVE and were skipped) but it was
two paths.
**What changed.**
- `sk_hermes_send_one()` marks the receiver as having work for the switch signal.
- What a VM runs on its own native stack (`sk_vm_switch_entry()`, until now a placeholder that
only yielded) now takes its own messages, then yields. Not while its interpreter is mid-line on
some other, parked, stack (new per-VM `interpret_depth`, counted in `vm_interpret()`): then
they wait and it asks for another turn.
- Hera's idle beat no longer runs anyone's messages but her own; it makes the switch the switch
signal has pending (`sk_vm_switch_service_pending()`, shared with the colon-word checkpoint),
so a message still arrives while she sits at her prompt.
- Every VM is registered with the switch signal at its birth (idempotent; the Tripod and
WIREBIND registrations stay) and unregistered when killed or reaped.
- `sk_hermes_drain_checkpoint()` refuses, with "Kernel-Hermes: message held -- its VM is not the
one running", any call not in the VM's own context: its interpreter running at the outermost
text, or it is the VM switched in and not mid-line elsewhere. This is the test: it failed
first, holding every relayed line (`logs/20261014-092558`), and never fires now.
- A VM yielding from the top of its own loop stays LIVE; only a VM switched out mid-line is
SWITCHED_OUT. Found by the test: with every yield SWITCHED_OUT, the console stopped relaying
to an identity after its first message (it relays only to a LIVE one) and KILL would have
refused every VM that had ever taken a message (`logs/20261014-095904`).
**A real defect found on the way, amd64 only:** `sk_vm_switch_prime()` (`arch/amd64/switch.S`)
built a first-entry frame that left `rsp` a multiple of 16 at `sk_vm_switch_entry()`'s entry; the
SysV ABI wants `rsp + 8` to be. Harmless while that function only switched back; a #GP (an
aligned SSE store to the stack) the first time it ran the interpreter there
(`logs/20261014-093823`). The frame is now 64 bytes with a null return address above the entry
address. aarch64 (160) and riscv64 (208) frames were already 16-aligned. This may also be what
stopped the 2026-09-14 attempt (`vm_interpret(self, "MSG-TICK")` in the same function, reverted
after a stall never root-caused) -- not proven.
**`FABRIC-3.5.md` §XXXII.5's three build questions, as answered here:** (1) the payload waits in
the receiver's kernel-Hermes queue and is run by the receiver on its own stack on its turn; (2)
Hera's special case stays only in this sense -- her messages run at her own idle beat, which is
her own context; (3) `g_mama_interpreting` and `g_idle_pump_active` stay, still guarding Hera's
own drain.
**Verified.** A WIREBIND identity (`S" 00" USE`, then four plain lines: `1 2 + .`, an unknown
word, `5 6 * .`, `7 8 + .`) receives and runs all four on its own stack -- `3`, the unknown-word
error, `30`, `15` -- with nothing held and no fault, on amd64 (`logs/20261014-101933`), aarch64
(`logs/20261014-102701`) and riscv64 (`logs/20261014-100948`). Five identity drives hot-plugged a
second apart at the prompt all attach (their attach acknowledgements are messages to Hera)
(`logs/20261014-102525`). Standard acceptance, committed disks: all three ISAs to `zuse@Hera`,
POST 1052 tests passed, `PARITY:M7.1a ... hash=0x08873e0f44b7cb2a` unchanged, no unknown word
(`logs/20261014-103248`, `-103409`, `-103616`). Superseded attempts, kept: `-092406` (wrong `USE`
syntax), `-094908` (before the LIVE-on-yield fix, one line only).
## XXXVII. Any identity could run FORTH as Zuse; a message could run twice; elevation removed (2026-10-14)
Found while building FABRIC-3.7's elevation entrypoint, proven live, fixed test first.
**1. Two words let any VM have Hera run any text, in her own dictionary -- Zuse's.**
`KH-ELEVATE-SEND ( paddr plen -- ok? )` and `KH-BLK-ATTACH-SEND ( paddr plen -- ok? )`
(`repl.c`) are registered in every VM (`word_registry.c`), and each sent whatever text it was
handed to Hera as a kernel-Hermes message, which Hera interprets. From a WIREBIND identity's
console: `S" 777 ." KH-ELEVATE-SEND .` and `S" 778 ." KH-BLK-ATTACH-SEND .` -- Hera printed
`777` and `778` (`logs/20261014-105930`, `-110937`). A line holding `"` is run on the identity's
console VM instead of relayed (`repl.c`'s own v1 limitation), which is what reached them.
**2. One message could run twice.** `sk_hermes_drain_checkpoint()` popped a message only after
running it; a payload that runs a colon word reaches the checkpoint in `execute_colon_word()`,
which drains the same VM again -- and found the same message at the head. A relayed `T3`
(`: T3 333 . ;`) printed `333 333`; `778` above printed twice (`logs/20261014-110937`).
**3. Elevation itself: not needed (Captain Bob, 2026-10-14).** Asked whether it was even a
necessary capability, given (1): privilege comes from the drive -- Zuse's, or the personality an
identity is minted with -- and a runtime request-and-grant channel only adds attack surface.
`ELEVATE-GRANT` granted on eligibility-list membership alone (no human approves), into Hera's own
dictionary (never the requester's), and could never reach a FORTH-79-locked identity's words (all
pinned; pins are one-way). Its only caller had been gone since 2026-09-22 and nothing missed it.
`FABRIC-3.7.md` is closed as not needed.
**Fixes.**
- Removed: `KH-ELEVATE-SEND`; message type 8 (retired, not reused); `capsules/zuse-eligibility.4th`
(`ELEVATE-GRANT`, blocks 4021-4022) and its `EXEC` in `init.4th`; the C words `ZUSE-ELIGIBLE?`,
`ZUSE-ELIGIBILITY-ADD`, `ELEVATE-PUBKEY-UNPACK`; the eligibility list (`zuse_eligibility.c`,
`zuse_eligibility.h`, `zuse_eligibility_list.h`); FABRIC-3.7 Part B's gate on
`ZUSE-ELIGIBILITY-ADD` in `zuse.4th`. `devblock_from_top` 1-63 on Artemis's disk stay reserved,
unused (his ruling). `NAME>XT` stays: general-purpose.
- `KH-BLK-ATTACH-SEND` is now `( dev-addr ok? -- sent? )`, refused unless Artemis calls it; the
kernel writes `<dev-addr> <0|1> BLK-ATTACH-ACK` itself. Artemis's `HERA-BLK-ATTACH-REQ` is now
`DUP BLK-ATTACH KH-BLK-ATTACH-SEND DROP` (its text builder is gone, and with it Artemis's one
"Unterminated comment" warning, a nested-paren comment).
- `BLK-ATTACH-ACK` is refused unless Hera runs it.
- The drain pops a message before running it; the message, and so its payload, is still held
until released after.
**Verified.** The same session after the fix (`logs/20261014-112514`): `333` once,
`KH-BLK-ATTACH-SEND: refused -- only Artemis replies to a storage attach`, `UNKNOWN WORD:
'KH-ELEVATE-SEND'`, identity `00` attaches. Five identities hot-plugged at the prompt all attach
(`logs/20261014-113615`). Standard acceptance, all three ISAs: `zuse@Hera`, POST 1052 passed, no
unknown word, **`PARITY:M7.1a word_count=523 ... hash=0xb73b58052d591638` -- a deliberate new
baseline** (was 530 / `0x08873e0f44b7cb2a`: the four C words and `zuse-eligibility.4th`'s
definitions are gone from Hera's dictionary) (`logs/20261014-113112`, `-113232`, `-113450`). A first attempt (`-111859`) broke
attach two ways, both mine: nested parens in the new capsule comment, and `%lld`, which the
kernel's freestanding `snprintf` does not do.
**Found, not fixed (pre-existing, unrelated):** Hera prints two and Hestia three `( Unterminated
comment` warnings at every boot, in logs from before this work too.
## XXXVIII. `LOG-FLUSH` built: a VM's log records reach Artemis's log ring (2026-10-14)
Deferred in §XXXII.4 as its own initiative; Captain Bob, 2026-10-14: build it before the
bare-metal builds. His rulings: **everything the VM logs** goes in its buffer (at or above the
log level -- the one, global `LOG-LEVEL!` setting, the same filter `log_message()` applies);
it goes to disk **on `LOG-FLUSH`, when the buffer fills, and at once on an ERROR record**.
**Built.**
- Each VM has a buffer of its own (`VM.log_buf`, 900 bytes, packed records: level, timestamp,
length, text; `vm_log_buffer.c`/`.h`). `log_message()` (`shim.c`) adds every record it prints
to the buffer of the VM it is attributed to (`vm_log_attributed_vm()`); a record made outside
any VM's text -- the kernel's own -- belongs to none and is not kept.
- A flush is one kernel-Hermes message to Artemis, type `SK_HERMES_MSG_TYPE_LOG_BATCH` (10), the
one message type that is not FORTH text: `sk_hermes_drain_checkpoint()` hands it to
`vm_log_batch_deliver()`, which writes each record with `log_region_append()` -- in Artemis's
own context, on her turn (§XXXVI). The record's source is the sender the kernel stamped on the
message, never a name the sender gives: a VM cannot write under another's name.
- Nothing is lost silently: records that cannot go (Artemis not yet live -- all of Hera's POST --
or the send refused) are counted, and the next flush that can be sent leads with "N log
records not sent: Artemis not ready" (175 at a normal boot).
- `LOG-FLUSH ( -- )`, every VM. `LOG-SHOW ( n -- )`, Hera only: the newest n records, oldest of
them first, as source, level, text -- added because the ring had no reader at all, so nothing
written there could be read or checked (`log_region_read_recent()`). Hera only because it shows
every VM's records, and Hera's console is Zuse's.
**A real defect in the ring, found by the first test that filled it:** growth
(`log_region_append()`) claimed to be "safe regardless of wrap state" and was not. The ring is
full when it grows, so head == tail; nothing moved and tail stayed put, so the next write
overwrote the oldest record and the new, blank slots read back as records inside the live
range. 30 records written to a fresh ring read back as 28 of them and 12 blank
(`logs/20261014-115648`; also `-115434` on a ring already damaged by an earlier test). Fixed:
the records from head on move up by the slots added, and the next write goes into the gap (with
head at 0 -- the only case growth meets, since nothing is evicted before the ring is at its full
size -- simply at the old end). §XXXII.4 had flagged eviction as never live-exercised.
**Verified.** Test first: `LOG-FLUSH` and `LOG-SHOW` unknown (`logs/20261014-114028`). Then:
Hera's WARN probe and her boot warnings, under source `Hera`, after `LOG-FLUSH`; identity `00`'s
ERROR probe, sent by itself at once, under source `00` (`-114847`); the lost-records notice
(`-115434`); 30 records through a growth, in order, no blank, on amd64 (`-115841`), aarch64
(`-120526`) and riscv64 (`-120746`). Standard acceptance, all three ISAs: `zuse@Hera`, POST 1052
passed, no unknown word, **new baseline `word_count=526 ... hash=0x82f4ae7cb2e2d424`**
(deliberate: Hera's new words) (`logs/20261014-120027`, `-120148`, `-120356`).
## XXXIX. The Pi 5's native path: MMU and caches on before any C, bounded mailbox, framebuffer address from the devicetree -- and a rehearsal on QEMU that found three more (2026-10-14)
Captain Bob, 2026-10-14: "fix the pi 5 problems" -- the three from the Friday review (`boards/BRINGUP.md`
R2, R3).
**1. MMU and caches off (R2).** The firmware enters at EL2 with the MMU off: every access is
Device memory, where an unaligned access or an exclusive faults and nothing is cached. The
aarch64 kernel had never needed to turn the MMU on -- under UEFI it runs on the firmware's map
(`arch_mmu_init()` is a stub; `vmm.c` builds x86-shaped tables it never loads on aarch64).
`native_rpi5_entry.S` now: cleans and invalidates the data cache over the whole image first
(so nothing the firmware left there lands on top of what follows); builds an identity map, the
image's GiB Normal write-back in 2 MiB blocks, every other GiB Device-nGnRE and never executable;
sets MAIR, TCR and TTBR0 and turns on M, C and I at whichever EL it was entered at (EL2 on the
Pi 5, EL1 handled too), with WXN and alignment checking off. In C, `rpi5_mmu.c` then makes every
further GiB the devicetree's `/memory` covers entirely Normal, and makes the framebuffer Normal
non-cacheable (the display reads it straight from RAM), each change break-before-make.
**2. Unbounded mailbox waits (R3).** Every wait now gives up after one second by the
architectural counter (`-5`); before any console exists a silent VideoCore must cost a missing
framebuffer, not a hang. With the caches on, the request buffer is cleaned to RAM before it is
sent and invalidated before the answer is read: the VideoCore does not see the ARM's caches.
**3. The framebuffer address (R3).** `& 0x3FFFFFFF` was the Pi 4's rule. The address the firmware
returns is now carried through the devicetree's `dma-ranges` from the firmware node up: on the
Pi 5 (the real `bcm2712-rpi-5-b.dtb`) the firmware node's is empty and `/soc` has none, so it is
already physical; on a Pi 4 `/soc` maps bus `0xC0000000` onto 0, and that is handled too. An
address no entry holds is refused (`-6`). Still unverified: the allocate tag's size field.
**The rehearsal.** There is no QEMU model of the Pi 5, but QEMU's virt machine with
`virtualization=on` enters a raw image exactly as the Pi 5's firmware does: at EL2, MMU off,
devicetree in x0. New `make -f kernel/Makefile ARCH=aarch64 RPI5_NATIVE_BASE=0x40080000
rpi5-rehearsal` links the same native image at virt's address (the linker script's base is now
`RPI5_NATIVE_BASE`, 0x80000 by default) and boots it, Cortex-A76, one QEMU, foreground. It found
three more, each of which would have stopped the Pi 5:
- **The PL011's register shift**, mine (`c9519173`): `fdt_uart.c` gave a devicetree PL011 a shift
of 0, but `console.c` numbers its registers by word -- the flag register was read at +6, not
+0x18: an alignment fault on Device memory at the first character. The UEFI path never met it
(it uses a built-in default with the right shift), and the host test asserted the wrong value.
Shift 2 now; the test expects it.
- **The GIC's address**: `apic.c` read the GIC's `reg` as two 64-bit cells with no translation --
right only where the GIC is a child of the root. On the Pi 5 it is on `/soc` (one cell,
`0x7fff9000`), `0x107fff9000` to the CPU. New `fdt_reg_address()` (`fdt.c`) reads a node's `reg`
entry in its parent's cells and carries it up through every bus's `ranges`; the GIC lookup uses
it, and accepts virt's `arm,cortex-a15-gic` too. Checked against the real Pi 5 devicetree:
`tools/fdt_uart_test.c <dtb> pl011 0x107d001000 2 4 arm,gic-400 0x107fff9000 0x107fffa000`.
- **No timer interrupt at EL2**: with `HCR_EL2.IMO/FMO/AMO` clear an IRQ targets EL1 and is never
taken while the CPU runs at EL2 -- "Heartbeat: 0 ticks". The entry stub sets them at EL2. The
UEFI path runs at EL1 and never met it.
**Verified.** Rehearsal, final: POST 1052 passed, `PARITY:M7.1a word_count=526 ...
hash=0x82f4ae7cb2e2d424` -- the same as the UEFI build -- the Tripod born, the heartbeat ticking,
no exception (`logs/20261014-124530/aarch64-rpi5/`). Earlier rehearsal and the hand-run QEMU
sessions that found the three are not logged (`-d int` to a scratch file); `logs/20261014-123129`
is the first, silent, run. Not rehearsed: the mailbox and framebuffer (virt has neither), the Pi
5's own UART and GIC addresses (the host test checks them against its devicetree), PCI (virt's
needs ACPI; the Pi 5's is R4). The board image (`make boot_image TARGET=RASPI`) links at 0x80000
and ends at 0x834000. Standard acceptance, all three ISAs: POST 1052 passed, same hash
(`logs/20261014-125305`, `-125427`, `-125635`).
## XL. The USB controller found as real hardware has it (`boards/BRINGUP.md` A1, 2026-10-14)
Captain Bob, 2026-10-14: "start on A1". The xHCI driver matched QEMU's own controller only --
vendor and device `1B36:000D`, on PCI bus 0, function 0 -- so no real board's controller was ever
found, and with it no thumbdrive, no login, no keyboard to come.
**What a real controller needs, done:**
- **Found by class**, `0x0C/0x03/0x30`, from any vendor: new `pci_find_class()` (`pci.c`) reads
every bus, slot and function the configuration space reaches (port I/O on amd64, all 256 buses;
through ECAM, the MCFG entry's bus range, now recorded). Real controllers sit behind bridges.
- **Mapped at its real size**: new `pci_bar_size()` (the standard all-ones probe, decoding off
meanwhile); never less than the old fixed 64 KiB.
- **Taken from the firmware** (xHCI 1.2 section 4.22.1): through the USB Legacy Support extended
capability, OS-owned set and BIOS-owned waited out for a second (taken regardless after, as
Linux does), every SMI enable off and SMI status cleared. QEMU's controller has no such
capability; a PC's BIOS, driving USB for its own setup screen, does.
- **64-byte contexts** (`HCCPARAMS1.CSZ=1`) laid out, not refused: every context is 32 or 64 bytes
apart (`xhci_ctx_bytes()`); a 64-byte context holds the same fields in its first 32 bytes, so the
existing structs stand.
- `XHCI_QEMU_ARGS` (`kernel/Makefile`) replaces the QEMU controller, to rehearse one placed as real
hardware places it.
**Verified.** Test first: QEMU's NEC controller (`nec-usb-xhci`, vendor 1033) behind a PCIe root
port on bus 1, Zuse's drive on it -- before, nothing attached and no `zuse@Hera` prompt
(`logs/20261014-131238`); after, the drive attaches and Zuse is minted, on amd64 (`-131934`),
aarch64 (`-132056`) and riscv64 (`-132257`). Standard acceptance with the usual controller, all
three: POST 1052 passed, hash `0x82f4ae7cb2e2d424` unchanged (`-132431`, `-132548`, `-132746`);
five identities hot-plugged, all attached (`-132912`).
**Not rehearsable, so unproven until the SER5:** the firmware handoff and 64-byte contexts --
QEMU's controller has neither. **Still open:** one controller only -- the first found. A PC with
several (the SER5 has more than one) drives that one's ports alone; the stick and keyboard must be
in them until the driver runs several (`xhci_get_dev()` is a single controller throughout).
## XLI. A USB keyboard, a full one (`boards/BRINGUP.md` A3) -- and a hang on any PC without PS/2 (S3) (2026-10-14)
Captain Bob, 2026-10-14: "start on A3", then, mid-way: "use this keyboard as a target. for example
include caps lock, numlock, keypad and arrow ... Note for `later`, let's build keyboard VM's"
(recorded as a concept, nothing built).
**Built.**
- **The device** (`xhci.c`): a configuration whose interface is HID / boot / keyboard (3/1/1) is
taken as a keyboard, not refused as "not a drive": its first interrupt IN endpoint is configured
(`xhci_cmd_configure_hid_endpoint()` -- interval converted from bInterval for full/low and high
speed), `SET_CONFIGURATION`, then `SET_PROTOCOL(boot)` (a keyboard starts in report protocol),
then one Normal TRB at a time on its ring; each report is read and the next queued, deferred like
every doorbell in this driver. Unplugging forgets it. "USB keyboard ready" on the console.
- **The keys** (`usb_kbd.c`): a boot report says which keys are held; the difference from the one
before is the presses and releases, modifiers included, ErrorRollOver ignored. HID usage IDs
become Linux keycodes -- the namespace the PS/2 and virtio keyboards already use -- for a full
keyboard: the main block, F1-F12, Print Screen/Scroll Lock/Pause, the navigation block, arrows,
Num Lock and the whole keypad. `sk_key_event_poll()` (`keyboard_words.c`) reads them first, on
every ISA.
- **What a key means** (`repl.c`, every keyboard alike): Caps Lock and Num Lock are toggles (Num
Lock on at start); Caps Lock acts on letters, Shift reverses it; the keypad types `/ * - +` and
Enter always, digits and `.` with Num Lock on, nothing with it off (navigation -- this REPL's
line editor appends and backspaces only, so arrows and Home/End type nothing either); the 102nd
key types `\` `|`. The lock state goes to a USB keyboard's lights by `SET_REPORT` on its next
report.
- **Speed**: one report at a time, serviced only on the once-a-second idle beat, lost keys -- the
keyboard's own queue overflowed at typing speed (found by the test: of a typed line, only `1`
arrived). While a USB keyboard runs, the console now services the event ring on every timer
tick as it waits for a key.
**S3, found on the way -- a hang.** To have the USB keyboard be QEMU's only keyboard on amd64 the
test turned the PS/2 controller off (`-machine i8042=off`), and the kernel hung at boot just after
the I/O APIC: with no controller port 0x64 reads 0xFF, "output full" for ever, and `i8042_init()`'s
drain never ended (nor would `i8042_drain_stale()`'s). A legacy-free PC -- quite possibly the SER5 --
would have stopped there. Now: 0xFF means no controller, "i8042: no PS/2 controller -- keyboard by
USB only", nothing more done to it; every drain bounded. With a controller, unchanged.
**Verified.** amd64 with the USB keyboard the only keyboard, typed over QMP (`logs/20261014-135243`):
`1 2 + .` on the main keys and again on the keypad with keypad Enter -- `3` both times; Caps Lock,
then `s" ab" type` typed in lower case -- the line reads `S" AB" TYPE` and prints `AB`; Num Lock
off, keypad 7, Enter -- nothing typed. aarch64 and riscv64 (`-135420`, `-135629`): "USB keyboard
ready" and the same three results -- there QEMU also has a virtio keyboard, so those runs show the
USB keyboard configured, not which keyboard each key came through. The hang and its fix:
`-134410` (stops after the I/O APIC), `-135022` (boots). Standard acceptance, all three ISAs: POST
1052 passed, hash unchanged, PS/2 initialised as before on amd64 (`-135808`, `-135918`, `-140123`);
five identities hot-plugged, all attached (`-140240`). Test first? No: this time the test was
written after the code, its "before" being no keyboard support at all (`-134213`, where QMP could
not reach the device, records the enumeration working).
**Limits, not hidden:** the first xHCI controller only (§XL); a keyboard whose first interface is
not its keyboard is not used; no key repeat (a boot keyboard does not repeat, and nothing here
does it for it); the lights are sent on the next report after a lock key, not at once.
## XLII. Every USB controller, not the first (`boards/BRINGUP.md` A1, the rest) (2026-10-14)
Captain Bob, 2026-10-14: "do multiple controllers" -- §XL's open item. A PC has several xHCI
controllers, each with its own ports; only the first found was driven, so a stick or keyboard in
another's ports was never seen.
**What assumed one controller, and now does not:**
- `xhci.c`: one latched `g_xhci_dev` → a table of up to `XHCI_MAX_CONTROLLERS` (8);
`xhci_poll_events()` services each in turn; `xhci_get_dev()` → `xhci_dev_count()` /
`xhci_dev_at(i)`; `xhci_find_and_map(dev, index)` finds the index-th controller (1 when there is
none). Everything per device was already per controller (`msc_slots`, the rings, the connect
state machine, the BOT state).
- `kernel_main.c`: brings up controller 0, 1, ... until there is none; one that fails is skipped.
- `repl.c` and `blkio_usb.c`: their per-slot arrays were indexed by slot ID alone -- but a slot ID is
a controller's own, so slot 1 on two controllers would have been one entry. Now one set per
controller (`g_usb_ctrl[]`; `blkio_usb.c` finds its set by the controller's pointer); the attach
acknowledgement looks the device up across all of them.
- `usb_kbd.c`: one "previous report" and one "lights sent" for every keyboard would have diffed two
keyboards against each other. Both are each keyboard's own now (in its slot); a keyboard that
goes releases whatever it still held (no Shift stuck down after unplugging).
**Verified.** Test first: amd64, no PS/2, Zuse's drive on the usual controller, a second (NEC,
behind a root port) with the USB keyboard and identity `00` -- before, only Zuse attached
(`logs/20261014-140826`); after, the keyboard types (`3`, `3`, `AB`), `00` attaches, Zuse is confirmed
(`-141442`) -- both controllers with a device in slot 1, the collision case. Four identities
hot-plugged onto the second controller all attach, and unplugging one detaches that one
(`-141621`). aarch64 and riscv64, the same two-controller boot: all the same results (`-141756`,
`-141953`). Standard acceptance, all three: POST 1052, hash unchanged (`-142120`, `-142237`,
`-142449`); five identities hot-plugged on the first controller, all attached (`-142606`).
## XLIII. Both systems on every board image, chosen at boot (`boards/BRINGUP.md` A6) (2026-10-14)
Captain Bob, 2026-10-13, ruled the boards carry "both, switchable"; asked 2026-10-14 where the
switch is: **at boot, one image** -- a word in the boot configuration, v3 as built.
**Built.**
- `STARFORTH_V4=1` already compiled the v4 engine in; `kernel_main` then ran v4 unconditionally.
Now it runs v4 only if the boot arguments say `system=v4`, or say nothing and the build's
default is v4 (`SK_V4_DEFAULT`, from `kernel/Makefile`'s `V4_DEFAULT`: 1 for a plain
`STARFORTH_V4=1` build, as before, so every v4 QEMU boot and test is unchanged). Otherwise v3,
which is compiled in alongside, runs. A kernel without v4 asked for it says so and runs v3. The
boot prints the choice and why: "System: StarForth v4 (system=v4)", "... (this build's
default)", ...
- `cmdline.c`: `system=v3` / `system=v4` (also `--system=`), a later one winning; anything else is
ignored, as every unknown argument is.
- `make boot_image`: `STARFORTH_V4=1 V4_DEFAULT=0` -- both systems, v3 unless asked -- and the
boot arguments file always written, `system=v3` first: `starforth.cfg` on the ESP (SER5, Mars),
`cmdline.txt` on the Pi 5's card (the firmware hands it over as the devicetree's `bootargs`).
- `make boot_image` also cleans its ISA's kernel objects first: they are shared with `make qemu`
and make does not see changed compile flags. Found doing it: the clean was handed the root's
`TARGET=SER5` and removed `build/amd64/SER5`, nothing -- the first SER5 image carried the v4
engine but a `kernel_main` compiled without it. Now `TARGET=kernel`; all three images checked to
carry both.
**Verified.** Board-style build (both, v3 default), each ISA: no argument -- v3, POST 1052, hash
unchanged; `system=v4` -- v4, `PARITY:V4_POST tests=538 pass=538`, `dict_hash=0xe5a57f3eb72ff94a`
(amd64 `logs/20261014-144027`, `-144141`; aarch64 `-144411`, `-144604`; riscv64 `-144934`,
`-145108`). A plain `STARFORTH_V4=1` build still boots v4 by default (`-145331`); a v3-only kernel
asked for v4 says so and runs v3 (`-145550`). The SER5 image itself, booted from its own disk under
OVMF (`logs/20261014-ser5-image/`): v3 as built; after changing the one word in `starforth.cfg` on
it, v4. The Pi 5 and Mars images: built, their `cmdline.txt` / `starforth.cfg` read back from the
image, both systems found in their kernels; not booted (no QEMU model for either). Standard
acceptance, all three ISAs: unchanged (`-150651`, `-150801`, `-151007`).
**XLIII, revised the same day -- v4 is the default build.** Captain Bob, 2026-10-14: "v4 is the
default build", then "no, qemu to v4 too ... we are effectively trying to retire v3". Every kernel
build now carries v4 and v3 and boots **v4**: `STARFORTH_V4` defaults on (Kconfig `default y`),
`V4_DEFAULT=1` everywhere, and the board images write `system=v4` into `starforth.cfg` /
`cmdline.txt`. `system=v3` is the one word that boots v3; `STARFORTH_V4=0` builds v3 alone. The
acceptance rule (`.claude/CLAUDE.md`) became: the three ISAs as built (v4), and the 32-bit build,
`make -C v4 test-32` ("the 32 bit build needs to go into the acceptance test too"). v3 is not part
of it ("i don't care about v3"); it stays in the tree, `system=v3` still boots it. Verified: the three images rebuilt with `system=v4` in their boot files; the
SER5 image under OVMF as built boots v4, and after changing the word, v3 (`logs/20261014-ser5-image/`).
+1 -1
View File
@@ -100,7 +100,7 @@
\part{Security and ACL Recipes} \part{Security and ACL Recipes}
\chapter{Word-Level ACL Basics} \chapter{Word-Level ACL Basics}
%% SOURCE: docs/working/architecture/03-architecture/word-acl/DESIGN.md %% SOURCE: docs/reference/word-acl/DESIGN.md
%% TODO(bob): promote ACL recipe: loading ACL.4th, granting/revoking modes, %% TODO(bob): promote ACL recipe: loading ACL.4th, granting/revoking modes,
%% TTL-based expiry. Do NOT draft independent claim language. %% TTL-based expiry. Do NOT draft independent claim language.
\input{../scraps/architecture/03-architecture/word-acl/DESIGN} \input{../scraps/architecture/03-architecture/word-acl/DESIGN}
+4 -4
View File
@@ -48,7 +48,7 @@
\part{$2^7$ Factorial Campaign} \part{$2^7$ Factorial Campaign}
\chapter{Campaign Design} \chapter{Campaign Design}
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/guide.md %% SOURCE: docs/working/archive/superseded/factorial-doe/guide.md
%% docs/working/experiments/campaigns/doe_2x7/README.md %% docs/working/experiments/campaigns/doe_2x7/README.md
\input{../scraps/experiments/02-experiments/factorial-doe/guide} \input{../scraps/experiments/02-experiments/factorial-doe/guide}
\input{../scraps/experiments/02-experiments/factorial-doe/workflow} \input{../scraps/experiments/02-experiments/factorial-doe/workflow}
@@ -57,7 +57,7 @@
\input{../scraps/experiments/campaigns/shape_validation/README} \input{../scraps/experiments/campaigns/shape_validation/README}
\chapter{Incompatible Configurations} \chapter{Incompatible Configurations}
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/incompatible-configs.md %% SOURCE: docs/working/archive/superseded/factorial-doe/incompatible-configs.md
\input{../scraps/experiments/02-experiments/factorial-doe/incompatible-configs} \input{../scraps/experiments/02-experiments/factorial-doe/incompatible-configs}
\chapter{Campaign Results — 90 Runs} \chapter{Campaign Results — 90 Runs}
@@ -146,8 +146,8 @@
\part{Supplementary Campaigns} \part{Supplementary Campaigns}
\chapter{Heartbeat DoE} \chapter{Heartbeat DoE}
%% SOURCE: docs/working/experiments/02-experiments/heartbeat-doe/design.md %% SOURCE: docs/working/archive/superseded/heartbeat-doe-design.md
%% docs/working/experiments/02-experiments/heartbeat-doe/corrected-design.md %% docs/working/archive/superseded/heartbeat-doe-corrected-design.md
\input{../scraps/experiments/02-experiments/heartbeat-doe/design} \input{../scraps/experiments/02-experiments/heartbeat-doe/design}
\input{../scraps/experiments/02-experiments/heartbeat-doe/corrected-design} \input{../scraps/experiments/02-experiments/heartbeat-doe/corrected-design}
\input{../scraps/experiments/02-experiments/heartbeat-doe/implementation-summary} \input{../scraps/experiments/02-experiments/heartbeat-doe/implementation-summary}
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/adaptive-systems/loop-5-sketch %% SCRAP: architecture/03-architecture/adaptive-systems/loop-5-sketch
%% SOURCE: docs/working/architecture/03-architecture/adaptive-systems/loop-5-sketch.md %% SOURCE: docs/working/archive/superseded/loop-5-sketch.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-physics %% FITS: dev-guide/ch-physics
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/README %% SCRAP: architecture/03-architecture/hal/README
%% SOURCE: docs/working/architecture/03-architecture/hal/README.md %% SOURCE: docs/working/archive/dead/hal-target-contract/README.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/interfaces %% SCRAP: architecture/03-architecture/hal/interfaces
%% SOURCE: docs/working/architecture/03-architecture/hal/interfaces.md %% SOURCE: docs/working/archive/dead/hal-target-contract/interfaces.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/migration-plan %% SCRAP: architecture/03-architecture/hal/migration-plan
%% SOURCE: docs/working/architecture/03-architecture/hal/migration-plan.md %% SOURCE: docs/working/archive/dead/hal-target-contract/migration-plan.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/overview %% SCRAP: architecture/03-architecture/hal/overview
%% SOURCE: docs/working/architecture/03-architecture/hal/overview.md %% SOURCE: docs/working/archive/dead/hal-target-contract/overview.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/platform-implementations %% SCRAP: architecture/03-architecture/hal/platform-implementations
%% SOURCE: docs/working/architecture/03-architecture/hal/platform-implementations.md %% SOURCE: docs/working/archive/dead/hal-target-contract/platform-implementations.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/hal/starkernel-integration %% SCRAP: architecture/03-architecture/hal/starkernel-integration
%% SOURCE: docs/working/architecture/03-architecture/hal/starkernel-integration.md %% SOURCE: docs/working/archive/dead/hal-target-contract/starkernel-integration.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-platform %% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/heartbeat-system/implementation-plan %% SCRAP: architecture/03-architecture/heartbeat-system/implementation-plan
%% SOURCE: docs/working/architecture/03-architecture/heartbeat-system/implementation-plan.md %% SOURCE: docs/working/archive/superseded/heartbeat-rate-logging-plan.md
%% STATUS: HISTORICAL %% STATUS: HISTORICAL
%% FITS: dev-guide/ch-heartbeat %% FITS: dev-guide/ch-heartbeat
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/physics-engine/feedback-loops-analysis %% SCRAP: architecture/03-architecture/physics-engine/feedback-loops-analysis
%% SOURCE: docs/working/architecture/03-architecture/physics-engine/feedback-loops-analysis.md %% SOURCE: docs/working/archive/superseded/feedback-loops-analysis.md
%% STATUS: HISTORICAL %% STATUS: HISTORICAL
%% FITS: dev-guide/ch-physics %% FITS: dev-guide/ch-physics
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/physics-engine/metrics-and-knobs %% SCRAP: architecture/03-architecture/physics-engine/metrics-and-knobs
%% SOURCE: docs/working/architecture/03-architecture/physics-engine/metrics-and-knobs.md %% SOURCE: docs/working/archive/dead/metrics-and-knobs.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-physics, cookbook/ch-physics %% FITS: dev-guide/ch-physics, cookbook/ch-physics
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/physics-engine/steady-state-machine %% SCRAP: architecture/03-architecture/physics-engine/steady-state-machine
%% SOURCE: docs/working/architecture/03-architecture/physics-engine/steady-state-machine.md %% SOURCE: docs/working/archive/superseded/steady-state-machine.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: dev-guide/ch-physics %% FITS: dev-guide/ch-physics
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/03-architecture/word-acl/DESIGN %% SCRAP: architecture/03-architecture/word-acl/DESIGN
%% SOURCE: docs/working/architecture/03-architecture/word-acl/DESIGN.md %% SOURCE: docs/reference/word-acl/DESIGN.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: dev-guide/ch-acl, cookbook/ch-acl %% FITS: dev-guide/ch-acl, cookbook/ch-acl
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: architecture/getting-started/quick-start/factorial-doe %% SCRAP: architecture/getting-started/quick-start/factorial-doe
%% SOURCE: docs/working/architecture/getting-started/quick-start/factorial-doe.md %% SOURCE: docs/working/archive/superseded/factorial-doe/quick-start.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: cookbook/ch-doe %% FITS: cookbook/ch-doe
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -36,7 +36,7 @@ The audit assigned priority as follows.
\begin{itemize} \begin{itemize}
\item Add missing \texttt{README} files to all numbered directories. \item Add missing \texttt{README} files to all numbered directories.
\item Update \texttt{CLAUDE.md} to reflect HAL and StarKernel vision. \item Update \texttt{CLAUDE.md} to reflect HAL and StarKernel vision.
\item Create \texttt{docs/03-architecture/README.md} as a system overview. \item Create \texttt{docs/working/archive/superseded/2026-08-tripod/03-architecture-README.md} as a system overview.
\end{itemize} \end{itemize}
\textbf{Medium priority:} \textbf{Medium priority:}
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/L8_WIRING_PLAN %% SCRAP: experiments/02-experiments/L8_WIRING_PLAN
%% SOURCE: docs/working/experiments/02-experiments/L8_WIRING_PLAN.md %% SOURCE: docs/working/archive/superseded/L8_WIRING_PLAN.md
%% STATUS: HISTORICAL %% STATUS: HISTORICAL
%% FITS: experiments/ch-l8 %% FITS: experiments/ch-l8
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/factorial-doe/guide %% SCRAP: experiments/02-experiments/factorial-doe/guide
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/guide.md %% SOURCE: docs/working/archive/superseded/factorial-doe/guide.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: experiments/ch-factorial, cookbook/ch-doe %% FITS: experiments/ch-factorial, cookbook/ch-doe
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/factorial-doe/incompatible-configs %% SCRAP: experiments/02-experiments/factorial-doe/incompatible-configs
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/incompatible-configs.md %% SOURCE: docs/working/archive/superseded/factorial-doe/incompatible-configs.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: experiments/ch-factorial %% FITS: experiments/ch-factorial
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/factorial-doe/index %% SCRAP: experiments/02-experiments/factorial-doe/index
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/index.md %% SOURCE: docs/working/archive/superseded/factorial-doe/index.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: experiments/ch-factorial %% FITS: experiments/ch-factorial
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/factorial-doe/workflow %% SCRAP: experiments/02-experiments/factorial-doe/workflow
%% SOURCE: docs/working/experiments/02-experiments/factorial-doe/workflow.md %% SOURCE: docs/working/archive/superseded/factorial-doe/workflow.md
%% STATUS: CURRENT %% STATUS: CURRENT
%% FITS: experiments/ch-factorial, cookbook/ch-doe %% FITS: experiments/ch-factorial, cookbook/ch-doe
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/heartbeat-doe/corrected-design %% SCRAP: experiments/02-experiments/heartbeat-doe/corrected-design
%% SOURCE: docs/working/experiments/02-experiments/heartbeat-doe/corrected-design.md %% SOURCE: docs/working/archive/superseded/heartbeat-doe-corrected-design.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: experiments/ch-heartbeat %% FITS: experiments/ch-heartbeat
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: experiments/02-experiments/heartbeat-doe/design %% SCRAP: experiments/02-experiments/heartbeat-doe/design
%% SOURCE: docs/working/experiments/02-experiments/heartbeat-doe/design.md %% SOURCE: docs/working/archive/superseded/heartbeat-doe-design.md
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: experiments/ch-heartbeat %% FITS: experiments/ch-heartbeat
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice
@@ -1,5 +1,5 @@
%% SCRAP: hardware/platform-integration/L4RE_DICTIONARY_ALLOCATION %% SCRAP: hardware/platform-integration/L4RE_DICTIONARY_ALLOCATION
%% SOURCE: docs/working/hardware/platform-integration/L4RE_DICTIONARY_ALLOCATION.adoc %% SOURCE: docs/working/archive/dead/l4re/L4RE_DICTIONARY_ALLOCATION.adoc
%% STATUS: WORKING %% STATUS: WORKING
%% FITS: dev-guide/ch-l4re %% FITS: dev-guide/ch-l4re
%% EDITORIAL: lifted — prose rewritten to press voice %% EDITORIAL: lifted — prose rewritten to press voice

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