gabriel / muse public
feat BREAKING task/issue-8-phase4 #1 / 1
AI Agent gabriel · 114 days ago · May 21, 2026 · Diff

feat: harmony integration — manually_resolved tracking (issue #8 phase 4)

Adds a manually_resolved field to MERGE_STATE that records which conflict paths were explicitly confirmed by the user via `muse resolve` (as opposed to being side-picked with `muse checkout --ours/--theirs`).

Changes: - merge_engine.py: MergeStatePayload + MergeState get manually_resolved list; _write_conflict_paths preserves and updates it; resolve_path / resolve_symbol append cleared entries to manually_resolved on each call - harmony.py: record_resolutions gains manually_resolved: set[str] | None param; paths in the set → confidence=1.0, human_verified=True (manual edit); paths not in the set → confidence=0.8, human_verified=False (side-pick); None → legacy behaviour: all paths human_verified=True - commit.py: passes set(merge_state.manually_resolved) to harmony when non-empty, else None to preserve pre-Phase-4 behaviour for pure side-pick flows - tests/test_resolve_phase4.py: 19 tests covering MERGE_STATE tracking, record_resolutions confidence matrix, and end-to-end CLI flow

sha256:f61171578c887cada67a384f0580dd8b392625934c03fefd45df9bb0e24fe78f sha
+55 ~8 symbols
sha256:48ab6e0f110cb2736d87550ab3cc7f52a90fc74f0031e9b6ca0de7198a9b6fcb snapshot
+55
symbols added
~8
symbols modified
0
dead code introduced
Semantic Changes 63 symbols
~ tests/test_resolve_phase4.py .py 55 symbols added
+ TestManuallyResolvedTracking class class TestManuallyResolvedTracking L114–206
+ test_legacy_merge_state_no_manually_resolved_key method method test_legacy_merge_state_no_manually_resolved_key L192–206
+ test_manually_resolved_accumulates_across_calls method method test_manually_resolved_accumulates_across_calls L143–153
+ test_manually_resolved_does_not_affect_original_conflict_paths method method test_manually_resolved_does_not_affect_original_conflict_paths L171–178
+ test_read_write_round_trip_manually_resolved method method test_read_write_round_trip_manually_resolved L180–190
+ test_resolve_path_noop_does_not_add_to_manually_resolved method method test_resolve_path_noop_does_not_add_to_manually_resolved L155–161
+ test_resolve_path_records_in_manually_resolved method method test_resolve_path_records_in_manually_resolved L115–121
+ test_resolve_path_symbol_entries_recorded method method test_resolve_path_symbol_entries_recorded L123–132
+ test_resolve_symbol_noop_does_not_add_to_manually_resolved method method test_resolve_symbol_noop_does_not_add_to_manually_resolved L163–169
+ test_resolve_symbol_records_in_manually_resolved method method test_resolve_symbol_records_in_manually_resolved L134–141
+ TestRecordResolutionsManuallyResolved class class TestRecordResolutionsManuallyResolved L213–350
+ test_empty_set_gives_low_confidence method method test_empty_set_gives_low_confidence L231–246
+ test_manual_rationale_text method method test_manual_rationale_text L306–317
+ test_mixed_paths_get_different_confidence method method test_mixed_paths_get_different_confidence L280–304
+ test_none_gives_legacy_human_verified_true method method test_none_gives_legacy_human_verified_true L214–229
+ test_path_in_manually_resolved_gets_high_confidence method method test_path_in_manually_resolved_gets_high_confidence L248–262
+ test_path_not_in_manually_resolved_gets_low_confidence method method test_path_not_in_manually_resolved_gets_low_confidence L264–278
+ test_side_pick_rationale_text method method test_side_pick_rationale_text L319–330
+ test_symbol_level_path_in_manually_resolved method method test_symbol_level_path_in_manually_resolved L332–350
+ TestResolveToHarmonyEndToEnd class class TestResolveToHarmonyEndToEnd L357–395
+ repo method method repo L359–364
+ test_muse_resolve_all_sets_all_in_manually_resolved method method test_muse_resolve_all_sets_all_in_manually_resolved L381–395
+ test_muse_resolve_sets_manually_resolved_in_merge_state method method test_muse_resolve_sets_manually_resolved_in_merge_state L366–379
+ _BASE variable variable _BASE L54–54
+ _FakePlugin class class _FakePlugin L96–98
+ schema method method schema L98–98
+ _OURS variable variable _OURS L55–55
+ _THEIRS variable variable _THEIRS L56–56
+ _harmony_repo function function _harmony_repo L68–70
+ _invoke function function _invoke L101–107
+ _repo function function _repo L63–65
+ _state function function _state L84–87
+ _write function function _write L73–81
+ _write_object function function _write_object L90–93
+ CliRunner import import CliRunner L50–50
+ MUSE_DIR import import MUSE_DIR L49–49
+ Manifest import import Manifest L49–49
+ MergeState import import MergeState L40–40
+ annotations import import annotations L27–27
+ blob_id import import blob_id L49–49
+ fake_id import import fake_id L49–49
+ json import import json L29–29
+ list_patterns import import list_patterns L35–35
+ list_resolutions import import list_resolutions L35–35
+ muse_dir import import muse_dir L48–48
+ os import import os L30–30
+ pathlib import import pathlib L31–31
+ pytest import import pytest L33–33
+ read_merge_state import import read_merge_state L40–40
+ record_resolutions import import record_resolutions L35–35
+ resolve_path import import resolve_path L40–40
+ resolve_symbol import import resolve_symbol L40–40
+ write_merge_state import import write_merge_state L40–40
+ write_object import import write_object L47–47
+ runner variable variable runner L52–52
~ muse/cli/commands/commit.py .py 1 symbol modified
~ run
~ muse/core/harmony.py .py 1 symbol modified
← Older Oldest on task/issue-8-phase4
All commits
Newer → Latest on task/issue-8-phase4

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:f61171578c887cada67a384f0580dd8b392625934c03fefd45df9bb0e24fe78f --body "your comment"