Files
LithosAnanake/docs/v4.0.0/ENGINE.md
T
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

11 KiB

StarForth v4.0.0 — The F18 engine in the VM's place

Design, 2026-10-05. Written from Captain Bob's rulings of that day (V3-PARITY.md sections 1a to 1h, where each is recorded with its words) and from v3's code. It replaces the lone-node assumptions of NUCLEUS.md sections 5.3 and 7 to 9.

1. The principle

JUSTIFICATION.md section 16: v4 is equivalent to v3 at any point in time; "the only difference is the machine underneath: the F18-derived engine instead of the original StarForth VM."

Ruled 2026-10-05: v4 is exactly like v3 in functional requirements up to the first FORTH prompt, and that is the stopping point for now. Nothing is stubbed, simulated or stood in for.

So v4 is not a new system beside LithosAnanke. It is LithosAnanke with a different machine executing its FORTH.

2. What stays, and what is replaced

Stays, untouched: everything the kernel does. The Stadium and each patron's own accounts; sessions; the switcher; kernel-Hermes; the capsule directory, birth protocol, hashing, signing and parity; the block subsystem and its devices; identity and Zuse; the HAL console, Hestia, the console proxies and the kernel's REPL; the heartbeat; the boot order in kernel_main.c.

Replaced: the part of a v3 VM that executes FORTH.

v3 v4
The inner interpreter (v3/src/vm.c, kernel/src/vm/vm_core.c) The node: v4/src, 32 opcodes
The dictionary as a list of C DictEntry records The dictionary in the node's memory (v4/capsule/dict.v4)
The FORTH-79 words as C functions (v3/src/word_source) The assembled nucleus (v4/capsule/*.v4) and colon definitions in capsules/v4/forth79.4th
The outer interpreter and compiler in C The same, in the nucleus

A v3 VM is also a record the kernel keeps: its identity, its Stadium ID, its heartbeat state, its place in the registry, its Zuse flags. That record stays. What changes is what stands behind it.

3. The interface

The kernel reaches a VM through a small number of things. Each is listed with what v3 has, what was ruled, and what a node needs. This is the whole of the work: when a node answers all of these, the kernel's boot runs on it as it runs on a v3 VM.

3.1 Interpret this text

v3: vm_interpret(vm, text). The kernel's REPL hands over each line it has read; capsule_exec_payload hands over each line of a capsule; kernel-Hermes hands over a message's payload when the target drains its queue. The VM runs the text and returns, with its error flag set or not.

Ruled: the kernel hands a node a whole line and takes characters back; the node's own prompt loop plays no part at that level. A node receives a message by being handed its text.

v4: the node has an entry that interprets the text in its input buffer and then stops, saying how the line ended: completed, ended in an error, or QUIT. It prints no prompt and no ok. The buffer takes 1024 characters, a block, as v3's does. QUIT and ABORT end the line and return to whoever handed it over. KEY, EXPECT and QUERY stay FORTH-79 words that read characters.

With this one entry v3's capsule loader, REPL and message drain can all drive a node, and v4/system/boot.c's own loader is not needed.

3.2 A character out

v3: the host service putc, then console_putc; the fabric adds [user@VM].

v4: the node's EMIT gives the character to its host, which calls the same service. Present today.

3.3 Asking the kernel

v3: a kernel word is a C function registered in the VM's dictionary: BIRTH, KILL, USE, the block words, the Stadium and Hermes words, the framebuffer words. It takes its arguments from the VM's data stack.

Ruled: a node asks for a block by number and the kernel decides the rest; a node sends a message by asking.

v4, ruled 2026-10-05: a kernel word is an ordinary dictionary entry on the node whose body writes its request number to the node's port. The write blocks the node until the kernel, its neighbour on that port, has served it (DECOMPOSITION.md section 6: "a write blocks until the neighbour reads"). The kernel serves between the node's opcodes, so the node is always stopped when C touches it; the function takes its arguments from the node's data stack and leaves its results there. Kernel words are made by handing the node text at boot. The C functions are v3's.

3.4 The stacks and the dictionary, from the kernel's side

v3: vm_push, vm_pop, vm_find_word, and the fields of a DictEntry (the kernel pins BIRTH and CAPSULE-BIRTH by setting two of them).

v4: the same operations on the node's stacks and on entries in the node's memory.

3.5 A word is being executed

v3: the inner loop, for every word: the ACL's countdown and recheck, execution_heat, stadium_word_dispatch, the rolling window, pipelining.

Ruled: the word card stays exactly as v3 — a run-time check, the TTL adaptive from the word's own count. Every kind of patron keeps its own accounts; the word's are as v3. Opcodes are counted and left unwired.

v4: the node dispatches a word at the call opcode, one place in the engine. The node does there what v3's loop does. A word that is to be checked must be called, so the in-line words that can be called become calls.

3.6 An error

v3: vm->error. v4: how a line ended (3.1), and the node's error register for a C function to raise one.

3.7 A tick

v3: the kernel's timer drives vm_tick and the heartbeat state in the VM's record. v4: unchanged; that state is the record's, not the engine's.

3.8 The dictionary hash

v3: vm_dict_hash_fn, a hook the birth protocol calls. v4: the same hook, answered from the node's dictionary.

3a. Many VMs at once (Captain Bob, 2026-10-05)

Do not forget that this is multiuser, multitasking, and a hybrid of preemptive and cooperative.

And, the same day: "Hera will be the process manager via compudynamics per node."

What that asks of the engine, and what it has:

  • A node can be stopped between any two instruction words and gone on with later. Everything a node is doing is in the node and its execution state; v4_exec_step_word runs one instruction word and returns. So whoever runs the nodes can take the processor from one at any word and give it to another: that is the preemptive half, and the engine already allows it. Nothing may be built that needs a node to run a line, or a request, to its end without interruption.
  • A node gives way by itself when it writes to its port. It is blocked until served (3.3), and while it is blocked another can run: that is the cooperative half.
  • Each node has its own execution state. The place a blocked node goes on from is kept per node (v4_exec_state), never in one shared place.
  • Each user is a VM (FABRIC-2.md D.2: "a session IS a VM"), so each is a node, with its own dictionary, stacks and ACL cards.

What is not designed: who decides which node runs next, and when. In v3 that is the switcher, reading what kernel-Hermes publishes, at the checkpoint in the inner loop; the ruling makes it Hera's, by compudynamics. It is step 6's, and section 6 lists it as open.

The loop that runs one node until its line ends (v4_boot_line, v4/system/boot.c) is the lone node's and the hosted program's, where there is one node and nothing to share the processor with. It is not how the kernel will run a fleet, and goes with the lone node at step 4.

4. What was built on the detour

Built 2026-10-05 What becomes of it
kernel_main.c calling sk_v4_run() before the fleet tables Goes at step 4. Until then it is how the bare-metal build is kept booting while the interface is built.
v4/system/boot.c: its own capsule loader and PARITY:V4_* lines Goes at step 4, when v3's birth protocol loads the capsules and prints v3's parity lines.
The node's prompt loop, and the code that strips ok from its output Goes at step 1.
capsules/v4/forth79.4th, post79.4th, mkpost.py, the rules Stay. POST is the gate for every word moved out of the nucleus.
(CATCH), (EMIT-HOOK), NODE-ERROR by name Stay; POST uses them.
The per-call-target count (v4/src/heat.c, call[]) Goes at step 3, when the node does at call what v3 does.
The hosted Linux product Stays, on the same interface. Hosted v3 has no fleet and neither has hosted v4.

5. Steps

Each ends with all six builds booting and agreeing, and is committed with its logs.

  1. Interpret this text (3.1). The node's line entry; no prompt loop. The hosts print the prompt and ok, as v3's REPL does. Done 2026-10-05. (LINE), (IDLE), (DONE) and (LINE-STATUS) in v4/capsule/quit.v4; v4_line_* in v4/src/image.c; v4_boot_line in v4/system/boot.c. All v4 tests pass at both widths; the six builds agree; lines typed at the three bare-metal prompts are answered. logs/20261005-180922, -181152, -181541.
  2. Asking the kernel, and the stacks from the kernel's side (3.3, 3.4). Settle how a request is carried. Kernel words callable from a node. The carrier is done, 2026-10-05; the rest is not. Ruled: a node asks by a blocking write to a port. Built: the port (v4/src/node.c, v4_node_port_attach, v4_node_port_served); a blocked node goes on from the opcode after the store, in the same instruction word (v4/src/exec.c); KERNEL-WORD (v4/capsule/compile.v4), which makes a word whose body writes its request number to the port; the boot makes the kernel's words by handing the node text, and serves requests (v4/system/boot.c). A request no one serves is error 12 on the node. The one kernel word so far is BYE, on both products: hosted it leaves the program, as hosted v3; on the lone node it is v3's cold restart. v4/tests/test_port.c; six builds agree; BYE and an unserved request typed at each bare-metal prompt. logs/20261005-185506, -185734, -190101. Not done: v3's own C functions serving a node. They take a VM * and use vm_push, vm_pop and, in places, the stack's fields directly; a node has to stand behind that VM record first.
  3. A word is being executed (3.5). The hook at call; the ACL's countdown and recheck; the word's count; stadium_word_dispatch. In-line words become calls. The per-call-target count goes.
  4. In place. Under STARFORTH_V4 the kernel's own boot brings the node up where it brings a v3 VM up, after the fleet tables; the kernel's REPL drives it; blocks come from the block subsystem. sk_v4_run() and boot.c go.
  5. Hera as v3 has her. init.4th runs on the node; v3's whole POST; v3's parity lines.
  6. The fleet. Hestia and Artemis; message delivery; the switcher.
  7. Identity and the prompt. Zuse; [zuse@Hera] ok>.

Moving words from the assembled nucleus to forth79.4th goes on beside these, a group at a time, with POST after each.

6. Open, and where each must be settled

Open Before
How the node tells a dictionary entry from a bare address at call Step 3
EXECUTE, which enters a word by a return Step 3
>R R> R@ I J LEAVE, which cannot be called Step 3
Who decides which node runs next, and when: Hera, by compudynamics; preemptive and cooperative Step 6
The node's safe moment for message delivery and switching Step 6
PAD 42 OVER !, a byte address given to ! (D-1) Step 5
Which word patrons' accounts the hosted product keeps, having no Stadium Step 3