Decided directly on request, no code written. "ACLs -> EXPIRE" isn't
wrong in spirit but was aimed at the wrong unit: acl_ttl-hits-zero
always renews (never revokes), so it can't carry EXPIRE's
residency-ending meaning. The unit that actually has a real lifetime
and should be revoked is a zuse superuser session (Phase 8, not yet
built) -- authenticate, hold elevated privilege for a bounded time,
then actually drop back to non-zuse.
Resolves to: admit the session (not a per-word ACL entry, which would
be redundant with item 4.1's existing word patrons) as the Stadium
patron, once Phase 8 exists. Not in scope now -- there is no session
to admit regardless of any other choice, and building Stadium's
missing generic ttl-decrement/reap mechanism ahead of its only real
consumer would be speculative infrastructure, the same shape of
premature build the no-stubs standard exists to prevent, just
inverted. EXPIRE stays explicitly deferred until Phase 8 lands, with
a concrete trigger for revisiting it -- not abandoned, not left
ambiguous.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
Same fix as DELIVER, on request. COOL is real and live for both words
(item 4.1) and VMs (this session) -- stadium_evict()'s own universal
reservoir credit is the whole of what "cooling off the floor" means
for both, no extra payload action needed. stadium_dispatch()'s COOL
case now prints the departing patron's identity (word_id for a word,
0 -- the patron-zero convention -- for a VM) instead of "(stub)".
Verified live: both shapes fired correctly on the same boot --
"COOL identity=0" at Hermes's/Artemis's own explicit channel-eviction
self-test and again at their VM-patron eviction at PARITY:KILL,
"COOL identity=1" at a second channel eviction -- conservation intact
throughout. Clean zero-warning compile and clean boot with
conservation intact on all three architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
Investigated on request. acl_ttl (DictEntry, per-word ACL-RECHECK
amortization) and StadiumPatronHeader.ttl (residency countdown) are
different mechanisms wearing the same name -- ACL-RECHECK always
renews (allow=1, fresh ttl), never revokes, so it doesn't resemble a
reap event at all. Separately, StadiumPatronHeader.ttl is completely
inert across the whole codebase: every candidate constructor sets it
to 0, nothing ever reads or decrements it -- the generic TTL-expiry
mechanism EXPIRE would fire from doesn't exist in Stadium's own engine
yet, a gap one level deeper than "ACL isn't wired to Stadium."
Recorded four open questions that need a real decision before any
code: whether "ACL patron" is even the right model, what unit would
be admitted (redundant per-word vs. a session-scoped patron once
Phase 8 PKI/zuse work lands), whether building Stadium's missing
generic ttl-reap mechanism is in scope here, and what the reap action
should actually do given ACL policy never revokes today.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
Words have been fully migrated and live via stadium_word_dispatch()
since item 4.1 -- this line just never got updated. Small, independent
doc fix flagged in FABRIC-3.md's punch list, addressed on request.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
Re-scoped on request. capsules/hermes/init.4th's MSG-ALLOC already
admits every message onto Stadium with SB-DELIVER, and MSG-FREE-NODE
(called from both MSG-ACK-LAST and heat-driven MSG-REAP) already
evicts it -- "behaviour=DELIVER (stub)" has been printing on boot logs
since at least 2026-08-05. The earlier "zero consumer, needs
substantial Hermes lifecycle mapping work" framing was wrong,
carried over unverified from FABRIC.md's old "open, not resolved" note
about which Hermes event maps to DELIVER vs. EXPIRE -- item 4.2
already answered that in code without the prose catching up. Same
documentation-drift class as the stale ONTOLOGY.md words note and the
earlier glibc misattribution.
Checked whether the dispatch body needed a real payload action the way
MIGRATE did: MSG-DELIVER (the FORTH word) already runs the actual
delivery (VM-EXEC of the payload) before eviction, decoupled from
Stadium reap -- so by dispatch time delivery is already done, same
shape as COOL, which needs no extra action beyond stadium_evict()'s
own universal reservoir credit.
Fix: stadium_dispatch()'s DELIVER case now prints the departing
message's real identity (DELIVER msg_idx=N, same shape as MIGRATE's
lbn= print) instead of a misleading (stub) label. COOL is in the
identical situation (real for both words and VMs) but left as-is --
out of scope for this pass, noted in stadium.c's own comment.
Also confirmed EXPIRE (ACL) is genuinely unscoped, not stale docs like
DELIVER turned out to be -- zero Stadium involvement anywhere in
ACL.4th/acl_recheck()/the ACL design doc. Stays open pending real
design decisions.
Verified live via a forced MSG-SEND/MSG-DELIVER-ALL/MSG-ACK-LAST
sequence from Hermes's own REPL context ("USE" now works after the
previous fix): "Stadium: dispatch cell=73653 behaviour=DELIVER
msg_idx=1". Clean zero-warning compile and clean boot with
conservation intact on all three architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
capsule_vm_kill() had zero Stadium involvement (vm_cleanup()/sf_free()
only), and child-VM birth only ever called stadium_grant_quota() -- a
resource pool for the VM's own future word/block patrons, never
stadium_admit() for the VM itself. stadium_birth_hera() looked like a
precedent but admits Hera into her own quota as a permanently pinned
cell 0, which can never reach stadium_evict() -- not a working example
of COOL firing for a VM.
Adds size_t stadium_patron_cell to VMRegistryEntry. At birth, right
after the existing stadium_grant_quota() call, admits a candidate into
the new VM's own quota mirroring stadium_birth_hera()'s shape
(identity=0, mass=1, behaviour=COOL) but deliberately unpinned --
pinning would need a new "unpin" primitive (none exists) to ever evict
it later, and unpinned costs nothing since nothing wires COOL's
dispatch body to kill anything; the worst case of an unrelated natural
eviction is stale bookkeeping, tolerated the same way
stadium_word_forget() already tolerates staleness elsewhere. At
capsule_vm_kill() and capsule_vm_kill_all_nonmama(): stadium_evict()
the tracked cell if still resident, silently tolerating refusal
(already gone). stadium_dispatch()'s COOL case needed no new payload
body -- same as it already is for words, where COOL has no defined
extra action beyond stadium_evict()'s own universal reservoir credit.
On investigation this turned out not to be entangled with the
still-iterating Tripod/Zuse/messaging vision after all -- birth and
kill already funnel through two single choke points, so the earlier
deferral (previous commit) was overcautious.
Verified live: a second, new "Stadium: dispatch cell=... behaviour=
COOL" now fires immediately before every PARITY:KILL line, for both
Hermes and Artemis, distinct from the pre-existing COMMON-CH
word-eviction self-test's own COOL print. Conservation
(resident_sum + reservoir == Q48_ONE) intact throughout. Clean
zero-warning compile and clean boot on all three architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
capsules/lib.4th:13-14 defined ": USE ( addr u -- ) EXEC ;" and the
same for RUN, shadowing the C-registered mama_word_use()/RUN primitives
(CLAUDE.md names both, with BIRTH, as untouchable C primitives) with an
unrelated "load/exec a capsule" meaning. This broke the interactive
USE-based VM-redirect (S" Artemis" USE printed "EXEC: failed: Artemis"
instead of redirecting), discovered while chasing FABRIC-3.md's
live-MIGRATE verification.
Traced every real caller before touching anything: RUN's alias was
dead code, never called anywhere as bare RUN. USE's alias had exactly
one real caller -- capsules/hermes/init.4th:397, intentionally
exploiting the shadow to load common:msg.4th right after lib.4th
itself loaded. Both aliases were pure EXEC wrappers with zero added
behavior, so this deletes both definitions outright and switches the
one real call site (plus its matching doc comment in
capsules/common/msg.4th) to call EXEC directly. No new names invented,
the C primitives untouched.
Verified live: Hermes still births and her COMMON-CH-eviction
self-test (depends on common:msg.4th having loaded) still passes;
interactively, S" Artemis" USE now correctly redirects the REPL and
prints "USE: now using Artemis". mkcapsule --lint clean (31/31).
Clean compile and clean boot with Stadium conservation intact
(resident_sum + reservoir == Q48_ONE) on all three architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
Confirmed the real MIGRATE dispatch fires live: a temporary boot probe
(STADIUM-ADMIT + STADIUM-EVICT against the live Artemis VM, inserted
into the existing 4.6 self-test and reverted immediately after capture)
produced "Stadium: dispatch cell=63257 behaviour=MIGRATE lbn=100" with
blk_flush(100) firing and zero error -- closes the honest gap left open
in the previous commit. Interactive flooding alone couldn't reach this:
Hera's reservoir sits at the Q48_ONE/3 floor from boot self-tests, so
block-touch candidates pull 0 heat and can never out-density an
existing resident, a pre-existing reservoir-floor/eviction interaction
unrelated to this pass.
Also reports (not fixes, per CLAUDE.md) a real dictionary-shadowing bug
found while chasing this: capsules/lib.4th:13 redefines USE as EXEC,
shadowing the C primitive mama_word_use() (REPL VM-redirect) with an
unrelated capsule-loading meaning -- same for RUN at lib.4th:14. Same
bug class as the K-PUSH dictionary-shadowing issue.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
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
Investigated whether stadium_admit()'s mass==1 refusal blocks block-patron
Stadium admission -- it doesn't: stadium_word_dispatch()'s real candidate
construction confirms Stadium cells carry identity/heat/bookkeeping only,
never the resident's actual content, so a block patron (identity=LBN,
payload unused) fits the same pattern words already use. The real gap is
just that no LBN->cell_index residency map or touch-on-access hook exists
yet -- real, scoped, buildable work, not a blocker.
Deferred VM-COOL pending the Tripod final-shape vision Captain Bob laid
out (thumbdrive minting, one-time Zuse fuse-blow, messaging-only inter-VM
interaction, polymorphic block-boundary behavior) -- recorded in a new
§D so near-term Stadium work doesn't ignore it, without treating a
one-sentence vision as a ready-to-implement spec.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
FABRIC-2.md closed archival at ~4,400 lines / 51 open items, same reasoning
FABRIC.md itself was closed for at 7,595 lines -- continuing to append made
still-open work hard to find. All 51 open items carried forward into
FABRIC-3.md's new Section A, verified complete via programmatic diff against
the source (49 unique + 2 confirmed pure duplicates from FABRIC-2.md's own
F.3 cross-reference section, not dropped content). .claude/CLAUDE.md's
pointer note updated to name FABRIC-3.md as current.
New Section B: full audit of stadium_dispatch()'s four behaviour stubs
(MIGRATE/DELIVER/EXPIRE/COOL), triggered by investigating "words/VMs/blocks/
messages should all be on the same engine". Found the picture is more
nuanced than "everything's a stub" -- words are already fully live via a
separate bespoke mechanism (stadium_word_dispatch(), wired into vm_core.c's
real word-execution path, item 4.1), contradicting ONTOLOGY.md's stale
"not yet migrated" claim (flagged for a follow-up fix). MIGRATE (blocks)
and VM-COOL are genuinely stub with zero consumers; DELIVER (Hermes) and
EXPIRE (ACL) are substantial, undecided subsystem integrations FABRIC.md
itself already flagged as open, not touched here.
New standing rule, saved as memory feedback_no_stubs_or_todos.md: stub
implementations and TODO placeholders are never acceptable in this
workflow, in any language, ever -- triggered by finding stadium_dispatch()'s
stub handlers during this investigation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn