docs(product): spec Phase L L7 — capture ordering, card metadata, and selection styling
Persisted gap-preserving per-bank display order + drag-drop reorder (model change, JSON round-trip + migration), decorative bars.beats/s.ms overlay, tertiary-border selection restyle. Model work separated from draw work; forks flagged (meter source, M9 substrate overlap, drag disambiguation).
This commit is contained in:
+148
@@ -1643,6 +1643,154 @@ predicate). The `TrackPopupMenu` popup, the `Main_OnCommand` dispatch, and the t
|
|||||||
timer + LICE overlay draw are the only DAW-bound pieces; the L1 kit draws. **L5 resolves its
|
timer + LICE overlay draw are the only DAW-bound pieces; the L1 kit draws. **L5 resolves its
|
||||||
menu/tooltip/action-id specifics against the landed L4 `bank_panel`** (build-time confirmation).
|
menu/tooltip/action-id specifics against the landed L4 `bank_panel`** (build-time confirmation).
|
||||||
|
|
||||||
|
## L7 capture ordering · card metadata · selection styling (ordering model · overlay · tertiary-border selection)
|
||||||
|
|
||||||
|
L7 is the **next ungated dock-panel pass over the same `bank_panel` grid** L4–L6 built. Unlike
|
||||||
|
L4/L5 (pure layout over existing actions), **L7 (1) is a persisted-model change** — it adds an
|
||||||
|
explicit per-sample display order with gap-preserving sparse placement to the persisted bank
|
||||||
|
state and its JSON round-trip. (2) and (3) are draw-only. **No new capture/placement behavior;**
|
||||||
|
the "capture ≠ placement" principle is untouched. Drawn through the L1 kit in the DS-2
|
||||||
|
grey-neutral + three-accent-pastel palette; **no palette/font decision is re-opened.** Ungated
|
||||||
|
by Phase S; independent of the L3 gate. Sequences AFTER L6.
|
||||||
|
|
||||||
|
**Research baseline (dev, confirmed at spec time).** The grid draws in **`BankIndex` insertion
|
||||||
|
order**: `BankIndex` holds `std::vector<Sample> samples_` in insertion order (`all()`), and
|
||||||
|
`bank_grid::computeCellRects` tiles exactly one contiguous rect per sample left-to-right,
|
||||||
|
top-to-bottom — **no explicit ordinal, no sparse slots today.** `Sample` already carries
|
||||||
|
`lengthSeconds`, `lengthBeats`, and `captureTempo` (BPM at capture) but **no time-signature
|
||||||
|
field.** The selected cell is drawn (`bank_panel::drawThumbnail`) as
|
||||||
|
`InteractionState::Active` (accent-fill surface) + an `accent/primary` border + an *inverted*
|
||||||
|
waveform (`bg/base`), with focus as a `text/primary` double-line ring. Drag today: press on a
|
||||||
|
selected cell arms a drag; crossing a threshold begins it; leaving the client rect hands off to
|
||||||
|
OS drag-out (`drag_out::decideGesture`); a drop on a tab / the other region moves (or copies on
|
||||||
|
Ctrl) the samples to that bank. **There is no same-bank in-grid reorder today.**
|
||||||
|
|
||||||
|
### 1. Persisted deterministic order + sparse (gap-preserving) placement
|
||||||
|
|
||||||
|
Each bank (and the pool) carries an **explicit, persisted display position per sample** — the
|
||||||
|
grid no longer derives order from insertion order. Positions are **gap-preserving**: a sample
|
||||||
|
may occupy a slot that leaves earlier slots empty (an empty first row above an occupied second
|
||||||
|
row is a valid, persisted state).
|
||||||
|
|
||||||
|
**Where the position data lives (the CLAUDE.md constraint).** `bank_model` / `Sample` are stated
|
||||||
|
**untouched by `bank_book`'s wrapping** (no `bankId` on `Sample`; a bank is a logical grouping
|
||||||
|
over the shared pool). Display position is a **per-bank display concern**, so it belongs with the
|
||||||
|
bank's membership, **not on `Sample`** — a copy of a sample into two banks can sit at different
|
||||||
|
slots. **Recommended carrier: a per-`Bank` ordered position map in `bank_book`** (sample id →
|
||||||
|
slot), leaving `bank_model` untouched. The exact carrier (ordered id list with gaps vs. explicit
|
||||||
|
id→slot map) is settled at build; the *contract* below holds either way.
|
||||||
|
|
||||||
|
**Ordering contract (deterministic, gap-preserving):**
|
||||||
|
- **Deterministic:** the grid iterates positions in ascending slot order; ties are impossible
|
||||||
|
(one sample per slot). The order is fully determined by the persisted position data, not by
|
||||||
|
insertion order or hash.
|
||||||
|
- **Insert (new capture):** a new capture takes the **next free slot after the last occupied
|
||||||
|
slot** (append). It never fills an earlier gap automatically — a gap is a user's deliberate
|
||||||
|
layout, not a hole to be plugged.
|
||||||
|
- **Delete / remove / prune:** removing a sample **leaves its slot empty** (does not re-pack) so
|
||||||
|
every other sample keeps its position. Define at build whether a purely-empty trailing tail is
|
||||||
|
trimmed for content-height purposes (the recommendation: trim trailing empties for scroll
|
||||||
|
extent, keep interior gaps).
|
||||||
|
- **Reorder:** the user drags a card to a target slot within its bank; the pure reorder mutator
|
||||||
|
moves that sample's position to the target slot, gap-preserving. (Whether a drop onto an
|
||||||
|
occupied slot displaces/swaps vs. inserts-and-shifts is settled at build — recommendation:
|
||||||
|
**drop-into-empty-slot places there; drop-onto-occupied inserts before and shifts the tail**,
|
||||||
|
matching common file-manager reorder.)
|
||||||
|
|
||||||
|
**JSON round-trip + migration (load-bearing).** `serialize`/`deserialize` stay lossless
|
||||||
|
including positions (`deserialize(serialize(x)) == x`). **A pre-L7 project blob has no position
|
||||||
|
data** → on load it defaults to **current insertion order, densely packed (no gaps)**, so a
|
||||||
|
project saved before L7 is visually identical on first post-L7 load. This default is the
|
||||||
|
migration; it is one-way (once re-saved, the position data is authoritative). Pure and
|
||||||
|
hard-tested — this is a persisted-model change, tested to the same bar as `bank_book`'s existing
|
||||||
|
round-trip + legacy migration.
|
||||||
|
|
||||||
|
**Undo.** A reorder is **one Ctrl-Z** — the actions/shell layer wraps the mutation in a batched
|
||||||
|
undo point (`Undo_BeginBlock2`/`EndBlock2`), matching every existing bank-verb's undo discipline.
|
||||||
|
|
||||||
|
**M9 overlap (flagged — Daniel's awareness).** M9 "slots" (capture-to-slot-N / insert-slot-N,
|
||||||
|
MIDI-bindable, MPC-style) is **explicitly deferred (Daniel, 2026-07-26).** L7's sparse-slot
|
||||||
|
model is a **partial overlap:** it builds the *addressable-position substrate* M9 would sit on,
|
||||||
|
but L7 adds **no** slot-numbered capture/insert actions and **no** MIDI bindings. Building L7
|
||||||
|
un-defers the *coordinate model* portion of M9, not the *action* portion. If Daniel wants the
|
||||||
|
substrate to be explicitly M9-shaped (fixed numbered slots vs. a plain gap-preserving ordinal),
|
||||||
|
that is a fork to settle before the model is built.
|
||||||
|
|
||||||
|
### 2. Decorative metadata overlay (bars.beats · s.ms)
|
||||||
|
|
||||||
|
Each card overlays, on the waveform, two decorative read-outs of **capture length**:
|
||||||
|
- **bottom-LEFT:** length in **bars.beats.subdivisions** (musical).
|
||||||
|
- **bottom-RIGHT:** length in **seconds.milliseconds** (wall-clock).
|
||||||
|
|
||||||
|
**Contract:** decorative and **non-interactive** — no hit-test, no hover, no selection role.
|
||||||
|
Drawn via the L1 kit `text()` in the **micro / value-mono** type class, in `text/dim` (or a
|
||||||
|
subtle shadowed variant for legibility over the peaks), subordinate to the waveform. **Respects
|
||||||
|
the speed constraint (no animation).** Pure formatting helpers (below) are unit-tested; only the
|
||||||
|
kit draw is shell.
|
||||||
|
|
||||||
|
**Bars.beats source (FORK F1 — Daniel to confirm).** bars.beats.subdivisions requires a
|
||||||
|
**tempo + time-signature** reference. `Sample` already carries `captureTempo` (BPM at capture)
|
||||||
|
and `lengthBeats`, but **no time-signature.** Two options:
|
||||||
|
- **(recommended) Capture-time stamp:** add `captureTimeSigNum` / `captureTimeSigDenom` to
|
||||||
|
`Sample` + its JSON round-trip, stamped on the capture path (read the project meter at capture
|
||||||
|
via the REAPER meter API — verify `TimeMap_GetTimeSigAtTime` / equivalent against the SDK at
|
||||||
|
build). *Why recommended:* the label is **stable** as the project's tempo/meter later changes;
|
||||||
|
a bank sample outlives the project state it was captured under, matching the existing
|
||||||
|
`captureTempo` stamp philosophy. **Cost:** this is a **capture-path write beyond draw work** —
|
||||||
|
its own flagged checkbox; old samples with no stamp fall back gracefully (blank musical
|
||||||
|
read-out, or a documented assumed 4/4).
|
||||||
|
- **(rejected) Live project meter at draw time:** the label would drift under the card as the
|
||||||
|
project tempo/meter changes, and would be wrong for any sample captured under a different
|
||||||
|
meter than the project's current one.
|
||||||
|
|
||||||
|
**Formatting helpers (pure, tested).** `bars.beats.subdivisions` from `lengthSeconds` +
|
||||||
|
`captureTempo` + capture-time signature; `seconds.milliseconds` from `lengthSeconds`.
|
||||||
|
Deterministic; graceful on edge cases (zero length → both read empty/`0`; missing tempo → blank
|
||||||
|
musical read-out, keep the s.ms read-out).
|
||||||
|
|
||||||
|
### 3. Selection styling — tertiary border replaces inversion
|
||||||
|
|
||||||
|
A selected card **drops the inverted accent-fill treatment** and instead draws the **normal
|
||||||
|
cell** (Rest or Hover surface) + an **`accent/tertiary` border** (pastel purple `#C2AAE8`); the
|
||||||
|
**waveform draws in its normal accent color** (the inverted `bg/base` wave is removed). The four
|
||||||
|
grid-card interaction states stay **visually distinct and coherent:**
|
||||||
|
- **Selected:** normal cell surface + **`accent/tertiary` (purple) 1px border**. No fill change,
|
||||||
|
no wave inversion.
|
||||||
|
- **Focus (caret):** the existing distinct inner ring — keep it separate from the selection
|
||||||
|
border so a focused *and* selected card reads both (e.g. purple outer border + a
|
||||||
|
`text/primary` inner focus ring). Settle the exact inner treatment at build so focus is
|
||||||
|
legible on top of the selection border.
|
||||||
|
- **Hover:** the kit Hover surface (unchanged) — a fill-state change, orthogonal to the purple
|
||||||
|
border, so a hovered selected card still reads as selected.
|
||||||
|
- **Drag-target slot:** the reorder drop-target highlight (a distinct accent — recommend
|
||||||
|
`accent/hot` outline on the target slot) must not be confusable with the purple selection
|
||||||
|
border; spec the exact treatment at build.
|
||||||
|
|
||||||
|
### Drag disambiguation (FORK F3 — proposed rule, Daniel to confirm)
|
||||||
|
|
||||||
|
In-grid reorder must coexist with the existing internal bank-move/copy drag and OS drag-out.
|
||||||
|
**Proposed precedence (one clean rule, evaluated live during the drag):**
|
||||||
|
1. **Pointer leaves the client rect → OS drag-out** (unchanged; `drag_out::decideGesture` wins
|
||||||
|
first — the existing invariant #4 boundary).
|
||||||
|
2. **Else drop lands on a tab / the OTHER region's bank → move/copy** (unchanged; Ctrl = copy).
|
||||||
|
3. **Else drop lands within the SAME bank's own grid → reorder-to-slot** (new).
|
||||||
|
|
||||||
|
So: leave-client wins → else other-bank wins → else same-bank-grid = reorder. The precedence is
|
||||||
|
encoded in a **pure decision helper** (mirror `drag_out::decideGesture`); the shell reads the
|
||||||
|
live pointer + focused region + client rect and calls it. This keeps the reorder gesture from
|
||||||
|
ever stealing an intended bank-move or OS-drag, and keeps a same-bank in-grid drag from being
|
||||||
|
mis-read as a no-op (today a same-bank drop is a no-op; L7 gives it reorder meaning).
|
||||||
|
|
||||||
|
### Pure/shell discipline (L7)
|
||||||
|
|
||||||
|
Model: the position carrier + gap semantics + reorder mutator + JSON round-trip/migration are
|
||||||
|
**pure** (in `bank_book`, CTest-covered to the bar of its existing round-trip). Layout: the
|
||||||
|
sparse-aware slot↔rect math + point→slot hit-test + the drag-disambiguation decision are **pure**
|
||||||
|
(extend `bank_grid`; mirror `mode_switch` / `drag_out::decideGesture`). Formatting: the
|
||||||
|
bars.beats and s.ms formatters are **pure**. Shell (DAW-bound): the reorder drag wiring +
|
||||||
|
drop-target highlight, the capture-time-signature stamp (F1) read on the capture path, and the
|
||||||
|
kit overlay/selection-border draw. The L1 kit draws; no palette/font decision re-opened.
|
||||||
|
|
||||||
## The L3 gate + Phase S coordination contract
|
## The L3 gate + Phase S coordination contract
|
||||||
|
|
||||||
**L3 (VST editor + embed-strip restyle) is GATED on Phase S landing on dev.** The VST
|
**L3 (VST editor + embed-strip restyle) is GATED on Phase S landing on dev.** The VST
|
||||||
|
|||||||
@@ -372,17 +372,123 @@ work.
|
|||||||
state — never a pulse, per the speed constraint) as the signature surface; VST3 class UID
|
state — never a pulse, per the speed constraint) as the signature surface; VST3 class UID
|
||||||
unchanged. (Gated.)
|
unchanged. (Gated.)
|
||||||
|
|
||||||
|
## L7 — capture ordering, card metadata, and selection styling (ungated, after L6)
|
||||||
|
**Goal:** Three grid-facing improvements to the dock panel, drawn through the L1 kit in the
|
||||||
|
settled DS-2 palette. (1) **Persisted deterministic capture order + drag-drop reorder + sparse
|
||||||
|
placement:** each bank (and the pool) carries an explicit, persisted per-sample order, changed
|
||||||
|
by dragging cards within the grid; a card may sit in a grid slot that leaves gaps (an empty
|
||||||
|
first row above an occupied second row). (2) **Decorative metadata over the peaks:** each card
|
||||||
|
overlays capture length as **bars.beats.subdivisions in the bottom-LEFT** and **seconds.ms in
|
||||||
|
the bottom-RIGHT**, subtle/legible over the waveform in the kit's micro / value-mono type
|
||||||
|
classes. (3) **Selection restyle:** a selected card drops the inverted accent-fill and instead
|
||||||
|
draws the *normal* cell + an **`accent/tertiary` (pastel purple `#C2AAE8`) border**; hover,
|
||||||
|
focus, and drag-highlight stay visually distinct. **No new capture/placement behavior** — this
|
||||||
|
is model + layout + draw only; the "capture ≠ placement" principle is untouched.
|
||||||
|
|
||||||
|
> **This is a persisted-model change, not pure layout.** Feature (1) adds an explicit
|
||||||
|
> per-sample ordinal/slot to the persisted state and its JSON round-trip + a migration for
|
||||||
|
> existing projects — scoped honestly below, model work separated from draw work.
|
||||||
|
|
||||||
|
> **Forks for Daniel (surface before build — see CONTEXT.md §L7):**
|
||||||
|
> - **F1 — bars.beats source.** `Sample` already carries `captureTempo` (BPM at capture) and
|
||||||
|
> `lengthBeats`, but **no time-signature field.** bars.beats.subdivisions needs a
|
||||||
|
> time-signature reference. **Recommendation: a capture-time stamp** (add `captureTimeSigNum`
|
||||||
|
> /`captureTimeSigDenom` to `Sample`, stamped on the capture path) so the label is stable as
|
||||||
|
> the project tempo/meter later changes — matching the existing `captureTempo` stamp
|
||||||
|
> philosophy. This adds a **capture-path stamp beyond draw work** (its own checkbox below,
|
||||||
|
> flagged). Alternative (live project meter at draw time) is rejected: the label would drift
|
||||||
|
> under the card as the project changes, and a bank sample outlives the project state it was
|
||||||
|
> captured under.
|
||||||
|
> - **F2 — M9 un-deferral awareness.** M9 "slots" (capture-to-slot-N / insert-slot-N,
|
||||||
|
> MIDI-bindable, MPC-style) is **explicitly deferred (Daniel, 2026-07-26).** L7's sparse
|
||||||
|
> placement is a **partial overlap** — both need addressable grid positions. Building L7's
|
||||||
|
> sparse-slot model effectively lays the *position substrate* M9 would sit on, but L7 does
|
||||||
|
> **not** add slot-numbered capture/insert actions or MIDI bindings. Flagged so Daniel knows
|
||||||
|
> L7 un-defers the *coordinate model* portion of M9, not the *action* portion. If Daniel wants
|
||||||
|
> the slot substrate to be explicitly M9-shaped (numbered addressable slots vs. a plain
|
||||||
|
> gap-preserving ordinal), that is a fork to settle before the model checkbox.
|
||||||
|
> - **F3 — drag-disambiguation rule (proposed, Daniel to confirm).** The panel already has
|
||||||
|
> internal bank-move/copy drag and OS drag-out. In-grid reorder must coexist. **Proposed
|
||||||
|
> rule:** a drag whose drop lands **within the SAME bank's own grid** = **reorder-to-slot**;
|
||||||
|
> a drop on **a tab / the other region's bank** = **move/copy** (as today); a drag that
|
||||||
|
> **leaves the client rect** = **OS drag-out** (as today). One clean precedence: leave-client
|
||||||
|
> wins → else other-bank wins → else same-bank-grid = reorder. See CONTEXT.md §L7.
|
||||||
|
|
||||||
|
**Verify (in DAW):** capture several samples; drag a card to a new position within its bank —
|
||||||
|
the order persists across project save/reload and Ctrl-Z restores the prior order; drag the
|
||||||
|
first card below the second so the first row is empty — the gap holds across reload; each card
|
||||||
|
shows bars.beats.subdivisions bottom-left and s.ms bottom-right, legible over the peaks; a
|
||||||
|
selected card shows the normal cell with a purple (`accent/tertiary`) border — no inversion —
|
||||||
|
and hover / focus / drag-target remain distinct; dragging a card to another bank's tab still
|
||||||
|
moves/copies (not reorder), and dragging out of the panel still starts an OS file drag; an
|
||||||
|
existing project (saved before L7) loads cleanly with cards in their prior insertion order.
|
||||||
|
**Depends on:** L1 (the kit) for all draw; sequences **after L6** (both rework the same
|
||||||
|
`bank_panel` grid). **Ungated by Phase S** (the dock panel is on dev); independent of the L3
|
||||||
|
gate. No `capture` / `insert` behavior change; no palette/font decision re-opened.
|
||||||
|
|
||||||
|
**(a) Persisted order + sparse-position model (pure, hard-tested) — model work, separate from draw:**
|
||||||
|
- [ ] Add an explicit per-sample **display position** to the persisted bank state (gap-preserving
|
||||||
|
ordinal or slot coordinate — settle the shape against F2). Decide the home: `bank_model`
|
||||||
|
is stated untouched by `bank_book`'s wrapping — position is a **per-bank display concern**, so
|
||||||
|
it belongs with the bank's membership, not on `Sample`. Candidate: a per-`Bank` ordered/keyed
|
||||||
|
position map in `bank_book` (id → slot), leaving `bank_model` / `Sample` untouched. Settle the
|
||||||
|
exact carrier at build.
|
||||||
|
- [ ] JSON round-trip for the position data (`serialize`/`deserialize` remain lossless:
|
||||||
|
`deserialize(serialize(x)) == x` including positions).
|
||||||
|
- [ ] **Migration for existing projects** (old blobs with no position data): load cleanly with a
|
||||||
|
**default = current insertion order, densely packed** (no gaps). Spec the default explicitly so
|
||||||
|
a pre-L7 project is visually identical on first load post-L7.
|
||||||
|
- [ ] **Gap semantics on insert / delete / prune** (pure, tested): a new capture takes the next
|
||||||
|
free slot after the last occupied one (append); a delete/remove/prune **leaves a gap** (does
|
||||||
|
not re-pack) so positions stay stable; define whether an empty trailing tail is trimmed.
|
||||||
|
- [ ] **Reorder mutator** (pure): move sample `id` to target slot within its bank, gap-preserving;
|
||||||
|
deterministic; unit-tested.
|
||||||
|
- [ ] Undo integration: a reorder is one Ctrl-Z (batched undo point in the actions/shell layer,
|
||||||
|
matching the existing bank-verb undo discipline).
|
||||||
|
|
||||||
|
**(b) Reorder-drag gesture + slot hit-test (pure geometry + shell wiring):**
|
||||||
|
- [ ] **Sparse-aware grid layout** (pure, extend `bank_grid`): map per-slot positions (with gaps)
|
||||||
|
to `CellRect`s — an empty slot is drawn empty (or skipped), not back-filled. Slot ↔ pixel-rect
|
||||||
|
math + point→slot hit-test stay pure and unit-tested (mirror `mode_switch`/`bank_grid`).
|
||||||
|
- [ ] **Drag-disambiguation** (F3): drop within the same bank's grid = reorder-to-slot; drop on a
|
||||||
|
tab / other bank = move/copy (unchanged); leave client = OS drag-out (unchanged). Precedence
|
||||||
|
encoded in a **pure decision helper** (mirror `drag_out::decideGesture`); shell reads live
|
||||||
|
pointer + region + client rect and calls it.
|
||||||
|
- [ ] Shell wiring: on a same-bank reorder drop, resolve the target slot via the pure hit-test and
|
||||||
|
call the reorder mutator; drop-target slot highlight during the drag (distinct from the existing
|
||||||
|
region/tab drop highlights).
|
||||||
|
|
||||||
|
**(c) Metadata overlay (pure formatting + kit draw):**
|
||||||
|
- [ ] **Pure formatters, unit-tested:** `bars.beats.subdivisions` from `lengthSeconds` +
|
||||||
|
`captureTempo` + capture-time signature (F1) and `seconds.milliseconds` from `lengthSeconds`.
|
||||||
|
Deterministic string output; edge cases (zero length, missing tempo → graceful blank/fallback).
|
||||||
|
- [ ] **[FLAGGED — F1, capture-path stamp beyond draw work] Capture-time signature stamp:** add
|
||||||
|
`captureTimeSigNum` / `captureTimeSigDenom` to `Sample` + its JSON round-trip, stamped on the
|
||||||
|
capture path (read the project meter at capture). Only needed if F1 resolves to the capture-time
|
||||||
|
stamp (recommended). Old samples with no stamp fall back gracefully in the formatter.
|
||||||
|
- [ ] **Kit draw:** overlay the two strings on the card — bars.beats bottom-LEFT, s.ms
|
||||||
|
bottom-RIGHT — via the kit `text()` in the micro / value-mono class, `text/dim` (or a subtle
|
||||||
|
shadowed variant for legibility over the waveform); **decorative, non-interactive** (no
|
||||||
|
hit-test, no hover). Respects the speed constraint (no animation).
|
||||||
|
|
||||||
|
**(d) Selection restyle (tertiary border):**
|
||||||
|
- [ ] `drawThumbnail`: a selected card draws the **normal cell fill** (Rest/Hover surface, not
|
||||||
|
`InteractionState::Active`) + an **`accent/tertiary` border** (pastel purple `#C2AAE8`); the
|
||||||
|
waveform draws in its normal accent color (drop the inverted `bg/base` wave). Focus ring, hover
|
||||||
|
state, and drag-target highlight stay **distinct** from the selection border (keep them
|
||||||
|
coherent — spec the four states' visual separation in CONTEXT.md §L7).
|
||||||
|
|
||||||
## Phase L — sequencing
|
## Phase L — sequencing
|
||||||
```
|
```
|
||||||
L1 (shared kit) ──► L2 (dock-panel layout redesign) [LANDED]
|
L1 (shared kit) ──► L2 (dock-panel layout redesign) [LANDED]
|
||||||
├─────────► L3 (VST editor + embed-strip restyle; GATED on Phase S landing on dev)
|
├─────────► L3 (VST editor + embed-strip restyle; GATED on Phase S landing on dev)
|
||||||
└─────────► L4 (dock-panel button layout enhancement) [LANDED]
|
└─────────► L4 (dock-panel button layout enhancement) [LANDED]
|
||||||
└────► L5 (dock-panel button refinements; ungated, after L4) [LANDED]
|
└────► L5 (dock-panel button refinements; ungated, after L4) [LANDED]
|
||||||
|
└────► L6 (toolbar polish; ungated, after L5) [LANDED]
|
||||||
Phase S (separate team, ungated): S-work builds with current drawing, adopts L1 when it lands.
|
└────► L7 (capture ordering + card metadata + selection styling; ungated, after L6)
|
||||||
```
|
```
|
||||||
L1, L2, L4, and L5 have landed. L3 waits for Phase S to reach dev.
|
L1, L2, L4, L5, and L6 have landed. L7 is the next ungated dock-panel work. L3 waits for
|
||||||
Phase S feature work runs in parallel, ungated by Phase L.
|
Phase S to reach dev. Phase S feature work runs in parallel, ungated by Phase L.
|
||||||
|
|
||||||
## Phase L — must-verify-before-build
|
## Phase L — must-verify-before-build
|
||||||
- **LICE design-kit surfaces (L1)** — `LICE_GradRect`, `LICE_RoundRect`, AA
|
- **LICE design-kit surfaces (L1)** — `LICE_GradRect`, `LICE_RoundRect`, AA
|
||||||
@@ -407,6 +513,15 @@ Phase S feature work runs in parallel, ungated by Phase L.
|
|||||||
pure module; sourced from the registered action phrase, prefix stripped at draw time); item-move
|
pure module; sourced from the registered action phrase, prefix stripped at draw time); item-move
|
||||||
and track-tag action ids confirmed; active-mode read confirmed via the same
|
and track-tag action ids confirmed; active-mode read confirmed via the same
|
||||||
`view().activeModeId()` the footer toggle uses.
|
`view().activeModeId()` the footer toggle uses.
|
||||||
|
- **L7 model + tempo surface (L7)** — settle at L7 build/spec-review: (1) **position carrier** —
|
||||||
|
where the per-sample display position lives (candidate: a per-`Bank` id→slot map in `bank_book`,
|
||||||
|
keeping `bank_model`/`Sample` untouched per CLAUDE.md); (2) **F1 bars.beats source** — confirm
|
||||||
|
the capture-time signature stamp with Daniel (recommended) vs. live project meter; the stamp adds
|
||||||
|
a capture-path write (its own flagged checkbox); (3) **F2 M9 overlap** — confirm L7's sparse-slot
|
||||||
|
substrate is not mis-scoped as M9's slot *actions*; (4) **F3 drag rule** — confirm the
|
||||||
|
same-bank-grid = reorder / other-bank = move-copy / leave-client = OS-drag precedence. Verify the
|
||||||
|
REAPER meter-read API for the stamp (`TimeMap_GetTimeSigAtTime` or equivalent) against the SDK at
|
||||||
|
build.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user