# 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\]** ``` python 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\]** ``` text $ muse domain-info --domain code ``` **\[SCREEN --- real source, the actual method body\]** ``` python 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\]** ``` text $ 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\]** ``` text $ 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\]** ``` text $ 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.