Files
LithosAnanake/docs/working/architecture/CAPSULE-LOADER-DEFINITIONS-ONLY-DESIGN-20260709.md
T

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 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 determinismcapsule_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.