gabriel / muse public
Open #31 Docs
filed by gabriel human · 5 days ago

Implement ^ref exclusion prefix syntax in muse traversal commands

0 Anchors
Blast radius
Churn 30d
0 Proposals

Background

Git supports two syntactically different but semantically equivalent ways to express commit exclusion in traversal commands:

  • Range syntaxA..B: commits reachable from B but not from A. Already implemented in muse rev-list.
  • Exclusion prefix^ref: exclude all commits reachable from ref. More flexible because multiple exclusions compose: git rev-list A ^B ^C ^D.

Git uses ^ref idiomatically in rev-list, log, cherry, and anywhere commit traversal is involved. Agents have deep ^ref muscle memory from git training data. When they write muse rev-list task/feature ^dev --json they get a hard CLI error with no hint about the correct form.

Additionally, muse log currently accepts only a single [ref] — it has no range or exclusion syntax at all. This means the idiomatic git log main..feat (show what's on feat that isn't on main) has no muse equivalent, forcing agents to reach for rev-list as a workaround or fall back to the broken ^ syntax.

Discovered during phase1-merge-engine merge prep (2026-06-12).


Goal

Every command in muse that idiomatically accepts commit ranges or exclusions in git supports both A..B range syntax and ^ref exclusion prefix. Agents can write natural commit traversal expressions without hitting CLI errors or unexpected output.


Phases

Phase 1 — Audit: where does git use ^ref and A..B?

Deliverable:

  • AU_01 — Produce a table mapping git commands that accept ^ref / A..B to their current muse equivalents, noting which already support range syntax and which do not. At minimum cover: rev-list, log, diff, commit-graph, cherry.

This table drives Phases 2 and 3. Scope is limited to commands already implemented in muse — no new commands.

Phase 2 — ^ref exclusion prefix support

Add ^ref as a first-class exclusion prefix to every traversal command identified in Phase 1.

Deliverables:

  • EX_01muse rev-list ^ref — single exclusion: muse rev-list HEAD ^main equivalent to muse rev-list main..HEAD.
  • EX_02muse rev-list multiple exclusions: muse rev-list A ^B ^C — commits reachable from A but not from B or C.
  • EX_03muse log ^ref — same semantics as rev-list, applied to log output.
  • EX_04 — Any additional commands surfaced by AU_01 that idiomatically accept ^ref in git.

Each deliverable requires a failing test written first (TDD), named test_EX_NN_*.

Phase 3 — A..B range syntax in muse log

muse log currently accepts only a single [ref]. Add range support so muse log main..feat works.

Deliverables:

  • RG_01muse log A..B — shows commits on B not on A, newest-first, in standard log format.
  • RG_02muse log A..B --json — same, structured output.
  • RG_03muse log A..B --oneline — compact form.
  • RG_04muse log A..B composes with existing filters: --author, --since, --touches, --max-count.

Each deliverable requires a failing test written first (TDD), named test_RG_NN_*.

Phase 4 — Glossary and agent-guide

Deliverables:

  • GL_01 — Add ^refmuse rev-list A..B / muse rev-list A ^B row to the Gitism Glossary table in muse/docs/agent-guide.md.
  • GL_02 — Add git log A ^Bmuse log A..B row to the same table.
  • GL_03 — Add a note explaining direction: A..B = "reachable from B but not A" (easy to mix up).
  • GL_04 — grep gate: grep -n " \^[a-zA-Z]" docs/agent-guide.md returns zero matches (no surviving ^ref gitisms in the guide itself).

Acceptance criteria

  1. muse rev-list HEAD ^main --json exits 0 and returns the same commit set as muse rev-list main..HEAD --json.
  2. muse rev-list A ^B ^C --json correctly excludes commits reachable from both B and C.
  3. muse log main..feat --json exits 0 and returns commits on feat not on main.
  4. All EX_*, RG_*, and GL_* deliverables checked off.
  5. No ^ref syntax survives in agent-guide.md.

Out of scope

  • Three-dot (A...B) symmetric difference — separate ticket if needed.
  • New traversal commands not already in muse.
  • Changing muse diff positional argument handling (it already takes commit_a commit_b explicitly).
Activity
gabriel opened this issue 5 days ago
No activity yet. Use the CLI to comment.