feat(kernel): v4 boots in the kernel's boot -- the Stadium, its checks, the opcode patrons
#189, ENGINE step 4, Phase 1 (plan 2026-11-13-engine-step4-phase1), Tasks 1-4. Captain Bob, 2026-11-13: Q1 "A new node key", Q2 "Per heartbeat tick", Q3 "All of v3's", Q4 "In Phase 1" / "Full births now", who runs next "Hera by compudynamics now" (Task 5, to come). - stadium.c/.h: stadium_node_key(node) ("NODE" | number), stadium_boot_init_for(first), stadium_birth_node(key, name); stadium_boot_init() and stadium_birth_hera() are them for Hera's key, so v3's path is as it was (only an impossible panic's words changed). - kernel_main.c: the system is chosen and said first, then the Stadium, sessions, switch-signal and kernel-Hermes tables for both systems in v3's order; v4: Hera, node 10, patron zero under her node key, the word, block and opcode layers. The quota self-test and the heartbeat's line are functions now, called by both systems. - sk_v4.c/.h: sk_v4_run() goes -- sk_v4_boot() returns, the kernel's checks after POST (opcodes, words, conservation, quota, heartbeat), then sk_v4_prompt(). sk_v4_charge_opcodes() at the heartbeat's service points (the key wait, after each line) and once after POST. - stadium_ops.c/.h: a node's 32 opcodes as Stadium patrons (HEAT-OP's feed, "Both"): retirements charged as the word layer's dispatches, a quantum each, the reservoir's floor kept, shared by retirements when short; cooling per tick as words. ~0.5 us a charge on the host: kept. - qemu_session.py: a v4 acceptance boot fails without "Stadium: N cells", "Stadium conservation: CONSERVED" and the heartbeat's ticks (#189). Tests first (logs/20261113-122142): the physics check failed on the v4 boot; test_stadium_node, test_stadium_ops (and its share case, after a real boot showed ";" taking all the heat) failed before. Now: kernel host tests all pass; amd64 v4 boot passes, POST 539/539, dict_hash unchanged, "Stadium opcodes: 30 resident, hottest opcode 8", CONSERVED; a system=v3 boot prints its Stadium lines as on 2026-11-06. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
# ENGINE Step 4, Phase 1: v4 in the kernel's boot -- Plan
|
||||
|
||||
> **For agentic workers:** steps use checkbox (`- [ ]`) syntax. One QEMU at a time, in the foreground
|
||||
> (`.claude/CLAUDE.md`); every log and CSV is committed.
|
||||
|
||||
**Goal (#189):** on bare metal, v4 boots *in* the kernel's boot, not before it: the kernel's own order,
|
||||
as v3's -- hardware, the heartbeat, **the Stadium**, then the v4 system on the first node (Hera) with
|
||||
POST, then the devices, then the prompt -- and the Stadium holds Hera from the start, so that Phase 2
|
||||
can feed it every word Hera calls. `sk_v4_run()`, which today takes the boot before the Stadium is
|
||||
made and never returns (`kernel_main.c:647`), goes.
|
||||
|
||||
**Parent plan:** `2026-10-20-engine-step4-node-in-the-vms-place.md`, Phase 1 (rows 1, 2, 5, 6 and 9 of
|
||||
`V3-PARITY.md` section 1). Order ruled 2026-11-12 (Captain Bob, #189): Part A (done), Phase 1, Phase 2,
|
||||
then Phase 7. HEAT-OP's Stadium feed was ruled into this phase ("Both": the registers now -- built
|
||||
2026-11-12 -- and the Stadium feed in Phase 1, measured, kept or reverted on the numbers).
|
||||
|
||||
## What a v4 boot does today, and what v3's does
|
||||
|
||||
| | v3 (`system=v3`) | v4 today |
|
||||
|---|---|---|
|
||||
| Heartbeat | started (`kernel_main_deep`) | started -- the same code, before the choice |
|
||||
| The Stadium | `stadium_boot_init`, `session_boot_init`, `stadium_birth_hera`, `stadium_words_init`, `stadium_blocks_init` -- "Stadium: 83886 cells (5242 KB), 50 VM slots" | **never made**: `sk_v4_run()` is called before it and does not return |
|
||||
| The system | the v3 VM, POST | one node, POST (`v4_boot_run`) |
|
||||
| The checks after POST | "Stadium words: promotions=...", "Stadium conservation: ... CONSERVED", "Stadium quota grant self-test: OK", "Heartbeat: N ticks" | none |
|
||||
| Devices | PCI, the disk | the block chain, after POST (`sk_v4_block_chain`) |
|
||||
| The prompt | `sk_repl()` | `sk_v4_run()`'s own loop |
|
||||
|
||||
## Rulings (Captain Bob, 2026-11-13)
|
||||
|
||||
- **Q1: "A new node key."** The Stadium is keyed by v4 node number now, ahead of the fleet -- not by
|
||||
`vm_uuid_hera()`. A node's key is made from its number (`stadium_node_key(node)`, a `VMUuid` that
|
||||
no v3 VM can have); the node the kernel brings up first, Hera -- node 10, as the hosted mesh numbers
|
||||
her (`test_host_unit.c`: "it is told it is 10") -- is patron zero under her key. v3's path keeps
|
||||
`vm_uuid_hera()` and `stadium_birth_hera()` unchanged (`MACHINE.md` 7 item 3); the v4 path gets
|
||||
`stadium_birth_node(key)`, the same birth for a key it is given.
|
||||
- **Q2: per heartbeat tick**, as recommended.
|
||||
- **Q3: "All of v3's."** A v4 boot runs every boot check v3's does that is not v3's VM itself: the
|
||||
Stadium, the session table, the switch-signal table, kernel-Hermes' channels and queues, Hera's
|
||||
birth, the word and block layers; and after POST the conservation check, the quota grant self-test
|
||||
and the heartbeat's tick line.
|
||||
- **Q4: "In Phase 1."** The registry (`v4/src/manage.c`) comes into the kernel build in this phase:
|
||||
Task 5 is in. Asked how much -- it needs a fabric of nodes, births that make them, and who runs
|
||||
next (`ENGINE.md` 6, open) -- **"Full births now."**
|
||||
- **Who runs next (`ENGINE.md` 6): "Hera by compudynamics now."** As v3's turn-attractor, agreed
|
||||
with Captain Bob (`FABRIC-3.md`, the turn-attractor: "the next turn to whichever live identity VM
|
||||
currently has the lowest `execution_heat_q48` ... No priority levels, no time slices, no
|
||||
preemption -- the same density comparison Stadium already uses"): the next instruction word goes
|
||||
to the **coolest awake node** that can run, by its resident heat in the Stadium -- its opcode
|
||||
patrons (Task 3) until Phase 2 adds its words. Switching only between instruction words
|
||||
(`ENGINE.md` 3a). A node asleep at its wires, or blocked, is not a candidate.
|
||||
|
||||
## Questions (as they were put)
|
||||
|
||||
**Q1. Hera's place in the Stadium.** *Recommend:* the v4 node is Hera, patron zero, under
|
||||
`vm_uuid_hera()`: `stadium_birth_hera()` as v3 has it, and its session. The Stadium's own code is the
|
||||
kernel's and unchanged (Q3 of 2026-10-20: "keyed by node number where they are keyed by VM today" --
|
||||
with one node, Hera's UUID is that key until the fleet, Phase 5 onward).
|
||||
|
||||
**Q2. The opcode patrons: how a count becomes heat.** The Stadium's heat is a conserved share of 1.0,
|
||||
not a count. *Recommend:* 32 opcode patrons for the node, one per opcode, admitted at boot as the word
|
||||
layer admits words (`stadium_words.c`), behaviour `COOL`; **at each heartbeat tick, not at each
|
||||
instruction**, each opcode's retirements since the last tick (`v4_heat.op[k]`'s delta) are charged as
|
||||
that many of the word layer's dispatches -- the same pull from the node's reservoir, the same cooling
|
||||
per tick -- in one step. Per instruction it would be a kernel call per instruction (the "huge
|
||||
performance hit" the ruling allows to be reverted); per tick it is 32 sums a tick. Measured either way
|
||||
(Task 3). *If not:* charged per instruction, at the hook in `v4/src/exec.c` -- then measured, and
|
||||
reverted if it is the hit.
|
||||
|
||||
**Q3. Which of v3's boot checks a v4 boot runs.** *Recommend:* those of the Stadium and the heartbeat,
|
||||
which are the kernel's: the Stadium's allocation, Hera's birth, the word and block layers, and after
|
||||
POST the conservation check (`stadium_words_print_boot_diagnostics`), the quota grant self-test and the
|
||||
heartbeat's tick line. Not v3's switch-signal table, kernel-Hermes' channels and queues, or the v3 VM's
|
||||
own Stadium step lines: they are a v3 VM's (Q1 of 2026-10-20: Hermes is v4's wires, not
|
||||
`kernel_hermes.c`).
|
||||
|
||||
**Q4. The registry (`v4/src/manage.c`, MESH step 9) in this phase or after alpha.5.** The parent plan
|
||||
puts it in Phase 1; the physics does not need it -- one node, Hera, is enough for Phases 2 and 7.
|
||||
*Recommend:* after alpha.5, with the fleet (Phase 5 onward), to keep #189's path short. *If not:* Task 5
|
||||
below.
|
||||
|
||||
## Tasks
|
||||
|
||||
### Task 1: The Stadium before the system
|
||||
|
||||
**Files:** `kernel/src/kernel_main.c`. Test: the amd64 boot (an acceptance check, Task 4).
|
||||
|
||||
- [ ] **Step 1: Seen to fail first:** the acceptance check of Task 4, on today's build: a v4 boot has no
|
||||
"Stadium: ... cells" line.
|
||||
- [ ] **Step 2:** `stadium_boot_init`, `session_boot_init`, `sk_vm_switch_signal_boot_init`,
|
||||
`sk_hermes_channels_boot_init`, `sk_hermes_queues_boot_init` move above the choice of system -- the
|
||||
kernel's, for both systems, in v3's order (Q3). Then on v3's path `stadium_birth_hera()` as today; on
|
||||
v4's, `stadium_birth_node(stadium_node_key(10))` (Q1, a failing host test first:
|
||||
`kernel/tests/test_stadium_node.c` -- the key is no v3 VM's, the node lands on cell 0, its session is
|
||||
registered and pinned). Then `stadium_words_init` and `stadium_blocks_init`. v3's path is otherwise
|
||||
unchanged (`MACHINE.md` 7 item 3): the same calls, in the same order, before its VM.
|
||||
- [ ] **Step 3:** the three boots and the stick, v4: "Stadium: N cells (... KB), 50 VM slots" before
|
||||
the system starts; POST and `dict_hash` unchanged (the node is not touched). One `system=v3` boot,
|
||||
for v3's path: the same lines it printed before.
|
||||
|
||||
### Task 2: `sk_v4_run()` goes
|
||||
|
||||
**Files:** `kernel/src/v4/sk_v4.c`, `kernel/include/starkernel/v4/sk_v4.h`, `kernel/src/kernel_main.c`.
|
||||
|
||||
- [ ] **Step 1:** `sk_v4_run()` becomes two: `sk_v4_boot()` -- the node, POST, the blocks, the
|
||||
identity; it returns -- and `sk_v4_prompt()`, the prompt loop, which does not. The kernel calls them
|
||||
in its own order: the Stadium (Task 1), `sk_v4_boot()`, the checks after POST (Q3), then
|
||||
`sk_v4_prompt()`.
|
||||
- [ ] **Step 2:** the checks after POST on v4, under Hera's node key: "Stadium words: ...", "Stadium
|
||||
conservation: ... CONSERVED", "Stadium quota grant self-test: OK", the heartbeat's tick line (Q3).
|
||||
- [ ] **Step 3:** the three boots and the stick: those lines, then `[zuse@Hera] ok> `; POST and
|
||||
`dict_hash` unchanged.
|
||||
|
||||
### Task 3: The opcode patrons (HEAT-OP into the Stadium), measured
|
||||
|
||||
**Files:** `kernel/src/vm/stadium_ops.c` (new), its header, `kernel/src/v4/sk_v4.c` (the tick).
|
||||
Test: `kernel/tests/test_stadium_ops.c` (the host harness, `make -C kernel/tests`), with the Stadium's
|
||||
own sources.
|
||||
|
||||
- [ ] **Step 1: Failing test:** 32 patrons admitted for a node; N retirements of an opcode between two
|
||||
ticks heat its patron as N of the word layer's dispatches would; the sum of the node's resident heat
|
||||
and its reservoir stays 1.0 (`stadium_conserved`); no retirements, no heat; cooling per tick as words.
|
||||
- [ ] **Step 2:** `stadium_ops.c`, as ruled in Q2; the heartbeat's tick charges the deltas.
|
||||
- [ ] **Step 3:** a line after POST, "Stadium opcodes: ..." (the hottest opcodes), and conservation
|
||||
still CONSERVED with them in.
|
||||
- [ ] **Step 4: Measured:** the amd64 boot's time and POST's instruction count, with and without the
|
||||
feed, five boots each -- recorded in the commit. Kept, or reverted on the numbers (Captain Bob,
|
||||
2026-11-12).
|
||||
|
||||
### Task 4: Acceptance asserts it
|
||||
|
||||
**Files:** `scripts/qemu_session.py` (the v4 boot's checks), `scripts/nightly.sh` (the stages read them).
|
||||
|
||||
- [ ] **Step 1:** a v4 acceptance boot must show "Stadium: ... cells", "Stadium conservation: ...
|
||||
CONSERVED" and the heartbeat's line before its prompt; one without them fails (#189 Done when, third
|
||||
item: "a boot without the physics fails"). Seen to fail on today's build (Task 1 Step 1).
|
||||
- [ ] **Step 2:** the protocol, all eight stages; then the push, on Captain Bob's word.
|
||||
|
||||
### Task 5: the registry and births (Q4: "Full births now")
|
||||
|
||||
Each its own increment, each test first, each a boot:
|
||||
|
||||
- [ ] **5a. A fabric in the kernel, Hera in it.** `v4/src/fabric.c` and `manage.c` into the kernel
|
||||
build; Hera, node 10, at a place of a kernel fabric, entered in the registry; the prompt's lines go
|
||||
to her through it. `centre.4th` and `hera.4th` loaded on her: `NODE-ME` answers her place (word
|
||||
count and `dict_hash` change).
|
||||
- [ ] **5b. Births.** `NODE-BORN`: room for a node from the kernel's heap, a place in the fabric, a
|
||||
Stadium quota granted from Hera's under the new node's key (`stadium_node_key(number)`), its
|
||||
opcode patrons; `NODE-KILL` gives the room and the quota back. The capsule words
|
||||
(`CAPSULE-OPEN/-CELL/-LINE`) from the kernel's capsule directory.
|
||||
- [ ] **5c. Who runs next.** The turn-attractor: each step, the coolest awake node that can run
|
||||
executes an instruction word; the opcode charge for every node at the heartbeat's service points.
|
||||
A test that two busy nodes take turns as their heat says, and a sleeping node is never chosen.
|
||||
- [ ] **5d. Acceptance.** A boot births a node from Hera, it answers a line, Hera kills it, and the
|
||||
Stadium is CONSERVED after.
|
||||
|
||||
## What this phase does not do
|
||||
|
||||
Phase 2 (the word accounts at `call`: the kernel's record per word, `execution_heat`,
|
||||
`stadium_word_dispatch`, the ACL's countdown) and Phase 7 (decay, the rolling window, pipelining,
|
||||
inference, L8 on those records). After Phase 1 the Stadium holds Hera and her 32 opcode patrons, and
|
||||
nothing yet of her words.
|
||||
|
||||
## Review focus
|
||||
|
||||
1. **v3's path:** a `system=v3` boot prints what it printed before, in the same order.
|
||||
2. **The 32-bit build and the stick:** the Stadium's allocation fits the stick loaded high as it does
|
||||
at 2 GiB.
|
||||
3. **Conservation with the opcodes in:** K = 1.0 after POST, before the prompt.
|
||||
4. **The tick's cost:** with the feed, the heartbeat still keeps its rate (its tick line's count against
|
||||
the boot's time).
|
||||
Reference in New Issue
Block a user