Skip to content

fix(strands-command): inline full PR diffs within a total budget#63

Open
yonib05 wants to merge 3 commits into
strands-agents:mainfrom
yonib05:fix/pr-diff-truncation
Open

fix(strands-command): inline full PR diffs within a total budget#63
yonib05 wants to merge 3 commits into
strands-agents:mainfrom
yonib05:fix/pr-diff-truncation

Conversation

@yonib05

@yonib05 yonib05 commented Jun 10, 2026

Copy link
Copy Markdown
Member

Problem

get_pr_files capped every changed file's patch at 50 lines:

if len(patch_lines) > 50:
    output += '\n'.join(patch_lines[:50])
    output += f"\n   ... (truncated, {len(patch_lines) - 50} more lines)\n"

The reviewer agent then reasons about a partial diff for any non-trivial
change. A bug introduced on line 60 of a changed file is simply invisible
to it, and the agent gets no signal that anything is missing beyond a
terse "truncated" note. This silently caps review quality on exactly the
larger PRs that most need a careful read.

Fix

Replace the blunt per-file line cap with a total diff character budget:

  • inline each file's full patch until the cumulative budget is reached,
  • once exceeded, list the remaining files (with their add/delete stats)
    and instruct the agent to fetch them on demand via the shell tool,
    rather than cutting a file off mid-diff.

This keeps the original intent (bounding how much diff goes into one
prompt) while ensuring that whatever is inlined is complete, and that
anything omitted is explicitly surfaced instead of hidden.

Tests

tests/test_github_tools.py exercises get_pr_files across the full budget behavior. Verbatim run output:

$ python -m pytest python/tests/test_github_tools.py -v

python/tests/test_github_tools.py::test_get_pr_files_inlines_full_diff_under_budget PASSED
python/tests/test_github_tools.py::test_get_pr_files_inlines_head_of_over_budget_file PASSED
python/tests/test_github_tools.py::test_get_pr_files_mixed_inline_and_overflow PASSED
python/tests/test_github_tools.py::test_get_pr_files_defers_whole_file_when_budget_nearly_exhausted PASSED
python/tests/test_github_tools.py::test_get_pr_files_inlines_patch_exactly_at_budget_boundary PASSED
python/tests/test_github_tools.py::test_get_pr_files_defers_file_when_head_trim_is_empty PASSED
python/tests/test_github_tools.py::test_get_pr_files_handles_binary_file PASSED

7 passed

What each case verifies:

  • inlines_full_diff_under_budget — a 120-line patch (well over the old 50-line cap) is inlined in full, no truncated marker. This case fails against the old code, confirming the regression it guards.
  • inlines_head_of_over_budget_file — a file too large for the remaining budget still gets a line-trimmed head slice plus an explicit "fetch on demand" note, rather than zero diff.
  • mixed_inline_and_overflow — earlier files inline fully while a later file that exceeds the budget is listed for on-demand fetch.
  • defers_whole_file_when_budget_nearly_exhausted — when too little budget remains for a useful head slice, the file is deferred wholesale.
  • inlines_patch_exactly_at_budget_boundary — a patch sized exactly at TOTAL_DIFF_BUDGET_CHARS is inlined (guards the <= boundary against off-by-one).
  • defers_file_when_head_trim_is_empty — a patch whose head trims to empty defers cleanly instead of emitting an empty diff block.
  • handles_binary_file — files with no patch are reported, not crashed on.

Full module suite: 39 passed.

Scope note: this is a unit-level fix to the diff-formatting helper. The budget path is deterministic and fully covered above; no live agent run is required to validate it.

Live validation (end-to-end)

Beyond the unit tests, this fix was exercised in a real reviewer run to prove the behavior that the old per-file truncation hid: a bug located past line 50 of a changed file.

Setup (on a fork, so reviewers can inspect everything):

Result: the agent read the full diff and identified the bug at lines 83–86 — both the inverted >= 0 guard and the wrong + fee_cents sign — then explained the before/after behavior: review comment.

With the pre-fix get_pr_files, lines 51+ of that file were replaced with a ... (truncated, N more lines) marker, so the overdraft logic would have been in the hidden tail and unreachable by the agent. Reading and acting on line 83 confirms the full diff is now inlined.

Note: the live run resolved to the agent's implementer (write) mode rather than read-only review, so it committed a fix rather than only commenting — immaterial to what is being validated here (full-diff consumption past line 50). The fork validation scaffolding (branches, test PR #14, workflow) is intentionally left in place for reviewer inspection.

yonib05 added 3 commits June 10, 2026 12:57
get_pr_files capped every file's patch at 50 lines, so the reviewer
silently lost the tail of any larger change and reasoned about code it
never saw. Replace the per-file line cap with a total character budget:
inline full patches until the budget is reached, then list remaining
files for on-demand fetch instead of truncating mid-file.
…ping it

A file whose patch alone exceeds the budget previously produced no inline
diff at all, leaving the reviewer dependent on fetching it. Inline a
line-trimmed head slice when enough budget remains so there is always some
inline signal, and note the omitted remainder is fetchable. Adds tests for
the partial-head and mixed inline/overflow cases.
Guard the partial-head branch so a patch starting with a newline (whose
line-boundary trim leaves an empty head) is fully deferred instead of
emitting an empty "Diff (head only):" block. Add tests covering the
full-deferral branch, the exact budget boundary, and the empty-head edge,
merge the two near-duplicate over-budget tests, and note the accepted
file-order dependence of the diff budget.
if head:
used += len(head)
omitted = len(patch) - len(head)
overflow.append(f"{filename} (+{additions} -{deletions}, partially shown)")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we write the overflow to disk and let the agent know where it is?


@tool
@log_inputs
def get_pr_files(pr_number: int, repo: str | None = None) -> str:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is PR output?

Can we just leverage the Strands Tool Offloader here and let it manage the truncation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call will swap it should simplify alot

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.

2 participants