gabriel / musehub public
docs_muse_merge.html html
806 lines 41.7 KB
Raw
sha256:42bc547653458bb15e283222247af0237872d9cb5c2a72ad2ca1c111ed2c0ca4 feat(9A-4 F7): overseer-run provenance enrichment API for S… Human minor ⚠ breaking 76 days ago
1 {% extends "musehub/base.html" %}
2
3 {% block container_extra_class %} page-container{% endblock %}
4 {% block body_class %}app-shell{% endblock %}
5 {% block title %}Merge Engine — Muse Developer Docs{% endblock %}
6 {% block page_json %}{"page":"docs-merge"}{% endblock %}
7
8 {% block content %}
9 <div class="devdocs">
10 <div class="devdocs-layout">
11
12 {# ── Sidebar ─────────────────────────────────────────────────────────────── #}
13 <aside class="devdocs-sidebar">
14 <nav class="devdocs-nav" aria-label="Docs navigation">
15 <div class="devdocs-nav-group">
16 <div class="devdocs-nav-group-label">Sections</div>
17 {% for slug, num, title, desc in phases %}
18 <a class="devdocs-nav-link devdocs-nav-link--phase{% if slug == current %} devdocs-nav-link--active{% endif %}"
19 href="/muse/{{ slug }}">{{ num }} {{ title }}</a>
20 {% endfor %}
21 </div>
22 <div class="devdocs-nav-group">
23 <div class="devdocs-nav-group-label">On this page</div>
24 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#overview">Overview</a>
25 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#granularity">Three altitudes</a>
26 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#engine-model">Engine model</a>
27 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#strategy">Strategy reference</a>
28 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#history">History modes</a>
29 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#on-conflict">--on-conflict</a>
30 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#explain">--explain</a>
31 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#local-merge">muse merge</a>
32 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#proposal-merge">Proposal merge</a>
33 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#safe-protocol">Safe merge protocol</a>
34 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#harmony">Harmony integration</a>
35 <a class="devdocs-nav-link devdocs-nav-link--sub" href="#cli">CLI reference</a>
36 </div>
37 </nav>
38 </aside>
39
40 {# ── Main content ─────────────────────────────────────────────────────────── #}
41 <main class="devdocs-content" id="main-content">
42
43 <div class="devdocs-breadcrumb">
44 <a href="/muse">Developer Docs</a>
45 <span>›</span>
46 <span>Merge Engine</span>
47 </div>
48
49 <div class="devdocs-phase-header">
50 <span class="devdocs-phase-num">PHASE 05</span>
51 <h1 class="devdocs-phase-title">Merge Engine</h1>
52 <p class="devdocs-phase-desc">
53 Muse merges at three altitudes — directory, file, and symbol — and resolves
54 conflicts at the right level for each one. Where Git applies a single line-level
55 diff to every file, Muse applies the merge algorithm that matches the content:
56 recursive three-way merge for code, overlay for config, snapshot for binary
57 domains, or replay for time-series data. The strategy, history mode, and
58 conflict fallback are all independently configurable per merge. Harmony sits
59 underneath, learning from every resolved conflict so future merges need less
60 human intervention.
61 </p>
62 </div>
63
64 <div class="devdocs-callout">
65 {{ icon("info", 16, "devdocs-callout-icon") }}
66 <div>
67 <strong>Merge ≠ conflict.</strong> Most Muse merges complete without conflicts.
68 The three-level model means that changes to different symbols in the same file —
69 the most common parallel-work pattern — are auto-merged without a conflict marker.
70 </div>
71 </div>
72
73 {# ── Overview ──────────────────────────────────────────────────────────── #}
74 <section class="devdocs-section" id="overview">
75 <h2>Overview</h2>
76 <p>
77 Git merges are line-level: two edits to different lines of the same function are
78 "no conflict" even if they produce broken code together. Two edits to the
79 <em>same line</em> always conflict even if they touch different semantic units.
80 </p>
81 <p>
82 Muse flips this: the unit of merging is the <strong>symbol</strong> — a function,
83 class, variable, or domain-defined atom. Two agents editing different symbols in
84 the same file never conflict. Two agents editing the same symbol always produce an
85 inspectable three-way diff at the symbol level, not at an arbitrary line boundary.
86 </p>
87 <p>
88 The practical effect: teams working on the same file in parallel see far fewer
89 spurious conflicts, and when a real conflict does occur, the diff is semantically
90 meaningful — it shows exactly which function changed and why, not which line number
91 happened to collide.
92 </p>
93 </section>
94
95 {# ── Three altitudes ───────────────────────────────────────────────────── #}
96 <section class="devdocs-section" id="granularity">
97 <h2>Three altitudes</h2>
98 <p>
99 The merge engine descends from coarse to fine, stopping at the level where the
100 content is cleanly separable.
101 </p>
102
103 <table class="devdocs-table">
104 <thead><tr><th>Altitude</th><th>Unit</th><th>When it fires</th><th>Conflict address example</th></tr></thead>
105 <tbody>
106 <tr>
107 <td><strong>Directory</strong></td>
108 <td>A directory subtree</td>
109 <td>One branch adds a directory the other deletes, or two branches diverge on the same directory with overlapping paths</td>
110 <td><code>src/auth/</code></td>
111 </tr>
112 <tr>
113 <td><strong>File</strong></td>
114 <td>A whole file</td>
115 <td>Binary files, files the domain treats as atomic (e.g. <code>.mid</code>, lock files), or files where both branches made changes the domain cannot split into symbols</td>
116 <td><code>src/config.json</code></td>
117 </tr>
118 <tr>
119 <td><strong>Symbol</strong></td>
120 <td>A function, class, variable, or domain atom</td>
121 <td>Code domain, identity domain, or any domain implementing <code>diff_symbols()</code>; two edits to the <em>same</em> symbol are a conflict; two edits to <em>different</em> symbols in the same file are auto-merged</td>
122 <td><code>src/auth/tokens.py::validate_token</code></td>
123 </tr>
124 </tbody>
125 </table>
126
127 <div class="devdocs-callout">
128 {{ icon("info", 16, "devdocs-callout-icon") }}
129 <div>
130 A conflict address like <code>src/auth/tokens.py::validate_token</code> uniquely
131 identifies the exact symbol in conflict. <code>muse conflicts --json</code> returns
132 the full list after any merge that does not complete cleanly.
133 </div>
134 </div>
135
136 <div class="devdocs-code-block">
137 <div class="devdocs-code-header">
138 <span class="devdocs-code-lang">bash</span>
139 <span class="devdocs-code-label">list conflict addresses after a partial merge</span>
140 </div>
141 <pre><code>muse conflicts --json</code></pre>
142 </div>
143 <div class="devdocs-code-block devdocs-code-block--output">
144 <div class="devdocs-code-header">
145 <span class="devdocs-code-lang">json</span>
146 <span class="devdocs-code-label">output</span>
147 </div>
148 <pre><code>[
149 { <span class="tok-key">"path"</span>: <span class="tok-str">"src/auth/tokens.py::validate_token"</span>, <span class="tok-key">"kind"</span>: <span class="tok-str">"symbol"</span> },
150 { <span class="tok-key">"path"</span>: <span class="tok-str">"pyproject.toml"</span>, <span class="tok-key">"kind"</span>: <span class="tok-str">"file"</span> }
151 ]</code></pre>
152 </div>
153 </section>
154
155 {# ── Engine model ──────────────────────────────────────────────────────── #}
156 <section class="devdocs-section" id="engine-model">
157 <h2>Engine model</h2>
158 <p>
159 Every merge is parameterised by two independent dimensions: the
160 <strong>diff unit</strong> (how the engine splits content into comparable atoms)
161 and the <strong>resolution policy</strong> (what the engine does when those atoms
162 diverge). Named strategies are shorthand for specific combinations of these two
163 dimensions.
164 </p>
165
166 <table class="devdocs-table">
167 <thead>
168 <tr>
169 <th>Named strategy</th>
170 <th>Diff unit</th>
171 <th>Resolution policy</th>
172 <th>Typical use</th>
173 </tr>
174 </thead>
175 <tbody>
176 <tr>
177 <td><code>recursive</code></td>
178 <td>Symbol (code domain) or line (text fallback)</td>
179 <td>Three-way merge; conflict on divergent edits to the same atom</td>
180 <td>Source code, structured text</td>
181 </tr>
182 <tr>
183 <td><code>overlay</code></td>
184 <td>Key (for maps) or element (for sequences)</td>
185 <td>Ours wins on key collision; additions from both sides kept</td>
186 <td>Config files, package manifests</td>
187 </tr>
188 <tr>
189 <td><code>snapshot</code></td>
190 <td>Whole file (atomic)</td>
191 <td>Conflict if both branches modified the file; no sub-file merge attempted</td>
192 <td>Binary blobs, MIDI, images</td>
193 </tr>
194 <tr>
195 <td><code>replay</code></td>
196 <td>Domain-defined event (e.g. note, frame, row)</td>
197 <td>Events replayed in causal order; duplicates suppressed</td>
198 <td>Event-sourced domains, time-series</td>
199 </tr>
200 <tr>
201 <td><code>ours</code></td>
202 <td>Whole file</td>
203 <td>Always adopt ours; incoming branch changes discarded on conflict</td>
204 <td>Generated files, lock files (use with a Harmony policy instead)</td>
205 </tr>
206 <tr>
207 <td><code>theirs</code></td>
208 <td>Whole file</td>
209 <td>Always adopt theirs; local branch changes discarded on conflict</td>
210 <td>Vendor files that must match upstream exactly</td>
211 </tr>
212 </tbody>
213 </table>
214
215 <div class="devdocs-callout">
216 {{ icon("warn", 16, "devdocs-callout-icon") }}
217 <div>
218 <strong><code>ours</code> and <code>theirs</code> silently discard work.</strong>
219 Prefer a Harmony policy (<code>muse harmony policy-add --action prefer-ours
220 --path-pattern "*.lock"</code>) so the decision is recorded, auditable, and
221 automatically applied on future merges. Use <code>ours</code>/<code>theirs</code>
222 as a strategy only when you have confirmed that one side is entirely superseded.
223 </div>
224 </div>
225 </section>
226
227 {# ── Strategy reference ────────────────────────────────────────────────── #}
228 <section class="devdocs-section" id="strategy">
229 <h2>Strategy reference</h2>
230 <p>
231 Pass <code>--strategy</code> to <code>muse merge</code> or
232 <code>muse hub proposal merge</code>. The default is <code>recursive</code>.
233 </p>
234
235 <div class="devdocs-code-block">
236 <pre><span class="tok-cmt"># recursive — default; symbol-level three-way merge for code</span>
237 <span class="tok-fn">muse</span> merge feat/auth
238
239 <span class="tok-cmt"># overlay — take additions from both sides; ours wins on key collision</span>
240 <span class="tok-fn">muse</span> merge feat/config <span class="tok-kw">--strategy</span> overlay
241
242 <span class="tok-cmt"># snapshot — atomic file merge; conflicts if both sides touched the file</span>
243 <span class="tok-fn">muse</span> merge feat/audio <span class="tok-kw">--strategy</span> snapshot
244
245 <span class="tok-cmt"># replay — causal event ordering; domain must implement replay semantics</span>
246 <span class="tok-fn">muse</span> merge feat/events <span class="tok-kw">--strategy</span> replay
247
248 <span class="tok-cmt"># ours — always take our version on conflict (⚠ discards incoming work)</span>
249 <span class="tok-fn">muse</span> merge feat/generated <span class="tok-kw">--strategy</span> ours
250
251 <span class="tok-cmt"># theirs — always take their version on conflict (⚠ discards local work)</span>
252 <span class="tok-fn">muse</span> merge upstream/vendor <span class="tok-kw">--strategy</span> theirs</pre>
253 </div>
254
255 <h3 class="devdocs-subsection-title"><a href="#strategy-dry-run">Dry-run before committing</a></h3>
256 <p>
257 Always switch to the target branch first. <code>muse merge --dry-run</code>
258 returns the merge plan without touching the working tree or MERGE_STATE.
259 </p>
260
261 <div class="devdocs-code-block">
262 <pre><span class="tok-fn">muse</span> switch dev
263 <span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--dry-run</span> <span class="tok-kw">--json</span></pre>
264 </div>
265 <div class="devdocs-code-block devdocs-code-block--output">
266 <div class="devdocs-code-header">
267 <span class="devdocs-code-lang">json</span>
268 <span class="devdocs-code-label">dry-run output (fast-forward)</span>
269 </div>
270 <pre><code>{
271 <span class="tok-key">"merge_type"</span>: <span class="tok-str">"fast_forward"</span>,
272 <span class="tok-key">"fast_forward"</span>: <span class="tok-kw">true</span>,
273 <span class="tok-key">"conflicts"</span>: [],
274 <span class="tok-key">"files_added"</span>: <span class="tok-num">3</span>,
275 <span class="tok-key">"files_modified"</span>: <span class="tok-num">7</span>,
276 <span class="tok-key">"files_removed"</span>: <span class="tok-num">0</span>,
277 <span class="tok-key">"commits_to_merge"</span>: <span class="tok-num">12</span>
278 }</code></pre>
279 </div>
280 </section>
281
282 {# ── History modes ─────────────────────────────────────────────────────── #}
283 <section class="devdocs-section" id="history">
284 <h2>History modes</h2>
285 <p>
286 <code>--history</code> controls the shape of the commit graph after a successful
287 merge. This is independent of the conflict resolution strategy.
288 </p>
289
290 <table class="devdocs-table">
291 <thead>
292 <tr>
293 <th>Mode</th>
294 <th>Graph shape</th>
295 <th>Harmony effect</th>
296 <th>When to use</th>
297 </tr>
298 </thead>
299 <tbody>
300 <tr>
301 <td><code>merge</code> (default)</td>
302 <td>Two-parent merge commit; full feature branch history preserved</td>
303 <td>All conflict resolutions from the branch are learned individually</td>
304 <td>Long-lived features, shared work — preserve full attribution</td>
305 </tr>
306 <tr>
307 <td><code>squash</code></td>
308 <td>Single commit on target branch; feature branch commits collapsed</td>
309 <td>One resolution record per conflict path (the squash commit)</td>
310 <td>Cleanup before merging experimental branches</td>
311 </tr>
312 <tr>
313 <td><code>rebase</code></td>
314 <td>Feature branch commits replayed linearly on top of target</td>
315 <td>Each replayed commit can generate independent Harmony records</td>
316 <td>Linear history preference; CI pipelines that require no merge commits</td>
317 </tr>
318 </tbody>
319 </table>
320
321 <div class="devdocs-code-block">
322 <pre><span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--history</span> merge <span class="tok-cmt"># default</span>
323 <span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--history</span> squash <span class="tok-cmt"># collapse to one commit</span>
324 <span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--history</span> rebase <span class="tok-cmt"># replay commits linearly</span></pre>
325 </div>
326
327 <div class="devdocs-callout">
328 {{ icon("info", 16, "devdocs-callout-icon") }}
329 <div>
330 <strong>Harmony learns from all three modes.</strong> Whether you use merge,
331 squash, or rebase, Harmony records conflict resolutions from the resulting
332 commit(s). The key difference is attribution granularity: <code>merge</code>
333 preserves the full per-commit resolution history; <code>squash</code> collapses
334 it to one record per conflict path.
335 </div>
336 </div>
337 </section>
338
339 {# ── --on-conflict ─────────────────────────────────────────────────────── #}
340 <section class="devdocs-section" id="on-conflict">
341 <h2>The <code>--on-conflict</code> flag</h2>
342 <p>
343 <code>--on-conflict</code> is the conflict <em>fallback</em> policy — what the engine
344 does when a conflict cannot be auto-resolved by Harmony and requires a decision.
345 It does not replace Harmony; it fires only when Harmony has nothing to offer.
346 </p>
347
348 <table class="devdocs-table">
349 <thead><tr><th>Value</th><th>Behaviour</th><th>When to use</th></tr></thead>
350 <tbody>
351 <tr>
352 <td><code>escalate</code> (default)</td>
353 <td>Merge pauses at the conflict. Working tree contains conflict markers. <code>muse conflicts --json</code> lists what needs manual resolution.</td>
354 <td>Always, unless you have a specific automated pipeline reason to use the others</td>
355 </tr>
356 <tr>
357 <td><code>ours</code></td>
358 <td>Automatically adopt our version for all unresolved conflicts. Merge completes without pausing.</td>
359 <td>Automated pipelines where incoming changes must never override ours (e.g. merging back from a deploy branch)</td>
360 </tr>
361 <tr>
362 <td><code>theirs</code></td>
363 <td>Automatically adopt their version for all unresolved conflicts. Merge completes without pausing.</td>
364 <td>Automated pipelines where incoming changes always take precedence (e.g. syncing a vendor mirror)</td>
365 </tr>
366 </tbody>
367 </table>
368
369 <div class="devdocs-code-block">
370 <pre><span class="tok-cmt"># default — pause for human inspection</span>
371 <span class="tok-fn">muse</span> merge feat/auth
372
373 <span class="tok-cmt"># CI pipeline — take ours for unresolved conflicts, never block</span>
374 <span class="tok-fn">muse</span> merge deploy/rc12 <span class="tok-kw">--on-conflict</span> ours
375
376 <span class="tok-cmt"># vendor sync — take theirs for everything unresolved</span>
377 <span class="tok-fn">muse</span> merge upstream/vendor <span class="tok-kw">--strategy</span> snapshot <span class="tok-kw">--on-conflict</span> theirs</pre>
378 </div>
379
380 <div class="devdocs-callout">
381 {{ icon("warn", 16, "devdocs-callout-icon") }}
382 <div>
383 <code>--on-conflict ours</code> and <code>--on-conflict theirs</code> silently
384 discard work. The defaults (<code>escalate</code>) are safe — they pause the merge
385 and let you inspect. Only use the non-default values in fully automated pipelines
386 where you have already audited what will be discarded.
387 </div>
388 </div>
389 </section>
390
391 {# ── --explain ─────────────────────────────────────────────────────────── #}
392 <section class="devdocs-section" id="explain">
393 <h2>The <code>--explain</code> flag</h2>
394 <p>
395 <code>muse merge --explain</code> returns a per-path decision trace showing exactly
396 why each file was merged the way it was — which strategy fired, which Harmony tier
397 (if any) resolved it automatically, and what the outcome was.
398 </p>
399
400 <div class="devdocs-code-block">
401 <div class="devdocs-code-header">
402 <span class="devdocs-code-lang">bash</span>
403 <span class="devdocs-code-label">merge with full decision trace</span>
404 </div>
405 <pre><code>muse merge feat/auth --explain --json</code></pre>
406 </div>
407 <div class="devdocs-code-block devdocs-code-block--output">
408 <div class="devdocs-code-header">
409 <span class="devdocs-code-lang">json</span>
410 <span class="devdocs-code-label">output — per-path decision trace</span>
411 </div>
412 <pre><code>{
413 <span class="tok-key">"status"</span>: <span class="tok-str">"ok"</span>,
414 <span class="tok-key">"explain"</span>: [
415 {
416 <span class="tok-key">"path"</span>: <span class="tok-str">"src/auth/tokens.py::validate_token"</span>,
417 <span class="tok-key">"altitude"</span>: <span class="tok-str">"symbol"</span>,
418 <span class="tok-key">"outcome"</span>: <span class="tok-str">"auto_merged"</span>,
419 <span class="tok-key">"strategy"</span>: <span class="tok-str">"recursive"</span>,
420 <span class="tok-key">"harmony_tier"</span>: <span class="tok-kw">null</span>,
421 <span class="tok-key">"note"</span>: <span class="tok-str">"changes were in different symbol regions"</span>
422 },
423 {
424 <span class="tok-key">"path"</span>: <span class="tok-str">"src/auth/tokens.py::refresh_token"</span>,
425 <span class="tok-key">"altitude"</span>: <span class="tok-str">"symbol"</span>,
426 <span class="tok-key">"outcome"</span>: <span class="tok-str">"harmony_applied"</span>,
427 <span class="tok-key">"strategy"</span>: <span class="tok-str">"recursive"</span>,
428 <span class="tok-key">"harmony_tier"</span>: <span class="tok-num">2</span>,
429 <span class="tok-key">"resolution_id"</span>: <span class="tok-str">"7c1a9e3f4d82..."</span>,
430 <span class="tok-key">"confidence"</span>: <span class="tok-num">1.0</span>,
431 <span class="tok-key">"note"</span>: <span class="tok-str">"replayed human-verified resolution from 2026-05-14"</span>
432 },
433 {
434 <span class="tok-key">"path"</span>: <span class="tok-str">"pyproject.toml"</span>,
435 <span class="tok-key">"altitude"</span>: <span class="tok-str">"file"</span>,
436 <span class="tok-key">"outcome"</span>: <span class="tok-str">"conflict"</span>,
437 <span class="tok-key">"strategy"</span>: <span class="tok-str">"overlay"</span>,
438 <span class="tok-key">"harmony_tier"</span>: <span class="tok-kw">null</span>,
439 <span class="tok-key">"note"</span>: <span class="tok-str">"both branches modified 'version' key"</span>
440 }
441 ]
442 }</code></pre>
443 </div>
444
445 <p>
446 <code>--explain</code> is safe with <code>--dry-run</code> — the full decision trace
447 is computed without modifying the working tree:
448 </p>
449
450 <div class="devdocs-code-block">
451 <pre><span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--dry-run</span> <span class="tok-kw">--explain</span> <span class="tok-kw">--json</span></pre>
452 </div>
453 </section>
454
455 {# ── muse merge ────────────────────────────────────────────────────────── #}
456 <section class="devdocs-section" id="local-merge">
457 <h2><code>muse merge</code> — local merge</h2>
458 <p>
459 <code>muse merge &lt;branch&gt;</code> merges the named branch into the current branch.
460 The current branch must be the <em>target</em> — switch to it before merging.
461 </p>
462
463 <div class="devdocs-code-block">
464 <pre><span class="tok-cmt"># always switch to the target branch first</span>
465 <span class="tok-fn">muse</span> switch dev
466 <span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--json</span></pre>
467 </div>
468 <div class="devdocs-code-block devdocs-code-block--output">
469 <div class="devdocs-code-header">
470 <span class="devdocs-code-lang">json</span>
471 <span class="devdocs-code-label">clean merge output</span>
472 </div>
473 <pre><code>{
474 <span class="tok-key">"status"</span>: <span class="tok-str">"ok"</span>,
475 <span class="tok-key">"merge_type"</span>: <span class="tok-str">"three_way"</span>,
476 <span class="tok-key">"auto_resolved"</span>: [<span class="tok-str">"src/auth/tokens.py::refresh_token"</span>],
477 <span class="tok-key">"conflicts"</span>: [],
478 <span class="tok-key">"commit_id"</span>: <span class="tok-str">"sha256:4e8b2f1a..."</span>
479 }</code></pre>
480 </div>
481
482 <h3>Flags</h3>
483 <table class="devdocs-table">
484 <thead><tr><th>Flag</th><th>Default</th><th>Description</th></tr></thead>
485 <tbody>
486 <tr><td><code>--strategy</code></td><td><code>recursive</code></td><td>Merge strategy: <code>recursive</code>, <code>overlay</code>, <code>snapshot</code>, <code>replay</code>, <code>ours</code>, <code>theirs</code></td></tr>
487 <tr><td><code>--history</code></td><td><code>merge</code></td><td>History mode: <code>merge</code>, <code>squash</code>, <code>rebase</code></td></tr>
488 <tr><td><code>--on-conflict</code></td><td><code>escalate</code></td><td>Conflict fallback: <code>escalate</code>, <code>ours</code>, <code>theirs</code></td></tr>
489 <tr><td><code>--dry-run</code></td><td>off</td><td>Compute merge plan without touching working tree or MERGE_STATE</td></tr>
490 <tr><td><code>--explain</code></td><td>off</td><td>Include per-path decision trace in JSON output</td></tr>
491 <tr><td><code>--no-harmony-autoupdate</code></td><td>off</td><td>Skip Harmony auto-apply for this merge (still records conflicts on commit)</td></tr>
492 <tr><td><code>--json</code></td><td>off</td><td>Structured JSON output</td></tr>
493 </tbody>
494 </table>
495
496 <h3>Exit codes</h3>
497 <table class="devdocs-table">
498 <thead><tr><th>Exit code</th><th>Meaning</th></tr></thead>
499 <tbody>
500 <tr><td><code>0</code></td><td>Merge complete (including fast-forward)</td></tr>
501 <tr><td><code>1</code></td><td>Merge paused — unresolved conflicts in working tree</td></tr>
502 <tr><td><code>2</code></td><td>Error — invalid arguments, bad branch reference, or cannot merge a branch into itself</td></tr>
503 </tbody>
504 </table>
505
506 <h3 class="devdocs-subsection-title"><a href="#local-merge-resolving">Resolving conflicts</a></h3>
507
508 <p>
509 When <code>muse merge</code> exits 1, the working tree contains conflict markers.
510 The conflict address format (<code>file.py::Symbol</code> for symbol-level,
511 <code>file.py</code> for file-level) is used in both <code>muse conflicts --json</code>
512 and <code>muse resolve</code>.
513 </p>
514
515 <div class="devdocs-code-block">
516 <pre><span class="tok-cmt"># 1. List what needs resolving</span>
517 <span class="tok-fn">muse</span> conflicts <span class="tok-kw">--json</span>
518
519 <span class="tok-cmt"># 2. Read the conflicted file — understand all three sections:
520 # &lt;&lt;&lt;&lt;&lt;&lt;&lt; ours [modified] ← what YOUR branch has
521 # ||||||| base ← common ancestor
522 # ======= theirs [modified] ← what the INCOMING branch has
523 # &gt;&gt;&gt;&gt;&gt;&gt;&gt; end conflict</span>
524
525 <span class="tok-cmt"># 3. Edit the file to the correct merged result incorporating both sides</span>
526
527 <span class="tok-cmt"># 4. Mark resolved — stages automatically</span>
528 <span class="tok-fn">muse</span> resolve src/auth/tokens.py::validate_token <span class="tok-kw">--json</span>
529 <span class="tok-cmt"># or resolve all at once:</span>
530 <span class="tok-fn">muse</span> resolve <span class="tok-kw">--all</span> <span class="tok-kw">--json</span>
531
532 <span class="tok-cmt"># 5. Commit — Harmony records the resolution (human_verified=true, confidence=1.0)</span>
533 <span class="tok-fn">muse</span> commit -m <span class="tok-str">"merge: resolve validate_token conflict"</span> \
534 <span class="tok-kw">--agent-id</span> claude-code <span class="tok-kw">--model-id</span> claude-sonnet-4-6 <span class="tok-kw">--sign</span></pre>
535 </div>
536 </section>
537
538 {# ── Proposal merge ────────────────────────────────────────────────────── #}
539 <section class="devdocs-section" id="proposal-merge">
540 <h2>Proposal merge</h2>
541 <p>
542 <code>muse hub proposal merge</code> merges a proposal's source branch into its
543 target branch on the server. It accepts the same strategy, history, and on-conflict
544 flags as local <code>muse merge</code>. The surface is intentionally identical so
545 that an automated CI pipeline and a human reviewing a proposal see the same
546 abstraction.
547 </p>
548
549 <div class="devdocs-code-block">
550 <pre><span class="tok-cmt"># merge proposal af54753d with squash history and overlay strategy</span>
551 <span class="tok-fn">muse</span> -C ~/ecosystem/musehub hub proposal merge af54753d \
552 <span class="tok-kw">--strategy</span> recursive \
553 <span class="tok-kw">--history</span> squash \
554 <span class="tok-kw">--json</span> | jq <span class="tok-str">'.status'</span>
555
556 <span class="tok-cmt"># check what the merge would do before committing</span>
557 <span class="tok-fn">muse</span> -C ~/ecosystem/musehub hub proposal merge af54753d \
558 <span class="tok-kw">--dry-run</span> <span class="tok-kw">--explain</span> <span class="tok-kw">--json</span></pre>
559 </div>
560
561 <h3>Strategy × history matrix — pick one of each</h3>
562 <table class="devdocs-table">
563 <thead>
564 <tr>
565 <th></th>
566 <th><code>--history merge</code></th>
567 <th><code>--history squash</code></th>
568 <th><code>--history rebase</code></th>
569 </tr>
570 </thead>
571 <tbody>
572 <tr>
573 <td><code>--strategy recursive</code></td>
574 <td>Symbol-level three-way, full history</td>
575 <td>Symbol-level three-way, collapsed history</td>
576 <td>Symbol-level three-way, linear history</td>
577 </tr>
578 <tr>
579 <td><code>--strategy overlay</code></td>
580 <td>Key-level merge, full history</td>
581 <td>Key-level merge, collapsed</td>
582 <td>Key-level merge, linear</td>
583 </tr>
584 <tr>
585 <td><code>--strategy snapshot</code></td>
586 <td>Atomic file, full history</td>
587 <td>Atomic file, collapsed</td>
588 <td>Atomic file, linear</td>
589 </tr>
590 </tbody>
591 </table>
592
593 <h3>Proposal merge flags</h3>
594 <table class="devdocs-table">
595 <thead><tr><th>Flag</th><th>Default</th><th>Description</th></tr></thead>
596 <tbody>
597 <tr><td><code>--strategy</code></td><td><code>recursive</code></td><td>Same values as <code>muse merge --strategy</code></td></tr>
598 <tr><td><code>--history</code></td><td><code>merge_commit</code></td><td><code>merge_commit</code>, <code>squash</code>, <code>rebase</code> (alias: <code>merge</code> → <code>merge_commit</code>)</td></tr>
599 <tr><td><code>--on-conflict</code></td><td><code>escalate</code></td><td>Same values as <code>muse merge --on-conflict</code></td></tr>
600 <tr><td><code>--dry-run</code></td><td>off</td><td>Return merge plan without writing anything server-side</td></tr>
601 <tr><td><code>--explain</code></td><td>off</td><td>Include per-path decision trace</td></tr>
602 <tr><td><code>--json</code></td><td>off</td><td>Structured JSON output</td></tr>
603 </tbody>
604 </table>
605 </section>
606
607 {# ── Safe merge protocol ───────────────────────────────────────────────── #}
608 <section class="devdocs-section" id="safe-protocol">
609 <h2>Safe merge protocol</h2>
610 <p>
611 After experiencing 8 accidental reverts from under-inspected merges, this workspace
612 adopted a four-step pre-merge checklist. Follow it every time — it takes less than
613 a minute and prevents hours of recovery work.
614 </p>
615
616 <div class="devdocs-callout">
617 {{ icon("warn", 16, "devdocs-callout-icon") }}
618 <div>
619 <strong>Create backup branches before every non-trivial merge.</strong>
620 <code>muse branch feat/my-thing-backup</code> creates a pointer at the current
621 feature branch HEAD without switching. If the merge goes wrong, the backup
622 preserves the work.
623 </div>
624 </div>
625
626 <h3 class="devdocs-subsection-title"><a href="#safe-step1">Step 1 — Topology check</a></h3>
627 <p>
628 Find the merge base. A fast-forward topology means no conflicts are possible.
629 </p>
630
631 <div class="devdocs-code-block">
632 <pre><span class="tok-fn">muse</span> merge-base dev feat/my-thing <span class="tok-kw">--json</span></pre>
633 </div>
634 <div class="devdocs-code-block devdocs-code-block--output">
635 <div class="devdocs-code-header">
636 <span class="devdocs-code-lang">json</span>
637 <span class="devdocs-code-label">output</span>
638 </div>
639 <pre><code>{
640 <span class="tok-key">"merge_base"</span>: <span class="tok-str">"sha256:abc123..."</span>,
641 <span class="tok-key">"commit_a"</span>: <span class="tok-str">"sha256:abc123..."</span>, <span class="tok-cmt">// dev tip</span>
642 <span class="tok-key">"commit_b"</span>: <span class="tok-str">"sha256:def456..."</span> <span class="tok-cmt">// feat/my-thing tip</span>
643 }</code></pre>
644 </div>
645 <p>
646 If <code>merge_base == commit_a</code> (dev tip), the merge is a pure fast-forward
647 — all feature branch commits are linear descendants of dev. No conflict is possible;
648 skip Step 3 if you're confident.
649 </p>
650
651 <h3 class="devdocs-subsection-title"><a href="#safe-step2">Step 2 — Inspect unique commits</a></h3>
652 <p>
653 List the commits that will be merged, then spot-check the diff for surprising changes.
654 </p>
655
656 <div class="devdocs-code-block">
657 <pre><span class="tok-cmt"># commits on feat/my-thing not yet on dev</span>
658 <span class="tok-fn">muse</span> rev-list dev..feat/my-thing <span class="tok-kw">--json</span> | jq <span class="tok-str">'.commits[] | {message, committed_at}'</span>
659
660 <span class="tok-cmt"># overall diff summary</span>
661 <span class="tok-fn">muse</span> diff dev feat/my-thing <span class="tok-kw">--json</span> | jq <span class="tok-str">'keys'</span></pre>
662 </div>
663
664 <h3 class="devdocs-subsection-title"><a href="#safe-step3">Step 3 — Dry-run merge</a></h3>
665 <p>
666 Switch to the target branch <em>first</em>, then dry-run. Running dry-run while
667 still on the feature branch will error ("Cannot merge a branch into itself").
668 </p>
669
670 <div class="devdocs-code-block">
671 <pre><span class="tok-fn">muse</span> switch dev <span class="tok-cmt"># ← must switch first</span>
672 <span class="tok-fn">muse</span> merge feat/my-thing <span class="tok-kw">--dry-run</span> <span class="tok-kw">--explain</span> <span class="tok-kw">--json</span> | jq</pre>
673 </div>
674
675 <p>Verify:</p>
676 <ul>
677 <li><code>"conflicts": []</code> — no conflicts expected</li>
678 <li><code>"fast_forward": true</code> — pure FF if applicable</li>
679 <li>The <code>explain</code> list accounts for all files you expect to change</li>
680 </ul>
681
682 <h3 class="devdocs-subsection-title"><a href="#safe-step4">Step 4 — Merge, test, push</a></h3>
683
684 <div class="devdocs-code-block">
685 <pre><span class="tok-cmt"># merge</span>
686 <span class="tok-fn">muse</span> merge feat/my-thing <span class="tok-kw">--json</span>
687
688 <span class="tok-cmt"># run relevant tests</span>
689 <span class="tok-fn">muse</span> code test <span class="tok-kw">--json</span>
690
691 <span class="tok-cmt"># push (use --force-with-lease if remote ref needs advancing after FF merge)</span>
692 <span class="tok-fn">muse</span> push local dev
693 <span class="tok-cmt"># or if rejected as diverged after a fast-forward:</span>
694 <span class="tok-fn">muse</span> push local dev <span class="tok-kw">--force-with-lease</span>
695
696 <span class="tok-cmt"># promote dev → main when ready</span>
697 <span class="tok-fn">muse</span> switch main
698 <span class="tok-fn">muse</span> merge dev <span class="tok-kw">--dry-run</span> <span class="tok-kw">--json</span>
699 <span class="tok-fn">muse</span> merge dev <span class="tok-kw">--json</span>
700 <span class="tok-fn">muse</span> push local main
701 <span class="tok-fn">muse</span> switch dev</pre>
702 </div>
703
704 <div class="devdocs-callout">
705 {{ icon("info", 16, "devdocs-callout-icon") }}
706 <div>
707 <strong><code>--force-with-lease</code> vs <code>--force</code></strong> — after a
708 fast-forward merge locally, the remote ref may not have been updated (common after
709 a previous push was rejected). <code>--force-with-lease</code> is safe: it advances
710 the ref only if the remote tip matches your last fetch. <code>--force</code> skips
711 that check. Always prefer <code>--force-with-lease</code>.
712 </div>
713 </div>
714 </section>
715
716 {# ── Harmony integration ───────────────────────────────────────────────── #}
717 <section class="devdocs-section" id="harmony">
718 <h2>Harmony integration</h2>
719 <p>
720 Harmony is the conflict-resolution memory layer that sits beneath every merge.
721 It fires automatically — you never call it directly during a merge. The relationship
722 is:
723 </p>
724
725 <ul>
726 <li><strong>Merge engine</strong> detects which paths conflict and at which altitude.</li>
727 <li><strong>Harmony</strong> checks whether a prior resolution exists for each conflicting
728 path, and if so, applies it automatically (Tier 1–3). No human intervention needed.</li>
729 <li>For paths Harmony cannot resolve (Tier 4), the merge pauses and conflict markers
730 appear in the working tree.</li>
731 <li>When you manually resolve and commit, Harmony records the outcome with
732 <code>human_verified = true</code> and <code>confidence = 1.0</code>. The same
733 conflict auto-resolves on the next merge.</li>
734 </ul>
735
736 <div class="devdocs-code-block">
737 <pre><span class="tok-cmt"># merge — Harmony auto-applies anything it knows</span>
738 <span class="tok-fn">muse</span> merge feat/auth <span class="tok-kw">--json</span>
739 <span class="tok-cmt"># ✔ [harmony] auto-resolved: src/auth/tokens.py::refresh_token (Tier 2)</span>
740 <span class="tok-cmt"># CONFLICT: pyproject.toml (Tier 4 — new)</span>
741
742 <span class="tok-cmt"># resolve manually, commit — Harmony learns</span>
743 <span class="tok-fn">muse</span> resolve pyproject.toml <span class="tok-kw">--json</span>
744 <span class="tok-fn">muse</span> commit -m <span class="tok-str">"merge: resolve pyproject.toml version conflict"</span> \
745 <span class="tok-kw">--agent-id</span> claude-code <span class="tok-kw">--model-id</span> claude-sonnet-4-6 <span class="tok-kw">--sign</span>
746 <span class="tok-cmt"># ✅ harmony: recorded resolution for 'pyproject.toml'</span>
747
748 <span class="tok-cmt"># next merge — auto-resolved</span>
749 <span class="tok-fn">muse</span> merge feat/other <span class="tok-kw">--json</span>
750 <span class="tok-cmt"># ✔ [harmony] auto-resolved: pyproject.toml (Tier 2)</span></pre>
751 </div>
752
753 <p>
754 For the full Harmony reference — confidence thresholds, policies, semantic
755 fingerprinting, audit log, and escalation — see
756 <a href="/muse/harmony">Phase 05: Harmony</a>.
757 </p>
758 </section>
759
760 {# ── CLI Reference ─────────────────────────────────────────────────────── #}
761 <section class="devdocs-section" id="cli">
762 <h2>CLI reference</h2>
763 <p>All commands accept <code>--json</code>.</p>
764
765 <table class="devdocs-table">
766 <thead><tr><th>Task</th><th>Command</th></tr></thead>
767 <tbody>
768 <tr><td>Merge a branch into current</td><td><code>muse merge &lt;branch&gt; --json</code></td></tr>
769 <tr><td>Dry-run merge plan</td><td><code>muse merge &lt;branch&gt; --dry-run --json</code></td></tr>
770 <tr><td>Merge with decision trace</td><td><code>muse merge &lt;branch&gt; --explain --json</code></td></tr>
771 <tr><td>Three-way strategy (default)</td><td><code>muse merge &lt;branch&gt; --strategy recursive</code></td></tr>
772 <tr><td>Overlay strategy (config)</td><td><code>muse merge &lt;branch&gt; --strategy overlay</code></td></tr>
773 <tr><td>Snapshot strategy (binary)</td><td><code>muse merge &lt;branch&gt; --strategy snapshot</code></td></tr>
774 <tr><td>Squash history</td><td><code>muse merge &lt;branch&gt; --history squash</code></td></tr>
775 <tr><td>Rebase history</td><td><code>muse merge &lt;branch&gt; --history rebase</code></td></tr>
776 <tr><td>Auto-take ours on conflict</td><td><code>muse merge &lt;branch&gt; --on-conflict ours</code></td></tr>
777 <tr><td>Find merge base</td><td><code>muse merge-base &lt;a&gt; &lt;b&gt; --json</code></td></tr>
778 <tr><td>List conflicts after partial merge</td><td><code>muse conflicts --json</code></td></tr>
779 <tr><td>Mark a path resolved (stages it)</td><td><code>muse resolve &lt;path&gt; --json</code></td></tr>
780 <tr><td>Mark all conflicts resolved</td><td><code>muse resolve --all --json</code></td></tr>
781 <tr><td>Commits not yet on target</td><td><code>muse rev-list &lt;target&gt;..&lt;source&gt; --json</code></td></tr>
782 <tr><td>Merge a proposal (server-side)</td><td><code>muse hub proposal merge &lt;id&gt; --json</code></td></tr>
783 <tr><td>Proposal merge dry-run</td><td><code>muse hub proposal merge &lt;id&gt; --dry-run --explain --json</code></td></tr>
784 <tr><td>Skip Harmony for one merge</td><td><code>muse merge &lt;branch&gt; --no-harmony-autoupdate</code></td></tr>
785 </tbody>
786 </table>
787
788 <nav class="devdocs-phase-nav" aria-label="Phase navigation">
789 <a class="devdocs-phase-nav-btn devdocs-phase-nav-btn--prev" href="/muse/intelligence">
790 {{ icon("arrow-left", 14) }}
791 Phase 04: Code Intelligence
792 </a>
793 <a class="devdocs-phase-nav-btn devdocs-phase-nav-btn--next" href="/muse/harmony">
794 Phase 06: Harmony
795 {{ icon("arrow-right", 14) }}
796 </a>
797 </nav>
798 </section>
799
800 </main>
801 </div>{# /.devdocs-layout #}
802 </div>{# /.devdocs #}
803 {% endblock %}
804
805 {% block page_scripts %}
806 {% endblock %}
File History 1 commit
sha256:42bc547653458bb15e283222247af0237872d9cb5c2a72ad2ca1c111ed2c0ca4 feat(9A-4 F7): overseer-run provenance enrichment API for S… Human minor ⚠ 76 days ago