docs: settle Design View two-canvas sub-phase (fixed-lane per-item modes)

Item-level mode separation via REAPER fixed lanes; new content auto-tags to
the active mode; inactive lanes hidden and silenced; a managed-vs-manual lane
index keeps toggles off user comp lanes; capture placement mode-aware.
Precision invariants unaffected; REAPER 7 floor.
This commit is contained in:
2026-07-23 16:32:58 -04:00
parent 3791e6c119
commit 1688de553b
2 changed files with 504 additions and 13 deletions
+164 -5
View File
@@ -184,9 +184,27 @@ are **Arrange** mode (the default). Toggling to a mode **hides and disables** th
tracks that don't belong to it. Workflow value: mental separation + clutter tracks that don't belong to it. Workflow value: mental separation + clutter
elimination — be in Design view, resample into the bank, flip to Arrange, place it. elimination — be in Design view, resample into the bank, flip to Arrange, place it.
**This is not a separate canvas.** REAPER has exactly one arrange timeline. Design Design View is a **mode projection over REAPER's single arrange timeline**
View is the *same timeline* with a curated, filtered track set and the inactive reaching both **tracks** (parked per mode) and **items** (lane-split per mode on
tracks parked — not a second surface, window, or duplicated project. shared tracks). It approximates two canvases without a second surface: same project,
same timeline, but each stance sees its own tracks and its own items. It **never**
duplicates the project or opens a second window.
> **Two-canvas reach — settled (2026-07-23).** The original single-canvas framing
> here was derived from a REAPER constraint, not chosen as a product stance. Daniel
> reopened it — "as close as possible to two separate design and arrange canvases,
> same project, different items and leaves" — and has now signed off on the
> mechanism and resolved all forks. The "different leaves" half is delivered by
> track-parking (D1). The "different items" half is delivered by **per-item mode
> membership via REAPER fixed lanes** (track-side `I_FREEMODE=2`, `I_NUMFIXEDLANES`,
> `C_LANEPLAYS:N`; item-side `I_FIXEDLANE`, `C_LANEPLAYS`, `B_FIXEDLANE_HIDDEN`):
> each mode owns a lane on a shared track, and toggling shows/plays only the active
> mode's lane. This is an item-visibility projection over the one timeline — the
> exact analog of today's track-visibility projection — with still **no** literal
> second surface, window, or duplicate project. It is an **additive sub-phase (Phase
> D2 / Phase E)** on top of D1, spec'd in *§Two-canvas sub-phase* below. Full framing
> and the rejected alternatives (timebase-offset, subproject) live in
> `docs/product/design-view.md` §Two-canvas direction.
It is the visibility/processing analog of the capture pillar's load-bearing rule: It is the visibility/processing analog of the capture pillar's load-bearing rule:
**designing and arranging are separate stances on one timeline**, and the tool **designing and arranging are separate stances on one timeline**, and the tool
@@ -297,10 +315,21 @@ togglable per selection.
## Non-goals / guardrails ## Non-goals / guardrails
- **No second canvas.** Do not build a parallel arrange surface — reject any such - **No *literal* second canvas.** A literal second arrange surface, a second window,
path in review. or a duplicated project stays **rejected** — reject any such path in review. This
guardrail was **narrowed (2026-07-23), not lifted**: per-item mode separation via
REAPER fixed lanes on shared tracks (an item-visibility projection over the one
timeline) is now **allowed** and specified in *§Two-canvas sub-phase* below. Paths
that remain **rejected**: subproject / second-project-file approaches, and
overloading item `D_POSITION` with mode semantics (timebase-offset regions) — the
latter collides with the capture null test. See `docs/product/design-view.md`
§Two-canvas direction for why those were rejected.
- **Never touch mute/solo.** Any code path reading/writing `B_MUTE` / `I_SOLO` is a - **Never touch mute/solo.** Any code path reading/writing `B_MUTE` / `I_SOLO` is a
bug. bug.
- **Never drive a manual lane** (Phase D2). A mode toggle touches only **managed**
lanes (minted by the mode system, keyed in the lane-ownership index). Any code path
that shows, hides, silences, or re-lanes a **manual** lane — a user-created comp/take
lane outside the mode system — is a bug. The tool drives only lanes it created.
- **Every leaf is managed.** The mode system owns all leaf tracks: an untagged leaf - **Every leaf is managed.** The mode system owns all leaf tracks: an untagged leaf
is an Arrange member, and when the active mode is not Arrange it is fully parked is an Arrange member, and when the active mode is not Arrange it is fully parked
and snapshot-restored exactly like a tagged leaf out of its mode. **show-both** is and snapshot-restored exactly like a tagged leaf out of its mode. **show-both** is
@@ -325,6 +354,136 @@ togglable per selection.
- Interaction with the user having a screenset active (Design View drives the same - Interaction with the user having a screenset active (Design View drives the same
flags a screenset recall would; last writer wins — confirm no surprising fight). flags a screenset recall would; last writer wins — confirm no surprising fight).
## Two-canvas sub-phase (Phase D2 / Phase E) — additive to D1
> **Additive sub-phase, settled 2026-07-23.** Extends D1's track-level mode
> projection to **item level** so each stance owns its own items as well as its own
> tracks. Nothing in D1 changes; this wraps it. Runtime floor rises to **REAPER 7**
> for this sub-phase (fixed lanes shipped in v7). Product framing in
> `docs/product/design-view.md` §Two-canvas direction.
### What it adds
On a track present in **both** stances (a show-both track, or a folder carrying its
own media), each mode owns a **fixed lane**: the active mode's lane shows and plays;
the inactive mode's lane is hidden and silent. A Design take and an Arrange take can
then live on the *same track, same time position*, without colliding on the view.
Track-only-in-one-mode content is still handled by D1 track-parking, unchanged.
### Settled decisions
- **Mechanism: fixed item lanes.** Map mode → lane; toggle drives per-lane play/show
so only the active mode's lane is present. Items keep their real position and real
track — nothing is moved in time or deleted. SDK surface (**verified present in
`vendor/reaper-sdk`**): track-side `I_FREEMODE = 2`, `I_NUMFIXEDLANES`,
`C_LANEPLAYS:N`; item-side `I_FIXEDLANE`, `C_LANEPLAYS`, `B_FIXEDLANE_HIDDEN`.
**`I_FREEMODE` changes require `UpdateTimeline()`** to take visible effect.
- **Membership: auto-tag by active mode at creation.** New content — **both new
tracks and new items** — is tagged to whatever mode is active when it is created.
Pre-existing content defaults to **Arrange**. Membership is **exclusive**:
Design-created content never appears in Arrange and vice versa, except via the
existing **show-both** escape hatch. (This is the same tag-to-active-mode rule as
D1 track membership, now reaching items on shared tracks.)
- **Inactive-mode content is hidden AND silenced.** The off-mode lane is set
`C_LANEPLAYS = 0` — neither shown nor played — consistent with exclusive
membership and with D1's "flipping modes is a real change, not cosmetic." Show-both
is the deliberate opt-out for a lane that must stay audible across modes.
- **Managed vs. manual lanes — indexed and distinct.** Fixed lanes are also REAPER's
native comping surface: a user may keep **their own** manual lanes (comp takes,
alternate reads) on a track alongside the mode system's lanes. The tool maintains a
**lane-ownership index** — per (track GUID, lane): **managed** (which mode owns it)
vs **manual** (user-minted, outside the mode system). Mode operations touch **only
managed lanes**; manual lanes are never shown, hidden, silenced, or re-laned by a
toggle, and their `C_LANEPLAYS` stays exactly as the user set it. Items a user adds
to a **manual** lane are **not** auto-tagged (auto-tag governs normal timeline
content, not hand-managed lanes). The ownership index rides in `"reasampler"`
`view_state` alongside the membership index, GUID-keyed and portable.
- **Capture placement is mode-aware.** An **explicit** placement while in Design mode
— including capture-and-place — lands the item in the **Design lane**; the same
rule governs manual insertion. **The capture load-bearing principle is untouched:**
capture still writes a file + index entry and **never** auto-inserts; this governs
only *where an explicit placement lands*.
- **REAPER floor: v7.** No version-gate branch — below v7 this sub-phase is simply
unavailable.
### Precision invariants (unaffected — called out explicitly)
The capture precision invariants — **null test, bit-identical repeats,
non-destructive, exact bounds, relative-paths-only** — are **entirely unaffected** by
this sub-phase. No capture path changes; lanes are a placement/view concern
downstream of the written file. Lane assignment and `C_LANEPLAYS` are **reversible
flags**: the item is never relocated in time or deleted, so the sub-phase extends the
D1 non-destructive snapshot/restore contract to a new (item-lane) flag family rather
than introducing any destructive operation.
**New invariant — mode operations touch only managed lanes.** A mode toggle drives
only lanes the mode system minted (managed lanes, keyed in the lane-ownership index).
Manual lanes — user-created comp/take lanes outside the mode system — are **never**
shown, hidden, silenced, or re-laned by a toggle; their `C_LANEPLAYS` is left exactly
as the user set it. This is the fixed-lane analog of *never touch `B_MUTE`/`I_SOLO`*
and *never touch master*: **the tool drives only what it created.** Enforceable and
testable in the pure layer — the "which lanes may this toggle touch" decision is a
pure query over the ownership index; only reading REAPER's live lane state is shell.
### Module architecture (preserve the pure/shell split)
- **Pure (`view_mode_model` extension).** Lane math — which lane maps to which mode,
which `C_LANEPLAYS` value per mode, the item-lane op family alongside the existing
track-flag op family — is **REAPER-free and unit-tested**, mirroring the D1
planner. The **lane-ownership index** (per (track GUID, lane): managed-which-mode vs
manual) and the **"which lanes may this toggle touch" query** (managed only) are
pure and unit-tested — the planner emits lane ops for managed lanes only and never
for manual lanes. The **auto-tag decision** is pure too: given *a set of new
track/item GUIDs + the active mode* — and, for items, whether the item landed in a
manual lane (exempt) — produce the membership writes.
- **Shell.** Two shell responsibilities. (1) **Apply** the planner's item-lane ops
(`I_FREEMODE`/`I_FIXEDLANE`/`C_LANEPLAYS`/`B_FIXEDLANE_HIDDEN` via the media-item
info setters, `UpdateTimeline()` after `I_FREEMODE` changes) — for managed lanes
only. (2) **Detect** new content and read live lane state — see below.
- **Persistence.** The tool persists which lane maps to which mode **and the
managed/manual ownership index** (a small addition to the `"reasampler"` view
section); REAPER stores fixed lanes and lane-plays in the `.rpp` natively.
### New-content detection (implementation design point)
REAPER exposes **no clean "item added" / "track added" event callback.** Auto-tagging
therefore requires the shell to **diff project state on the panel's existing timer**
the `bank_panel` already polls and fingerprints the bank; this extends that machinery
to the timeline's tracks and items.
- Each poll, compare the live track/item GUID set against the previous poll's set;
**any GUID new since the last poll is tagged to the then-active mode.**
- Correctness the implementation must handle: the **first poll after project open must
not mass-tag** pre-existing content (pre-existing defaults to Arrange, per the
membership rule).
- **Manual-lane exemption (design point).** An item added to a **manual** lane is
**not** auto-tagged — auto-tag governs normal timeline content, not lanes the user
hand-manages. Distinguishing the two may need a heuristic at detection (e.g., an item
whose `I_FIXEDLANE` is marked manual in the ownership index is exempt; content
outside any managed lane on a mode-managed track follows the active-mode rule). The
precise rule is an **open implementation design point**; the settled boundary is that
manual-lane content is off-limits to auto-tag.
- **Lane-identity fragility (design point).** `I_FIXEDLANE` is the lane's identity and
is how the ownership index keys to a lane. Whether the index survives lane
reorder/renumber/deletion without going stale is an **implementation design point**
(same class as GUID-keyed reorder-safety for tracks) — flag, don't solve here.
- Pure/shell seam: the **detection** (diffing REAPER's live set each tick, reading live
lane ownership) is shell; the **tagging decision** and the **managed/manual lane
query** (new GUIDs + active mode + manual-lane exemption ⇒ membership + lane writes)
are pure and unit-tested.
### REAPER API surface (verify all signatures)
- Fixed lanes — track: `I_FREEMODE` (=2), `I_NUMFIXEDLANES`, `C_LANEPLAYS:N` via
`GetMediaTrackInfo_Value`/`SetMediaTrackInfo_Value`; item: `I_FIXEDLANE`,
`C_LANEPLAYS`, `B_FIXEDLANE_HIDDEN` via `GetMediaItemInfo_Value` /
`SetMediaItemInfo_Value`. Call `UpdateTimeline()` after `I_FREEMODE` changes.
- Detection reuses the `bank_panel` timer + GUID fingerprinting already in place;
item GUIDs via the item's `GUID` (`GetSetMediaItemInfo_String` `"GUID"`), track
GUIDs via `GetTrackGUID` as in D1.
- **Verify every name/signature against the SDK header before use** — the surface is
verified *present*, but confirm argument order, types, and flag values.
--- ---
# Multi-bank — additive phase spec # Multi-bank — additive phase spec
+340 -8
View File
@@ -6,8 +6,10 @@ detail in `CONTEXT.md` (§Design View). This doc holds the *why* — the workflo
narrative, the N-mode reasoning, the screenset differentiation, and the narrative, the N-mode reasoning, the screenset differentiation, and the
design-direction recommendations — so those don't clutter the build docs. design-direction recommendations — so those don't clutter the build docs.
Status: settled with Daniel (2026-07-22). Open items for Daniel are listed at the Status: settled with Daniel (2026-07-22). The **two-canvas direction** (item-level
bottom. mode separation via fixed lanes) is also settled with Daniel (2026-07-23) — see the
§Two-canvas direction section, which **supersedes** the "not a second canvas"
framing below. Open items for Daniel are listed above that section.
--- ---
@@ -25,12 +27,19 @@ place it. The design scaffolding never touches the arrangement while you're
arranging, and the arrangement never buries the design bench while you're arranging, and the arrangement never buries the design bench while you're
designing. designing.
**It is not a second canvas.** REAPER has exactly one arrange timeline. Design **It is not a *literal* second canvas.** REAPER has exactly one arrange timeline.
View does not create a parallel surface, a separate window, or a duplicate Design View does not create a parallel surface, a separate window, or a duplicate
project. It is the *same timeline* with a curated, filtered track set and the project — that stays true and is enforced in review. It is the *same timeline* with
inactive tracks parked. Anyone expecting a second arrange view will be a curated, filtered track set and the inactive content parked.
disappointed — and that expectation must be headed off in the spec, not
discovered in review. > **Superseded in one respect (2026-07-23).** The original claim here was that
> Design View separates only *tracks*, not *items*. That is now extended: the
> settled §Two-canvas direction adds **item-level** mode separation on shared tracks
> via REAPER fixed lanes — so each stance can own its own items as well as its own
> tracks. It is still not a literal second surface/window/project; it is a mode
> *projection* over the one timeline that now reaches items. Read §Two-canvas
> direction for the settled shape; the sentence "It does not separate items" no
> longer holds.
This is the visibility/processing analog of the capture pillar's load-bearing This is the visibility/processing analog of the capture pillar's load-bearing
rule. The capture pillar says *capture and placement are separate acts*. Design rule. The capture pillar says *capture and placement are separate acts*. Design
@@ -345,3 +354,326 @@ tooltip on the switch.
deleted or a folder is restructured while parked, the index holds a stale GUID. deleted or a folder is restructured while parked, the index holds a stale GUID.
The pure model should tolerate unknown GUIDs (ignore-and-prune on next reconcile) The pure model should tolerate unknown GUIDs (ignore-and-prune on next reconcile)
— noted as a hardening item for the build, not a phase-defining decision. — noted as a hardening item for the build, not a phase-defining decision.
---
# Two-canvas direction — settled (2026-07-23)
> **Status: settled with Daniel (2026-07-23).** This section reopens and supersedes
> the "not a second canvas" decision above. Daniel's stated intent (verbatim): *"I
> wasn't the one who specified single-canvas, that emerged from REAPER's design. I
> want to come as close as possible to supporting two separate design and arrange
> canvases, which are actually the same project but have different items and
> leaves."* The single-canvas framing above was a **derivation from a REAPER
> constraint**, not a product choice — so it was reopened, and Daniel has now signed
> off on the mechanism (fixed item lanes) and resolved all five forks. Everything
> under this heading **supersedes** the "not a second canvas" language in *What it is
> (and what it is not)*: Design View is now a mode projection that reaches **both
> tracks and items**. This is an **additive sub-phase** (Phase D2 / Phase E) on top
> of the shipped track-parking work — not a rewrite of it.
## What actually changed in the ask
The shipped model separates modes by **track membership** on one shared timeline:
tag a leaf into Design, and when you flip to Arrange that leaf is parked — hidden,
out of the mix, FX offline. Because items ride their tracks, a Design track's items
already vanish from the Arrange view. **The "different leaves" half of Daniel's ask
is already delivered.** Flipping modes already gives you a different *track set*.
The genuinely new half is **"different items."** Daniel wants two canvases that
differ not only in which tracks are present but in which *items* are present —
including items that live on a track shared by both stances. Concretely: a track
that exists in both Arrange and Design (a show-both reference track, or a folder
carrying its own media) should be able to hold a design take that only appears in
Design and an arrangement take that only appears in Arrange, on the *same track*,
without the two colliding on the timeline. Track-parking can't express that,
because parking is all-or-nothing per track — it can hide a whole track, never a
subset of its items.
So the reframe is precise: **the feature grows from track-level mode separation to
track-level *plus* item-level mode separation.** "Two canvases" = each stance owns
its own item set, layered over the shared project, with tracks it doesn't want
parked as today.
## The hard constraint (and why it's not fatal)
REAPER has exactly one arrange timeline and one project item graph. There is no
API to instantiate a second arrange surface, and the "no second window/no
duplicate project" observation in the shipped framing is *structurally true* — you
cannot conjure a literal second canvas. What is reversed is only the **conclusion
drawn from it**: that item separation is therefore off the table. It isn't. Items
carry per-item state (`I_FIXEDLANE`, `C_LANEPLAYS`, `D_POSITION`, track
assignment) that the tool can drive to make an item present-or-absent *per mode*
without destroying it. "Two canvases" becomes an **item-visibility projection over
one timeline**, exactly as "two track sets" is a track-visibility projection over
one timeline today. Same discipline, one level deeper.
## Mechanism (settled) and the alternatives it beat
**The settled mechanism is Option A — fixed lanes as per-mode item layers.** The two
alternatives (B timebase-offset, C subproject) are kept below because *why they were
rejected* is load-bearing: both collide with settled invariants, and recording that
keeps them from being re-proposed.
### Option A — Fixed lanes as per-mode item layers (SETTLED)
REAPER's **fixed-lane** feature lets a single track hold multiple horizontal lanes
of items sharing one timebase, with **per-lane play/visibility control**. Map each
mode to a lane: Arrange items live in the Arrange lane, Design items in the Design
lane. Toggling a mode sets `C_LANEPLAYS` so only the active mode's lane plays and
shows; the collapse/hidden flags hide the inactive lane. Items keep their real
positions and their real track — nothing is moved off the timeline, nothing is
deleted.
**SDK surface (verified present in `vendor/reaper-sdk`).** Track-side:
`I_FREEMODE = 2` (fixed-lane mode), `I_NUMFIXEDLANES`, per-lane `C_LANEPLAYS:N`.
Item-side: `I_FIXEDLANE`, `C_LANEPLAYS`, `B_FIXEDLANE_HIDDEN`. Two operational
notes for the implementation spec: **`I_FREEMODE` changes require
`UpdateTimeline()`** to take visible effect, and fixed lanes shipped in **REAPER 7**,
which sets the runtime floor (see fork 5).
- **Fidelity to the two-canvas feel:** high. Same track, same time position, but the
design take and the arrange take are genuinely distinct item sets that never
co-occupy the view. This is exactly "same project, different items."
- **Non-destructiveness:** strong. Lane assignment and `C_LANEPLAYS` are
reversible flags; the item is never relocated in time or deleted. Snapshot the
prior lane state, restore on toggle — a direct extension of the existing
snapshot/restore contract to a new flag family.
- **Fit with park/restore:** clean. It's the same architecture — the planner gains
an item-lane op family alongside the track-flag op family. Pure model stays pure:
lane math (which lane = which mode, which `C_LANEPLAYS` value per mode) is
REAPER-free and unit-testable, mirroring the existing flag planner.
- **Capture-pillar precision:** untouched. Capture writes files to the bank and
never inserts into the timeline; lanes are a placement/view concern downstream of
capture. The null test and bit-identical invariants are unaffected because no
capture path changes.
- **Portability/persistence:** native. Fixed lanes and lane-plays are stored in the
`.rpp` by REAPER itself; the tool only persists which lane maps to which mode
(a small addition to the `"reasampler"` view section).
- **Cost / caveats:** fixed lanes are a real REAPER mode on a track — enabling
`I_FREEMODE=2` changes how that track behaves for the user (lane buttons, comp
behavior), and users unfamiliar with fixed lanes see new UI on managed tracks.
Under the settled **auto-tag** membership rule (see *Membership — settled* below),
a track becomes lane-split when it first needs to hold content for a second mode,
not by a manual "make this a two-canvas track" opt-in. Requires **REAPER 7**, where
fixed lanes shipped — this sets the runtime floor.
### Option B — Timebase-region offset (each mode owns a stretch of the timeline)
Give each mode a disjoint region of the single timeline — Arrange from 0, Design
starting at some large offset (say bar 1000). Items are authored in their mode's
region; toggling a mode scrolls/zooms the arrange view to that region
(`GetSet_ArrangeView2`) and optionally sets the loop/time selection there.
Different items appear because you're *looking at a different part of the timeline*.
- **Fidelity:** medium. It reads as two workspaces if the scroll is snappy, but
they share tracks vertically — a Design track is still a lane on the same track
strip, just at a different horizontal offset. It doesn't give per-track item
layering; a shared track shows both stances' items if you scroll between them.
- **Non-destructiveness:** high (items just have positions), but **positions become
semantically loaded** — an item's `D_POSITION` now encodes its mode. That
collides with the capture pillar's null test, which re-inserts a capture *at its
source position* to verify it nulls. If source positions live in the Design
region, the null-test placement logic has to be region-aware. Friction with a
load-bearing invariant.
- **Fit with park/restore:** awkward. Parking is per-track; this is per-region.
Two orthogonal separation axes that don't compose cleanly.
- **Portability:** fine (just positions + a stored offset), but the offset is a
magic constant that leaks into every position calculation.
- **Verdict:** clever, but it overloads timeline position with mode semantics and
rubs against the capture invariants. Not recommended.
### Option C — Dual sub-projects / project tabs (true separation, heavy)
REAPER supports project tabs and subprojects (a project rendered as an item in a
parent). Model Design as a genuinely separate project surface, imported/rendered
back into Arrange. This is the *only* option that yields a literally separate
canvas.
- **Fidelity:** highest — it *is* two canvases.
- **Cost:** enormous, and it fights the whole premise. "Same project" is Daniel's
explicit constraint; a subproject is a *different* project file with its own
item graph, its own render boundary, and a copy/sync problem between the two. The
capture pillar's "one bank per project, GUID-keyed project identity, travels with
the .rpp" assumption breaks — which project owns the bank? Persistence,
reconcile, and the show-both/derivation model all have to be rethought across a
project boundary. This is a different product.
- **Verdict:** rejected. It satisfies "two canvases" literally by violating "same
project." Daniel asked for *close as possible* within one project, not a second
project.
## The settled shape
**Option A — fixed lanes as per-mode item layers — layered on top of the shipped
track-parking model.** The shipped model already delivers "different leaves"; this
adds "different items" using a native REAPER mechanism that (a) preserves every
precision invariant, (b) extends the existing snapshot/restore architecture rather
than replacing it, (c) keeps the pure/shell split intact (lane math is pure, lane
writes are shell), and (d) persists natively. It is the transplant-a-known-pattern
move: REAPER already solved "multiple item sets, one track, one timebase,
switchable visibility" for comping — we repurpose comping lanes as mode lanes.
The mental model: **modes are a projection, and now the projection reaches items as
well as tracks.** A track can be Arrange-only (parked in Design as today),
Design-only (parked in Arrange as today), or **shared-and-lane-split** (present in
both, but showing each mode its own lane of items). The third case is the new
capability and the concrete meaning of "two canvases."
Phase namespace: **Phase D2 / Phase E** (per the lettered-phase convention for
parallel features) — additive to the shipped D1 track-mode work, not a rewrite.
## Membership — settled (auto-tag by active mode at creation)
The earlier draft floated a manual per-track opt-in ("make this a two-canvas
track"). **That is superseded.** The settled rule, verbatim from Daniel:
> *"Items AND tracks added to the timeline in arrange mode or design mode should be
> tagged as for that mode only. Existing tracks and items default to arrange. If an
> item is added to arrange mode, it does not appear in design mode. If an item is
> added in design mode, it is NOT part of the arrange mode."*
Unpacked into the settled model:
- **Auto-tag at creation, not manual opt-in.** New content — **both new tracks and
new items** — is tagged to whatever mode is **active at the moment it is created**.
There is no separate "convert this track" gesture; membership follows the active
stance automatically.
- **Pre-existing content defaults to Arrange.** Every track and item that existed
before the mode system (or before this sub-phase) is an Arrange member, exactly as
the track-level default already established.
- **Membership is exclusive.** Design-created content never appears in Arrange, and
Arrange-created content never appears in Design — the one exception is the existing
**show-both** escape hatch, which continues to pin a leaf visible across modes.
- **Track level unchanged; item level is the new reach.** At the track level this is
the same tag-to-active-mode rule already settled. What is new: when a **shared**
track (present in both stances — a show-both track, or a folder carrying its own
media) gains an item in Design mode, that item lands in the track's **Design lane**
and is invisible/silent in Arrange, and vice versa. That per-item split is the
fixed-lane mechanism doing its job.
This resolves the old fork 2 (opt-in vs. automatic) in favor of **automatic**, and
it is the through-line that also settles fork 4 (capture placement) below.
## Inactive-mode items — settled (hidden AND silenced)
When you are in one mode, the other mode's items on a shared track are **both hidden
and silenced**: the off-mode lane is set `C_LANEPLAYS = 0` — neither shown nor
played. This matches the exclusive-membership rule (Design-created content is *not
part of* Arrange, so it must not sound there) and the track-level principle already
settled: **flipping modes is a real change, not a cosmetic one.** A user who wants
the design lane audible under the arrangement uses show-both, which is the deliberate
opt-out; the default is full separation.
## Managed vs. manual lanes — settled (2026-07-23)
Fixed lanes are not only the mechanism we borrow for mode-item layering — they are
also **REAPER's native comping surface.** A user may want *their own* multiple lanes
on a track (manual comp takes, alternate reads) that have nothing to do with the mode
system. So a fixed-lane track can host **both** kinds of lane at once, and the tool
must not confuse them. Daniel's constraint, verbatim intent: *"as long as I can still
opt in manually to put multiple lanes on a track. we must index which lanes are
managed and which lanes are manual."*
The settled distinction:
- **Managed lanes** — minted and owned by the mode system to represent a mode's item
set on that track. Mode toggles drive these: the active mode's managed lane shows
and plays (`C_LANEPLAYS`), inactive-mode managed lanes are hidden and silenced.
These are the lanes the two-canvas mechanism creates and controls.
- **Manual lanes** — lanes the user created outside the mode system (native REAPER
comping, alternate takes). The mode system did **not** mint these and **must never
touch them**: a mode toggle never shows, hides, silences, re-lanes, or re-plays a
manual lane. Its `C_LANEPLAYS` state is the user's, left exactly as they set it.
This is the fixed-lane analog of the two invariants already load-bearing in D1 —
*never touch `B_MUTE`/`I_SOLO`* and *never touch the master* — extended to a third
surface: **never drive a lane the tool did not mint.** It is the same non-destructive
promise (the tool owns only what it created) reaching one level deeper, into the lane
dimension.
### Lane-ownership index (the new data)
The tool maintains a **lane-ownership index**: per (track GUID, lane) it records
whether the lane is **managed** (and if so, which mode owns it) or **manual**. This
rides in the `"reasampler"` `view_state` alongside the membership index, GUID-keyed
and portable — same travel-with-the-`.rpp` guarantee as everything else in the view
section. Deciding *which lanes a toggle may touch* (managed only) is a **pure,
testable** query over this index; reading REAPER's live lane state is **shell**. The
seam is the same as everywhere else in the phase.
> **Lane-identity fragility — flag for the implementation spec, not solved here.**
> REAPER's `I_FIXEDLANE` is the lane's identity and is how the ownership index keys to
> a specific lane. Whether `I_FIXEDLANE` values survive lane reorder / renumber /
> deletion without the index going stale is a **design point the technical spec must
> resolve** (the same class of concern as GUID-keyed reorder-safety for tracks). The
> product decision is only that managed and manual lanes are indexed and distinct; how
> the index stays correct under lane reordering is an implementation call, not a
> product one.
### What a mode toggle does to manual lanes (intended behavior)
A mode toggle **leaves every manual lane exactly as the user set it** — its
`C_LANEPLAYS` (play/show) state is untouched across the toggle. Only managed lanes are
partitioned into active (shown/played) and inactive (hidden/silenced). Concretely: if
a shared track has an Arrange managed lane, a Design managed lane, and two manual comp
lanes the user is auditioning, flipping Arrange↔Design swaps which managed lane plays
and leaves both manual lanes precisely as they were.
**Interaction with auto-tag.** Auto-tag applies to content the user adds as **normal
timeline content** — items dropped, recorded, or placed onto the arrange surface in
the active mode. It does **not** reach into a lane the user is hand-managing: items a
user adds to a **manual** lane are **not** auto-tagged to the active mode, because the
user has taken explicit lane control there and the tool respects that boundary — the
manual/managed distinction is exactly the signal that this content is outside the mode
system.
> **Auto-tag/manual-lane boundary heuristic — flag for the implementation spec.**
> Distinguishing "item added as normal timeline content (auto-tag it)" from "item added
> to a manual lane the user hand-manages (leave it alone)" may need a heuristic at the
> detection layer — e.g., an item landing in a lane the ownership index marks manual is
> exempt from auto-tag; an item landing outside any managed lane on a mode-managed
> track follows the active-mode rule. The precise rule is an **open implementation
> design point**, not invented here. The product decision is the boundary itself:
> manual-lane content is off-limits to auto-tag.
## Capture placement — settled (mode-aware)
Daniel's rule is general over *"items added to the timeline."* So an **explicit**
placement while in Design mode — including capture-and-place — lands the item in the
**Design lane**; the same rule governs manual insertion. This is the same auto-tag
rule reaching the placement pillar, not a new special case.
**The capture load-bearing principle is untouched.** Capture still writes a file to
the bank and an index entry and **never** auto-inserts into the timeline. This rule
governs only *where an explicit placement lands* once the user chooses to place —
it does not create any auto-insertion path. The precision invariants (null test,
bit-identical repeats, non-destructive, exact bounds, relative paths) are entirely
unaffected: no capture path changes; lanes are a placement/view concern downstream
of the file.
## REAPER version floor — settled (v7)
Fixed lanes shipped in **REAPER 7**, so this sub-phase sets the runtime floor at
**v7**. The full API surface (track-side `I_FREEMODE=2` / `I_NUMFIXEDLANES` /
`C_LANEPLAYS:N`, item-side `I_FIXEDLANE` / `C_LANEPLAYS` / `B_FIXEDLANE_HIDDEN`) is
**verified present in the vendored SDK header**. No version gate branch is needed —
below v7 the sub-phase is simply unavailable.
## Technical consideration — detecting new content (for the implementation spec)
**REAPER exposes no clean "item added" / "track added" event callback.** The auto-tag
rule therefore requires the shell to detect new track/item GUIDs by **diffing project
state on the panel's existing timer**. The `bank_panel` already polls and fingerprints
the bank; this extends that same machinery to the timeline's tracks and items.
- **Cadence / correctness.** Each poll, the shell compares the live track/item GUID
set against the previous poll's set; **any GUID new since the last poll is tagged to
the then-active mode.** The diffing cadence and the "new-since-last-poll ⇒ tag"
correctness rule are a design point the implementation must handle (e.g., first poll
after project open must not mass-tag pre-existing content — pre-existing defaults to
Arrange, per the membership rule).
- **Pure/shell split.** The **tagging decision** — given a set of new GUIDs plus the
active mode, produce the membership writes — is **pure and unit-testable**, mirroring
the existing planner. The **detection** — diffing REAPER's live item/track set each
timer tick — is **shell**. Keep the seam here: the shell hands the pure model "these
GUIDs are new, the active mode is M," and the model returns the membership mutations.