# MUSL-TIER W3 — DISPATCH RULING (doyle → todlando)

**GO 2026-07-08** (operator "drive to release publish"). W1 (registry, `b659420`) + W2 (register musl, `7a3ee6e`) both merged to `main`. Branch W3 off `main` @`7a3ee6e`. Activate `REQ-RELEASE-MUSL-ARTIFACT` `required_stages = ["impl","unit","int"]` in the work-start commit ([[traceable-per-wave-activation]]) — W3 is the wave that delivers it; it stays `[]` until you start.

## What W3 closes (the field gap)
A musl-built `spt` now self-identifies as `x86_64-unknown-linux-musl` (W2) — so today it `spt update fetch` → `UPDATE_FETCH_REJECTED: NoArtifactForPlatform(musl)` because **no release carries a musl artifact**. W3 supplies that artifact end-to-end: CI build → SHA256SUMS → signed release upload → update-set entry → self-update works on a sub-2.39-glibc box.

## CONTEXT / ADR grounding (checked — design-aligned)
- **CONTEXT.md:3** — platforms additive, "not a re-architecture." musl is ADDITIVE; **gnu stays the default Linux artifact**, musl rides alongside.
- **CONTEXT.md:828** — novel Linux (handhelds, sub-glibc) foreseen: "relocatable binary + minimal, non-OS-entangled install." The static musl binary IS that relocatable artifact.
- **ADR-0016** — platform-targeted update sets; the update-set names each platform's artifact + the recipient selects `current_platform()`'s. musl becomes one more named entry, no machinery change.

## Scope — release-pipeline data, NOT dependency work
`/diagnose` 2026-07-08 (backlog #14) proved the tree builds+runs static musl with ZERO source changes (rustls not openssl; aws-lc-sys + bundled-sqlite clean under `musl-gcc`; openpty; static DNS/HTTPS). So W3 is CI-matrix + assemble + sign + update-set wiring. Sites:

1. **`release.yml` — musl matrix entry** (build on **kitsubito**, the proven musl toolchain box):
   - install in-job: `musl-tools` + `cmake` + `rustup target add x86_64-unknown-linux-musl`
   - env: `CC_x86_64_unknown_linux_musl=musl-gcc` (aws-lc-sys/bundled-sqlite C compile)
   - `cargo build --release --target x86_64-unknown-linux-musl --bin spt` → upload artifact `spt-x86_64-linux-musl` (asset name matches the W2 registry row exactly).
2. **assemble job** — `spt-x86_64-linux-musl` joins SHA256SUMS + the release upload set (derive from `SUPPORTED_PLATFORMS`, don't hardcode a third literal).
3. **release-publish (xtask)** — signs the musl artifact under the SAME whole-artifact Ed25519 flow (REQ-UPD-9 single-artifact verify); no per-platform signing divergence.
4. **update-set** — carries the musl artifact entry (`update-set.json` SignedRelease envelope per [[v0190-published]]) so a musl node's `fetch` selects it.

## Gate criteria (doyle — release-pipeline touch → REAL E2E, no mocks)
- clippy `--workspace --all-targets -D warnings`; `traceable-reqs check --json` exit 0 (`REQ-RELEASE-MUSL-ARTIFACT` +impl +unit +int).
- Full `nextest --workspace` BOTH legs (Windows hfenduleam + Linux kitsubito) green — gnu/windows release/update/apply/propagate suites UNCHANGED (musl additive).
- **The int gate is a real cut**: assemble a **draft/test release** carrying the musl artifact, then on a **static musl binary running on a sub-2.39-glibc box**:
  - `spt update fetch` → gets the musl artifact (NO `NoArtifactForPlatform`)
  - verifies SHA256 + Ed25519 signature **over the musl bytes**
  - `apply` → self-updates → the re-launched binary self-reports `x86_64-unknown-linux-musl` at the fetched version.
- gnu default-Linux path unchanged: a gnu node still fetches `spt-x86_64-linux`, never the musl asset.

## Sequencing
W1 ✅ → W2 ✅ → **W3 (this)** → gate → **release publish (deployah)**. Do NOT solo the publish — hand the gated, signed, E2E-proven artifact to deployah for the actual release cut ([[dont-solo-across-role-lines]]). doyle gates W3 + rules the release readiness; deployah drives the publish.

## Watch-fors
- **`Win update-exe UAC-740`** is Windows-only — irrelevant to musl, but don't rename the musl asset into an installer-detected name.
- **CI runner contention** ([[seedmap-test-collides-live-daemon]]): kitsubito is the musl BUILD box AND a gnu CI runner — a musl build job racing a gnu test job on the same box can leak/contend. Sequence the matrix or scope the daemon sweep; a Phase-A e2e daemon-timeout on kitsubito is contamination, not a musl regression (W2 CI hit exactly this — rerun cleared it).
- update-set **stale-serve window** ([[release-updateset-stale-window.md]]): upload-before-flip holds for the musl entry too.

Co-authored by: doyle
