gabriel / musehub public
feat patch proposals task/proposal-models-v2 #16 / 19
AI Agent gabriel · 127 days ago · May 8, 2026 · Diff

feat(proposals): phase 3 — merge strategy engine

Five merge strategies: STATE_OVERLAY (from_wins), STATE_WEAVE (three-way file-level), STATE_REBASE (from-delta onto to), DOMAIN_SELECTIVE (subset by domain), PHASED (dependency-order execution).

- proposal_merge_strategies.py: pure strategy engine with classify_domain, _manifest_delta, _apply_delta, MergeResult, ConflictEntry, and all five strategy functions plus execute_merge_strategy router - musehub_proposals.py: _resolve_ancestor_manifest walks branch history to find merge-base; merge_proposal gates on dependencies, loads ancestor, and dispatches through execute_merge_strategy - test_proposal_reimagination_phase3.py: 56 unit + integration tests; uses muse.core.types.fake_id and blob_id(os.urandom()) for all IDs — no UUIDs

sha256:61f8a55666c7d5ed05011a10b04c8e52d03f431344662b3412153fc72c435098 sha
+116 ~1 symbols
sha256:106f6b4b4bb81ea34d29330a2f6ccbcb62c59e82caa48cbf78734773a5f78352 snapshot
+116
symbols added
~1
symbol modified
0
dead code introduced
Semantic Changes 117 symbols
+ ConflictEntry class class ConflictEntry L89–94
+ MergeResult class class MergeResult L107–130
+ PhaseResult class class PhaseResult L98–103
+ _DOMAIN_EXTENSIONS variable variable _DOMAIN_EXTENSIONS L36–50
+ _DOMAIN_PATH_PREFIXES variable variable _DOMAIN_PATH_PREFIXES L53–58
+ _apply_delta function function _apply_delta L151–166
+ _domain_summary function function _domain_summary L169–171
+ _manifest_delta function function _manifest_delta L138–148
+ classify_domain class function classify_domain L61–74
+ execute_merge_strategy function function execute_merge_strategy L538–609
+ PurePosixPath import import PurePosixPath L24–24
+ Sequence import import Sequence L25–25
+ StrDict import import StrDict L27–27
+ annotations import import annotations L20–20
+ dataclass class import dataclass L23–23
+ field import import field L23–23
+ logging import import logging L22–22
+ logger variable variable logger L29–29
+ merge_domain_selective function function merge_domain_selective L375–440
+ merge_phased function function merge_phased L443–530
+ merge_state_overlay function function merge_state_overlay L179–223
+ merge_state_rebase function function merge_state_rebase L325–372
+ merge_state_weave function function merge_state_weave L226–322
+ paths_for_domains function function paths_for_domains L77–80
+ TestDomainClassifier class class TestDomainClassifier L101–149
+ test_flac_is_stem method method test_flac_is_stem L117–118
+ test_midi_dot_midi_extension method method test_midi_dot_midi_extension L111–112
+ test_midi_extension method method test_midi_extension L108–109
+ test_path_prefix_identity method method test_path_prefix_identity L133–134
+ test_path_prefix_midi_beats_extension method method test_path_prefix_midi_beats_extension L123–125
+ test_path_prefix_payment method method test_path_prefix_payment L130–131
+ test_path_prefix_stem method method test_path_prefix_stem L127–128
+ test_paths_for_domains_filter method method test_paths_for_domains_filter L136–149
+ test_python_file_is_code method method test_python_file_is_code L102–103
+ test_typescript_file_is_code method method test_typescript_file_is_code L105–106
+ test_unknown_extension_fallback_to_code method method test_unknown_extension_fallback_to_code L120–121
+ test_wav_is_stem method method test_wav_is_stem L114–115
+ TestDomainSelective class class TestDomainSelective L331–372
+ test_conflict_recorded_when_ancestor_provided method method test_conflict_recorded_when_ancestor_provided L365–372
+ test_domains_merged_lists_selected method method test_domains_merged_lists_selected L355–359
+ test_empty_selective_domains_raises method method test_empty_selective_domains_raises L351–353
+ test_files_skipped_counted method method test_files_skipped_counted L345–349
+ test_non_selected_files_unchanged method method test_non_selected_files_unchanged L339–343
+ test_selected_domain_applied method method test_selected_domain_applied L332–337
+ test_strategy_name method method test_strategy_name L361–363
+ TestMergePhased class class TestMergePhased L380–428
+ test_fallback_has_one_phase_result method method test_fallback_has_one_phase_result L389–392
+ test_fallback_overlay_when_no_phase_manifests method method test_fallback_overlay_when_no_phase_manifests L381–387
+ test_full_phased_applies_in_order method method test_full_phased_applies_in_order L394–414
+ test_phase_results_have_correct_indices method method test_phase_results_have_correct_indices L416–424
+ test_strategy_name method method test_strategy_name L426–428
+ TestMergeProposalStrategyIntegration class class TestMergeProposalStrategyIntegration L549–619
+ test_default_overlay_merges_manifests method async_method test_default_overlay_merges_manifests L551–584
+ test_domain_selective_only_applies_selected_domain method async_method test_domain_selective_only_applies_selected_domain L587–619
+ TestStateOverlay class class TestStateOverlay L157–216
+ _from method method _from L161–162
+ _to method method _to L158–159
+ test_conflicts_when_ancestor_provided method method test_conflicts_when_ancestor_provided L191–198
+ test_counts method method test_counts L179–184
+ test_domains_merged_populated method method test_domains_merged_populated L211–216
+ test_from_only_files_added method method test_from_only_files_ L174–177
+ test_from_wins_shared_file method method test_from_wins_shared_file L164–167
+ test_no_conflict_when_only_one_side_changed method method test_no_conflict_when_only_one_side_changed L200–205
+ test_no_conflicts_without_ancestor method method test_no_conflicts_without_ancestor L186–189
+ test_strategy_name method method test_strategy_name L207–209
+ test_to_only_files_preserved method method test_to_only_files_preserved L169–172
+ TestStateRebase class class TestStateRebase L288–323
+ test_conflict_when_both_modified_same_file method method test_conflict_when_both_modified_same_file L305–311
+ test_from_delta_applied_onto_to method method test_from_delta_applied_onto_to L289–296
+ test_from_removal_applied method method test_from_removal_applied L313–319
+ test_strategy_name method method test_strategy_name L321–323
+ test_to_only_changes_preserved method method test_to_only_changes_preserved L298–303
+ TestStateWeave class class TestStateWeave L224–280
+ test_clean_from_change_applied method method test_clean_from_change_applied L225–231
+ test_clean_to_change_preserved method method test_clean_to_change_preserved L233–239
+ test_from_deletion_honoured method method test_from_deletion_honoured L257–262
+ test_new_file_from_only_added method method test_new_file_from_only_ L271–276
+ test_strategy_name method method test_strategy_name L278–280
+ test_to_deletion_honoured_when_from_untouched method method test_to_deletion_honoured_when_from_untouched L264–269
+ test_true_conflict_recorded_from_wins method method test_true_conflict_recorded_from_wins L248–255
+ test_unchanged_file_kept method method test_unchanged_file_kept L241–246
+ TestStrategyRouter class class TestStrategyRouter L436–474
+ test_routes_domain_selective method method test_routes_domain_selective L453–457
+ test_routes_phased method method test_routes_phased L459–461
+ test_routes_state_overlay method method test_routes_state_overlay L437–439
+ test_routes_state_rebase method method test_routes_state_rebase L447–451
+ test_routes_state_weave method method test_routes_state_weave L441–445
+ test_state_rebase_fallback_without_ancestor method method test_state_rebase_fallback_without_ancestor L472–474
+ test_state_weave_fallback_without_ancestor method method test_state_weave_fallback_without_ancestor L467–470
+ test_unknown_strategy_raises method method test_unknown_strategy_raises L463–465
+ _make_branch_with_commit function async_function _make_branch_with_commit L506–546
+ _make_repo function async_function _make_repo L482–503
+ _now function function _now L83–84
+ _oid function function _oid L91–93
+ _uid function function _uid L87–88
+ Any import import Any L58–58
+ AsyncSession import import AsyncSession L62–62
+ ConflictEntry import import ConflictEntry L64–64
+ MergeResult import import MergeResult L64–64
+ annotations import import annotations L54–54
+ blob_id import import blob_id L61–61
+ classify_domain class import classify_domain L64–64
+ datetime import import datetime L57–57
+ execute_merge_strategy import import execute_merge_strategy L64–64
+ fake_id import import fake_id L61–61
+ merge_domain_selective import import merge_domain_selective L64–64
+ merge_phased import import merge_phased L64–64
+ merge_state_overlay import import merge_state_overlay L64–64
+ merge_state_rebase import import merge_state_rebase L64–64
+ merge_state_weave import import merge_state_weave L64–64
+ os import import os L56–56
+ paths_for_domains import import paths_for_domains L64–64
+ pytest import import pytest L60–60
+ short_id import import short_id L61–61
+ timezone import import timezone L57–57
~ musehub/services/musehub_proposals.py .py 1 symbol added, 1 symbol modified
+ _resolve_ancestor_manifest function async_function _resolve_ancestor_manifest L442–504

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:61f8a55666c7d5ed05011a10b04c8e52d03f431344662b3412153fc72c435098 --body "your comment"