Episode 08 --- The Merge Engine
Working YouTube title:
What Actually Happens Underneath a Merge
Thumbnail thought:
the conflict knows exactly where it lives.
Target runtime: ~7:45
[0:00--0:20] COLD OPEN
[CAMERA --- Episode 07's closing question, on screen: "how much of merge does the diff get for free?"]
GABRIEL:
A lot of it. Let's open the engine up and see exactly how much.
[TITLE CARD --- fast]
THE MERGE ENGINE
[Music enters.]
[0:20--1:00] FINDING THE STARTING LINE
[TERMINAL]
$ muse merge-base feature/alice feature/bob
{ "merge_base": "sha256:6ae5e2..." }
GABRIEL VO:
Before Muse can merge anything, it has to answer one question: where did these two branches actually split apart?
[beat]
That common ancestor is the base every three-way merge measures against. Get this wrong, and everything downstream is wrong with it.
[1:00--1:40] THE EASY CASE, NAMED PROPERLY
[SCREEN --- callback to Episode 01's clean merge]
GABRIEL:
We've watched this succeed twice already --- Episode 01's two branches, Episode 06's todo list.
[beat]
Here's what was actually happening both times: Muse diffs base against ours, diffs base against theirs, and reasons about the two operation lists directly. Different addresses, no shared ground, nothing to argue about. That's the whole trick behind every clean merge this season.
[1:40--2:20] DRY RUN FIRST, ALWAYS
[TERMINAL]
$ muse merge --dry-run feature/bob
{ "status": "conflict", "conflicts": ["calc.py::add"] }
[cat calc.py --- unchanged, no markers]
GABRIEL VO:
Predicted, before a single byte on disk moved. That's not a convenience feature. That's the same computation the real merge is about to do, just stopping short of writing the result.
[2:20--3:10] A REAL CONFLICT
[TERMINAL --- for real this time, no --dry-run]
$ muse merge feature/bob
[SCREEN --- real conflict markers]
def add(a, b):
<<<<<<< main [modified]
return a + b + 1
||||||| base
return a + b
======= feature/bob [modified]
return a + b + 100
>>>>>>> end conflict
GABRIEL:
Alice and Bob both fixed the exact same function, differently. This one's a real conflict. There's no clever address-keying trick that gets you out of two people disagreeing about the same line of logic.
[3:10--3:50] NOTICE WHAT'S NOT IN CONFLICT
[TERMINAL]
$ muse conflicts
{ "conflicts": [{ "path": "calc.py::add", "symbol": "add", "kind": "symbol" }] }
GABRIEL VO:
kind: symbol. Not kind: file.
[beat]
If calc.py had a second function neither of them touched, it would
sail through untouched, in the same merge, at the same time. The
conflict is scoped to exactly the thing that's actually contested ---
nothing wider.
[3:50--4:30] RESOLVING IT
[TERMINAL]
$ echo 'def add(a, b):
return a + b + 101' > calc.py
$ muse resolve calc.py::add
$ muse commit -m "merge: resolve add conflict"
GABRIEL:
Read both sides, decide what's actually correct, write it, mark it resolved, commit. No magic in the resolution itself --- a human still has to decide 101 is the right answer here.
[beat]
The magic was never in resolving conflicts. It's in not manufacturing fake ones.
[4:30--5:15] WHAT'S ACTUALLY RUNNING UNDER merge
[SCREEN --- the real dispatch, simplified]
if isinstance(plugin, AddressedMergePlugin):
ours_delta = plugin.diff(base, ours, repo_root=repo_root)
theirs_delta = plugin.diff(base, theirs, repo_root=repo_root)
result = plugin.merge_ops(
base, ours, theirs,
ours_delta["ops"], theirs_delta["ops"],
)
GABRIEL VO:
Two calls to the exact same diff() method from Episode 07. Then one
call to merge_ops(), which walks both operation lists and asks a
single question per address: did only one side touch this, or did
both?
[beat]
Only-one-side wins automatically. Both-sides-different-results is the only thing that becomes a conflict --- and it becomes a conflict at that address specifically, not at the file, not at the repo.
[5:15--5:50] EVERY DOMAIN GETS THIS SHAPE
[CAMERA]
Nothing here is code-specific. Any domain that implements the
optional AddressedMergePlugin extension from Episode 05 gets this
exact reasoning --- diff twice, compare op lists, conflict only where
both sides genuinely collide.
[beat]
Domains that don't implement it still get a real three-way merge --- just at whole-file granularity, the way Git always has. The address- keyed version is strictly better when a domain can support it.
[5:50--6:25] THE POINT
[CAMERA]
A merge conflict isn't a failure of the tool. It's supposed to be rare, and it's supposed to be precise when it happens.
[ON SCREEN]
A CONFLICT AT THE RIGHT ADDRESS IS A FEATURE. A CONFLICT AT THE WRONG ADDRESS IS A BUG WEARING A CONFLICT'S CLOTHES.
[6:25--7:00] OUT
[TERMINAL --- the conflict markers from earlier, one more time]
GABRIEL VO:
muse resolve handled this conflict because a human was here to
decide. What happens when nobody's watching --- when it's two agents,
merging independently, and neither can just ask the other what they
meant?
[beat]
Next episode: Harmony. Muse's answer to conflicts that can't wait for a human.
[CAMERA.]
[CUT TO BLACK]
musehub.ai
Production Notes
Episode 08 is the season's most mechanically dense episode so far, and
the temptation will be to explain the merge algorithm in full. Resist
it. The episode needs exactly one real conflict, cleanly scoped, and
one clear sentence about what runs underneath --- not a walkthrough of
merge_engine.py.
Opening
Answer Episode 07's question directly, then go straight to
merge-base. No re-explanation of what a three-way merge is in
general terms --- the audience has already watched three clean merges
happen on screen across the season; this episode is about what's
underneath those, not reintroducing the concept.
The Conflict Must Be Genuine
Unlike the false conflict discovered while researching this episode
(two branches each adding a trailing comment to different functions
in the same file — filed as staging#92, not used on screen), the
calc.py::add conflict shown here is a real, correct, symbol-scoped
conflict: both branches genuinely changed the same function's logic
differently. Don't substitute a contrived or unstable example --- this
one was verified for real, multiple times, before scripting.
Say the Quiet Part Out Loud: Scoping Is the Feature
The "notice what's not in conflict" beat is the actual thesis of the episode, more than the conflict itself. A viewer who's used Git has plenty of experience with conflicts; what they haven't experienced is a conflict that's provably scoped to only the contested symbol. Give that beat room to land.
Don't Introduce Harmony Yet
muse resolve here is manual, deliberate, human-driven --- exactly as
primitive as Git's own conflict resolution. That's intentional
contrast-setting for Episode 09, not a gap to patch. Resist explaining
anything about automatic or policy-based resolution in this episode.
The Seed
The viewer arrives thinking:
Okay, symbol-scoped conflicts, that's a nice improvement over Git's file-level conflicts. Still just a conflict though.
They should leave thinking:
What if nobody's around to run
muse resolve? Two agents can't exactly have a conversation about whose fix is right.
That's Episode 09, and it should open by taking that scenario completely seriously.