Stadium: real block-patron admission + MIGRATE dispatch (FABRIC-3.md §B)

stadium_admit()'s mass==1 refusal looked like a hard blocker for 1024-byte
blocks, but stadium_word_dispatch()'s real candidate construction proves
Stadium cells carry pure identity/heat/bookkeeping, never the resident's
actual content -- a block patron follows the same shape (identity=LBN,
payload unused), so this was real, scoped work, not a case for stubbing.

New stadium_blocks.h/.c mirror stadium_words.c's admission/cooling shape,
keyed by (quota_slot, lbn) in a fixed-capacity open-addressing hash table
(tombstone deletion) instead of a dense array, since LBN space isn't
densely bounded like word_id. Wired into block_word_block()/buffer()/
update() (block_words.c), __STARKERNEL__-guarded. stadium_dispatch()'s
MIGRATE case now calls blk_flush(lbn) for real instead of printing
"(stub)". Three new Kconfig constants (STADIUM_BLOCK_HEAT_QUANTUM/
STADIUM_BLOCK_COOL_RATE_Q48/STADIUM_BLOCK_TRACK_CAP_MULT) mirror the
word-patron ones, same three-layer wiring.

VM-COOL/DELIVER/EXPIRE stay explicit punch-list items -- VM-COOL
deferred pending the still-iterating Tripod/Zuse/messaging vision,
DELIVER/EXPIRE are their own future subsystem integrations per
FABRIC.md's own "open, not resolved" notes.

Verified clean compile (zero warnings) and clean boot to REPL with
conservation intact (resident_sum + reservoir == Q48_ONE) on all three
architectures (amd64/aarch64/riscv64); BLOCK/BUFFER touches exercised
live from the REPL with no crash; a 22,000-distinct-block flood loop
against an artificially shrunk Stadium ran clean under heavy admission
load. A live MIGRATE console fire was not directly observed this
session (root-caused to a pre-existing reservoir-floor/density-eviction
interaction unrelated to this change, documented in FABRIC-3.md) --
flagged as an honest follow-up, not silently claimed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
This commit is contained in:
Robert Allan James
2026-08-25 23:28:59 -04:00
co-authored by Claude Sonnet 5
parent ecdb547786
commit c7c9332321
17 changed files with 27731 additions and 13 deletions
+29 -6
View File
@@ -300,12 +300,35 @@ other three become honest, explicit punch-list items instead of being touched sp
sites). Not yet built — this is real, scoped, buildable work, not a stub-around candidate.
**Still open**, plan to be presented before implementation per the no-stubs/no-early-coding
conventions.
- [ ] Wire `STADIUM_BEHAVIOUR_MIGRATE` in `stadium_dispatch()` to call
`blk_subsys_relocate_block()` for real, once block-patron admission (above) exists. On
reap, `MIGRATE`'s real action may just be `blk_flush(lbn)` (write-back, per `FABRIC.md`
§17.2's own wording: "reap event is migration back to Artemis") — `blk_subsys_relocate_block()`
is a separate primitive for compudynamics-driven mid-residency relocation to a *different*
LBN, not necessarily what fires at ordinary Stadium eviction. Confirm which before wiring.
- [x] **Resolved (2026-08-25): real block-patron admission + real `MIGRATE` dispatch, both
live.** New `stadium_blocks.h`/`stadium_blocks.c` mirror `stadium_words.c`'s shape (Option B
starter-grant admission, redirected Loop #3 cooling, self-healing stale-entry detection) but
key residency by `(quota_slot, lbn)` in a fixed-capacity open-addressing hash table sized off
`stadium_cell_count()` (tombstone-based deletion, since LBN space isn't densely bounded like
`word_id`), not a dense array. Wired into `block_word_block()`/`block_word_buffer()`/
`block_word_update()` (`block_words.c`), `#ifdef __STARKERNEL__`-guarded. `stadium_dispatch()`'s
`MIGRATE` case now calls `blk_flush(lbn)` for real (confirmed `blk_flush()`, not
`blk_subsys_relocate_block()`, is the right primitive — the latter is for compudynamics-driven
relocation to a *different* LBN mid-residency, not ordinary reap write-back). Three new Kconfig
tuning constants (`STADIUM_BLOCK_HEAT_QUANTUM`/`STADIUM_BLOCK_COOL_RATE_Q48`/
`STADIUM_BLOCK_TRACK_CAP_MULT`) mirror the word-patron ones exactly, same three-layer wiring.
**Verified:** clean compile, zero warnings, on all three architectures; clean boot to
`zuse)ok>`/`ok>` REPL on all three, conservation (`resident_sum + reservoir == Q48_ONE`) intact
identically across all three; `BLOCK`/`BUFFER` touches exercised live from the REPL on amd64 and
riscv64 with no crash; a 22,000-distinct-block flood loop (amd64, artificially shrunk to a
20,971-cell Stadium via a one-off smaller `-m` to make quota pressure reachable) ran clean under
heavy admission-path load with no corruption. **Honest gap, not silently claimed:** a live
`MIGRATE lbn=...` console print was NOT directly observed firing in this session. Root cause
traced, not a defect in this work: Hera's reservoir was already sitting exactly at the
`Q48_ONE / 3` floor from the boot-time self-tests before any manual testing began, so every
block-touch candidate pulled 0 heat — and a 0-heat candidate can never be *strictly denser* than
an existing resident, so `stadium_admit()`'s eviction fallback correctly refuses rather than
evicts once the free list is exhausted. This is a pre-existing interaction between the reservoir
floor and density-based eviction (applies equally to word patrons, not something this pass
introduced), not something wrong with the new code. Follow-up: force a live `MIGRATE` fire from
inside a child VM's own REPL context (where the `STADIUM-ADMIT`/`STADIUM-EVICT` diagnostic words
are registered — attempted via `USE` this session, which failed with "EXEC: failed", not yet
root-caused) to directly and deterministically exercise the eviction path with nonzero heat.
- [ ] Scope VM-`COOL`: confirm whether `capsule_vm_kill()`/Tripod's existing VM lifecycle has
any real hook point equivalent to `stadium_evict()`, or needs the same kind of admission
work `MIGRATE` needs. **Deferred (2026-08-25)** per the user's own "we're going to have to