docs(phase-s): spec three-view editor redesign (S-VIEW) — Sample/Browse/Zone
This commit is contained in:
+290
-27
@@ -2139,6 +2139,274 @@ not a raw literal). What S18 adds is only the missing *plugin identity* layer.
|
||||
headers before use — several §1a claims are experienced estimates until the spike
|
||||
confirms them.
|
||||
|
||||
## Editor view-model redesign — three views: Sample / Browse / Zone (S-VIEW; Daniel, 2026-07-27, r9)
|
||||
|
||||
> **Additive sub-phase of Phase S — an *editor* redesign, not an engine change.** Re-partitions
|
||||
> the ReaSampler 9000 editor from today's two-view toggle (Browser + Zones) into a **three-view
|
||||
> model where the loaded sample is the home**, adds two new performance parameters (key-tracking,
|
||||
> preview velocity) and two visual components (envelope overlay, real piano-key pattern), and
|
||||
> frames two engineering prerequisites (drop-to-FX bug, default window size). The S3 voice
|
||||
> engine, keymap resolution, and read-only-over-bank contract are **unchanged**; the
|
||||
> component-state format extends additively for key-tracking. Product framing: `docs/product/
|
||||
> midi-playback.md` §Addendum r9. Same standing discipline: **LICE/SWELL drawing only,
|
||||
> all layout/hit-test in pure geometry modules, RT-safe, VST3 class UID unchanged, verify every
|
||||
> API name/signature against the vendored headers before use.**
|
||||
|
||||
### The view model — Sample is home; Browse is modal; Zone is a dedicated surface
|
||||
|
||||
The three views are **not a flat three-way toggle** (today's Browser|Zones segmented switch is
|
||||
retired). The model is **document-with-modal-picker** (mirror: Ableton Simpler — the device face
|
||||
*is* the loaded sample; loading a new one is a distinct act):
|
||||
|
||||
- **Sample (the home / default face).** What the editor shows on open with a capture loaded. The
|
||||
hero waveform, the envelope overlay, all per-sample tuning controls, the preview-trigger. This
|
||||
is where the user lives.
|
||||
- **Browse (a modal page layered over Sample).** Summoned by a **Browse button** (and, when
|
||||
nothing is loaded, the empty-state's primary affordance — Browse must be *very* easy to open
|
||||
when there is no capture selected). It renders as a **full-window overlay** over the Sample
|
||||
face — filters + captures grid + **select-then-confirm** to change the loaded sample, then
|
||||
dismisses back to Sample. It is a picker sheet, not a peer tab.
|
||||
- **Zone (a dedicated editing surface).** Opened by its own **Zone button** when the user wants
|
||||
to map the capture(s) across the keyboard. Not shown by default ("most of the time zones won't
|
||||
be used" — the S10 reframe). Returns to Sample on close.
|
||||
|
||||
**Navigation contract.** From Sample: a Browse button opens the Browse overlay; a Zone button
|
||||
opens the Zone surface. From Browse: select a card + confirm (or cancel) returns to Sample with
|
||||
(or without) a new loaded capture. From Zone: a close/back affordance returns to Sample. The
|
||||
empty state (no capture loaded) surfaces Browse as its dominant call-to-action. **The fresh
|
||||
instance stays silent with a "pick a capture" empty state (S10 reversal, unchanged).**
|
||||
|
||||
### View 1 — Sample (the new main view)
|
||||
|
||||
The home face. Composition follows the reference devices (Simpler / Phase Plant): a **hero
|
||||
waveform up top with the envelope drawn over it at accurate time**, a **dense labelled
|
||||
value-strip beneath**, **root fenced as its own affordance**, and a **preview cluster**. Bands,
|
||||
top to bottom:
|
||||
|
||||
- **Title band.** Plugin name (channel-derived `vstPluginName()`) + live readout (loaded capture
|
||||
name / `[pick a capture]` / `[bank empty]` / `[host: no bridge]`) + the **Browse** and **Zone**
|
||||
view buttons. (Inherits today's title-band text logic.)
|
||||
- **Hero waveform band (enlarged) with the ENVELOPE OVERLAY (new).** The picked capture's
|
||||
full-resolution envelope (from `peaks` over the cached mono PCM — no new decode), given real
|
||||
vertical space (the Simpler/Phase-Plant hero, materially taller than today's 72px strip). Drawn
|
||||
over it, at **accurate wall-clock time**: (a) the **S11 markers** — start (teal/secondary),
|
||||
loop start/end (purple/tertiary), the faint loop-region fill — moved here from Browse
|
||||
unchanged; and (b) the **NEW amplitude-envelope overlay** — the AHDSR shape (Gate) or the
|
||||
fade-in/%-length/fade-out shape (Trigger) traced as a curve across the sample at the same time
|
||||
base the voice engine uses, in an accent hue. This is the "reads like a real sampler, not a
|
||||
spreadsheet" move: the envelope becomes a *shape over the sound*, not four abstract sliders.
|
||||
- **Root + preview cluster (fenced, new preview-trigger).** Root note shown as a first-class,
|
||||
always-visible control (fenced like Phase Plant's "Root" box), draggable/typeable — this is the
|
||||
keyboard-strip root-drag from today's Browse setup, promoted to a fenced control. Adjacent: the
|
||||
**NEW preview-trigger button** (fires the sampler at the loaded capture's root note through the
|
||||
live voice engine, off the audio-thread commit path — no MIDI controller needed) with an
|
||||
**adjacent velocity knob** setting the preview velocity level. The **Mono/Stereo toggle** moves
|
||||
here from Browse (it is a per-capture output-mode tuning concern, not a choosing concern).
|
||||
- **The "Modes-and-down" control strip (moved from Zone).** Every per-sample control that lives
|
||||
on today's Zones param panel for the single-capture case — **Mode** (Gate/Trigger), **Pitch
|
||||
engine** (Varispeed/Preserve), the **AHDSR** sliders (Gate) or **Length%/Fade-in/Fade-out**
|
||||
(Trigger), and the **AD pitch envelope** (Off/On + P.Attack/P.Decay/P.Depth) — renders here as
|
||||
the Sample view's control strip, laid out as a dense labelled value-row (bold micro-caps over a
|
||||
value/slider, the reference grammar). For a single loaded capture this is the same one-zone
|
||||
storage site the S15-F2 lean already established (the empty-map single-capture face reads/writes
|
||||
the same `PerformanceZone` defaults) — no new storage.
|
||||
|
||||
**Browse elements that MOVE to Sample (inventory — nothing silently dropped):** the large
|
||||
waveform preview, the S11 start/loop markers + loop fill, the keyboard-strip root affordance (now
|
||||
the fenced root control), and the Mono/Stereo toggle.
|
||||
|
||||
### View 2 — Browse (reduced to *choosing*, laid over Sample as a modal)
|
||||
|
||||
Browse's only job is **pick a capture**. Today's Browser view is close but overloaded; it is cut
|
||||
to the choosing essentials and rendered as a modal overlay:
|
||||
|
||||
- **Kept (the excellent core, unchanged):** the **type-to-filter search box**, the **bank filter
|
||||
tabs** (All + one per named bank), the **captures grid** (cards: peak thumbnail + name +
|
||||
root/key badge), **scroll** (wheel + thumb), and card **selection**.
|
||||
- **Added:** a **confirm/cancel** affordance (select a card, confirm to load it into Sample and
|
||||
dismiss; cancel to dismiss unchanged) — the modal-picker close semantics. Double-click-to-load
|
||||
is the natural accelerator.
|
||||
- **Removed from Browse (moved to Sample or cut):** the **large waveform preview** (redundant —
|
||||
the grid thumbnails already show every capture's waveform; moved to Sample as the hero); the
|
||||
**Mono/Stereo toggle** (moved to Sample); the **root-note keyboard-strip** in the setup band
|
||||
(moved to Sample as the fenced root control); the **loop-point labels** and the **track-root
|
||||
message** (cut — they waste space and add nothing to *choosing*).
|
||||
|
||||
**Rationale (why cut, not keep-and-hide):** Browse is a picker. Every tuning affordance on it is
|
||||
a mode error — you tune what you *have*, you browse for what you *want*. Concentrating tuning on
|
||||
Sample and choosing on Browse makes each view do one job, and makes the modal overlay light
|
||||
enough to summon and dismiss without ceremony.
|
||||
|
||||
### View 3 — Zone (dedicated keyboard-mapping surface + key-tracking + real piano pattern)
|
||||
|
||||
Zone is the multi-zone keymap editor — RS5K structurally lacks a multi-zone-in-one-instance view,
|
||||
so this is a genuine capability, kept as the deliberate secondary surface. Retains today's Zones
|
||||
view wholesale, with two changes:
|
||||
|
||||
- **Kept (inventory — nothing silently dropped):** **+ Add Zone** / **Delete** buttons, the
|
||||
**keyboard strip with one bar per zone** (selected zone lit accent-primary + static glow, others
|
||||
categorical), the **selected-zone legend** with the three **Low/High/Root numeric-entry fields**
|
||||
(click-to-type, `parseNoteEntry`), and the **per-zone param control panel** (Mode, Pitch engine,
|
||||
AHDSR/Trigger, AD pitch envelope) — the same panel Sample now also hosts for the single-capture
|
||||
case (one storage site, two surfaces).
|
||||
- **NEW — key-tracking parameter (0%–200%, default 100%).** A per-`PerformanceZone` scalar on how
|
||||
sample pitch tracks the keyboard around the root note. **100% = standard 12-tone-ET tracking**
|
||||
(today's behavior, bit-identical); **0% = no tracking** (the sample plays at root pitch on every
|
||||
key — a fixed one-shot); **200% = double-rate tracking**. Additive on `PerformanceZone`,
|
||||
version-bumped, defaulting to 100% so pre-existing zones are unchanged. Applies inside the
|
||||
repitch math in **both** engines: under **Varispeed** it scales the semitone offset feeding
|
||||
`pitchRatio(note, root)` (`effectiveSemis = (note − root) · keyTrack`); under **Preserve** it
|
||||
scales the semitone offset feeding `set_shift(2^(effectiveSemis/12))`. Surfaces as a control in
|
||||
the Zone param panel (and, for the single capture, on the Sample control strip). **The pure
|
||||
sampler core owns the key-track math** (unit-tested: a known note/root/keyTrack triple asserts
|
||||
the expected ratio); the shell only maps the 0–200% control to the scalar.
|
||||
- **NEW — real piano-key pattern on the keyboard strip.** Today's spectral strip is pretty but
|
||||
does not read as a keyboard (Daniel's note). Keep the pastel spectral hue as the backdrop, but
|
||||
**overlay the actual alternating white/black key pattern** — bright cells for naturals, dark
|
||||
cells for accidentals (C#/D#/F#/G#/A#), per the palette (bright ≈ a light neutral, dark ≈
|
||||
`bg/base`/hairline) — so the strip is instantly identifiable as a keyboard. It need not be
|
||||
*shaped* like a keyboard (no protruding black keys); it carries the **pattern** as an overlay,
|
||||
so a glance reads pitch position without counting. The pure `keyboard_strip` geometry gains a
|
||||
`isBlackKey(note)`/per-key-natural query (12-tone pattern, pure + unit-tested); the shell draws
|
||||
the two-tone overlay over the spectral fill. This same strip serves the Sample view's fenced
|
||||
root affordance (one keyboard grammar everywhere).
|
||||
|
||||
### New parameters — ownership and persistence (D-B; instrument-owned, never bank facts)
|
||||
|
||||
- **Key-tracking** — per-`PerformanceZone`, additive/version-bumped component state, default 100%.
|
||||
A **performance choice**, never written to `Sample` or the bank. Back-compat: an absent field on
|
||||
an older blob → 100% (bit-identical playback).
|
||||
- **Preview velocity** — a **utility** setting for the Sample view's preview-trigger button, not a
|
||||
musical parameter of the capture. **Lean: transient editor state** (like a metronome level) —
|
||||
it does not need to persist in component state, so it adds no version bump and no bank-fact risk.
|
||||
*(Fork S-VIEW-F1, Daniel's call: transient vs. a small persisted editor convenience. Lean
|
||||
transient — simplest, no compat surface, and a preview level is not something users expect to
|
||||
survive a reload.)*
|
||||
|
||||
### The envelope overlay — visual component (new)
|
||||
|
||||
The amp envelope drawn as a curve over the Sample view's hero waveform at accurate wall-clock
|
||||
time (the Simpler/Phase-Plant grammar). Gate → the AHDSR shape (attack ramp, hold, decay to
|
||||
sustain, release tail); Trigger → the fade-in/unity/%-length/fade-out shape anchored to `playEnd`.
|
||||
The time base is the same the voice engine resolves (seconds → frames at the live rate), so the
|
||||
drawn shape lines up with the waveform under it. **Pure geometry:** an `envelope_overlay` module
|
||||
(mirror of `waveform_view` / `param_slider`) maps the AHDSR/Trigger params + the sample's
|
||||
frame-length to a polyline in the waveform rect (`param↔pixel` at the shared time base),
|
||||
unit-tested against known param sets; the shell traces it via kit line draws in an accent hue.
|
||||
Decorative + informative — it never captures input (the sliders remain the edit surface); dragging
|
||||
the envelope *nodes* directly is a deferred stretch (fork S-VIEW-F2, lean defer — sliders first,
|
||||
node-drag is polish once the overlay reads).
|
||||
|
||||
### The real piano-key pattern — visual component (new)
|
||||
|
||||
Covered under View 3 above. Pure: `keyboard_strip` gains the natural/accidental predicate; shell
|
||||
draws the bright/dark overlay over the existing pastel spectral fill. Shared by the Zone strip and
|
||||
the Sample root affordance.
|
||||
|
||||
### Engineering prerequisite 1 — drop-to-FX bug (routed to implementation, NOT a design call)
|
||||
|
||||
**Symptom (Daniel):** dropping a capture onto a track's FX chain does not instantiate + init
|
||||
ReaSampler 9000 — the audio-to-arrange drop works, but the "instrument init never fires."
|
||||
|
||||
**SDK sweep (done this pass — no false ceiling asserted):** the S17 drop-to-FX machinery is
|
||||
**present and SDK-correct**. `src/instrument_drop_win.cpp` calls `TrackFX_AddByName(track,
|
||||
"VST3:" + vstPluginName(), /*recFX*/false, /*instantiate*/-1)` then injects component state via
|
||||
`TrackFX_SetNamedConfigParm(track, fx, "vst_chunk", <base64>)`; both signatures + semantics are
|
||||
**verified present** in `reaper_plugin_functions.h` (the `VST3:` prefix, negative-instantiate =
|
||||
always-new, and the `vst_chunk` base64 write-parm are all documented). The gesture is wired
|
||||
(`src/bank_panel.cpp`: `decideGesture` → `InstrumentDrop` → on release `buildInstrumentDropChunk`
|
||||
→ `performInstrumentDrop`), FX-hotspot detection uses `GetThingFromPoint` (`fx_*` prefix), and the
|
||||
factory registers `kInstrumentSynthSampler` correctly. **So the platform CAN do this — the
|
||||
capability is not in question; the wiring is present.** This is therefore a **runtime diagnosis
|
||||
task, not a design decision or a platform-ceiling problem.** The likely fault domains for
|
||||
staff-engineer to investigate (in order):
|
||||
1. **FX-name resolution:** whether REAPER's scanned name for the plugin exactly matches `"VST3:" +
|
||||
vstPluginName()` (a display-name/scan-name mismatch would make `TrackFX_AddByName` return −1).
|
||||
2. **The gesture reaching `performInstrumentDrop`:** whether `decideGesture` actually resolves
|
||||
`InstrumentDrop` over an FX button (vs. falling through to `OsDrag`, which produces exactly the
|
||||
observed "drops as audio into arrange" symptom) — check the `overFxHotspot`/`GetThingFromPoint`
|
||||
path and the single-capture arming guard.
|
||||
3. **The `vst_chunk` write / blob format:** whether `TrackFX_SetNamedConfigParm` returns true and
|
||||
the injected blob matches what `setState` accepts (a format drift would create-then-play-nothing
|
||||
rather than fail to instantiate).
|
||||
|
||||
**Routing:** flagged for **staff-engineer** as a bug diagnosis. No product fork; no redesign
|
||||
gates on it, but it is a **functional prerequisite** for the drop-to-FX gesture to feel finished.
|
||||
**Verify in DAW:** drag a capture onto a track's FX button → a ReaSampler 9000 instance appears on
|
||||
that track already playing that capture (one Ctrl-Z removes it).
|
||||
|
||||
### Engineering prerequisite 2 — default window size for 1080p (routed to implementation)
|
||||
|
||||
**Symptom (Daniel):** the editor window is too small by default; assume a 1080p minimum screen.
|
||||
|
||||
**SDK sweep (done this pass — mechanism verified):** the VST3 editor size is set by the
|
||||
`IPlugView`/`CPluginView` contract. `getSize()` returns the view's `rect` (set via `setRect` — the
|
||||
default the host opens at); `checkSizeConstraint()` is where a minimum is enforced; `onSize()`
|
||||
handles host resizes; `canResize()` already returns `kResultTrue`. **Verified in
|
||||
`vendor/vst3sdk/public.sdk/source/common/pluginview.h`.** Today `ReaSamplerEditor`'s constructor
|
||||
sets `ViewRect(0, 0, 560, 400)` — the undersized default. **The fix is a one-line default change**
|
||||
(a larger initial `ViewRect` sized for the new three-band Sample face on a 1080p display) **plus
|
||||
an optional `checkSizeConstraint` minimum** so the host cannot shrink the window below a usable
|
||||
floor. **This is not a platform limitation — the mechanism exists and is trivial.** The exact
|
||||
default dimensions are a build-time value to set against the Sample face's band heights (hero
|
||||
waveform + control strip want materially more than 400px tall; a ~840×560 or larger default is the
|
||||
starting point, tuned at build). **Routing:** flagged for **staff-engineer**; no product fork.
|
||||
**Verify in DAW:** the editor opens at the new default on a 1080p screen showing the full Sample
|
||||
face without scrolling, and cannot be resized below the constraint floor.
|
||||
|
||||
### Module architecture (preserve the pure/shell split)
|
||||
|
||||
- **Pure (new/extended):** `envelope_overlay` (AHDSR/Trigger params + frame-length → polyline in a
|
||||
rect; unit-tested); `keyboard_strip` extended with the natural/accidental predicate; the sampler
|
||||
core extended with the **key-track scalar** in the repitch math (unit-tested against known
|
||||
note/root/keyTrack → ratio); `sample_map` (`PerformanceZone`) extended with the additive
|
||||
`keyTrack` field + component-state version bump + back-compat default.
|
||||
- **Shell (`reasampler_editor.cpp`):** re-partition the paint/hit-test into the three views
|
||||
(Sample face, Browse modal overlay, Zone surface) replacing the two-view toggle; add the
|
||||
preview-trigger button + velocity knob wired to an off-audio-thread preview note through the
|
||||
voice engine; draw the envelope overlay + piano-key overlay via the kit; set the larger default
|
||||
`ViewRect` + `checkSizeConstraint`. All layout/hit-test math stays in the pure geometry modules.
|
||||
|
||||
### Precision / invariant implications
|
||||
|
||||
- **Read-only bank consumer (unchanged).** Key-tracking, preview velocity, and every marker/mode
|
||||
control are the instrument's **performance map** (D-B) — never written to `Sample` or the bank.
|
||||
- **Additive, back-compat component state.** `keyTrack` is a new optional field defaulting to 100%;
|
||||
an older blob (absent field) restores to 100% → **playback bit-identical** under the same engine.
|
||||
No existing field changes.
|
||||
- **RT discipline (unchanged).** The preview-trigger fires a note through the existing voice engine
|
||||
via the off-audio-thread commit path (`commitMapAndReload` idiom); no new `process`-thread work,
|
||||
no allocation on the audio thread.
|
||||
- **VST3 class UID unchanged.** A view reorganization + additive param is **not** a compat event;
|
||||
saved instances rebind and restore. The UID stays the S-NAME-1/S18 forever-locked identity.
|
||||
- **Capture ≠ placement ≠ playback (unchanged).** The preview-trigger plays; it never captures,
|
||||
never inserts a timeline item. The three acts stay distinct.
|
||||
|
||||
### Open questions / forks (Daniel / Phase S team)
|
||||
|
||||
- **S-VIEW-F1 — preview velocity persistence.** Transient editor state (lean) vs. a small persisted
|
||||
editor convenience. Lean transient — no compat surface, no version bump.
|
||||
- **S-VIEW-F2 — envelope-overlay interactivity.** Read-only informative overlay + sliders as the
|
||||
edit surface (lean, ship first) vs. draggable envelope nodes on the overlay (deferred stretch —
|
||||
polish once the overlay reads).
|
||||
- **S-VIEW-F3 — Browse modal presentation.** Full-window overlay (lean — the modal-picker feel) vs.
|
||||
a large centered sheet with a dimmed Sample behind. Presentation detail; either satisfies "easy
|
||||
to summon and dismiss."
|
||||
|
||||
### Must-verify before build (S-VIEW)
|
||||
|
||||
- **Editor size mechanism** — `getSize`/`setRect`/`checkSizeConstraint`/`onSize`/`canResize`
|
||||
**verified present** in `vendor/vst3sdk/public.sdk/source/common/pluginview.h`; confirm the exact
|
||||
min-size enforcement point (`checkSizeConstraint`) behaves under REAPER's host at build.
|
||||
- **Drop-to-FX** — `TrackFX_AddByName` / `TrackFX_SetNamedConfigParm` / `GetThingFromPoint` all
|
||||
**verified present** in `reaper_plugin_functions.h`; the remaining work is **runtime diagnosis**
|
||||
(name match, gesture routing, blob format), not an SDK question.
|
||||
- **Preview note through the voice engine off-thread** — confirm the existing `commitMapAndReload`
|
||||
/ off-thread reload idiom is the right seam to fire a one-shot preview note without touching
|
||||
`process` on the UI thread; no torn state on the atomic voice-engine pointer.
|
||||
- **Envelope-overlay time base** — confirm the seconds→frames resolution the overlay draws against
|
||||
matches the voice engine's live-rate resolution so the drawn shape lines up with the waveform.
|
||||
|
||||
---
|
||||
|
||||
# Look-and-feel — visual design language (Phase L)
|
||||
@@ -2520,12 +2788,10 @@ slots that persist independent of their occupant, no slot actions, no MIDI-binda
|
||||
no capture-to-slot-N. A slot is just a display position a sample occupies; dragging cards
|
||||
rearranges which sample sits where.
|
||||
|
||||
**M9 overlap (awareness note — unchanged intent).** M9 "slots" (capture-to-slot-N /
|
||||
insert-slot-N, MIDI-bindable, MPC-style) remains **explicitly deferred (Daniel, 2026-07-26).**
|
||||
The interchangeable substrate L7 builds still *eases* a future M9 revival — it lays the
|
||||
addressable-position groundwork M9 would sit on — but L7 adds **no** slot-numbered capture/insert
|
||||
actions and **no** MIDI bindings. The "plain vs. M9-shaped" sub-fork is closed: plain
|
||||
gap-preserving substrate, per F2 above.
|
||||
**M9 note.** M9 "slots" (capture-to-slot-N / insert-slot-N, MIDI-bindable, MPC-style) is
|
||||
**abandoned (Daniel, 2026-07-27)** — will not be built. L7 adds **no** slot-numbered
|
||||
capture/insert actions and **no** MIDI bindings. The "plain vs. M9-shaped" sub-fork is closed:
|
||||
plain gap-preserving substrate, per F2 above.
|
||||
|
||||
### 2. Decorative metadata overlay (bars.beats · s.ms)
|
||||
|
||||
@@ -2656,20 +2922,18 @@ overlay/selection-border draw. The L1 kit draws; no palette/font decision re-ope
|
||||
|
||||
## The L3 gate + Phase S coordination contract
|
||||
|
||||
**L3 (VST editor + embed-strip restyle) is GATED on Phase S landing on dev.** The VST
|
||||
editor (`IPlugView` LICE surface), the S6 embed strip, and the keyboard strip live in
|
||||
Phase S, which is **not on dev yet** (it exists on the phase-s worktree). L3 cannot be
|
||||
built on dev until Phase S's editor/embed surfaces (≈ S1 / S6 / S10) merge to dev — **the
|
||||
Phase L team must not chase these files on dev; they are not there.** Until then L3 is a
|
||||
planned, blocked point; L1, L2, L4, L5, L6, and **L7 have all landed** — see `COMPLETED.md`.
|
||||
L4, L5, L6, and L7 are independent of the L3 gate.
|
||||
**L3 (VST editor + embed-strip restyle) has landed (merged `c53683e`, 2026-07-27).** The
|
||||
Phase S surfaces (`reasampler_editor.cpp` + `reasampler_embed.cpp`) arrived on dev drawing
|
||||
flat `LICE_FillRect` blocks + raw GDI `DrawTextA`, off a local pre-L1 forest-green palette
|
||||
— the coordination contract's "born in the kit" branch did not occur — so L3 performed a
|
||||
full restyle of both draw shells through the L1 kit. **L1, L2, L3, L4, L5, L6, and L7
|
||||
have all landed — see `COMPLETED.md`. Phase L is complete.** The Phase Q gate condition
|
||||
"Phase S + L3 merged to dev" is now satisfied.
|
||||
|
||||
**Coordination contract (load-bearing):** Phase S's S10–S13 build their interaction UX with
|
||||
the **current** drawing and **adopt the L1 kit when it is available — they are NOT gated on
|
||||
Phase L.** Whichever lands first (the L1 kit or the S10–S13 UX), the kit is the **one source
|
||||
of drawing**: if S10–S13 reach dev before L1, they draw in the current language and L3
|
||||
restyles them; if L1 lands first, they are born in the kit. Either way there is one kit and
|
||||
one look; L3 completes the VST/embed adoption and applies the settled-and-revised **B +
|
||||
**Coordination contract (load-bearing — resolved):** Phase S's S10–S13 built their
|
||||
interaction UX with the current drawing and adopted the L1 kit via L3 (the coordination
|
||||
contract's "L3 restyles them" branch). There is now one kit and one look across both
|
||||
artifacts; L3 completed the VST/embed adoption and applied the settled-and-revised **B +
|
||||
three-accent pastel** treatment (with C's **pastel** spectral keyboard strip as the
|
||||
signature surface), routing text through the kit's cached-font `text()` (§3.1 — the kit's
|
||||
current face; no font change). The VST3 class UID is unchanged — a visual refresh is not a
|
||||
@@ -2925,8 +3189,9 @@ and **(2) Phase L L3** merged to dev (the VST restyle, itself gated on Phase S).
|
||||
have already landed** (see `COMPLETED.md`) — the earlier "L2 + L3" wording was stale and is
|
||||
corrected to **L3 only**. **D2** is functionally complete (D2-W1..W3-B landed; its lone open item,
|
||||
a per-track lane-split panel indicator, is *explicitly deferred*, not a blocking residual). **M9**
|
||||
(slots) is *explicitly deferred* (Daniel, 2026-07-26), not scheduled work. D2 and M9 are named here
|
||||
only so that *reactivating* either re-arms the quiescence condition; neither blocks the gate today.
|
||||
(slots) is **abandoned** (Daniel, 2026-07-27) — will not be built. D2 is named here only so that
|
||||
*reactivating* its deferred panel indicator re-arms the quiescence condition; neither D2 nor M9
|
||||
blocks the gate today.
|
||||
*Why:* Phase Q touches **nearly every file in `src/`** (relocate, re-namespace, split the four
|
||||
largest TUs, plus the §2b renames); every large in-flight branch (Phase S on its worktree, L3 once
|
||||
it lands) is diffed against the *current flat layout*, so landing a rename-and-relocate-everything
|
||||
@@ -2935,10 +3200,8 @@ re-resolution, not a linear one. Phase Q is *last* precisely because it reshapes
|
||||
other pillar stands on: landing it early taxes every subsequent phase; landing it last taxes
|
||||
nothing. Re-confirm quiescence against dev before Q-W1.
|
||||
|
||||
> **M9 disposition (Daniel-decision note).** "Deferred indefinitely" ≠ "abandoned." Immaterial to
|
||||
> the gate (both clear it); matters only if M9 is reactivated — *before* Phase Q it lands cheaply on
|
||||
> the flat layout, *after* it is authored against the reorganized tree. Surfaced, not silently
|
||||
> resolved (full note: `docs/product/code-organization.md` §4).
|
||||
> **M9 disposition — resolved (Daniel, 2026-07-27): abandoned.** M9 is out; it will not be
|
||||
> reactivated. The gate remains satisfied; no re-arm condition applies.
|
||||
|
||||
## Wave sequencing (each independently landable, CTest-green at every step)
|
||||
|
||||
@@ -2991,7 +3254,7 @@ every commit), a property only an *incremental* reorg uses. Risk-ordered:
|
||||
the thumbnail path is noted but **not touched** — reworking it risks the hot path.
|
||||
- **No big-bang commit.** Every wave is independently landable and CTest-green; reject a change set
|
||||
that cannot be verified at each step.
|
||||
- **Do not begin before the GATE.** Re-confirm the tree is quiescent (Phase S + L + D2 + M9
|
||||
merged/closed) before any Q point.
|
||||
- **Do not begin before the GATE.** Re-confirm the tree is quiescent (Phase S + L + D2 merged/closed;
|
||||
M9 abandoned) before any Q point.
|
||||
- **Verify** the CMake `src/` path updates and the SWELL/LICE surfaces still resolve after
|
||||
relocation, as the existing build already requires.
|
||||
|
||||
Reference in New Issue
Block a user