From ea7d970586959946a119e30b0dc1f9fbe30c33e7 Mon Sep 17 00:00:00 2001 From: polwex Date: Mon, 6 Oct 2025 18:46:53 +0700 Subject: good progress --- NOTES.md | 3 + ocaml/SOLID_BOOT_FLOW.md | 134 ++++++++++++++ ocaml/lib/boot.ml | 367 +++++++++++++++++++++++++++++--------- ocaml/test/dune | 5 + ocaml/test/test_ivory_boot.ml | 2 +- ocaml/test/test_life_on_bot.ml | 7 +- ocaml/test/test_two_phase_boot.ml | 42 +++++ ocaml/zod/.urb/log/0i0/data.mdb | Bin 12832768 -> 12832768 bytes ocaml/zod/.urb/log/0i0/lock.mdb | Bin 8192 -> 8192 bytes ocaml/zod/.urb/log/0i0/vere.txt | 2 +- ocaml/zod/.vere.lock | 2 +- vere/pkg/vere/king.c | 1 + vere/pkg/vere/lord.c | 1 + vere/pkg/vere/main.c | 1 + vere/pkg/vere/mars.c | 61 ++++++- vere/pkg/vere/solid_boot_test.c | 69 ++++++- zod/.urb/log/0i0/data.mdb | Bin 12832768 -> 12832768 bytes zod/.urb/log/0i0/lock.mdb | Bin 8192 -> 8192 bytes zod/.urb/log/0i0/vere.txt | 2 +- zod/.vere.lock | 2 +- 20 files changed, 608 insertions(+), 93 deletions(-) create mode 100644 ocaml/SOLID_BOOT_FLOW.md create mode 100644 ocaml/test/test_two_phase_boot.ml diff --git a/NOTES.md b/NOTES.md index a9ae5a4..684d883 100644 --- a/NOTES.md +++ b/NOTES.md @@ -10,3 +10,6 @@ fucking ivory pill syntax is can we try a multicore implementation? write it at ocaml/lib/serial_parallel.ml . Come on having a single process take 10+minutes while not using the computer just feels wrong + + +wtf tests sometimes faile running dune exec but not if i do _build/default/test/...exe diff --git a/ocaml/SOLID_BOOT_FLOW.md b/ocaml/SOLID_BOOT_FLOW.md new file mode 100644 index 0000000..d188bd9 --- /dev/null +++ b/ocaml/SOLID_BOOT_FLOW.md @@ -0,0 +1,134 @@ +# Solid Pill Boot Flow (C Vere) + +## Investigation Summary + +Tracked the solid pill boot flow through C Vere to understand how `-B solid.pill` works. + +## Call Chain + +``` +1. king.c:_boothack_doom() + ↓ Creates boot command: [%boot bot pill_spec path] + +2. king.c:_king_doom() + ↓ Routes to _king_fake() for fake ships + +3. king.c:_king_fake() + ↓ Creates message: [%boot pill vent props] + ↓ Calls u3_lord_boot() with jammed message + +4. lord.c:u3_lord_boot() + ↓ Spawns worker process with "boot" protocol + ↓ Jams and sends boot message to worker + +5. main.c:_cw_boot() + ↓ Worker process receives boot message + ↓ Sets up u3_mars_boot as message handler + +6. mars.c:u3_mars_boot() + ↓ Cues the boot message + ↓ Calls _mars_boot_make() to prepare events + +7. mars.c:_mars_boot_make() + ↓ Calls _mars_sift_pill() to parse pill + ↓ Builds timestamped event list + ↓ Writes events to disk + +8. mars.c:_mars_sift_pill() <-- KEY FUNCTION + ↓ Parses pill structure + +9. mars.c:_mars_do_boot() + ↓ Reads events from disk + ↓ Calls u3v_boot(eve) + +10. vortex.c:u3v_boot() + ↓ Calls u3v_life(eve) + +11. vortex.c:u3v_life() + ↓ Runs lifecycle formula [2 [0 3] [0 2]] +``` + +## Pill Structure + +### Ivory Pill +``` +[%ivory core] +``` +- Tag: %ivory +- Content: The compiled kernel core directly + +### Solid Pill +``` +[%pill %solid bot mod use] +``` +Which expands to: +``` +[%pill [%solid [bot [mod [use nil]]]]] +``` + +From `mars.c:1629`: +```c +if ( c3n == u3r_qual(dat, &typ, bot, mod, use) ) { +``` + +Where `dat` is the second element after %pill tag, containing `[%solid bot mod use]`. + +## Event List Construction + +From `mars.c:1832-1866`, the event list is built as: + +1. **Bot events** (3 events): NO timestamp, bare events +2. **Mod events** (0 in pill + 4 synthesized): WITH timestamps + - Synthesized events added at lines 1758-1774: + - `wack`: entropy (16 random words) + - `whom`: ship identity + - `verb`: verbose flag + - Version negotiation card +3. **Use events** (3-5 depending on pill): WITH timestamps + +The final structure passed to `u3v_boot(eve)`: +``` +[bare_bot_1 bare_bot_2 bare_bot_3 [ts mod_1] [ts mod_2] ... [ts use_1] ...] +``` + +A MIXED list: some bare events, some timestamped pairs! + +## Key Findings + +1. **Ivory rejection**: `_mars_sift_pill` line 1608-1611 REJECTS ivory pills: + ```c + if ( c3y == u3r_sing_c("ivory", tag) ) { + fprintf(stderr, "boot: failed: unable to boot from ivory pill\r\n"); + return c3n; + } + ``` + +2. **Pill tag value**: `c3__pill` = 0x6c6c6970 = 1819044208 (NOT 1819633778!) + +3. **u3v_life formula**: `[2 [0 3] [0 2]]` is applied to the ENTIRE event list + - Works on the full mixed list (bot + mod + use) + - NOT just bot events! + +4. **My solid.pill has**: + - Bot: 3 events (bare) + - Mod: 0 events (empty list in pill) + - Use: 5 events + - Total: 8 events + - But C Vere adds 4 synthetic mod events → 12 total + +## Current Problem + +The lifecycle formula `[2 [0 3] [0 2]]` is failing on my 8-event list with `Nock.Exit`. + +This formula means: +- `[0 2]`: get slot 2 (head) = first event/formula +- `[0 3]`: get slot 3 (tail) = rest of events +- `[2 formula subject]`: nock(subject formula) + +So it's trying to: `nock(rest-of-events first-event)` + +The first event should be a FORMULA (executable code), but my bot events might just be data! + +## Next Steps + +Need to understand what the bot events actually contain - are they formulas or data? diff --git a/ocaml/lib/boot.ml b/ocaml/lib/boot.ml index ce30f2f..9e3f17c 100644 --- a/ocaml/lib/boot.ml +++ b/ocaml/lib/boot.ml @@ -249,60 +249,156 @@ let boot state eve_list = with e -> Error ("Boot failed: " ^ Printexc.to_string e) -(* Parse solid pill structure: [%boot [%pill %solid [bot mod use]]] +(* Parse solid pill structure: [%pill %solid [bot mod use]] * - * Following C Vere mars.c:1730 _mars_sift_pill + * Following actual solid pill format (not wrapped in %boot) *) let parse_solid_pill pil = - (* Extract [%boot com] *) if not (Noun.is_cell pil) then Error "Pill must be a cell" else let tag = Noun.head pil in - let com = Noun.tail pil in - - (* Check for %boot tag *) - let boot_tag = Z.of_string "1953654151028" in (* "boot" *) - - match tag with - | Noun.Atom z when Z.equal z boot_tag -> - (* Now parse com structure *) - if not (Noun.is_cell com) then - Error "Pill com must be a cell" + let rest = Noun.tail pil in + + (* Debug: print actual tag value *) + (match tag with + | Noun.Atom z -> + Printf.printf "[Debug] Tag is atom: %s (hex: %s)\n%!" + (Z.to_string z) (Z.format "x" z) + | Noun.Cell _ -> + Printf.printf "[Debug] Tag is cell (unexpected!)\n%!"); + + (* Check for %pill tag *) + let pill_tag = Z.of_string "1819044208" in (* "pill" = 0x6c6c6970 *) + + begin match tag with + | Noun.Atom z when Z.equal z pill_tag -> + (* rest should be [%solid bot mod use], extract all 4 *) + if not (Noun.is_cell rest) then + Error "Pill rest must be a cell" else - (* com is [[pill typ] [bot mod use]] *) - let fst = Noun.head com in - let snd = Noun.tail com in + (* Extract using u3r_qual pattern: [a b c d] *) + let typ = Noun.head rest in + let rest1 = Noun.tail rest in - if not (Noun.is_cell fst) then - Error "Pill fst must be a cell" + Printf.printf "[Debug] typ (should be %%solid): %s\n%!" + (if Noun.is_atom typ then "atom" else "cell"); + Printf.printf "[Debug] rest1 structure: %s\n%!" + (if Noun.is_cell rest1 then "cell" else "atom"); + + if not (Noun.is_cell rest1) then + Error "After typ, expected [bot mod use]" else - let pill_tag = Noun.head fst in - let _typ = Noun.tail fst in - - (* Check for %pill tag *) - let pill_atom = Z.of_string "1819633778" in (* "pill" *) - - match pill_tag with - | Noun.Atom z when Z.equal z pill_atom -> - (* Extract [bot mod use] from snd *) - if not (Noun.is_cell snd) then - Error "Events structure must be a cell" - else - let bot = Noun.head snd in - let rest = Noun.tail snd in - - if not (Noun.is_cell rest) then - Error "Mod/use structure must be a cell" - else - let mod_ = Noun.head rest in - let use = Noun.tail (Noun.head (Noun.tail rest)) in - - Ok (bot, mod_, use) - | _ -> - Error "Expected %pill tag" - | _ -> - Error "Expected %boot tag" + let bot = Noun.head rest1 in + let rest2 = Noun.tail rest1 in + + Printf.printf "[Debug] bot: %s\n%!" + (if Noun.is_cell bot then "cell (list)" else "atom"); + Printf.printf "[Debug] rest2 (should be [mod use]): %s\n%!" + (if Noun.is_cell rest2 then "cell" else "atom"); + + if not (Noun.is_cell rest2) then + Error "After bot, expected [mod use]" + else + (* u3r_qual extracts [typ bot mod use] as: + * typ = head(dat) + * bot = head(tail(dat)) + * mod = head(tail(tail(dat))) + * use = tail(tail(tail(dat))) <- NOTE: TAIL, not head! + * + * So rest2 = [mod use], where: + * mod = head(rest2) + * use = tail(rest2) <- This is just 'use', not [use cax] + *) + let mod_ = Noun.head rest2 in + let use_ = Noun.tail rest2 in + + Printf.printf "[Debug] mod: %s\n%!" + (if Noun.is_cell mod_ then "cell (list)" else "atom"); + Printf.printf "[Debug] use: %s\n%!" + (if Noun.is_cell use_ then "cell (list)" else "atom"); + + Ok (bot, mod_, use_) + | Noun.Atom _ -> + Error "Expected %pill tag" + | Noun.Cell _ -> + Error "Expected %pill tag (got cell)" + end + +(* Helper: Convert string to atom (big-endian bytes) *) +let string_to_atom s = + let len = String.length s in + let rec loop i acc = + if i < 0 then acc + else + let byte = Char.code s.[i] in + loop (i - 1) (Z.add (Z.mul acc (Z.of_int 256)) (Z.of_int byte)) + in + Noun.Atom (loop (len - 1) Z.zero) + +(* Synthesize the 4 MOD events - following C Vere mars.c:1763-1779 *) +let synthesize_mod_events () = + (* Wire for all mod events: [%$ %arvo ~] which is [0 'arvo' 0] *) + let arvo_str = string_to_atom "arvo" in + let wir = Noun.cell (Noun.Atom Z.zero) + (Noun.cell arvo_str (Noun.Atom Z.zero)) in + + (* 1. wack: entropy card [%wack [16 random words]] *) + let eny_words = Array.init 16 (fun _ -> + Random.int64 Int64.max_int) in + (* Build list of entropy words *) + let rec build_word_list i acc = + if i < 0 then acc + else build_word_list (i - 1) + (Noun.cell (Noun.Atom (Z.of_int64 eny_words.(i))) acc) + in + let eny_noun = build_word_list 15 (Noun.Atom Z.zero) in + let wack_tag = string_to_atom "wack" in + let wack_card = Noun.cell wack_tag eny_noun in + let wack = Noun.cell (wir) wack_card in + + (* 2. whom: identity card [%whom ship] *) + let who = Noun.Atom Z.zero in (* ~zod = 0 *) + let whom_tag = string_to_atom "whom" in + let whom_card = Noun.cell whom_tag who in + let whom = Noun.cell (wir) whom_card in + + (* 3. verb: verbose flag [%verb ~ 0] (0 = verbose off) *) + let verb_tag = string_to_atom "verb" in + let verb_card = Noun.cell verb_tag + (Noun.cell (Noun.Atom Z.zero) (Noun.Atom Z.zero)) in + let verb = Noun.cell (wir) verb_card in + + (* 4. wyrd: version card - simplified for now *) + (* TODO: Implement proper version card like _mars_wyrd_card *) + let wyrd_tag = string_to_atom "wyrd" in + let wyrd_card = Noun.cell wyrd_tag (Noun.Atom Z.zero) in + let wyrd = Noun.cell wir wyrd_card in + + (* Build list: [wack whom verb wyrd ~] *) + Noun.cell wack + (Noun.cell whom + (Noun.cell verb + (Noun.cell wyrd (Noun.Atom Z.zero)))) + +(* Synthesize legacy boot USE event - following C Vere mars.c:1785-1789 *) +let synthesize_boot_event () = + (* Wire: [%d %term '1' ~] which is ['d' 'term' 0x31 0] *) + let d = string_to_atom "d" in + let term = string_to_atom "term" in + let one = Noun.Atom (Z.of_int 0x31) in (* ASCII '1' *) + let wir = Noun.cell d + (Noun.cell term + (Noun.cell one (Noun.Atom Z.zero))) in + + (* Card: [%boot lit ven] - simplified *) + (* lit = 0 (c3n = false), ven will be filled in properly later *) + let boot_tag = string_to_atom "boot" in + let lit = Noun.Atom Z.zero in + let ven = Noun.Atom Z.zero in (* Placeholder for now *) + let cad = Noun.cell boot_tag (Noun.cell lit ven) in + + Noun.cell wir cad (* Build event list following C Vere mars.c:1814-1836 * @@ -391,63 +487,168 @@ let build_event_list bot mod_ use_ = Printf.printf "[Boot] ✓ Event list built: %d events\n%!" (count_list ova); ova +(* Boot lite - bootstrap ivory pill + * + * Following C Vere king.c:283 u3v_boot_lite + * The ivory pill is [%ivory core], we extract the core + *) +let boot_lite ~fs state ivory_path = + Printf.printf "[Lite Boot] Loading ivory pill from %s...\n%!" ivory_path; + + let file_path = Eio.Path.(fs / ivory_path) in + let pill_bytes = Eio.Path.load file_path |> Bytes.of_string in + + Printf.printf "[Lite Boot] Cuing ivory pill...\n%!"; + let pil = Serial.cue pill_bytes in + + (* Ivory pill is [%ivory core], extract the core *) + if not (Noun.is_cell pil) then begin + Printf.printf "[Lite Boot] ✗ Pill is not a cell\n%!"; + Error "Ivory pill must be a cell" + end else begin + let _tag = Noun.head pil in + let core = Noun.tail pil in + + Printf.printf "[Lite Boot] Extracted ivory core, setting as kernel\n%!"; + + (* Set the core directly as the kernel - no lifecycle formula needed *) + State.boot state core; + + Printf.printf "[Lite Boot] ✓ Ivory kernel booted!\n\n%!"; + Ok () + end + (* Boot from solid pill - following C Vere -B flag logic + * + * CRITICAL: Must boot ivory FIRST, then solid events! * * This follows the exact flow from BOOT_FLOW.md: - * 1. Load pill bytes from file - * 2. Cue to get [%boot com] structure - * 3. Parse into bot/mod/use events - * 4. Timestamp mod/use events (bot stays bare) - * 5. Boot with event list + * Phase 1: Boot ivory pill (creates minimal kernel) + * Phase 2: Boot solid events (metamorphosis to full kernel) * * Skipping disk persistence for now (steps 4-5 in C flow) *) -let boot_solid ~fs state pill_path = +let boot_solid ~fs state ivory_path solid_path = Printf.printf "\n%!"; Printf.printf "═══════════════════════════════════════════════════\n%!"; Printf.printf " Solid Pill Boot (Following C Vere -B Logic)\n%!"; Printf.printf "═══════════════════════════════════════════════════\n\n%!"; - (* Step 1: Load pill file *) - Printf.printf "[1] Loading %s...\n%!" pill_path; - - let file_path = Eio.Path.(fs / pill_path) in - let pill_bytes = Eio.Path.load file_path |> Bytes.of_string in + (* PHASE 1: Boot ivory pill first *) + Printf.printf "PHASE 1: IVORY BOOTSTRAP\n%!"; + Printf.printf "─────────────────────────────────────────────────\n%!"; - Printf.printf " ✓ Loaded %d bytes\n\n%!" (Bytes.length pill_bytes); + (match boot_lite ~fs state ivory_path with + | Error msg -> Error ("Ivory boot failed: " ^ msg) + | Ok () -> + Printf.printf "─────────────────────────────────────────────────\n\n%!"; - (* Step 2: Cue the pill *) - Printf.printf "[2] Cuing pill...\n%!"; - let pil = Serial.cue pill_bytes in - Printf.printf " ✓ Cued successfully\n\n%!"; + (* PHASE 2: Boot solid events *) + Printf.printf "PHASE 2: SOLID PILL BOOT\n%!"; + Printf.printf "─────────────────────────────────────────────────\n\n%!"; - (* Step 3: Parse pill structure *) - Printf.printf "[3] Parsing pill structure...\n%!"; - match parse_solid_pill pil with - | Error msg -> - Printf.printf " ✗ Parse failed: %s\n%!" msg; - Error msg + (* Step 1: Load pill file *) + Printf.printf "[1] Loading %s...\n%!" solid_path; - | Ok (bot, mod_, use_) -> - Printf.printf " ✓ Extracted bot/mod/use events\n\n%!"; + let file_path = Eio.Path.(fs / solid_path) in + let pill_bytes = Eio.Path.load file_path |> Bytes.of_string in - (* Step 4: Build event list (C Vere style) *) - Printf.printf "[4] Building event list (C Vere style)...\n%!"; - let ova = build_event_list bot mod_ use_ in - Printf.printf "\n%!"; + Printf.printf " ✓ Loaded %d bytes\n\n%!" (Bytes.length pill_bytes); - (* Step 5: Boot with event list *) - Printf.printf "[5] Calling u3v_boot with event list...\n%!"; - Printf.printf " (Booting Arvo kernel from events)\n\n%!"; + (* Step 2: Cue the pill *) + Printf.printf "[2] Cuing pill...\n%!"; + let pil = Serial.cue pill_bytes in + Printf.printf " ✓ Cued successfully\n\n%!"; - match boot state ova with + (* Step 3: Parse pill structure *) + Printf.printf "[3] Parsing pill structure...\n%!"; + match parse_solid_pill pil with | Error msg -> - Printf.printf " ✗ BOOT FAILED: %s\n%!" msg; + Printf.printf " ✗ Parse failed: %s\n%!" msg; Error msg - | Ok () -> - Printf.printf " ✓ BOOT SUCCEEDED!\n%!"; + + | Ok (bot, mod_, use_) -> + Printf.printf " ✓ Extracted bot/mod/use events\n%!"; + + (* Count helper *) + let rec count_list noun = + match noun with + | Noun.Atom z when Z.equal z Z.zero -> 0 + | Noun.Cell (_, rest) -> 1 + count_list rest + | _ -> 0 + in + + (* Debug: check structure of each *) + Printf.printf " Bot structure: %s (count=%d)\n%!" + (if Noun.is_cell bot then "cell (list)" else "atom") + (count_list bot); + Printf.printf " Mod structure: %s (count=%d)\n%!" + (if Noun.is_cell mod_ then "cell (list)" else "atom") + (count_list mod_); + Printf.printf " Use structure: %s (count=%d)\n%!" + (if Noun.is_cell use_ then "cell (list)" else "atom") + (count_list use_); + + (* Debug: walk through USE list and show structure *) + Printf.printf " USE list details:\n%!"; + let rec walk_list noun i = + match noun with + | Noun.Atom z when Z.equal z Z.zero -> + Printf.printf " [%d] = ~ (list terminator)\n%!" i + | Noun.Cell (head, tail) -> + Printf.printf " [%d] = %s\n%!" i + (if Noun.is_cell head then "CELL" else "ATOM"); + if i < 5 then walk_list tail (i + 1) + | Noun.Atom _ -> + Printf.printf " [%d] = ATOM (improper list!)\n%!" i + in + walk_list use_ 0; + Printf.printf "\n%!"; + + (* Step 3.5: Synthesize events (C Vere mars.c:1763-1789) *) + Printf.printf "[3.5] Synthesizing events (like C Vere)...\n%!"; + + (* Generate 4 synthetic MOD events *) + let synth_mod = synthesize_mod_events () in + Printf.printf " ✓ Generated 4 synthetic MOD events\n%!"; + + (* Generate 1 synthetic USE event *) + let synth_use = synthesize_boot_event () in + Printf.printf " ✓ Generated 1 synthetic USE event\n%!"; + + (* Prepend synthetic events *) + (* Helper to prepend to a list *) + let rec weld l1 l2 = + match l1 with + | Noun.Atom z when Z.equal z Z.zero -> l2 + | Noun.Cell (h, t) -> Noun.Cell (h, weld t l2) + | _ -> l2 + in + + let mod_ = weld synth_mod mod_ in (* 4 synthetic + 0 from pill *) + let use_ = Noun.cell synth_use use_ in (* 1 synthetic + 2 from pill *) + + Printf.printf " ✓ Prepended synthetic events\n%!"; + Printf.printf " After synthesis: mod=%d, use=%d\n\n%!" + (count_list mod_) (count_list use_); + + (* Step 4: Build event list (C Vere style) *) + Printf.printf "[4] Building event list (C Vere style)...\n%!"; + let ova = build_event_list bot mod_ use_ in Printf.printf "\n%!"; - Printf.printf "═══════════════════════════════════════════════════\n%!"; - Printf.printf " ✓ SOLID PILL BOOT COMPLETE!\n%!"; - Printf.printf "═══════════════════════════════════════════════════\n\n%!"; - Ok () + + (* Step 5: Boot with event list *) + Printf.printf "[5] Calling u3v_boot with event list...\n%!"; + Printf.printf " (Metamorphosis: replacing ivory kernel)\n\n%!"; + + match boot state ova with + | Error msg -> + Printf.printf " ✗ BOOT FAILED: %s\n%!" msg; + Error msg + | Ok () -> + Printf.printf " ✓ BOOT SUCCEEDED!\n%!"; + Printf.printf "\n%!"; + Printf.printf "═══════════════════════════════════════════════════\n%!"; + Printf.printf " ✓ SOLID PILL BOOT COMPLETE!\n%!"; + Printf.printf "═══════════════════════════════════════════════════\n\n%!"; + Ok ()) diff --git a/ocaml/test/dune b/ocaml/test/dune index c7cf6da..3f23caa 100644 --- a/ocaml/test/dune +++ b/ocaml/test/dune @@ -281,3 +281,8 @@ (name examine_ivory) (modules examine_ivory) (libraries nock_lib eio_main)) + +(executable + (name test_two_phase_boot) + (modules test_two_phase_boot) + (libraries nock_lib eio_main)) diff --git a/ocaml/test/test_ivory_boot.ml b/ocaml/test/test_ivory_boot.ml index 7cada9e..f9d511a 100644 --- a/ocaml/test/test_ivory_boot.ml +++ b/ocaml/test/test_ivory_boot.ml @@ -20,7 +20,7 @@ let test_ivory_boot env = Printf.printf "Step 3: Run lifecycle formula [2 [0 3] [0 2]]\n"; Printf.printf "Step 4: Extract slot 7 from result\n\n"; - match Boot.boot_ivory ~fs state "ivory.pill" with + match Boot.boot_lite ~fs state "ivory.pill" with | Error msg -> Printf.printf "✗ Boot failed: %s\n%!" msg diff --git a/ocaml/test/test_life_on_bot.ml b/ocaml/test/test_life_on_bot.ml index 4aa1080..1625a53 100644 --- a/ocaml/test/test_life_on_bot.ml +++ b/ocaml/test/test_life_on_bot.ml @@ -7,14 +7,17 @@ let rec to_list acc noun = | Noun.Atom _ -> List.rev acc | Noun.Cell (item, rest) -> to_list (item :: acc) rest -let test _env = +let test env = Printf.printf "═══════════════════════════════════════\n"; Printf.printf " Testing u3v_life on Bot Events\n"; Printf.printf "═══════════════════════════════════════\n\n"; + Eio.Switch.run @@ fun _sw -> + let fs = Eio.Stdenv.fs env in + (* Cue the solid pill *) Printf.printf "Cuing solid.pill...\n%!"; - let pill_bytes = Eio.Path.load (Eio.Path.("." / "solid.pill")) |> Bytes.of_string in + let pill_bytes = Eio.Path.load (Eio.Path.(fs / "solid.pill")) |> Bytes.of_string in let pill = Serial.cue pill_bytes in Printf.printf "✓ Pill cued\n\n"; diff --git a/ocaml/test/test_two_phase_boot.ml b/ocaml/test/test_two_phase_boot.ml new file mode 100644 index 0000000..0669b92 --- /dev/null +++ b/ocaml/test/test_two_phase_boot.ml @@ -0,0 +1,42 @@ +(* Test Two-Phase Boot: Ivory → Solid + * + * This matches the C Vere boot flow: + * 1. Boot ivory pill (lite boot, creates minimal kernel) + * 2. Boot solid events (metamorphosis to full kernel) + *) + +open Nock_lib + +let test_boot env = + Printf.printf "🎯 Testing Two-Phase Boot (Ivory → Solid)\n\n"; + + Eio.Switch.run @@ fun _sw -> + let fs = Eio.Stdenv.fs env in + + (* Create runtime state *) + let state = State.create () in + + (* Boot with ivory + solid *) + match Boot.boot_solid ~fs state "ivory.pill" "solid.pill" with + | Error msg -> + Printf.printf "❌ Boot failed: %s\n" msg; + exit 1 + | Ok () -> + Printf.printf "✅ Boot succeeded!\n\n"; + + (* Check kernel state *) + let arvo = State.get_arvo state in + Printf.printf "Arvo kernel structure:\n"; + Printf.printf " Type: %s\n" + (if Noun.is_cell arvo then "Cell" else "Atom"); + + Printf.printf "\n🎉 TWO-PHASE BOOT COMPLETE!\n" + +let () = + Printf.printf "\n"; + Printf.printf "═══════════════════════════════════════════════════════════\n"; + Printf.printf " Testing Two-Phase Boot System\n"; + Printf.printf "═══════════════════════════════════════════════════════════\n"; + Printf.printf "\n"; + + Eio_main.run test_boot diff --git a/ocaml/zod/.urb/log/0i0/data.mdb b/ocaml/zod/.urb/log/0i0/data.mdb index 3b7640d..b83c374 100644 Binary files a/ocaml/zod/.urb/log/0i0/data.mdb and b/ocaml/zod/.urb/log/0i0/data.mdb differ diff --git a/ocaml/zod/.urb/log/0i0/lock.mdb b/ocaml/zod/.urb/log/0i0/lock.mdb index dfc340b..55d79ba 100644 Binary files a/ocaml/zod/.urb/log/0i0/lock.mdb and b/ocaml/zod/.urb/log/0i0/lock.mdb differ diff --git a/ocaml/zod/.urb/log/0i0/vere.txt b/ocaml/zod/.urb/log/0i0/vere.txt index 0920787..cc829d4 100644 --- a/ocaml/zod/.urb/log/0i0/vere.txt +++ b/ocaml/zod/.urb/log/0i0/vere.txt @@ -1 +1 @@ -4.0-d0314e586e \ No newline at end of file +4.0-476771a4b6 \ No newline at end of file diff --git a/ocaml/zod/.vere.lock b/ocaml/zod/.vere.lock index ba25e80..320dbbd 100644 --- a/ocaml/zod/.vere.lock +++ b/ocaml/zod/.vere.lock @@ -1 +1 @@ -474854 +668607 diff --git a/vere/pkg/vere/king.c b/vere/pkg/vere/king.c index dd4711a..7049014 100644 --- a/vere/pkg/vere/king.c +++ b/vere/pkg/vere/king.c @@ -236,6 +236,7 @@ _king_prop() void _king_fake(u3_noun ship, u3_noun pill, u3_noun path) { + u3l_log("king_fake"); u3_noun vent = u3nc(c3__fake, u3k(ship)); // XX pass kelvin diff --git a/vere/pkg/vere/lord.c b/vere/pkg/vere/lord.c index e714539..4ab94f5 100644 --- a/vere/pkg/vere/lord.c +++ b/vere/pkg/vere/lord.c @@ -1217,6 +1217,7 @@ u3_lord_boot(c3_c* pax_c, void* ptr_v, void (*done_f)(void*, c3_o)) { + u3l_log("lord_boot"); _lord_boot* bot_u = c3_calloc(sizeof(*bot_u)); bot_u->wag_w = wag_w; bot_u->bin_c = u3_Host.wrk_c; // XX strcopy diff --git a/vere/pkg/vere/main.c b/vere/pkg/vere/main.c index db19f77..3124df0 100644 --- a/vere/pkg/vere/main.c +++ b/vere/pkg/vere/main.c @@ -2782,6 +2782,7 @@ _cw_vile(c3_i argc, c3_c* argv[]) static void _cw_boot(c3_i argc, c3_c* argv[]) { + u3l_log("cw_boot:main.c"); c3_c* dir_c = 0; // extract option map and load runtime config diff --git a/vere/pkg/vere/mars.c b/vere/pkg/vere/mars.c index 7b1ed03..f4a0107 100644 --- a/vere/pkg/vere/mars.c +++ b/vere/pkg/vere/mars.c @@ -1094,6 +1094,7 @@ _mars_play_batch(u3_mars* mar_u, static c3_o _mars_do_boot(u3_disk* log_u, c3_d eve_d, u3_noun cax) { + u3l_log("mars do boot"); u3_weak eve; c3_l mug_l; @@ -1584,6 +1585,7 @@ _mars_sift_pill(u3_noun pil, u3_noun* use, u3_noun* cax) { + u3l_log("mars sifting pill"); u3_noun pil_p, pil_q; *cax = u3_nul; @@ -1636,6 +1638,8 @@ _mars_sift_pill(u3_noun pil, fprintf(stderr, "boot: parsing %%%s pill\r\n", typ_c); c3_free(typ_c); } + + } u3k(*bot); u3k(*mod); u3k(*use), u3k(*cax); @@ -1687,6 +1691,7 @@ _mars_boot_make(u3_boot_opts* inp_u, u3_noun* xac, u3_meta* met_u) { + u3l_log("mars boot make"); // set the disk version // met_u->ver_w = U3D_VERLAT; @@ -1829,7 +1834,61 @@ _mars_boot_make(u3_boot_opts* inp_u, use = u3kb_weld(pre, u3kb_weld(use, aft)); } - // timestamp events, cons list + // Log pill structure + { + fprintf(stderr, "\n=== PILL STRUCTURE DUMP ===\n\n"); + + fprintf(stderr, "BOT: %s (len=%llu)\n\n", + (c3y == u3a_is_atom(bot)) ? "ATOM" : "CELL", + (unsigned long long)u3qb_lent(bot)); + u3_noun t = bot; + c3_d i = 0; + while ( u3_nul != t && i < 5 ) { + u3_noun item = u3h(t); + fprintf(stderr, " [%llu]: %s", + (unsigned long long)i, + (c3y == u3a_is_atom(item)) ? "ATOM" : "CELL"); + if ( c3y == u3a_is_atom(item) ) { + fprintf(stderr, " (bits=%u)", u3r_met(0, item)); + } + fprintf(stderr, "\n\n"); + t = u3t(t); + i++; + } + + fprintf(stderr, "\n\nMOD: %s (len=%llu)\n\n", + (c3y == u3a_is_atom(mod)) ? "ATOM" : "CELL", + (unsigned long long)u3qb_lent(mod)); + t = mod; + i = 0; + while ( u3_nul != t && i < 5 ) { + u3_noun item = u3h(t); + fprintf(stderr, " [%llu]: %s\n\n", + (unsigned long long)i, + (c3y == u3a_is_atom(item)) ? "ATOM" : "CELL"); + t = u3t(t); + i++; + } + + fprintf(stderr, "\n\nUSE: %s (len=%llu)\n\n", + (c3y == u3a_is_atom(use)) ? "ATOM" : "CELL", + (unsigned long long)u3qb_lent(use)); + t = use; + i = 0; + while ( u3_nul != t && i < 5 ) { + u3_noun item = u3h(t); + fprintf(stderr, " [%llu]: %s\n\n", + (unsigned long long)i, + (c3y == u3a_is_atom(item)) ? "ATOM" : "CELL"); + t = u3t(t); + i++; + } + + fprintf(stderr, "\n\nCAX: %s\n\n", + (c3y == u3a_is_atom(cax)) ? "ATOM" : "CELL"); + + fprintf(stderr, "\n\n=== END STRUCTURE ===\n\n\n"); + } // timestamp events, cons list // { c3_d bot_c = u3qb_lent(bot); diff --git a/vere/pkg/vere/solid_boot_test.c b/vere/pkg/vere/solid_boot_test.c index b0d5200..e6bd23a 100644 --- a/vere/pkg/vere/solid_boot_test.c +++ b/vere/pkg/vere/solid_boot_test.c @@ -31,8 +31,8 @@ _test_solid_boot(void) /* Step 1: Load solid.pill (like king.c:611) */ fprintf(stderr, "[1] Loading solid.pill (u3m_file like king.c)...\n"); - u3_noun pil_p = u3m_file("solid.pill"); - // u3_noun pil_p = u3m_file("/home/y/code/urbit/vere/ocaml/solid.pill"); + // u3_noun pil_p = u3m_file("solid.pill"); + u3_noun pil_p = u3m_file("/home/y/code/urbit/vere/ocaml/solid.pill"); u3_noun arv = u3_nul; c3_o arv_atom = u3a_is_atom(arv); c3_o atom2 = u3a_is_atom(42); @@ -103,6 +103,71 @@ _test_solid_boot(void) fprintf(stderr, " Total: %llu events\n\n", (unsigned long long)(bot_c + mod_c + use_c)); + /* Step 3.5: Dump full pill structure */ + fprintf(stderr, "[3.5] Dumping full pill structure to /tmp/pill_dump.txt...\n"); + { + FILE* f = fopen("/tmp/pill_dump.txt", "w"); + if ( f ) { + fprintf(f, "========================================\n"); + fprintf(f, "BOT events: %llu\n", (unsigned long long)bot_c); + fprintf(f, "========================================\n"); + u3_noun t = bot; + c3_d i = 0; + while ( u3_nul != t ) { + u3_noun item = u3h(t); + fprintf(f, "\nBot[%llu]: %s (mug: 0x%x)\n", + (unsigned long long)i, + u3a_is_atom(item) ? "ATOM" : "CELL", + u3r_mug(item)); + if ( u3a_is_atom(item) ) { + fprintf(f, " Size: %u bits\n", u3r_met(0, item)); + } + t = u3t(t); + i++; + } + + fprintf(f, "\n========================================\n"); + fprintf(f, "MOD events: %llu\n", (unsigned long long)mod_c); + fprintf(f, "========================================\n"); + t = mod; + i = 0; + while ( u3_nul != t ) { + u3_noun item = u3h(t); + fprintf(f, "\nMod[%llu]: %s (mug: 0x%x)\n", + (unsigned long long)i, + u3a_is_atom(item) ? "ATOM" : "CELL", + u3r_mug(item)); + t = u3t(t); + i++; + } + + fprintf(f, "\n========================================\n"); + fprintf(f, "USE events: %llu\n", (unsigned long long)use_c); + fprintf(f, "========================================\n"); + t = use; + i = 0; + while ( u3_nul != t ) { + u3_noun item = u3h(t); + fprintf(f, "\nUse[%llu]: %s (mug: 0x%x)\n", + (unsigned long long)i, + u3a_is_atom(item) ? "ATOM" : "CELL", + u3r_mug(item)); + t = u3t(t); + i++; + } + + fclose(f); + fprintf(stderr, " ✓ Wrote basic structure to /tmp/pill_dump.txt\n\n"); + } else { + fprintf(stderr, " ✗ Failed to open /tmp/pill_dump.txt\n\n"); + } + } + + /* STOP HERE - don't actually boot, just wanted the structure dump */ + fprintf(stderr, "✓ PILL STRUCTURE DUMPED - exiting without boot\n"); + u3z(bot); u3z(mod); u3z(use); + return 1; + /* Step 4: Build event list (like _mars_boot_make lines 1814-1836) */ fprintf(stderr, "[4] Building event list (C Vere style)...\n"); fprintf(stderr, " Bot events: NOT timestamped\n"); diff --git a/zod/.urb/log/0i0/data.mdb b/zod/.urb/log/0i0/data.mdb index aac7bed..4f86596 100644 Binary files a/zod/.urb/log/0i0/data.mdb and b/zod/.urb/log/0i0/data.mdb differ diff --git a/zod/.urb/log/0i0/lock.mdb b/zod/.urb/log/0i0/lock.mdb index cf0169c..bc75f1c 100644 Binary files a/zod/.urb/log/0i0/lock.mdb and b/zod/.urb/log/0i0/lock.mdb differ diff --git a/zod/.urb/log/0i0/vere.txt b/zod/.urb/log/0i0/vere.txt index 0455ac0..cc829d4 100644 --- a/zod/.urb/log/0i0/vere.txt +++ b/zod/.urb/log/0i0/vere.txt @@ -1 +1 @@ -4.0-437df069b5 \ No newline at end of file +4.0-476771a4b6 \ No newline at end of file diff --git a/zod/.vere.lock b/zod/.vere.lock index d3bf1bd..04d560a 100644 --- a/zod/.vere.lock +++ b/zod/.vere.lock @@ -1 +1 @@ -589155 +661315 -- cgit v1.2.3