Stage C-a: work law — running VM charged at each of its own beats, with carry (FABRIC-3.8 §3.13.2)
vm_physics_charge(): per-beat slope into a per-VM carry, whole units pulled from the rest of the live fleet in proportion to heat (conservative vm_physics_transfer), rounding shortfall kept in the carry, no fleet_window sample. Called from vm_tick() only for the switch-current VM. Closes G9: a VM running its own mail on its own stack now heats up while it works. Probe (reverted): baseline Hestia heat 0->0->0 over 71 beats (FAIL, proves G9); with charge 0->11->23 at beats 15->51->86, identical on amd64/aarch64/ riscv64, conserved, PASS. Acceptance: dict_hash unchanged, WIREBIND relay 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
29447abb7d
commit
7c3736841d
+57
-5
@@ -529,10 +529,13 @@ switch-current. Hera's is seeded at `sk_vm_switch_set_current()`, so her first c
|
||||
cover every beat since boot. The clamp to `others_total` would make that harmless anyway, but it
|
||||
should be defined rather than left to the clamp.
|
||||
|
||||
**What a beat counts.** A beat is 256 of *either* colon-word entries or words parsed at top level
|
||||
by `vm_interpret` (the two `check_counter` sites). Primitives executed inside colon bodies are
|
||||
**not** counted. So the "words" figures below are beat counts × 256 in that sense, not total
|
||||
primitive executions.
|
||||
**What a beat counts** (corrected at the start of C-a, from reading `vm_core.c:909` in context).
|
||||
|
||||
- A beat is every 256 words a VM executes. That counts each word dispatched inside a colon body,
|
||||
primitives included (the `check_counter` bump in `execute_colon_word`'s inner loop), plus each
|
||||
word parsed at top level by `vm_interpret` (`:1286`).
|
||||
- The earlier draft said primitives inside colon bodies weren't counted. That was wrong.
|
||||
- The "words" figures below are therefore beat counts × 256 executed words.
|
||||
|
||||
**Hera's reservoir mass (ruling C-4, open, arithmetic shown).**
|
||||
|
||||
@@ -540,7 +543,7 @@ primitive executions.
|
||||
added to a closed system").
|
||||
- At slope 1/3 raw per beat, the workers together have to produce about `65536 × 3 × (N/(N+1))`
|
||||
beats before Hera cools to a worker's level. For N = 8 that is ≈175k beats, ≈45M
|
||||
colon-entries/top-level words (see "What a beat counts" above).
|
||||
executed words (see "What a beat counts" above).
|
||||
- Until then, Hera is never the coolest while any worker has work, **so the console gets no turn
|
||||
under load.** This doesn't block Stage C's relay evidence, because the relay runs while the
|
||||
workers are idle. It does block Stage F/H usability.
|
||||
@@ -827,3 +830,52 @@ explicit instruction.
|
||||
and zero refused interprets**. The `dict_hash` set is identical across ISAs and unchanged
|
||||
from Stages A/B. The full mint → WIREBIND → `USE` → `1 2 + .` → `3` relay works (the path
|
||||
with a nested frame on Hera's stack). Clean build on all three plus hosted, no new warnings.
|
||||
- [x] **Stage C-a — the work law: the running VM is charged at each of its own beats, with carry
|
||||
(§3.13.2).** 2026-09-23. Captain Bob: *"commit it and start stage C-a"*, which accepts
|
||||
§3.13.2's proposals C-1(a) and C-2 as written: charge at each beat, keep a carry, record no
|
||||
`fleet_window` samples. C-3, C-4 and C-5 are C-b's rulings and are still open.
|
||||
Changes:
|
||||
- `capsule_vm_physics.c` gets a new `vm_physics_charge(vm_id)`. It adds one beat's slope
|
||||
to a new per-VM `charge_carry`, then pulls the whole units from the rest of the live
|
||||
fleet in proportion to each VM's heat, through `vm_physics_transfer()`.
|
||||
- Clamped to what the others hold. That shortfall is dropped, as in touch, so the carry
|
||||
can't grow without bound while one VM runs alone.
|
||||
- Units lost to the proportional split's rounding go back into the carry.
|
||||
- No `fleet_window` sample and no `last_active_tick` change, so `vm_physics_touch()` and
|
||||
`VM-EXEC` behave byte-for-byte as before.
|
||||
- `vm_runtime.c`'s `vm_tick()` calls the charge right after `vm_physics_heartbeat_tick()`,
|
||||
only when the VM producing the beat is `sk_vm_switch_current_vm()`. A VM running nested
|
||||
inside someone else's `VM-EXEC` stays on the dispatch law.
|
||||
- §3.13.2 "What a beat counts" is corrected. `vm_core.c:909` is in `execute_colon_word`'s
|
||||
inner loop, so primitives inside colon bodies *are* counted.
|
||||
|
||||
**Evidence, as named in §4.** A temporary probe (`kernel_main.c`: `SB-GO`/`SB-BACK` plus
|
||||
`SB-HEAT`, which records Hestia's heat, the rest of the fleet's heat, her beat count and
|
||||
`vm_physics_conserved()`; reverted with `git checkout`). It sends Hestia `: SBW ; : SBL 3000
|
||||
0 DO SBW LOOP ; SB-HEAT SBL SB-HEAT SBL SB-HEAT SB-BACK`, and Hera runs `SB-GO SB-GO`.
|
||||
- **Baseline (pre-change code, probe only):** `logs/20260923-160929/amd64/` gives
|
||||
`hestia_heat 0 → 0 → 0` over beats 15 → 51 → 86, and **FAIL**. Hestia ran 71 beats of
|
||||
her own mail on her own stack and gained nothing, which **proves G9**.
|
||||
- **With the charge, all three ISAs:** `logs/20260923-161448/amd64/`,
|
||||
`-161959/aarch64/` and `-162543/riscv64/` give, byte-identically, `hestia_heat 0 → 11 →
|
||||
23` at beats 15 → 51 → 86, `rest 65536 → 65525 → 65513`, conserved at every sample, and
|
||||
**PASS**. The heat rises **mid-turn** at each in-turn sample.
|
||||
- Exact to the arithmetic: switched in at beat 15, so ⌊36·21845/65536⌋ = 11 and
|
||||
⌊71·21845/65536⌋ = 23. Every unit Hestia gained came out of the rest of the fleet (all
|
||||
from Hera; Artemis held 0).
|
||||
- `fleet_window_warm=NO` and `slope 21845` are unchanged. By source, the charge never
|
||||
writes `fleet_window`.
|
||||
|
||||
**Formal acceptance with the probe gone,** coupled images reset before each:
|
||||
`logs/20260923-163215/amd64/`, `-163757/aarch64/`, `-164359/riscv64/`.
|
||||
- All reach `[zuse@Hera] ok>` with zero `UNKNOWN WORD`, failures, faults, `VM FRAME
|
||||
CORRUPTION` and refused interprets.
|
||||
- The `dict_hash` set is identical across ISAs and unchanged from Stages A/B/FR.
|
||||
- The full mint → WIREBIND → `USE` → `1 2 + .` → `3` relay works, with
|
||||
`stadium_conserved(self)=true`.
|
||||
- Clean build on all three plus hosted, no new warnings.
|
||||
|
||||
**Consequence to watch in C-b:** heat now moves at boot too. Hera is switch-current from
|
||||
her Stage 3 registration onward and is charged for her own beats. She holds nearly all the
|
||||
heat, so her charges pull almost nothing; that is the C-4 arithmetic playing out as
|
||||
expected. The per-beat DoE heat columns will read differently from pre-C-a runs.
|
||||
|
||||
Reference in New Issue
Block a user