Scope sample-remove (B5) and prune (Phase R) into the plan
Adds the two missing removal capabilities: sample-level remove (Phase B point B5, index-only) and the prune file-lifecycle path (new Phase R, the sole file-deleting op), resolving the dangling capture/prune reference. Adds CONTEXT.md spec, PLAN.md points, and a product note; surfaces forks R-A..R-E for decision.
This commit is contained in:
@@ -118,23 +118,34 @@ landed milestone.
|
||||
> spec. Product framing: `docs/product/design-view.md` §Two-canvas direction. When a
|
||||
> point lands, doc-keeper moves it to `COMPLETED.md`.
|
||||
>
|
||||
> **D2-W1 (pure lane extension) and D2-W2 (shell: lane application + new-content detection) have landed** — see `COMPLETED.md`.
|
||||
> **D2-W1 (pure lane extension), D2-W2 (shell: lane application + new-content
|
||||
> detection), and D2-W3-A (lane minting + item→lane assignment + persist
|
||||
> round-trip) have landed** — see `COMPLETED.md`.
|
||||
|
||||
## D2-W3 — actions, persist wiring, panel UI
|
||||
**Goal:** Any new lane/mode-management actions, the persist slice serializing the
|
||||
lane-ownership index alongside the membership index, and any panel UI indicator.
|
||||
## D2-W3-B — two-canvas actions + panel UI indicators
|
||||
**Goal:** Any new lane/mode-management actions (bindable in the Actions list), and
|
||||
any panel UI indicator for lane/mode state. The persist slice and the
|
||||
lane-ownership index round-trip were completed in D2-W3-A; this wave closes the
|
||||
remaining UI and action surface.
|
||||
See CONTEXT.md §Two-canvas sub-phase (Module architecture — persistence).
|
||||
**Verify (in DAW):** The lane-ownership index survives Save / Save As / reopen
|
||||
(rides in the `"reasampler"` `view_state` alongside the membership index);
|
||||
lane/mode-management actions are registered and bindable.
|
||||
**Depends on:** D2-W2.
|
||||
**Verify (in DAW):** Lane/mode-management actions are registered and bindable in
|
||||
the Actions list; the panel UI indicator reflects the current lane/mode state.
|
||||
**Depends on:** D2-W3-A.
|
||||
|
||||
- [ ] Any new lane/mode-management actions (`command_id`/`gaccel`/`hookcommand`);
|
||||
bindable in the Actions list.
|
||||
- [ ] Persist slice: serialize/deserialize the lane-ownership index in the
|
||||
`"reasampler"` `view_state` section, alongside the membership index.
|
||||
- [ ] Any panel UI indicator for lane/mode state.
|
||||
|
||||
**D2-W3-A code-review polish (fold into this wave):**
|
||||
- [ ] Simplify the redundant per-mint `I_NUMFIXEDLANES` re-read in `view.cpp`
|
||||
(`applyMintPlan`): a single grow-and-track pass removes the second
|
||||
`GetMediaTrackInfo_Value` call inside the mint loop.
|
||||
- [ ] Optional shared item-read helper to remove duplicated `itemGuid`/`itemLaneName`
|
||||
read logic between `view.cpp` and `bank_panel.cpp`.
|
||||
- [ ] Optional defensive note/check in `reconcileManagedLanes` for the edge case
|
||||
where a managed lane name encodes an unregistered mode id (log and skip rather
|
||||
than silently record an orphaned ownership entry).
|
||||
|
||||
---
|
||||
|
||||
# Phase B — Multi-bank (parallel to the M0–M11 capture roadmap and Phase D)
|
||||
@@ -254,6 +265,34 @@ and product notes → *Fork 5 — settled*.)
|
||||
index-only and reversible). **Verify the drag hit-test doesn't collide with the M5
|
||||
grid's multi-select drag.**
|
||||
|
||||
## B5 — sample-remove (the missing sample-level verb)
|
||||
**Goal:** Drop an individual `Sample`'s index entry from a bank or the pool —
|
||||
the sample-level companion to move/copy/evacuate/delete-bank. Index-only,
|
||||
non-destructive to the file; exposes the `BankIndex::remove` primitive that
|
||||
`bank_model` already has (wires it, does not add it). CONTEXT.md §Sample removal.
|
||||
Product framing + open forks: `docs/product/removal-and-prune.md` §Sample-remove.
|
||||
**Verify (in DAW):** Remove drops the selected sample's entry from the target
|
||||
bank; a same-hash entry in another bank is untouched (no cross-bank dedup);
|
||||
pool *contents* are removable while pool-container privileges hold; removing the
|
||||
last index reference to a file leaves that file on disk (orphaned until prune —
|
||||
never deleted by remove); non-destructive (index + ext-state only, no file, no
|
||||
timeline item).
|
||||
**Depends on:** B1, B2, B3 (action set), B4 (panel affordance).
|
||||
|
||||
- [ ] Surface `BankIndex::remove` through `bank_book`: remove a `Sample` from a
|
||||
bank's index; pool contents removable, pool-container privileges unchanged.
|
||||
- [ ] "Remove selected sample(s)" action (`command_id`/`gaccel`/`hookcommand`),
|
||||
MIDI-bindable; carries a `scope: this-bank | all-banks` seam (fork R-A — default
|
||||
this-bank until Daniel settles).
|
||||
- [ ] `bank_panel` remove affordance on the current selection (reuse M5 selection
|
||||
model, as move/copy do).
|
||||
- [ ] Confirm-on-last-reference guardrail: remove that orphans a file (no other
|
||||
bank references it) confirms, naming the orphaned-until-prune consequence;
|
||||
remove of a still-referenced sample does not confirm.
|
||||
- [ ] Tests: remove drops the target entry; same-hash entry in another bank
|
||||
survives; remove-from-pool allowed; last-reference remove leaves an orphan (file
|
||||
untouched); non-destructive (no file/timeline mutation).
|
||||
|
||||
## Phase B open questions
|
||||
All five forks settled by Daniel (2026-07-23): persistence key = fold pool into `banks`,
|
||||
retire legacy key (1a); delete drops members + add evacuate verb (2); move is the
|
||||
@@ -265,3 +304,102 @@ ready to scope into implementation waves. One polish detail remains:
|
||||
- **Active-bank indicator placement** — per-region headers vs. single header readout
|
||||
vs. lit-tab. "Unmistakable" is settled; only placement is open. Polish detail.
|
||||
(touches B4)
|
||||
|
||||
- **B5 sample-remove forks (NEW, unsettled — need Daniel):** **R-A** — remove scope
|
||||
(this-bank | all-banks | both); spec-of-record is this-bank-primary with a
|
||||
scope-parameter seam. **R-B** — undo model for `"reasampler"` ext-state index
|
||||
mutations (affects *all* of Phase B, surfaced by remove; move/copy/evacuate/
|
||||
delete-bank/remove are not on REAPER Ctrl-Z as specced). Lean: a single-snapshot
|
||||
ReaSampler-internal "undo last bank change." Both in `docs/product/removal-and-prune.md`.
|
||||
|
||||
---
|
||||
|
||||
# Phase R — Reclaim (file lifecycle: the prune path)
|
||||
|
||||
> **New pillar, own lettered namespace.** Prune is the file-lifecycle path the
|
||||
> capture and multi-bank specs forward-reference throughout ("files persist on disk
|
||||
> until prune") but that had no phase, module, or point. It is the **only** operation
|
||||
> in ReaSampler that deletes bytes off disk. Namespaced **`R` (Reclaim)** alongside
|
||||
> `M`/`D`/`B` because it is a distinct pillar — it serves *every* orphan-producing
|
||||
> path (delete-bank, sample-remove B5, potentially M10 re-capture), not just
|
||||
> Multi-bank, and it carries a new risk class (file deletion) with its own
|
||||
> invariants. Authoritative spec: **CONTEXT.md §Prune — file-lifecycle spec**.
|
||||
> Product framing + phase-placement justification + forks:
|
||||
> `docs/product/removal-and-prune.md` §Prune. When a point lands, doc-keeper moves it
|
||||
> to `COMPLETED.md`.
|
||||
>
|
||||
> **Boundary (load-bearing):** *remove creates orphans; prune reclaims them.* No
|
||||
> operation other than prune deletes a file; prune deletes only files no index
|
||||
> references. A bank op that deletes a file is still a bug.
|
||||
>
|
||||
> **Depends on:** B1, B2 (needs the multi-bank book to union the referenced-set
|
||||
> across all banks) and B5 conceptually (sample-remove is a primary orphan-producer,
|
||||
> so remove-then-prune is the coherent pair — mirror of evacuate-then-delete). Does
|
||||
> **not** depend on the B3/B4 UI.
|
||||
|
||||
## R1 — prune-reconcile core (pure)
|
||||
**Goal:** REAPER-free, filesystem-free reconciler — given the set of files present
|
||||
in the bank folder and the set of files referenced by the book (unioned across all
|
||||
banks, pool included), compute the orphan set. The mirror of
|
||||
`ViewModeModel::reconcile(liveGuids)`, one level down (files instead of GUIDs).
|
||||
CONTEXT.md §Prune (Module architecture — pure).
|
||||
**Verify:** CTest green. **Prune null test:** a folder whose every file is
|
||||
referenced deletes nothing; prune returns exactly `present − referenced` and
|
||||
nothing else. Referenced-set unioned across every bank (a file referenced by any
|
||||
bank — including via a copy — is never an orphan).
|
||||
|
||||
- [ ] Prune-reconcile pure function: `(present, referenced) → orphans`, referenced
|
||||
unioned across the whole book (copies keep a file alive).
|
||||
- [ ] Tests: prune null test (all-referenced → empty); orphan = present−referenced;
|
||||
a copied file referenced by a second bank survives; empty folder / empty book edge
|
||||
cases.
|
||||
|
||||
## R2 — prune shell + persist wiring (filesystem I/O, thin)
|
||||
**Goal:** Enumerate the current project bank folder (M4 project-relative resolution),
|
||||
supply the referenced-set (and, per fork R-D, the owned-file set) from the session,
|
||||
feed the pure core, and produce a dry-run manifest. No deletion in this wave — the
|
||||
report path only. CONTEXT.md §Prune (persist / prune shell).
|
||||
**Verify (in DAW):** Dry-run reports the orphan count + reclaimed size (+ file list
|
||||
for a small set) against the resolved current bank folder; resolves paths the same
|
||||
way the index does (survives a Save-As relocation); deletes nothing.
|
||||
**Depends on:** R1, B1, B2.
|
||||
|
||||
- [ ] Prune shell: enumerate the resolved current bank folder; feed the pure core.
|
||||
- [ ] Session supplies the referenced-set (union across the book); resolve the bank
|
||||
folder via the M4 project-relative machinery.
|
||||
- [ ] Dry-run manifest: orphan count + reclaimed size (+ files for a small set);
|
||||
**no deletion in this wave.**
|
||||
|
||||
## R3 — deletion + action (the destructive step, guarded)
|
||||
**Goal:** The confirmed deletion step and the bindable "Prune bank folder" action:
|
||||
dry-run-first, confirm-with-manifest, then reclaim the orphan set — via OS trash if
|
||||
portably available (fork R-C), else unlink. CONTEXT.md §Prune (guardrails, API).
|
||||
**Verify (in DAW):** "Prune bank folder" reports first, deletes only on explicit
|
||||
confirm, and reclaims exactly the orphan set — never a referenced file, never a
|
||||
hand-dropped non-bank file; the referenced/owned-set safety holds; non-bank and
|
||||
capture invariants untouched.
|
||||
**Depends on:** R2. **Forks R-C / R-D / R-E must be settled before this wave.**
|
||||
|
||||
- [ ] "Prune bank folder" action (`command_id`/`gaccel`/`hookcommand`),
|
||||
dry-run-first, confirm-to-delete.
|
||||
- [ ] Deletion mechanism (fork R-C): OS trash if a portable move-to-trash is
|
||||
verified available, else unlink with the dry-run/confirm guardrail. **Verify the
|
||||
platform move-to-trash surface before use.**
|
||||
- [ ] Orphan attribution (fork R-D): reclaim only the bank system's own leavings,
|
||||
not hand-dropped folder files (owned-file manifest per the lean — see below).
|
||||
- [ ] Trigger (fork R-E): manual-primary; optional "…and prune now" offered at the
|
||||
delete-bank confirmation; **no** background sweep.
|
||||
|
||||
## Phase R open questions (unsettled — need Daniel)
|
||||
- **Fork R-C — deletion mechanism (OS trash vs. unlink).** Lean: trash if portably
|
||||
available (recoverable), else unlink with strong dry-run/confirm. Needs Daniel +
|
||||
a platform to-verify (SWELL / per-platform trash APIs).
|
||||
- **Fork R-D — orphan attribution (owned-file manifest vs. index-diff vs.
|
||||
folder-sweep).** Lean: **owned-file manifest**. **Design-the-seam call:** the
|
||||
manifest is cheap to maintain from capture onward but a backfill cliff to
|
||||
reconstruct later — so **start tracking owned files as part of capture / Phase B
|
||||
now, even though prune ships in Phase R.** Folder-sweep rejected as unsafe (deletes
|
||||
hand-dropped files). Needs Daniel (touches the persisted shape + ideally lands
|
||||
earlier than R3).
|
||||
- **Fork R-E — trigger (manual-only vs. offer-on-orphaning vs. periodic).** Lean:
|
||||
manual-primary + optional delete-time "prune now"; no background sweep. Needs Daniel.
|
||||
|
||||
Reference in New Issue
Block a user