git diff/show/log route by predicate set membership, where git resolves output shape by suppressor recency plus a precedence lattice
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Refactor
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- rust
- Domain
- cli, testing-qa, tooling
Research direction
Start with the run_diff, run_show, and run_log call sites and the differential harness used for #3681; first measure the complete shape precedence lattice against git before changing the implementation. Done means the three call sites share the folded output-shape result and the harness reports zero unexplained divergences across randomized flag combinations.
Written by the indexing model from the issue text.
Description
run_diff, run_show and run_log decide between three output routes — raw passthrough, RTK's compacted diff, and summary-only — by asking a set of per-token predicates "does any token match", at three separate call sites. git does not work that way, and the mismatch has been the single most productive source of regressions in the arg_tokenizer work (#3681): most review rounds there found at least one, and they were all the same shape — a flag combination taking the wrong route.
Filing the measurements rather than the fix, because the fix belongs on develop after #3681 lands (that PR is what introduced most of these predicates, so doing it before would mean rewriting code that does not exist here yet).
Measured semantics
Probed against git 2.53, LC_ALL=C, in a repo with a modification, a staged create, a rename, a delete, a binary file and a merge commit. Every flag singly across diff/show/log, then all 272 ordered pairs per subcommand.
Result 1 — only suppressors are order-sensitive. 40 ordered pairs per subcommand change shape when reversed, and every one of them has -s or --no-patch on one side. Identical across all three subcommands:
-s -p = PATCH -p -s = NONE
-s --stat = STAT --stat -s = NONE
-s --numstat = NUMSTAT --numstat -s = NONE
-s --raw = RAW --raw -s = NONE
--no-patch -U0 = PATCH -U0 --no-patch = NONE
Result 2 — --quiet is not one of them. Zero order-sensitive pairs. It loses to any shape request from either side and suppresses only when nothing else asked for output. Modelling it as a third spelling of -s silently dropped patches; fixed in #3681, but it is the clearest example of the class.
Result 3 — "last flag wins" is wrong for shape-vs-shape. I tested that model against 343 random 2–4 flag combinations: it predicts 207. Since two shape flags are never order-sensitive (Result 1), what git applies among them is a fixed precedence, not recency:
--name-only --compact-summary -> NAMES (not STAT)
--patch-with-stat --numstat --compact-… -> PATCH (not STAT)
--numstat -W --compact-summary -> NUMSTAT (not STAT)
--check --raw --shortstat -> NONE (not STAT)
So the real model is two rules, not one:
- suppressor vs shape → last one wins
- shape vs shape → fixed precedence, order-independent
Neither is expressible as "does any token match this predicate", which is why each new flag combination has had to be discovered empirically.
Suggested shape of the fix
Fold the tokens once into an output shape, and let the three call sites read the result instead of each re-deriving it:
enum OutputShape { Patch { unified: Option<u32> }, Stat, NumStat, Raw, Names, None, Unparseable }
fn output_shape(sub: Subcommand, tokens: &[Token]) -> OutputShape
Each flag classifies as Suppressor, Sets(shape) or Inert — data, not control flow — and the precedence lattice among Sets is a table derived from the probe above rather than from reading documentation. Unparseable covers the flags that re-shape the columns the compaction keys on (--line-prefix, --output-indicator-*, word diff) and therefore have to take the raw route; note the probe classifier independently rediscovers this, since --line-prefix=X stops matching as a patch.
Before implementing, the precedence lattice needs measuring properly — the four rows above are a refutation of the simple model, not a complete ordering. That measurement is most of the work and is what makes this worth doing as its own change with its own verification budget.
Verification available
The differential harness used for #3681 compares real git / develop / branch across randomised flag combinations on exit code, first stderr line, and body presence, and it is what caught the --quiet case. Any implementation here should have to pass it with zero divergences that are not improvements — that is a much stronger gate than unit tests over the individual predicates, which reported green for every one of these regressions.
- Dominant language
- Rust
- Stars
- 81.1k
- Forks
- 5.1k
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 40
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rtk-ai/rtk
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
bug core output-formatting
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
uv_cmd discards print_with_hint's return value, so the tee hint is not counted and savings read 100% Openanalytics bug python
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
area:cli bug good first issue platform:windows priority:medium resolved-pending-close
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
area:cli bug good first issue priority:high
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
A-linter
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
oxc-project/oxc#26863 ·