diff --git a/docs/TODO.md b/docs/TODO.md index 14b8c2d..87fa831 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -847,24 +847,6 @@ doc-keeper edit. **Done looks like.** The enumeration distinguishes "in the project's state" from "on disk in the `.rpp`", and does not gain a second home for the distinction. -## The VST3 parameter surface's DAW-verifiable claims - -**Context (what shipped — Γ-W4-T1).** The instrument reports 44 automatable parameters under the frozen id table, services both delivery channels (the controller's `setParamNormalized` and the audio thread's `IParameterChanges` drain), and folds automated values back into the blob on the UI thread. - -**What is settled without a DAW.** The channel question itself is answered by the vendored SDK, not by observation: `ivsteditcontroller.h` documents `setParamNormalized` as the GUI-update channel ("should update the according GUI element(s) only"), and the SDK's own `SingleComponentEffect` sample (`public.sdk/samples/vst/again/source/againsimple.cpp`) drains `ProcessData::inputParameterChanges` in `process()` while also implementing `setParamNormalized`. Servicing both is what the SDK's own precedent does; it needs no verification, only exercise. - -**What genuinely needs a running REAPER, and why none of it can change the design.** Each item below is a host BEHAVIOUR, not a contract — the plug-in is correct under either answer, so discovering the answer costs a display fix at worst: - -1. **Whether REAPER renders `ParameterInfo::units` beside the string `getParamStringByValue` returns, or shows the string alone.** We ship the SDK's own convention (digits in the string, unit carried separately). If REAPER shows no unit at all, the fallback is to append the unit inside the one formatter — one line in one place, touching neither the frozen id table nor the editor, because display strings are explicitly not frozen. -2. **Whether REAPER's own per-parameter MIDI learn covers what a shipped `IMidiMapping` CC table would have.** The decision to ship no default map rests on it; if learn does not reach these parameters, a CC table is additive and frozen by nothing. -3. **That the three migration round trips hold**: a pre-parameter project opens with every parameter reading the blob's value and sounds identical; a project saved by this build restores fully in an older binary; a project with automation drawn, saved and reopened, replays against the same plain values. -4. **That an offline render replays automation** — the sharpest case for the audio-side drain, because the host drives `process()` and may never touch the controller. -5. **That REAPER restores instance state through `setState`, not `setComponentState`.** This is the ENTRY-POINT half of the original bundled `[verify, FIRST]`; the pass that closed that item closed only its delivery-channel half, which is a different question. The evidence short of a DAW is strong but is inference: `vstsinglecomponenteffect.h:41-47` collapses the two names on a single-component plug-in, our `setState`/`getState` overrides land on the `IComponent` pair with `setEditorState`/`getEditorState` left at the base's `kNotImplemented`, and the blob has round-tripped through payload v1…v16 in real projects. Exercising it costs one save/reopen. - -**Priority / risk.** Low. Nothing here is load-bearing on the frozen contract: the id table, the plain ranges and the norm↔plain laws are all decided and tested without a host. - -**Done looks like.** Each of the four exercised once in REAPER, with the unit-rendering answer recorded and, if it went the other way, the one-line formatter change made. - ## `view_mode_model.cpp` is over the ~600-line structural bar, and `view.cpp` is close behind **Context (surfaced by the FX-GUID keying track).** Root `CLAUDE.md`'s structural diff --git a/docs/VERIFICATION.md b/docs/VERIFICATION.md index 1d2ccdc..0330528 100644 --- a/docs/VERIFICATION.md +++ b/docs/VERIFICATION.md @@ -1,6 +1,6 @@ # DAW verification — post-1.0 work on `dev` -Checks for Θ, Ξ, Ψ, Ε, and Ρ work that no unit test can close. Build **Release**, install into +Checks for Θ, Ξ, Ψ, Ε, Ρ, and Γ work that no unit test can close. Build **Release**, install into `UserPlugins/`, restart REAPER. Panel tail toggle = **None**, project rate 48000, unless a check says otherwise. ## Precision invariants @@ -174,3 +174,29 @@ Checks for Θ, Ξ, Ψ, Ε, and Ρ work that no unit test can close. Build **Rele - [ ] Piano strip at the 840 px default — keys tile uniformly, the 37 px end gutters read as acceptable (`docs/COMPLETED.md` §"Θ-W2-T3") - [ ] Resize the editor across several widths — gutters stay symmetric, no key width jumps (`docs/COMPLETED.md` §"Θ-W2-T3") - [ ] Set host/OS scaling to 150% then 200% — record how the strip and the AA strokes actually look (`docs/TODO.md` §"High-DPI host scaling is unverified (distinct from the antialiasing audit)", `docs/COMPLETED.md` §"Θ-W2-T3" — "Width uniformity is guaranteed in client pixels only") + +## The VST3 parameter surface + +- [ ] `[verify — DAW]` Whether REAPER renders `ParameterInfo::units` beside the string + `getParamStringByValue` returns, or shows the string alone. We ship the SDK's own + convention (digits in the string, unit carried separately); if REAPER shows no unit at + all, the fallback is a one-line change to the single formatter, touching neither the + frozen id table nor the editor (`docs/COMPLETED.md` §"Γ-W4-T1") +- [ ] Whether REAPER's own per-parameter MIDI learn covers what a shipped `IMidiMapping` + CC table would have — the decision to ship no default map rests on it; if learn does not + reach these parameters, a CC table is additive and frozen by nothing (`docs/COMPLETED.md` + §"Γ-W4-T1") +- [ ] The three migration round trips: a pre-parameter project opens with every parameter + reading the blob's value and sounds identical; a project saved by this build restores + fully in an older binary; a project with automation drawn, saved and reopened, replays + against the same plain values (`docs/COMPLETED.md` §"Γ-W4-T1") +- [ ] `[verify — DAW]` **Whether an offline render replays automation at all** — the + sharpest case for the audio-side drain, because the host drives `process()` and may + never touch the controller (`docs/COMPLETED.md` §"Γ-W4-T1") +- [ ] `[verify — DAW]` **Whether REAPER restores instance state through `setState`, not + `setComponentState`** — the entry-point half of the original bundled `[verify, FIRST]` + that an earlier pass closed only the delivery-channel half of. The evidence short of a + DAW is strong but is inference: `vstsinglecomponenteffect.h:41-47` collapses the two + names on a single-component plug-in, and the blob has round-tripped through payload + v1…v16 in real projects. Exercising it costs one save/reopen (`docs/COMPLETED.md` + §"Γ-W4-T1")