docs: spec Phase Omega — mode-switch responsiveness and the control surface's second pass

Eight tracks across two waves, from Daniel's seven-item list of 2026-08-03; all
six forks ruled, none open. Amends instrument-control-surface.md 6.3(d) and 6.4,
both reversed by Omega-F2.
This commit is contained in:
2026-08-03 11:43:28 -04:00
parent 3376f3eaa1
commit 0eb2c67875
2 changed files with 784 additions and 34 deletions
+46 -30
View File
@@ -1156,17 +1156,23 @@ cosmetic gain.
**(d) The off-state and the Trigger state get words, not just alpha.**
- **Loop off.** The pair draws in the kit's **Disabled** state with a centred dim caption in
the span — `DRAG TO SET LOOP` when no span has ever been set (the pair is parked at the
last quarter, `defaultLoopBounds`), `LOOP OFF` when a span is retained. The full off-state
machine, and what the explicit enable does to it, is **§6.4**.
- **Trigger mode.** Loop is Gate-only (`resolveLoop` refuses in Trigger) but the markers
still draw at full strength today, which is marks that do nothing. **In Trigger the loop
pair and the crossfade mark draw Disabled and are not grabbable**, with a dim
`LOOP — GATE ONLY` caption in the span. Disabled rather than hidden, because that is the
established grammar — the editor's Gate segment already refuses and paints Disabled off
the `splineActive` predicate — and because hiding a set loop on a mode flip destroys
information the user put there. The START mark stays fully live in both modes.
> **AMENDED by Ω-F2 (Daniel, 2026-08-03).** The Trigger bullet below is REVERSED and the
> `LOOP — GATE ONLY` caption is retired; the Gate off-state bullet survives with its styling
> corrected. The amended text is what ships — see `docs/PLAN.md` §Phase Ω, Ω-W1-T5.
- **Loop off (Gate).** The pair stays **drawn and grabbable**, styled **grey disabled** — not
the dim teal that shipped, which read as decoration rather than as an off state
(*"that was not intuitive to me"*). The centred dim caption in the span survives and still
says which off state you are in: `DRAG TO SET LOOP` when no span has ever been set (the pair
is parked at the last quarter, `defaultLoopBounds`), `LOOP OFF` when a span is retained. The
full off-state machine, and what the explicit enable does to it, is **§6.4**.
- **Trigger mode.** Loop is Gate-only (`resolveLoop` refuses in Trigger). **In Trigger the loop
pair and the crossfade mark are HIDDEN OUTRIGHT** — not Disabled, not dim: absent, along with
their labels and the caption. *"Trigger mode doesn't work with loop anyway."* The stored span
is untouched and returns with the mode, so nothing the user put there is destroyed — only its
drawing is suppressed where it can mean nothing. **The superseded rule, recorded so it is not
reinstated: the marks once drew Disabled-rather-than-hidden in Trigger, with a dim
`LOOP — GATE ONLY` caption in the span.** The START mark stays fully live in both modes.
### 6.4 The explicit loop enable (Γ-F4, ruled by Daniel 2026-08-01)
@@ -1255,34 +1261,44 @@ The parked pair at the last quarter was carrying two messages in one alpha value
no loop* **and** *drag here to make one*. The enable takes the first message; the pair keeps
the second.
- **Off, no span ever set** — pair parked at `defaultLoopBounds`, drawn Disabled, caption
`DRAG TO SET LOOP`. Dragging either mark **turns the enable on.** The shipped
drag-to-create gesture survives intact, and it now teaches the enable by demonstration:
the user drags and watches the chrome toggle light up.
- **Off, span retained** — pair drawn Disabled *at its own positions*, caption `LOOP OFF`.
There is nothing to "set," so the drag-me copy would be wrong. Dragging still turns the
enable on, by the same rule.
- **Off, no span ever set** — pair parked at `defaultLoopBounds`, drawn **grey disabled**
(Ω-F2; the shipped dim teal was not readable as an off state), caption `DRAG TO SET LOOP`.
Dragging either mark **turns the enable on.** The shipped drag-to-create gesture survives
intact, and it now teaches the enable by demonstration: the user drags and watches the chrome
toggle light up.
- **Off, span retained** — pair drawn **grey disabled** *at its own positions*, caption
`LOOP OFF`. There is nothing to "set," so the drag-me copy would be wrong. Dragging still
turns the enable on, by the same rule.
- **On** — full four-mark grammar of §6.3, unchanged.
> **A grab implies intent to loop.** That is the one rule behind both off-states, and it is
> what keeps the enable from being a gate the user has to remember to open.
> **A grab implies intent to loop. This rule SURVIVES Ω-F2 and is the reason the Gate off-state
> marks stay grabbable rather than going grey-and-inert.** It is what keeps the enable from
> being a gate the user has to remember to open. It has nothing to say about Trigger, where
> there is no mark to grab.
#### The Trigger case — the enable disables itself, it does not clear itself
Per the Disabled-not-hidden principle already established for the marks: **in Trigger the
chrome-row enable draws Disabled and inert, with its state preserved and restored on the
return to Gate.** It does not clear `hasLoop`, and it does not hide. The enable's Disabled
state and the span's `LOOP — GATE ONLY` caption are the same message delivered at two
scales — the chrome row says *this control is unavailable here*, the span says *why*.
> **AMENDED by Ω-F2 (Daniel, 2026-08-03).** The MARKS are now hidden in Trigger (§6.3(d) as
> amended); the chrome-row ENABLE is not. The two halves of the old "same message at two
> scales" argument no longer travel together, and the paragraph below says which one survives.
**In Trigger the chrome-row enable draws Disabled and inert, with its state preserved and
restored on the return to Gate.** It does not clear `hasLoop`, and it does not hide — a control
that vanishes from the chrome row costs the user the map of what the instrument has. **The
span's `LOOP — GATE ONLY` caption is retired along with the marks it was centred in**, so the
chrome row now carries the message alone: *this control is unavailable here*. The *why* is the
mode segment sitting beside it.
This transitively covers the drawn-EG case: `enforceGateUnavailableWhileDrawn`
(`play_params.h:198-205`) forces Trigger whenever any envelope is drawn, so a spline EG
(`play_params.h`) forces Trigger whenever any envelope is drawn, so a spline EG
disables the loop enable through the same predicate rather than through a second rule.
**Disabled-but-grabbable (the off marks) vs. Disabled-and-inert (Trigger) is a deliberate
distinction, not an inconsistency**, and the discriminator is who said no: the user's own
off is reversible by the very gesture being offered, while Trigger's refusal comes from the
engine and no marker drag can talk it out of it.
**Three states, not two, and collapsing any pair of them is a defect:** *grey-disabled but
grabbable* (the Gate off marks — the user's own off, reversible by the very gesture on offer),
*Disabled and inert* (the chrome enable in Trigger — the engine's refusal, which no drag can
talk it out of), and *absent* (the marks in Trigger — a position that can mean nothing in this
mode). The discriminator between the first two is who said no; the discriminator for the third
is whether the thing being drawn could be acted on at all.
### 6.5 Trade-offs and consequences, named