Skip to content

Commit 818bb76

Browse files
committed
feat: surface incremental PR review coverage
1 parent 4633ba3 commit 818bb76

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ This roadmap is derived from deep research into Greptile's public docs, blog, MC
9595
56. [x] Add lifecycle-aware PR summaries that explain what still blocks merge.
9696
57. [x] Add a "train the reviewer" callout when thumbs coverage on a review is low.
9797
58. [ ] Add review-change comparisons so users can diff one review run against the next on the same PR.
98-
59. [ ] Add better surfacing for incremental PR reviews so users know when only the delta was reviewed.
98+
59. [x] Add better surfacing for incremental PR reviews so users know when only the delta was reviewed.
9999
60. [ ] Add discussion workflows that can convert repeated human comments into candidate rules or context snippets.
100100

101101
## 7. Analytics, Reporting, and Quality Dashboards
@@ -169,4 +169,5 @@ This roadmap is derived from deep research into Greptile's public docs, blog, MC
169169
- [x] Add structured custom context and per-path instruction editors to the Settings review context workflow.
170170
- [x] Expose latest-review PR comment search with unresolved, resolved, and dismissed lifecycle filters through the API.
171171
- [x] Close TODO drift for existing comment lifecycle update APIs now that read and write surfaces are both shipped.
172+
- [x] Make PR readiness explicitly call out incremental review coverage when newer commits were not part of the latest pass.
172173
- [ ] Commit and push each validated checkpoint before moving to the next epic.

web/src/components/PrReadinessSummary.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ const READINESS_LABELS: Record<MergeReadiness, string> = {
2424
export function PrReadinessSummary({ readiness, isLoading = false, error, onOpenReview }: Props) {
2525
const latestReview = readiness?.latest_review
2626
const summary = latestReview?.summary
27+
const isIncrementalReview = Boolean(
28+
readiness?.current_head_sha
29+
&& latestReview?.reviewed_head_sha
30+
&& readiness.current_head_sha !== latestReview.reviewed_head_sha,
31+
)
2732

2833
return (
2934
<div className="mb-4 rounded-lg border border-border-subtle bg-surface p-3">
@@ -64,6 +69,17 @@ export function PrReadinessSummary({ readiness, isLoading = false, error, onOpen
6469
</div>
6570
) : (
6671
<>
72+
{isIncrementalReview && readiness?.current_head_sha && latestReview?.reviewed_head_sha && (
73+
<div className="mb-3 rounded border border-accent/20 bg-accent/5 p-3">
74+
<div className="text-[11px] font-medium text-accent mb-1">Incremental review coverage</div>
75+
<div className="text-[11px] text-text-secondary">
76+
DiffScope last reviewed PR head <span className="font-code text-text-primary">{shortSha(latestReview.reviewed_head_sha)}</span>,
77+
but GitHub is now at <span className="font-code text-text-primary">{shortSha(readiness.current_head_sha)}</span>.
78+
This readiness summary does not include the newer delta yet.
79+
</div>
80+
</div>
81+
)}
82+
6783
<div className="flex flex-wrap items-center gap-2 mb-3">
6884
<span className={`text-[10px] px-2 py-0.5 rounded font-code ${READINESS_STYLES[summary.merge_readiness]}`}>
6985
{READINESS_LABELS[summary.merge_readiness]}

web/src/components/__tests__/PrReadinessSummary.test.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,19 @@ describe('PrReadinessSummary', () => {
6767
render(<PrReadinessSummary readiness={makeSnapshot()} />)
6868

6969
expect(screen.getByText('Needs Attention')).toBeInTheDocument()
70+
expect(screen.getByText('Incremental review coverage')).toBeInTheDocument()
71+
expect(screen.getByText(/does not include the newer delta yet/i)).toBeInTheDocument()
7072
expect(screen.getByText('Open blockers')).toBeInTheDocument()
7173
expect(screen.getByText('2')).toBeInTheDocument()
7274
expect(screen.getByText('2 blocking findings remain open.')).toBeInTheDocument()
73-
expect(screen.getByText('0123456789ab')).toBeInTheDocument()
74-
expect(screen.getByText('fedcba987654')).toBeInTheDocument()
75+
expect(screen.getAllByText('0123456789ab')).toHaveLength(2)
76+
expect(screen.getAllByText('fedcba987654')).toHaveLength(2)
77+
})
78+
79+
it('does not show the incremental callout when the latest review matches the current head', () => {
80+
render(<PrReadinessSummary readiness={makeSnapshot({ current_head_sha: 'fedcba9876543210' })} />)
81+
82+
expect(screen.queryByText('Incremental review coverage')).not.toBeInTheDocument()
7583
})
7684

7785
it('opens the latest review when requested', async () => {

0 commit comments

Comments
 (0)