gabriel / muse public
feat patch range-diff task/supercharge-range-diff #1 / 1
AI Agent gabriel · 163 days ago · Apr 17, 2026 · Diff

feat(range-diff): supercharge muse range-diff — fix sha256: bugs, add agent fields, rewrite tests

Bug fixes: - _resolve_ref: accept sha256:-prefixed commit IDs (strip prefix before hex fullmatch); previously all sha256:-prefixed commit IDs in ranges silently returned None, making all range expressions with commit IDs fail - _SAFE_REF_RE / _SAFE_RANGE_RE: allow ':' so sha256:-prefixed commit IDs pass input validation (previously rejected with 'Invalid ref' error) - _compute_patch_id: now returns (sha256:-prefixed patch_id, files_changed) tuple — patch_ids in JSON were bare hex, inconsistent with muse patch-id --json

New agent fields in JSON output: - old_count, new_count: commit counts for each range (no need to count pairs) - stable: reflects the --stable flag used for this comparison - creation_factor: the clamped value actually applied for pairing - files_changed: per-commit count in every pair's old/new commit info - duration_ms: wall-clock time in milliseconds - exit_code: 0 (trivially equivalent) or 1 (differences found), mirrored in JSON

Tests: - Delete tests/test_cmd_range_diff.py (19/24 failing, pre-sha256: helpers) - Add tests/test_range_diff_supercharge.py: 59 tests covering unit, integration, data integrity, performance, security, and stress tiers

sha256:f4552a503d9c232c87d9cfd12091accacd50b86f6f2bc4cddd524f1cb71b4818 sha
+63 ~23 −12 symbols
sha256:a07e835579a1c781dd8d1ccbe04e46d52da2a0bfe17636161c21e3edba920dda snapshot
+63
symbols added
~23
symbols modified
−12
symbols removed
0
dead code introduced
Semantic Changes 98 symbols
~ muse/cli/commands/range_diff.py .py 1 symbol added, 8 symbols modified
~ tests/test_range_diff_supercharge.py .py moved from tests/test_cmd_range_diff.py; 62 added, 12 removed, 15 modified
− _sha function function _sha L41–42
− test_commit_added function function test_commit_ L184–196
− test_commit_dropped function function test_commit_dropped L169–181
− test_creation_factor_zero_no_fuzzy_pairing function function test_creation_factor_zero_no_fuzzy_pairing L297–308
− test_identical_series_all_equivalent function function test_identical_series_all_equivalent L136–151
− test_json_pair_commit_info function function test_json_pair_commit_info L252–264
− test_json_schema_all_fields function function test_json_schema_all_fields L234–249
− test_nonexistent_old_ref_exits_nonzero function function test_nonexistent_old_ref_exits_nonzero L327–331
− test_stress_50_commits_mixed function function test_stress_50_commits_mixed L398–422
− test_stress_50_commits_trivially_equivalent function function test_stress_50_commits_trivially_equivalent L381–395
− test_text_output_shows_changed function function test_text_output_shows_changed L282–289
− test_text_output_shows_equivalent function function test_text_output_shows_equivalent L272–279
+ TestCreationFactor class class TestCreationFactor L546–576
+ test_creation_factor_clamped_to_range method method test_creation_factor_clamped_to_range L568–576
+ test_zero_no_fuzzy_pairing method method test_zero_no_fuzzy_pairing L547–556
+ TestDataIntegrity class class TestDataIntegrity L646–707
+ test_commit_ids_are_sha256_prefixed method method test_commit_ids_are_sha256_prefixed L674–687
+ test_duration_ms_is_plausible method method test_duration_ms_is_plausible L700–707
+ test_files_changed_accurate method method test_files_changed_accurate L647–663
+ test_old_count_zero_when_old_range_empty method method test_old_count_zero_when_old_range_empty L665–672
+ test_pair_subject_matches_commit_message method method test_pair_subject_matches_commit_message L689–698
+ TestDifferences class class TestDifferences L331–380
+ test_commit_added method method test_commit_ L343–353
+ test_commit_dropped method method test_commit_dropped L355–364
+ TestErrors class class TestErrors L627–638
+ test_nonexistent_old_ref method method test_nonexistent_old_ref L628–632
+ TestJsonSchema class class TestJsonSchema L388–538
+ test_complete_schema_keys method method test_complete_schema_keys L528–538
+ test_exit_code_reflects_differences method method test_exit_code_reflects_differences L412–421
+ test_has_creation_factor method method test_has_creation_factor L469–478
+ test_has_duration_ms method method test_has_duration_ms L389–399
+ test_has_exit_code method method test_has_exit_code L401–410
+ test_has_new_count method method test_has_new_count L435–446
+ test_has_old_count method method test_has_old_count L423–433
+ test_has_stable_field method method test_has_stable_field L448–457
+ test_old_count_new_count_match_pairs method method test_old_count_new_count_match_pairs L514–526
+ test_pair_has_files_changed method method test_pair_has_files_changed L496–512
+ test_patch_id_has_sha256_prefix method method test_patch_id_has_sha256_prefix L480–494
+ test_stable_false_by_default method method test_stable_false_by_default L459–467
+ TestParseRange class class TestParseRange L144–168
+ test_sha256_prefixed_base method method test_sha256_prefixed_base L163–168
+ TestPatchId class class TestPatchId L219–278
+ test_different_content_different_patch_id method method test_different_content_different_patch_id L252–260
+ test_first_commit_zero_files_changed method method test_first_commit_zero_files_changed L272–278
+ test_returns_files_changed_count method method test_returns_files_changed_count L231–240
+ test_returns_sha256_prefixed_patch_id method method test_returns_sha256_prefixed_patch_id L220–229
+ test_same_content_same_patch_id method method test_same_content_same_patch_id L242–250
+ test_stable_ignores_trailing_whitespace method method test_stable_ignores_trailing_whitespace L262–270
+ TestPerformance class class TestPerformance L753–779
+ test_50_commit_equivalent_series_under_2_seconds method method test_50_commit_equivalent_series_under_2_seconds L754–770
+ test_duration_ms_under_threshold method method test_duration_ms_under_threshold L772–779
+ TestResolveRef class class TestResolveRef L176–211
+ test_nonexistent_branch_returns_none method method test_nonexistent_branch_returns_none L202–205
+ test_nonexistent_sha_returns_none method method test_nonexistent_sha_returns_none L207–211
+ test_resolves_branch_name method method test_resolves_branch_name L177–182
+ test_resolves_head method method test_resolves_head L196–200
+ test_resolves_sha256_prefixed_commit_id method method test_resolves_sha256_prefixed_commit_id L184–194
+ TestSecurity class class TestSecurity L715–745
+ test_control_char_in_range_rejected method method test_control_char_in_range_rejected L726–729
+ test_no_ansi_in_json_output method method test_no_ansi_in_json_output L731–737
+ test_no_ansi_in_text_output method method test_no_ansi_in_text_output L739–745
+ TestStress class class TestStress L787–830
+ test_50_commits_all_equivalent method method test_50_commits_all_equivalent L788–803
+ test_50_commits_mixed method method test_50_commits_mixed L805–830
+ TestTextOutput class class TestTextOutput L584–619
+ test_added_shows_gt_symbol method method test_added_shows_gt_symbol L603–610
+ test_changed_shows_exclamation_symbol method method test_changed_shows_exclamation_symbol L594–601
+ test_dropped_shows_lt_symbol method method test_dropped_shows_lt_symbol L612–619
+ test_equivalent_shows_equals_symbol method method test_equivalent_shows_equals_symbol L585–592
+ TestTriviallyEquivalent class class TestTriviallyEquivalent L286–323
+ test_identical_series_exit_zero method method test_identical_series_exit_zero L287–298
+ _oid function function _oid L74–76
+ re import import re L52–52
+ time import import time L53–53
← Older Oldest on task/supercharge-range-diff
All commits
Newer → Latest on task/supercharge-range-diff

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