Files
Robert Allan JamesandClaude Sonnet 5 cbe7b49a59 Documentation debt sweep: 5 of 6 items resolved, 1 confirmed accurate
- docs/lithosananke/ROADMAP.md + M7.1.md: fixed stale "Branch: lithosananke"
  (no such branch post-split), M7.1's "Design Complete" status (shipped
  and live, redirected to FABRIC*.md), the M8/success-criteria
  self-contradiction (OBSOLETE marking vs. unqualified live criterion),
  and the stale AHCI/SATA claim for M9 (real implementation is
  virtio_blk.c) -- also corrected BLOCK/BUFFER/UPDATE/FLUSH and block
  device abstraction to [x] since both are confirmed live in
  src/word_source/block_words.c and block_subsystem.c.
- Top-level ROADMAP.md: marked OBSOLETE (Captain Bob's call -- more than
  "stale," the architecture/branch topology/terminology it describes no
  longer exist), pointing to docs/lithosananke/ROADMAP.md and
  FABRIC*.md for current status.
- docs/03-architecture/word-acl/DESIGN.md: fixed the ACL Phase 7
  contradiction -- Phase 7 (LithosAnanke kernel parity) is independently
  verified complete per .claude/CLAUDE.md, not "remaining"; removed the
  stale lithosananke-branch-parity framing.
- VM-FLEET-ATTRACTOR-DESIGN-20260705.md's doe-campaign.4th "broken" claim:
  investigated, ran SMOKE-CAMPAIGN live (completes clean, fleet heat
  conserved) -- initially read as contradicting the claim, corrected
  directly by Captain Bob: a clean execution trace doesn't disprove the
  doc's actual argument (no real controlled-experimental-factor
  mechanism). Confirmed accurate, left untouched.
- Isabelle/HOL pipeline-metrics model/C-struct mismatch: confirmed a real
  proof-modeling gap (pm_last_accuracy_num/den has no analogue in the
  real PipelineGlobalMetrics struct), not stale prose -- tracked here
  rather than fixed, matching the .thy file's own scope boundary and
  this project's standing caution that each Isabelle gap needs its own
  subsystem model.

ACL-RWT DoE overhead re-measurement (the 6th item) intentionally not
started -- a full multi-architecture DoE campaign, not a doc-text fix,
holding for explicit confirmation given the scale.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 06:30:36 -04:00

572 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M7.1: Init Capsule Architecture
**Status:** Shipped and live, not just designed — this document predates the actual
capsule/Tripod/Stadium work; see `FABRIC.md`/`FABRIC-2.md`/`FABRIC-3.md` for real status
(per `.claude/CLAUDE.md`'s standing redirect)
**Branch:** `master` (post-split; the old `lithosananke` branch no longer exists in this repo)
**Prerequisite:** M7 (VM Parity Validation)
## The Immutable Law
> **Exactly ONE production INIT `(p)` defines a baby VM.**
>
> No INIT is shared implicitly.
> No base INIT exists.
> Any similarity between VMs is the result of deliberate reuse by Mama.
This rule is non-negotiable. Everything in this document exists to enforce it.
---
## 1. DOMAIN vs PERSONALITY
### 1.1 DOMAIN (Mama-only Concept)
**DOMAIN** is a *construction and selection space* that exists **only in Mama FORTH**.
DOMAIN is used to:
- Classify *kinds* of VMs (e.g., HTTP, storage, control-plane)
- Compose and curate block sets
- Run experiments `(e)`
- Decide which block set is promoted to production `(p)`
DOMAIN:
- Is **never** executed by babies
- Is **never** visible to babies
- Is **not** part of VM truth
- Leaves **no** runtime trace in the baby
DOMAIN answers: *"What kind of thing is Mama trying to create?"*
### 1.2 PERSONALITY (Baby-only Reality)
**PERSONALITY** is the *result* of Mama's work.
A baby VM receives:
- **Exactly one `(p)` INIT**
- Executed exactly once at birth
- Which defines its entire worldview
PERSONALITY:
- Defines role, capabilities, invariants, vocabulary
- Is immutable for the lifetime of the VM
- Is the only truth the VM knows
PERSONALITY answers: *"What am I?"*
**The baby has no knowledge of DOMAIN.**
---
## 2. What is an Init Capsule?
An INIT capsule is **not**:
- A shared base
- A layered inheritance mechanism
- A runtime-selectable script
- A file or "boot code"
An INIT capsule **is**:
- An **ordered, immutable block sequence**
- A **truth-bearing unit**
- Executed **exactly once** at VM birth
- The **sole source of identity** for that VM
- **Referentially addressable** — by content hash, not name
- **Observationally enumerable** — Mama can list all capsules
Think: ROM image + provenance, not "config."
---
## 3. Architecture Decision
### Option 1: One Big Memory Blob (Indexed)
Single contiguous arena with descriptor table + payload region.
### Option 2: Individual Named Blobs
Separate addressable entities with symbolic names.
### Decision: Hybrid
**Physically:** Option 1 — single arena, indexed by ID + offset
**Logically:** Option 2 — capsules declared symbolically at build time
At runtime: **symbols do not exist.** Only facts (hashes, offsets, lengths).
> Names lie. Hashes don't.
---
## 4. Data Structures
### 3.1 CapsuleDesc (64 bytes, cache-line aligned)
```c
typedef struct {
uint64_t magic; /* 0x00: 'CAPS' | ver | hashAlg | reserved */
uint64_t capsule_id; /* 0x08: == content_hash (content-addressed) */
uint64_t content_hash; /* 0x10: hash of payload bytes */
uint64_t offset; /* 0x18: byte offset into payload arena */
uint64_t length; /* 0x20: payload length in bytes */
uint32_t flags; /* 0x28: state + policy bits */
uint32_t owner_vm; /* 0x2C: 0 = mama, else child VM ID */
uint64_t birth_count; /* 0x30: how many VMs born from this */
uint64_t created_ns; /* 0x38: monotonic timestamp at registration */
} CapsuleDesc; /* 0x40 = 64 bytes */
```
### 3.2 Magic Field Packing
```
bits 0..31 : 'CAPS' (0x53504143 little-endian)
bits 32..39 : version (0 for v0)
bits 40..47 : hashAlg (enum CapsuleHashAlg)
bits 48..63 : reserved (zero)
```
### 3.3 CapsuleDirHeader
```c
typedef struct {
uint64_t magic; /* 'CAPD' | ver | reserved */
uint64_t arena_base; /* phys or virt base of payload arena */
uint64_t arena_size; /* bytes */
uint32_t desc_count; /* current number of descriptors */
uint32_t desc_capacity; /* max (fixed at compile time for Phase A) */
uint64_t dir_hash; /* hash of descriptor table (for parity) */
} CapsuleDirHeader;
```
### 3.4 CapsuleRunRecord (for DoE logging)
```c
typedef struct {
uint64_t run_id; /* sequential run identifier */
uint32_t vm_id; /* which VM executed this */
uint32_t reserved;
uint64_t capsule_id; /* which capsule was run */
uint64_t capsule_hash; /* hash at time of execution */
uint64_t pre_dict_hash; /* dictionary state before run */
uint64_t post_dict_hash; /* dictionary state after run */
uint64_t started_ns; /* monotonic start time */
uint64_t ended_ns; /* monotonic end time */
uint32_t result_code; /* execution result */
uint32_t flags; /* run flags (mode, etc.) */
} CapsuleRunRecord;
```
---
## 5. Content Addressing
**Rule:** `capsule_id` MUST be derived from `content_hash`.
For v0: `capsule_id == content_hash` (identity)
This ensures:
- No sequential ID collisions
- No "what's the salt" questions
- Facts only, no oracles
---
## 6. Hash Algorithm
**v0 Choice:** xxHash64
- Deterministic across hosted + kernel
- Easy to implement freestanding
- Fast
- Good enough collision resistance for practice
**Future-proofing:** The `hashAlg` field in magic allows upgrade to SHA-256 or BLAKE3 without breaking history.
```c
typedef enum {
CAPSULE_HASH_XXHASH64 = 0,
CAPSULE_HASH_SHA256 = 1,
CAPSULE_HASH_BLAKE3 = 2,
} CapsuleHashAlg;
```
---
## 7. Flags
### 6.1 State Flags
```c
#define CAPSULE_FLAG_ACTIVE 0x00000001 /* eligible for use */
#define CAPSULE_FLAG_REVOKED 0x00000002 /* birth-blocked forever */
#define CAPSULE_FLAG_DEPRECATED 0x00000004 /* eligible but discouraged */
#define CAPSULE_FLAG_PINNED 0x00000008 /* immune to GC */
```
### 6.2 Mode Flags (Production vs Experiment)
```c
#define CAPSULE_FLAG_PRODUCTION 0x00000010 /* (p) truth-bearing */
#define CAPSULE_FLAG_EXPERIMENT 0x00000020 /* (e) workload only */
```
**Invariant:** Exactly one of (p) or (e) must be set.
```c
#define CAPSULE_MODE_VALID(f) \
((((f) & CAPSULE_FLAG_PRODUCTION) != 0) ^ \
(((f) & CAPSULE_FLAG_EXPERIMENT) != 0))
```
If both or neither are set: **invalid capsule.**
### 6.3 Revocation Semantics
A revoked capsule:
- Remains enumerable (for audit)
- Remains hashable (for provenance)
- Is birth-blocked (mama refuses to bind it)
**REVOKED always overrides ACTIVE.**
---
## 8. Eligibility Rules
### 7.1 Birth Eligibility
A VM may be born **only** from a (p) capsule:
```c
#define BIRTH_ELIGIBLE(flags) \
(((flags) & CAPSULE_FLAG_PRODUCTION) && \
((flags) & CAPSULE_FLAG_ACTIVE) && \
!((flags) & CAPSULE_FLAG_REVOKED))
```
If mama attempts to bind an (e) capsule at birth: **hard refusal.**
No warnings. No fallback. No exceptions.
### 7.2 DoE/Runtime Eligibility
**(e) capsules exist ONLY in Mama's domain.** Baby VMs never see them, never execute them, never know they exist.
Mama may execute:
- **(e) capsules** freely on herself (subject to policy)
- **(p) capsules** only as birth capsules for babies (never as workloads)
This prevents the deadly mistake:
> "Let's just rerun a production init as an experiment."
No. That turns truth into a variable.
### 7.3 Twins, Triplets, and Variants
**Twins/Triplets/Variants are not special constructs.** They are simply:
- Multiple VMs born from the **same (p) capsule** (twins)
- VMs born from **similar (p) capsules** (variants)
Any similarity between VMs is the result of:
1. Mama deliberately choosing the same (p) capsule for birth
2. Mama creating similar (p) capsules from shared block sets
There is no implicit inheritance. There is no base class. If two VMs share behavior, it's because Mama *made* them share it — not because of any hidden mechanism.
---
## 9. Parity Integration
Birth becomes a parity checkpoint:
```
PARITY:BIRTH vm_id=42 capsule_id=0xA13F mode=p capsule_hash=0x... dict_hash=0x...
```
DoE runs are logged separately:
```
PARITY:RUN vm_id=42 run_id=17 capsule_id=0xBEEF mode=e pre_dict=0x... post_dict=0x...
```
### 8.1 Truth Chain
For any VM, you can prove:
1. Which capsule created it (birth_capsule_id)
2. What the capsule contained (content_hash)
3. What dictionary state resulted (dict_hash)
4. What workloads were run after birth (CapsuleRunRecord log)
This is **provenance**. This is **science**. This is **patent-grade**.
---
## 10. Arena Placement
### Phase A: Static (M7.1 - M8)
- Descriptor table + payload arena live in `.rodata` or dedicated section
- Built by tooling (or compiled-in)
- Zero allocator dependency
- Deterministic
```c
/* In kernel image */
extern const CapsuleDirHeader capsule_directory;
extern const CapsuleDesc capsule_descriptors[];
extern const uint8_t capsule_arena[];
```
### Phase B: Dynamic (Future)
- Mama manages RAM arena
- Runtime capsule registration
- Optional persistence via memory-mapped block store
**Key:** `CapsuleDesc` doesn't care where bytes come from. It only cares about `offset`/`length` within "the arena."
---
## 11. Capacity
### Phase A: Fixed Array
```c
#define MAX_CAPSULES 256
```
`CapsuleDirHeader` includes `desc_count` and `desc_capacity`.
Growable arrays can come later without interface changes.
---
## 12. Who Writes Descriptors?
### Phase A (Static)
- **Build tooling** generates descriptors
- Kernel boots with sealed capsule directory
- Mama reads and binds, never writes
### Phase B (Dynamic)
- **Mama** appends new capsules to RAM arena
- Only mama writes descriptors at runtime
- **Children never write descriptors, ever**
---
## 13. VM Birth Protocol
1. Mama selects **one production INIT `(p)`** (by content hash)
2. Mama validates eligibility:
- `CAPSULE_FLAG_PRODUCTION` set
- `CAPSULE_FLAG_ACTIVE` set
- `CAPSULE_FLAG_REVOKED` not set
3. Mama allocates a new VM
4. INIT blocks are **copied** into the VM execution window (RAM blocks 02047)
5. INIT blocks are **executed sequentially**
6. Execution window is **cleared**
7. VM begins life with its **PERSONALITY fully imprinted**
8. Mama logs parity checkpoint:
```
PARITY:BIRTH vm_id=N capsule_id=X mode=p capsule_hash=H dict_hash=D
```
9. Mama increments `capsule.birth_count`
**There is:**
- No shared INIT
- No implicit base
- No post-birth INIT execution
- No runtime selection
**The baby VM cannot:**
- Enumerate sibling capsules
- Mutate the arena
- Know its own capsule ID (optional: can query mama)
- See or know about DOMAIN
---
## 14. DoE Execution Protocol
1. Mama selects workload capsule(s)
2. Mama validates eligibility:
- `CAPSULE_FLAG_EXPERIMENT` set
- `CAPSULE_FLAG_ACTIVE` set
- `CAPSULE_FLAG_REVOKED` not set
3. For each workload:
a. Record `pre_dict_hash`
b. Execute capsule on target VM
c. Record `post_dict_hash`
d. Log run record:
```
PARITY:RUN vm_id=N run_id=R capsule_id=X mode=e pre_dict=P post_dict=Q
```
**DoE runs do not change the VM's birth truth.** They are experiments, not identity.
---
## 15. Validation Function
```c
typedef enum {
CAPSULE_VALID = 0,
CAPSULE_ERR_BAD_MAGIC,
CAPSULE_ERR_BAD_VERSION,
CAPSULE_ERR_BAD_HASH_ALG,
CAPSULE_ERR_BOUNDS,
CAPSULE_ERR_MODE_INVALID,
CAPSULE_ERR_REVOKED_ACTIVE,
CAPSULE_ERR_HASH_MISMATCH,
} CapsuleValidateResult;
CapsuleValidateResult capsule_validate(
const CapsuleDesc *desc,
const uint8_t *arena_base,
uint64_t arena_size,
int verify_hash /* if true, recompute and compare */
);
```
Checks:
1. Magic signature and version
2. Hash algorithm is known
3. `offset + length <= arena_size`
4. Exactly one of (p)/(e) is set
5. REVOKED and ACTIVE not both set (REVOKED wins, but warn)
6. Optional: recompute hash and compare to `content_hash`
---
## 16. File Deliverables
| File | Purpose |
|------|---------|
| `include/starkernel/capsule.h` | CapsuleDesc, CapsuleDirHeader, flags, enums |
| `include/starkernel/capsule_run.h` | CapsuleRunRecord for DoE logging |
| `src/starkernel/capsule/capsule_validate.c` | Validation function |
| `src/starkernel/capsule/capsule_birth.c` | Birth protocol implementation |
| `src/starkernel/capsule/capsule_run.c` | DoE run logging |
---
## 17. Summary
| Principle | Enforcement |
|-----------|-------------|
| One truth per VM | Birth only accepts (p) capsules |
| DOMAIN is Mama-only | Construction concept, never visible to babies |
| PERSONALITY is baby-only | Executed INIT result, immutable identity |
| (e) capsules are Mama-only | Never executed by or visible to baby VMs |
| Content-addressed | `capsule_id == content_hash` |
| Names don't exist at runtime | Symbolic resolution at build time only |
| Revocation is permanent | REVOKED overrides ACTIVE, capsule stays enumerable |
| DoE doesn't change truth | Workloads are (e), logged separately |
| Mama sees all | Children see one capsule, read-only |
| No implicit sharing | Twins exist because Mama chose same capsule |
| Provenance is mandatory | PARITY:BIRTH and PARITY:RUN logged |
---
## 18. Next Steps
1. **Implement `capsule.h`** — structs, flags, macros
2. **Implement `capsule_validate()`** — freestanding, no libc
3. **Build tooling** — generate static capsule directory from `.4th` files
4. **Integrate with birth** — extend `sk_vm_bootstrap` to accept capsule pointer
5. **Parity logging** — extend parity subsystem for BIRTH/RUN records
---
## 19. Gap Analysis (Resolved)
### 18.1 Payload Encoding
**Decision:** Raw UTF-8 FORTH source for Phase A.
- Simple, debuggable, portable
- Hash computed over raw bytes
- Tokenization/compilation is premature optimization
- Future phases may add `CAPSULE_FLAG_TOKENIZED` if needed
### 18.2 VM ID Allocation
Mama maintains a VM registry:
```c
typedef struct {
uint32_t vm_id; /* assigned at birth, immutable */
uint64_t birth_capsule_id;
uint64_t birth_timestamp_ns;
uint32_t state; /* EMBRYO, LIVE, DEAD */
uint32_t flags;
} VMRegistryEntry;
```
- VM ID 0 is reserved (mama)
- IDs are sequential (1, 2, 3, ...)
- ID is never reused within a session
### 18.3 Birth Failure Handling
If init execution fails:
1. VM never transitions to LIVE state
2. VM is marked STILLBORN
3. Parity log records failure:
```
PARITY:BIRTH_FAILED vm_id=N capsule_id=X error=E partial_dict_hash=H
```
4. Partial state is **not** observable by other VMs
5. Mama may retry with same or different capsule
### 18.4 Run Log Storage
`CapsuleRunRecord` entries stored in:
**Phase A:** Fixed ring buffer in kernel BSS
```c
#define MAX_RUN_RECORDS 1024
CapsuleRunRecord run_log[MAX_RUN_RECORDS];
uint32_t run_log_head;
```
**Phase B:** Append-only log, optionally persisted to block device
### 18.5 Atomicity of birth_count
**Rule:** Only mama increments `birth_count`.
Since mama is single-threaded (or serialized), no atomic operations needed in Phase A. Phase B (SMP mama) would require `__atomic_fetch_add`.
### 18.6 xxHash64 Implementation
Freestanding xxHash64 required:
```
include/starkernel/xxhash64.h
src/starkernel/hash/xxhash64.c
```
Public domain implementation (~200 lines). Must be:
- No libc dependency
- Deterministic across platforms
- Seedable (seed = 0 for capsule hashing)
---
## 20. Implementation Checklist
- [ ] `include/starkernel/capsule.h` — structs, flags, macros
- [ ] `include/starkernel/capsule_run.h` — CapsuleRunRecord
- [ ] `include/starkernel/xxhash64.h` — hash function
- [ ] `src/starkernel/hash/xxhash64.c` — freestanding xxHash64
- [ ] `src/starkernel/capsule/capsule_validate.c` — validation
- [ ] `src/starkernel/capsule/capsule_birth.c` — birth protocol
- [ ] `src/starkernel/capsule/capsule_run.c` — DoE run logging
- [ ] `tools/mkcapsule.c` — build tool to generate capsule directory
- [ ] Extend parity subsystem for BIRTH/BIRTH_FAILED/RUN records
- [ ] VM registry in mama
---
*This design will still make sense 20 years from now.*