docs(product): spec S18 — VST3 channel isolation (beta ReaSampler 9000 pairs with beta extension only)

This commit is contained in:
2026-07-26 23:37:53 -04:00
parent be67c93b39
commit 0e9ef05c75
3 changed files with 200 additions and 0 deletions
+45
View File
@@ -918,6 +918,51 @@ This reshapes S16 and **flips the r7 WDL verdict** on `WDL_SimplePitchShifter`.
with forks S16-F1/F2 and the corrected WDL finding) and the S15 × S16 interaction note;
CONTEXT.md §Pitch engine modes — Varispeed vs Preserve + the corrected WDL surface finding.
### Addendum — VST channel isolation (Daniel, 2026-07-26)
**Daniel's directive (2026-07-26, settled):** *"support the beta/stable channels for the VST
as well. The VST in beta should talk to the beta extension only."* This extends Phase V's V4
beta/stable split — which fully isolated the **extension** per channel — to the **ReaSampler
9000 VST3 instrument**. Spec'd as **S18**, an immediate Phase S wave, dispatchable in parallel
with or right after the in-flight waves (S9 ext_keys, S15/S16 processor/editor) — it touches
`vst_entry.cpp` / `reasampler_vst.h` / the CMake VST3 block, mostly disjoint from those.
**Established honestly from the tree — what already works vs. what's missing:**
- **Already isolated (the V4↔S4 reconcile did this): data pairing.** A beta-built VST already
*reads* the beta namespace — `ext_keys.h`'s `kProjExtNamespace()` delegates to
`app_version::extStateNamespace()`, and every wire key (`banks`, `assign_request`, S9's
generation key, S17's blob key, any future key) is a plain constant *under* that namespace.
Channel data-isolation is therefore **structural, not per-key** — new keys inherit it for
free. No S18 work here.
- **Missing: the VST's *plugin identity*.** Its class UID, binary filename, and display
strings are single-valued (same for both channels), so two installed channels would collide
on UID and filename. S18 closes exactly this.
**The shape of S18 (mirrors V4's philosophy — one channel per binary, one bit drives it):**
1. **A UID pair.** The stable class UID is locked forever (S-NAME-1). Beta needs its own
forever-stable UID (a second constant, minted once, locked identically). Both frozen
forever; the channel bit selects which is compiled in. **One class per binary, not both**
— the V4 fully-isolated-binary philosophy, so a beta build never presents the stable
identity. Saved-project isolation follows: a beta-saved instance rebinds only to the beta
VST. *Fork S18-F1 (Daniel's call):* mint the beta UID **now** (lean — mirrors the stable
UID minted at the S1 spike, removes a pre-ship landmine, zero cost unused) vs. defer to
first beta release behind a locked-once placeholder.
2. **Channel-derived binary + display identity.** `reasampler_9000` / `reasampler_9000_beta`
filename (mirror the extension's `OUTPUT_NAME` fork); "ReaSampler 9000" / "ReaSampler 9000
beta" display; editor title + embed label channel-aware — all from the ONE bit via
`app_version` accessors, no scattered `#ifdef`s (the V4 invariant).
3. **The pairing guarantee, stated as an invariant.** A channel's VST talks to that channel's
extension only, because identity keeps the plugins distinct and the channel-derived
namespace keeps the data distinct. **Structural, not per-key** — S8/S9/S17's cross-artifact
keys all inherit it; a future key that forgets to isolate is impossible by construction.
4. **DAW-verify contract.** Both channels installed side-by-side; each browser sees only its
channel's banks; stable-project + beta-VST = clean empty (not error); the S-NAME-1
rename/rebind test extends to the beta UID.
**Where the spec lives:** PLAN.md §S18; CONTEXT.md §VST3 channel identity — the UID pair + the
pairing surface. The pairing surface's data half is already load-bearing V4 machinery; S18
adds only the identity fork on top.
---
## Where this landed