List the threads a push leaves behind - #50
Conversation
Findings exclude outdated review threads on purpose: the code they point at is gone, and anything carrying a thread ID blocks the round until it is resolved. After a push that is every thread from the previous head — so an agent that fixed and pushed had no way to close them through crq at all. The workaround was to query GitHub's GraphQL API by hand, which is the one thing the skill tells agents never to do. crq threads <repo> <pr> lists every unresolved thread, outdated ones included, current ones first, each with the thread_id resolve and decline already take. The titles are cleaned up rather than shown raw. Both bots wrap theirs in badge images and HTML, and CodeRabbit prefixes a rubric identical on every finding, so the raw first line shows everything except what the finding says.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds ChangesOpen Review Thread Listing
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant OpenThreads
participant GitHubGraphQL
CLI->>OpenThreads: request repository and pull request threads
OpenThreads->>GitHubGraphQL: load thread data
GitHubGraphQL-->>OpenThreads: return unresolved and resolved threads
OpenThreads-->>CLI: return ordered JSON records
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@cmd/crq/main.go`:
- Around line 201-213: Update the "threads" command after repoPR argument
validation and before service.OpenThreads to call cfg.RequireState(), handling
any returned error through fatal and returning 1. Preserve the existing
OpenThreads and JSON output flow when the configured-state check succeeds.
In `@internal/crq/threads.go`:
- Line 80: Update the markup regular expression used for title sanitization so
it removes only structural Markdown and HTML constructs, while preserving
literal underscores, backticks, asterisks, hashes, and other content characters
such as those in “user_id”.
- Around line 93-100: Update the title-normalization logic around the
strings.Cut handling in threads.go to strip the suffix only when the leading
segment matches the recognized CodeRabbit rubric prefix; leave ordinary
pipe-containing titles such as “Support A | B configuration” unchanged. Add a
test covering this non-rubric title while preserving existing rubric parsing
behavior.
- Around line 101-103: Update the title truncation logic in the surrounding
thread creation flow to count and slice Unicode characters using []rune,
preserving the 120-character limit and ellipsis without splitting multi-byte
characters. Add a test covering a multi-byte title and verifying the result
remains valid UTF-8.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: 0afa6de8-a44e-41d1-9bea-3a0ff2746475
📒 Files selected for processing (6)
README.mdcmd/crq/main.gointernal/crq/threads.gointernal/crq/threads_test.gollms.txtskills/coderabbit-queue/SKILL.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
internal/crq/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
Keep
internal/crqlimited to orchestration and effects wiring;service.gois the only effects executor for CAS writes andPostIssueComment, andDryRunmust write nothing.
Files:
internal/crq/threads.gointernal/crq/threads_test.go
🔇 Additional comments (6)
internal/crq/threads.go (1)
12-75: LGTM!internal/crq/threads_test.go (1)
10-83: LGTM!cmd/crq/main.go (1)
357-357: LGTM!Also applies to: 511-525
README.md (1)
380-405: LGTM!llms.txt (1)
189-195: LGTM!skills/coderabbit-queue/SKILL.md (1)
161-170: LGTM!
Four review findings, all correct. Stripping every underscore, backtick, asterisk and hash turned "Handle user_id" into "Handle user id" — a different identifier. Emphasis is now matched only where it delimits a span, at a boundary, so markup goes and content stays. Any pipe was treated as CodeRabbit's severity rubric, so "Support A | B configuration" became "B configuration". The rubric is matched by its shape now, not by containing a separator a title is allowed to use. Truncation cut bytes, which can split a multi-byte character and leave invalid UTF-8 that JSON renders as a replacement character. It cuts runes. And `crq threads` skipped RequireState, so it failed inside the API instead of saying the configuration was missing.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa1d0d03ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5f0eaa472
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Four findings, one P1 about this repository's own rule: all bot-text knowledge lives in dialect. The badge stripping and rubric handling had encoded four bots' comment formats inside the orchestration layer, where a wording change would bypass the corpus and golden-classification workflow entirely. ThreadTitle moves to dialect, and moving it exposed what living there means: the first bold span is the SEVERITY for Bugbot and Macroscope, so every one of their threads was listed as "High Severity" or "High". It now prefers a heading for the bots that lead with a severity label, and rejects a title that is only a severity word whatever the source. Two smaller ones. The command promises every unresolved thread, humans included, and it copied the author into `bot` — so a person's thread was serialized as `"bot":"alice"`. A bot is named only when the author is one; a human is named as the author. And an outdated thread often keeps only originalLine, which is exactly the case this command exists for, so dropping the location lost the only pointer to what the comment was about.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84138515b9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
Six findings, all about the title reading as something a person can use. Against the real corpus, Bugbot's first bold span is "High Severity" and Macroscope's first line is a severity and a path — so both listed every finding under a label that says nothing. The extraction now prefers a heading, then the bold span, then the first line that reads like prose, and rejects a candidate that is only a severity word or only a file reference. The tests run against the captured comments rather than my idea of them. Whether the author is a reviewer is the CALLER's question now. dialect knows co-reviewers, not the configured primary, and CoReviewerByName also matches the config name — so a human whose GitHub handle is "codex" was serialized as that bot. crq answers it by login. The markup stripping was eating real content: a generic <[^>]+> removed `Map<string, User>` down to "Map", and stripping every # turned "#123" into "123". Only the tags the bots actually use, and emphasis only where it delimits. A person's first line is what they meant to say, so a label they bolded later no longer wins over it. And TitleOf caps at 180 BYTES, which can leave half a rune for JSON to render as a replacement character.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@internal/dialect/title.go`:
- Line 15: Update the markup regular expression in title.go so hash characters
are removed only when they form a Markdown heading marker followed by
whitespace, while preserving literal issue references such as “#123”. Keep the
existing handling for emphasis, code markers, images, and HTML unchanged.
- Around line 54-60: Remove the fallback that returns the first non-empty
cleaned candidate in the title-selection logic, so severity-only candidates
produce an empty title. Update the related title tests to cover “High Severity”
returning “”.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: 61eb841f-2f2e-43a2-b484-9e4b1beaf6c5
📒 Files selected for processing (5)
cmd/crq/main.gointernal/crq/threads.gointernal/crq/threads_test.gointernal/dialect/title.gointernal/dialect/title_test.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
internal/dialect/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
internal/dialect/**/*.go: Keep all bot-text knowledge, wording classifiers, finding parsers, bot-event types, severity/SHA vocabulary, and co-reviewer registry data ininternal/dialect; do not place bot literal wording inengine,state, orcrq.
When adding a bot-message format, modify only the appropriate dialect classifier/parser and add its verbatim corpus fixture and golden classification row.
Add new co-reviewers throughdialect.KnownCoReviewers()and dialect wording helpers; do not enumerate bot identities or per-bot event kinds in engine, state, or crq.
Files:
internal/dialect/title.gointernal/dialect/title_test.go
internal/crq/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
Keep
internal/crqlimited to orchestration and effects wiring;service.gois the only effects executor for CAS writes andPostIssueComment, andDryRunmust write nothing.
Files:
internal/crq/threads_test.gointernal/crq/threads.go
internal/dialect/*_test.go
📄 CodeRabbit inference engine (AGENTS.md)
Add one golden row for each new bot-message or check-run format in
TestGoldenClassification,TestGoldenCoReviewers, orTestGoldenCheckRuns; the row defines the classification specification.
Files:
internal/dialect/title_test.go
🔇 Additional comments (3)
internal/crq/threads.go (1)
12-24: LGTM!Also applies to: 38-85, 87-100
internal/crq/threads_test.go (1)
49-54: LGTM!Also applies to: 56-93
cmd/crq/main.go (1)
207-210: LGTM!Also applies to: 361-361, 516-528
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@coderabbitai review |
✅ Action performedReview finished.
|
A comment whose every candidate reduced to a severity label or a bare path still got a title: the first non-empty candidate. That put "High Severity" back in the listing — exactly the label the extraction exists to reject — and for Macroscope it repeated the path the thread already carries. Empty is the honest answer. Title is omitempty, so the entry falls back to path, line and URL, which say strictly more.
|
@codex review |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@internal/dialect/title_test.go`:
- Around line 121-135: Update the table-driven test around ThreadTitle to store
the normalized expected title for each corpus file and assert exact equality
with got. Remove the strings.HasPrefix/Contains fallback and retain only a
direct comparison against the normalized expected value.
- Around line 127-130: In the corpus-loading setup around the table-driven test,
replace t.Skipf with t.Fatalf when os.ReadFile fails so missing or renamed
fixtures fail the test and preserve required corpus coverage.
In `@internal/dialect/title.go`:
- Around line 110-116: Update the line-filtering loop in the title extraction
function to replace the raw strings.HasPrefix(line, "#") check with the same
whitespace-aware Markdown heading detection used by headingOf. Continue skipping
actual headings while preserving prose such as “#123 breaks parsing,” and leave
the existing usableTitle handling unchanged.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: 526d1df0-7290-4bd8-8ac7-5e159a686be4
📒 Files selected for processing (4)
internal/crq/threads.gointernal/crq/threads_test.gointernal/dialect/title.gointernal/dialect/title_test.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
internal/crq/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
Keep
internal/crqlimited to orchestration and effects wiring;service.gois the only effects executor for CAS writes andPostIssueComment, andDryRunmust write nothing.
Files:
internal/crq/threads_test.gointernal/crq/threads.go
internal/dialect/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
internal/dialect/**/*.go: Keep all bot-text knowledge, wording classifiers, finding parsers, bot-event types, severity/SHA vocabulary, and co-reviewer registry data ininternal/dialect; do not place bot literal wording inengine,state, orcrq.
When adding a bot-message format, modify only the appropriate dialect classifier/parser and add its verbatim corpus fixture and golden classification row.
Add new co-reviewers throughdialect.KnownCoReviewers()and dialect wording helpers; do not enumerate bot identities or per-bot event kinds in engine, state, or crq.
Files:
internal/dialect/title.gointernal/dialect/title_test.go
internal/dialect/*_test.go
📄 CodeRabbit inference engine (AGENTS.md)
Add one golden row for each new bot-message or check-run format in
TestGoldenClassification,TestGoldenCoReviewers, orTestGoldenCheckRuns; the row defines the classification specification.
Files:
internal/dialect/title_test.go
🧠 Learnings (2)
📚 Learning: 2026-07-27T01:11:18.244Z
Learnt from: kristofferR
Repo: kristofferR/coderabbit-queue PR: 57
File: internal/crq/feedback.go:91-92
Timestamp: 2026-07-27T01:11:18.244Z
Learning: When reviewing code in `internal/crq` that deals with bot configuration, keep the separation of concerns intact: `Config.isConfiguredBot(login)` should only be evaluated against the fleet-wide primary `Config.Bot`. Do not override or reinterpret `Config.Bot` based on repo-specific reviewer/co-reviewer data. If repo-added co-reviewers are involved, they must be handled via repo-derived bot sets (e.g., `Config.evidenceBots()`), and not via `isConfiguredBot`. `Config.ForRepo(...)` should adjust co-reviewer-derived fields like `CoBots`, `RequiredBots`, `Reviewers`, and `FeedbackBots`, but intentionally not change the meaning of `Config.Bot` used by `isConfiguredBot`.
Applied to files:
internal/crq/threads_test.gointernal/crq/threads.go
📚 Learning: 2026-07-27T01:11:20.071Z
Learnt from: kristofferR
Repo: kristofferR/coderabbit-queue PR: 57
File: internal/crq/repoconfig.go:163-183
Timestamp: 2026-07-27T01:11:20.071Z
Learning: In internal/crq, treat the “observe → decide → apply” effects restriction as applying only to effects produced by review decisions. Explicit operator mutation commands (e.g., Service.SetReviewers, Service.ClearReviewers, enqueue/cancel flows) are allowed to perform state mutations outside the standard apply path, so review logic should not incorrectly require them to follow observe/decide/apply.
For CRQ_DRY_RUN: it should suppress review requests and fire-record writes, but it must not make explicit configuration/mutation commands (e.g., `crq reviewers set`) silently succeed without persisting the requested changes.
Ensure Service.applyFire revalidates repository reviewer overrides just before posting, to protect against stale/changed overrides since earlier reads.
Applied to files:
internal/crq/threads_test.gointernal/crq/threads.go
🔇 Additional comments (5)
internal/dialect/title.go (1)
8-105: LGTM!Also applies to: 132-145
internal/dialect/title_test.go (1)
4-5: LGTM!Also applies to: 43-72, 94-115, 143-163
internal/crq/threads.go (2)
38-53: LGTM!Also applies to: 55-86, 89-115
54-60: 🎯 Functional CorrectnessNo repository-derived
ForRepoconfig path exists to use here.
Config.ForRepo(...)is not present in this codebase, and repo-scopedFeedbackBots/CoBotsconfiguration is not modeled inConfig, so this classification concern does not apply as described.> Likely an incorrect or invalid review comment.internal/crq/threads_test.go (1)
56-90: LGTM!
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@coderabbitai review |
✅ Action performedReview finished.
|
…threads # Conflicts: # cmd/crq/main.go
* Delete the trigger comments nothing needs any more A PR driven through a dozen rounds collects a dozen "@coderabbitai review" comments and a dozen acknowledgements, which buries the conversation a human came to read. crq now removes its own half of that as rounds progress, and `crq tidy` does it on demand. Deleting a comment crq still reads is how this becomes expensive, so a comment has to clear three guards. It belongs to a round that has PROGRESSED — a live round keeps its command, because that is the comment crq adopts instead of posting another. The bot acted after it, so it was read rather than merely old. And it predates the current head, because adoption only ever considers commands newer than the head commit; delete one of those and the next pump posts a duplicate and buys a second review. Only comments crq posted. Candidates are the command IDs recorded on its own rounds, never anything matching the text — a person's "@coderabbitai review" is their decision to ask, not crq's to erase, and crq posts under the same account so authorship alone cannot tell them apart. Never the bots' own comments. An auto-generated reply can be a rate-limit or skipped-review notice, which crq classifies as evidence and surfaces as a finding, so deleting those would quietly destroy feedback nobody had read yet. A recorded command that is already gone counts as tidied rather than failing: the bot removes some of its own command comments, and a person may have tidied by hand. * Remember the review request each retry replaces A rate-limited round retries, and every retry posts a NEW "@coderabbitai review" — the bot answered the previous one with the rate-limit notice, so it can never be adopted again. crq overwrote CommandID and forgot the old comment, which is why a throttled PR collects a column of identical requests: nothing knew they were there, and tidying could only ever find commands from rounds that had finished. A round now records the commands it supersedes, bounded so a PR that retries all day cannot grow its round without limit, and tidy treats them as spent whichever phase the round is in. They are exempt from the predates-the-head check on purpose: crq's own record that it has posted a successor is stronger evidence than any timestamp. Observed on PR #50 — five heads, nine review requests, three of them for the first head alone. Codex is not affected: it gets one command per head because crq skips the trigger when the bot has already reviewed it. * Only delete the review requests crq wrote itself Adoption was the hole. A round records the command it adopted in exactly the same CommandID as one it posted, so "the command IDs crq recorded on its own rounds" included a person's "@coderabbitai review" — and once the head moved on and the bot had spoken, tidy would delete it. With a maintainer token nothing even objects. A round now records the comments it WROTE, with the reviewer each was addressed to and when it landed, and that list is the only candidate source. Adopting a comment is not writing one. It also replaces the spent-command list: a command missing from the round's current anchors is one the round replaced, which is the same fact without a second field. Four things fall out of carrying the reviewer with the comment: * a co-only round's anchor is the co-reviewer's trigger, not the primary's — unrelated CodeRabbit activity no longer passes for the answer that trigger is still waiting on, and the id stops appearing on the deletion list twice; * a superseded co-reviewer trigger is attributed to the bot that was asked rather than to CodeRabbit; * candidates are filtered against the comments actually on the PR, so a comment tidy already deleted is not DELETEd again on every later pass with the 404 read back as a fresh removal; * state is re-read after the observation and before the deletes, so a round another fleet member started in that window keeps its command. An unreadable head commit now keeps every non-superseded command instead of clearing the guard: the command may well be adoptable again once the read recovers, and deleting it buys a second review. And a round that completes while holding the slot ("cleared") or inside the reviewing sweep is tidied — between them that is most successful rounds, so the automatic cleanup was barely running. * Keep tidy off comments that stopped being trigger comments Four things review found in the tidy pass. A recorded comment ID proves crq wrote that comment, not that it is still the one-line command crq wrote. crq posts under the operator's own account, so anyone can edit it into an explanatory note — and the pass would then delete someone's words as a spent request. The body is now checked against the reviewer's trigger command; anything else, including a command whose config changed since, is kept. A refused delete was only logged, so a caller reading an empty `deleted` could not tell "nothing was spent" from "this token may not delete". The pass still tries every ID and now reports the failures in `.failed[]`. Codex can answer a trigger with nothing but its thumbs-up, and that reaction alone completes the round — leaving no review, event or check for answeredAt to find, so the `@codex review` comment was kept for ever. Tidy observes with no round, so observe() never fetches reactions; they are read here instead, once per candidate nothing else has answered. And the README documented neither `crq tidy` nor `CRQ_TIDY`, so an upgrade started deleting comments with no entry in the documented CLI contract. * Tidy the triggers a force-push and a PR reaction retired Three ways the tidy pass read the PR differently from the code it mirrors. Adoption's cutoff is the head commit date raised to the last force-push, because a force-push can point the PR at a commit object older than the commands made for an earlier head. Tidy compared against the commit date alone, so a rebase onto such a commit kept a trigger no round can ever adopt again — for ever, once the PR merged and the closed-PR guard stopped looking. It now asks for the same cutoff, and TidyInput.HeadAt is renamed AdoptableFrom to say which one it is. Codex answers a command in the PR description by reacting to the PR, and observe() accepts that as the round's completion. Tidy only read reactions on each recorded trigger, so a round that ended that way left no evidence it could see and kept the spent "@codex review" comment. Both of observe's sources count now; the PR's reactions are read at most once per pass, and only when a candidate is still unanswered. And a pump that changed nothing reports "waiting", which tidy treated as progress: every poll of a long-running review bought a second full observation of the PR the pump had just observed. Housekeeping does not get to spend the REST quota the queue runs on. The one "waiting" that does move a round parks it with its commands still live, so it has nothing of its own to remove. * Read the third place a Codex thumbs-up can be A Codex-gated round completes on a +1 left on the trigger, on the PR, or on the command the round fired on — observe() reads all three, and for a round whose primary is CodeRabbit that last one is a different comment from the "@codex review" crq posted beside it. Tidying now reads it too, at most once per candidate nothing cheaper has answered, so a round that ended there stops looking like a trigger nobody read. The README and llms.txt said a comment is removed once it predates the current head; it is the cutoff adoption uses, the head commit raised to the last force-push. * Take the reviewer configuration as a value, like the rest of crq This branch was cut before #51, so it still read the reviewer configuration off the Service: observe with no config argument, and coCommandBodies as a Service method. Both are Config methods now, and the branch stopped compiling the moment main moved under it — the tests here passed only because CI builds the branch, not the merge. Tidy takes a Config through the whole path now: which comments count as a trigger depends on who reviews, so that has to be a value the caller supplies. It reads the fleet configuration today, and per-repo reviewers (#57) can substitute one there in a single line without threading anything new through. * Preserve review evidence when tidying commands * Harden tidy command cleanup * Preserve tidy history and throttle backoff * Retain Codex reaction evidence during tidy * Preserve tombstones after ambiguous deletes * Address tidy review findings --------- Co-authored-by: kristofferR <kristofferR@users.noreply.github.com>
A gap I hit dogfooding this repo today, and one crq itself made unavoidable.
The gap
Findings exclude outdated review threads deliberately: the code they point at is gone, so
re-reporting them is noise, and anything carrying a
thread_idblocks the round until it isresolved.
After a push, every thread from the previous head is outdated. They are still open on the PR, and
still want an answer — but
crq feedbackno longer reports them, socrq resolvehas nothing towork from. The only way to get their IDs was:
gh api graphql -f query='{ repository(...) { pullRequest(...) { reviewThreads(...) ... } } }'which is exactly what the skill tells agents never to do ("Never hand-poll the GitHub API ... that
drains the shared account-wide GitHub REST quota"). crq was forcing the rule it publishes to be
broken.
The command
Every unresolved thread, outdated included, current ones first, each with
thread_id,path,line,bot,outdated,title,url. Read it, decide,crq resolveorcrq decline.Read-only, and one GraphQL query — the same one
Feedbackalready makes.Titles are cleaned rather than shown raw. Both bots wrap theirs in badge images and HTML, and
CodeRabbit prefixes a rubric that is identical on every finding, so the raw first line reads
instead of what the finding says.Live output on this repo's PR #39:
Verification
TestOpenThreadsIncludesOutdatedAndOrdersThempins that a resolved thread is dropped, an outdatedunresolved one is kept (omitting it is the bug), and current threads sort first.
TestThreadTitleReadsAsTextcovers both bots' badge wrapping, CodeRabbit's rubric prefix, a plainbody, and the length cap.
gofmt -l .clean,go vet ./...clean,go test ./... -count=1green.Ref #42
Summary by CodeRabbit
crq threads <repo> <pr>to list all unresolved GitHub review threads, including outdated ones.thread_id, cleaned titles, locations, bot/author info, and links.crq threadsforresolve/decline.