Skip to content

fix(review): /describe, /changelog, /add-docs run on a truncated diff with no partial-coverage disclosure #296

Description

@devops-thiago

The on-demand AI commands /describe, /changelog, and /add-docs reuse ReviewDiffFormatter (flat line cap, thrillhousebot.review.max-diff-lines) exactly like the review path, but — unlike the review path hardened in #234 and #245 — they silently drop the omitted-file count and never disclose that the output covers only a truncated slice of the diff.

Problem

All three commands run against a diff that ReviewDiffFormatter may truncate, and none of them surface it:

  • /describe and /changelog go through AbstractPrSuggestionGenerator.fetchDiff, which calls diffFormatter.buildDiffString(files) (AbstractPrSuggestionGenerator.java:107). buildDiffString returns only the text and throws away the FormattedDiff.omittedFiles() the formatter already computed.
  • /add-docs calls diffFormatter.buildDiffStringWithStats(files, reviewable).text() (DocGenerationService.java:175) — it holds the full FormattedDiff in hand but discards .omittedFiles() / .truncated().

The formatter already knows the count: FormattedDiff.truncated() / omittedFiles() (ReviewDiffFormatter.java:45-50) and it logs the omission at ReviewDiffFormatter.java:296-298. The review path threads this through to the user via ReviewResult.truncationNotice(int) (ReviewResult.java:129), consumed in VerdictBuilder.java:253 and ReviewPublisher.java:347. The three command generators have zero truncation awareness — grep -niE 'truncat|omitted|partial' over PrDescriptionGenerator.java, ChangelogEntryGenerator.java, DocGenerationService.java, AbstractPrSuggestionGenerator.java returns nothing.

Net effect: on a large PR, the bot posts a PR description / changelog entry / doc suggestions derived from a partial diff and presents them as if they were complete.

Evidence

Dogfood, native 0.3.0-SNAPSHOT, DeepSeek.

On #256 (75 changed files), the logs show the same truncation for all three commands:

WARN  ReviewDiffFormatter — Diff truncated to 5000 lines (max: 5000, 48 files omitted)

/add-docs on that PR then logged:

posted 1 suggestion(s) and 0 note(s)

By contrast, on devops-thiago/MongOCOM#46 (27 files, not truncated), /add-docs logged:

posted 16 suggestion(s) and 2 note(s)

None of the three commands' posted comments on #256 mentioned the 48 omitted files. The low #256 suggestion count was truncation, not an absence of documentable symbols.

Where

  • AbstractPrSuggestionGenerator.java:103-108fetchDiff calls buildDiffString, dropping the omitted count for /describe and /changelog.
  • PrDescriptionGenerator.java:80-93/describe builds the comment body (HEADER + suggestion + FOOTER).
  • ChangelogEntryGenerator.java:92-112/changelog builds the comment body.
  • DocGenerationService.java:175/add-docs calls buildDiffStringWithStats(...).text(), dropping .omittedFiles().
  • CommentCommandService.java:158-160 — routes DESCRIBE / CHANGELOG / ADD_DOCS; handlers at :215, :245, :275.
  • Existing reusable disclosure: ReviewResult.truncationNotice(int) (ReviewResult.java:129).

Proposed fix

Interim (surface what the formatter already knows):

  1. In AbstractPrSuggestionGenerator, keep the FormattedDiff instead of the flattened string: have fetchDiff (or loadInputs) return the omittedFiles count alongside the diff text so /describe and /changelog can see it.
  2. In DocGenerationService.generate, capture the FormattedDiff from buildDiffStringWithStats and read .omittedFiles() rather than calling .text() inline.
  3. When omittedFiles > 0, append a disclosure line to each posted comment, reusing ReviewResult.truncationNotice(omittedFiles) (or an equivalent one-liner: "N file(s) were omitted because the diff exceeded the size limit; this covers only the reviewed portion") so the three surfaces match the review path's wording.

Full (stop truncating):

  1. Route these commands through the token-aware budgeting / map-reduce path once spike(review): define a better large-diff handling strategy #53 / feat(review): whole-PR review via token-aware budgeting + multi-call map-reduce (#53) #256 lands, so on-demand commands no longer run on a flat-capped diff.

Acceptance criteria

  • On a truncated diff, /describe, /changelog, and /add-docs each append a partial-coverage disclosure naming the omitted-file count to their posted comment.
  • The disclosure wording matches the review path (reuse ReviewResult.truncationNotice).
  • Non-truncated case unchanged: no disclosure line is appended when omittedFiles == 0.
  • /add-docs on a truncated PR still posts its suggestions/notes, now with the disclosure.
  • Test coverage for each command's truncated and non-truncated branches.

Related

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions