diff --git a/docs/v4.0.0/V3-PARITY.md b/docs/v4.0.0/V3-PARITY.md new file mode 100644 index 00000000..e2ea2cbd --- /dev/null +++ b/docs/v4.0.0/V3-PARITY.md @@ -0,0 +1,213 @@ +# 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. + +## 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. + +## 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.