docs: archive Phase L L7 to COMPLETED; reconcile CLAUDE.md + CONTEXT.md + PLAN.md
This commit is contained in:
@@ -285,7 +285,8 @@ build:** the `IReaperUIEmbedInterface` contract + embed message/lifecycle agains
|
||||
> moves it to `COMPLETED.md`.
|
||||
>
|
||||
> **L1 (shared LICE drawing kit — the foundation), L2 (dock-panel layout redesign), L4
|
||||
> (dock-panel button layout enhancement), and L5 (dock-panel button refinements) have landed** —
|
||||
> (dock-panel button layout enhancement), L5 (dock-panel button refinements), L6 (toolbar
|
||||
> polish), and L7 (capture ordering, card metadata, and selection styling) have landed** —
|
||||
> `theme`/palette module, `component_geometry` geometry/hit-test helpers, `draw_kit` shell, GDI
|
||||
> `DrawText` retirement in `bank_panel` (L1); `action_bar` pure task-grouped layout module, full
|
||||
> M11-aware button inventory placed by task cluster, `bank_panel` redesigned through the L1 kit
|
||||
@@ -294,8 +295,11 @@ build:** the `IReaperUIEmbedInterface` contract + embed message/lifecycle agains
|
||||
> `Switching` in `action_bar` (L4); top-bar overflow menu (`overflow_menu` pure module),
|
||||
> custom LICE-kit hover-delay tooltips (`tooltip` pure module), opposite-mode Item/Track tag
|
||||
> buttons + Show Both, Toggle + Activate-Arrange/Design buttons removed, grouping spacing
|
||||
> widened (`mode_enable` pure module) (L5). See `COMPLETED.md`. **L3 remains** — L3 gated on
|
||||
> Phase S landing on dev.
|
||||
> widened (`mode_enable` pure module) (L5); single-row button faces, keybinding in tooltip,
|
||||
> Cancel RT moved to overflow, top-bar cluster order tidied (L6); per-bank `SlotMap`
|
||||
> (id→slot) in `bank_book`, sparse-grid rendering, `card_drag` + `card_meta` pure modules,
|
||||
> `captureTimeSigNum`/`captureTimeSigDenom` on `Sample`, tertiary-border selection (L7). See
|
||||
> `COMPLETED.md`. **L3 remains** — L3 gated on Phase S landing on dev.
|
||||
>
|
||||
> **This section is self-contained for a team without Phase S context.** Where a point
|
||||
> touches a Phase S surface (the VST editor, the embed strip, the keyboard strip), the
|
||||
@@ -372,139 +376,6 @@ work.
|
||||
state — never a pulse, per the speed constraint) as the signature surface; VST3 class UID
|
||||
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 — all SETTLED 2026-07-27 (see CONTEXT.md §L7 for full detail):**
|
||||
> - **F1 — SETTLED: capture-time stamp.** Add `captureTimeSigNum` / `captureTimeSigDenom` to
|
||||
> `Sample`, stamped on the capture path alongside the existing `captureTempo`;
|
||||
> bars.beats.subdivisions renders from the stamped tempo + meter, stable under later project
|
||||
> changes. Live-meter-at-draw-time rejected (would drift). The capture-path stamp checkbox
|
||||
> below is **settled, not flagged.**
|
||||
> - **F2 — SETTLED: plain interchangeable-slot substrate, NOT fixed MPC-style slots.** The
|
||||
> carrier is a **per-bank id→slot map** (gap-preserving interchangeable slots): a slot is just a
|
||||
> display position an occupant sits in — **no slot identities, no numbered/addressable slots, no
|
||||
> slot actions, no MIDI-bindable slot numbers, no capture-to-slot-N.** The "plain vs. M9-shaped"
|
||||
> sub-fork is closed (plain). M9 (capture-to-slot-N / insert-slot-N, MIDI-bindable, MPC-style)
|
||||
> stays **explicitly deferred (Daniel, 2026-07-26);** the substrate still eases a future M9
|
||||
> revival but L7 adds no M9 actions or bindings.
|
||||
> - **F3 — SETTLED + EXTENDED.** Drag precedence: leave-client → OS drag-out; else tab/other-bank
|
||||
> → move/copy (Ctrl = copy); else same-bank grid → reorder-to-slot. **Extensions:**
|
||||
> (a) **drop-result cursor cues** — the cursor indicates the drop result via REAPER-idiomatic
|
||||
> special cursors (reorder / move / copy / OS-drag-out / replace); the shell sets it via
|
||||
> Win32/SWELL `SetCursor`, but the *decision* of which cue applies stays in the pure gesture
|
||||
> helper. (b) **Alt+drop-onto-occupied = REPLACE** — default occupied-slot drop stays
|
||||
> insert-and-shift; holding Alt replaces the occupant (index-only removal, existing
|
||||
> remove-from-bank semantics — file stays on disk, prune governs bytes, `hashReferencedElsewhere`
|
||||
> handles last-reference). **Pool rule:** Alt+Replace in the un-evacuable pool is allowed only
|
||||
> when the same pool-privilege guard that `remove` applies would permit removing that sample —
|
||||
> one rule, no pool-only path; the replace cursor cue shows only when Alt is actually held over
|
||||
> an occupied slot.
|
||||
|
||||
**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; during any drag the cursor shows the correct
|
||||
special cue (reorder within the bank, move/copy over a tab/other bank, OS drag-out past the client
|
||||
edge); Alt+drop over an occupied card **replaces** the occupant (the replaced sample leaves that
|
||||
bank's grid but its file survives on disk; if it was the last reference, prune later reclaims it),
|
||||
and the replace cursor appears only while Alt is held over an occupied slot; 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 — a
|
||||
**per-`Bank` id→slot map in `bank_book`** (gap-preserving interchangeable slots, per F2
|
||||
settled). `bank_model` / `Sample` stay untouched (position is a per-bank display concern, not a
|
||||
`Sample` property — a copy of a sample into two banks may sit at different slots). **No slot
|
||||
identities / numbered addressable slots** — a slot is just a position an occupant sits in.
|
||||
- [ ] 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. **Confirmed defaults:** trailing empty tail trimmed for
|
||||
scroll-extent purposes; interior gaps preserved.
|
||||
- [ ] **Reorder mutator** (pure): move sample `id` to target slot within its bank, gap-preserving;
|
||||
deterministic; unit-tested. Drop-into-empty places there; **drop-onto-occupied (default, no
|
||||
modifier) inserts-before-and-shifts-tail.**
|
||||
- [ ] **Alt-replace mutator** (pure): Alt+drop over an occupied slot **replaces the occupant** —
|
||||
index-only removal of the occupant from THAT bank (reuse the existing remove-from-bank
|
||||
semantics: file stays on disk, owned-manifest/prune govern bytes, `hashReferencedElsewhere`
|
||||
handles the last-reference case), then the dragged sample takes the vacated slot (position
|
||||
preserved). **Pool guard:** if the sample sits in the un-evacuable pool, the replace's
|
||||
index-removal step passes the **same pool-privilege guard that `remove` applies** — if
|
||||
remove-from-pool would be rejected for that sample, Alt+Replace over it is rejected (falls back
|
||||
to no-op / default insert-shift; settle rejection UX at build). One rule, no pool-only path.
|
||||
Deterministic; unit-tested. **No new deletion authority — never touches disk.**
|
||||
- [ ] Undo integration: a reorder **or a replace** 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 (empty =
|
||||
place; occupied+no-modifier = insert-shift; **occupied+Alt = replace**); drop on a tab / other
|
||||
bank = move/copy (unchanged, Ctrl = copy); leave client = OS drag-out (unchanged). Precedence
|
||||
encoded in a **pure decision helper** (mirror `drag_out::decideGesture`); shell reads live
|
||||
pointer + region + client rect + **modifier state (Alt)** and calls it. The helper returns the
|
||||
**resolved gesture** (reorder / move / copy / os-drag-out / replace) so the shell can map it to
|
||||
a cursor cue.
|
||||
- [ ] **Drop-result cursor cues** (F3 extension): the shell sets a REAPER-idiomatic special cursor
|
||||
per the pure resolved-gesture (reorder / move / copy / OS-drag-out / replace) via Win32/SWELL
|
||||
`SetCursor`; the **replace** cursor shows only when Alt is actually held over an occupied slot.
|
||||
**Cue-decision logic stays in the pure helper;** the shell owns only the `SetCursor` call and
|
||||
the cursor resources (load/synthesize kit-consistent cursors at build; REAPER's own action
|
||||
cursors as the visual reference).
|
||||
- [ ] Shell wiring: on a same-bank reorder drop, resolve the target slot via the pure hit-test and
|
||||
call the reorder mutator (or, when Alt is held over an occupied slot, the **Alt-replace
|
||||
mutator**); drop-target slot highlight during the drag (distinct from the existing region/tab
|
||||
drop highlights, and — for a pending replace — distinct from the pending-reorder highlight).
|
||||
|
||||
**(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).
|
||||
- [ ] **Capture-time signature stamp (F1, settled — capture-path write beyond draw work):** add
|
||||
`captureTimeSigNum` / `captureTimeSigDenom` to `Sample` + its JSON round-trip, stamped on the
|
||||
capture path (read the project meter at capture — verify `TimeMap_GetTimeSigAtTime` / equivalent
|
||||
against the SDK at build). Old samples with no stamp fall back gracefully in the formatter
|
||||
(blank musical read-out, or a documented assumed 4/4).
|
||||
- [ ] **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
|
||||
```
|
||||
L1 (shared kit) ──► L2 (dock-panel layout redesign) [LANDED]
|
||||
@@ -512,10 +383,10 @@ L1 (shared kit) ──► L2 (dock-panel layout redesign) [LANDED]
|
||||
└─────────► L4 (dock-panel button layout enhancement) [LANDED]
|
||||
└────► L5 (dock-panel button refinements; ungated, after L4) [LANDED]
|
||||
└────► L6 (toolbar polish; ungated, after L5) [LANDED]
|
||||
└────► L7 (capture ordering + card metadata + selection styling; ungated, after L6)
|
||||
└────► L7 (capture ordering + card metadata + selection styling; ungated, after L6) [LANDED]
|
||||
```
|
||||
L1, L2, L4, L5, and L6 have landed. L7 is the next ungated dock-panel work. L3 waits for
|
||||
Phase S to reach dev. Phase S feature work runs in parallel, ungated by Phase L.
|
||||
L1, L2, L4, L5, L6, and L7 have all landed. L3 waits for Phase S to reach dev. Phase S
|
||||
feature work runs in parallel, ungated by Phase L.
|
||||
|
||||
## Phase L — must-verify-before-build
|
||||
- **LICE design-kit surfaces (L1)** — `LICE_GradRect`, `LICE_RoundRect`, AA
|
||||
@@ -540,16 +411,11 @@ Phase S to reach dev. 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
|
||||
and track-tag action ids confirmed; active-mode read confirmed via the same
|
||||
`view().activeModeId()` the footer toggle uses.
|
||||
- **L7 model + tempo surface (L7)** — forks F1/F2/F3 **all settled 2026-07-27** (see the §L7
|
||||
forks block above and CONTEXT.md §L7): position carrier = per-`Bank` id→slot map in `bank_book`
|
||||
(plain interchangeable substrate, `bank_model`/`Sample` untouched); F1 = capture-time signature
|
||||
stamp; F3 = drag precedence + REAPER-idiomatic cursor cues + Alt-replace-over-occupied with the
|
||||
stated pool guard. **Remaining build-time verification (SDK/API, not product decisions):**
|
||||
(1) the REAPER meter-read API for the F1 stamp (`TimeMap_GetTimeSigAtTime` or equivalent) —
|
||||
verify signature/argument order against the SDK; (2) the Win32/SWELL `SetCursor` path and cursor
|
||||
resource loading/synthesis for the drop-result cues — confirm the cursor idiom against SWELL and
|
||||
REAPER's own action cursors; (3) confirm the existing remove-from-bank pool-privilege guard is
|
||||
reusable as-is for the Alt-replace index-removal step.
|
||||
- **L7 model + tempo surface (L7)** — **RESOLVED at build (L7 landed).** Forks F1/F2/F3 all
|
||||
confirmed: `TimeMap_GetTimeSigAtTime` confirmed at build for the meter stamp; SWELL stock
|
||||
cursors chosen for drop-result cues (Reorder→IDC_SIZEALL, Move→IDC_HAND, Copy→IDC_UPARROW,
|
||||
Replace→IDC_SIZEWE); existing pool-privilege guard reused as-is for Alt-replace. Gap navigation
|
||||
in the grid = skip gaps (arrow keys skip empty slots). See `COMPLETED.md` §L7.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user