#325 B5: authoritative image + flip probe to adopt; forced-divergence identity check (Axis B)
openPart of #318 (epic). Axis B — the authoritative-world layer (new, atop ADR 0025). Depends on B4.
Goal
Make the image authoritative and complete (carry the whole symbol/keyword/package world) and flip the B1 probe from "dispatch to old loader" to "adopt the image's world wholesale" — skipping cold primordial construction entirely. This deletes the reason for identity reconciliation.
Approach
- Dump the full symbol/keyword/package world into the core.
- On adopt: install the image's pools directly; do NOT cold-build then reconcile.
- Bypass or prove-loader-private every pre-image symbol/keyword creation path.
Acceptance gate
Forced-divergence check: instrument so that if ANY cold path interns a symbol
or mints a keyword before adoption, it is detected (not merely "no visible bug").
"Identity for free" holds only under that proof. Suite-green incl. asdf load;
keyword/symbol eq-identity holds across save/restore by construction (retires
the cave#314 class).
Comments (2)
Codex review of the raw-boot plan — agreed on step 1, expanded step 2+
Codex confirmed the plan and found the fatal gap I suspected plus more. Before the raw BOOT (step 2) can work, raw restore must OWN:
- GC start-map (
+gc-start-map-vaddr+) + region directory — a raw byte copy of [base,hi) does NOT repopulate the object-start side map or region dir, which the object-path allocators build incrementally. Every GC walk /gc-next-start/ pointer classification is side-map-driven, so a raw heap with a stale/zero start-map corrupts the first GC. Must EITHER dump+restore the start-map bytes at its fixed VA, OR rebuild it deterministically from object starts; rebuild the region dir from restored spans. (This also affects the B3 bitmap builder, which uses the start-map.) - Alloc window (R15/R13 / high-water) — restored bytes do not reinstall
allocator register state. After restore, compute the restored high-water/free
range and call
%SET-ALLOC-WINDOW(writing the fixed next-window slots first), or new allocation overwrites the restored heap. - Master-consuming restore phases must be bypassed for raw:
ag-image-canonicalize-heap-keywordsand the code-mmap pool-slot relocation both read*ag-image-loaded-heap-master*. The pool-offset rebuilds are raw-safe (they scan gc-root-ranges, not the master). - CODE-MMAP is read from HARDCODED section slot 2 (
ag-image-restore-code-mmap). New raw sections MUST append (CODE-MMAP stays index 2, HEAP index 3); do not insert before them.
Verdict on step 1: SAFE as transport-only (flag-gated 6-section save, boot still via object path) provided it does not alter section-ordering assumptions or live restore behavior. Proceeding with step 1 now; the start-map/region-dir/ alloc-window ownership is added to the B5 scope for step 2.
B5 raw-boot restore design (from mapping the regions + bootstrap-globals)
Runtime state spans 3 regions: fixed runtime heap (
+elf-heap-vaddr++ fixed offsets: PACKAGE, gc-root-ranges slot, pool start/count, high-water, ...), the collectable heap (+gc-collectable-heap-start-vaddr+: all cons/record/symbol objects), and the code mmap (+elf-mmap-vaddr+: code + dyn-sym slice).Key insight: the bootstrap globals are a CONTAINER LIST living in the collectable heap (index 0=PACKAGE, 1=FUNCL-PACKAGES, ... 5=gc-root-ranges, 6=mc-tables, 7=cond-tables, 8=nicknames). A raw collectable dump at delta 0 restores the container and every value it references IN PLACE at their original vaddrs. So the raw boot does NOT reconstruct objects; it just re-points the fixed-heap slots at the in-place container.
Raw-boot restore sequence (vs the object path):
Becomes UNNECESSARY at delta 0 (the B5/B6 win):
New save-side requirement: record the root container vaddr so step 4 can find it without the master. That is the first implementation increment.