When an author pushes new commits, lines shift. Platforms mark comments attached to changed lines as outdated, and a naive bot posts a fresh comment for the same finding. Good design matches findings by a stable key, updates the existing comment, and resolves it when the issue is gone.
The lifecycle of a finding on a pull request
A finding has four moments: first seen, still present after a push, moved, and fixed. A comment strategy should handle each deliberately.
| Moment | What the bot should do |
|---|---|
| First seen | Post one comment on the line |
| Still present, same line | Do nothing, no repeat |
| Still present, line moved | Keep the thread, update the location if needed |
| Fixed | Resolve the thread or add a one line note |
GitHub's conversations menu on the Files changed tab shows unresolved, resolved and outdated threads, and people with write access or the pull request author can resolve a conversation. A bot that cleans up after itself keeps that menu meaningful.
Match by identity, not by line number
Line numbers change with every edit above the finding. Use a fingerprint built from the rule, the file and a hash of the surrounding code, so the same issue gets the same key after a move. Scanners that upload SARIF can carry partial fingerprints for exactly this purpose, and when they are missing, duplicate alerts appear. See why duplicate alerts appear.
Handle force pushes and rebases
A rebase rewrites commits, and a comment attached to an old commit can lose its anchor. Plan for this by keeping the finding state in the bot, not only in the comment thread. After a force push, re-evaluate all findings against the new head and reconcile: keep, move or resolve.
Avoid the three common failures
- Repeat posting. The same finding comments again on each push. Cause: no stable key.
- Ghost threads. The issue is fixed but the thread stays open and blocks a "resolve all conversations" rule. Cause: the bot never resolves.
- Wrong resolution. The bot resolves a thread because the line changed, not because the issue was fixed. Cause: matching by line.
If your repository requires conversation resolution before merge, ghost threads become a real blocker. Test this case before enabling it.
Keep a record
Even when a thread is resolved, keep the scan result for that commit. An auditor or a retrospective may ask what the check saw at each push. Resolved comments are a presentation detail, and the record is what proves what happened.
Safeguard scan results are tied to the scanned commit so you can compare runs. Try a free scan and rerun it after a change to see the difference.
Quick check
Should the bot delete outdated comments?
Prefer resolving over deleting. Deleted comments lose the history of what was raised and why it was closed.
What if the author disagrees and resolves the thread themselves?
Treat that as a dismissal request. Ask for a reason, record it, and do not repost the finding while the dismissal holds.
Sources
Last reviewed: 19 October 2026.