#325 B5: authoritative image + flip probe to adopt; forced-divergence identity check (Axis B)

open
Opened by atgreen

Part 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

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)

atgreen3993126455

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):

  1. restore code-mmap (UNCHANGED)
  2. populate-fn-table (UNCHANGED)
  3. raw-restore the collectable heap (B2p1 primitive) -- replaces pass1/pass2
  4. set fixed-heap globals from the in-place container -- needs the ROOT container vaddr, which the save side must RECORD (new field). Reuse restore-bootstrap-globals logic but walk the live in-place list, not the master.
  5. rebuild-symbol/keyword/pkgsym-pool-offsets -- still RUN (maps arent persisted) but from the restored, valid gc-root-ranges. NOT no-ops, but correct as-is.
  6. install-fn-cells; restore-mc/cond-tables -- still run (write registries into mini-clos globals). Heap-resident symbol cells are already valid (delta 0).

Becomes UNNECESSARY at delta 0 (the B5/B6 win):

  • pass-1/pass-2 object reconstruction (raw copy replaces it)
  • ag-image-canonicalize-heap-keywords (cave#314) -- keywords are the SAME records at the SAME addresses, no duplication to reconcile
  • pool-slot index relocation (pointers already absolute)

New save-side requirement: record the root container vaddr so step 4 can find it without the master. That is the first implementation increment.

atgreen3993127317

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:

  1. 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.)
  2. 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.
  3. Master-consuming restore phases must be bypassed for raw: ag-image-canonicalize-heap-keywords and 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).
  4. 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.