releases#338 apply side — #331 W5. A node applying a signed set whose metadata carries the `bundle` entry installs or upgrades the bundle's members; a bundle-less set is nothing to apply.

## What changed

- **Acquisition.** `spt update fetch` fetches `spt-bundled-adapters.tar.gz` when the set declares it, verifies it against the SIGNED entry, stages it (`UPDATE_BUNDLE_SKIPPED` on any failure, binary staging unchanged). The pump pulls it from peers (`FetchAsset bundle`, W1's leg) through `pull_staged_bundle` — the `request_asset` wrap that IS the digest gate (W1 gate forward note) — with its own per-peer cooldown and learn-on-serve (`record_served(.., "bundle", ..)`).
- **Retention.** `ReleaseCache::{stage,staged,clear_staged}_bundle`; kept across a restage only when the incoming set signs exactly those bytes, dropped by a single release. Applying never clears it, so the node serves it as the `bundle` asset.
- **Apply** (`land_staged_bundle`, after `land_staged_docs` at both apply sites). No `bundle` entry → `NothingToApply`, silently, and **the verifier is never asked** (it refuses a bundle-less set as `Malformed` — that is the RELEASE path's rule and stays untouched; no change to `verify_update_set_bundle`, so no stop-and-refer). Otherwise: re-verify staged bytes vs the signed entry → extract the VERIFIED bytes → read `bundle.json` → per member:
  - absent → installed through `complete_adapter_add` (the `adapter add` tail, extracted verbatim so both share one path);
  - older → upgraded through `update_one_adapter` with the member as a `preset` candidate (same floor peek / crc swap / daemon routing / re-register / retain / post-step as any update);
  - equal or newer → untouched; removed by the operator → left removed;
  - member bytes vs `bundle.json` sha256 and the archive's own manifest identity (`check_archive_identity`) checked before anything registers.
- **`(built-in)`** — `AdapterRecord.built_in`, additive `serde(default)`, written `false` by every registration, set by `registry::mark_built_in` after the bundle's own registration. Per doyle's amendment it says where the CURRENT bytes came from: any non-bundle update re-registers and clears it. `install_source` is a separate axis and a bundle upgrade never rewrites it.
- **AUTO-SET SEAM (W7, releases#336)** — named marker at the upgrade site and in the REQ text: a newer member is applied unconditionally until `DaemonConfig.auto_classes` exists.
- **Doc** — docs-site self-update "Releases carry the built-in adapters".

## Measured while building

- **tar and the `./` prefix.** One release-shaped archive (`tar -czf b -C tree .`) on hfenduleam: recorded names `./`, `./a.spt`, `./bundle.json`. bsdtar 3.8.4 extracted the BARE `bundle.json` (rc 0); GNU tar 1.35 refused it (rc 2, "Not found in archive") and took `./bundle.json` (rc 0). So a name-addressed reader would behave differently per tar; the reader addresses no member by name — it extracts the whole archive and reads dirents (the `extract_release_archive` precedent). Row 2's negative control is the bare-name lookup among the RECORDED names, which fails on either tar.
- **A vacuous green, caught.** Row 1 first passed with a fixture that staged NO set at all (`staged_update()` needs a platform artifact file). Fixed; `stage()` now asserts the set is staged before any row runs.

## Evidence

REQ-BUNDLE-APPLY-MEMBERS minted in this commit (dispatch seed text verbatim + the two rulings appended); REQ-BUNDLE-RELEASE-ASSET `int` activated and discharged by the same int.

