demo-script.md
markdown
| 1 | # Muse Demo — Video Narration Script (v0.1.2) |
| 2 | |
| 3 | > **Format:** YouTube walkthrough of the interactive Muse demo. |
| 4 | > Open `artifacts/demo.html` before recording. Click **Play Tour** |
| 5 | > and let the demo advance step by step while you narrate. Timestamps are |
| 6 | > approximate at 1.2 s/step; adjust to your natural pace. |
| 7 | > |
| 8 | > **Tone:** conversational, curious, a little excited — like showing a friend |
| 9 | > something you built that you genuinely believe in. |
| 10 | > |
| 11 | > **What's new in v0.1.2:** After the original 5 acts, we now have **4 additional |
| 12 | > acts** covering Typed Delta Algebra, Domain Schema & Diff Algorithms, |
| 13 | > Operation-Level OT Merge, CRDT Convergent Writes, and the live Domain Dashboard. |
| 14 | > The original 41 steps are unchanged — new acts continue from step 42. |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## INTRO — Before clicking anything (~90 s) |
| 19 | |
| 20 | *(Camera on screen, demo paused at step 0)* |
| 21 | |
| 22 | Hey — so I want to show you something I've been building called **Muse**. |
| 23 | |
| 24 | The elevator pitch: Muse is a version control system for multidimensional |
| 25 | state. Think Git, but instead of treating a file as the smallest thing you |
| 26 | can reason about, Muse understands the *internal structure* of your files — |
| 27 | and that changes everything about what a conflict means. |
| 28 | |
| 29 | To make this concrete I'm going to use music, because music is a perfect |
| 30 | example of something that *looks* like a file but is actually several |
| 31 | completely independent things layered on top of each other. |
| 32 | |
| 33 | Take a MIDI file. On disk it's one blob of bytes. But inside it there are at |
| 34 | least five things that have nothing to do with each other: |
| 35 | |
| 36 | - **Melodic** — the notes being played, the pitch and duration of each one |
| 37 | - **Rhythmic** — when those notes land in time, the groove, the syncopation |
| 38 | - **Harmonic** — chord voicings, key changes, the tonal color |
| 39 | - **Dynamic** — velocity, expression, how hard or soft each note hits |
| 40 | - **Structural** — tempo, time signature, the skeleton the rest hangs on |
| 41 | |
| 42 | These are orthogonal axes. A drummer and a pianist can edit the same MIDI |
| 43 | file — one touching only the rhythmic dimension, the other only the harmonic |
| 44 | — and there is *no conflict*. They didn't touch the same thing. Git would |
| 45 | flag the whole file. Muse resolves it in silence. |
| 46 | |
| 47 | That's the idea. Let me show you the demo. |
| 48 | |
| 49 | --- |
| 50 | |
| 51 | ## HEADER — Reading the stats (~20 s) |
| 52 | |
| 53 | *(Point to the stats bar: 14 commits · 6 branches · 1 merge · 1 conflict resolved · 41 operations)* |
| 54 | |
| 55 | Everything you're about to see ran against a real Muse repository — real |
| 56 | commits, real branches, real SHA-256 content hashes. The whole demo took |
| 57 | about 150 milliseconds to execute. |
| 58 | |
| 59 | Fourteen commits. Six branches. One merge conflict. All resolved. Let's |
| 60 | walk through how we got here. |
| 61 | |
| 62 | --- |
| 63 | |
| 64 | ## ACT 1 — Foundation (Steps 1–5) |
| 65 | |
| 66 | *(Click Play Tour — steps 1–5 advance. Pause after step 5.)* |
| 67 | |
| 68 | ### Step 1 — `muse init` |
| 69 | |
| 70 | We start with an empty directory. `muse init` creates the `.muse/` folder — |
| 71 | the repository root. Content-addressed object store, branch metadata, config |
| 72 | file. Same idea as `git init`, but designed from scratch to be domain-agnostic. |
| 73 | |
| 74 | ### Step 2 — `muse commit -m "Root: initial state snapshot"` |
| 75 | |
| 76 | This is the first commit. Notice in the dimension matrix at the bottom — |
| 77 | every single dimension lights up on this first commit. Melodic, rhythmic, |
| 78 | harmonic, dynamic, structural — all five. Because this is the root: we're |
| 79 | establishing the baseline state for every dimension simultaneously. |
| 80 | |
| 81 | Under the hood, Muse called `MidiPlugin.snapshot()` — which walked the |
| 82 | working directory, hashed every MIDI file with SHA-256, and returned a |
| 83 | content-addressed manifest. That manifest is what got committed to the DAG. |
| 84 | |
| 85 | ### Step 3 — `muse commit -m "Layer 1: add rhythmic dimension"` |
| 86 | |
| 87 | Now we add a layer. Look at the dimension matrix: only **rhythmic** and |
| 88 | **structural** light up. Rhythmic because we're adding a new rhythmic layer |
| 89 | file. Structural because adding a file changes the shape of the snapshot. |
| 90 | The melodic, harmonic, and dynamic dimensions? Untouched. Muse sees that. |
| 91 | |
| 92 | ### Step 4 — `muse commit -m "Layer 2: add harmonic dimension"` |
| 93 | |
| 94 | Same pattern — **harmonic** and **structural** light up. We're adding a |
| 95 | harmonic layer. The rhythmic work from the previous commit is preserved |
| 96 | exactly as-is. These are independent operations on independent dimensions. |
| 97 | |
| 98 | ### Step 5 — `muse log --oneline` |
| 99 | |
| 100 | Quick sanity check. Three commits, linear history, on `main`. This is your |
| 101 | foundation — the musical canvas everyone will branch from. |
| 102 | |
| 103 | --- |
| 104 | |
| 105 | ## ACT 2 — Divergence (Steps 6–16) |
| 106 | |
| 107 | *(Resume Play Tour — steps 6–16. Pause after step 16.)* |
| 108 | |
| 109 | *(Point to the DAG as branches appear)* |
| 110 | |
| 111 | This is where it gets interesting. We're going to branch the repository three |
| 112 | ways simultaneously — three different creative directions diverging from the |
| 113 | same base. |
| 114 | |
| 115 | ### Steps 6–8 — Branch `alpha` |
| 116 | |
| 117 | `muse checkout -b alpha` creates a new branch. We commit two texture patterns: |
| 118 | |
| 119 | - **"Alpha: texture pattern A (sparse)"** — melodic and rhythmic dimensions. |
| 120 | A sparse arrangement: few notes, lots of space. |
| 121 | - **"Alpha: texture pattern B (dense)"** — melodic and dynamic dimensions. |
| 122 | The dense version: more notes, more expression. |
| 123 | |
| 124 | Watch the dimension dots on the DAG nodes — each commit shows exactly which |
| 125 | dimensions it touched. Alpha is doing melodic work. |
| 126 | |
| 127 | ### Steps 9–11 — Branch `beta` |
| 128 | |
| 129 | Back to `main`, then `muse checkout -b beta`. One commit: |
| 130 | |
| 131 | - **"Beta: syncopated rhythm pattern"** — rhythmic and dynamic dimensions. |
| 132 | |
| 133 | Beta is a completely different musical idea. It's not touching melody at all — |
| 134 | it's a rhythm section, working in its own lane. Rhythmic and dynamic only. |
| 135 | |
| 136 | ### Steps 12–15 — Branch `gamma` |
| 137 | |
| 138 | Back to `main`, then `muse checkout -b gamma`. Two commits: |
| 139 | |
| 140 | - **"Gamma: ascending melody A"** — pure melodic dimension. |
| 141 | - **"Gamma: descending melody B"** — melodic and harmonic. The descending |
| 142 | line implies a harmonic movement, so two dimensions change. |
| 143 | |
| 144 | ### Step 16 — `muse log --oneline` |
| 145 | |
| 146 | Three parallel stories. Alpha is building texture. Beta is building rhythm. |
| 147 | Gamma is building melody. None of them know about each other. The DAG is |
| 148 | starting to look like a real project. |
| 149 | |
| 150 | --- |
| 151 | |
| 152 | ## ACT 3 — Clean Merges (Steps 17–21) |
| 153 | |
| 154 | *(Resume Play Tour — steps 17–21. Pause after step 21.)* |
| 155 | |
| 156 | Now we bring it together. This is the part that's usually painful in Git. |
| 157 | In Muse, it's going to be boring — which is the point. |
| 158 | |
| 159 | ### Steps 17–18 — Merge `alpha` → `main` |
| 160 | |
| 161 | `muse checkout main`, then `muse merge alpha`. The output says: |
| 162 | `Fast-forward to cb4afaed`. |
| 163 | |
| 164 | Alpha was strictly ahead of main — no divergence. Fast-forward. Zero conflict. |
| 165 | |
| 166 | ### Step 19 — `muse status` |
| 167 | |
| 168 | `Nothing to commit, working tree clean.` Main now has all of alpha's work. |
| 169 | |
| 170 | ### Step 20 — Merge `beta` → `main` |
| 171 | |
| 172 | `muse merge beta`. This one creates a real merge commit — |
| 173 | `Merged 'beta' into 'main'`. |
| 174 | |
| 175 | Here's what happened under the hood: Muse found the common ancestor (the |
| 176 | `Layer 2` commit), computed the three-way delta, and asked: did the same |
| 177 | dimension change on both sides? |
| 178 | |
| 179 | - Alpha touched **melodic** and **dynamic**. |
| 180 | - Beta touched **rhythmic** and **dynamic**. |
| 181 | - Dynamic changed on *both sides*. |
| 182 | |
| 183 | In Git: `CONFLICT`. In Muse: the dynamic changes are on different files, so |
| 184 | the union is clean. Merge commit. No human intervention. Done. |
| 185 | |
| 186 | *(Point to the merge commit node in the DAG — it has the double-ring that marks it as a merge)* |
| 187 | |
| 188 | ### Step 21 — `muse log --oneline` |
| 189 | |
| 190 | The DAG shows the merge. Main now contains the work of three contributors. |
| 191 | Clean. |
| 192 | |
| 193 | --- |
| 194 | |
| 195 | ## ACT 4 — Conflict & Resolution (Steps 22–31) |
| 196 | |
| 197 | *(Resume Play Tour — steps 22–31. Pause after step 31.)* |
| 198 | |
| 199 | *(Lean in a little — this is the money shot)* |
| 200 | |
| 201 | Now we're going to manufacture a real conflict. Two branches are going to |
| 202 | modify the *same file* on the *same dimension*. This is where Muse shows |
| 203 | what makes it different. |
| 204 | |
| 205 | ### Steps 22–23 — Branch `conflict/left` |
| 206 | |
| 207 | `muse checkout -b conflict/left`. Commit: **"Left: introduce shared state |
| 208 | (version A)"**. |
| 209 | |
| 210 | This branch adds `shared-state.mid` and edits it with a **melodic** approach |
| 211 | and a **structural** change. |
| 212 | |
| 213 | ### Steps 24–26 — Branch `conflict/right` |
| 214 | |
| 215 | Back to main, then `muse checkout -b conflict/right`. Commit: **"Right: |
| 216 | introduce shared state (version B)"**. |
| 217 | |
| 218 | This branch adds its own version of `shared-state.mid` with a **harmonic** |
| 219 | approach and also a **structural** change. |
| 220 | |
| 221 | *(Point to dimension matrix — both conflict/left and conflict/right columns)* |
| 222 | |
| 223 | Look at the dimension matrix. Left touched melodic + structural. Right touched |
| 224 | harmonic + structural. **Structural appears on both sides.** That's the conflict. |
| 225 | |
| 226 | ### Steps 27–28 — Merge `conflict/left` |
| 227 | |
| 228 | Fast-forward. Clean. |
| 229 | |
| 230 | ### Step 29 — Merge `conflict/right` |
| 231 | |
| 232 | ``` |
| 233 | ❌ Merge conflict in 1 file(s): |
| 234 | CONFLICT (both modified): shared-state.mid |
| 235 | ``` |
| 236 | |
| 237 | Here it is. Now — in Git, you'd open the file, see angle-bracket markers, |
| 238 | and try to figure out what "their" version of a binary MIDI file even means. |
| 239 | Good luck. |
| 240 | |
| 241 | In Muse, the merge engine already knows *which dimensions* conflicted. |
| 242 | It ran `MidiPlugin.merge()` with `repo_root` set, which: |
| 243 | |
| 244 | 1. Loaded `.museattributes` to check for strategy rules |
| 245 | 2. Called `merge_midi_dimensions()` on `shared-state.mid` |
| 246 | 3. Extracted the five dimension slices from base, left, and right |
| 247 | 4. Compared them: melodic only changed on the left. Harmonic only changed on |
| 248 | the right. Structural changed on **both**. |
| 249 | 5. Auto-merged melodic from left. Auto-merged harmonic from right. |
| 250 | 6. Flagged structural as the one dimension that needs a human decision. |
| 251 | |
| 252 | *(Point to the red-bordered structural cell in the dimension matrix for that commit)* |
| 253 | |
| 254 | **One dimension conflicted. Four resolved automatically.** Git would have |
| 255 | thrown the entire file at you. |
| 256 | |
| 257 | ### Step 30 — Resolve and commit |
| 258 | |
| 259 | The human makes a decision on the structural dimension and commits: |
| 260 | `"Resolve: integrate shared-state (A+B reconciled)"`. |
| 261 | |
| 262 | Look at the dimension matrix for this commit — only **structural** lights up. |
| 263 | That's the exact scope of what was resolved. The merge result carries |
| 264 | `applied_strategies` and `dimension_reports` that document exactly which |
| 265 | dimension was manually resolved and which were auto-merged. |
| 266 | |
| 267 | ### Step 31 — `muse status` |
| 268 | |
| 269 | `Nothing to commit, working tree clean.` |
| 270 | |
| 271 | The conflict is history. Literally — it's in the DAG, attributed, auditable, |
| 272 | permanent. |
| 273 | |
| 274 | --- |
| 275 | |
| 276 | ## ACT 5 — Advanced Operations (Steps 32–41) |
| 277 | |
| 278 | *(Resume Play Tour — steps 32–41. Let it play to completion.)* |
| 279 | |
| 280 | The last act shows that Muse has the full surface area you'd expect from a |
| 281 | modern VCS. |
| 282 | |
| 283 | ### Steps 32–38 — The audition arc *(pause here and explain this slowly)* |
| 284 | |
| 285 | This sequence is subtle but it's one of the most important things Muse |
| 286 | demonstrates. Watch what happens. |
| 287 | |
| 288 | `muse cherry-pick` — we grab the *ascending melody* commit from the `gamma` |
| 289 | branch and replay it on top of `main`. This is an **audition**. We're not |
| 290 | merging gamma — we're borrowing one idea and trying it on. |
| 291 | |
| 292 | Notice: this cherry-pick has no structural connection to gamma in the DAG. |
| 293 | It's a content copy — a new commit with a new hash, parented to main's HEAD. |
| 294 | Gamma doesn't know it happened. The two commits are not linked by an edge. |
| 295 | |
| 296 | *(Brief pause — let the cherry-pick commit appear in the DAG)* |
| 297 | |
| 298 | `muse show` — we inspect what actually changed. `muse diff` — working tree |
| 299 | is clean. The idea is in. Now we listen. |
| 300 | |
| 301 | `muse stash`, `muse stash pop` — showing you can shelve unfinished work |
| 302 | mid-session without losing anything. Bread and butter. |
| 303 | |
| 304 | Now — `muse revert`. The ascending melody doesn't fit. We undo it. |
| 305 | |
| 306 | *(Point to the revert commit in the DAG — pause)* |
| 307 | |
| 308 | This is the moment. Look at what just happened in the DAG: there are now |
| 309 | **two** commits sitting between the resolve and the tag. One that says |
| 310 | "here's the melody." One that says "never mind." Both are permanent. Both |
| 311 | are in the history forever. |
| 312 | |
| 313 | That's not a mistake — that's the *point*. Six months from now, when someone |
| 314 | asks "did we ever try a melody in this section?" the answer is in the DAG: |
| 315 | yes, on this date, here's exactly what it was, and here's the explicit |
| 316 | decision to reject it. You can check it out, listen to it, and put it back |
| 317 | if you change your mind. |
| 318 | |
| 319 | The `descending melody B` commit on gamma? It's still there too — never |
| 320 | used, never merged, never deleted. Muse doesn't garbage-collect ideas. The |
| 321 | entire creative history of the project — including the roads not taken — is |
| 322 | preserved. |
| 323 | |
| 324 | *(Let that land before moving on)* |
| 325 | |
| 326 | ### Steps 39–40 — `muse tag add release:v1.0` / `muse tag list` |
| 327 | |
| 328 | Tag the final state. `release:v1.0`. Permanent named reference to this point |
| 329 | in history. |
| 330 | |
| 331 | ### Step 41 — `muse log --stat` |
| 332 | |
| 333 | Full log with file-level stats for every commit. The entire history of this |
| 334 | project — 14 commits, 6 branches, 1 real conflict, resolved — in one |
| 335 | scrollable view. |
| 336 | |
| 337 | *(Let the demo settle. Let it breathe for a second.)* |
| 338 | |
| 339 | --- |
| 340 | |
| 341 | ## DIMENSION MATRIX — Closing walkthrough (~60 s) |
| 342 | |
| 343 | *(Scroll down to the Dimension State Matrix. Let the audience take it in.)* |
| 344 | |
| 345 | This is the view I want to leave you with. |
| 346 | |
| 347 | Every column is a commit. Every row is a dimension. Every colored cell is |
| 348 | a dimension that changed in that commit. The red-bordered cell — that one |
| 349 | structural change — is the only moment in this entire session where a human |
| 350 | had to make a decision. |
| 351 | |
| 352 | *(Trace across the rows)* |
| 353 | |
| 354 | Look at the melodic row. It moves. It's active on alpha commits, on gamma |
| 355 | commits, on the cherry-pick, on the revert. A continuous creative thread. |
| 356 | |
| 357 | Look at the rhythmic row. It's its own thread. Beta's work. Completely |
| 358 | parallel. Never interfered with melody. |
| 359 | |
| 360 | Look at structural — it barely touches anything until the conflict commit. |
| 361 | Then it lights up on both sides at once. That's the red cell. That's the |
| 362 | conflict. One cell out of seventy. |
| 363 | |
| 364 | This is what multidimensional version control means. Not "track files better." |
| 365 | Track the *dimensions of your work* so that conflicts only happen when two |
| 366 | people genuinely disagree about the same thing — not because they happened |
| 367 | to edit the same file on the same day. |
| 368 | |
| 369 | --- |
| 370 | |
| 371 | ## ACT 6 — Typed Delta Algebra (Steps 42–46) |
| 372 | |
| 373 | *(New section — show terminal, not the HTML demo)* |
| 374 | |
| 375 | *(Camera on terminal. Switch to showing raw muse commands.)* |
| 376 | |
| 377 | I want to show you what's under the hood now — the new engine that powers |
| 378 | every operation you just saw. |
| 379 | |
| 380 | In v0.x, `muse show` gave you: `files modified: shared-state.mid`. That's it. |
| 381 | A filename. A black box. You had no idea what changed inside the file. |
| 382 | |
| 383 | ### Step 42 — `muse show` on a commit with note-level changes |
| 384 | |
| 385 | ``` |
| 386 | $ muse show HEAD |
| 387 | commit: a3f2c9... "Alpha: texture pattern B (dense)" |
| 388 | |
| 389 | patch shared-state.mid (melodic layer) |
| 390 | insert note C4 tick=480 vel=80 dur=240 + |
| 391 | insert note E4 tick=720 vel=64 dur=120 + |
| 392 | delete note G3 tick=240 vel=90 dur=480 - |
| 393 | |
| 394 | 3 operations: 2 added, 1 removed |
| 395 | ``` |
| 396 | |
| 397 | That's the **Typed Delta Algebra**. Every commit now carries a |
| 398 | `StructuredDelta` — a list of typed operations. Not "file changed." Note added |
| 399 | at tick 480 with velocity 80 and duration 240. That's the actual thing that |
| 400 | happened. |
| 401 | |
| 402 | *(Pause to let that sink in)* |
| 403 | |
| 404 | There are five operation types: |
| 405 | |
| 406 | - `InsertOp` — something was added (note, row, element) |
| 407 | - `DeleteOp` — something was removed |
| 408 | - `MoveOp` — something was repositioned |
| 409 | - `ReplaceOp` — something's value changed (has before/after content hashes) |
| 410 | - `PatchOp` — a container was internally modified (carries child ops) |
| 411 | |
| 412 | ### Step 43 — `muse diff` between two commits |
| 413 | |
| 414 | ``` |
| 415 | $ muse diff HEAD~2 HEAD |
| 416 | patch tracks/bass.mid (rhythmic layer) |
| 417 | insert note F2 tick=0 vel=100 dur=120 + |
| 418 | insert note F2 tick=480 vel=80 dur=120 + |
| 419 | replace note G2 tick=240 vel=90 dur=480 → vel=70 |
| 420 | |
| 421 | 2 added, 1 modified |
| 422 | ``` |
| 423 | |
| 424 | Every diff is now operation-level. You're not comparing binary blobs — |
| 425 | you're comparing structured semantic events. The merge engine works on these |
| 426 | typed operations. So does the conflict detector. |
| 427 | |
| 428 | ### Step 44 — `muse log --stat` |
| 429 | |
| 430 | The log now shows operation summaries inline: |
| 431 | |
| 432 | ``` |
| 433 | a3f2c9 Alpha: texture pattern B (dense) |
| 434 | 2 notes added, 1 note removed |
| 435 | cb4afa Alpha: texture pattern A (sparse) |
| 436 | 1 note added, 3 notes removed |
| 437 | ``` |
| 438 | |
| 439 | Every commit has a `summary` field — computed by the plugin at commit time, |
| 440 | stored for free display later. No re-scanning. No re-parsing. |
| 441 | |
| 442 | --- |
| 443 | |
| 444 | ## ACT 7 — Domain Schema & Diff Algorithms (Steps 47–51) |
| 445 | |
| 446 | *(Show `muse domains` output)* |
| 447 | |
| 448 | ### Step 47 — `muse domains` |
| 449 | |
| 450 | ``` |
| 451 | ╔════════════════════════════════════════════════════════════╗ |
| 452 | ║ Muse Domain Plugin Dashboard ║ |
| 453 | ╚════════════════════════════════════════════════════════════╝ |
| 454 | |
| 455 | Registered domains: 2 |
| 456 | ────────────────────────────────────────────────────────────── |
| 457 | |
| 458 | ● music ← active repo domain |
| 459 | Module: plugins/music/plugin.py |
| 460 | Capabilities: Typed Deltas · Domain Schema · OT Merge |
| 461 | Schema: v1 · top_level: set · merge_mode: three_way |
| 462 | Dimensions: melodic, harmonic, dynamic, structural |
| 463 | Description: MIDI and audio file versioning with note-level diff |
| 464 | |
| 465 | ○ scaffold |
| 466 | Module: plugins/scaffold/plugin.py |
| 467 | Capabilities: Typed Deltas · Domain Schema · OT Merge · CRDT |
| 468 | Schema: v1 · top_level: set · merge_mode: three_way |
| 469 | Dimensions: primary, metadata |
| 470 | Description: Scaffold domain — copy-paste this to build your own |
| 471 | |
| 472 | ────────────────────────────────────────────────────────────── |
| 473 | To scaffold a new domain: |
| 474 | muse domains --new <name> |
| 475 | ``` |
| 476 | |
| 477 | This is the **Domain Dashboard** — a live inventory of every registered domain |
| 478 | plugin, its capability level, and its declared schema. The `●` bullet marks |
| 479 | the domain of the current repository. The `○` is a template. |
| 480 | |
| 481 | ### Step 48 — What the schema does |
| 482 | |
| 483 | The `schema()` method is the **Domain Schema** capability. When a plugin declares its schema, the core |
| 484 | engine knows: |
| 485 | |
| 486 | - **Melodic dimension**: `sequence` of `note_event` elements → use Myers LCS diff |
| 487 | - **Harmonic dimension**: `sequence` of `chord_event` elements → use Myers LCS diff |
| 488 | - **Dynamic dimension**: `tensor` of float32 values → use epsilon-tolerant numerical diff |
| 489 | - **Structural dimension**: `tree` of track nodes → use Zhang-Shasha tree edit diff |
| 490 | |
| 491 | One schema declaration. Four different algorithms. The right algorithm for each |
| 492 | dimension, automatically. |
| 493 | |
| 494 | ### Step 49 — `muse domains --new genomics` |
| 495 | |
| 496 | ``` |
| 497 | $ muse domains --new genomics |
| 498 | ✅ Scaffolded new domain plugin: muse/plugins/genomics/ |
| 499 | Class name: GenomicsPlugin |
| 500 | |
| 501 | Next steps: |
| 502 | 1. Implement every NotImplementedError in muse/plugins/genomics/plugin.py |
| 503 | 2. Register the plugin in muse/plugins/registry.py |
| 504 | 3. muse init --domain genomics |
| 505 | 4. See docs/guide/plugin-authoring-guide.md for the full walkthrough |
| 506 | ``` |
| 507 | |
| 508 | That's it. Thirty seconds to scaffold a fully typed, full-capability domain |
| 509 | plugin for any structured data type you can imagine. Copy, fill in, register. |
| 510 | |
| 511 | *(Point to the scaffold file)* |
| 512 | |
| 513 | The scaffold is fully typed. Zero `Any`. Zero `object`. Zero `cast()`. It passes |
| 514 | `mypy --strict` out of the box. It's a copy-paste starting point, not a toy. |
| 515 | |
| 516 | --- |
| 517 | |
| 518 | ## ACT 8 — Operation-Level OT Merge (Steps 52–56) |
| 519 | |
| 520 | *(Back to the conflict scenario — two branches editing the same MIDI file)* |
| 521 | |
| 522 | Let me show you what happens when two musicians edit the same MIDI file at |
| 523 | the note level, concurrently. |
| 524 | |
| 525 | ### Step 50 — Two branches, same file, different notes |
| 526 | |
| 527 | ``` |
| 528 | Branch alpha-notes: inserts note C4 at tick 480 |
| 529 | Branch beta-notes: inserts note G4 at tick 960 |
| 530 | ``` |
| 531 | |
| 532 | Both branches modified `melody.mid`. In old Muse — file-level merge — this |
| 533 | would be a conflict. One file, both modified, done. |
| 534 | |
| 535 | In **OT Merge** — the engine asks: |
| 536 | |
| 537 | > Do these two operations commute? Can I apply them in either order and |
| 538 | > get the same result? |
| 539 | |
| 540 | ### Step 51 — `muse merge beta-notes` with operation-level merge |
| 541 | |
| 542 | ``` |
| 543 | $ muse merge beta-notes |
| 544 | ✅ Merged 'beta-notes' into 'alpha-notes' (clean) |
| 545 | 2 operations auto-merged: |
| 546 | insert note C4 tick=480 (from alpha-notes) |
| 547 | insert note G4 tick=960 (from beta-notes) |
| 548 | Conflicts: none |
| 549 | ``` |
| 550 | |
| 551 | Two insertions at different tick positions → they commute → auto-merged. |
| 552 | No human needed. The notes are in the same file. They're at different positions. |
| 553 | They don't interfere. |
| 554 | |
| 555 | ### Step 52 — When ops genuinely conflict |
| 556 | |
| 557 | ``` |
| 558 | Branch left: replace note C4 tick=480 vel=64 → vel=80 |
| 559 | Branch right: replace note C4 tick=480 vel=64 → vel=100 |
| 560 | ``` |
| 561 | |
| 562 | Now we have a real conflict: both branches changed the velocity of the *same |
| 563 | note* from the *same base value* to *different target values*. That's a |
| 564 | genuine disagreement. The engine flags it: |
| 565 | |
| 566 | ``` |
| 567 | $ muse merge right |
| 568 | ❌ Merge conflict: |
| 569 | CONFLICT (op-level): melody.mid note C4 tick=480 vel (64→80 vs 64→100) |
| 570 | ``` |
| 571 | |
| 572 | One note. One parameter. That's the minimal conflict unit. |
| 573 | |
| 574 | *(This is what "operation-level" means — the conflict detector understood |
| 575 | the internal structure of your file well enough to isolate the conflict to |
| 576 | a single note parameter.)* |
| 577 | |
| 578 | --- |
| 579 | |
| 580 | ## ACT 9 — CRDT Convergent Writes (Steps 57–61) |
| 581 | |
| 582 | *(Switch to CRDT scenario — many agents writing simultaneously)* |
| 583 | |
| 584 | Everything I've shown so far is for human-paced collaboration: commits once |
| 585 | an hour, a day, a week. Three-way merge is exactly right for that. |
| 586 | |
| 587 | But what if you have twenty automated agents writing simultaneously? What if |
| 588 | you're collecting telemetry from a distributed sensor network? What if your |
| 589 | domain is a set of annotations where a thousand researchers are contributing |
| 590 | concurrently? |
| 591 | |
| 592 | Three-way merge breaks down. You can't resolve 10,000 conflicts per second |
| 593 | with a human. |
| 594 | |
| 595 | ### Step 57 — CRDT mode: join always succeeds |
| 596 | |
| 597 | **CRDT Semantics** allow a plugin that implements `CRDTPlugin` to replace |
| 598 | `merge()` with `join()`. The join is a mathematical operation on a |
| 599 | **lattice** — a partial order where any two states have a unique least upper bound. |
| 600 | |
| 601 | The key property: **join always succeeds. No conflict state ever exists.** |
| 602 | |
| 603 | ### Step 58 — The six CRDT primitives |
| 604 | |
| 605 | ```python |
| 606 | from muse.core.crdts import ( |
| 607 | VectorClock, # causal ordering between agents |
| 608 | LWWRegister, # last-write-wins scalar |
| 609 | ORSet, # unordered set — adds always win |
| 610 | RGA, # ordered sequence — commutative insertion |
| 611 | AWMap, # key-value map — adds win |
| 612 | GCounter, # grow-only counter |
| 613 | ) |
| 614 | ``` |
| 615 | |
| 616 | Each one satisfies the three lattice laws: |
| 617 | |
| 618 | 1. `join(a, b) == join(b, a)` — order of messages doesn't matter |
| 619 | 2. `join(join(a, b), c) == join(a, join(b, c))` — batching is fine |
| 620 | 3. `join(a, a) == a` — duplicates are harmless |
| 621 | |
| 622 | These three laws are the mathematical guarantee that all replicas converge to |
| 623 | the same state — regardless of how late or how many times messages arrive. |
| 624 | |
| 625 | ### Step 59 — ORSet: adds always win |
| 626 | |
| 627 | ```python |
| 628 | # Agent A and Agent B write simultaneously: |
| 629 | s_a, tok_a = ORSet().add("annotation-GO:0001234") |
| 630 | s_b = ORSet().remove("annotation-GO:0001234") # B doesn't know about A's add |
| 631 | |
| 632 | # After join: |
| 633 | merged = s_a.join(s_b) |
| 634 | assert "annotation-GO:0001234" in merged.elements() # A's add survives |
| 635 | ``` |
| 636 | |
| 637 | This is the semantics for a genomics annotation set: concurrent adds win. |
| 638 | If you didn't know I added that annotation, your remove doesn't count. No |
| 639 | silent data loss. Ever. |
| 640 | |
| 641 | ### Step 60 — `muse merge` in CRDT mode |
| 642 | |
| 643 | ``` |
| 644 | $ muse merge agent-branch-1 (CRDT mode detected) |
| 645 | ✅ Joined 'agent-branch-1' into HEAD |
| 646 | CRDT join: 847ms |
| 647 | Labels joined: 3 adds merged |
| 648 | Sequence joined: RGA converged (12 elements) |
| 649 | Conflicts: none (CRDT join never conflicts) |
| 650 | ``` |
| 651 | |
| 652 | Joins never conflict. You can run `muse merge` on a thousand agent branches |
| 653 | and it always succeeds. The result is always the convergent state — the |
| 654 | least upper bound — of all writes. |
| 655 | |
| 656 | ### Step 61 — When to use CRDT vs. three-way |
| 657 | |
| 658 | This is the judgment call every plugin author makes: |
| 659 | |
| 660 | | Scenario | Right choice | |
| 661 | |----------|-------------| |
| 662 | | Human composer editing a MIDI score | Three-way merge (operation-level) | |
| 663 | | 100 agents annotating a genome | CRDT `ORSet` | |
| 664 | | DAW with multi-cursor note input | CRDT `RGA` | |
| 665 | | Distributed IoT telemetry counter | CRDT `GCounter` | |
| 666 | | Configuration parameter (one writer) | `LWWRegister` | |
| 667 | |
| 668 | CRDTs give up human arbitration in exchange for infinite scalability. Use them |
| 669 | when you have more concurrent writes than humans can handle. |
| 670 | |
| 671 | --- |
| 672 | |
| 673 | ## OUTRO — Muse v1.0 (~60 s) |
| 674 | |
| 675 | *(Back to camera or full screen)* |
| 676 | |
| 677 | So that's Muse v0.1.2. |
| 678 | |
| 679 | We started with the foundation — a domain-agnostic VCS where conflicts are |
| 680 | defined by dimension, not by file. That's still the core. But we've now built |
| 681 | four layers on top of it that progressively close the gap between "a VCS that |
| 682 | understands files" and "a VCS that understands your domain." |
| 683 | |
| 684 | **Typed Deltas**: Every operation is typed. Every commit carries a semantic |
| 685 | operation list. `muse show` tells you what changed inside the file, not just |
| 686 | which file. |
| 687 | |
| 688 | **Domain Schema**: Every domain declares its data structure. The diff engine |
| 689 | automatically selects the right algorithm — LCS for sequences, tree-edit for |
| 690 | hierarchies, epsilon-tolerant for tensors, set algebra for unordered collections. |
| 691 | |
| 692 | **OT Merge**: Merges happen at operation granularity. Two musicians editing |
| 693 | the same file at different positions don't conflict. The merge engine uses |
| 694 | Operational Transformation to compute the minimal, real conflict set. |
| 695 | |
| 696 | **CRDT Semantics**: For high-throughput multi-agent scenarios, CRDT semantics |
| 697 | replace merge with a mathematical join that always converges. No conflict state |
| 698 | ever exists. Hundreds of agents can write simultaneously. |
| 699 | |
| 700 | And all of this is accessible to any domain through a single six-method plugin |
| 701 | interface. Music is the proof. Genomics, climate simulation, 3D spatial design, |
| 702 | neural network checkpoints — any domain with structure can be versioned with Muse. |
| 703 | |
| 704 | `muse domains --new <your_domain>`. Thirty seconds to scaffold. Fill in the |
| 705 | methods. Register. Done. |
| 706 | |
| 707 | The code is on GitHub. The link is in the description. If you're building |
| 708 | something with structured state that deserves better version control — reach out. |
| 709 | |
| 710 | --- |
| 711 | |
| 712 | ## APPENDIX — Speaker Notes |
| 713 | |
| 714 | ### On questions you might get |
| 715 | |
| 716 | **"Why not just use Git with LFS?"** |
| 717 | Git LFS stores big files — it doesn't understand them. You still get binary |
| 718 | merge conflicts on the whole file. The dimension is the thing. |
| 719 | |
| 720 | **"What does 'domain-agnostic' actually mean?"** |
| 721 | The core engine — DAG, branches, object store, merge state machine — has |
| 722 | zero knowledge of music. It calls six methods on a plugin object. Swap the |
| 723 | plugin, get a different domain. The same commit graph, the same `muse merge`, |
| 724 | different semantics. |
| 725 | |
| 726 | **"What's the difference between OT Merge and CRDT Semantics?"** |
| 727 | OT assumes you have a base and can identify the common ancestor. It produces |
| 728 | a minimal conflict set when ops genuinely disagree. CRDT assumes there is no |
| 729 | shared base — every agent writes to their local replica and the join is |
| 730 | always clean. OT is right for human-paced editing; CRDT is right for |
| 731 | machine-speed concurrent writes. |
| 732 | |
| 733 | **"Is this production-ready?"** |
| 734 | v0.1.2 is solid: strict typing, 697 passing tests, CI, four semantic layers |
| 735 | fully implemented. Not production for a studio yet — but the architecture is |
| 736 | sound and the hard parts (content-addressed storage, OT, CRDT) are working. |
| 737 | |
| 738 | **"What about performance?"** |
| 739 | The original demo runs in 150ms for 14 commits and 41 operations. The CRDT |
| 740 | joins run in sub-millisecond. The bottleneck will be large files — handled |
| 741 | by chunked object storage in the roadmap. |
| 742 | |
| 743 | ### Suggested chapter markers for YouTube |
| 744 | |
| 745 | | Timestamp | Chapter | |
| 746 | |-----------|---------| |
| 747 | | 0:00 | Intro — what is multidimensional VCS? | |
| 748 | | 1:30 | The five musical dimensions | |
| 749 | | 3:00 | Act 1 — Foundation | |
| 750 | | 5:30 | Act 2 — Three branches diverge | |
| 751 | | 9:00 | Act 3 — Clean merges | |
| 752 | | 11:30 | Act 4 — The conflict (and why it's different) | |
| 753 | | 16:00 | Act 5 — Full VCS surface area | |
| 754 | | 18:30 | Dimension Matrix walkthrough | |
| 755 | | 20:00 | Act 6 — Typed Delta Algebra | |
| 756 | | 23:00 | Act 7 — Domain Schema & muse domains dashboard | |
| 757 | | 27:00 | Act 8 — Operation-level OT Merge | |
| 758 | | 31:00 | Act 9 — CRDT Convergent Writes | |
| 759 | | 36:00 | Outro — Muse v0.1.2 and what's next | |