## TL;DR
Compare file content, not commit SHAs: after a rebase, compute per-file blob SHAs on both heads and re-review only the files whose content actually changed. Carry prior findings and approvals forward for everything else. A rebase that touches nothing should cost nothing.

## The problem

```text
review agent failed to skip already-approved files after a rebase: wasted budget: how to fix
```

## When to use
- A rebase triggers a full re-review with no content changes
- Force-pushes with identical trees redo all review work
- Findings get re-posted after history rewrites
- Review budgets spike on repos with rebase-heavy workflows

## When not to use
- The rebase resolved conflicts and file contents changed (re-review is correct)
- Files were renamed with modifications (content changed; review them)
- The previous review never completed (there is nothing to carry forward)

## Steps

### 1. Resolve both heads and list changed files between them
```bash
git diff --name-only OLD_HEAD_SHA NEW_HEAD_SHA | tee /tmp/rebase-changed.txt
wc -l /tmp/rebase-changed.txt
```

Expected output: the file list the rebase actually touched. Empty output means a pure history rewrite with zero content change - the whole re-review can be skipped.

### 2. Compare per-file blob SHAs, not commit SHAs
For each file, compare the blob hash at the old head versus the new head. Only files whose blob changed need re-review; identical blobs mean identical content regardless of the new commit SHAs.

Expected output: a short list of truly-changed files, usually a fraction of the PR.

### 3. Carry prior findings and approvals forward
For unchanged files, re-attach the previous run's findings and approval state, marked as carried forward rather than re-reviewed. Do not re-post their comments.

Expected output: the review state after the rebase equals the state before it, minus only the files that changed.

### 4. Supersede stale comments only for changed files
Dismiss or update old inline comments solely on files whose content changed. Leave comments on unchanged files alone.

Expected output: no comment churn on files the rebase did not touch.

### 5. Record the (old-head, new-head) pair
Store the pair in the run metadata. If the same rebase is seen again (repeated force-push of the same tree), it is a no-op. Expected output: idempotent handling of repeated rebases.

## Tool compatibility
- git CLI: `diff --name-only` and blob comparisons between any two SHAs; works everywhere.
- GitHub review APIs: dismissing or updating stale comments per file; github.com and GHES.
- gh CLI 2.x: for fetching head SHAs and managing review comments.

## Variant phrasings

### full re-review after force push with no changes
Same fix. Step 1 alone often resolves it: an empty changed-file list short-circuits the entire run.

### wasted review budget on rebase
Track budget per run and tag runs triggered by rebases; the step-2 blob comparison is what converts them from full cost to near-zero.

### findings re-posted after history rewrite
The carry-forward in step 3 plus per-file supersede in step 4 stop the re-posting without losing the review history.

## Why it happens
Review pipelines key their "already reviewed" state on commit SHAs. A rebase replaces every commit SHA even when file contents are byte-identical, so the pipeline concludes nothing was reviewed and starts over. Content addressing (blob SHAs) instead of commit addressing fixes the identity confusion.

## Edge cases
- Conflict resolution during rebase: blobs change, correctly triggering re-review of those files only.
- Renamed files: match by content hash across the rename so a pure rename does not trigger a full re-review.
- Partial rebases (some commits rewritten): the blob comparison handles this naturally; only rewritten content re-reviews.
- Squash-merge after rebase: the final squash is a new tree; review the squash result once, keyed on its tree SHA.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_XHNCmqQZs9hoPqsCXXwAjQ
