Repository navigation
chore(sync): Conflicted Sync of upstream/develop 2026-09-07 (42 commits), re-adopt #3268 head - #162
Merged
Merged
Conversation
Replace the RTK reference (meta commands, rtk proxy bypass, install verification, branding, hook framing) with a minimal note stating that condensed output is complete/authoritative and commands should be run normally. Removes the runnable command blocks and bypass hint that led agents to run extra commands and re-verify. Claude only.
…nks, raw fallback
Parse the stream into (prologue)(file-header)(hunk)* regions before
classifying: hunk extent comes from the @@ line budget (one old-budget per
parent, so @@@ combined headers parse too), content is classified only
inside hunks, and any structural disagreement (invalid body prefix, budget
over/under-run, budget owed at EOF, malformed @@) falls back to raw
passthrough. Detector precedence is a documented total order on
condense_unified_diff_strict.
Fixes, each with its reproducer from
claudedocs/diff-classifier-review-2026-08-29.md as a test:
- SQL/Lua '-- comment' removals (--- on the wire) no longer dropped
- added '++ text' lines no longer parsed as file headers
- format-patch mbox prose and the '-- ' signature no longer counted
- +++ /dev/null deletions named by their --- side
- binary / rename-only / mode-only sections reported instead of vanishing
- --color input stripped (was: silently empty output), non-UTF-8 stdin
read lossily (was: hard error, no fallback)
- CRLF content bytes survive verbatim (split('\n'), not lines())
- b/ prefix stripped exactly once; timestamps tab-split from header names
- the '... +N more' trailer removed: it claimed truncation that never
happened (all lines were printed above it)
Fixture corpus: 13 real-producer captures (git 2.54, GNU diff) in
tests/fixtures/diff -- multi-file, -U0, -W, rename/delete/binary,
log -p, show --cc, format-patch single/series/cover, diff -u/-ru/-rN,
CRLF. Property tests: every marked body line survives to the output,
counters equal rendered lines, the fallback fires on zero corpus fixtures.
…fixture hygiene - Structural fallback now emits the caller's exact bytes (a lossy UTF-8 decode or ANSI-stripped 'raw' is not raw); the decode-strip-parse-guard pipeline moved into condense_stdin so it is unit-testable. - Dropped the mailer-padding tolerance: a line shorter than the hunk's prefix width now falls back instead of being guessed into context. - Plain-diff fixtures recaptured with relative paths (no local usernames or session ids); copy-only and mode-only sections get real fixtures and a vanish-class test.
…ighten guards - new file mode / deleted file mode sections (an empty file added or removed) get their own notes; previously they vanished silently whenever another file in the stream parsed cleanly. Real fixture captured, fix proven load-bearing by revert. - Signature tolerance (rule 6) now requires the stream to have carried an mbox From separator; a bare '--' in a plain diff falls back raw. - never_worse discrimination by token estimate instead of pointer identity; stdin decoded once (Cow) instead of twice; hunk-body prefix checked on the byte view without a per-line allocation.
- File-level facts outside hunks become note-only entries instead of vanishing while the stream condenses: 'Only in <dir>: <file>' and standalone 'Binary files ... differ' (GNU diff -r), '* Unmerged path' (git diff --ours during a merge), and 'Submodule <a>..<b>' headers. Suppressed inside mbox message regions, where column-0 prose is indistinguishable by value. Real fixtures captured for all four shapes; fix proven load-bearing by revert. - is_mbox_from accepts 64-hex separators: SHA-256 repos' format-patch streams no longer fall back raw wholesale. - .context() on the stdin read and raw-fallback write paths. - Savings comment corrected to the measured corpus numbers (52-87% metadata-heavy, single digits content-heavy); exemption escalation unchanged.
…-8 gate - '\ No newline at end of file' survives to the output (in-hunk and the common new-side position just after the budget closes): it is the only witness of a trailing-newline-only change, which otherwise renders as two byte-identical -/+ lines. Real fixture; proven load-bearing by revert. - Non-UTF-8 stdin now always takes the raw-bytes branch, even when the stream parses: condensing would rewrite content bytes to U+FFFD, and byte fidelity outranks savings. (Base hard-errored here; raw passthrough is strictly better on both counts.) - Doc-comment bounds recorded for the mbox header-pair spoof and the raw-fallback newline append.
- A ---/+++ pair opening a NEW section must be followed by a hunk header (every real producer's is); a stray marked pair left over from a lying budget now falls through to the marked-line detector and raw fallback instead of being consumed as a phantom header, losing both lines. - never_worse guard in condense_stdin compares against the original input, not the ANSI-stripped intermediate. - HUNKLESS_CORPUS pulls the four note-only fixtures into the no-fallback and never-larger property tests; savings comment names its metric.
Review round 2 (KuSh): no maintainer decision is pending on the savings floor — CONTRIBUTING.md is authoritative at 20% as an admission criterion. Drop the stale escalation sentence and cite that bar plus the never-worse invariant directly.
…ar asserted Rule 8's exemption narrows from the whole prologue to the mbox message region only. A stream whose beginning was cut mid-hunk (head-clipped capture, pipe that lost its first chunk) puts real hunk-body lines before the first file header; the prologue exemption silently dropped them while the intact tail condensed into a complete-looking result. Now they force raw passthrough, honoring the parser's disagree->raw contract. mbox commit prose (the format-patch --- separator, bullet lists, quoted hunks) keeps its tolerance; no corpus fixture has stream-start column-0 marked lines, so nothing real regresses. Also pins the CONTRIBUTING.md 20% admission bar as a per-fixture assertion on the metadata-heavy corpus streams, so the percentages cited in the fidelity comment cannot rot.
… --no-prefix names Structure is read through a per-line ANSI/CR-stripped view and content is pushed raw, so escapes that are part of the user's content survive (the file path was already byte-faithful on the same input). Rule 8's mbox tolerance now ends at the first diffstat line: an orphaned hunk body in a hand-edited series falls back raw instead of being dropped as prose, while version notes between `---` and the diffstat stay prose. `diff --git X Y` with X == Y marks a --no-prefix stream whose header names keep their leading a/ b/ (creations and deletions included); the check is confined to the two-path form. The new-side `\ No newline` marker is kept only on the line right after its hunk closes. The dead `!in_prologue` conjunct and the variable behind it are gone. Real `git diff --cached --no-prefix` fixture added to the corpus.
…less region
`condense_unified_diff_strict` ends rule 8's mbox prose exemption at
format-patch's diffstat, detected by `contains(" | ")`. That matches
ordinary commit prose. It fires on this repo's own history: a bullet
reading "- The FEATURES.md `--line-numbers | -n` row was STALE" ends the
exemption, the bullets after it read as lost content, and the stream
falls back raw — 4097 bytes where 1634 condensed would do. Documenting
an option as `long | short` is standard notation, not an edge case.
Anchor the trigger on the count-and-signs right-hand side instead. Nine
real diffstat shapes still end the tolerance, including `Bin`, a bare
count for a pure rename, brace renames and paths containing a pipe.
`past_diffstat` is kept, not replaced. It is load-bearing beyond the
diffstat: it is the only mid-region check, so it is what catches a
stat-ful patch whose *first* section lost its headers while a later one
survived. Five designs that swapped it for a region-close check all lost
that shape — 60 real multi-file commits, 60 raw fallbacks before, 60
silent losses after.
A `--no-stat` patch has no diffstat, so there the exemption is settled
when the region closes, and only for a region that never reached a file
header. Such a region is bodyless by construction — a cover letter, an
`--always` empty commit — or a patch whose body lost its headers, and
only the second is loss. Shape tells them apart: over 111k marked lines
from 698 real diffs, no whole diff is entirely prose-shaped. Measured on
49 real two-patch series, 8 raw fallbacks before, 49 after.
The cost is honest: tightening the trigger gives up the streams the
loose match rescued by accident, when a pipe in a context line inside an
orphan body happened to force a fallback. Those rescues were a side
effect of the bug being fixed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ames, quoted paths Review round 3 on the file-level-fact arms, plus a cold pass on top: - `Only in <dir>: <file>` splits on the FIRST `: ` (GNU diff's separator follows the directory; a filename may carry its own). - Standalone `Binary files X and Y differ` splits at the ` and ` where both sides agree past their first component, so a filename containing ` and ` is not cut, and is named through `header_name` so the `a/`/`b/` strip follows the same decision as a header pair. - `* Unmerged path X` folds into the section git emits for X right after it: one `[file] X (unmerged) (+A -B)` entry instead of two. - `Submodule <path> <a>..<b>` keeps only the path in the name slot (the tokens before the LAST `..` token, so a path containing `..` survives), and the sha-less `Submodule <path> contains ... content` dirty line is a fact too -- it used to be dropped silently beside a condensed sibling. Real fixture `git_diff_submodule_dirty_raw.txt` joins the corpus. - `rename to` / `copy to` is git's exact path; the `+++` pair no longer re-derives it, which stripped a real `b/` directory under `--no-prefix`. - `core.quotepath` wraps non-ASCII paths in quotes on every header line; names are dequoted before the prefix strip. - The header-pair hunk gate applies to open hunkless sections as well: git only emits `---`/`+++` before the first `@@`, so a stray pair there is lost content and falls back raw instead of renaming the section. - `diff --cc X` carries one path and leaves `prefixed` to its header pair. - `past_diffstat` comment states the first-section-mangled shape it alone catches; the ` name | 3` bound says it fires always (the `---` separator is the marked line that follows); the stdin doc says the never-worse check is inlined and why. A/B against 9106d48: 400 `git show` streams byte-identical; 290 format-patch series identical except 12 that fell back raw through a prose pipe and now condense, zero new fallbacks.
…ule range kept GNU diff translates `Only in` and `Binary files … differ` (git translates none of its own lines). Rule 6 read the English spelling only, so on a French machine `diff -ru g1 g2 | rtk diff -` dropped the three translated fact lines as prose and, because a text section still parsed, returned `Some` -- four files became one, silently. Rule 3b now reads GNU diff's per-file `diff <opts> X Y` echo (printed whenever it compares directories) as the mark of a `diff -r` stream. Such a stream carries no prose, so a column-0 line no arm read there is a fact in a language the parser does not speak, and rule 9 returns `None` instead of dropping it. A line dropped before the echo settled the question counts the same way once it does -- `diff -r` may list an `Only in` first. Real fixture `diff_ru_fr_raw.txt` (`LC_ALL=fr_FR.UTF-8`, diffutils 3.10) pins the raw fallback; the English `diff_ru_raw.txt` still parses in full, as do `git log -p` streams whose prologue is prose. The `Submodule <path> <a>..<b>` note now carries the range -- `[file] sub (submodule e139196..b0ac9b1)` -- for parity with the dirty arm's `(submodule, modified content)`.
…dequoted renames `\ No newline at end of file` describes the line directly above it. The parser never renders context lines, so a marker git attached to an unchanged last line landed under the last `-`/`+` line rendered and claimed THAT line lacked a newline -- the one place the output stated something untrue about the diff. The marker is now kept exactly when the line above it was emitted (in-hunk after a `-`/`+`, or on the line right after the budget closed on one), which keeps the witness of a newline-only change and drops a marker that would describe the wrong line. `emitted_at` replaces `closed_at`: the position test is the same for both rules. Real fixture `git_diff_no_newline_raw.txt` carries both shapes. `# HG changeset patch` opens a message region like an mbox `From`, so `hg export`'s column-0 headers and message no longer latch `dropped_prologue` and send the whole changeset raw through its own `diff -r <a> -r <b> <file>` echo. Real fixture `hg_export_raw.txt` (Mercurial 7.0.1) joins the corpus. `rename to`/`copy to` (and their `from`) go through `dequote`, so a `core.quotepath` name has one spelling across a stream. The submodule note keeps the range's direction qualifier: `[file] sub (submodule e139196..b0ac9b1 rewind)`. The body-line replay in `corpus_every_marked_body_line_survives` shares the parser's per-parent presence rule (there is no second formula for combined-diff columns); its doc now says so and names the oracle -- git's header counts -- and it asserts a budget is never still owed at a non-body line or at EOF, so under-consumption fails there too.
…ction) Adds `rtk sqlfluff lint` for SQL linting workflows, particularly dbt projects. Discovered as a savings opportunity via `rtk discover`. - Injects `--format json` automatically; passes through if user sets it - Groups violations by rule (top N) and by file with per-file breakdown - Surfaces first violation location per rule and line numbers per file - Shows fixable count and suggests `sqlfluff fix` when relevant - Passes fix/format/version/parse subcommands through unchanged (capped) - Registers hook rule in `discover/rules.rs` to auto-rewrite `sqlfluff lint` - Preserves exit codes for CI/CD compatibility - dbt-aware path compaction: keeps models/, macros/, seeds/ prefixes Real-world tested on a production dbt project. Tolerates both v3+ `start_line_no` and legacy `line_no` schemas. 17 tests: happy path, edge cases, JSON parse fallback, real schema regression, hook classification/rewrite, and token savings assertion (≥60% verified).
…wiring Address the second-round review on PR rtk-ai#253: - JSON parse failure now passes raw sqlfluff output through unchanged, with an stderr warning, honoring the non-negotiable fallback rule (rust-patterns.md) instead of emitting a truncated hybrid summary. - "first at" rule locations are derived from the original sqlfluff JSON order, not the sorted worst-first file list, so the sample points at the earliest occurrence rather than the first file in the report. - All report sorts are now deterministic: tied rule counts break alphabetically by rule code, tied files by path. - rtk lint sqlfluff now routes through the shared structured filter, with the same format-flag handling as sqlfluff_cmd::run; a user-supplied non-JSON format keeps raw (truncated) output. - Document the joined short-flag gap (-fhuman) as a known limitation to be fixed with the arg-tokenizer migration (rtk-ai#3681). - Add regression tests for fallback passthrough (incl. large, uncapped), original-order first-location, and deterministic tie ordering. Pre-existing, out of scope, tracked separately: ruff_cmd's identical fallback deviation, a shared compact_path/grouping helper across the six duplicated modules, and the bare-sqlfluff discover rule gap (same as ruff).
…, field aliases, README) - F1: gate 'No issues found' on success; surface stderr on failure (lint_cmd) - F2: early_exit_on_failure() so non-zero exit surfaces stderr (sqlfluff_cmd) - F3: add description field + per-violation section (50-line cap, ruff-style) - F4: '+N more rules' overflow after top-rules list - F5: '+N more rules' overflow in per-file breakdown - F6: dual-field line/col deserialization (start_line_no/line_no aliases) - F7: README example with bare-path usage - F8: pointer-only (lockstep comment already in lint_cmd) Test fixture updated to include realistic sqlfluff fields (end_line_no, end_line_pos, fixable) that real output always emits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DVD4ZD5wiSjSsNpKCK6h7q
Resolved: awareness constants vs Pi/OMP rework, InitContext destructures, bun/deno CLI additions, write_if_changed split. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DVD4ZD5wiSjSsNpKCK6h7q
fix(awareness): slim awareness text
…redirects, stage rewrite consolidation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UAVhpAvWDmsEWuLehm9RAo
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UAVhpAvWDmsEWuLehm9RAo
… GNU diff, hg and svn
Review round 7 asked for two things; a producer enumeration and two
adversarial review passes answered for thirty. Every item below has a
real capture in the corpus (81 fixtures now: git 2.47/2.54, diffutils
3.10 and 3.12, Mercurial 7.0, Subversion 1.14, PowerShell) and a test
that fails without the fix.
Silent loss (a file or content line missing while the output looked
complete) -- each now returns `None`, byte-exact raw passthrough:
- GNU sorts its output, so a fact the parser cannot read (`File X is a
fifo ...`, `Symbolic links ... differ`, a translated `Only in`) can
come before the first `Only in` / `Binary files` / `Files` line, and
`-q` streams carry no echo at all. The latch is now `dropped_line` --
any column-0 line dropped as prose outside a message region -- and is
judged once after the loop against `gnu_stream`, which GNU's fact arms
set as well as its echo (hg's echo does not: an `hg log -p --template`
prologue is prose, not a fact).
- `hg export`'s region stayed open until the first header pair and
swallowed `Binary file bin.dat has changed` on a binary-first
changeset. hg's `diff -r` echo (one `-r` from `hg diff`, two from
`hg export` / `hg log -p`) now closes the region, counts as reaching
its body, and the line is a binary fact; rule 6 stays live inside an
hg region. `hg log -p`'s `changeset:` line opens the region like
`# HG changeset patch` does.
- `git diff --word-diff` / `--color-words` hunks whose lines are all
indented carry their `[-x-]{+y+}` markers behind the indent, so the
hunk was booked as context and the file vanished. A hunk that closes
with no `-`/`+` line is not a unified-diff shape (whitespace-ignoring
modes suppress the hunk) -> `None`.
- `git format-patch --submodule=log` puts `Submodule sub a..b:` where a
file section would go, inside the message region where rule 6 is
suppressed. The strict `<hex>..<hex>[ (<how>)]:` shape is admitted
there (`is_submodule_range`); prose never ends a line that way.
- A stream cut off right after `diff --git` / `index` dropped the file
it named: git never emits a header-only section, so one that closes
with nothing behind it -> `None` (`FileEntry::from_git`; `flush`
returns `Option`). git's `index` / `similarity index` lines are
structural and no longer count as dropped prose.
- A plain `svn diff` names a binary only as `Index: b.dat` + `Cannot
display: file marked as a binary type.`, both prose before: the
binary vanished beside its text siblings. `Index: <path>` opens a
section (rule 3c); the notice is its binary note; an `Index:` section
that closes empty is `(no content)` (a copy/move target) unless a
column-0 line was dropped inside it (a localized notice) -> `None`.
- A binary section followed by another producer's header pair was
renamed in place and its `binary` note landed on the next file; a
pair after a binary section opens its own section.
A crash: the shared-tail scan behind `diff --git X Y` and `Binary files
X and Y` compared bytes, and two different multi-byte characters can
share trailing bytes (`😀`/`🙀`, `é`/`©`): the slice landed mid-character
and the process aborted with no output at all. The scan backs off to a
character boundary on both sides.
Names, byte-equal to the real filename under the producer's own root:
- `dequote` decodes git's C quoting (`"caf\303\251.txt"` -> `café.txt`)
instead of stripping the wrapper; a name that would split a `[file]`
line (newline) or is not UTF-8 keeps git's own quoted spelling, with
the prefix stripped inside the quotes, so `rename to`, `diff --cc` and
the header pair agree on one spelling and two Latin-1 names stay two.
- `unquote_shell` decodes diffutils >= 3.11's shell quoting on `Only in`
/ `Binary files` names -- `'…'`, `$'…'` and the `"…"` form it picks
for a name holding a `'`; a quoted directory may itself hold `: `, so
the `Only in` split follows the quoting (`shell_word_len`). 3.10
prints those names bare; a bare `Only in` with more than one `: `
splits at the root the stream already named on its echo, header pairs
or `Binary files` lines. Both generations are in the corpus.
- `diff --git X Y` is split where the sides share the longest tail at a
`/` boundary (`shared_tail`); the first path component before the
tail on each side is that side's prefix (`FileEntry::prefixes`
replaces `prefixed`): `a/`/`b/`, `i/`/`w/` under
`diff.mnemonicPrefix`, `--src-prefix`/`--dst-prefix`, none under
`--no-prefix`. The header pair strips exactly those, so `* Unmerged
path b/inb.txt` folds into its `i/b/inb.txt w/b/inb.txt` section, a
binary under a directory named `x b/` keeps its path, and `git diff
--no-index d1/f d2/f` names `d2/f`. `diff --cc <path>` is kept whole;
`--no-index --no-prefix x.bin y.bin` names `y.bin`.
- GNU diff names files under the roots it was given, never prefixes:
header pairs after a GNU echo and the standalone `Binary files` /
`Files` arms keep them (`diff -ru a b` -> `b/c.txt`, `diff -ru .
../new` -> `../new/x`), splitting `X and Y` by the same shared tail.
- Timestamps are stripped from `---`/`+++` lines only, at the LAST tab
and only when shaped like one of the real producers' (GNU ISO date,
hg `Mon Sep 07 …`, svn `(revision 1)`, git's bare tab), so a name
containing a tab survives even under `hg diff --nodates`.
- An `* Unmerged path` fact git printed unquoted and cut at a newline
folds into its quoted section instead of a phantom entry.
Spurious raw fallbacks on well-formed streams, now condensed: `git log
--stat -p` / `git show --stat -p` (bare `---` followed by a diffstat
line is the separator -- which also drops the old ` name | 3` bound),
`git log --numstat -p` (`-<TAB>-<TAB>` binary rows), `hg log -p` with
and without `--template`, an hg binary-only changeset whose message has
a marked non-prose line, `--format=%B` prose starting with `diff ` (the
GNU echo arm keys on `diff -`), `diff -u` on directories (`Common
subdirectories:` dropped), an svn copy/move target.
Also: GNU `-s` / `-q` facts are entries; a PowerShell-written stream's
UTF-8 BOM is stripped; a submodule both dirty and moved is one entry;
the budget replay in property (a) asserts under-consumption; the docs
list rule 1b and every bound is executable in `documented_bounds_hold`.
…ry points sqlfluff exits 1 whenever it finds violations, which is the normal case this filter exists for. Two changes in the last push read that exit code as failure and so disabled the filter exactly when it had something to compress: - `sqlfluff_cmd` used `early_exit_on_failure()`, which dumps the injected JSON raw. On a 51-file corpus that is 9.8 KB where plain `sqlfluff lint` is 1.1 KB. - `lint_cmd` substituted `result.stderr`, which is always empty: sqlfluff writes even fatal errors to stdout (verified against 2.3.5 and 4.3.0 - `Error: Unknown dialect 'NOPE'` on stdout, stderr empty, exit 2). Every violation was discarded in favour of a 25-byte `SQLFluff: failed (exit 1)`. Both are one bug reached two ways, because both entry points restated the same routing and format-flag logic and were then edited differently. Extract it into `sqlfluff_cmd::plan`, which states once how rtk invokes sqlfluff and how it reads the result back; `lint_cmd` now calls it instead of keeping a copy. The exit code only disambiguates output the filter could not parse, so a fatal error reaches the user verbatim while violations are still summarized. Also in the report: - Rank the `Violations:` section worst-file-first like every section above it. Iterating sqlfluff's emission order and taking the first 50 dropped exactly the file the summary ranked first. - Build only the lines that get printed, instead of every line to keep fifty. - Omit positions sqlfluff did not report rather than fabricating `:0:0`. - Keep two path segments when no dbt root matches, so `migrations/orders.sql` and `reports/orders.sql` stay distinct in the section meant to be opened. - Treat a missing `fixes` key as unknown rather than zero. sqlfluff 2.x omits it entirely, which silently suppressed the `sqlfluff fix` hint. - Rename the savings test to the bound it actually asserts. Tests cover both regressions against real captured output: 4.3.0 for the current field names and fix data, 2.3.5 for the legacy names and the absent `fixes` key.
The consumer-flag cases were a hand-maintained list that grew one literal per review round, so each new spelling was found by review rather than by a test. Generate the spellings from SAFE_PIPE_CONSUMERS instead: every unambiguous long-option prefix getopt_long accepts, each in bare, double-quoted, single-quoted, backslash-escaped and =value form, and every unsafe short flag bare, quoted, escaped and bundled. A consumer added to the table later is covered on arrival. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…d-slim-instructions feat(rewrite): rewrite in pipe when consummer is safe
feat: add rtk sqlfluff lint with JSON filter (~75% token reduction)
…ments-4pky96 fix(diff): region parser for condense_unified_diff — budget-owned hunks, raw fallback
…conflicts Conflicted Sync of upstream/develop ab0cf40 (dev-0.49.0-rc.410) per CONTEXT.md. - src/cmds/git/diff_cmd.rs: upstream verbatim. Upstream merged the fork's own region-parser rework (rtk-ai#3788, rounds 1-8), so every fork-side hunk was either an older round of the same work or the alignment half of the rtk-ai#3268 adoption (Myers compute_diff, Unaligned/Replaced, positional, frame_legend) interleaved with it. The rtk-ai#3268 half is superseded here and re-adopted from the PR's current head in the next commit, attribution preserved. - src/cmds/js/lint_cmd.rs: upstream's sqlfluff dispatch restructure verbatim; the fork's rtk-ai#3567 adoption (bare-path guard in detect_linter) and its fork-authored amendment (failure passthrough in filter_generic_lint) stay, since upstream rtk-ai#3567 is still open. The generic arm keeps `result.success()`. - src/discover/rules.rs: upstream's new pipeline_safety field taken; the fork's rtk-ai#3414 adoption (yadm removed from the git rule's rewrite_prefixes) stays, since upstream rtk-ai#3414 / rtk-ai#3408 are still open. - src/discover/registry.rs: fork test test_rewrite_ls_pipe_skipped dropped. It came from e95207d (already in HEALED_SHAS) and asserted `ls -t | head -1` is never rewritten; upstream's per-rule PipelineSafety now marks ls a safe producer on purpose, so the assertion encoded a superseded design. Writeup: claudedocs/sync-conflict-2026-09-07.md Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
develop now carries the byte-equality verdict (0cb34ac, 428af61), so this branch no longer argues for it. The alignment fix and the reporting that depends on it remain. compute_diff compared line N to line N, so a single inserted or deleted line reported every line after it as modified. This aligns by Myers' greedy edit script, so one insertion reads as one insertion. The script folds into hunks, one per run of differing lines with no matched line between. Both renderers group by hunk: the classic fallback prints one NcM per region, as diff does, because the classic format cannot express which old line became which new line, and rendering the pairing split a region into an NcM plus a trailing NaM that diff never prints. Inside a hunk the condensed render pairs old and new lines by best similarity rather than by position, so an insertion at the head of a run no longer shifts every pairing after it into a rewrite that did not happen. Op::Keep carries a run length. One entry per matched line made the script scale with the file rather than with the change, 45MB of separators for a million-line pair with 700 rewrites. The aligner's trace is one flat vector with each round's bookkeeping stored inline, so MAX_TRACE_CELLS charges what is allocated: a per-round Vec cost 5.8x the cells being counted on a lopsided pair. The bool develop passes into render_diff cannot express the third case the aligner produces, a comparison that ran and then refused to build a listing because it would cost more than the raw text. FileComparison replaces the bool with Identical, InvisibleDifference and Lines, and DiffResult::unaligned carries the refusal reason. An empty change list is not a synonym for identical, and routing a refusal through the identical branch exits 0 on files that differ. The invisible-difference message keeps develop's wording, so the phrase diff_byte_accuracy_test matches on survives, and then names the measured cause instead of stopping at "no line-content change". It is shown whenever the case arises. A fixed token allowance above raw could not be met: the message's shortest form is ~20 tokens and a one-line pair ~2, so the ceiling sat under the message's floor and dropped it on 90% of one-line pairs, printing the two indistinguishable blobs it exists to replace. The render drops the file-pair header and the blank line, names the files in the frame legend by argument position instead of by path, and prints the counts line only once the listing runs to a screenful. On 120 agent-sized diffs the framing cost more than the change list saved: the body alone is 7% smaller than diff, and each line of chrome erased that.
…he cap a refusal hit `pair_rewrites` pairs by similarity, so two similar lines swapped and both edited pair crosswise. The condensed render listed them in file1 order with one number each, which read as two in-place edits and described a file2 that does not exist: `timeout = 60` rendered onto line 2, where `retries = 5` is. A crossed hunk now renders each `~` as `~ N→M`. A hunk that only shifted keeps the single number, since order already says where the new text goes, so output size is unchanged outside a crossing. A refusal by `POSITIONAL_BYTE_CAP` reached the count refusal's wording, so two 3MB single-line files reported "1 lines ... too many to list". Both `Unaligned` refusal variants carry which cap they hit, and the render names it: the byte form states the size of the text it declined to list. Tests: the crossed render as an exact string beside the shifted-only form, a property that rebuilds file2 from the condensed listing over 3,000 random similar-line pairs, and both byte refusal messages as exact strings.
…ff rounds Writeup for the merge of upstream/develop ab0cf40 and the rtk-ai#3268 re-adoption on top of it: every conflict, what upstream's side replaced, the one fork test dropped, real-binary before/after, and the residual upstream rtk-ai#3268 finding the adopted head still carries. HEALED_SHAS gains the fork's region-parser lineage now merged upstream under PR rtk-ai#3788 (5a61595 as ee614e4, plus the five hunk fixes it subsumed) and the ecef036 snapshot of rtk-ai#3268 superseded by the re-adopted head. Delta page regenerated: 51 fixes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Conflicted Sync of
upstream/develop(headab0cf40,dev-0.49.0-rc.410, 42 commits since the 2026-09-05 sync) into forkdevelop, per the CONTEXT.md Conflicted Sync policy: topic branch, upstream wins, only proven-additive fork code survives.Full writeup:
claudedocs/sync-conflict-2026-09-07.md.Commits
8a6658achore(sync): merge upstream/develop (42 commits), upstream wins on 3 conflicts8ca2e0efix(diff): align by LCS and name the cause of an invisible differenced4239ec(re-adoption; two adjacency conflicts resolved as the union, no PR line changed)091e4a5fix(diff): number both files on a crossed rewrite pairing, and name the cap a refusal hit8073112(clean)686af2cdocs(sync): record the 2026-09-07 conflicted sync, heal the merged diff roundsHEALED_SHAS, delta pageConflicts and how each was resolved
src/cmds/git/diff_cmd.rssrc/cmds/js/lint_cmd.rs617ef8e, WoldenMn: bare-path guard indetect_linter) and its amendment (3240075: failure passthrough infilter_generic_lint) survive — upstream rtk-ai#3567 is still open andgit show upstream/develop:src/cmds/js/lint_cmd.rs | grep 'exists()|succeeded'is blank.src/discover/rules.rspipeline_safetyfield on every rulePipelineSafety::ProducerOnlytaken on the git rule; the fork'srewrite_prefixes: &["git"]survives (1d67272, RawNuke, adoption of rtk-ai#3414 — upstream rtk-ai#3408 is still open and upstream's rule still rewritesyadm committortk git commit).Fork code removed or superseded
diff_cmd.rs: the fork's copies of rounds 1-4 (8243d1a,2219c6d,25a17c0,fb5a3dc,5939842) are byte-identical to upstream'sf42eaf9…1b11b52and heal by patch-id;5a61595and the five pre-region-parser hunk fixes (1f64783,8e65037,89cfe86,5bcee1c,6375941) are subsumed by upstream'see614e4and enterHEALED_SHAS. Theecef036snapshot of fix(diff): stop reporting differing files as identical, and align by LCS rtk-ai/rtk#3268 (acbe88c) is superseded by the re-adopted head and entersHEALED_SHAStoo.registry.rs: fork testtest_rewrite_ls_pipe_skippedremoved. It came frome95207d(already healed) and assertedls -t \| head -1is never rewritten; upstream's per-rule safety now markslsa safe producer on purpose. Measured: pipedrtk ls -tprintsgit/wherels -tprintsgit— a trailing/on directories, not the "size columns" the test's comment claimed. Upstream's call; the test encoded a superseded design.Why rtk-ai#3268 is re-adopted whole (not the alignment half alone, as on 2026-09-03)
Ilia's 2026-09-04 rebase narrowed the PR onto upstream's rtk-ai#3469 byte-equality fix:
compare_filesdecides identity oncontent1 == content2first (upstream's check),IDENTICAL_FILES_MESSAGE/render_file_headerare upstream's, and the invisible-difference message opens with upstream's wording.FileComparisonis the third state the aligner needs (ran, then refused to list) that abytes_equalbool cannot carry.src/core/guard.rschanges are doc-only;tests/diff_byte_accuracy_test.rskeeps every upstream assertion and adds a one-line case. Proof of additivity:git show upstream/develop:src/cmds/git/diff_cmd.rs \| grep -n 'FileComparison\|Unaligned\|myers_ops\|frame_legend'is blank.Known residual: upstream rtk-ai#3268 is
CHANGES_REQUESTED(KuSh, 2026-09-07): the frame legend misdescribes crossed~ N→Mpairs and is omitted when the crossing is the only pairing; two non-blocking wording notes. Legend/wording defects in a corner case, no content loss. Refreshes on Ilia's next push, as PR #153 did for the previous head.Repro, real binaries
Before =
~/bin/rtk.exebuilt fromdevelop(5809fb7); after = debug build of091e4a5.Quality gate
x64 host toolchain:
cargo fmt --all -- --checkclean ·cargo clippy --all-targets0 warnings ·cargo test --allexit 0 — 3430 unit tests passed, 0 failed, 8 ignored; all integration suites green. The first run, on the merge commit before the registry test removal, failed exactly that one test (Some("rtk ls -t | head -1")vsNone).Fork Delta
scripts/fork-delta.shregenerated: 51 fixes (page said 61). Five healed by patch-id, seven newHEALED_SHASentries (above).Deliberately not done
rtk lsas a pipeline producer appends/to directories; upstream's choice, recorded, not filed.🤖 Generated with Claude Code