Files
LithosAnanake/v4/README.md
T
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

161 lines
8.2 KiB
Markdown

# v4/
StarForth v4: the 32-instruction F18-derived core. The design lives in
`docs/v4.0.0/JUSTIFICATION.md` (why) and `docs/v4.0.0/DECOMPOSITION.md`
(every v3 word mapped to a v4 fate).
The first deliverable is the hosted C99 golden model (`JUSTIFICATION.md` §10,
step 1). It must pass POST and hold K≡1.0 with 32- and 64-bit cells on all
three host ISAs.
Acceptance (`JUSTIFICATION.md` §16): v4 must be equivalent to v3 at any point
in time, with the same vocabularies and behaviour, on the F18-derived engine;
and every ISA, hosted and bare metal, must still reach its `ok` prompt.
`make -C v4 test` passing is a development check, not acceptance.
What exists so far is the single node: registers, circular stacks, memory, all
32 opcodes, per-opcode and per-call-target heat, and three console
registers (`CONSOLE-TX`, which captures output, and `CONSOLE-RX` and `CONSOLE-STATUS`, which hand out
input a test feeds) standing in for the console node until the mesh exists. The tests load definitions
onto a node either opcode by opcode (`v4/include/v4/asm.h`) or as text in the notation `DECOMPOSITION.md`
uses (`v4/include/v4/text.h`). `make -C v4 test` builds
and runs the tests at both cell widths; `make -C v4 sanitize` repeats them
under ASan and UBSan. There is no POST and no K measurement yet.
## The system: nucleus, capsules, prompt
`docs/v4.0.0/NUCLEUS.md` is the design. A v4 system is four things:
| Part | Where | What it is |
|---|---|---|
| Engine | `v4/src` | The golden model of the 32-opcode node |
| Nucleus | `v4/capsule/*.v4`, built by `v4/tools/mkimage.c` into `capsules/v4/nucleus-64.f18` | The assembled words, as a capsule of F18 code: sent through its port to a node born empty |
| Capsules | `capsules/v4/*.4th`, baked by `tools/mkcapsule.c` | FORTH source, loaded when the system comes up |
| Boot | `v4/system/boot.c` | Starts the nucleus, checks and loads each capsule, prints the parity lines, gives the prompt |
Two products link the same four and differ only in the console:
- **Hosted Linux**, `v4/tools/hosted.c`: `make -C v4 hosted` builds
`v4/build/starforth4-amd64`, `-aarch64` and `-riscv64`, static, 64-bit cells.
- **Bare metal**, `kernel/src/v4/sk_v4.c`: `make -f kernel/Makefile ARCH=<arch> STARFORTH_V4=1`.
A boot prints:
```
PARITY:V4_NUCLEUS words=292 image_hash=0x...
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
PARITY:OK
ok>
```
Every build of one commit prints the same hashes. `make -C v4 hosted-check`
boots the three hosted binaries (the two foreign ones under user-mode QEMU)
and fails unless their output is identical and ends in `PARITY:OK`.
A capsule line the node does not answer ` ok` to ends the boot, naming the
capsule, block and line, with `PARITY:FAIL` and `POST: FAILED`.
State, 2026-10-05, after `ENGINE.md` step 1: all six builds start the nucleus,
load `v4:forth79.4th`, pass POST and reach `ok>`, with the same lines:
```
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=... capsule_hash=0x97a655081b2af559 words=298
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=... dict_hash=...
PARITY:V4_POST tests=550 pass=550 fail=0
PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=... dict_hash=...
PARITY:OK
POST: PASSED
ok>
```
Bare-metal logs: `logs/20261006-110551/amd64/`, `logs/20261006-111621/aarch64/`,
`logs/20261006-111341/riscv64/`. On each, seven lines were then typed at the
prompt through the serial port — a definition, its use with the capsule's
`U*`, `COLD`, the capsule word again, a `FORGET` of it (refused), a kernel
word no one serves, and `BYE` — and each was answered as the hosted binary
answers it. The
capsules were unsigned (no signing key on this machine).
**A node is sent text as a message** (`docs/v4.0.0/MESH.md` section 6). It
does not read its own command line, prints no prompt and has no console of
its own. With nothing to do it is blocked reading its ports. A neighbour
writes it a message; text for it is interpreted; what it prints goes back
as messages to the sender, and then a message saying how the text ended.
Its console says ` ok` or ` ERROR` and prompts, as the kernel's REPL does
for a v3 VM. A message carries 1024 characters, a block. `v4/src/message.c`
is the format for a host; `v4_boot_line` (`v4/system/boot.c`) is the
console both products and the capsule loader use.
**A node asks its kernel by writing to its port** (`ENGINE.md` 3.3). The
write blocks the node until it has been served. A kernel word is a
dictionary entry made by `n KERNEL-WORD name`, whose body writes `n` to the
port; its arguments and results are on the data stack. `BYE` is the one
kernel word so far. A node can be stopped between any two instruction
words and is blocked while it waits at its port, which is what a system of
many users and tasks, preemptive and cooperative, needs of it
(`ENGINE.md` 3a).
**The two products have parted** (`ENGINE.md` 3c). They share the engine,
the FORTH-79 capsule and its POST; their nuclei may differ. The hosted
product is its own and may become a hosted SDK. The bare-metal product is
to be LithosAnanke with the node in the StarForth VM's place, and
everything about word records, the fleet and identity is its alone.
**Nodes that talk** (`docs/v4.0.0/MESH.md`) are the next step, ahead of
making v4 equal v3 on bare metal. Its first part is built and tested in
the engine: a node has `V4_PORTS` ports; a read from one blocks until the
neighbour writes and a write until the neighbour reads; a node is born
empty with `P` at its ports and executes what a neighbour sends it, which
is how each product's node now gets its nucleus, as a capsule; and
the fabric (`v4/src/fabric.c`) is the nodes there are and the table of how
their ports are wired, both of which change while they run. The products
below are still one node each; they become the five nodes at `MESH.md`
steps 8 and 9.
**Finding the way** (`MESH.md` step 4) is built: a node has a table of
which port leads toward which node (`ROUTE`, `DEFAULT-ROUTE`, `NO-ROUTES`),
passes on a message that is not for it, and `SEND`s text to another node;
`v4/tests/test_host_mesh.c` runs three StarForth nodes in a row. **It has
a fault that stands:** two neighbours that write to each other at the same
moment wait for ever, because a write blocks until the neighbour reads and
a node that is writing is not reading. The test shows it, named KNOWN
FAULT. The ways out are in `MESH.md` section 7a and none is chosen yet.
**This is still the lone node.** On bare metal `kernel_main.c` starts it
before the fleet tables, beside the kernel's own system and not in the VM's
place. `ENGINE.md` sets out the steps from here; step 1 is done and step 2 is
part done. `V3-PARITY.md` records the rulings it is built from.
**What this does not yet show.** `forth79.4th` holds two definitions, `U*`
and `U/MOD`. Every other word is still in the assembled nucleus, so POST is
so far a test of the assembled words. Moving them to the capsule, a group at
a time with POST after each, is the next step (`NUCLEUS.md` section 8).
## POST
`capsules/v4/post79.4th`: 550 cases in blocks 7000 up, covering 126 of the
130 words of the FORTH-79 Required Word Set. 443 are v3's cases with what
the hosted v3 binary did as the expected result. The other 107, and the 27
v3 cases left out, are listed with reasons in `docs/v4.0.0/POST79.md`.
- `make -C v4 post` boots the amd64 system: the quick check after a change.
- `make -C v4 hosted-check` boots all three hosted ISAs and compares them.
- `make -C v4 post79` writes the capsule again (`tools/mkpost.py`,
`tools/post79_rules.py`); it needs the hosted v3 binary.
POST is FORTH: a harness of FORTH-79 words and two nucleus hooks, `(CATCH)`
and `(EMIT-HOOK)`. It forgets itself when it has finished. The boot passes
only on seeing POST's tally line with `fail=0` (`v4/system/boot.c`). A colon
definition broken on purpose (`U/MOD` without its last `SWAP`) fails five
cases and the boot stops with `POST: FAILED`.
Not tested: `KEY`, `EXPECT`, `QUERY` (the keyboard) and `QUIT` (it returns
without ` ok`).
Open: `PAD 42 OVER !` faults on v4, because `PAD` is a byte address and `!`
takes a cell address (D-1). FORTH-79 expects it to work. The v3 case for it
is left out until that is ruled.
The Required Word Set list in `tools/mkpost.py` was written from memory of
the standard and has not been checked against the document.