Skip to content

Hold pr_review.py merge on a Running Hosted Review and Route Declined Qodo Findings to a Dismiss Request - #3809

Merged
ptr727 merged 6 commits into
developfrom
burndown/2252-merge-gate-reviews
Nov 2, 2026
Merged

ptr727 merged 6 commits into
developfrom
burndown/2252-merge-gate-reviews

Conversation

@ptr727

@ptr727 ptr727 commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two Merge Gate gaps pr_review.py merge hit on PlexCleaner pull requests.

A hosted review still running holds the merge (#3789). merge squash-merged a feature pull request while CodeRabbit was still reviewing its head. That happened because an UNSTABLE merge state let an unrequired check stop holding the wait.

  • check_nodes now records who posted each check. That is a StatusContext's creator login, newly read by the query, or a CheckRun's app slug.
  • hosted_reviews_running names each CodeRabbit or Qodo check on the head still settling. It matches by the poster or by a context named for the reviewer. The reviewers come from OTHER_REVIEWERS. It skips a reviewer whose newest output is a rate limit posted or edited since the check began, so that state still clears. An older limit the reviewer has moved past does not. The held read now carries each comment's updatedAt for that.
  • wait holds an attested head on such a check whatever the merge state reads. Its CHECKS_PENDING line then adds (reviewing: <name>).
  • merge's fresh read refuses it as CHECKS_PENDING, which routes redrive. That covers a head wait does not poll and a review that starts after the gate read.
  • A merge run inside the write scope that merged nothing and routes to redrive or the maintainer now prints pending= before next=. It names each check on the head that has neither passed nor failed, from a fresh read. So a pull request handed to the maintainer names what still runs.
  • A hosted status that has not registered on the head yet is not held. That second factor from Hold pr_review.py merge While a CodeRabbit Review of the Head Is Still Running #3789 needs a design choice, filed as Hold pr_review.py merge for a Hosted Review Whose Status Has Not Registered Yet #3806.

Qodo findings are answered with a dismiss request (#2252). Per the maintainer's answer on #2252, qodo_open keeps reading Qodo's own badge.

  • The digest's Qodo remedy text no longer says to answer in the conversation, which never adds the badge. It says Qodo marks a fixed finding Resolved itself. For a disproved one, the --ack comment's body mentions @<Qodo's login> and asks it to dismiss that finding by its number, with the reason. The number comes from the findings comment.
  • pr-review-conduct Merge Gate item 3 and drive-pr step 4 say the same thing. drive-pr routes an UNTHREADED_FINDINGS line naming qodo_open to that answer rather than to a blocked merge.
  • pr-review-conduct item 2 states the hosted-review hold.

The live check #2252 asks for is not part of this change. It confirms on a PlexCleaner pull request that a dismiss request adds the badge, which wording Qodo accepts, and which number it wants. So #2252 stays open.

scripts/README.md is held by another group in this round, so its pr_merge.py, wait, and findings paragraphs are not updated here. #3805 tracks that.

Line counts stay under every ceiling: pr_review.py 2171 of 2200, pr_review_answers.py 402 of 450, pr_review_checks.py 435 of 450, pr_merge.py 246 of 250.

Local-review finding outcomes

  • introduced, listed on the opening push: limited_since dated a rate limit by the newest edit across every reviewer comment, so a summary comment edited as a review starts could clear the hold. Fixed in f38355e, which compares the edit time of the node rate_limited_by reads, with a test for that case.
  • Copilot, [P1] Hold every unfinished hosted check: fixed in 7eb8ee6 and 75b4dd1. The hold now reads every shape short of a pass or a failure, so a hosted check queued past the pickup grace, waiting, or a stale record still holds. Its thread was already resolved when the fix landed.

Verification

  • tests/test_pr_review.py (550), tests/test_pr_merge.py (70), tests/test_pr_review_copilot.py, tests/test_pr_review_size.py, tests/test_pr_cleanup.py, and tests/test_build_dist.py pass.
  • New cases cover the poster each check carries and each way a hosted check matches. They also cover the rate-limit clear and an older limit that does not clear. They cover the hold on CLEAN, UNSTABLE, and HAS_HOOKS, and merge's CHECKS_PENDING refusal. The pending= line, its unread form, and its absence on an out-of-scope refusal are covered, and so is the Qodo dismiss remedy.
  • ruff format and check, mypy, the prose gate, repo_gate.py --check eol, and build_dist.py --check are clean.

Closes on promotion: #3789

🤖 Generated with Claude Code

ptr727 and others added 3 commits November 2, 2026 08:28
…smiss Request

`wait` now holds an attested head while a CodeRabbit or Qodo check on it is
still settling, whatever the merge state reads, and `merge` refuses it as
CHECKS_PENDING. A reviewer whose newest output is its rate limit holds
nothing. A gate refusal in `merge` prints `pending=` with each check still
running, so a pull request handed to the maintainer names what is not done.

Qodo's remedy text and the drive-pr and pr-review-conduct skills now say
that only Qodo's badge closes its finding. A disproved one is answered with
a comment mentioning Qodo that asks it to dismiss the finding by number,
with the reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tie the rate-limit clear to a limit posted since the check began, so an
older limit a reviewer has moved past no longer releases its running
review. Print `pending=` on every in-scope refusal routed to redrive or
the maintainer, read through `checks_settling` rather than a near copy.
Derive the hosted reviewers from `OTHER_REVIEWERS`, name Qodo's login in
the dismiss remedy, and stop calling a threaded Qodo finding unthreaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodeRabbit rewrites its one summary comment in place, so a limit edited
into it after a push kept the comment's first creation time and held the
new head's pending status as a running review. The held read now carries
each comment's updatedAt, and the rate-limit clear compares that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings November 2, 2026 16:44
@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head fb9519a2ab74624ca917a9e6f2a940f7e7d9cc3e, the content this pull request carries at that commit against develop, and it recorded 1 finding.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

`limited_since` took the newest edit across every reviewer comment, so a
summary comment CodeRabbit edits as a review starts could date an older
rate-limit reply and clear the running review's hold. It now picks the
newest output as `rate_limited_by` does and compares that node's own edit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head f38355e305b7b6d014df954bdf130b6144568b55, the content this pull request carries at that commit against develop, and it recorded 1 finding.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Two critical issues can allow merges to proceed while the selected rate-limit review or hosted checks are still incomplete, so the gating logic must be corrected.

2 open issues
What changed in this PR

This PR strengthens Merge Gate handling for active CodeRabbit and Qodo reviews, adds pending-check diagnostics, and documents the Qodo dismissal-request workflow across skill distributions.

Changes:

  • Tracks check posters and holds merges while hosted reviews remain unfinished.
  • Reports pending checks during merge refusals.
  • Updates Qodo finding remedies and synchronized skill guidance.
  • Adds regression coverage for hosted reviews, rate limits, pending checks, and merge routing.

This pull request requires changes.

Review findings:

  • scripts/pr_review_checks.py: [P1, critical, 4 votes] compare the selected rate-limit node’s timestamp; [P1, critical, 1 vote] hold every unfinished hosted check; [P2, moderate, 1 vote] evaluate hosted-review holds before the BLOCKED short circuit.
  • scripts/pr_merge.py: [P1, moderate, 1 vote] handle GraphQLError during the pending read; [P2, moderate, 1 vote] treat truncated check rollups as unread.
File Description
tests/​test_pr_review.py Tests hosted-review detection, rate-limit handling, pending checks, and Qodo remedies.
tests/​test_pr_merge.py Tests merge holds, pending diagnostics, and refusal routing.
scripts/​pr_review.py Integrates hosted-review data into queries, wait handling, and reporting.
scripts/​pr_review_checks.py Normalizes check posters and detects hosted reviews still settling.
scripts/​pr_review_answers.py Adds hosted-review gate findings and Qodo dismissal guidance.
scripts/​pr_merge.py Adds fresh pending-check reporting during merge refusal handling.
.github/​skills/​pr-review-conduct/​SKILL.md Documents hosted-review holds and Qodo dismissal requests.
.github/​skills/​drive-pr/​SKILL.md Routes hosted-review holds and Qodo findings through the driving workflow.
.claude-plugin/​fleet-skills/​skills/​pr-review-conduct/​SKILL.md Generated Claude distribution of the review-conduct guidance.
.claude-plugin/​fleet-skills/​skills/​drive-pr/​SKILL.md Generated Claude distribution of the drive guidance.
.claude-plugin/​fleet-skills/​.source-digests/​pr-review-conduct Updates the generated review-conduct source digest.
.claude-plugin/​fleet-skills/​.source-digests/​drive-pr Updates the generated drive source digest.
.agents/​skills/​pr-review-conduct/​SKILL.md Updates the canonical review-conduct skill.
.agents/​skills/​drive-pr/​SKILL.md Updates the canonical drive skill.

Review effort: Lite

Comment thread scripts/pr_review_checks.py Resolved
Comment thread scripts/pr_review_checks.py Resolved
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.83%. Comparing base (23c7d78) to head (75b4dd1).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3809      +/-   ##
===========================================
+ Coverage    82.72%   82.83%   +0.10%     
===========================================
  Files           29       29              
  Lines         9629     9686      +57     
===========================================
+ Hits          7966     8023      +57     
  Misses        1663     1663              
Flag Coverage Δ
python-3.13 82.83% <100.00%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

ptr727 and others added 2 commits November 2, 2026 09:19
A CodeRabbit or Qodo check left queued past the pickup grace, waiting on
its environment, or a stale record has still posted no review, yet the
hold read only the settling shapes and released it. The hold now reads
every shape short of a pass or a failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 75b4dd13a52a7caefd01a96af4783a359901e3d8, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@ptr727
ptr727 merged commit 2690b87 into develop Nov 2, 2026
13 checks passed
@ptr727
ptr727 deleted the burndown/2252-merge-gate-reviews branch November 2, 2026 17:36
ptr727 added a commit that referenced this pull request Nov 3, 2026
…rge on a Running Hosted Review, and Gate Skill Description Length (#3843)

Promotes the changes merged into `develop` since promotion #3797 to
`main`, the end of an away-mode backlog burndown.

- [#3803](#3803) exempts
the Roslyn embedded-language marker (`// lang=json`, `language=`) from
the prose gate's comment rules as a tool directive.
- [#3807](#3807) has
`local_review.py record` take `--report`, the file the reviewer wrote,
bind the pass to its sha256, and derive the finding count from it.
`status` gains `reportPath`.
- [#3809](#3809) holds
`pr_review.py merge` while a hosted review is still running on the head,
and routes a declined Qodo finding to a dismiss request.
- [#3811](#3811) dates an
anchored `intentRef` by the section its anchor names, and lets a
`driftNote` acknowledge a verified intent advisory.
- [#3816](#3816) moves the
null GraphQL node check into the shared `gh_graphql` transport as
`NullNodeError`.
- [#3818](#3818) explains
the workspace-edit default in `GOVERNANCE.md` and names the aggregator's
expression form.
- [#3822](#3822) moves the
abandon discard to the `backlog-burndown` orchestrator, aligns the
abandoned-branch delete, and holds a grown agent-safety set.
- [#3823](#3823) scopes
the Husky prose gate to staged paths and adds `--skip-generated` so a
named file inside a generated tree is skipped.
- [#3828](#3828) reads
Copilot's `Open findings:` label, drops the duplicate `null_node`, and
matches `scripts/README.md` to the Merge Gate.
- [#3829](#3829) bumps the
two stale hub caller snippet pins and documents the fallback's
mixed-pair refusal.
- [#3831](#3831) keeps an
inherited `GIT_DIR` from rerooting the prose gate's subdirectory git
reads.
- [#3832](#3832) gives
`backlog-burndown` a disposition for a worker's standalone clone and
keeps the agent-safety hold past a park.
- [#3835](#3835) makes
`carry.py check-sections` refuse what `apply-sections` would, and name
an open fence.
- [#3836](#3836) pins the
reusable-workflow stubs by placeholder and ticks the PlexCleaner gates
item.
- [#3838](#3838) has the
`runtime-secrets` audit dimension detect a bare `secrets/` directory
from the tracked files that name it.
- [#3839](#3839) gates
skill descriptions at the 1024-character limit and trims every one over
it.
- [#3846](#3846) fixes an
adjacent doc, an in-file pre-existing defect, and an edge case on new
code in the open pull request instead of filing an issue for each, and
keeps filing for code that runs elsewhere.
- [#3847](#3847) refuses
skill frontmatter that parses to a list or a scalar, so the description
length gate cannot be bypassed.

Fixes #3770
Fixes #3699
Fixes #3705
Fixes #3789
Fixes #1819
Fixes #727
Fixes #3710
Fixes #3706
Fixes #3623
Fixes #3687
Fixes #3617
Fixes #3757
Fixes #3790
Fixes #3786
Fixes #3785
Fixes #3772
Fixes #1657
Fixes #3443
Fixes #3824
Fixes #3817
Fixes #3805
Fixes #1666
Fixes #3700
Fixes #3821
Fixes #3771
Fixes #3794
Fixes #3825
Fixes #3690
Fixes #1472
Fixes #3813
Fixes #3719
Fixes #1592
Fixes #3845

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants