diff --git a/FABRIC.md b/FABRIC.md index 58f02e3..fa5830c 100644 --- a/FABRIC.md +++ b/FABRIC.md @@ -3386,6 +3386,32 @@ document and committing that amendment as its own item.* > the hosted build's layout must stay untouched outside the `__STARKERNEL__` guard. > Set once, at VM creation, from the same `VMRegistryEntry.vm_id` the birth path > already assigns (`capsule_birth.c`) — not invented at the dispatch call sites. + > 4. **Primitive surface grows from five to seven.** Found while reading Hermes's actual + > implementation (`capsules/hermes/init.4th`): `MSG-COOL-ALL`/`CH-COOL-ALL` (blocks + > 4108/4114) mutate each live node's own heat field in place every `HERMES-TICK`, and + > `MSG-TOTAL-HEAT`/`CH-TOTAL-HEAT` sum it. None of the original five primitives expose + > a resident cell's own `heat` field at all — only admission, eviction, and the calling + > VM's reservoir. Ruled: two more primitives, same implicit-self discipline as the + > original five (cell must belong to the calling VM's own quota): + > ``` + > STADIUM-HEAT@ ( cell -- heat ) + > STADIUM-HEAT! ( new-heat cell -- ) + > ``` + > `STADIUM-HEAT!` reconciles the reservoir delta atomically in C — pulls from the + > calling VM's reservoir if `new-heat` is higher than current (refusing, leaving heat + > unchanged, if the reservoir can't cover it), pushes back if lower — the same shape as + > `stadium_word_dispatch()`'s own cooling code. Conservation is never left to FORTH to + > get right by remembering to call `STADIUM-RES-PULL`/`-PUSH` itself; a single call is + > both the write and the correct accounting. Serves two callers: a cooling tick + > (`heat × Q-DECAY`, replacing `MSG-COOL-ONE`'s in-place multiply) and a floor-refresh + > (`COMMON-INIT`/`HERMES-TICK` reset `COMMON-CH`'s heat to a fixed `Q.1/3` unconditionally, + > not a decay — needs the same delta-reconciling write, just with a different target + > value). `STADIUM-HEAT@` alone serves `MSG-TOTAL-HEAT`/`CH-TOTAL-HEAT`'s summation and + > `MSG-REAP`/`CH-REAP-SAFE`'s heat-reached-zero check. Cooling cadence stays entirely in + > Hermes's own FORTH `HERMES-TICK` loop (rewritten to call these, not a new C-side + > per-tick sweep) — matches `HERMES.md`'s language constraint and the fact that + > `HERMES-TICK` already owns this loop; nothing about moving the heat storage changes + > who decides when to cool. > > **Open, surfaced not resolved:** mapping Hermes's message/channel lifecycle onto the > closed `STADIUM_BEHAVIOUR_*` set (`MIGRATE`/`DELIVER`/`EXPIRE`/`COOL`) — `DELIVER` and @@ -3399,7 +3425,7 @@ document and committing that amendment as its own item.* > implementation; do not resolve by assumption. > > *Done when:* - > - The five `STADIUM-*` FORTH primitives exist, are kernel-only (not in the shared/ + > - The seven `STADIUM-*` FORTH primitives exist, are kernel-only (not in the shared/ > vendored word set), and are exercised by at least one Hermes word each. > - `stadium_owner[idx]` is written correctly on both the free-list-pop and > eviction-fallback paths in `stadium_admit()`, verified by a resident cell's @@ -3423,7 +3449,7 @@ document and committing that amendment as its own item.* > - The POST suite (regression gate per §10) passes. > - **The effort number is recorded explicitly** — per §10, "what Hermes costs is the > multiplier for everything else." Report at minimum: wall-clock/session time spent, - > lines changed (FORTH + the five-primitive C surface, split out), and file count + > lines changed (FORTH + the seven-primitive C surface, split out), and file count > touched, so 4.3/4.4 can be estimated from a real data point rather than guessed. > - All three architectures boot to `ok>`/`zuse)ok>` with logs under `logs/`, and > Hermes's own conservation check (K≡1.0 across messages + channels + reservoir) closes