fix(image): cave#314 — canonicalize heap-copied keyword references at restore (gen-2 load-system works)Verified

(asdf:load-system "alexandria") on the baked gen-2 image errored 'no
accessor': a baked mini-clos instance (vector :%mc-instance% class
slotvec) had slot0 = a keyword named %MC-INSTANCE% at a different heap
record than the runtime/reader/compiled-code :%mc-instance%, so
(eq (svref obj 0) :%mc-instance%) failed, mc-instance-p returned nil,
class-of returned SIMPLE-VECTOR, and slot-value raised.

Root cause (codex 2nd opinion): keyword EQ-IDENTITY splits across
save/restore.  ag-image-heap-needs-collection-p returns 1 for every
symbol including keywords, so a keyword reached from a heap slot is
HEAP-COPIED and restores as a fresh duplicate; the keyword-pool
rebuild only canonicalizes ARENA keywords and the pre-pass2 symbol
canonicalizer (cave#155) only unifies keywords with a BAKED STATIC
record — a minted keyword like :%mc-instance% has none.  This bites
EVERY eq/member/case-on-keyword against baked data.

Fix (codex-recommended, lowest-risk of the options — no image-format
change, repairs in place): after ag-image-rebuild-keyword-pool-offsets,
while the heap master is live, walk the restored heap and rewrite every
keyword REFERENCE (cons car/cdr, simple-vector slots) to the canonical
keyword of the same name — static, else pooled, else minted
(idempotent, pool-backed).  Identity-preserving (same name → one
identity), always safe.  Gated on the symbol-pool-range readiness
ag-image-restore-bootstrap-globals uses, so the host-built stage1
(reduced runtime — keywordp/ag-runtime-* would SIGSEGV via the
not-yet-ready fn-table during image-load) skips it; stage1 has no
keywords to canonicalize anyway.

Verified: the baked gen-2 image (build/funcl-asdf) now runs
(asdf:asdf-version) => "3.3.7" AND (asdf:load-system "alexandria")
to completion with (alexandria:curry #'+ 1) 41) => 42; gen-2 boot
unchanged ~2.86s (heap-walk adds no measurable cost); 8/8 sharded
suite (incl. the stage1 save-image-restart roundtrip, which the
ungated first cut segfaulted), smoke, spike 16/16, package edge
probes, and alexandria-via-fasl on build/funcl all green.

cave#314 layer 4 is now fully closed: the CDS-style baked-asdf
fast-boot image works end to end at ~2.8s (vs ~10s fasl replay).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anthony Green2026-07-15 07:55:28 -0400 49f858c7dc66c8a113fbf2606a57fccd7167d7ee
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>