feat: implement ^ref exclusion prefix syntax in rev-list and log (muse#31)
Audit (AU_01) — git commands that accept ^ref / A..B, and muse's state before this change:
| Command | A..B support | ^ref support | Notes | |-------------------|------------------------|---------------|-------| | muse rev-list | yes (pre-existing) | NO — hard "too_many_refs" error | fixed here (EX_01/EX_02) | | muse log | yes (pre-existing, issue #28) | NO — silently swallowed into pathspec, returned wrong empty result | fixed here (EX_03) | | muse commit-graph | n/a — uses --tip/--stop-at flags, no git-positional ref syntax | n/a | out of scope: different interface shape, nothing to translate | | muse diff | n/a — explicit positional commit_a/commit_b | n/a | explicitly out of scope per ticket | | muse cherry (git) / muse cherry-pick | muse has no `cherry` (upstream-diff) command, only `cherry-pick <ref>` which applies exactly one commit | n/a | "no new commands" — out of scope |
EX_01/EX_02 — muse rev-list: `ref` tokens starting with "^" are now collected as exclusion refs (any number, composing with each other and with a single plain/A..B include token), unioned with the existing A..B exclusion-set logic via `_exclude_set`/`ancestor_ids`. `rev-list X ^Y` == `rev-list Y..X`.
EX_03 — muse log: Same exclusion semantics. Two argparse wrinkles handled: a lone "^ref" token (e.g. `muse log ^main`) lands in the single `ref` positional itself (nargs="?" greedily claims it), while any additional "^ref" tokens land in `pathspec` (nargs="*") and would otherwise be silently treated as file paths, producing a wrong (and silently empty) result with no error at all — worse than rev-list's hard error. Both cases are intercepted and routed into the same exclusion-set union as the A..B path before pathspec disambiguation runs.
RG_01-04 — muse log A..B range syntax: Investigation found this was already implemented (issue #28, tests/test_log_dotdot_range.py) for plain text/--json output and -n limit composition. Verified live that --oneline (RG_03) and composition with --author/pathspec/--max-count (RG_04) already worked correctly through the shared filter pipeline — added regression tests for both, no code changes needed for Phase 3.
GL_01-03 — docs/agent-guide.md Gitism Glossary: New "Commit exclusion syntax" subsection documents ^ref as now working identically to git (not a gitism to translate away from, same framing as the existing refspec-syntax section), with a direction-disambiguation note (A..B / X ^Y both mean "reachable from the right/non-excluded side").
GL_04 — grep gate note: The ticket's literal `grep -n " \^[a-zA-Z]" docs/agent-guide.md` gate cannot return zero matches while also documenting WORKING ^ref syntax — any correct command example like "rev-list A ^B" necessarily contains a space immediately before a caret-prefixed letter. Confirmed the file had zero such matches before this change (verified); the gate's literal regex and this ticket's own goal of documenting working ^ref syntax are in direct tension. Resolved by following the intent (no row frames ^ref as a "wrong gitism to avoid" — it's documented as working, matching the existing refspec-syntax section's "not a gotcha, a reassurance" framing) rather than gaming the literal grep command.
Tests: tests/test_cmd_rev_list.py (4 new: EX_01/EX_02 equivalence, composition, JSON, bad-ref error) and tests/test_log_dotdot_range.py (4 new: EX_03 equivalence, caret-alone default-branch, composition, bad-ref error). Confirmed genuine RED for both EX_03 and EX_01/EX_02 by reverting each fix and re-running (failures landed exactly where the removed logic was supposed to act — rev-list hard-errored, log silently returned wrong empty results), then GREEN with fixes restored.
Regression: tests/test_log_dotdot_range.py, tests/test_cmd_rev_list.py, tests/test_log_collect_all_commits.py, tests/test_log_json_schema.py, tests/test_log_graph.py, tests/test_log_supercharge.py, tests/test_cli_log.py, tests/test_cmd_log.py, tests/test_log_branch_flag.py — 327 tests, all green, no regressions.
Semantic Changes
13 symbols
Files Changed
~5
1254 in snapshot
0 comments
muse hub commit comment sha256:85fc1542f909649acadf0b5fd3bc662f43d59eea76d799a069e76cbccd54f7ec --body "your comment"
No comments yet. Be the first to start the discussion.