# 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 unused `CAPSULE_RAM_OFFSET` macro (`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 in `kernel_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 calls `write_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 `LOAD` word against a capsule-written block number — verified by grepping every `.4th` file under `capsules/` for `LOAD`; the only matches are substrings inside unrelated word names (`FLEET-DOE-WORKLOAD`, `LOAD-DOE`). The "so FORTH can call `LOAD N` later 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.md` and `ARTEMIS-BLOCK-PHYSICS-DESIGN-20260708.md` both 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_block` removal. That's a small, well-scoped follow-on change (delete one call, its now-dead callee, the two `capsule_clear_blocks` call sites, and the already-dead `capsule_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.md` in 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 a `Block N` range" 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 1. **What compudynamics-driven placement actually looks like** — an allocator interface, a heat-driven selection among candidate blocks, something else. Not specified here. 2. **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. 3. **Whether removing `write_ramdrive_block` has any effect on parity logging or dict-hash determinism** — `capsule_birth_mama`/ `capsule_birth_baby` log `post_dict_hash` after 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. 4. **Whether `MANIFEST.md`/`BLOCK_MAP.md`'s block-numbering conventions need to change** once `Block N` carries no persistence meaning — the `4000+` 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.