docs(adr0020): release-profile capability slicing + report-tag renameVerified

Two pieces, single commit because the report-tag rename and the
ADR draft both flow from the same codex review (2026-06-10):

1. RENAME STRICT-LINK-{LIVE,DEAD} → BODY-{REACHABLE,UNREACHABLE}.

   The old tags overstated what the analyzer proves.  Today's
   tree-shake analyzer is sound only for direct out-of-line body
   reachability — it doesn't follow funcall / (function NAME)
   indirection or inline-emitted primitives.  Calling its output
   "STRICT-LINK-DEAD" misleadingly suggested liveness.

   Changes:
     - cold-tree-shake.lisp:277-278 emits BODY-REACHABLE /
       BODY-UNREACHABLE tags.
     - ag-tree-shake-bfs docstring rewritten to describe what
       the BFS actually traces (the old text said "Strict-link
       BFS from ROOTS through fn-patches + value-patches"
       — fn-patches is now redundant since step 1.5 routed
       edges through *ag-call-graph-edges* and value-patches
       were always excluded).
     - tests/bootstrap.el's two tree-shake tests updated to
       match the new tags.
     - cold-bootstrap-only.lisp + cold-bootstrap-retained.lisp
       docstrings updated.

2. DRAFT ADR 0020: release-profile capability slicing.

   ADR 0019 step 2.5 reached a dead end: every BODY-UNREACHABLE
   name was either (a) inline-emitted primitive, (b) CL stdlib
   user-facing, (c) REPL/hosted/save-image runtime helper, or
   (d) gensym/trap.  Step 2.5's bootstrap-only file is empty
   today, and codex's review pointed out why: the criterion "no
   user can call indirectly via funcall" makes elimination
   impossible by construction.  ag-build-fn-installs
   (compiler.lisp:3290) emits a symbol-function cell per top-
   level defun, so "the user could call it via (symbol-function
   'NAME)" is universally true.

   The transferable form of SBCL #8 is release-profile capability
   slicing, not genesis cleanup.  ADR 0020 stages this:

   Step 1 — provenance at emit time:
     extend *ag-call-graph-edges* with edge-class (direct-call,
     function-value-reference, synthetic-install-reference,
     inline-semantic-use).

   Step 2 — explicit capability tags:
     (declaim (capability NAME ...)) recognition; first batch
     covers CL Phase-1 stdlib as public-root + REPL entry points
     as runtime-feature repl.

   Step 3 — profile manifest format + per-profile reports:
     docs/release-profiles/{full,no-image,compiler-only}.lisp.
     funcl-cold --tree-shake-report --profile NAME runs BFS
     with profile capabilities as roots.

   Step 4 — gated elimination:
     funcl-cold --strict-link --profile NAME emits only defuns
     reachable from profile roots OR in profile retain list.
     Supersedes ADR 0019 step 3.

   The synthetic-install-reference distinction is the key fix
   for the "everything is reachable via symbol-function" problem
   — synthetic refs tagged at emit time, excluded from
   reachability proofs.

   ADR 0019 step 3 marked superseded; ADR 0019 steps 1, 1.5,
   2, 2.5 remain valid (the analyzer and gate machinery feeds
   ADR 0020 step 1).

Verified:
  - 197/197 GREEN
  - Both tree-shake tests pass with renamed tags
  - cold-of-cold reachability set unchanged (1194 reachable /
    229 unreachable) — purely a label change
Anthony Green2026-06-10 10:41:05 -0400 2276134ffd7078ee9337b8f7d842628c4a3d9307
Verified: - 197/197 GREEN