Stage H: DoE rebuilt on BIRTH/SEND/KILL, defs-only workloads; work heat floor on contact (FABRIC-3.8 §3.9, §3.13.7)

Workload capsules the DoE births are definitions only; each defines WL-RUN
(its old birth-time work plus its entry word twice) and WL-DONE-ARGS. The
driver births N workers, SENDs each 'WL-RUN WL-DONE-ARGS SEND', waits in an
ordinary loop for N MU-DONE messages, KILLs them (parked idle), and emits
the marker. The serialized VM-EXEC round-robin is gone.

Kernel: no switch checkpoint after a payload's last word; work heat is the
assessed per-beat charge, and a VM gaining work is raised to the busy set's
floor (Captain Bob's ruling) -- fixes a live stall where a busy-waiting Hera
never yielded, without serializing batch starts.

Evidence: cfg-4 rows spread evenly over Hera and all 8 worker slots (44k
switches); full cfg-4 trials on amd64/aarch64/riscv64 end fail=0 with 8/8
KILL dead; Stage G interleave byte-identical on all three. Acceptance:
dict_hash unchanged, relay 3, idle growth 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-23 23:48:16 -04:00
co-authored by Claude Opus 5.5
parent 81def7b4a5
commit f152a91099
29 changed files with 165584 additions and 153 deletions
+99
View File
@@ -715,6 +715,24 @@ a loop. So would the console under load (already recorded under C-b).
conserved, and still appears in the DoE heat columns; it just no longer decides turns. The
prediction held on all three ISAs: see the Stage G entry in §6.
**Refined at Stage H, RULED 2026-09-23, Captain Bob: "floor on contact."** Two changes to what
work heat is, both forced by a live stall (Stage H entry, §6):
- **Assessed, not moved.** Work heat accrues each beat's assessed charge (the slope, in the
carry's sub-unit scale), whether or not the rest of the fleet held heat to move.
- As first built, it counted only heat actually moved.
- A busy-waiting Hera, with nobody else holding absolute heat, then stayed at 0 forever, tied
the workers, and never yielded.
- **Floor on contact.** When a VM with no work gains some (its kernel-Hermes queue goes from
empty to one message, and it is neither running nor parked mid-task), its work heat is raised
to the lowest work heat among the VMs that have work right now: the running one, and every
eligible participant.
- Without the floor, a fresh worker at 0 would run alone until it had done as much work as
Hera has since boot. The batch would start serially.
- No tuning constant.
- Rejected alternatives: decay/dissipation (needs a rate constant), and assessed charge
without the floor.
#### 3.13.6 Stage C, split
This splits the single C row in §4 in two:
@@ -1226,3 +1244,84 @@ explicit instruction.
- Hera's work heat grows only when other VMs hold absolute heat for her charges to pull
from. She runs cheaply while they hold ~0.
- Both are properties of the ruled quantity, recorded here, not changed.
- *(Superseded at Stage H: both consequences above turned out to matter, and the "floor on
contact" refinement replaced them. See §3.13.7 and the Stage H entry.)*
- [x] **Stage H — the DoE rebuilt on ordinary words; "floor on contact" (§3.9, §3.13.7).**
2026-09-23. Captain Bob: *"defs-only, no users factor yet, accept PRNG, go ahead with H"*,
and then ruled **floor on contact** when the first trial stalled.
**Changes, capsules:**
- The ten workload capsules the DoE births (`workload-0`, `-1-lite`, `-2`, `-3`, `-4`,
`-5-lite`, `-6`, `-7`, `-8`, `-9`) are now **definitions only**.
- Every top-level line that executed at birth is removed. That includes the heavy
self-exec tails and the mid-file `SEED`/wave/`RUN-ASYM`/`RUN-DUAL` runs in 2, 3 and 9.
- Each gains `: WL-RUN <exactly what it used to run at birth> <its entry word, twice> ;`.
That is the old trial's birth work plus its two `VM-EXEC` passes, now one job.
- Each also gains `: WL-DONE-ARGS S" MU-DONE" S" Hera" ;`.
- `workload-4` keeps its `4:dopi-ok` print inside `WL-RUN`.
- `workload-7` needed a second block for the two definitions. Block 2151 was unclaimed;
the conflict gate and `mkcapsule --lint` pass (37 files, 0 violations).
- `workload-1` and `-5` (full versions) are untouched, since the DoE doesn't birth them.
- `multiuser-doe.4th`:
- `WL-ENTRY`, `MU-TOUCH-WORKER/ALL` (the serialized `VM-EXEC` round-robin) and
`MU-CHECK-WORKER/ALL` are gone.
- New: `MU-DONE-COUNT`/`MU-DONE`, `MU-JOB` (the constant job text `WL-RUN WL-DONE-ARGS
SEND`), `MU-SEND-WORKER/ALL`, and `MU-WAIT-ALL` (an ordinary `BEGIN … WHILE REPEAT`;
Hera's own checkpoints drain the `MU-DONE`s).
- `MU-RUN-TRIAL` is now birth all, send all, wait, kill all, marker.
- A refused `SEND` counts as a failure **and** as done, so the wait can't hang on it.
**Changes, kernel:**
- `vm_core.c`: the between-top-level-words checkpoint (C-b) doesn't fire after the
**last** word (`vm_input_exhausted()`). The job's final word is the `SEND` to Hera, which
makes a decision due. Switching the worker out right there would park it "mid-task" with
nothing left, and `KILL` would refuse it. The trampoline decides a moment later anyway.
- **Floor on contact** (§3.13.7):
- `vm_physics_charge()` accrues the assessed slope into `work_heat_q48`.
- New `vm_physics_work_heat_floor()`.
- New `sk_vm_switch_signal_note_work_gained()`, called by `sk_hermes_send_one()` when the
recipient's queue goes from empty to one message.
**First trial, before the floor** (`logs/20260923-211253/amd64/`, kept): stalled.
- After 8,200+ beats the rows showed `switch_count_cumulative=0` and
`switch_current_slot=2` (Hera) throughout.
- Hera sat in `MU-WAIT-ALL`, with work heat 0 against workers at 0: a tie, so the
incumbent stays, forever.
**Evidence, as named in §4.**
- **Rows** (`logs/20260923-212353/amd64/`, cfg 4 with `HB-ON`, stopped deliberately once
captured because per-VM rows at every beat make a full trial take hours):
- `switch_count_cumulative` reached 44,297.
- Over the first ~7,600 rows, `switch_current_slot` was spread **evenly** across Hera
(slot 2: 851) and all eight workers (slots 5–12: 844–846 each).
- **Full trials** at cfg 4 (8 workers, uniform `workload-8`), rows off, one per ISA:
`logs/20260923-220439/amd64/`, `-222512/aarch64/`, `-231553/riscv64/`.
- Each ends with **`MU-TRIAL isa=<isa>run=999 cfg=4 rep=0 nw=8 mode=0 fail=0`**.
- **All 8 `KILL: muN dead`, 0 refused.** Every worker ended parked idle and killable.
- Times: amd64 ≈ 13 min, aarch64 ≈ 43 min, riscv64 ≈ 23 min.
- **Stage G's test, re-run on each boot under the refined rule:** byte-identical on all
three, `ABBAABBABAABBAABBABAABBA…` (A = 40, B = 40, **48** runs). It is finer than
Stage G's 16 runs because work heat now moves by sub-unit steps every beat.
**Acceptance,** in the same three boots after the trial:
- All reach `[zuse@Hera] ok>` with zero `UNKNOWN WORD`, failures and faults.
- The `dict_hash` set is unchanged from Stage G (word_count 533, M7.1a
`0x330b28ce0f4e1c75`).
- Mint → WIREBIND → `USE` → `1 2 + .` → `3`.
- Idle log growth: 0 bytes.
- Clean build on all three plus hosted, no new warnings.
**Known limits, recorded, not changed:**
- **A worker whose job errors never sends `MU-DONE`,** so `MU-WAIT-ALL` waits forever.
The error prints, but the trial produces no marker.
- **Worker execution errors are no longer counted.** `VM-ERROR?` can't see them, because
`sk_hermes_drain_checkpoint()` restores the VM's error flag after each payload (by
design: a bad message must not abort the enclosing context). `fail` now counts only
refused `SEND`s.
- **Hera's wait loop is a busy loop.** She takes a fair share of the CPU
(1/(N+1)), as the row tally shows.
- Per-VM, per-beat `HB-ON` rows make trials slow. One row in that capture shows a negative
(wrapped) `tick_interval_ns` for a VM a beat behind the others. That's a DoE-row
observation, not investigated.
- Stage F's remaining evidence (work proceeds with the console idle) is shown by Stage G's
interleave and by these trials.
+69 -68
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-24T00:51:15Z -->
<!-- Generated by mkcapsule --manifest 2026-09-24T03:15:17Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -25,23 +25,23 @@
| `init-l8-volatile.4th` | 4810, 4811, 4812, 4813 | `0x98caabbbd92abac4` | yes |
| `init.4th` | 2049, 2050, 2057 | `0xea038ba684c53443` | yes |
| `lib.4th` | 4050 | `0x4b216635c359ef73` | yes |
| `multiuser-doe.4th` | 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055 | `0xb4f6f0c2c582a4d4` | yes |
| `multiuser-doe.4th` | 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055 | `0x2b268decf6065736` | yes |
| `per-isa-doe.4th` | 5117, 5119 | `0xab13edecabfd78db` | yes |
| `sdk.4th` | 5109, 5110, 5111, 5112, 5113, 5114, 5115 | `0x008fdbbb62c94a3a` | yes |
| `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | yes |
| `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | yes |
| `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | yes |
| `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | yes |
| `workload-0.4th` | 2200, 2201 | `0x5597918289a363e3` | yes |
| `workload-1-lite.4th` | 5058, 5059 | `0xbc13567fea25063a` | yes |
| `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | yes |
| `workload-2.4th` | 4506, 4515, 4525, 4535, 4545 | `0xf113b3d0bcccae47` | yes |
| `workload-3.4th` | 4606, 4615, 4625, 4635, 4645, 4655, 4665 | `0x62b7a71576ad1041` | yes |
| `workload-4.4th` | 2130, 2131, 2132 | `0x099619264e650b1c` | yes |
| `workload-5-lite.4th` | 5056, 5057 | `0xea0303f38824f254` | yes |
| `workload-2.4th` | 4506, 4515, 4525, 4535, 4545 | `0x9f87a07575e8f86a` | yes |
| `workload-3.4th` | 4606, 4615, 4625, 4635, 4645, 4655, 4665 | `0xc4a88f6991036cc4` | yes |
| `workload-4.4th` | 2130, 2131, 2132 | `0x65372d2d3787d2ba` | yes |
| `workload-5-lite.4th` | 5056, 5057 | `0x05c651e140ef667b` | yes |
| `workload-5.4th` | *(none — raw code capsule)* | `0x526964c7c9506a11` | yes |
| `workload-6.4th` | 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095 | `0x06fc0ce1e369ef5a` | yes |
| `workload-7.4th` | 2150 | `0x02862291387eb7ac` | yes |
| `workload-8.4th` | 2160 | `0x56b7f2f0efa000df` | yes |
| `workload-9.4th` | 4706, 4715, 4725, 4735, 4745 | `0x3f2bec73142aa424` | yes |
| `workload-6.4th` | 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095 | `0x2526f98096581e63` | yes |
| `workload-7.4th` | 2150, 2151 | `0x3441183353715e63` | yes |
| `workload-8.4th` | 2160 | `0xe182180361013aa8` | yes |
| `workload-9.4th` | 4706, 4715, 4725, 4735, 4745 | `0x6c08bf4ad3f286b2` | yes |
| `workload-calib1.4th` | 5043 | `0x3b9f2d17b554fabc` | yes |
| `zuse-eligibility.4th` | 4021, 4022 | `0x7b28f4776a32e0b7` | yes |
| `zuse.4th` | 4016, 4017, 4018 | `0xa14d5a7a88791cf6` | yes |
@@ -69,22 +69,22 @@
| 2077 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2078 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2079 | `init-l8-omni.4th` | `0x5979e314d6452045` | ok |
| 2080 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2081 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2082 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2083 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2084 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2085 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2086 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2087 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2088 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2089 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2090 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2091 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2092 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2093 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2094 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2095 | `workload-6.4th` | `0x06fc0ce1e369ef5a` | ok |
| 2080 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2081 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2082 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2083 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2084 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2085 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2086 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2087 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2088 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2089 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2090 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2091 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2092 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2093 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2094 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2095 | `workload-6.4th` | `0x2526f98096581e63` | ok |
| 2100 | `doe.4th` | `0xf154616d248e861f` | ok |
| 2101 | `doe.4th` | `0xf154616d248e861f` | ok |
| 2102 | `doe.4th` | `0xf154616d248e861f` | ok |
@@ -93,13 +93,14 @@
| 2105 | `doe.4th` | `0xf154616d248e861f` | ok |
| 2106 | `doe.4th` | `0xf154616d248e861f` | ok |
| 2107 | `doe.4th` | `0xf154616d248e861f` | ok |
| 2130 | `workload-4.4th` | `0x099619264e650b1c` | ok |
| 2131 | `workload-4.4th` | `0x099619264e650b1c` | ok |
| 2132 | `workload-4.4th` | `0x099619264e650b1c` | ok |
| 2150 | `workload-7.4th` | `0x02862291387eb7ac` | ok |
| 2160 | `workload-8.4th` | `0x56b7f2f0efa000df` | ok |
| 2200 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
| 2201 | `workload-0.4th` | `0x93f86f60aeba8feb` | ok |
| 2130 | `workload-4.4th` | `0x65372d2d3787d2ba` | ok |
| 2131 | `workload-4.4th` | `0x65372d2d3787d2ba` | ok |
| 2132 | `workload-4.4th` | `0x65372d2d3787d2ba` | ok |
| 2150 | `workload-7.4th` | `0x3441183353715e63` | ok |
| 2151 | `workload-7.4th` | `0x3441183353715e63` | ok |
| 2160 | `workload-8.4th` | `0xe182180361013aa8` | ok |
| 2200 | `workload-0.4th` | `0x5597918289a363e3` | ok |
| 2201 | `workload-0.4th` | `0x5597918289a363e3` | ok |
| 4000 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4001 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
| 4002 | `ACL.4th` | `0xf8890c05c0d8f921` | ok |
@@ -202,23 +203,23 @@
| 4415 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
| 4425 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
| 4435 | `workload-1.4th` | `0x63e251adb0a03613` | ok |
| 4506 | `workload-2.4th` | `0xf113b3d0bcccae47` | ok |
| 4515 | `workload-2.4th` | `0xf113b3d0bcccae47` | ok |
| 4525 | `workload-2.4th` | `0xf113b3d0bcccae47` | ok |
| 4535 | `workload-2.4th` | `0xf113b3d0bcccae47` | ok |
| 4545 | `workload-2.4th` | `0xf113b3d0bcccae47` | ok |
| 4606 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4615 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4625 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4635 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4645 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4655 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4665 | `workload-3.4th` | `0x62b7a71576ad1041` | ok |
| 4706 | `workload-9.4th` | `0x3f2bec73142aa424` | ok |
| 4715 | `workload-9.4th` | `0x3f2bec73142aa424` | ok |
| 4725 | `workload-9.4th` | `0x3f2bec73142aa424` | ok |
| 4735 | `workload-9.4th` | `0x3f2bec73142aa424` | ok |
| 4745 | `workload-9.4th` | `0x3f2bec73142aa424` | ok |
| 4506 | `workload-2.4th` | `0x9f87a07575e8f86a` | ok |
| 4515 | `workload-2.4th` | `0x9f87a07575e8f86a` | ok |
| 4525 | `workload-2.4th` | `0x9f87a07575e8f86a` | ok |
| 4535 | `workload-2.4th` | `0x9f87a07575e8f86a` | ok |
| 4545 | `workload-2.4th` | `0x9f87a07575e8f86a` | ok |
| 4606 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4615 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4625 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4635 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4645 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4655 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4665 | `workload-3.4th` | `0xc4a88f6991036cc4` | ok |
| 4706 | `workload-9.4th` | `0x6c08bf4ad3f286b2` | ok |
| 4715 | `workload-9.4th` | `0x6c08bf4ad3f286b2` | ok |
| 4725 | `workload-9.4th` | `0x6c08bf4ad3f286b2` | ok |
| 4735 | `workload-9.4th` | `0x6c08bf4ad3f286b2` | ok |
| 4745 | `workload-9.4th` | `0x6c08bf4ad3f286b2` | ok |
| 4806 | `init-l8-stable.4th` | `0xdc3830f189063a9a` | ok |
| 4810 | `init-l8-volatile.4th` | `0x98caabbbd92abac4` | ok |
| 4811 | `init-l8-volatile.4th` | `0x98caabbbd92abac4` | ok |
@@ -333,22 +334,22 @@
| 5001 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 5002 | `fabric.4th` | `0x9d9489cbeca4099b` | ok |
| 5043 | `workload-calib1.4th` | `0x3b9f2d17b554fabc` | ok |
| 5044 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5045 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5046 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5047 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5048 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5049 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5050 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5051 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5052 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5053 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5054 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5055 | `multiuser-doe.4th` | `0xb4f6f0c2c582a4d4` | ok |
| 5056 | `workload-5-lite.4th` | `0xea0303f38824f254` | ok |
| 5057 | `workload-5-lite.4th` | `0xea0303f38824f254` | ok |
| 5058 | `workload-1-lite.4th` | `0x44a7a7e3176dcc8d` | ok |
| 5059 | `workload-1-lite.4th` | `0x44a7a7e3176dcc8d` | ok |
| 5044 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5045 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5046 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5047 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5048 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5049 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5050 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5051 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5052 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5053 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5054 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5055 | `multiuser-doe.4th` | `0x2b268decf6065736` | ok |
| 5056 | `workload-5-lite.4th` | `0x05c651e140ef667b` | ok |
| 5057 | `workload-5-lite.4th` | `0x05c651e140ef667b` | ok |
| 5058 | `workload-1-lite.4th` | `0xbc13567fea25063a` | ok |
| 5059 | `workload-1-lite.4th` | `0xbc13567fea25063a` | ok |
| 5100 | `turtle.4th` | `0x4d470418ca543365` | ok |
| 5101 | `turtle.4th` | `0x4d470418ca543365` | ok |
| 5102 | `turtle.4th` | `0x4d470418ca543365` | ok |
+18 -31
View File
@@ -29,19 +29,14 @@ Block 5045
ENDCASE ;
Block 5046
: WL-ENTRY ( idx -- c-addr u )
CASE
0 OF S" RUN-TRANSPOSE" ENDOF
1 OF S" MICRO-BURST" ENDOF
2 OF S" RUN-SAW" ENDOF
3 OF S" DUAL-SINE" ENDOF
4 OF S" RUN-PI" ENDOF
5 OF S" CHAOS-FIELD" ENDOF
6 OF S" RUN-OMNI" ENDOF
7 OF S" RUN-MMUL" ENDOF
8 OF S" RUN-FIB" ENDOF
9 OF S" RUN-SAW" ENDOF
ENDCASE ;
( FABRIC-3.8 3.9 Stage H: workers are born defs-only and )
( each is SENT one job. WL-RUN, defined in every workload )
( capsule, is its old birth-time tail plus its entry word )
( twice, as the old two VM-EXEC passes did. The LAST word )
( of the job SENDs MU-DONE back to Hera, who counts them. )
VARIABLE MU-DONE-COUNT
: MU-DONE ( -- ) MU-DONE-COUNT @ 1+ MU-DONE-COUNT ! ;
: MU-JOB ( -- c-addr u ) S" WL-RUN WL-DONE-ARGS SEND" ;
Block 5047
: MU-WORKER-NAME ( n -- c-addr u )
@@ -66,17 +61,12 @@ Block 5048
WL-CAPSULE
MU-TMP-NC @ MU-TMP-NU @
WORKER-BIRTH ;
: MU-TOUCH-WORKER ( wl-idx worker-n -- )
MU-WORKER-NAME MU-TMP-NU ! MU-TMP-NC !
WL-ENTRY
MU-TMP-NC @ MU-TMP-NU @
VM-EXEC ;
Block 5049
VARIABLE MU-FAIL-COUNT
: MU-CHECK-WORKER ( worker-n -- )
MU-WORKER-NAME VM-ERROR?
IF MU-FAIL-COUNT @ 1+ MU-FAIL-COUNT ! THEN ;
: MU-SEND-WORKER ( worker-n -- )
MU-JOB ROT MU-WORKER-NAME SEND 0= IF
MU-FAIL-COUNT @ 1+ MU-FAIL-COUNT ! MU-DONE THEN ;
: MU-KILL-WORKER ( worker-n -- )
MU-WORKER-NAME KILL ;
CREATE MU-RUN-MATRIX MU-MAX-RUNS CELLS ALLOT
@@ -125,14 +115,12 @@ Block 5052
MU-NW @ 0 DO
MU-MODE @ I MU-WL-FOR I MU-BIRTH-WORKER DROP
LOOP ;
: MU-TOUCH-ALL ( -- )
: MU-SEND-ALL ( -- )
MU-NW @ 0 DO
MU-MODE @ I MU-WL-FOR I MU-TOUCH-WORKER
LOOP ;
: MU-CHECK-ALL ( -- )
MU-NW @ 0 DO
I MU-CHECK-WORKER
I MU-SEND-WORKER
LOOP ;
: MU-WAIT-ALL ( -- )
BEGIN MU-DONE-COUNT @ MU-NW @ < WHILE REPEAT ;
Block 5053
: MU-KILL-ALL ( -- )
@@ -141,13 +129,12 @@ Block 5053
LOOP ;
: MU-RUN-TRIAL ( cfg rep run-id -- )
MU-RUN-ID ! MU-REP ! MU-CFG !
0 MU-FAIL-COUNT !
0 MU-FAIL-COUNT ! 0 MU-DONE-COUNT !
MU-CFG @ MU-CONC-OF MU-NW !
MU-CFG @ MU-MODE-OF MU-MODE !
MU-BIRTH-ALL
MU-TOUCH-ALL
MU-TOUCH-ALL
MU-CHECK-ALL
MU-SEND-ALL
MU-WAIT-ALL
MU-KILL-ALL
MU-EMIT-TRIAL-MARKER ;
+3 -2
View File
@@ -15,5 +15,6 @@ Block 2201
TRANSPOSE-CHUNK 46 EMIT
LOOP
;
( RUN-TRANSPOSE )
TRANSPOSE-CHUNK
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN TRANSPOSE-CHUNK RUN-TRANSPOSE RUN-TRANSPOSE ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+3 -1
View File
@@ -15,4 +15,6 @@ Block 5058
Block 5059
: RUN-MICRO-BURSTS ( -- )
1000 0 DO MICRO-BURST LOOP ;
RUN-MICRO-BURSTS
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN RUN-MICRO-BURSTS MICRO-BURST MICRO-BURST ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+4 -8
View File
@@ -12,7 +12,6 @@ Block 4506
Block 4515
( Rising edge with random perturbation )
42 SEED
: RISING-EDGE ( steps -- )
0 DO
I 1+
@@ -41,11 +40,8 @@ Block 4525
TRIANGLE-CYCLE
LOOP DROP ;
3 10 TRIANGLE-WAVE
Block 4535
( Asymmetric triangles - fast rise, slow fall )
7777 SEED
: ASYM-TRIANGLE ( -- )
8 0 DO
I 1+ 80 120 RANDOM 100 */ RAMP-STEP
@@ -56,14 +52,11 @@ Block 4535
80 120 RANDOM WAIT
LOOP ;
: RUN-ASYM 4 0 DO ASYM-TRIANGLE LOOP ;
RUN-ASYM
Block 4545
( Sawtooth variant - all rise, sharp drop )
54321 SEED
: SAWTOOTH ( steps -- )
0 DO
I 1+ 85 115 RANDOM 100 */ RAMP-STEP
@@ -72,4 +65,7 @@ Block 4545
50 WAIT ;
: RUN-SAW 3 0 DO 12 SAWTOOTH LOOP ;
RUN-SAW
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN 42 SEED 3 10 TRIANGLE-WAVE 7777 SEED RUN-ASYM
54321 SEED RUN-SAW RUN-SAW RUN-SAW ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+4 -9
View File
@@ -36,7 +36,6 @@ Block 4625
Block 4635
( Sinusoidal wave with random amplitude/frequency modulation )
42 SEED
: SINE-PULSE ( phase amplitude -- )
SWAP FULL-SIN * 100 / 1+
COMPUTE ;
@@ -61,14 +60,10 @@ Block 4645
100 200 RANDOM WAIT ( inter-cycle pause )
LOOP ;
3 SINE-WAVE
Block 4655
( Phase-shifted dual sine - interference pattern )
98765 SEED
: DUAL-SINE ( -- )
32 0 DO
I FULL-SIN 80 120 RANDOM 100 */
@@ -78,11 +73,9 @@ Block 4655
LOOP ;
: RUN-DUAL 4 0 DO DUAL-SINE LOOP ;
RUN-DUAL
Block 4665
( Damped sine - decaying amplitude )
11111 SEED
: DAMPED-SINE ( cycles -- )
100 SWAP ( starting amplitude )
0 DO
@@ -94,5 +87,7 @@ Block 4665
85 * 100 / ( decay by 15% each cycle )
DUP 10 < IF DROP 10 THEN
LOOP DROP ;
3 DAMPED-SINE
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN 42 SEED 3 SINE-WAVE 98765 SEED RUN-DUAL
11111 SEED 3 DAMPED-SINE DUAL-SINE DUAL-SINE ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+3 -2
View File
@@ -30,5 +30,6 @@ Block 2132
DO-PI
LOOP
;
RUN-PI
." 4:dopi-ok" CR
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN RUN-PI ." 4:dopi-ok" CR RUN-PI RUN-PI ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+3 -1
View File
@@ -21,4 +21,6 @@ Block 5057
CHAOS-BLOCK
LOOP
;
CHAOS-FIELD
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN CHAOS-FIELD CHAOS-FIELD CHAOS-FIELD ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+3 -2
View File
@@ -163,5 +163,6 @@ Block 2095
: RUN-OMNI
OMNI-WORK
;
RUN-OMNI
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN RUN-OMNI RUN-OMNI RUN-OMNI ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+4 -1
View File
@@ -14,4 +14,7 @@ Block 2150
MM-CHUNK 46 EMIT
LOOP
;
RUN-MMUL
Block 2151
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN RUN-MMUL RUN-MMUL RUN-MMUL ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+3 -2
View File
@@ -12,5 +12,6 @@ Block 2160
FIB-SEQ 46 EMIT
LOOP
;
FIB-SEQ
( RUN-FIB )
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN FIB-SEQ RUN-FIB RUN-FIB ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
+4 -8
View File
@@ -12,7 +12,6 @@ Block 4706
Block 4715
( Rising edge with random perturbation )
42 SEED
: RISING-EDGE ( steps -- )
0 DO
I 1+
@@ -41,11 +40,8 @@ Block 4725
TRIANGLE-CYCLE
LOOP DROP ;
3 10 TRIANGLE-WAVE
Block 4735
( Asymmetric triangles - fast rise, slow fall )
7777 SEED
: ASYM-TRIANGLE ( -- )
8 0 DO
I 1+ 80 120 RANDOM 100 */ RAMP-STEP
@@ -56,14 +52,11 @@ Block 4735
80 120 RANDOM WAIT
LOOP ;
: RUN-ASYM 4 0 DO ASYM-TRIANGLE LOOP ;
RUN-ASYM
Block 4745
( Sawtooth variant - all rise, sharp drop )
54321 SEED
: SAWTOOTH ( steps -- )
0 DO
I 1+ 85 115 RANDOM 100 */ RAMP-STEP
@@ -72,4 +65,7 @@ Block 4745
50 WAIT ;
: RUN-SAW 3 0 DO 12 SAWTOOTH LOOP ;
RUN-SAW
( FABRIC-3.8 3.9: defs only; the DoE SENDs WL-RUN )
: WL-RUN 42 SEED 3 10 TRIANGLE-WAVE 7777 SEED RUN-ASYM
54321 SEED RUN-SAW RUN-SAW RUN-SAW ;
: WL-DONE-ARGS S" MU-DONE" S" Hera" ;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+20 -6
View File
@@ -114,15 +114,29 @@ void vm_physics_charge(VMUuid vm_id);
/**
* vm_physics_work_heat_of - Cumulative heat a VM has pulled in by working
*
* FABRIC-3.8.md §3.13.7, ruling C-4 (β), Captain Bob 2026-09-23: the sum of
* every transfer vm_physics_charge() actually moved INTO this VM -- heat
* earned by its own work, independent of any structural endowment (Hera's
* initial Q48_ONE). This is the quantity the switch decision compares
* ("coolest VM with work" = least work heat). Only grows; 0 for an unknown
* or dead VM.
* FABRIC-3.8.md §3.13.7, ruling C-4 (β), Captain Bob 2026-09-23: heat
* earned by the VM's own work -- the charge vm_physics_charge() assessed at
* each of its beats (beats x slope, in the charge carry's sub-unit scale),
* whether or not the rest of the fleet held heat to move -- independent of
* any structural endowment (Hera's initial Q48_ONE). This is the quantity
* the switch decision compares ("coolest VM with work" = least work heat).
* Never decreases, except that it may be raised by
* vm_physics_work_heat_floor(). 0 for an unknown or dead VM.
*/
uint64_t vm_physics_work_heat_of(VMUuid vm_id);
/**
* vm_physics_work_heat_floor - "Floor on contact" (Captain Bob, Stage H)
*
* Raise vm_id's work heat to floor_q48 if it is below it; never lowers it.
* Called when a VM that had no work gains some (sk_vm_switch_signal_note_
* work_gained()), with the lowest work heat among the VMs that currently
* have work -- so a newly-busy VM joins the running set level with its
* floor instead of at whatever it last had (0 for a new VM), which would
* otherwise let it run alone until it "caught up."
*/
void vm_physics_work_heat_floor(VMUuid vm_id, uint64_t floor_q48);
/**
* vm_physics_tick - Heartbeat-gated inference pass
*
@@ -150,6 +150,15 @@ int sk_vm_switch_signal_take_decision_due(void);
*/
struct VM *sk_vm_switch_decide(struct VM *self, int self_competes);
/* Stage H, "floor on contact" (Captain Bob, 2026-09-23): vm_id just gained
* work (kernel_hermes.c: its queue went from empty to one message). If it
* had none before -- not running, not parked mid-task -- raise its work
* heat to the lowest work heat among the VMs that have work now (the one
* running and every eligible participant). A new or long-idle VM thus
* joins the busy set level with its floor, rather than at 0 and running
* alone until it "caught up" with VMs that have worked since boot. */
void sk_vm_switch_signal_note_work_gained(VMUuid vm_id);
/* Reap one participant marked pending_reap (a WIREBIND identity whose
* device detached while it was parked), if any. Call only at a safe point
* (checkpoint, trampoline, idle point) -- same contract the old Stage 3
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+25 -11
View File
@@ -68,15 +68,16 @@ typedef struct {
* away, so a one-beat charge (slope < 1 unit)
* still moves heat once enough beats accrue */
uint64_t work_heat_q48; /* FABRIC-3.8.md §3.13.7, ruling C-4 (β), Captain
* Bob 2026-09-23: cumulative heat this VM has
* pulled in through its OWN per-beat charges --
* heat earned by working. The switch decision
* Bob 2026-09-23: heat earned by working -- the
* charge assessed at each of this VM's own
* beats (sub-unit scale), whether or not it
* could be moved; raised to the busy set's
* floor when the VM gains work (Stage H,
* "floor on contact"). The switch decision
* compares this, not execution_heat_q48, so
* Hera's structural endowment (all of Q48_ONE
* at init) never counts against her. Only ever
* grows; a record of transfers that already
* happened, not heat of its own (fleet K is
* unaffected). */
* Hera's structural endowment never counts
* against her. Bookkeeping, not heat of its
* own: fleet K is unaffected. */
} VMPhysics;
typedef struct vm_physics_node {
@@ -388,6 +389,15 @@ void vm_physics_charge(VMUuid vm_id)
if (!target || !target->physics.is_live) return;
/* §3.13.7 (β), refined at Stage H (Captain Bob, "floor on contact"):
* work heat accrues the charge each beat was ASSESSED, in the carry's
* own sub-unit scale -- not what could actually be moved. Counting
* only moved heat left a busy VM at 0 whenever the rest of the fleet
* held nothing to pull (seen live: Hera busy-waiting in the DoE never
* yielded). This is work done, beats x slope, independent of who holds
* heat. */
target->physics.work_heat_q48 += fleet_transfer_slope_q48;
target->physics.charge_carry += fleet_transfer_slope_q48;
amount = target->physics.charge_carry >> 16;
if (amount == 0) return;
@@ -419,9 +429,6 @@ void vm_physics_charge(VMUuid vm_id)
* vanishing. Conservation is unaffected either way -- only what
* vm_physics_transfer() actually moved ever changed any heat. */
target->physics.charge_carry += (moved_total - moved) << 16;
/* §3.13.7 (β): what this VM's own work actually pulled in. */
target->physics.work_heat_q48 += moved;
}
uint64_t vm_physics_work_heat_of(VMUuid vm_id)
@@ -431,6 +438,13 @@ uint64_t vm_physics_work_heat_of(VMUuid vm_id)
return n->physics.work_heat_q48;
}
void vm_physics_work_heat_floor(VMUuid vm_id, uint64_t floor_q48)
{
vm_physics_node_t *n = vm_physics_find(vm_id);
if (!n || !n->physics.is_live) return;
if (n->physics.work_heat_q48 < floor_q48) n->physics.work_heat_q48 = floor_q48;
}
/**
* l8_regime_modulation_q16 - Read-only Q16 multiplier from Hera's own L8
*
@@ -269,6 +269,46 @@ VM *sk_vm_switch_decide(VM *self, int self_competes) {
return best;
}
/* Stage H, "floor on contact" (Captain Bob, 2026-09-23). See the header. */
void sk_vm_switch_signal_note_work_gained(VMUuid vm_id) {
VM *current = sk_vm_switch_current_vm();
VM *mama = (VM *)sk_get_mama_vm();
VMRegistryEntry e;
VM *v;
uint64_t floor_q48 = 0;
int have = 0, i;
if (capsule_vm_registry_get(vm_id, &e) != 0 || !e.vm_ptr) return;
v = (VM *)e.vm_ptr;
/* Only a VM that had NO work gains some here: not the one running, and
* not one parked mid-task (either already had work, and keeps its own
* work heat). */
if (v == current) return;
if (v->native_stack_saved_sp != 0 && v->frames.count > 0 &&
v->frames.entries[v->frames.count - 1].kind != VM_FRAME_IDLE) return;
/* The floor: the lowest work heat among the VMs that have work right
* now -- the one running, and every other eligible participant. */
if (current) {
floor_q48 = vm_physics_work_heat_of(current->stadium_vm_id);
have = 1;
}
for (i = 0; i < g_slot_count; i++) {
VMRegistryEntry o;
VM *ov;
uint64_t heat, stamp;
if (vm_uuid_equal(g_slots[i].vm_id, vm_id)) continue;
if (capsule_vm_registry_get(g_slots[i].vm_id, &o) != 0) continue;
ov = (VM *)o.vm_ptr;
if (!ov || ov == current || o.pending_reap) continue;
if (o.state == VM_STATE_DEAD || o.state == VM_STATE_STILLBORN) continue;
if (!candidate_standing(ov, mama, g_slots[i].parked_stamp, &heat, &stamp)) continue;
if (!have || heat < floor_q48) { floor_q48 = heat; have = 1; }
}
if (have) vm_physics_work_heat_floor(vm_id, floor_q48);
}
void sk_vm_switch_reap_pending(void) {
VM *current = sk_vm_switch_current_vm();
int i;
+1
View File
@@ -536,6 +536,7 @@ int sk_hermes_send_one(VMUuid from, VMUuid to, uint32_t type, uint32_t channel_i
* the switch decision told something changed -- the recipient may now
* be the coolest VM with work. */
msg->wait_stamp = sk_vm_switch_signal_next_stamp();
if (q->count == 1) sk_vm_switch_signal_note_work_gained(to); /* Stage H floor */
sk_vm_switch_signal_note_mail();
return 0;
+22 -1
View File
@@ -1213,6 +1213,19 @@ int sk_vm_owns_outermost_frame(VM *vm) {
vm->mode != MODE_COMPILE;
}
/* Stage H (FABRIC-3.8.md §3.9): 1 if the rest of the input holds no more
* words -- the same whitespace set vm_parse_word() skips, so "exhausted"
* means exactly "the next vm_parse_word() would return 0". */
static int vm_input_exhausted(const VM *vm) {
size_t p = vm->input_pos;
while (p < vm->input_length) {
char c = vm->input_buffer[p];
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') return 0;
p++;
}
return 1;
}
void vm_interpret(VM* vm, const char* input)
{
vm_interpret_kind(vm, input, VM_FRAME_INTERPRET);
@@ -1276,7 +1289,15 @@ void vm_interpret_kind(VM* vm, const char* input, uint32_t kind)
* is a clean switch point too -- without it, a payload made only
* of primitives (no colon word, so no execute_colon_word()
* checkpoint) could never be displaced. Same ownership gate. */
if (!vm->error && !vm->abort_requested && sk_vm_owns_outermost_frame(vm)) {
/* Stage H (2026-09-23): not after the LAST word. A VM with nothing
* left to interpret isn't mid-task -- its trampoline decides the
* moment this returns -- and switching it out here would park it
* "mid-task" with no work left, which KILL (rightly) refuses. Seen
* in design for the DoE's completion notice: a payload whose final
* word is a SEND to Hera sets decision-due, and this checkpoint
* would otherwise act on it one word too late to matter. */
if (!vm->error && !vm->abort_requested && sk_vm_owns_outermost_frame(vm) &&
!vm_input_exhausted(vm)) {
sk_vm_switch_checkpoint(vm);
}
#endif