Skip to content
Source
Sign inSign up

[Bug]: Truncated checkpoint turn diffs lack an incomplete-preview notice #36073

Send to my agent
Closedcoygeek(GitHub profile, opens in a new tab) opened this issue 0 comments

Summary

When a checkpoint diff exceeds the server's output limit, the Diff panel renders the returned prefix as a normal turn diff and does not tell the reviewer that changes are missing. The panel should disclose that the turn diff is incomplete, as it does for git and tool-call previews. A focused server test confirmed the checkpoint response carries a truncation marker, and a browser render reproduced the missing notice with that response shape.

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. On commit c00a373491d20ebcef901b81170abfb9f5f757fe, save the script below as repro.sh in the checkout's parent directory, enter the checkout, and run sh ../repro.sh "$PWD".
  2. The script makes a disposable copy of the existing Diff panel browser fixture, selects a completed turn, and supplies a patch ending in the server's truncation marker.
  3. The control assertion confirms first.txt renders from that turn response; the expected-behavior assertion then looks for the incomplete-preview notice.

The final run reproduced the failure once. An earlier run was inconclusive because the isolated HOME hid the installed Playwright browser; a later assertion failure was classified inconclusive by an overly narrow output matcher. Both setup issues were corrected before the final run.

Prerequisites are the checkout's installed dependencies, vp, Node, Python, ripgrep, and the Playwright Chromium headless shell in the normal browser cache or PLAYWRIGHT_BROWSERS_PATH. The script prints runtime versions, confines its state to a temporary directory, removes its uniquely named test on exit, and leaves the checkout unchanged. Exit 0 means the notice appeared, exit 1 means the file rendered but the notice did not, and exit 2 means the run was inconclusive.

Reproduction script: repro.sh
#!/bin/sh
set -eu

checkout=${1:?Pass the checkout path}
browser_cache=${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}
scratch=$(mktemp -d)
test_file="$checkout/apps/web/src/components/turn-diff.y05-01.browser.test.tsx"
cleanup() {
  rm -f "$test_file"
  rm -rf "$scratch"
}
trap cleanup EXIT HUP INT TERM

export HOME="$scratch/home"
export TMPDIR="$scratch/tmp"
export T3CODE_HOME="$scratch/t3"
export PLAYWRIGHT_BROWSERS_PATH="$browser_cache"
mkdir -p "$HOME" "$TMPDIR" "$T3CODE_HOME"
printf 'node: '; node --version
printf 'python: '; python3 --version
printf 'rg: '; rg --version | head -n 1
printf 'vp: '; vp --version

cp "$checkout/apps/web/src/components/DiffPanel.browser.test.tsx" "$test_file"
python3 - "$test_file" <<'PY'
from pathlib import Path
import sys
p = Path(sys.argv[1])
s = p.read_text()
s = s.replace(
    'useThreadCheckpointSummaries: () => [],',
    'useThreadCheckpointSummaries: () => [{ runId: "run" as never, checkpointTurnCount: 1, checkpointRef: "ref" as never, status: "ready", files: [], assistantMessageId: null, completedAt: "2026-01-01T00:00:00Z" }],',
)
s = s.replace(
    'useCheckpointDiff: () => ({ data: null, error: null, isPending: false }),',
    'useCheckpointDiff: () => ({ data: { diff: "diff --git a/first.txt b/first.txt\\n--- a/first.txt\\n+++ b/first.txt\\n@@ -0,0 +1 @@\\n+visible\\n\\n[truncated]" }, error: null, isPending: false }),',
)
s += '''
it("shows that a server-truncated turn patch is incomplete", async () => {
  using context = setup("origin/orphan");
  useDiffPanelStore.getState().selectTurn(context.threadRef, "run" as never);
  await using screen = await render(
    <RegistryContext.Provider value={context.registry}>
      <div style={{ height: 600, display: "flex", flexDirection: "column" }}>
        <DiffPanel composerDraftTarget={context.threadRef} workspaceMutationId={null} visible />
      </div>
    </RegistryContext.Provider>,
  );
  await expect.element(screen.getByText("first.txt", { exact: true }).first()).toBeVisible();
  console.log("CONTROL: rendered first.txt from the truncated checkpoint response");
  await expect.element(screen.getByText("This preview exceeds the size limit. Changes shown are incomplete.", { exact: true })).toBeVisible();
});
'''
p.write_text(s)
PY

set +e
(cd "$checkout" && vp test run apps/web/src/components/turn-diff.y05-01.browser.test.tsx -t 'shows that a server-truncated turn patch is incomplete') >"$scratch/test.log" 2>&1
status=$?
set -e
rg 'CONTROL:|^ FAIL|^Error:|^Caused by:|^ *Tests|^ *Test Files|Unhandled Errors' "$scratch/test.log" || true
if [ "$status" -eq 0 ] && rg -q 'CONTROL: rendered first.txt' "$scratch/test.log" && rg -q 'Tests  1 passed' "$scratch/test.log"; then
  echo 'RESULT: expected behavior'
  exit 0
fi
if rg -q 'CONTROL: rendered first.txt' "$scratch/test.log" && rg -q 'Matcher did not succeed in time' "$scratch/test.log" && rg -q 'Tests  1 failed' "$scratch/test.log" && ! rg -q 'Unhandled Errors' "$scratch/test.log"; then
  echo 'RESULT: defect reproduced'
  exit 1
fi
echo 'RESULT: inconclusive'
exit 2

Expected behavior

The Diff panel should disclose that a server-capped turn patch is incomplete, as it already does for incomplete tool-call and git previews (apps/web/src/components/DiffPanel.tsx#L483-L485, apps/web/src/components/DiffPanel.tsx#L1332-L1339). The file list and line totals derived from the returned prefix should not imply that they cover the whole turn.

Actual behavior

The browser test supplied a valid one-file checkpoint patch followed by the server's \n\n[truncated] marker through a mocked turn-diff response. The file appeared in the Diff panel, but the expected incomplete-preview notice did not. The production query applies a 10,000,000-byte cap and appends that marker on overflow; its return schema contains only the diff string and turn identifiers (apps/server/src/checkpointing/CheckpointDiffQuery.ts#L226-L263, packages/contracts/src/checkpointDiff.ts#L21-L39).

Impact and scope

Impact: P2 - For checkpoint patches above the server cap, a reviewer can miss later files or hunks while the panel presents the visible prefix and its line totals without an incomplete notice.

The cap is 10,000,000 bytes (apps/server/src/vcs/VcsDriver.ts#L25). A closed Android report documents a real 8,200,127-byte single-turn patch, but the frequency of patches above the cap is NOT_ENOUGH_INFO; production usage data would establish it. Inspecting the Git changes outside this panel may recover omitted content, but that workaround was not tested here.

Earliest failure stage

Output or presentation.

Analysis or suspected cause

The existing focused server test shares the turn and full-thread diff budget across real Git batches passed (one test, five skipped). It asserts that the returned turn and full-thread diffs match, stay at or below the byte cap, end in [truncated], and omit a later file (apps/server/src/checkpointing/CheckpointDiffQuery.test.ts#L203-L304).

For a selected turn, the panel reads activeCheckpointDiff.data.diff, but its truncation predicate checks only tool-call and git-preview metadata (apps/web/src/components/DiffPanel.tsx#L478-L486). The notice depends on that predicate (apps/web/src/components/DiffPanel.tsx#L1332-L1339); the header totals come from the rendered files (apps/web/src/components/DiffPanel.tsx#L693-L695, apps/web/src/components/DiffPanel.tsx#L1141-L1148).

Additional context

The current main version of apps/web/src/components/DiffPanel.tsx#L482-L486 retains the same predicate and apps/web/src/components/DiffPanel.tsx#L1326-L1335 notice gate; the current apps/server/src/checkpointing/CheckpointDiffQuery.ts#L227-L246 still appends the marker on overflow. This was checked through GitHub's file contents API without modifying the checkout.

Evidence provenance: observed server test and browser render, with source inspection. Local verification: reproduced. Reproduction completeness: complete. Missing fact: the frequency of production turn patches above the cap is unknown; production usage data would establish it.

Impact

Minor bug or occasional failure

Version or commit

main @ c00a373

Environment

macOS arm64; Node v26.12.1, Python 3.15.2, ripgrep 15.2.0, vp v1.6.0 with local vite-plus v1.4.0 and Vitest v5.0.5; Chromium browser test.

Logs or stack traces

node: v26.12.1
python: Python 3.15.2
rg: ripgrep 15.2.0
vp: vp v1.6.0

Local vite-plus:
  vite-plus  v1.4.0

Tools:
  vite             v8.3.5
  rolldown         v1.2.15
  vitest           v5.0.5
  oxfmt            v0.74.0
  oxlint           v1.89.0
  oxlint-tsgolint  v7.0.2004
  tsdown           v0.23.1

Environment:
  Package manager  pnpm v12.14.0
  Node.js          v26.12.1 (engines.node)
CONTROL: rendered first.txt from the truncated checkpoint response
 FAIL  |@t3tools/web (browser) (chromium)| src/components/turn-diff.y05-01.browser.test.tsx > shows that a server-truncated turn patch is incomplete
    282|   console.log("CONTROL: rendered first.txt from the truncated checkpoi…
Caused by: Error: Matcher did not succeed in time.
 Test Files  1 failed (1)
      Tests  1 failed | 4 skipped (5)
RESULT: defect reproduced

Screenshots, recordings, or supporting files

No response

Workaround

No verified workaround. Inspecting Git changes outside this panel may recover omitted content, but this was not tested.

References

  • https://github.com/pingdotgg/t3code/issues/7431 — its completed repair covers branch and working-tree previews; the selected-turn checkpoint path still lacks an incomplete notice.
  • https://github.com/pingdotgg/t3code/issues/14649 — documents a large turn patch below the checkpoint cap that reached a client.
  • https://github.com/pingdotgg/t3code/pull/10822 — merged repair for progressively loading branch and working-tree review diffs; it does not change the checkpoint turn-diff path.
  • https://github.com/pingdotgg/t3code/pull/18395 — merged server change that caps checkpoint diffs across batches; the client still ignores the resulting marker.
  1. github-actions[bot](GitHub profile, opens in a new tab) added labelsvouch:denounced

  2. tanstack-source added labelsbug

  3. juliusmarminge closed this

Sign in to join this conversation.