gabriel / muse public
fix fix/91-reorder-only-semver-classification #1 / 1
AI Agent gabriel · 14 hours ago · Oct 21, 2026 · Diff

fix: semver classifier no longer flags breaking on reorder-only diffs (muse#91)

Root cause confirmed exactly as hypothesized in the ticket: build_diff_ops() (muse/plugins/code/symbol_diff.py) falls back to a whole-file ReplaceOp labeled "<path> (reformatted -- no semantic change)" whenever every symbol's content_id in a modified file is unchanged -- e.g. a pure reorder of two top-level functions, or a comment-only edit (the same fallback behind muse#92). _classify_replace() (muse/core/semver_classifier.py) pattern- matches new_summary for "renamed to"/"signature"/"implementation" but had no case for this exact fallback text, so it fell through to the conservative "unrecognised summary" catch-all and was classified breaking/minor -- directly contradicting the op's own "no semantic change" claim one field over.

Per the ticket's own Ask: this was a genuine gap (Ask #1/#3), not intentional conservatism -- there's no reason to assume worst-case when the diff engine already determined, with certainty, that nothing semantic changed. Fixed by adding a recognized branch in _classify_replace() for "no semantic change", classifying it `invisible` (no API impact, no bump, confidence 1.0) instead of falling through to the catch-all. Left the existing generic "reformatted" (without the "no semantic change" suffix) catch-all test untouched and passing -- this fix is scoped to the specific, unambiguous fallback text, not "reformatted" generically.

New regression tests (per Ask #4): - tests/test_sem_ver.py::TestClassifyDeltaReplace::test_replace_no_semantic_change_is_invisible -- synthetic-op unit test matching this file's existing style. - tests/test_reorder_only_semver_classification.py -- real-CLI end-to-end test reproducing the ticket's exact repro steps (commit two functions, commit again with only their order swapped, assert the resulting commit's structured_delta has sem_ver_bump == "none" and breaking_changes == []). Confirmed this test reproduces the exact contradictory JSON from the ticket body when run against the pre-fix code (sem_ver_bump: "minor", breaking_changes: ["extra.py"]).

Confirmed genuine RED on both new tests (reverted the fix, both failed for the right reason) before GREEN with the fix restored.

Targeted regression suite -- test_sem_ver.py (123 tests, includes the untouched catch-all test), test_reorder_only_semver_classification.py, test_comment_only_independence_merge.py, test_cmd_commit.py, test_cmd_diff.py (the only two direct callers of classify_delta per muse code impact) -- all pass (336 passed), zero regressions.

Co-Authored-By: Claude Sonnet 5 <[email protected]>

sha256:ac275030a7ff043ecc2e5a084bc43dba13bf0881f433f43002b2809e3d11893f sha
+10 ~2 symbols
3 changed · 1216 in snapshot files
sha256:0e96074c9c1bb622e021617635fb8e766b1b38e95758c9f5eb67d1544553dcf6 snapshot
+10
symbols added
~2
symbols modified
3
files changed
1216
files in snapshot
0
dead code introduced
Semantic Changes 12 symbols
+ _run function function _run L34–40
+ CliRunner import import CliRunner L29–29
+ InvokeResult import import InvokeResult L29–29
+ annotations import import annotations L23–23
+ json import import json L25–25
+ os import import os L26–26
+ pathlib import import pathlib L27–27
+ runner variable variable runner L31–31
+ test_reorder_only_diff_is_zero_bump_and_not_breaking function function test_reorder_only_diff_is_zero_bump_and_not_breaking L43–74
~ tests/test_sem_ver.py .py 1 symbol added, 1 symbol modified
+ test_replace_no_semantic_change_is_invisible method method test_replace_no_semantic_change_is_invisible L586–599
Files Changed
+1 ~2
1216 in snapshot
← Older Oldest on fix/91-reorder-only-semver-classification
All commits
Newer → Latest on fix/91-reorder-only-semver-classification

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