FABRIC.md: resolve four of five §17.7 questions -- Stadium heat already conserved

The Stadium cell's heat field (stadium.h:64, item 3.1) was already declared
Q48.16 conserved share of 1.0, citing §19.1, before this section was reopened.
L0 already has a real conservation mechanism (items 3.4/3.5 consume it); it
has just never been fed. execution_heat and Stadium heat are two different
fields with two different jobs -- item 4.1 feeds the second, not converts the
first. Resolves the promotion-threshold, dict_hash-baseline, parity, and
new-loop questions on that basis; states an explicit one-governor-per-build
rule mirroring §17.3. The per-dispatch transfer rule and its cost remain
open and still block item 4.1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-05 10:35:05 -04:00
co-authored by Claude Sonnet 5
parent 6d3d6e5ea6
commit abb1d92190
+74 -52
View File
@@ -1078,66 +1078,88 @@ that matters. The total stays fixed; only the partition shifts.
Decide how big the Stadium is at runtime. Do not decide what an entry is, or how entries
are addressed, at runtime.
### 17.7 Word-level heat conservation — LEANING, paper only, blocks item 4.1
### 17.7 Word-level heat conservation — LEANING, one question open, blocks item 4.1
Item 4.1 (hot words onto the Stadium, §25.5) needs `DictEntry.execution_heat` converted into
the Stadium's Q48.16 `heat` field. The obvious move — `q48_from_u64(execution_heat)`, a pure
representation change, no semantics touched — was proposed and **rejected 2026-08-04**:
Captain Bob wants real conservation for word heat too, on the same footing as §19.1's
fleet-level invariant, not just a unit conversion.
Item 4.1 (hot words onto the Stadium, §25.5) needs word patrons to carry a Stadium `heat`
share. The obvious move — `q48_from_u64(execution_heat)`, a pure representation change
grafted onto `DictEntry.execution_heat`, no real conservation — was proposed and **rejected
2026-08-04**: Captain Bob wants real conservation for word heat, on the same footing as
§19.1's fleet-level invariant, not just a unit conversion of the existing counter.
This is open. It is *not* a smaller version of §19.1 — it conflicts with two things already
load-bearing, and both have to be resolved on paper before any code touches Loop #1:
**Corrected premise (2026-08-05): this was never a choice between converting
`execution_heat` or leaving it alone.** `include/starkernel/vm/stadium.h:64` already declares
the Stadium cell's `heat` field as `Q48.16, conserved share of 1.0 (§19.1)` — written when
item 3.1 was done, before this section was reopened. Items 3.4 (density = heat ÷ mass) and
3.5 (admit if denser than the least-dense resident) already consume it as a real, relative,
conserved quantity. **L0 already has a genuine conservation mechanism; it has just never
been fed, because nothing has been admitted to the Stadium yet.** `execution_heat` and
Stadium `heat` are two different fields with two different jobs. Item 4.1's task is to feed
the second one from word dispatch, not to convert the first one into it. That reframing
resolves four of the five questions this section left open:
1. **The promotion threshold breaks.** `hotwords_cache_lookup()` promotes a word on
`execution_heat > HOTWORDS_EXECUTION_HEAT_THRESHOLD` (`50`, absolute, against an unbounded
counter — `physics_hotwords_cache.h:87`). A conserved share of `Q48_ONE` (65536) split
across however many words are resident cannot be compared against `50` in any consistent
way. §17.3, decided the same day this question was raised, says plainly "execution heat
(Loop #1) is what promotes a word" — treating the existing counter, and its absolute
threshold, as the mechanism. Conservation needs a *relative* trigger instead (density-rank
within the resident set, margin above the resident median, something else) — a real
change to Loop #1's promotion rule, not a units change.
2. **`dict_hash` moves.** `capsule_dict_hash_hook()` hashes exactly two things per entry:
name and `execution_heat`. That hash is the parity baseline every item this phase has been
verified against. If `execution_heat`'s value now comes from a transfer instead of an
increment, it changes on every dispatch for a different reason than before, and the
baseline moves in the same commit that introduces the change. The design has to say
explicitly what happens to parity comparisons made before vs. after — not leave it
implicit.
1. ~~**The promotion threshold breaks.**~~ **RESOLVED — it doesn't, because nothing replaces
it.** `HOTWORDS_EXECUTION_HEAT_THRESHOLD` belongs to the old cache mechanism, and §17.3's
resolution already retires that mechanism's *effect* under `__STARKERNEL__` regardless of
this question. Item 4.1 admits by item 3.5's rule instead — density relative to the
least-dense resident — which is already the relative trigger this bullet said conservation
would require, and it is already built.
2. ~~**`dict_hash` moves.**~~ **RESOLVED — it doesn't move, because `execution_heat` is not
touched.** `capsule_dict_hash_hook()` keeps hashing name and `execution_heat` exactly as
today; the counter keeps incrementing and decaying exactly as today. Stadium `heat` is not
part of `dict_hash` and item 4.1 does not need to add it there. No baseline discontinuity,
no "before vs. after" comparison problem — there is nothing to reconcile.
3. **What transfers, from whom, on every dispatch — and its cost.** **Still open.** This is
real work, not dissolved by the reframing above: on a kernel-build word dispatch, some
Q48.16 amount has to move toward the touched word's cell from the rest of the VM's
resident pool — the same shape as `vm_physics_transfer()`'s clamped subtract/add at the
fleet level, or the proportional redistribution at `capsule_vm_physics.c:334`, but nobody
has picked the exact rule or measured its cost on this path yet. This sits in both the
hosted and kernel dispatch primitive today (`physics_execution_heat_increment()`), but
under the resolution below the *new* transfer is kernel-only, alongside — not replacing —
that existing increment. Still blocks item 4.1's code.
4. ~~**What happens to `dict_hash` and parity comparisons that predate this change.**~~
**RESOLVED by #2 above** — nothing predates a change that isn't being made to the hashed
field.
5. ~~**A new "L9" loop, or composes into an existing one.**~~ **RESOLVED — composes into L0.**
The Stadium engine (§18) already owns a conserved heat wire per cell; item 4.1 populates
that existing wire for the word patron kind. It is not a new loop and needs no name.
There's a third thing underneath both: real conservation means the *increment itself* becomes
a *transfer* — heat pulled toward the touched word from the rest of the resident set, or from
the full dictionary, on every single word dispatch. That is the hottest path in the entire VM,
in both hosted and kernel builds, and Loop #1 is one of the seven feedback loops this project
has a formal-verification claim about (0.000% CV across 90 runs). This does not get touched
speculatively.
**What sums to what, and admission semantics — settled by code already written, not
re-derived here:** per-VM Stadium, summing to 1.0 across every patron resident in that VM's
quota (words, blocks, ACLs, messages together, not a word-only sub-pool) — matching §21.4's
"K conserved here, independently" and the `stadium.h:64` field comment. No reset on
admit/evict: the sum stays invariant across *any* call per §19.1's own conservation check, so
admission is itself a transfer, not a reset — mirroring `capsule_vm_physics.c`'s VM-birth
pattern, where a new patron starts at 0 (or a starter share) and is topped up by transfer,
never by manufactured heat.
**Captain Bob's own first sketch (2026-08-04, to be developed further, not yet a ruling):** a
quantity between 0 and 1, possibly derived from something that already exists as a DoE output
parameter, kept conserved by its own dedicated loop rather than folded into an existing one —
explicitly *not* gated by L8 the way L1L7 are (§18.1's "L8 cannot be gated... L0 cannot be
gated" bookend structure is the closest existing precedent for an always-on, ungated loop).
`stale_word_ratio` (`doe_metrics.c:273`, `stale_word_count / word_count`, already bounded
[0,1], already flowing into the DoE CSV) is one candidate for "something that already exists"
worth checking against when this gets picked back up — not proposed as the answer, just the
nearest existing fit to "0 to 1, already measured."
**One governor per build — states explicitly what closes the §11/§25.5 "never two live heat
mechanisms" gap:**
**Open, to settle before item 4.1 writes any Loop #1 code:**
- **Kernel builds:** `execution_heat` stops being a *decision input* once item 4.1 lands — it
keeps incrementing, decaying, and getting hashed exactly as today (ENTROPY@, ACL words,
diagnostics, `dict_hash` all keep working unchanged), but it no longer governs residency.
Stadium `heat`/density governs Stadium residency instead.
- **Hosted builds: unchanged**, per §17.3's own resolution — no Stadium exists there,
`execution_heat` keeps governing the old cache exactly as it does today.
- What sums to what: per-VM over its resident set? Over the full dictionary? Does the sum
reset on residency change (admit/evict), or is that a different mechanism wearing
conservation's name?
- What replaces the absolute promotion threshold, given a relative/conserved quantity can't
be compared against a fixed constant the way `execution_heat > 50` is today.
- What transfers, from whom, on every dispatch — and its cost, given this sits on the hottest
path in the VM, before it is approved for the dispatch loop in either build.
- What happens to `dict_hash` and to parity comparisons that predate this change.
- Whether this is really a new, ungated loop (a candidate "L9," by the naming scheme in
§18.1) or something that composes into an existing one — not decided here.
This is the same per-build split §17.3 already ruled for the cache itself; word-level heat
conservation follows it rather than inventing a second shape.
**Nothing in this section authorizes touching `execution_heat`'s current increment
behaviour, Loop #1, or `dict_hash` before this section reads DECIDED.**
**Open, to settle before item 4.1 writes any transfer code:**
- The exact per-dispatch transfer rule (pull from a proportional share of current residents?
from a designated "unclaimed" pool representing non-resident dictionary words? something
else) and its measured cost on the dispatch path, kernel build only.
- Whether `rolling_window_seed_hotwords_cache()`'s POST warm-start
(`rolling_window_of_truth.c:786`) needs a Stadium-side counterpart to seed word patrons'
initial `heat` distribution — noted here as the natural seeding site, not designed.
**Nothing in this section authorizes touching the per-dispatch transfer rule, or wiring
`stadium_admit`/`stadium_dispatch` for words, before the open bullet above reads DECIDED.
`execution_heat`'s current increment/decay behaviour and `dict_hash` are explicitly out of
scope for item 4.1 — this section's earlier ban on touching them no longer applies, because
nothing here proposes touching them.**
---