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

20 KiB
Raw Blame History

StarForth v4.0.0 — Parity with v3 up to the first prompt

Started 2026-10-05. This file measures v4 against one ruling:

v4 is exactly like v3 in functional requirements up to the first FORTH prompt. That is the stopping point for now. (Captain Bob, 2026-10-05)

and a second, given the same day:

I would never stub, simulate or develop outside of functional, as-intended code. Piecemeal is how errors and intent get hidden.

It records what v3 does, where in v3's code, what v4 does today, and what has to be ruled before v4 can do the same. It proposes; it decides nothing. Nothing described here as missing has been built.

1. What v3 does before its first prompt

From the bare-metal boot log logs/20261003-100613/amd64/, in order, after the kernel's M0–M6 hardware milestones:

# v3 v4 today
1 Stadium allocated (cells, 50 VM slots); switch-signal and kernel-Hermes channel tables Missing
2 VM arena; 530 words registered One node; 295 assembled words and 2 from the capsule
3 Physics live whenever a word executes: per-word heat, decay, rolling window, pipelining, L8 mode selector (61 mode changes during POST), heartbeat Missing; see section 2
4 POST: 1050 tests, every module (FORTH-79, StarForth extensions, ACL, Mama, Q48, inference, physics freeze) 550 cases, FORTH-79 Required Word Set only
5 PARITY:M7.1a word count, here, latest, dictionary hash; PARITY:OK; POST: PASSED Present, as PARITY:V4_*
6 PCI; virtio-blk attached; Artemis genesis signature Missing. Blocks are a RAM array
7 Mama init capsule init.4th: signature checked, executed, PARITY:MAMA_INIT v4 loads its own two capsules the same way; not init.4th
8 ACL: BIRTH and CAPSULE-BIRTH pinned strict Missing. The ACL words are assembled but not loaded
9 Heartbeat running; Stadium conservation checks; quota and kernel-Hermes self-tests Missing
10 Hestia born, then Artemis (disk formatted, self-test, K figures), each with PARITY:BIRTH Missing. One node, no fleet
11 Kernel-Hermes fleet self-tests; USB mass storage; Zuse genesis minted on the thumbdrive Missing
12 Banner with versions; [zuse@Hera] ok> ok> alone

Rows 1, 6, 9, 10 and 11 are messaging, blocks and the console's wider setting. They are to be discussed before anything is written about them. Section 2 is row 3.

1a. Correction (2026-10-05): the table above is wrong about "Missing"

Captain Bob: "You haven't looked at the codebase. You're assuming missing pieces that are not missing and ignoring the entire v3 architecture. Don't look at pieces until you see how they fit."

The table was made from a boot log and a few functions. Read as a whole, the system is this.

How v3 fits together. After the hardware milestones, kernel_main.c (kernel_main_deep, from line 526) does, in order:

  1. Fleet tables, before any VM exists: Stadium, sessions, switch-signal, kernel-Hermes channels and queues; Hera made patron zero.
  2. sk_vm_bootstrap_parity() (kernel/src/vm/bootstrap/sk_vm_bootstrap.c): one VM is initialised with the kernel's host services; the capsule hooks and the VM registry are set up; its fleet physics is seeded (vm_physics_init); the kernel's own words are registered (BIRTH, KILL, the capsule words); the block subsystem is given to it; POST runs; parity is collected and printed.
  3. Devices: block RAM and ramdrive, PCI, entropy, Artemis's virtio disk and its signature, keyboard, USB, framebuffer.
  4. The capsule directory is copied and capsule_birth_mama() runs init.4th on that VM; BIRTH and CAPSULE-BIRTH are pinned.
  5. The timer starts: the heartbeat.
  6. Stadium and kernel-Hermes self-tests; Hestia and Artemis are born, each another VM; Zuse; the banner; the REPL.

Every one of those steps is kernel code in kernel/src and works on a VM through one interface: the VM structure (v3/include/vm.h) and the functions on it. Counted across the kernel's services, the most used are the stacks (vm_push, vm_pop), vm_interpret, vm_find_word, the dictionary (latest, here, DictEntry), error, the heartbeat state, the rolling window, and stadium_vm_id.

What v4 is, by its own justification (JUSTIFICATION.md section 16): "The only difference is the machine underneath: the F18-derived engine instead of the original StarForth VM." And section 15: StarshipOS is "LithosAnanke running the v4 F18 engine", with the FORTH-79 vocabulary and "the StarshipOS-specific portions" stored as capsules.

So nothing in rows 1, 6, 7, 8, 9, 10, 11 or 12 is missing. It is all in this kernel and it all runs today. What is wrong is where v4 was put: kernel_main.c calls sk_v4_run() before step 1 and it never returns. The v4 node comes up beside the system instead of inside it, and so the whole of the architecture is skipped. That is the detour. The capsule loader, POST and parity lines built on 2026-10-05 (v4/system/boot.c) repeat, for a lone node, things steps 2 and 4 already do for a VM.

The real question is therefore not "what does v4 lack" but "how does the F18 engine take the place of the StarForth VM behind that one interface", so that steps 1 to 6 run as they do now. That has not been worked out, and nothing here should be read as a plan for it.

Section 2 below was written before this correction. Its account of what v3's inner loop does is from the code and stands. Its section 2.2, "what v4 has", describes the lone node, not v4 in its place in the system.

1b. Console (discussed and ruled 2026-10-05)

v3, as built (FABRIC-3.5.md sections XVII and XVIII):

  • Layer 0, the fabric: UART, framebuffer, VT100, font, in kernel C (kernel/src/hal). Singular, permanent, and it never knows a VM exists; anything VM-shaped reaches it by a registered callback.
  • Layer 1, Hestia: the Tripod leg that owns console policy and is the bind point. Her vocabulary is the drawing words.
  • Layer 2, console proxies: one VM per attached user, born at WIREBIND; their traffic goes through kernel-Hermes.
  • Input belongs to the kernel. kernel/src/repl.c reads the serial port and the keyboard, echoes, edits and builds the line, then hands the whole line to the VM USE has made active (vm_interpret), or sends it through kernel-Hermes. It services the heartbeat while idle.
  • Output: a VM's EMIT goes to the host service putc, then console_putc. The fabric puts [user@VM] before each line. The prompt is the REPL's, not the VM's.

A v3 VM never reads its own command line and never prints its own prompt.

Ruling (Captain Bob, "for now, yeah"): the kernel hands a v4 node a whole line and takes characters back, exactly as it does a v3 VM. The node's own prompt loop plays no part at that level. Layers 0, 1 and 2 and the kernel's REPL stay as they are. KEY, EXPECT, QUERY and QUIT remain FORTH-79 words but are not how the kernel drives a node.

"For now": DECOMPOSITION.md makes EMIT and KEY messages to a console device node, which in the mesh is Hestia's part. That is the destination, not this step.

What this says about the lone-node boot. It has the node run its own QUIT loop, print its own prompt and ok, and wait in KEY; v4/system/boot.c then takes the ok and prompt back out of what the node prints. That is a work-around for the node owning what the kernel owns, and it goes when the engine takes the VM's place.

1c. The frame: the Stadium

FABRIC-2.md section B: "words are stadium patrons, VMs are patrons, blocks are patrons, messages are stadium patrons, all should be operated on by THE SAME ENGINE."

  • A patron is one 64-byte cell of nine wires: identity, heat, TTL, pin, link, behaviour, mass, payload, contains (kernel/include/starkernel/vm/stadium.h).
  • Heat is a conserved share of 1.0; K is that conservation.
  • The behaviour is what happens when a patron leaves: words and VMs COOL, blocks MIGRATE, messages DELIVER, ACLs EXPIRE.
  • A cell never holds the thing itself, only its identity and heat. A word's code stays in the dictionary; a block's bytes stay in the block subsystem.

Compudynamics is therefore the kernel's Stadium, not something inside the VM engine. The engine's part is to report what it executes: in v3, stadium_word_dispatch(vm, word_id, tick) from the inner loop.

Reading of the opcode ruling (section 2.7) in this frame, stated to Captain Bob 2026-10-05 and not corrected: on v4 that report carries an opcode, and a VM's word patrons become its 32 opcode patrons.

1d. Blocks (discussed and ruled 2026-10-05)

v3, as built:

  • One block address space in kernel C (v3/src/block_subsystem.c): fast RAM at 0 to 2047, the ramdrive, Artemis's virtio disk, USB drives, chained.
  • Every block has metadata (blk_meta_t): the owner's fingerprint, acl_allow, acl_ttl, a write count, chain links.
  • Blocks are patrons: BLOCK, BUFFER and UPDATE call stadium_block_dispatch with the LBN; heat drives migration and wear levelling (kernel/src/vm/stadium_blocks.c).
  • Artemis is the Tripod leg that owns persistent storage.
  • Identity lives there: a keypair Zuse mints onto a thumbdrive; its fingerprint is stamped on every block it claims at first touch, behind the home-blocks fence; the disk's genesis signature is how the kernel knows Artemis's disk.

A v3 VM's block words ask the kernel's block subsystem for a block and get a buffer back. Ownership, ACL, physics and devices are the kernel's.

Ruling (Captain Bob, "yes"): a v4 node only ever asks for a block by number. Everything about who may have it is decided on the kernel's side, under the VM's identity. The device chain, metadata, first-touch claim, ACL, migration and the Stadium touch stay where they are.

What this says about the lone-node boot. It gives the node a bare RAM array behind its four block registers (D-19), which skips the address space, the metadata, the owner, the ACL and the Stadium.

2. Row 3: physics and per-word heat

2.1 What v3 does

For every word a definition executes — the inner loop, kernel/src/vm/vm_core.c:757-880, and the same on the interpreter's path at :1053-1110:

  1. Decay (Loop #3). The word's heat is reduced by the ticks since it was last touched times the decay slope, in Q48.16 (physics_metadata_apply_linear_decay, v3/src/physics_metadata.c). Not for a frozen word, and not while L8 has gated Loop #3 off.
  2. Heat (Loop #1). The word's execution_heat is raised by one.
  3. Stadium. The word's ID, the VM's ID and the tick go to the Stadium's conserved heat wire (stadium_word_dispatch).
  4. Rolling window (Loop #2). The word's ID is recorded (rolling_window_record_execution).
  5. Pipelining (Loop #4). The transition from the previous word is recorded, the most likely next word is worked out, and a likely one is promoted to the hot-words cache.
  6. ACL. The word's TTL is counted down, or the word rechecked at zero; a denied word stops the definition.
  7. The word runs. Then its physics record is touched (temperature, time) and the heartbeat's count of words executed is raised.

On every heartbeat tick — kernel/src/vm/vm_runtime.c, driven by the timer interrupt: vm_tick; the window tuner (Loop #5, :158); the slope validator (Loop #6, :228); background decay (:355); the L8 mode update (:400), which turns loops on and off; the inference engine (:579); and a published snapshot.

What each word carries — DictEntry, v3/include/vm.h:342-358: execution_heat; a DictPhysics record (temperature, last decay tick, mass, state flags); a pointer to its transition metrics; a stable word_id; the four ACL fields; and the WORD_FROZEN and WORD_PINNED flags.

All of this is running before the first prompt. POST itself executes under it.

2.2 What v4 has

  • A v4 word is native code. Executing one is the call opcode going to its address. There is no inner loop, so there is no place in software where v3's seven steps could happen.
  • Short words are not called at all. DUP, +, @, >R and about fifty others are compiled in line as opcodes (header DUP inline, v4/capsule/forth.v4). At run time nothing says "this was DUP".
  • The engine counts three things as instructions retire (v4/src/exec.c): each opcode's count (32 counters), the anti-clock, and a count for each call target.
  • The call-target count is a stand-in, by its own account. It is a C array beside the node, 4096 entries, written 2026-10-02 (v4/src/heat.c). A call to an address of 4096 or above is silently not counted. The nucleus runs to about word 6300 and capsule definitions start at 8192, so some assembled words and every capsule word get nothing. No FORTH word can read it: ACL-HEAT@ returns 0 (v4/capsule/acl.v4:80).
  • A dictionary entry is three cells before the code — flags, name, link (v4/capsule/dict.v4). It has no heat, no physics record, no word ID.
  • There is no decay, rolling window, pipelining, inference, L8, heartbeat or Stadium wire on the node.

2.3 What the v4 design documents say

The documents ruled on 2026-10-01 do not say "as v3". They say:

  • JUSTIFICATION.md section 4, item 4: "Compudynamics as a side effect of execution. Heat counters, the anti-clock, and the heartbeat are driven by instruction retirement in hardware. They cost no instructions."
  • DECOMPOSITION.md section 1.4: "every call increments the heat counter of its target".
  • DECOMPOSITION.md section 7: registers HEAT-OP[0..31], HEAT-CALL[...], ANTICLOCK, HEARTBEAT, GOV-*.
  • DECOMPOSITION.md sections 5.19 and 5.23 use the words "heat table" for HEAT-CALL (ENTROPY@, FREEZE-WORD).
  • D-6, deferred: "Which heat structures exist in hardware: per-opcode counters only, or also per-call-target and word-to-word transition counters. … The golden model implements per-opcode and per-call-target heat in the meantime."
  • Section 5.22: the six PIPELINING-* words are retired, to return "if D-6 adds transition counters". Section 5.21: the hot-words cache words are retired as having no equivalent on a node.

So the 4096-entry array is the "in the meantime" of D-6, and "heat table" is these documents' own term.

2.4 The conflict

Today's ruling and those documents do not say the same thing, in three places. Each needs a ruling; none is mine to settle.

A. Where a word's heat is kept. v3: in the word's own dictionary entry. The documents: in the node, as a register indexed by call target.

B. What counts as a word. v3 counts every execution of DUP as DUP's. v4 compiles DUP in line; what is counted is the dup opcode, and a word built of several opcodes in line (2DUP is over over) leaves no count of its own. v3's per-word heat for these words cannot be had from a v4 node as it compiles now.

C. Which loops exist. v3 runs all seven and L8 before the prompt. The documents retire Loop #4 (pipelining) and the hot-words cache, and leave the rest to registers whose behaviour is not written down beyond their names.

2.5 What each answer would take

Offered so that the ruling can be made knowing its cost. Not a plan.

If heat is kept as v3 keeps it (A, v3's way). Each entry gains cells before its code, beside flags, name and link: heat, last-decay tick, word ID, and what of DictPhysics is kept. dict.v4's entry words, the header macro of the text assembler and every assembled header line account for them. The node, on call, finds the entry from the target address and does steps 1 to 5 of section 2.1. Heat is then ordinary memory: HEAT@ is a fetch, and it is inside the dictionary, so the dictionary hash either covers it or is defined to skip it, as v3's canonical hash skips it.

If heat is kept as the documents have it (A, the node's way). The call-target counts become part of the node, cover every address of it, and are readable through HEAT-CALL as a memory-mapped register, which needs D-4, the memory map, settled. This is not "as v3" in where heat lives; it is in what is counted.

B either way. Three ways, and they are not equivalent:

  1. In-line words are counted by opcode: DUP's heat is HEAT-OP[dup]. Words that are more than one opcode in line have no heat. Not as v3.
  2. Nothing is compiled in line except what must be (>R, R>, R@, I, J, LEAVE: a call would bury the return address). Every other word is called and so counted. As v3 for those words; slower, and the six that must stay in line are still uncounted.
  3. The compiler lays down a marker the node counts and does not execute. That is a new opcode or a new use of one, which is a change to the instruction set.

C. For each of Loops #2 to #7 and L8: where its state lives, what advances it, and what the heartbeat is on a node that has no timer of its own (v3's is the kernel's timer interrupt; the documents' is "in the fabric"). v3's code for each is the reference: rolling_window_of_truth.c, physics_pipelining_metrics.c, inference_engine.c, ssm_jacquard.c, vm_runtime.c.

2.6 What depends on this

  • Decomposition. Moving a word from assembler to a colon definition does not change how it is called, but it turns in-line opcodes into calls, which changes what is counted under every answer to B. It should wait for B.
  • ACL. v3's TTL comes from heat (ACL-TTL-COMPUTE). With ACL-HEAT@ returning 0 every word has the same TTL. Row 8 waits for A.
  • POST's other 500 cases (row 4) include the physics-freeze and inference modules, which test words that read and write heat.
  • K. Nothing computes K on v4. It is a figure over heat; it waits for A and C.

2.7 Ruling (Captain Bob, 2026-10-05)

One more time: v4 = v3 functionally. We will use [heat accumulation] on 32 opcodes rather than words. Before, a word was our smallest unit; now it is the opcode.

This settles section 2.4:

  • A. Heat is kept per opcode: 32 accumulators in the node. Not in a word's dictionary entry, and not per call target.
  • B. The unit is the opcode. Whether a word is called or compiled in line makes no difference to what is counted. call is one of the 32 and is counted as itself.
  • C. v4 = v3 functionally, so every loop v3 runs before its prompt runs on v4, over opcodes where v3's runs over words.

What follows from it, and is not yet done:

  • The per-call-target array (v4/src/heat.c, call[], the freeze mask, v4_heat_on_call) has no place and is to be removed, with HEAT-CALL in DECOMPOSITION.md sections 1.4, 5.19, 5.23 and 7. D-6 is answered: per-opcode.
  • Sections 5.21 and 5.22 of DECOMPOSITION.md retire pipelining and the hot-words cache. Under C they are not retired.
  • Decomposition no longer waits on this: moving a word from assembler to a colon definition changes which opcodes run, and those are counted wherever the code is.

Still open, for the words v3 keys by word and v4 must key by something:

  • ACL. Access control is per word, and v3 works a word's TTL out from that word's heat (ACL-TTL-COMPUTE). A v4 word has no heat of its own.
  • Freeze and pin. v3 freezes or pins a word's heat (FREEZE-WORD, WORD_PINNED). In v4 what is frozen is an opcode, or nothing.
  • Hot-words cache. v3 promotes a hot word so that it is found faster. A v4 opcode is not looked up.
  • Heartbeat. What ticks it on a node (v3: the kernel's timer interrupt).

3. Stand-ins in v4, as found 2026-10-05

Each describes itself as one. None has been changed.

What Where Says of itself
Per-call-target heat v4/src/heat.c, v4/include/v4/heat.h "in the meantime" (D-6)
ACL-HEAT@ v4/capsule/acl.v4:80 returns 0; "not readable from a programme yet"
Console v4/include/v4/node.h:136, :156 "the model stands in for the console" until the mesh exists
Block storage v4/include/v4/node.h:248, D-19 "the model stands in" until the mesh carries the storage service
Memory map v4/tests/host_map.h, D-4 deferred a test header the product image is built from
CA public key v4/capsule/ACL.fth:40 "placeholders, as in v3"
Address-dependent POST cases v4/tools/post79_rules.py, ADDRESS check how many values are left, not which

NUCLEUS.md section 3 puts Q48, logging, ACL and the StarForth extensions out of scope until FORTH-79 is accepted. Under the ruling at the head of this file they are in scope, since v3 has them before its prompt. That section is to be corrected once the rows above are ruled.