Skip to content

[Fix] Scope GitHub sync review to the PR's Files Changed, not the rebase range#49

Merged
daniel-lxs merged 3 commits into
developfrom
fix/sync-review-scope-to-pr-diff
Jul 9, 2026
Merged

[Fix] Scope GitHub sync review to the PR's Files Changed, not the rebase range#49
daniel-lxs merged 3 commits into
developfrom
fix/sync-review-scope-to-pr-diff

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

What problem this solves

Observed on #44 (2026-07-09): after the branch was rebased onto develop, the openmote sync re-review (mode=sync) flagged 3 findings in files the PR's diff never touched — apps/api/src/handlers/ado/index.ts, apps/web/src/components/settings/CommsProviderSection.tsx, packages/cloud-agents/src/server/__tests__/opencode-runtime.test.ts — all inherited from other commits already on develop. The merged PR now permanently shows "3 issues outstanding" for code that isn't the PR's.

Root cause: the sync review computes its since-last-review delta as the GitHub compare lastReviewSha...currentHead, which uses three-dot semantics. After a rebase, lastReviewSha is no longer an ancestor of currentHead, so the range's merge-base is the old base and the diff includes every base-branch commit the rebase pulled in.

What changed

  • githubPrReviewSync.ts now also fetches the PR's authoritative Files Changed (base...head, via gh pr diff) and intersects the range diff and changed-file list with it, so rebased-in base-branch files are dropped from diff_in_range and changed_files_since_last_review. A rebase-only head change that leaves no PR-relevant delta collapses to the existing no-op path.
  • New filterUnifiedDiffToFiles util (keeps only the per-file diff sections whose target path is in the allowed set; leaves a header-less/truncated diff untouched).
  • The review-code skill records the authoritative set as pull_request_changed_files and is instructed to report findings only within it, and to restrict its own local git diff lastReviewSha...HEAD to those paths (disregarding base-branch/rebase hunks) — so the model can't re-import them even when it fetches the delta itself.
  • Documented in workflow-contracts.md.

Validation

New filterUnifiedDiffToFiles unit tests (keep-allowed, drop-all, keep-all, header-less passthrough); updated the pinned skill-content assertion. Full cloud-agents workflow suite green (201 tests); lint + typecheck clean; guidance knowledge-check OK.

🤖 Generated with Claude Code

…ase range

The sync re-review computed its since-last-review delta as
compare(lastReviewSha...currentHead) — three-dot semantics, so after the
branch was rebased onto its base it also contained every commit pulled
in from the base branch. The reviewer then flagged findings in files the
PR never touched (observed on #44: 3 findings in ado/index.ts,
CommsProviderSection.tsx, opencode-runtime.test.ts inherited from
develop), and the merged PR permanently showed them as outstanding.

The sync review now fetches the PR's authoritative Files Changed
(base...head, via gh pr diff) and intersects the range diff and
changed-file list with it, dropping rebased-in base-branch files. A
rebase-only head change with no PR-relevant delta collapses to the
existing no-op path. The review-code skill also records the authoritative
file set (pull_request_changed_files) and is instructed to only report
findings within it and to disregard base-branch/rebase hunks when running
its own local delta diff.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown

No code issues found. See task

  • packages/cloud-agents/src/server/workflows/githubPrReviewSync.ts:388 Filtering the three-dot range to PR file paths still retains the PR's already-reviewed file sections after a rebase, so a rebase-only head change for any non-empty PR will not collapse to no-op and can be reviewed again as net-new.
  • packages/cloud-agents/src/server/workflows/githubPrReviewSync.ts:376 The new no-op decision treats empty changedFiles as authoritative, but both diff helpers return empty changedFiles on fetch failure; a transient gh pr diff or compare API failure would now suppress the delta and commits instead of telling the reviewer to inspect manually.
  • packages/cloud-agents/src/server/workflows/skills/standard/review-code/SKILL.md:834 The new two-dot sync-review instruction, duplicated in the approval variant at packages/cloud-agents/src/server/workflows/skills/standard/review-code/SKILL.md:1145, still lets rebased-in base-branch changes through when the base branch modifies a file that the PR also touches. git diff last_review_sha..HEAD -- <PR files> compares the old reviewed tree with the new rebased tree, so same-file base-branch hunks appear as reviewable new changes even though they are outside the PR's current Files Changed diff.

daniel-lxs and others added 2 commits July 9, 2026 13:57
…base no-op

Addresses the two review findings on #49:

- A fetch failure or too-large diff from either gh pr diff or the compare
  API returns { diff: undefined, changedFiles: [] }, indistinguishable
  from a genuine empty result. The no-op decision now keeps the delta
  (reviewer inspects manually) on failure, and falls back to the unscoped
  range when the PR's authoritative Files Changed cannot be read, instead
  of silently suppressing the delta. Extracted the decision into a pure,
  unit-tested resolveScopedSyncReviewDelta helper.
- Filtering the three-dot range to PR file paths still re-shows the PR's
  own already-reviewed files after a rebase, so it cannot collapse to
  no-op from the API layer. The review-code skill now inspects the delta
  with a two-dot diff (git diff last..head) scoped to the PR files — the
  actual content difference between the reviewed commits, which is empty
  for a rebase-only head change — and marks no_new_delta when it is empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Second review round on #49:

- knip: dropped the unused exported ScopedSyncReviewDelta interface
  (the helper now returns an inline-typed object).
- A two-dot last..head diff still leaks base-branch hunks on files the PR
  also touches: it compares the old reviewed tree with the new rebased
  tree, so a base-branch change to a shared file shows up as a reviewable
  change even though it is outside the PR's base...head Files Changed. The
  only leak-free scope is the PR's own base...head diff. resolveScoped-
  SyncReviewDelta now uses the three-dot range only to pick which PR files
  changed since the last review, and presents the PR's authoritative
  base...head hunks for those files (fed as a pull-request diff, not a
  compare range). The skill makes base...head the sole in-scope change set
  and uses two-dot only to detect the no-op/rebase-only case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daniel-lxs
daniel-lxs merged commit d93d4d4 into develop Jul 9, 2026
@mrubens
mrubens deleted the fix/sync-review-scope-to-pr-diff branch July 12, 2026 04:19
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