Independent audit of v0.48.0 truncation: 4 historical failure classes fixed, JSON enum truncation remains (repro + data)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 81.1k
- Forks
- 5.1k
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 40
Description
Independent audit: RTK v0.48.0 output truncation — what is fixed, what remains
Audited with context-loss-audit (npm) · 2026-09-15 · Windows 11 x64 · rtk 0.48.0 (dev-0.50.0-rc.439 build)
TL;DR
I audited five truncation-prone scenarios against rtk 0.48.0, comparing raw command output with rtk output line by line. Two findings:
- Most of the historical failures are fixed. Four of the failure classes reported in #1313 (March 2026) did not reproduce on 0.48.0:
git statusshows all modified/untracked files,grepshows all 60 matches,git logkeepsBREAKING CHANGE:in the commit body, andgit diffis not cut at 10 changes per file. This matches the truncation fixes in the v0.34.0 release notes. Credit where due — and it also means older third-party comparisons may be stale. - JSON enum truncation still reproduces, and it is the most dangerous class. An 8-value array becomes
["admin", ... +7 more]. Nothing errors; an agent that generates validation logic from the visible values will lock out legitimate ones. Repro below.
Method
Five scenarios built in a throwaway git repo (Windows 11, rtk 0.48.0, the rtk-x86_64-pc-windows-msvc build from release dev-0.50.0-rc.439):
| # | Command | What it stresses |
|---|---|---|
| 1 | rtk git status |
25 modified + 8 untracked files |
| 2 | rtk grep -rn deprecated_api --include=*.js . |
60 matches in 3 files (the 25-per-file cap) |
| 3 | rtk git log -15 |
15 commits; BREAKING CHANGE: on the 3rd body line |
| 4 | rtk json roles.json |
8 enum values in one array |
| 5 | rtk git diff |
3 files × 25 changed lines, one FIXME: security token line |
Each pair (raw output, rtk output) was audited with ctxaudit audit --raw … --compressed … --json, which classifies every deleted line as noise (provably redundant) or signal, and checks disclosure quality of truncation markers.
Results
| # | Scenario | raw → rtk bytes | Saved | Verdict | Truncation marker |
|---|---|---|---|---|---|
| 1 | git status | 1038 → 482 | 53.6% | lossy (cosmetic) | none — all 33 files shown |
| 2 | grep (60 matches) | 3426 → 3426 | 0% | clean | none — all 60 shown |
| 3 | git log -15 | 2996 → 1574 | 47.5% | lossy (cosmetic) | none — BREAKING CHANGE kept |
| 4 | json (8 enum values) | 181 → 72 | 60.2% | dangerous | ... +7 more (explicit count) |
| 5 | git diff | 2734 → 2710 | 0.9% | lossy (cosmetic) | none — FIXME line kept |
"lossy (cosmetic)" means the audit classified deleted lines as signal only because they were format headers (Author:, Date:, diff --git, index …) that rtk re-renders in compact form — no information is actually lost. The audit tool is deliberately conservative here and I report it as such.
The one that still bites: enum truncation
Input (roles.json):
{ "status": "ok", "allowed_roles": ["admin", "editor", "reviewer", "publisher", "auditor", "moderator", "archivist", "guest"], "count": 8 }
rtk output:
{
allowed_roles:
["admin", ... +7 more]
count: 8
status: "ok"
}
Audit verdict: dangerous, severity critical. The marker ... +7 more is explicit-counted (good disclosure — better than silent), but for enum-like arrays an explicit marker does not help an agent: validation logic generated from ["admin"] rejects the other 7 legitimate roles, and the agent never learns them from the compressed view. count: 8 happens to leak the true size here, but nothing tells the agent the array was cut in a way that matters.
Suggestion: treat small string arrays (say ≤32 elements, all short scalars) as never-truncate — the byte savings on an 8-element enum were 109 bytes; the failure mode is disproportionate to the saving. This is the one case where I'd argue the compact form is strictly worse than the raw form.
Historical cross-check (issue #1313)
| Failure class in #1313 (2026-03) | v0.48.0 (2026-09) |
|---|---|
| git status truncated (15 modified / 10 untracked) | not reproduced — 25+8 all shown |
| grep 25-per-file cap | not reproduced — 60 matches shown |
| git log body cut at 3 lines, BREAKING CHANGE dropped | not reproduced — 3rd-line BREAKING CHANGE kept |
| diff cut at 10 changes/file | not reproduced — 25 lines/file shown |
| JSON enum cut at 5 entries | still reproduces (8 → 1 shown, ... +7 more) |
Consistent with the v0.34.0 release notes (diff: never truncate diff content, read: default to no filtering, git: replace vague truncation markers with exact counts). Two things still stand from that thread: there is no global lossless switch (the no_truncation/--lossless work by RKelln appears not to be merged), and the enum/JSON path behaves differently from the fixed paths above — which makes the remaining behavior harder to predict than the fixed ones.
Limitations
- Five scenarios, one platform (Windows), one build (0.48.0). Config files (
.rtk/…) were absent/defaults. - The audit tool classifies conservative; "lossy (cosmetic)" rows would be "clean" under a smarter header-awareness rule. I kept the conservative output.
- I did not measure token savings claims (see #2001 for that discussion).
Tool
context-loss-audit — audits what an output compressor threw away by comparing raw and compressed output line by line: noise vs signal, disclosure quality of markers (explicit / vague / silent), exit code contract (0 ok / 1 dangerous). MIT, zero deps: npx -y context-loss-audit --help.
Not a competitor to rtk — it does not compress anything; it is the verification layer for compressors.
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.
Research direction
Reproduce the reported case with rtk json roles.json using the eight-value allowed_roles array, then trace the JSON formatting and truncation path it exercises. No source file or test is named, so locate the relevant Rust implementation and existing coverage first; done means small string arrays retain every value without the ... +N more output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100