I Stopped Eyeballing Agent Diffs, and the 2.8.0 View Limits Are Why
Version 2.8.0 caps how much of a file and how much of a large history diff you can view. Losing the ability to scroll to the end forced a better split: let a script decide what machines can catch, and spend human attention only on what they cannot. Includes a working script and the defects it found in a real repository.
The scroll stopped partway through the diff. Version 2.8.0, released on August 12, added caps on how much of a file the viewer will render and how much of a large history diff it will show. The caps shipped alongside a fix for crashes in conversations containing large command output, so on the stability side they are welcome.
The problem was that I had been working under an assumption: that I read everything an agent touched. Hitting the cap made me notice that the assumption had never actually been tested. Back when I could see all of it, was I really seeing all of it?
What I Was Missing While I Could Still See Everything
The answer took one command. As an indie developer I run a set of technical blogs, and the Japanese-language repository alone holds 1,006 MDX articles. I counted how many stray backslash escapes were sitting inside published code blocks.
Twenty-eight files, 130 lines. They looked like this:
// what readers were actually servedif (\!researchOutput.sources || researchOutput.sources.length === 0) {
\! is not valid JavaScript. Anyone copying that line gets a syntax error immediately. The backslash came from shell history-expansion escaping when the file was written through a shell, and it simply stayed there.
None of those lines were ever hidden. I looked at a diff before every commit, which means I scrolled past that screen 130 separate times. The view cap did not hide anything from me. It made visible the part I had only believed I was reading.
Reading Effort Does Not Scale With Diff Size
Once I looked at the structure, the failure stopped being surprising.
Adding one article means two files, Japanese and English. Articles in this repository run to a median of 211 lines, with the largest at 1,265. A single addition produces a diff somewhere between 400 and 2,000 lines. Mix in edits to existing articles and it grows from there.
The number of lines a person can read attentively does not grow with the diff. What grows is the speed at which you feel like you have read them. A two-character anomaly like \! is exactly the kind of thing that disappears at that speed.
Defect
Machine detection
Human detection
Stray escapes, broken syntax
Reliable
Degrades with diff size
Bare URLs, broken markup
Reliable
Same
Links to pages that do not exist
Reliable
Effectively impossible
Prose that contradicts the code below it
No
Yes
Whether the claim is actually true
No
Yes
I had been assigning myself the top half of that table. That was the real mistake, and the cap was the nudge to fix the split.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦You will be able to clear the parts of an agent's change that must not slip through, without reading the whole diff
✦You will be able to separate the defects a machine can catch from the ones only you can catch, before broken code reaches your readers
✦You will be able to add a review step whose cost stays flat no matter how large the change is
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
The new rule is simple. Stop handing a raw diff to a human. Produce two things instead:
A digest with a fixed length. It carries what a machine already decided, plus pointers to where a human should start.
The full patch, written to a file. Never discarded, but never opened by default.
The fixed length is what matters. Whether the change is 400 lines or 4,000, the first thing you read is the same size. Review time stops tracking diff size.
Here is the script I actually use.
#!/usr/bin/env bash# review-digest.sh — split a diff into a one-screen digest and a full artifact# usage: ./review-digest.sh inspect uncommitted work# ./review-digest.sh origin/main inspect against a revisionset -uo pipefailBASE="${1:-}"OUT_DIR="${REVIEW_OUT_DIR:-.review}"mkdir -p "$OUT_DIR"FULL="$OUT_DIR/diff-full.patch"if [ -n "$BASE" ]; then git diff "$BASE" > "$FULL"; STATUS=$? STAT=$(git diff --stat "$BASE" | tail -1) NUMSTAT=$(git diff --numstat "$BASE")else # make untracked files visible to diff (see below) git add -N . >/dev/null 2>&1 || true git diff HEAD > "$FULL"; STATUS=$? STAT=$(git diff --stat HEAD | tail -1) NUMSTAT=$(git diff --numstat HEAD)fiif [ "$STATUS" -ne 0 ]; then echo "git diff failed (exit=$STATUS)" >&2 exit "$STATUS"fi# added lines only, so removed defects are not re-reportedADDED=$(grep -E '^\+[^+]' "$FULL" || true)E_BANG=$(printf '%s\n' "$ADDED" | grep -c '\\!' || true)BARE=$(printf '%s\n' "$ADDED" | grep -E '(^|[[:space:]])https?://' \ | grep -vE '\]\(|<https?://|"https?://' | grep -c . || true)MDTBL=$(printf '%s\n' "$ADDED" | grep -cE '^\+[[:space:]]*\|[-: |]+\|[[:space:]]*$' || true)echo "== change size =="echo " ${STAT:- (no changes)}"echoecho "== machine findings (fix these before opening the full patch) =="echo " stray \\! escapes : ${E_BANG} lines"echo " bare URLs : ${BARE} lines"echo " markdown table rules : ${MDTBL} lines"echoecho "== needs human eyes (largest changes first) =="printf '%s\n' "$NUMSTAT" | sort -rn | head -5 | while read -r add del path; do [ -z "${path:-}" ] && continue printf ' %5s+ %5s- %s\n' "$add" "$del" "$path"doneechoecho "full patch: $FULL ($(wc -l < "$FULL") lines)"# exit non-zero when anything was found[ "${E_BANG:-0}" -eq 0 ] && [ "${BARE:-0}" -eq 0 ] && [ "${MDTBL:-0}" -eq 0 ]
Dropping in a file that contains all three defects produces this:
== change size == 1 file changed, 3 insertions(+)== machine findings (fix these before opening the full patch) == stray \! escapes : 1 lines bare URLs : 1 lines markdown table rules : 1 lines== needs human eyes (largest changes first) == 3+ 0- content/articles/ja/tips/_probe.mdxfull patch: .review/diff-full.patch (9 lines)
Exit code 1. Twelve lines to understand the situation and know what to fix.
The First Version Found Nothing at All
The first time I ran the script, all three counters read zero. This was immediately after I had planted a file containing all three defects.
The cause is git diff HEAD: untracked files do not appear in a diff. When an agent creates a new file, its entire contents fall outside the check. Newly created files are the ones you most want inspected, and by default they pass through untouched.
The fix is the git add -N . in the script above. Intent-to-add registers the file's existence in the index without staging its contents, so the body shows up as added lines while leaving your later git add behavior alone.
Command
Untracked files
git diff
Not shown
git diff HEAD
Not shown
git add -N . then git diff HEAD
Shown as added lines
A gate you believe is running while it inspects nothing is a real failure mode. Whenever you add one, feed it an input that must fail and confirm that it does. Agent-written files slipping past checks shows up in another form in why agent output gets swallowed by .gitignore.
Piping the Digest to head Throws the Verdict Away
One more thing surfaced after a few days of use. The digest grew a little, so I trimmed it at the call site:
./review-digest.sh | head -20 # the verdict is now gone
A pipeline exits with the status of its last command. head succeeds, so even when the script returns 1 the caller receives 0. Findings are detected and nothing stops.
Keeping the digest short is the script's job, so the call site should just run it. When trimming is unavoidable, resolve the verdict first:
if ./review-digest.sh > .review/digest.txt; then echo "no machine findings"else head -20 .review/digest.txt # trim only after the verdict is capturedfi
Once the digest passes, I open only the top two or three files by change size, and I look strictly for things a machine cannot judge:
Does the prose say the same thing as the code beneath it?
Is the reason for the chosen approach written down anywhere?
Was the described behavior actually verified?
The dangerous code an agent writes is rarely the code that fails to parse. It is the code that parses cleanly while drifting slightly from its own description. Machines catch the first category reliably; only people catch the second. Since splitting the roles, I notice the second kind more often. Reading everything meant spending my attention before I ever got there.
How much context to carry in the first place is a separate decision, covered in context strategy and its cost for agents. This piece sits one step earlier, on the human side of the handoff.
Living With the Caps
The 2.8.0 caps apply to the viewer and to large history diffs. They do not remove the times you genuinely need the whole thing. My split looks like this:
Situation
What I open
Routine review
Digest only; top files if warranted
Digest exited non-zero
Just the offending lines, via grep
A bug whose cause is unclear
The saved .review/diff-full.patch, in an editor
The full patch is on disk, so it is there when I want it. The cap is on the viewer, not on the data. Once that distinction was clear, the change stopped feeling like a restriction and started feeling like a different default.
Three Steps to Put This in Place
Setup takes about fifteen minutes. This is the order I used.
1. Drop the script in and ignore its output directory
Put review-digest.sh at the repository root or under scripts/, and make it executable. Add .review/ to .gitignore. Skip that and the saved patch lands in the next diff, which grows with every run.
2. Feed it something that must fail, and watch it fail
Skipping this is how you end up with the detector that detects nothing. Write a throwaway file holding one line of each defect, run the script, and confirm the exit code is 1.
printf 'if (\\!ok) {}\nhttps://example.com\n| --- | --- |\n' > _probe.md./review-digest.sh; echo "exit=$?" # exit=1 means it is workingrm _probe.md
3. Put it ahead of your existing checks
In a production pipeline, place it before the expensive steps — tests, builds, linters. There is no reason to spend a full build on a two-character anomaly. Catching it earlier avoids that build entirely, which is where most of the saved wall-clock time comes from.
./review-digest.sh || { echo "machine findings; fixing first"; exit 1; }npm run lint && npm test
Nothing existing has to be replaced; the digest only goes in front. Runtime is essentially flat regardless of diff size — under a second in my setup, and the same on a 3,000-line diff.
What to Do Next
If you keep a similar workflow, run grep -rc '\\!' across your published code once. A zero is one less thing to worry about. Anything above zero is the kind of defect you can clear the same afternoon.
I still have only three checks in the digest and I am adding more. If you have found a check worth including, I would like to hear about it.
Share
Thank You for Reading
Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.