Skip to content

feat(action): opt-in resolution of the bot's own outdated review threads (#567) - #28

Open
chethanuk wants to merge 4 commits into
mainfrom
feat/issue-567-resolve-outdated
Open

feat(action): opt-in resolution of the bot's own outdated review threads (#567)#28
chethanuk wants to merge 4 commits into
mainfrom
feat/issue-567-resolve-outdated

Conversation

@chethanuk

@chethanuk chethanuk commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Description

When OCR comments inline and the author pushes a fix, the conversations have to be resolved by hand (alibaba#567).

This is the deterministic version of that, not the LLM one. @lizhengfeng101's objection on the issue — that inferring "was this addressed?" from a later diff is hallucination-prone, and that tolerance for false positives is near zero at the last gate before merge — rules out asking a model. So nothing here asks one. The signal is GitHub's own server-computed isOutdated, which GitHub recomputes against the current head and which is force-push and rebase aware.

Adds an opt-in resolve_outdated input, default off:

mode what it does scope needed
false off, default — no behaviour change
report read-only: logs which threads it would resolve and why, plus a comments_resolved_preview output. Mutates nothing. contents: read (today's)
true performs the mutations, comments_resolved output contents: write

How conservative is it?

@stay-foolish-forever asked this directly on the issue, so: a thread is resolved only when all of

  1. GitHub reports it isOutdated and not already resolved.
  2. This action created the thread, proven by the marker OCR already stamps into every inline comment it posts (newCommentId, used today for retry idempotency) — not by the author. Under the default GITHUB_TOKEN every workflow in a repo posts as github-actions[bot], so authorship cannot tell OCR's threads from a sibling workflow's, and under a GitHub App token isBotComment's github-actions[bot] fallback would accept them outright. Only the root comment's body is fetched, via an aliased comments(first: 1) selection.
  3. Every comment in the thread was authored by this token. One human reply and it is never touched — that is a conversation, not a stale marker.
  4. This run parsed OCR's output and finished posting. A failed or unparseable run must never make a PR look "all fixed".
  5. No current-run finding overlaps the thread's original span, reusing the existing lineSpan / sameCommentSpan helpers rather than a second implementation.

(4) is enforced positionally rather than by a flag: the resolve step sits after the parse-failure and zero-findings exits, so a run where the model reported nothing cannot close a batch of threads. That case — model silence reading as "all clear" — is the one worth being paranoid about, and a flag can be got wrong in a later refactor where control flow cannot.

The overlap set in (5) is built from the raw parsed findings rather than from what actually got posted. A finding suppressed by incremental dedupe is still a live finding, so it still vetoes resolving the thread on its own lines.

Two things measured rather than assumed

Both came out of GitHub Actions runs against a real PR, not from docs:

  • resolveReviewThread requires contents: write. Under contents: read + pull-requests: write — exactly what .github/workflows/ocr-review.yml grants — it fails with Resource not accessible by integration. Under contents: write it succeeds. This holds even when the bot resolves a thread it created itself. That is why report mode exists and why it is the mode that works today: asking consumers to grant push access to a review bot is a real cost, and they should be able to see what this would do before paying it.
  • viewerCanResolve is a false negative here. It returned false on both runs, including the one where the mutation then succeeded. So it is never branched on — the mutation is attempted and its failure caught. Gating on it would have made the feature a permanent silent no-op that still passed unit tests.

On a FORBIDDEN or rate-limited response: one core.warning naming the contents: write requirement, stop resolving for the rest of the run, count zero. Never fails the run.

Limitations

  • isOutdated is sticky across a force-push back to a byte-identical anchor: the thread stays outdated with line: null even though the flagged code is unchanged and the finding may still be live. Gate (4) is what covers this — if the finding is still real, this run re-reports it and the overlap veto fires.
  • This repo's own .github/workflows/ocr-review.yml triggers on pull_request_target: types: [opened] only, so it never emits a synchronize event and cannot exercise this. Consumers who review on update can.
  • report mode is deliberately the useful first step: how often the predicate actually fires depends on whether fixes tend to rewrite the flagged lines or fix the cause elsewhere, and that is worth measuring on real PRs before anyone turns on mutations.

Incremental mode is untouched. No minimizeComment, no deletion — nothing here removes history.

Type of Change

  • New feature (non-breaking change that adds functionality)

How Has This Been Tested?

  • make test passes locally
  • Manual testing (describe below)

npm run test:github-actions exits 0 and prints both suites' pass lines; make test and make check are unaffected (no Go changes). All pre-existing post-review-comments.test.js cases are unmodified and green, with new cases added alongside covering each predicate gate, both non-default modes, the human-reply veto, the zero-findings and parse-failure exits resolving nothing, and the FORBIDDEN stop-and-continue path.

The two API behaviours above were verified by live GitHub Actions runs on a throwaway PR under each permission set, not by reading documentation.

Checklist

  • My code follows the project's coding style (go fmt, go vet)
  • I have performed a self-review of my code
  • I have added tests that prove my fix is effective or my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the documentation accordingly (if applicable)
  • I have signed the CLA

Related Issues

closes alibaba#567

…ads (alibaba#567)

When OCR comments inline and the author pushes a fix, the conversations
have to be resolved by hand.

Adds an opt-in `resolve_outdated` input with three modes. Resolution is
fully deterministic — no model is asked whether a finding was addressed.
The signal is GitHub's own server-computed `isOutdated`, which is
recomputed against the current head and is force-push aware.

  false   off. Default. No behaviour change.
  report  read-only. Reports which threads it would resolve and why,
          mutating nothing. Works under the existing contents: read scope.
  true    performs the mutations. Requires contents: write.

A thread is resolved only when all of these hold: GitHub reports it
outdated and unresolved; every comment in it was written by this token
(one human reply and it is left alone — that is a conversation, not a
stale marker); the current run parsed its output and finished posting;
and no current-run finding overlaps the thread's original span.

That last gate is positional rather than a flag: the resolve step sits
after the parse-failure and zero-findings exits, so a run that reported
nothing can never close a batch of threads. The overlap set is built
from the raw parsed findings rather than from what was posted, so a
finding suppressed by incremental dedupe still vetoes resolving its own
thread.

Two behaviours are measured rather than assumed. resolveReviewThread
returns "Resource not accessible by integration" under contents: read
plus pull-requests: write, and succeeds under contents: write — even
when the bot resolves a thread it created itself. And viewerCanResolve
reports false for these tokens even when the mutation then succeeds, so
it is never branched on; the mutation is attempted and its failure
caught. A FORBIDDEN or rate-limited response logs one warning naming the
contents: write requirement, stops resolving for the run, and counts
zero. It never fails the run.
@codeant-ai

codeant-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 7204595 Aug 08, 2026 · 08:30 08:34

@codeant-ai

codeant-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The action adds disabled, report-only, and active modes for outdated bot review-thread handling. The post-review script lists and filters stale threads, resolves eligible threads with GraphQL, reports counts, and continues after resolution errors. Documentation and comprehensive tests cover the new behavior.

Changes

Outdated thread resolution

Layer / File(s) Summary
Action configuration and wiring
action.yml, examples/github_actions/README.md
The action defines the resolve_outdated input and resolution-count outputs. The post-review step receives the setting through the environment and function arguments. The README documents modes, permissions, limits, skip conditions, outputs, and resolution semantics.
Resolution flow and GraphQL cleanup
scripts/github-actions/post-review-comments.js
Successful runs with findings can list, filter, preview, and resolve outdated bot-only threads. Resolution uses pagination, overlap checks, sequential capped mutations, pacing, error classification, and fail-open behavior.
Resolution behavior validation
scripts/github-actions/post-review-comments.test.js
Tests cover eligibility, partial visibility, pagination, caps, pacing, report mode, default-off behavior, empty and parse-failure safeguards, integration wiring, and non-fatal errors.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubAction
  participant runPostReviewComments
  participant resolveOutdatedThreads
  participant GitHubGraphQL
  GitHubAction->>runPostReviewComments: pass resolveOutdated
  runPostReviewComments->>resolveOutdatedThreads: pass current finding spans
  resolveOutdatedThreads->>GitHubGraphQL: list review threads
  GitHubGraphQL-->>resolveOutdatedThreads: return paginated threads
  resolveOutdatedThreads->>GitHubGraphQL: resolve eligible threads
  GitHubGraphQL-->>resolveOutdatedThreads: return mutation results
  resolveOutdatedThreads-->>runPostReviewComments: return resolution statistics
  runPostReviewComments-->>GitHubAction: set resolution outputs
Loading

Suggested reviewers: stay-foolish-forever, lizhengfeng101, nitishagar

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the opt-in resolution of the bot's outdated review threads.
Description check ✅ Passed The description follows the template, explains the feature and safeguards, documents testing, completes the checklist, and links the related issue.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Aug 8, 2026
@codeant-ai

codeant-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

User description

Description

When OCR comments inline and the author pushes a fix, the conversations have to be resolved by hand (alibaba#567).

This is the deterministic version of that, not the LLM one. @lizhengfeng101's objection on the issue — that inferring "was this addressed?" from a later diff is hallucination-prone, and that tolerance for false positives is near zero at the last gate before merge — rules out asking a model. So nothing here asks one. The signal is GitHub's own server-computed isOutdated, which GitHub recomputes against the current head and which is force-push and rebase aware.

Adds an opt-in resolve_outdated input, default off:

mode what it does scope needed
false off, default — no behaviour change
report read-only: logs which threads it would resolve and why, plus a comments_resolved_preview output. Mutates nothing. contents: read (today's)
true performs the mutations, comments_resolved output contents: write

How conservative is it?

@stay-foolish-forever asked this directly on the issue, so: a thread is resolved only when all of

  1. GitHub reports it isOutdated and not already resolved.
  2. Every comment in the thread was authored by this token. One human reply and it is never touched — that is a conversation, not a stale marker.
  3. This run parsed OCR's output and finished posting. A failed or unparseable run must never make a PR look "all fixed".
  4. No current-run finding overlaps the thread's original span, reusing the existing lineSpan / sameCommentSpan helpers rather than a second implementation.

(3) is enforced positionally rather than by a flag: the resolve step sits after the parse-failure and zero-findings exits, so a run where the model reported nothing cannot close a batch of threads. That case — model silence reading as "all clear" — is the one worth being paranoid about, and a flag can be got wrong in a later refactor where control flow cannot.

The overlap set in (4) is built from the raw parsed findings rather than from what actually got posted. A finding suppressed by incremental dedupe is still a live finding, so it still vetoes resolving the thread on its own lines.

Two things measured rather than assumed

Both came out of GitHub Actions runs against a real PR, not from docs:

  • resolveReviewThread requires contents: write. Under contents: read + pull-requests: write — exactly what .github/workflows/ocr-review.yml grants — it fails with Resource not accessible by integration. Under contents: write it succeeds. This holds even when the bot resolves a thread it created itself. That is why report mode exists and why it is the mode that works today: asking consumers to grant push access to a review bot is a real cost, and they should be able to see what this would do before paying it.
  • viewerCanResolve is a false negative here. It returned false on both runs, including the one where the mutation then succeeded. So it is never branched on — the mutation is attempted and its failure caught. Gating on it would have made the feature a permanent silent no-op that still passed unit tests.

On a FORBIDDEN or rate-limited response: one core.warning naming the contents: write requirement, stop resolving for the rest of the run, count zero. Never fails the run.

Limitations

  • isOutdated is sticky across a force-push back to a byte-identical anchor: the thread stays outdated with line: null even though the flagged code is unchanged and the finding may still be live. Gate (4) is what covers this — if the finding is still real, this run re-reports it and the overlap veto fires.
  • This repo's own .github/workflows/ocr-review.yml triggers on pull_request_target: types: [opened] only, so it never emits a synchronize event and cannot exercise this. Consumers who review on update can.
  • report mode is deliberately the useful first step: how often the predicate actually fires depends on whether fixes tend to rewrite the flagged lines or fix the cause elsewhere, and that is worth measuring on real PRs before anyone turns on mutations.

Incremental mode is untouched. No minimizeComment, no deletion — nothing here removes history.

Type of Change

  • New feature (non-breaking change that adds functionality)

How Has This Been Tested?

  • make test passes locally
  • Manual testing (describe below)

npm run test:github-actions exits 0 and prints both suites' pass lines; make test and make check are unaffected (no Go changes). All pre-existing post-review-comments.test.js cases are unmodified and green, with new cases added alongside covering each predicate gate, both non-default modes, the human-reply veto, the zero-findings and parse-failure exits resolving nothing, and the FORBIDDEN stop-and-continue path.

The two API behaviours above were verified by live GitHub Actions runs on a throwaway PR under each permission set, not by reading documentation.

Checklist

  • My code follows the project's coding style (go fmt, go vet)
  • I have performed a self-review of my code
  • I have added tests that prove my fix is effective or my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the documentation accordingly (if applicable)
  • I have signed the CLA

Related Issues

closes alibaba#567


CodeAnt-AI Description

Add opt-in cleanup for outdated bot review threads

What Changed

  • Adds resolve_outdated modes to leave behavior unchanged, preview eligible threads, or resolve them after a successful review with findings.
  • Resolves only outdated, unresolved threads containing exclusively the bot’s comments and no overlap with current findings; threads with human replies or incomplete comment data remain open.
  • Limits resolution to 50 threads per run and stops safely on permission or rate-limit errors without failing the review.
  • Adds comments_resolved and comments_resolved_preview outputs, with documentation and test coverage for pagination and failure handling.

Impact

✅ Fewer stale bot review threads
✅ Human conversations remain open
✅ Review results continue when cleanup permissions are missing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@coderabbitai coderabbitai 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: 2

🧹 Nitpick comments (2)
examples/github_actions/README.md (1)

186-188: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the pacing cost of 'true' mode.

resolveOutdatedThreads sleeps between mutations. The delay comes from OCR_RESOLVE_DELAY and defaults to 1000 ms. A run that hits the 50-thread cap therefore adds about 49 seconds to the job. The section states the cap but not the added run time. OCR_RESOLVE_DELAY is also env-only, so a user cannot set it through with:.

Add one sentence next to the cap so users can predict the job duration before they enable 'true'.

📝 Proposed documentation change
-A thread is left alone whenever **a human has replied** to it, when it is already resolved, when a finding from the current run still covers its lines, or when it has more comments than one API page returns (so a reply the action cannot see is never resolved over). Resolution also runs only after a run that actually produced findings: a run that failed to parse OCR's output, or that reported nothing, resolves nothing — "the model said nothing this time" is not evidence the old findings are gone. At most 50 threads are resolved per run; the rest carry over to the next one.
+A thread is left alone whenever **a human has replied** to it, when it is already resolved, when a finding from the current run still covers its lines, or when it has more comments than one API page returns (so a reply the action cannot see is never resolved over). Resolution also runs only after a run that actually produced findings: a run that failed to parse OCR's output, or that reported nothing, resolves nothing — "the model said nothing this time" is not evidence the old findings are gone. At most 50 threads are resolved per run; the rest carry over to the next one. Mutations are paced one second apart, so a run that hits the cap adds roughly 50 seconds to the job. Set the `OCR_RESOLVE_DELAY` environment variable (milliseconds) on the workflow to change the pacing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/github_actions/README.md` around lines 186 - 188, Add a sentence
beside the 50-thread resolution cap in the README explaining that `'true'` mode
waits between mutations using the env-only `OCR_RESOLVE_DELAY`, which defaults
to 1000 ms, so resolving 50 threads adds approximately 49 seconds to the job.
scripts/github-actions/post-review-comments.js (1)

1279-1308: 🚀 Performance & Scalability | 🔵 Trivial

Consider the added job duration from the default pacing.

OCR_RESOLVE_DELAY defaults to 1000 ms and the loop sleeps between mutations. A run that reaches MAX_RESOLVE_PER_RUN therefore holds the runner for about 49 extra seconds after the review has already been published. The delay is also env-only, so a workflow author cannot tune it through the action inputs.

Two options worth weighing:

  • Expose the delay as an action input so operators can trade pacing against job time.
  • Emit the elapsed resolution time in the summary log line, so a fleet dashboard can see when this step dominates the job duration.

The sequential design itself is correct for a write endpoint. This is about cost visibility, not correctness.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/github-actions/post-review-comments.js` around lines 1279 - 1308,
Expose the resolve pacing delay through an action input and use that value when
initializing delay in the sequential resolution loop around parseNonNegInt and
OCR_RESOLVE_DELAY, while retaining the current default for backward
compatibility. Also include the elapsed resolution duration in the final summary
log so operators can identify runs where thread resolution dominates job time.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/github-actions/post-review-comments.js`:
- Around line 1211-1213: Update the thread status predicate around the span
construction and overlapsHistory call to return "unverified" when both
thread.originalLine and thread.originalStartLine are null or otherwise cannot
produce a usable span. Preserve the existing "overlap" result for detected
history overlap and "resolve" result for verified non-overlapping spans, and
update the corresponding post-review-comments test expectation to "unverified".
- Around line 1202-1205: Normalize GraphQL author logins and REST bot logins
before the isBotComment check in the nodes loop, so equivalent values such as
github-actions and github-actions[bot] are recognized as the same bot and
bot-only threads do not return human_reply. Update isBotComment or its callers
while preserving human-authored comment detection, and add coverage for the
mismatched login formats.

---

Nitpick comments:
In `@examples/github_actions/README.md`:
- Around line 186-188: Add a sentence beside the 50-thread resolution cap in the
README explaining that `'true'` mode waits between mutations using the env-only
`OCR_RESOLVE_DELAY`, which defaults to 1000 ms, so resolving 50 threads adds
approximately 49 seconds to the job.

In `@scripts/github-actions/post-review-comments.js`:
- Around line 1279-1308: Expose the resolve pacing delay through an action input
and use that value when initializing delay in the sequential resolution loop
around parseNonNegInt and OCR_RESOLVE_DELAY, while retaining the current default
for backward compatibility. Also include the elapsed resolution duration in the
final summary log so operators can identify runs where thread resolution
dominates job time.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ff1074fd-0c1f-4038-95f2-4dc3df7ae952

📥 Commits

Reviewing files that changed from the base of the PR and between f8f0851 and 7204595.

📒 Files selected for processing (4)
  • action.yml
  • examples/github_actions/README.md
  • scripts/github-actions/post-review-comments.js
  • scripts/github-actions/post-review-comments.test.js

Comment thread scripts/github-actions/post-review-comments.js
Comment thread scripts/github-actions/post-review-comments.js
for (const c of nodes) {
const login = c && c.author && c.author.login ? c.author.login : "";
if (!isBotComment({ user: { login } }, botLogin)) return "human_reply";
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The ownership check reuses isBotComment, whose unconditional github-actions[bot] suffix fallback treats comments from any workflow using the shared GITHUB_TOKEN identity as this action's comments. In a repository with another automation posting review threads, this can resolve that workflow's outdated threads when resolve_outdated is enabled. Require an action-specific marker or otherwise distinguish comments created by this action before allowing destructive resolution. [security]

Severity Level: Major ⚠️
- ❌ Unrelated GitHub Actions review threads can be resolved.
- ⚠️ Opt-in cleanup may alter another workflow's review state.
- ⚠️ Existing action-specific markers are not used for ownership.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** scripts/github-actions/post-review-comments.js
**Line:** 1205:1205
**Comment:**
	*Security: The ownership check reuses `isBotComment`, whose unconditional `github-actions[bot]` suffix fallback treats comments from any workflow using the shared `GITHUB_TOKEN` identity as this action's comments. In a repository with another automation posting review threads, this can resolve that workflow's outdated threads when `resolve_outdated` is enabled. Require an action-specific marker or otherwise distinguish comments created by this action before allowing destructive resolution.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

// viewerCanResolve reports false for tokens that CAN resolve, so the
// predicate must ignore it entirely (no "cannot_resolve" outcome exists).
{ name: "viewerCanResolve:false is ignored", thread: botThread({ viewerCanResolve: false }), spans: sameLine.slice(0, 0), want: "resolve" },
{ name: "no original line information", thread: botThread({ originalLine: null, originalStartLine: null }), spans: sameLine, want: "resolve" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The test explicitly requires a thread with no original line coordinates to be resolved. Without coordinates, the resolver cannot prove that a current finding does not overlap the old thread, so this expectation codifies unsafe behavior and will prevent the implementation from adopting the conservative unverified veto. Expect an unverified result instead. [security]

Severity Level: Major ⚠️
- ❌ A bot-only outdated thread with missing coordinates can be resolved without an overlap check.
- ⚠️ A current finding may be hidden behind an incorrectly closed thread.
- ⚠️ GitHub review threads expose nullable original-line fields.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** scripts/github-actions/post-review-comments.test.js
**Line:** 3300:3300
**Comment:**
	*Security: The test explicitly requires a thread with no original line coordinates to be resolved. Without coordinates, the resolver cannot prove that a current finding does not overlap the old thread, so this expectation codifies unsafe behavior and will prevent the implementation from adopting the conservative unverified veto. Expect an unverified result instead.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

…le span

Two review findings, both of which made the feature wrong in opposite
directions.

GraphQL's reviewThreads returns a bot's slug ("github-actions") while
getAuthenticatedLogin and isBotComment use REST's suffixed form
("github-actions[bot]"). Confirmed against a live PR: the same comment
reads `github-actions` with __typename "Bot" through GraphQL and
`github-actions[bot]` through REST. Comparing them raw made every one of
our own threads look like a human reply, so nothing would ever have been
resolved and the feature would have looked merely inert. Normalized at
the call site so isBotComment's REST contract stays intact for
incremental mode, its other caller.

A thread with no originalLine and no originalStartLine produced a span
lineSpan cannot build, so overlapsHistory could only ever answer "no
overlap" and the veto was unreachable — the thread resolved on a check
structurally unable to fail. That veto is the entire mitigation for
GitHub reporting a still-live finding's thread as outdated after a
force-push, so an unbuildable span now returns "unverified" and the
thread stays open, exactly as a partial comment view already did.

The table case that asserted "resolve" for the null-line thread had
encoded the bug as expected behaviour; it now expects "unverified", with
cases added for both bot-login shapes and for a User whose login merely
looks bot-ish.
@chethanuk

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Under the default GITHUB_TOKEN every workflow in a repository posts as
github-actions[bot], so authorship cannot distinguish OCR's own review
threads from a sibling workflow's; under a GitHub App token isBotComment's
github-actions[bot] fallback accepts them outright. Gate the destructive
path on the marker OCR already stamps into every inline comment it creates
(newCommentId), fetched via an aliased root-comment selection so only the
one body that can carry the proof crosses the wire.

Reported by CodeAnt on the fork PR.
@chethanuk

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Unknown values already fall back to off, which is the correct default but an
invisible one: a workflow that says 'TRUE' looks configured and does nothing.
Warn so the typo is visible; empty/unset/'false' stay silent as the documented
ways to be off.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI Actions to automatically resolve past comments

1 participant