cgcardona / muse public
muse-variation-spec.md markdown
216 lines 5.3 KB
83fa3d6e docs: full sweep — domain-agnostic rewrite of all docs Gabriel Cardona <gabriel@tellurstori.com> 3d ago
1 # Muse Variation Spec — Music Domain Reference
2
3 > **Scope:** This spec describes the *Variation* UX pattern as implemented
4 > for the music domain in the Stori DAW + Maestro backend. It is not part of
5 > the core Muse VCS engine.
6 >
7 > For the domain-agnostic VCS protocol, see [muse-protocol.md](muse-protocol.md).
8 > For a discussion of how "Variation" might generalize across domains, see
9 > [muse-domain-concepts.md](muse-domain-concepts.md).
10
11 ---
12
13 ## What a Variation Is
14
15 A Variation is a **proposed musical change set awaiting human review** before
16 being committed to the Muse DAG. It is the music plugin's implementation of the
17 propose → review → commit pattern.
18
19 ```
20 VCS equivalent mapping:
21 Variation = A staged diff
22 Phrase = A hunk (contiguous group of changes within a region)
23 Accept = muse commit
24 Discard = Discard working-tree changes (no commit)
25 Undo = muse revert
26 ```
27
28 The defining characteristic: a Variation is *heard before committed* — the
29 musician auditions the proposed change in the DAW's playback engine and then
30 decides whether to accept or discard. This is layered on top of the VCS DAG,
31 not part of it.
32
33 ---
34
35 ## Lifecycle
36
37 ```
38 1. Variation Proposed — AI or user creates a proposed change set
39 2. Stream — phrases stream to the DAW in SSE events
40 3. Review Mode Active — DAW shows proposed state alongside canonical state
41 4. Accept (or partial) — accepted phrases are committed; discarded phrases are dropped
42 5. Canonical state updates — only after commit
43 ```
44
45 Canonical state MUST NOT change during review. The proposed state is always
46 ephemeral.
47
48 ---
49
50 ## Terminology
51
52 | Term | Definition |
53 |---|---|
54 | **Variation** | A proposed set of musical changes, organized as phrases |
55 | **Phrase** | A bounded group of note/controller changes within one region |
56 | **NoteChange** | An atomic note delta: added, removed, or modified |
57 | **Canonical State** | The actual committed project state in the Muse DAG |
58 | **Proposed State** | The ephemeral preview state during variation review |
59 | **Accept** | Committing accepted phrases to the Muse DAG |
60 | **Discard** | Dropping the variation; canonical state unchanged |
61
62 ---
63
64 ## Execution Mode Policy
65
66 | User Intent | Mode | Result |
67 |---|---|---|
68 | Composing / generating | `variation` | Produces a Variation for human review |
69 | Editing (add track, set tempo) | `apply` | Applied immediately, no review |
70 | Reasoning / chat only | `reasoning` | No state mutation |
71
72 The backend enforces execution mode. Frontends MUST NOT override it.
73
74 ---
75
76 ## Data Shapes
77
78 ### Variation (meta event)
79
80 ```json
81 {
82 "variationId": "...",
83 "intent": "add countermelody to verse",
84 "aiExplanation": "I added a countermelody in the upper register...",
85 "noteCounts": { "added": 12, "removed": 0, "modified": 3 }
86 }
87 ```
88
89 ### Phrase
90
91 ```json
92 {
93 "phraseId": "...",
94 "trackId": "...",
95 "regionId": "...",
96 "startBeat": 1.0,
97 "endBeat": 5.0,
98 "label": "Verse countermelody",
99 "noteChanges": [...],
100 "controllerChanges": [...]
101 }
102 ```
103
104 ### NoteChange
105
106 ```json
107 {
108 "noteId": "...",
109 "changeType": "added",
110 "before": null,
111 "after": {
112 "startBeat": 1.5,
113 "durationBeats": 0.5,
114 "pitch": 72,
115 "velocity": 80
116 }
117 }
118 ```
119
120 Rules:
121 - `added` → `before` MUST be `null`
122 - `removed` → `after` MUST be `null`
123 - `modified` → both `before` and `after` MUST be present
124
125 ---
126
127 ## SSE Streaming Contract
128
129 Events stream in this order (strictly):
130
131 ```
132 meta → phrase* → done
133 ```
134
135 | Event type | When sent |
136 |---|---|
137 | `meta` | First event; carries variation summary |
138 | `phrase` | One per phrase; may be many |
139 | `done` | Last event; signals review mode is active |
140
141 Event envelope:
142 ```json
143 {
144 "type": "phrase",
145 "sequence": 3,
146 "variationId": "...",
147 "projectId": "...",
148 "baseStateId": "...",
149 "timestampMs": 1234567890,
150 "payload": { ...phrase... }
151 }
152 ```
153
154 `sequence` is strictly increasing. `baseStateId` is the Muse snapshot ID the
155 variation was computed against.
156
157 ---
158
159 ## API Endpoints
160
161 | Method | Path | Purpose |
162 |---|---|---|
163 | `POST` | `/variation/propose` | Propose a new variation |
164 | `GET` | `/variation/stream` | SSE stream of meta + phrase events |
165 | `POST` | `/variation/commit` | Accept (all or partial phrases) |
166 | `POST` | `/variation/discard` | Discard without committing |
167 | `GET` | `/variation/{id}` | Poll status / reconnect |
168
169 ### Commit request
170
171 ```json
172 {
173 "variationId": "...",
174 "acceptedPhraseIds": ["phrase-1", "phrase-3"]
175 }
176 ```
177
178 Partial acceptance is supported: only listed phrases are committed.
179
180 ---
181
182 ## Audition Modes
183
184 | Mode | What plays |
185 |---|---|
186 | Original | Canonical state only |
187 | Variation | Proposed state (with changes applied) |
188 | Delta Solo | Only the added/modified notes |
189
190 ---
191
192 ## Safety Rules
193
194 1. Review mode is isolated — destructive edits are blocked during review.
195 2. Canonical state MUST NOT mutate during proposal.
196 3. Commit is a single undo boundary: `muse revert` can undo the entire commit.
197 4. If the stream fails mid-phrase, keep received phrases and allow the user to
198 discard or commit what arrived.
199
200 ---
201
202 ## Relationship to Muse VCS
203
204 A committed Variation becomes a standard `muse commit` in the DAG:
205
206 ```bash
207 muse log --oneline
208 ```
209
210 ```
211 a1b2c3d4 (HEAD -> main) Add countermelody to verse
212 ```
213
214 From Muse's perspective, a committed Variation is indistinguishable from any
215 other commit. The Variation UX is a music-domain layer on top of the standard
216 VCS commit cycle.