Skip to content

fix(review): reserve header length in buildUnifiedReviewDiff's no-patch branch - #10345

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
shin-core:fix/review-diff-nopatch-header-budget-10327
Aug 4, 2026
Merged

fix(review): reserve header length in buildUnifiedReviewDiff's no-patch branch#10345
JSONbored merged 1 commit into
JSONbored:mainfrom
shin-core:fix/review-diff-nopatch-header-budget-10327

Conversation

@shin-core

Copy link
Copy Markdown
Contributor

What & why

buildUnifiedReviewDiff builds a size-bounded unified diff for review. The patched-file branch already reserves the header's length against the remaining budget before appending:

if (header.length + body.length + 2 > remaining) {
  body = keepHighSignalHunks(file.patch, remaining - header.length - 4 - truncationNotice.length);
}

The no-patch branch (binary or too-large files) did not — it appended header + suffix unconditionally:

if (!file.patch) {
  diff += `${header}(no inline patch — binary or too large)\n\n`;
  continue;
}

Because the header interpolates file.path, a long enough path makes header.length + suffix.length exceed the file's remaining budget, and the returned diff overflows budget. That breaks the same bounded-output invariant the patched branch upholds — the one asymmetry between the two branches' budget handling.

The fix

Mirror the patched branch's reservation in the no-patch branch: check header.length + suffix.length against remaining before appending, and when it doesn't fit, fall through to the same truncation-notice-and-break path the loop already uses for the remaining < 240 case — rather than silently overflowing budget or silently dropping the file with no visible signal.

if (!file.patch) {
  const suffix = `(no inline patch — binary or too large)\n\n`;
  if (header.length + suffix.length > remaining) {
    diff += truncationNotice;
    break;
  }
  diff += `${header}${suffix}`;
  continue;
}

Unchanged: the patched-file branch's existing logic, and the common case — a patch-less file whose header+suffix fits comfortably renders byte-for-byte as before ("${header}(no inline patch — binary or too large)\n\n"). This is an edge-case fix for a long file.path only.

Tests (test/unit/review-diff.test.ts)

Extends the existing #10017 budget-invariant suite:

  • True branch (the fix): a patch-less file with a ~250-char path and budget: 250remaining clears the < 240 floor but header + suffix (~310) overflows it. Asserts the returned diff's .length <= budget, the truncation notice is present, and the overflowing file was not appended. Fails on main (returns 308 > 250).
  • False branch (regression): a short-path patch-less file with a comfortable budget still renders exactly "### logo.png (added) +0/-0\n(no inline patch — binary or too large)\n\n" with no truncation notice.

Validation

  • Diff line + branch coverage on src/review/review-diff.ts is 100% — both arms of the new header.length + suffix.length > remaining check are exercised (lcov BRDA confirms taken=true and taken=false).
  • npm run typecheck clean; npm run engine-parity:drift-check passes (the DIFF_FILE_PRIORITY twin markers are untouched — 7 pairs agree); npm run dead-exports:check, manifest:drift-check, docs:drift-check clean.
  • git diff --check clean; no schema / migration / generated-artifact change.

Closes #10327

…ch branch

The patched-file branch of buildUnifiedReviewDiff already reserves the header's
length against the remaining budget before appending, but the no-patch branch
(binary/too-large files) appended header + suffix unconditionally. A long enough
file.path made that header overflow the caller's budget, breaking the same
bounded-output invariant the patched branch upholds.

Mirror the patched branch's reservation: when header.length + suffix.length would
exceed the remaining budget, fall through to the existing truncation-notice-and-break
path instead of silently overflowing. The common case (a short path that fits
comfortably) renders byte-for-byte as before.

Closes JSONbored#10327
@shin-core
shin-core requested a review from JSONbored as a code owner August 4, 2026 05:59
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored
JSONbored merged commit c353e9d into JSONbored:main Aug 4, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

review(review-diff): reserve header length in buildUnifiedReviewDiff's no-patch branch

2 participants