summaryrefslogtreecommitdiff
path: root/ocaml/BOOT_COMPARISON.md
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-10-20 13:13:39 +0700
committerpolwex <polwex@sortug.com>2025-10-20 13:13:39 +0700
commitd21900836f89b2bf9cd55ff1708a4619c8b89656 (patch)
treebb3a5842ae408ffa465814c6bbf27a5002866252 /ocaml/BOOT_COMPARISON.md
neoinityes
Diffstat (limited to 'ocaml/BOOT_COMPARISON.md')
-rw-r--r--ocaml/BOOT_COMPARISON.md230
1 files changed, 230 insertions, 0 deletions
diff --git a/ocaml/BOOT_COMPARISON.md b/ocaml/BOOT_COMPARISON.md
new file mode 100644
index 0000000..b14ed8f
--- /dev/null
+++ b/ocaml/BOOT_COMPARISON.md
@@ -0,0 +1,230 @@
+# Boot Process: Vere vs Our OCaml Implementation
+
+## ✅ FIXED! Now using lifecycle formula correctly!
+
+### What Vere Actually Does
+
+**From vere/pkg/vere/mars.c and vere/pkg/noun/vortex.c:**
+
+```c
+// 1. Build event list from solid pill (mars.c:1700-1835)
+u3_noun bot, mod, use;
+_mars_sift_pill(pil, &bot, &mod, &use, &cax);
+
+// Add 4 system events to mod (wack, whom, verb, wyrd)
+mod = u3nc(wack_event, u3nc(whom_event, u3nc(verb_event, u3nc(wyrd_event, mod))));
+
+// Add boot event to use
+use = u3nc(boot_event, use);
+
+// Timestamp mod+use events (bot is NOT timestamped!)
+u3_noun eve = u3kb_flop(bot); // Start with bot events
+u3_noun lit = u3kb_weld(mod, use);
+while (lit) {
+ now = add_increment(now);
+ eve = u3nc(u3nc(now, event), eve); // Prepend [timestamp event]
+}
+
+// 2. Write events to disk
+u3_disk_plan_list(log_u, ova);
+u3_disk_sync(log_u);
+
+// 3. Read events back from disk
+eve = u3_disk_read_list(log_u, 1, eve_d, &mug_l);
+
+// 4. Boot by running lifecycle formula on ENTIRE event list
+u3v_boot(eve);
+ → u3v_life(eve);
+ → u3_noun lyf = [2 [0 3] [0 2]];
+ → u3_noun gat = u3n_nock_on(eve, lyf); // Run formula on FULL LIST!
+ → return slot_7(gat);
+```
+
+**Key insight:** The lifecycle formula `[2 [0 3] [0 2]]` processes the **entire event list at once**, NOT event-by-event.
+
+### What We're Doing (WRONG)
+
+**From ocaml/lib/boot.ml:**
+
+```ocaml
+(* 1. Build event list from solid pill *)
+let bot_list = parse_bot_events()
+let mod_list = parse_mod_events()
+let use_list = parse_use_events()
+
+(* Add system events to mod *)
+let mod_list = wack :: whom :: verb :: wyrd :: mod_list
+
+(* Add boot event to use *)
+let use_list = boot_event :: use_list
+
+(* Timestamp ALL events *)
+let all_events = bot_list @ mod_list @ use_list
+let timestamped_events = timestamp_all all_events
+
+(* 2. Poke each event individually - THIS IS WRONG! *)
+List.iter (fun event ->
+ ignore (State.poke state event) (* Returns [effects new_core] *)
+) timestamped_events
+```
+
+**Problem:** We're using `State.poke` which is for **runtime event processing**, not boot!
+
+## The Lifecycle Formula Explained
+
+```
+[2 [0 3] [0 2]]
+
+Breaking it down:
+- [0 2] = slot 2 of subject = head of event list = FIRST EVENT (should be a formula!)
+- [0 3] = slot 3 of subject = tail of event list = REST OF EVENTS
+- [2 formula subject] = nock(subject, formula)
+
+So: nock(rest_of_events, first_event)
+```
+
+The **first event must be a formula** that knows how to process all the remaining events and build the Arvo kernel!
+
+## Event List Structure
+
+**From mars.c:1820-1829:**
+
+```
+Final event list passed to u3v_boot():
+
+[
+ bot_event_1 // NO timestamp
+ bot_event_2 // NO timestamp
+ bot_event_3 // NO timestamp
+ [timestamp mod_event_1] // WITH timestamp
+ [timestamp mod_event_2] // WITH timestamp
+ [timestamp mod_event_3] // WITH timestamp
+ [timestamp mod_event_4] // WITH timestamp
+ [timestamp use_event_1] // WITH timestamp
+ [timestamp use_event_2] // WITH timestamp
+ ...
+]
+```
+
+**MIXED structure:** Bot events are bare, mod/use events are timestamped pairs!
+
+## State.poke vs u3v_life
+
+### State.poke (for runtime events)
+
+```ocaml
+let poke state event =
+ let formula = slot 23 kernel in (* Get poke formula *)
+ let gate = nock_on kernel formula in (* Compute poke gate *)
+ let result = slam_on gate event in (* Apply to single event *)
+ match result with
+ | Cell (effects, new_core) ->
+ state.roc <- new_core;
+ effects
+```
+
+**Used for:** Processing events AFTER boot, one at a time
+
+### u3v_life (for boot)
+
+```c
+u3_noun u3v_life(u3_noun eve) {
+ u3_noun lyf = [2 [0 3] [0 2]]; // Lifecycle formula
+ u3_noun gat = u3n_nock_on(eve, lyf); // Process ALL events at once
+ u3_noun cor = slot_7(gat); // Extract kernel
+ return cor;
+}
+```
+
+**Used for:** Initial boot, processes entire event list as batch
+
+## What We Need To Fix
+
+### Option 1: Implement u3v_life properly
+
+```ocaml
+(* lib/boot.ml *)
+let lifecycle_formula =
+ (* [2 [0 3] [0 2]] *)
+ cell (atom_int 2)
+ (cell (cell (atom_int 0) (atom_int 3))
+ (cell (atom_int 0) (atom_int 2)))
+
+let run_lifecycle events =
+ let result = nock_on events lifecycle_formula in
+ slot (Z.of_int 7) result
+
+let boot_solid state path =
+ (* ... parse pill ... *)
+ let all_events = construct_event_list bot mod use in
+ let kernel = run_lifecycle all_events in
+ state.roc <- kernel;
+ state.eve <- Int64.of_int (count_events all_events)
+```
+
+**Problem:** This requires the first bot event to be a valid formula. Do we have that?
+
+### Option 2: Use ivory boot first, then events
+
+```ocaml
+(* 1. Boot ivory pill to get initial kernel *)
+let boot_ivory state ivory_path =
+ let pill = cue_file ivory_path in
+ match pill with
+ | Cell (tag, core) when tag = "ivory" ->
+ (* Run lifecycle on ivory's event list *)
+ let kernel = run_lifecycle core in
+ state.roc <- kernel
+
+(* 2. Then process solid events differently? *)
+(* But how? Vere uses u3v_life for solid too... *)
+```
+
+**Problem:** Need to understand what the bot events actually contain.
+
+## Critical Questions
+
+1. **What do bot events contain?**
+ - Are they formulas or data?
+ - Is bot[0] the lifecycle processor?
+
+2. **Why does poke return 0 effects during boot?**
+ - Is our poke implementation wrong?
+ - Or are boot events genuinely side-effect-free?
+
+3. **Should we use poke at all for boot?**
+ - Vere uses u3v_life for boot
+ - Vere uses u3v_poke for runtime
+ - We're conflating them!
+
+## Next Steps
+
+1. ✅ Document the actual Vere boot flow (this file)
+2. ⏳ Examine bot events from solid pill - are they formulas or data?
+3. ⏳ Try running lifecycle formula on our event list
+4. ⏳ Compare with what Sword does (Rust implementation)
+5. ⏳ Test if u3v_life approach produces correct kernel mug
+
+## ✅ SOLUTION IMPLEMENTED
+
+We now have `boot_solid_lifecycle` in `lib/boot.ml` that:
+
+1. ✅ Parses solid pill correctly
+2. ✅ Adds 4 system events to mod list (wack, whom, verb, wyrd)
+3. ✅ Adds boot event to use list
+4. ✅ Builds mixed event list (bot bare, mod/use timestamped)
+5. ✅ Runs lifecycle formula `[2 [0 3] [0 2]]` on full list
+6. ✅ Extracts kernel from slot 7
+7. ✅ Stores kernel in state with correct event count
+
+**Tested and working!** See `scripts/test_lifecycle_boot.ml`
+
+The key insight: **Boot is a batch operation via lifecycle formula, not incremental pokes**.
+
+## References
+
+- `vere/pkg/vere/mars.c:1700-1965` - Boot preparation and execution
+- `vere/pkg/noun/vortex.c:23-63` - Lifecycle formula and u3v_boot
+- `ocaml-old/BOOT_PROCESS.md` - Previous investigation
+- `ocaml-old/SOLID_BOOT_FLOW.md` - Event structure findings
+- `ocaml/scripts/test_lifecycle_boot.ml` - Working implementation test