diff --git a/docs/COMPLETED.md b/docs/COMPLETED.md index de49d1a..b3af1cf 100644 --- a/docs/COMPLETED.md +++ b/docs/COMPLETED.md @@ -754,3 +754,76 @@ bank-format change under the current deserializer, which fails the whole bank bl an out-of-range value — it wants its own decision); and `instrument_bake` copies the interleaved render buffer into a `std::vector` for the WAV build, roughly doubling peak memory for a large bake. + +### Phase Ψ — The extension trust pass: exact bounds, disjoint solo surfaces, reachable actions, honest drops, real names, true mono + +Seven tracks across three waves, code-complete, reviewed, remediated, and integrated on +this branch: 89/89 tests passing, a clean build. Phase Ψ came from a direct list of +seven defects and refinements (Daniel, 2026-08-01) rather than a backing product doc — +see `docs/PLAN.md`'s Phase Ψ section for the Ψ.1–Ψ.7 provenance list this phase traces +back to. + +**Ψ-W1-T1 — `capture-range-exactness`.** A ranged item capture now renders the +requested window instead of the whole item, by re-sourcing through the selected-tracks +render when the item extent does not already print the window. **Deviation worth +recording:** the spec named two candidate architectures; the engineer shipped a +*conditional* form of candidate (a) — the full-extent case runs literally unchanged +code, which makes the byte-identity regression floor structural rather than hoped-for, +and makes the fix cheap to revert if the underlying inference proves wrong. Also added: +a transient isolation guard cutting `B_MAINSEND` on direct folder children and muting +receives so an item capture stays true to item scope, and a post-render frame-count +gate (±1 tolerance, tail-None only) that refuses and self-cleans a widened render. New +modules `core/capture/render_window`, `core/capture/track_topology`, +`shell/capture/render_selection`, `shell/capture/render_isolation`. + +**Ψ-W1-T2 — `mode-switch-discipline`.** Per-mode SOLO surfaces: solo cached, cleared, +and replayed across a Design/Arrange switch, with the switch itself visibly refused +while the transport runs. New `core/view/solo_cache`, `shell/view/view_solo`. Also +closed a pre-existing bug where a footer mode-segment click never persisted view state. +Required amending a thrice-stated never-touch-solo invariant (`src/shell/view/CLAUDE.md`, +`src/core/view/CLAUDE.md`, `docs/product/design-view.md`) to the snapshot sense of +non-destructive: solo is cached per mode on a real switch and restored verbatim, not +left untouched absolutely the way `B_MUTE` and the master track are. + +**Ψ-W1-T3 — `media-explorer-section`.** The Media Explorer import action is published +into REAPER's Media Explorer action section (32063) via `custom_action` + +`hookcommand2`, while remaining in Main so existing keybindings survive. A second +FOREVER-STABLE id was minted — `INGEST_IMPORT_MEDIA_EXPLORER_MX` — permanent, per +channel. The root `CLAUDE.md` REAPER extension contract gained the second, +non-main registration mechanism alongside the original four-step main-section pattern. + +**Ψ-W1-T4 — `drop-target-resolution`.** The drag-out gesture became a per-move, +stateless law: target class resolves from what is under the cursor on every move, +transitions reversible, OS hand-off reserved for leaving REAPER. The whole TCP/MCP is +now the instrument-drop hotspot; a single-card arrange drop lands a timeline item at +the pointer's track and time; every surface has a defined outcome and cue, no silent +no-op release anywhere. New `shell/actions/arrange_drop_win`. + +**Ψ-W2-T1 — `capture-naming`.** Captures are named after their source track plus a +discriminator (` [+N] [#ordinal] MM-DD HHMM`) at every interactive mint site, +with the name shown on the panel card over a scrim clearing the 4.5:1 contrast floor. +New `core/capture/capture_name`. Recapture, ingest, and the bake deliberately keep +their own naming. + +**Ψ-W2-T2 — `mono-collapse`.** A capture whose channels are bit-identical collapses to +one lossless mono channel, written via temp file plus atomic rename, with the index's +channel count now *measured* off the landed file rather than echoed from the request. +Required amending root `CLAUDE.md`'s channel-count-preserved precision invariant — the +current wording ("no lossy channel fold... one permitted collapse is lossless") is the +landed form. + +**Ψ-W3-T1 — `track-scope-range` — a wave that did not exist when the phase was +scoped, and consolidates none of the original seven.** Opened after Ψ-W2's review +surfaced that the track scope carried the same multi-track stem-collapse hole +Ψ-W1-T1 had just closed for item scope. Now any multi-track selected-tracks render +refuses, both scopes, keyed on the render *source* rather than the capture scope. +Realtime deliberately diverges — it sums correctly and was left untouched. + +**None of the seven is DAW-verified.** All are code-complete and unit-tested; none +has been confirmed in a running REAPER. Several rest on a **shared unverified +inference** about how REAPER's selected-tracks render source interacts with custom +time bounds — and Ψ-W3's refusal now rests on it too, meaning if the inference is +wrong that refusal costs a working capture. Each track's DAW-verification obligation +is recorded in `docs/PLAN.md`'s Phase Ψ section; `docs/verify-track-scope-multitrack.md` +is a new standalone verification script on this branch, for Ψ-W3-T1's multi-track +refusal specifically. No human has observed any of these seven behaviors in a DAW.