Skip to content

Judge the whole PR on every push, not just the newest commit - #83

Merged
mk7luke merged 1 commit into
mainfrom
fix/pr-diff-refresh
Aug 2, 2026
Merged

Judge the whole PR on every push, not just the newest commit#83
mk7luke merged 1 commit into
mainfrom
fix/pr-diff-refresh

Conversation

@mk7luke

@mk7luke mk7luke commented Aug 2, 2026

Copy link
Copy Markdown
Owner

The bug

On a push to an open PR, the incremental review trims context.files to the delta — then hands the model that slice alongside the whole-PR title and description, plus a system-prompt rule that explicitly asks for a PR-level finding when "a claimed change is missing" from the diff. The model does what it's told.

Observed on mk7luke/atlas-timeclock#89: a docs-only follow-up commit turned an approved feature branch into

Claimed overlay implementation is missing from the diff. … The only file in the diff is .env.example.

— CHANGES_REQUESTED, naming the four backend files that had been reviewed and accepted a week earlier.

#81 fixed this for the drift pass only (detectDescriptionDrift gets allReviewableFiles). The main ai.review() call — the one that sets the verdict — kept the same blind spot, and the finding sails past the hallucination verifier because PR-level findings have no path/line and are kept fail-open.

What changed

The model sees the whole PR on every push

  • New ## Already reviewed earlier in this PR (context only — do NOT comment on these) section in buildReviewPrompt, carrying the earlier commits' diffs. It states outright that the diff is partial, that the description covers the earlier work, that absence is not evidence, and that findings go only against Changed Files.
  • buildPriorReviewContext() sizes it against the headroom the delta + related-context left, so it never displaces the diff under review. When there's no room for even one more file it degrades to naming them — most of the value, since the false finding comes from the model believing those files aren't in the PR at all.
  • System prompt: never raise a description-vs-diff finding when the diff shown is partial (incremental, truncated, or budget-omitted).
  • dropContextOnlyFindings() is the deterministic backstop — inline findings against context-only files are dropped, so a push can't re-litigate the whole branch. PR-level findings are untouched; whole-PR reasoning is the point of the context.

Other whole-PR judgments stopped being computed from the delta

These render in the walkthrough comment that every push replaces, so a delta-derived value misreports the branch:

  • Walkthrough + the PR-description summary table (was rewriting a whole-PR summary to cover only the newest commit)
  • Risk score, test-coverage signal (a PR whose tests landed two commits ago read as "🔴 production code added with no test changes"), and the split suggestion

Full reviews are byte-identical to before — every path is gated on previously-reviewed files existing.

Verification

  • npx vitest run392 passed (27 files), including 14 new tests in tests/unit/incremental-scope.test.ts. They fail against the old code.
  • npx tsc --noEmit clean; eslint 0 errors (remaining warnings pre-existing).
  • Reconstructed the exact atlas-timeclock#89 second-review prompt and rendered it: the four backend files now appear with the "do not report as missing" rules.
  • New e2e scenario incremental-full-pr reproduces #89's shape (feature PR → docs-only follow-up commit) with a new reviewBodyNotContains assertion in the harness. Not run — e2e needs a live GitHub App + AI provider, so the model's actual behavior on the new prompt is unverified.

Database / schema changes

None.

🤖 Generated with Claude Code


Summary

Fixed incremental reviews so every push judges the whole PR instead of only the newest commit, by attaching already-reviewed files as read-only prompt context and computing walkthrough, risk, coverage, and split signals from the full branch.

Changes

File Changes
CHANGELOG.md Documented the fix that incremental reviews now judge the whole PR, not just the newest commit.
src/ai/prompt.ts Added buildPriorReviewSection and a system-prompt rule forbidding description-vs-diff findings on partial diffs; injects the prior-review block into the review prompt.
src/reviewer.ts Added buildPriorReviewContext and dropContextOnlyFindings; wires prior context into ai.review, and computes walkthrough, risk, coverage, and split suggestion from the full PR file set on incremental runs.
src/types.ts Introduced PriorReviewContext and optional priorReview on PRContext for incremental read-only context.
tests/e2e/runner.ts Added reviewBodyNotContains expectation evaluation for regression assertions.
tests/e2e/scenarios/incremental-full-pr.ts New e2e scenario reproducing a docs-only follow-up commit that must not claim earlier feature work is missing.
tests/e2e/scenarios/index.ts Registered the incremental-full-pr scenario in the e2e suite.
tests/e2e/types.ts Extended Scenario expectations with optional reviewBodyNotContains needles.
tests/unit/incremental-scope.test.ts Unit tests covering prior-review prompt section, names-only degradation, dropContextOnlyFindings, and buildPriorReviewContext budgeting.

An incremental review trimmed context.files to the delta, then handed the
model that slice alongside the WHOLE-PR title and description — plus a
system-prompt rule asking for a PR-level finding when "a claimed change is
missing". The model duly reported the earlier commits' work as never
written. On mk7luke/atlas-timeclock#89 a docs-only follow-up commit flipped
an approved feature branch to CHANGES_REQUESTED over four files that had
been reviewed and accepted a week earlier. #81 fixed this for the drift
pass; the main review call had the same blind spot, and PR-level findings
skip the hallucination verifier (no path/line ⇒ fail-open).

- Review prompt gains an "Already reviewed earlier in this PR (context
  only)" section carrying the earlier diffs, with explicit rules: the diff
  is partial, the description covers this work too, absence is not evidence,
  comment only on Changed Files.
- Sized against the headroom the delta left (buildPriorReviewContext), so it
  never displaces the diff under review; degrades to naming the files when
  the budget is spent — naming alone is most of the value.
- System prompt: never raise a description-vs-diff finding when the diff
  shown is partial.
- dropContextOnlyFindings() is the deterministic backstop, so a push can't
  re-litigate already-reviewed files.
- The walkthrough (and the PR-description summary it rewrites), risk score,
  coverage signal, and split suggestion now use the full branch too — they
  render in a whole-PR comment that every push replaces, so computing them
  from the delta reported "no test changes" for a PR whose tests landed two
  commits ago.

Full reviews are unchanged: every path is gated on prior files existing.

Tests: 14 new unit tests (tests/unit/incremental-scope.test.ts) covering the
prompt section, the budget degradation, and the backstop; they fail against
the old code. New e2e scenario incremental-full-pr reproduces #89's shape,
with a reviewBodyNotContains assertion added to the harness. Not run — e2e
needs a live GitHub App + AI provider.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@diffsentry

diffsentry Bot commented Aug 2, 2026

Copy link
Copy Markdown

DiffSentry has completed the review — Looks good!

@diffsentry

diffsentry Bot commented Aug 2, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Fixed incremental reviews so every push judges the whole PR instead of only the newest commit, by attaching already-reviewed files as read-only prompt context and computing walkthrough, risk, coverage, and split signals from the full branch.

Changes

Cohort / File(s) Summary
Prior Review Prompt Context
src/ai/prompt.ts, src/types.ts
Added PriorReviewContext types and a prompt section that shows already-reviewed files as read-only context, plus a system rule blocking description-vs-diff findings on partial diffs.
Incremental Review Wiring
src/reviewer.ts
Built and attached budgeted prior context on synchronize runs, dropped inline findings against context-only files, and switched walkthrough/risk/coverage/split inputs to the whole PR file set.
Regression Tests
tests/unit/incremental-scope.test.ts, tests/e2e/scenarios/incremental-full-pr.ts, tests/e2e/scenarios/index.ts, tests/e2e/runner.ts, tests/e2e/types.ts
Added unit coverage for the incremental-scope fix and an e2e scenario plus harness support asserting the bot does not report earlier work as missing.
Changelog
CHANGELOG.md
Recorded the whole-PR incremental review fix under Fixed.

Sequence Diagram(s)

sequenceDiagram
    participant Push as GitHub Push
    participant Reviewer
    participant Budget as Diff Budget
    participant AI as AI Review
    participant Walkthrough as Walkthrough

    Push->>Reviewer: synchronize on open PR
    Reviewer->>Reviewer: partition delta vs already-reviewed files
    Reviewer->>Budget: size prior context from remaining headroom
    Budget-->>Reviewer: patches or names-only prior context
    Reviewer->>AI: review(delta + priorReview context)
    AI-->>Reviewer: findings
    Reviewer->>Reviewer: dropContextOnlyFindings
    Reviewer->>Walkthrough: generate from whole PR files
    Walkthrough-->>Reviewer: summary risk coverage split
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested Labels

bug, enhancement

Risk Assessment

Score: 8/100 — 🟢 Low

Factor Weight Detail
Large change +3 564 lines changed across 9 files
High review effort +5 Effort estimate 4/5

Test Coverage Signal

🟢 242 prod / 303 test lines added.

Source files changed Test files changed Source lines + Test lines +
3 5 242 303

Linked Issues

  • #81 — Stop reporting "no matching diff" for code the model was never shown 🔴
🚥 Pre-merge checks | ✅ 5 | ❌ 0
✅ Passed checks (5 passed)
Check name Status Explanation
PR Title ✅ Passed Imperative verb ('Judge'), 58 chars, no trailing period, no Conventional Commits prefix.
PR Description ✅ Passed Description explains WHAT changed (whole-PR context on incremental reviews, walkthrough/risk/coverage/split from full branch) and WHY (stop false 'missing from diff' findings on push). Links related PRs #89 and #81.
Schema bump ✅ Passed src/storage/db.ts was not modified in this PR; no schema version check required.
Provider parity ✅ Passed src/ai/anthropic.ts was not modified in this PR; no request/response contract changes to propagate to openai.ts or openai-compatible.ts.
Pattern test coverage ✅ Passed Neither src/safety-scanner.ts nor src/pattern-checks.ts was modified in this PR; no new rule to cover.

✏️ Tip: You can configure your own custom pre-merge checks in your .diffsentry.yaml.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Generate docstrings (beta)
  • Push docstring commit to this branch
🧹 Simplify (beta)
  • Push simplification commit to this branch
🪄 Autofix unresolved comments (beta)
  • Push autofix commit to this branch

Comment @diffsentry help to get the list of available commands and usage tips.

@diffsentry diffsentry Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

This PR addresses the incremental-review blind spot comprehensively: the prompt now carries earlier PR files as read-only context, whole-PR summary signals are computed from the full branch, and the new unit/e2e coverage is targeted and convincing. I did not find any correctness or contract regressions in the changed code paths. The implementation is well-scoped, budget-aware, and preserves full-review behavior.


ℹ️ Review info
⚙️ Run configuration

Configuration used: .diffsentry.yaml

Review profile: ASSERTIVE

Run ID: 03b0142d-5098-4572-87ae-932ff1577a04

📥 Commits

Reviewing files at 3efae37 (base SHA unavailable).

📒 Files selected for processing (9)
  • CHANGELOG.md
  • src/ai/prompt.ts
  • src/reviewer.ts
  • src/types.ts
  • tests/e2e/runner.ts
  • tests/e2e/scenarios/incremental-full-pr.ts
  • tests/e2e/scenarios/index.ts
  • tests/e2e/types.ts
  • tests/unit/incremental-scope.test.ts

ℹ️ The primary review model was unavailable; this review was generated by the configured backup provider.

@diffsentry

diffsentry Bot commented Aug 2, 2026

Copy link
Copy Markdown

📌 Status — last updated 3efae37

🟢 Approved

Risk score 8/100 (Low) ▁
Unresolved threads 0
Failing checks 0
Pending checks 1
Files reviewed 9
Updated 2026-08-02 23:04Z

Live-updated by DiffSentry on every push. Use @diffsentry ship for a verdict, @diffsentry timeline for full history.

@mk7luke
mk7luke merged commit 69248bd into main Aug 2, 2026
4 checks passed
@mk7luke
mk7luke deleted the fix/pr-diff-refresh branch August 2, 2026 23:18
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.

1 participant