# MUSL-TIER W1 — DISPATCH RULING (doyle → todlando)

**GO 2026-07-08 (operator "start now, drive to release publish").** Branch off `main` @738eb28. Activate `REQ-PLATFORM-REGISTRY` `required_stages = ["impl","unit"]` in the work-start commit ([[traceable-per-wave-activation]]).

## CONTEXT grounding (checked — design-aligned, no conflict)
- **CONTEXT.md:3** — "Windows + Linux for v1 … kept structurally easy … a later test/CI-budget decision, **not a re-architecture**." Adding a platform must be additive. This wave makes it so.
- **CONTEXT.md:828** — novel Linux platforms (handhelds) foreseen; "relocatable binary + minimal, non-OS-entangled install." (W2/W3 deliver the musl artifact; W1 is the enabling refactor.)
- **ADR-0016** (platform-targeted update sets) + **CONTEXT.md:575** — per-platform artifact set is the model; `NoArtifactForPlatform` is *designed* behaviour for a missing platform.

## Ruling — registry shape: **const-table, NOT enum**
One authoritative table; everything derives from it. Rationale: adding a platform = adding one row (CONTEXT:3 "structurally easy"), no match-arm sprawl across methods.

```rust
pub struct PlatformSpec { pub triple: &'static str, pub asset_name: &'static str }
pub const SUPPORTED_PLATFORMS: &[PlatformSpec] = &[
    PlatformSpec { triple: "x86_64-pc-windows-msvc",  asset_name: "spt-x86_64-windows.exe" },
    PlatformSpec { triple: "x86_64-unknown-linux-gnu", asset_name: "spt-x86_64-linux" },
    // W2 adds: { "x86_64-unknown-linux-musl", "spt-x86_64-linux-musl" }
];
```
- **`KNOWN_TARGET_TRIPLES`** (release.rs:190) → derive from `SUPPORTED_PLATFORMS.map(|p| p.triple)` (keep the const name/type if callers depend on `&[&str]`; a helper or a `once`/const-fn projection).
- **`current_platform()`** (release.rs:196-211) STAYS a `cfg`→triple fn (a running binary's triple is a **build fact**, cfg-selected — not runtime-derivable). Keep the loud `"unknown"` fallback. ADD a unit asserting `current_platform()` is a member of `SUPPORTED_PLATFORMS` for the compiled target (self-identity can't drift from the registry).
- **`applyhost.rs:740-743`** — the "the OTHER platform" binary `if me==windows { linux } else { windows }` is the **N-platform blocker**. Generalize to "every `SUPPORTED_PLATFORMS` triple except `current_platform()`" (a filter). Preserve the existing semantic (a node's own platform vs the others) — the test that uses it must stay green.
- **asset-name ↔ triple map** (`xtask/src/main.rs:598-599`) → derive from the table (lookup by `asset_name`).
- Test literals (`cli.rs:16922-923`, release.rs/update.rs/net-update.rs) — leave as-is unless they block; they assert on the existing two triples, which are unchanged.

## Behaviour-neutral — the gate IS the unchanged green suite
gnu + windows behaviour **byte-identical**: same triples, same asset names, same `current_platform()` outputs. No new platform this wave (musl is W2). The existing **release / update / apply / propagate** test suites stay green — that is the proof of neutrality, not a new test (beyond the `current_platform ∈ registry` unit + a registry-projection unit).

## Gate criteria (doyle)
- clippy `--workspace --all-targets -D warnings`; `traceable-reqs check --json` exit 0 (REQ-PLATFORM-REGISTRY +impl +unit).
- Full `nextest --workspace` BOTH legs (Windows hfenduleam + Linux kitsubito) — release/update/apply/propagate suites unchanged + green.
- Diff review: no behaviour change for gnu/windows; `SUPPORTED_PLATFORMS` is the single source; applyhost generalized correctly (N-platform, not hardcoded pair).
- A musl build is NOT required for W1 (that's W2) — but the tree must still compile for a musl target (the `"unknown"` fallback stays until W2 adds the arm).

## Sequencing
W1 (this) → gate → **W2** (register musl: `current_platform()` musl cfg arm + the musl `PlatformSpec` row + asset map; DNS/crypto/build already proven) → gate → **W3** (CI musl build + sign + update-set publish + self-update E2E on a sub-2.39-glibc box) → gate → release (deployah publishes). doyle drives the whole arc.
