Episode 05 --- The Six-Method Protocol
Working YouTube title:
Six Methods. Infinite Domains.
Thumbnail thought:
this is the whole interface.
Target runtime: ~7:30
[0:00--0:20] COLD OPEN
[CAMERA --- Episode 04's closing question, on screen for a beat: "what's actually left that Muse doesn't already know how to version?"]
GABRIEL:
Nothing, if the thing implements six methods.
[beat]
Let's see the actual interface.
[TITLE CARD --- fast]
THE SIX-METHOD PROTOCOL
[Music enters.]
[0:20--1:00] THE SIX NAMES, FOR REAL THIS TIME
[TERMINAL / SCREEN --- real source, not a slide]
class MuseDomainPlugin(Protocol):
def snapshot(self, live_state) -> StateSnapshot: ...
def diff(self, base, target) -> StateDelta: ...
def merge(self, base, left, right) -> MergeResult: ...
def drift(self, committed, live) -> DriftReport: ...
def apply(self, delta, live_state) -> LiveState: ...
def schema(self) -> DomainSchema: ...
GABRIEL VO:
Episode 00 named these six and moved on. That's the actual protocol class, straight from the source.
[CAMERA]
Implement these six. Muse gives you the DAG, branching, checkout, lineage, log, merge-base finding --- all of it --- for free.
[1:00--1:40] SNAPSHOT --- WHAT EXISTS RIGHT NOW
[SCREEN --- callback to Episode 02's read-snapshot manifest]
GABRIEL:
snapshot turns live state --- your actual files, your actual MIDI
track, whatever's really there --- into something hashable.
[beat]
We've already seen its output, twice. Episode 02's manifest, Episode
03's content-addressed snapshot ID. That output is what snapshot
produces. It's not a new concept --- it's the method behind two
episodes of concepts we already trust.
[1:40--2:25] SCHEMA --- DECLARE YOUR SHAPE
[TERMINAL]
$ muse domain-info --domain code
[SCREEN --- real source, the actual method body]
def schema(self) -> DomainSchema:
return DomainSchema(
domain="timeline",
top_level=TreeSchema(kind="tree", node_type="timeline_element"),
dimensions=[
DimensionSpec(name="structure", schema=TreeSchema(...)),
DimensionSpec(name="clips", schema=SequenceSchema(...)),
],
)
GABRIEL VO:
That's the timeline domain, by the way. Video editing.
[beat]
schema is the plugin telling Muse, once, up front: here's the shape
of my state. A tree here, a sequence there. Muse uses this declaration
to pick diff algorithms and drive merge conflict detection --- before a
single byte of actual content shows up.
[2:25--3:10] DIFF --- WHAT CHANGED, IN YOUR OWN TERMS
[SCREEN --- callback to Episode 03's structured_delta JSON]
GABRIEL:
diff takes two snapshots and returns typed operations, not text
lines.
[beat]
We saw this too --- "1 symbol added," an insert op with a real address and a real content ID. Every domain gets to define what an "operation" even means for its own state. Code gets symbol inserts. MIDI gets note moves. A CAD domain might get vertex displacements.
[CAMERA]
Muse doesn't interpret any of that. It just stores whatever typed ops the domain hands back.
[3:10--3:45] DRIFT --- WHAT CHANGED SINCE THE LAST COMMIT
[TERMINAL]
$ muse status
GABRIEL VO:
drift is diff's quieter sibling. Not "what changed between two
commits" --- "what changed between the last commit and whatever's on
disk right now."
[beat]
Every muse status you've watched run across this entire series was
one call to this method.
[3:45--4:25] APPLY --- REBUILDING STATE
[TERMINAL]
$ muse checkout gabriel-tempo
GABRIEL:
apply runs a delta forward, onto some live state, to produce a new
live state.
[beat]
That's the entire mechanism behind checkout. Walk back to some snapshot, then replay deltas forward until you're standing in the state that branch actually describes. No special-casing per domain --- the domain just has to know how to apply its own kind of operation.
[4:25--5:10] MERGE --- THE HARD ONE
[SCREEN --- callback to Episode 01's clean two-branch merge]
GABRIEL VO:
merge takes a common ancestor and two divergent snapshots, and tries
to reconcile them.
[beat]
This is the one method with real optional depth. Some domains --- code is one --- implement an extra sub-protocol for operation-level merge, so two edits at different addresses never even look like a conflict. Some domains implement a completely different sub-protocol --- CRDT join --- where conflicts structurally can't happen at all.
[CAMERA]
Both of those are entire future episodes. For now: every domain gets at least the baseline three-way merge, for free, just by implementing this one method honestly.
[5:10--6:00] SAME SIX METHODS, WILDLY DIFFERENT SHAPES
[TERMINAL --- side by side]
$ muse domain-info --domain code
dimensions: structure, symbols, imports, variables, metadata
(5 dimensions)
$ muse domain-info --domain midi
dimensions: notes, pitch_bend, cc_volume, tempo_map,
key_signatures, track_structure, ... (21 dimensions)
GABRIEL:
Same six method names. Same protocol class. Five dimensions on one side, twenty-one on the other.
[beat]
Neither plugin knows the other exists. Neither one had to. Muse's engine --- the DAG, the branching, the merge base finder --- doesn't care that one of these is source code and the other is music. It only ever talks to six methods.
[6:00--6:40] THE POINT
[CAMERA]
Go back to Episode 00's infinity symbol.
[beat]
It wasn't a slogan. It's a direct consequence of this interface being narrow enough that almost anything with structured state that changes over time can implement it.
[ON SCREEN]
SIX METHODS. THE ENGINE NEVER NEEDS A SEVENTH REASON TO CARE WHAT YOUR DATA IS.
[6:40--7:15] OUT
[TERMINAL --- empty directory, cursor blinking]
GABRIEL VO:
Six method names and a protocol class are easy to nod along to.
[beat]
Next episode we stop nodding. We're going to implement one of these,
from an empty file, live --- something that doesn't exist as a Muse
domain yet --- and watch muse commit, muse diff, and muse merge
just work on it the moment the six methods are filled in.
[CAMERA.]
Bring a domain. We'll build it.
[CUT TO BLACK]
musehub.ai
Production Notes
Episode 05 is the season's hinge point --- everything before it established trust in the engine; everything after it explores what the engine enables. The risk is that six method names in a row reads as a dry API tour. The guardrail: every method gets tied to something the viewer has already watched happen in a previous episode before its formal definition is given.
Opening
Answer Episode 04's closing question immediately and literally, then
go straight to the real Protocol class source. Resist any urge to
build up to it with a preamble --- the whole point of this episode is
that the answer is small enough to put on screen in the first minute.
Every Method Needs a Callback, Not Just a Definition
Snapshot → Episode 02's manifest. Diff → Episode 03's structured
delta. Merge → Episode 01's clean two-branch merge. Drift → every
muse status in the series. Apply → checkout, which the viewer has
now seen run half a dozen times without ever being told what powers
it. Schema → the domain-info calls from Episode 02. Landing each
method on a memory the viewer already has is what keeps this from
feeling like documentation.
The Timeline Snippet Is a Deliberate Wink
Using the video-editing domain's real schema() method as the code
example --- in a show that is itself being edited on a timeline --- is
intentional. Don't explain the joke. Let anyone who notices, notice.
Don't Resolve Merge's Depth Here
The AddressedMergePlugin and CRDTPlugin sub-protocols are mentioned by
name and immediately deferred. This episode's job is to establish that
merge() is a real method with a real baseline guarantee --- not to
teach operation-level merge or CRDT convergence. Those are Episodes 08
and 12, and rushing them here would flatten both future episodes.
The Seed
The viewer arrives thinking:
Okay, six methods, sounds reasonable, but is that actually a complete protocol, or is there some asterisk?
They should leave thinking:
Wait --- if it's really just six methods... could I write one of these?
That's Episode 06, and it should open with exactly that dare answered: yes, right now, from nothing.