# Complete Boot Flow in C Vere (`-B solid.pill`) ## The Simple Truth When you run `vere -B solid.pill`, here's exactly what happens: ### Step 0: Command Line Processing **Location**: `main.c:418` ```c case 'B': u3_Host.ops_u.pil_c = _main_repath(optarg); // Store pill filepath ``` ### Step 1: Load Pill File (`_boothack_pill`) **Location**: `king.c:611-613` ```c if ( 0 != u3_Host.ops_u.pil_c ) { u3l_log("boot: loading pill %s", u3_Host.ops_u.pil_c); pil = u3m_file(u3_Host.ops_u.pil_c); // Load raw bytes into memory } ``` Returns: `[pil arv]` where `pil` is raw pill bytes, `arv` is optional filesystem ### Step 2: Cue the Pill Bytes (`u3_mars_boot`) **Location**: `mars.c:1958` ```c u3_weak jar = u3s_cue_xeno(len_d, hun_y); // Cue the pill bytes if ( (u3_none == jar) || (c3n == u3r_p(jar, c3__boot, &com)) ) { fprintf(stderr, "boot: parse fail\r\n"); exit(1); } ``` Expects pill structure: `[%boot com]` ### Step 3: Extract Events from Pill (`_mars_boot_make`) **Location**: `mars.c:1971` ```c _mars_sift_pill(u3k(pil), &bot, &mod, &use, &cax) ``` Pill structure: `[%pill %solid [bot mod use]]` - `bot`: Lifecycle events (boot sequence) - `mod`: Module/vane events - `use`: Userspace/app events ### Step 4: Write Events to Disk **Location**: `mars.c:1985-1987` ```c u3_disk_plan_list(log_u, ova); // Write events to LMDB u3_disk_sync(log_u); // Sync to disk ``` ### Step 5: Read Events Back and Boot **Location**: `mars.c:1993` ```c _mars_do_boot(log_u, log_u->dun_d, cax); // Boot from disk ``` Inside `_mars_do_boot` (line 1107): ```c eve = u3_disk_read_list(log_u, 1, eve_d, &mug_l); // Read from disk ``` Then (line 1160): ```c u3v_boot(eve); // Boot with event list! ``` ## Event Structure Details ### Event Creation in `_mars_boot_make` (`mars.c:1814-1836`) ```c u3_noun now = u3_time_in_tv(&inp_u->tim_u); u3_noun eve = u3kb_flop(bot); // Start with bot events (NO TIMESTAMP!) u3_noun lit = u3kb_weld(mod, use); while ( u3_nul != t ) { u3x_cell(t, &i, &t); now = u3ka_add(now, u3k(bit)); eve = u3nc(u3nc(u3k(now), u3k(i)), eve); // Add timestamped event [now i] } *ova = u3kb_flop(eve); // Final event list ``` **KEY**: Bot events are **NOT timestamped**, mod/use events ARE timestamped as `[timestamp event]` ### Step 4: Write Events to Disk **Location**: `mars.c:1955` ```c u3_disk_plan_list(log_u, ova); // Write events to LMDB u3_disk_sync(log_u); // Sync to disk ``` ### Step 5: Read Events Back and Boot (`_mars_do_boot`) **Location**: `mars.c:1107` ```c eve = u3_disk_read_list(log_u, 1, eve_d, &mug_l); // Read from disk ``` Each event is cued from disk: ```c // disk.c: *job = u3ke_cue(u3i_bytes(len_i - 4, dat_y + 4)); ven_u->eve = u3nc(job, ven_u->eve); // Cons onto list return u3kb_flop(ven_u->eve); // Return flipped list ``` ## Summary: The Complete `-B` Flow 1. **Load**: `u3m_file()` loads pill bytes from filepath 2. **Cue**: `u3s_cue_xeno()` deserializes to `[%boot com]` structure 3. **Parse**: `_mars_boot_make()` extracts bot/mod/use events and timestamps them 4. **Persist**: `u3_disk_plan_list()` writes to LMDB, `u3_disk_sync()` commits 5. **Read**: `u3_disk_read_list()` reads events back from disk 6. **Boot**: `u3v_boot(eve)` boots with the event list ## What We Need to Implement in OCaml Just follow the same pattern: ```ocaml (* Load pill file *) let pill_bytes = load_file pill_path in (* Cue the pill *) let pill_noun = Serial.cue pill_bytes in (* Extract [%boot com] *) let com = extract_boot_structure pill_noun in (* Parse into bot/mod/use events *) let (bot, mod_, use_) = parse_pill_structure com in (* Timestamp mod/use events (bot events stay bare) *) let event_list = build_event_list bot mod_ use_ in (* For now, skip disk persistence and boot directly *) Boot.boot event_list ``` **Key Insight**: Bot events are **NOT timestamped** (they're bare nouns), while mod/use events **ARE timestamped** as `[timestamp event]` pairs. ## The "eve=null" Mystery Solved From the actual boot log: ``` lite: arvo formula 4ce68411 u3v_life: eve=null (atom=yes cell=no) ← First call (ivory pill) u3v_life: completed successfully lite: core 641296f _mars_do_boot: first event is atom ← Bot events are atoms! u3v_boot: processing 10 events u3v_life: eve=null (atom=yes cell=no) ← Second call (from vortex.c) ``` There are **TWO** `u3v_life` calls: 1. First: Ivory pill bootstrap (eve=null creates initial kernel) 2. Second: Inside `u3v_boot()` which processes the 10 events The `eve=null` log in the second call is likely referring to the **original** `eve` parameter before it's been processed, NOT the actual subject passed to the lifecycle formula!