8.6 KiB
Capsules Load Definitions Only — Design Doc
Date: 2026-07-09 (rev a)
Branch: lithosananke
Status: RETRACTED (2026-07-10). This doc's entire premise — that
capsule_exec_payload should stop writing a capsule's Block N content
to the literal block N — is wrong. Captain Bob's direct correction:
"all capsule does is LOAD a block with a given Block xxxxx header to
THAT BLOCK. that's all. They are not ordered in the capsule necessarily."
This doc was implemented (commit e1c3ac01) and then reverted (commits
43d81d49/548062ab) once the correction landed; three-arch Tripod
acceptance re-confirmed identical dict_hash with the original mechanism
restored (ee91280d). write_ramdrive_block and its call site are back
exactly as they were. Kept as a record of a wrong turn, per this repo's
revision-history convention, not deleted. Do not implement anything in
this doc. See CAPSULE-BLOCK-PERSISTENCE-BOUNDARY-FINDING-20260709.md
for the corrected, closed status of the underlying finding.
Author: Captain Bob / Claude Code
Problem, restated from the finding doc
capsule_exec_payload() (src/starkernel/capsule/capsule_loader.c:448)
does two things per parsed block, not one:
1. write_ramdrive_block(current_block_num, block_start, block_len); /* line 484 */
2. exec_block_with_retry(vm, block_start, block_len, current_block_num);
Step 2 is what a capsule loader is for: interpret the block's FORTH text,
compile words into the dictionary. Step 1 is not — it writes the block's
raw content into the live block-device LBN space, keyed by the literal
number in the capsule's own Block N source header, with no boundary
check. CAPSULE-BLOCK-PERSISTENCE-BOUNDARY-FINDING-20260709.md documents
the consequence: every capsule numbered 4000+ (most of them) has that
write land on Artemis's real disk once attached, entirely outside
Artemis's own allocator's knowledge.
Confirmed direction
"let the capsules load definitions only. persistence needed to message will sit and compudynamics will provide the where. logical blocks will start to put the rest of this together"
Three separate claims, each addressed below:
1. Capsules load definitions only
Step 1 (write_ramdrive_block) is removed from capsule_exec_payload.
A capsule's Block N headers go back to being pure source-file
organization — the mkcapsule --lint format check (≤64 chars/line, ≤16
lines/block) and MANIFEST.md/BLOCK_MAP.md's content-addressed
bookkeeping — with no runtime persistence meaning. Capsule execution
becomes exactly what the function's own header comment already claims
for step 2 alone: interpret the payload bytes directly, no block device
touched.
This is a clean removal, not a guess dressed as one — checked, not assumed:
write_ramdrive_block()itself (capsule_loader.c:146) becomes dead code once its one call site is gone, along with the unusedCAPSULE_RAM_OFFSETmacro (capsule_loader.c:51) whose comment already described a scheme (dest = source - CAPSULE_RAM_OFFSET) the code never actually implemented.capsule_clear_blocks()(capsule_loader.c:514) exists only to undo step 1's write — its two call sites (capsule_exec_init,capsule_loader.c:569; the post-Mama-birth cleanup inkernel_main.c:570) become no-ops on nothing and should go too.capsule_load_blocks()(capsule_loader.c:192) — a second, separate function that also callswrite_ramdrive_block— has zero callers anywhere in the codebase (verified:grep -rn "capsule_load_blocks(" src/matches only its own definition and header declaration). Already-dead code, not something this change orphans.- No capsule in the current corpus calls the real FORTH
LOADword against a capsule-written block number — verified by grepping every.4thfile undercapsules/forLOAD; the only matches are substrings inside unrelated word names (FLEET-DOE-WORKLOAD,LOAD-DOE). The "so FORTH can callLOAD Nlater if needed" capability the removed comment describes has no real consumer today.
Net effect: capsule_exec_payload shrinks to the execute-only loop;
nothing in the current capsule corpus observably changes behavior,
because nothing currently depends on the write it's losing.
2. Persistence, when actually needed, is placed — not addressed by convention
A capsule defining MSG-ALLOC no longer implies anything about where a
message physically lives. When an entity genuinely needs to persist
(a Hermes message, eventually), compudynamics decides the placement —
the same role capsule_vm_physics.c already plays for VM heat: a live
mechanism making a runtime decision, not a number an author typed into a
.4th file.
This is new scope for compudynamics, not a capability it has today —
worth stating plainly rather than implying otherwise.
include/compudynamics.h/src/compudynamics.c currently expose tuning
values (CDTuning via cd_tuning_word()/cd_tuning_vm()), not block
placement or allocation. Extending it to decide where a persisted
entity lands is follow-on design work, not yet specified — see Open
questions.
3. Logical blocks are the layer that ties it together
Captain Bob named this as the piece that "puts the rest of this together" but did not specify a mechanism, and this doc does not invent one. What's already on record, factually, from prior design work:
HERMES-MESSAGE-BLOCK-STORAGE-DESIGN-20260708.mdandARTEMIS-BLOCK-PHYSICS-DESIGN-20260708.mdboth name "Logical BAM" — per-VM normalization of physical block-heat accounting so a VM participates correctly in fleet-wide heat conservation — as a real, already-deferred gap (ARTEMIS-BAM-ACCEPTANCE-20260703.md's Phase 1 acceptance left it explicitly unbuilt for Artemis).- The storage doc's confirmed simplification was that Physical BAM and Logical BAM "will look like the same mechanism right now" — a deliberate non-split, not a permanent one.
This session's direction reopens that simplification: "logical blocks" now sounds like the addressing layer between "an entity needs to live somewhere" and "here is the physical LBN," which is a bigger role than "normalization for fleet conservation" alone. Whether that's the same logical-block concept wearing a larger hat, or something adjacent, is not yet settled — flagged as the central open question below, not guessed at.
What this doc does NOT do
- Does not implement the
write_ramdrive_blockremoval. That's a small, well-scoped follow-on change (delete one call, its now-dead callee, the twocapsule_clear_blockscall sites, and the already-deadcapsule_load_blocks) — but still a code change, held per standing instruction until asked for. - Does not specify how compudynamics decides placement, or what a "logical block" concretely is as data or as an API. Both are named directions, not designed mechanisms.
- Does not revise
HERMES-MESSAGE-BLOCK-STORAGE-DESIGN-20260708.mdin full — its storage-tiering discussion (own RAM blocks → own ramdrive blocks → own appended disk, no cross-VM coupling) is not contradicted by this doc, only its specific "claim aBlock Nrange" mechanism, which no longer applies once capsules stop writing blocks at all. A fuller rewrite of that doc is follow-on work once compudynamics placement and logical blocks are designed enough to describe how Hermes's messages actually get placed.
Open questions
- What compudynamics-driven placement actually looks like — an allocator interface, a heat-driven selection among candidate blocks, something else. Not specified here.
- What a "logical block" is, concretely — an addressing indirection (logical ID → physical LBN, resolved at access time), a renamed Logical BAM, or a new layer distinct from both. Not specified here.
- Whether removing
write_ramdrive_blockhas any effect on parity logging or dict-hash determinism —capsule_birth_mama/capsule_birth_babylogpost_dict_hashafter execution (capsule_birth.c:377, 462), which only depends on step 2 (dictionary state), not step 1 (block-device writes) — so removal should be parity-neutral, but this wants confirming against a real three-arch run when the change is actually made, not asserted here. - Whether
MANIFEST.md/BLOCK_MAP.md's block-numbering conventions need to change onceBlock Ncarries no persistence meaning — the4000+numbering could stay as pure namespace (no reason to renumber just because the aliasing risk is gone), or get simplified now that nothing constrains it to a real device's address space. Not decided here.