fix(review): stop the inherited label gate deadlocking CodeRabbit auto-review - #1425
Conversation
…o-review `reviews.auto_review.labels` is now set explicitly to `[]` — the schema default — to override a required-labels list inherited from the dashboard / org config. The inherited gate demanded at least one of ~26 labels before a review would start. Four of those (`architecture-gap`, `ci-cd`, `pipeline-critical`, `placeholder-code`) are labels CodeRabbit applies itself, as part of a review, via `auto_apply_labels: true`. A PR opens unlabelled, so the gate skipped it, and nothing then applied a label to un-skip it. Labelling after the fact does not retro-trigger. Observed on both currently-open non-draft PRs: the `CodeRabbit` commit status reads "Review skipped: excluded by label configuration" on #1381 (head 8628b5e) and #1410 (head 3f72b75). Every review this repo has had was requested by hand with `@coderabbitai full review`. The file's header claimed to be the single source of truth for settings that used to live only in the dashboard, but this gate was not in it — and with `inheritance: true`, anything left unset can be overridden from there. Header now says so, and recommends setting values explicitly even at their default. No other setting changed; `drafts: false` still keeps draft PRs out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mDBbUAmEHFXrYboYd9TzR
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) 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:
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 |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
Agent Completion Truth Gate: BLOCKEDReasons: Machine-readable verdict{
"details": {
"collection_errors": [
"incomplete_linked_issue_contract",
"linked_issue_not_agent_task",
"missing_intent_snapshot",
"missing_agent_run_id",
"missing_agent_login"
],
"invalid_fields": [
"policy.agent_login",
"policy.run_id"
]
},
"reasons": [
"invalid_payload"
],
"verdict": "blocked"
} |
This PR reproduced its own bug, and the truth-gate red is a two-gate conflictTwo things to record on 1. The defect reproduced live, on this PRI wrote in the Verification section that auto-review firing was unverifiable here, and attributed the expected skip to CodeRabbit skipped this PR on the label gate, before the draft check ever mattered — same notice, same 26-label list:
This PR carries zero labels. That makes it the cleanest reproduction of the three: #1410 was skipped despite carrying two labels that are in the required list (added post-open), and this one was skipped carrying none at all. Three independent heads, one cause. It also demonstrates the deadlock directly rather than by inference: 2.
|
| PR | Branch | pullProvenance |
truth-gate |
|---|---|---|---|
| #1381 | groupthinking-fix-upstream-error-leakage |
false | ✅ not_applicable: all rules passed |
| #1410 | claude/clever-heisenberg-0zuq9k |
true | ❌ invalid_payload |
| #1425 | claude/clever-heisenberg-4k5fv7 |
true | ❌ invalid_payload |
Same base, same kind of change; the only variable that tracks the outcome is the branch prefix. The in-code comment anticipates this — "A branch named claude/... is a naming convention, not a dispatch" — and #1368 merged with this status failing.
Not fixing it here. The only ways to clear it are to fabricate agent_login / run_id in an agent-lock-manifest, or to label #1424 as a dispatched agent task it never was. Both inject false evidence into the mechanism the gate exists to enforce, which is worse than a red advisory status.
And it does not block. .github/workflows/README.md:179 is explicit: pr-checks.yml retains the advisory agent-completion/truth-gate/pr-<number> status; it is never required. MERGE_POLICY.md gate 2 does not list it either.
Worth folding into #1409's scope: the arming defect is not just "claude/ prefix arms it", it is "claude/ prefix plus the linked issue Governance mandates arms it", which is why no author-side action can clear it.
Everything else on this head
Vercel deployed, Dependency Review clean (no vulnerabilities, no license or Scorecard issues). One file, +20/−3, configuration only.
Terminal state: HALTED(awaiting_merge_approval)
No automerge label, main is protected, and the publish gate is human-by-default. Staged:
merge_pull_request(owner=groupthinking, repo=EventRelay, pullNumber=1425, merge_method=squash)
Note the fix only takes effect once it is on main — CodeRabbit reads .coderabbit.yaml from the pull request's base branch. The check afterwards is to open a non-draft PR and confirm the CodeRabbit status is a real review rather than a skip.
Generated by Claude Code
The fix here is right; the mechanism in the body is not
Root cause: the inherited list is one folded YAML scalarCodeRabbit inspected its own effective configuration on #1439 and reported that labels:
- >-
[‘architecture-gap’, ..., ‘python’, ...]So there is exactly one required label, and its literal value is the entire bracketed string — smart quotes, commas, brackets and all. No PR can carry that label. The gate is unsatisfiable rather than merely unsatisfied. The tell was in the skip message the whole timeThe notice reads:
That trailing Direct disproof of the timing explanationThis PR's body says the gate skipped #1410 "because they were applied after open", and that "labelling afterwards does not retro-trigger". #1439 tested that:
The second is a fresh evaluation, several minutes after the labeller applied I asserted the timing explanation myself on #1439 before checking, and have corrected it there. What I'd change in the body, not the diff
One consequence worth adding: because the inherited value is malformed rather than merely unwanted, Not opening a competing PR
Generated by Claude Code |
Independent confirmation from #1451 — and a warning about a bad CodeRabbit "learning"Your diagnosis is correct, and #1451 is a clean reproduction of it. Separately, CodeRabbit has just recorded a contradictory explanation into its persistent knowledge base, and following that one would undo this fix. #1451 reproduces the deadlock exactly as this PR describesMeasured on head
I verified the self-referential part of your claim too. Of the 26 required labels, six — The
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- PR .coderabbit.yaml outline ---'
ast-grep outline .coderabbit.yaml --lang yaml --items all 2>/dev/null || true
echo '--- PR reviews.auto_review context ---'
rg -n -A35 -B5 '^\s*auto_review\s*:' .coderabbit.yaml
echo '--- origin/main reviews.auto_review context ---'
git show origin/main:.coderabbit.yaml | rg -n -A35 -B5 '^\s*auto_review\s*:' || true
echo '--- `#1451` current GitHub metadata ---'
gh pr view 1451 --repo groupthinking/EventRelay \
--json number,headRefName,isDraft,labels,createdAt,updatedAt,statusCheckRollup \
--jq '{number,headRefName,isDraft,labels:[.labels[].name],createdAt,updatedAt,statuses:[.statusCheckRollup[]? | {name:.name,conclusion:.conclusion,status:.status}]}'Length of output: 6648
PR The The malformed-scalar claim cannot be verified from this repository because the alleged value is inherited configuration. It is not valid as a repository-YAML learning. The persisted learning you quoted contradicts verified repository state and gives a harmful remediation. Remove it in the Learnings app. 🐇 ✏️ Learnings added
You are interacting with an AI system. |
Green on
|
…1508) * fix(review): make the label-gate override actually bind (inheritance: false) #1425 set `reviews.auto_review.labels: []` to clear an inherited required-labels gate that was deadlocking CodeRabbit auto-review against `auto_apply_labels: true`. The gate is still active. Evidence: PRs opened after #1425 landed on main still receive the CodeRabbit commit status "Review skipped: excluded by label configuration" — #1483 (21:02Z) and #1494 (21:10Z), both non-draft, both based on a main that already carried the empty list. That message can only be emitted by a label gate that is still evaluating, so the override was not taking effect. Cause: with `inheritance: true` the org/dashboard config layers underneath this file, and a key set to an empty collection reads as unset rather than as "override with nothing" — so the inherited list survived. `inheritance` is the only in-file lever over that, hence flipping it off. Note the failure mode this restores protection against: auto-label.yml labels a PR by changed path, but it is an Actions job and queues behind whatever else is running. CodeRabbit evaluates the gate on PR open. When the Actions queue is saturated the PR is still unlabelled at that moment, the gate skips it, and — per the comment already in this file — labelling afterwards does not retro-trigger a review. The PR is then silently never reviewed. Trade-off: settings this file leaves unset now fall back to the CodeRabbit schema default instead of the dashboard. The file already sets the review, tooling, labeling, chat, knowledge-base and issue-enrichment blocks explicitly, which is what its header claims it does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yTj3erqg8xRb79v2djrmH * test(review): pin inheritance to false, with the reason CI caught this: `test_inheritance_enabled` asserts `.coderabbit.yaml`'s `inheritance is True`, which aa31594 changed to false. 1 failed, 8069 passed — a real assertion, not a flake. The test was a snapshot of the values chosen when the CodeRabbit config was version-controlled; its docstring restated the setting rather than defending it. Changing the setting deliberately means the test changes with it, so this flips the assertion and renames it to match. The docstring now carries the reason instead of the restatement. The failure mode is invisible — flipping inheritance back to true does not fail anything, it just silently stops auto-review from ever starting — so the test is the only place that will tell someone why the value is what it is. Verified by replicating the file's config assertions directly; pytest is not installed in this sandbox, so CI is the real check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yTj3erqg8xRb79v2djrmH --------- Co-authored-by: Claude <noreply@anthropic.com>
Canonical issue
Closes #1424
Outcome
CodeRabbit auto-review runs on pull requests again instead of being skipped before it starts.
reviews.auto_review.labelsis now set explicitly to[]— the schema default — overriding a required-labels gate inherited from the dashboard / org UI. Under that gate, no pull request in this repository has ever been auto-reviewed. Every CodeRabbit review the repo has had was requested by hand with@coderabbitai full review.The failure is silent, which is the most important part: the
CodeRabbitcommit status reportssuccesswhen it skips. A green CodeRabbit status has meant "did not review" for every PR here, not "reviewed and found nothing".Why the gate is unsatisfiable
The inherited value appears to be a single folded YAML scalar rather than a list — one required label whose literal name is the entire bracketed string, smart quotes and all:
The tell is in the skip notice itself, and it is directly observable rather than inferred:
That trailing
(1)is the count of required labels, and the list beneath renders as exactly one bullet containing the whole string — not 26 bullets. No label of that name can exist, so the gate is unsatisfiable rather than merely unsatisfied. This has been identical on every skip observed: #1381, #1410, #1425 (×2 heads), #1439.Confidence, stated honestly. This is read from CodeRabbit's own rendering of its effective config and its report on #1439. It cannot be confirmed from this repository, because the value lives in inherited dashboard/org configuration and not in any file here — a fair objection CodeRabbit raised on this PR. The
(1)count is observed fact; the folded-scalar shape is the best explanation for it.The discriminating test
An earlier version of this description blamed ordering — that PRs open unlabelled, and labelling afterwards does not retro-trigger. #1439 tests that directly and refutes it as the root cause:
openede8e6de70ready_for_reviewpython— in the quoted list09426734The second is a fresh evaluation minutes after the labeller applied a qualifying label. Under the ordering explanation it should have reviewed. It did not.
The ordering hazard is real, but secondary
It is still true that labels applied after open do not retro-trigger — seen on #1410 (
documentation,ci-cd) and #1451 (documentationadded by thelabeljob post-open). So gating review on labels thatauto_apply_labels: truehas CodeRabbit apply during a review would be unsafe even if the list parsed correctly. That is a genuine second-order defect; it is not what is breaking things today.Scope
.coderabbit.yaml—reviews.auto_review.labels: []with the reasoning inline; header comment updated to record thatinheritance: truemakes any unset value dashboard-overridable, so a default worth keeping should be written down explicitly.drafts: false— unchanged. Draft PRs stay out of auto-review, which is most of the open queue.labels: []repairs this repository only. The same broken scalar keeps applying to every other repo under the same org configuration, and no repo-level YAML can fix those. Correcting or removing it in the CodeRabbit UI is the actual org-wide remedy and needs dashboard access.Risk
drafts: falsebounds this — most open PRs are drafts and remain excluded. The opposite failure — a gate silently suppressing all review while reportingsuccess— is the one being fixed.git revert. No executable surface; the file is configuration read by a third-party app.Verification
Head
65683bf(mergedmainat794746c). One file, +20/−3.All CI green — 24 checks, zero failures.
validate,guards,build,test,lint-python,lint-frontend,CodeQL,gitleaks (working tree),dependency-review,Canonical issue and evidence, Vercel, and all six security contexts (Security Scan - python,Security Scan - javascript,bandit,python-safety,npm-audit,trivy).agent-completion/truth-gateis gone, not merely passing. It was the only red on the previous head. ci: retire the agent-completion truth gate #1431 retired it; this branch merged that, and the check no longer exists on this head (0 truth-gate check-runs; enforcement workflow and gate scripts deleted from the tree).YAML parses and the intended key is set, every neighbouring setting intact:
labelsis a real schema property with default[]— confirmed againsthttps://coderabbit.ai/integrations/schema.v2.json, which documents it as the array gating which PRs are reviewed.[]is the documented "no gate" value.origin/maindoes not definereviews.auto_review.labels— independently confirmed by CodeRabbit on this PR, establishing the gate is inherited and not repository YAML.Reproduced on four heads —
Review skipped: excluded by label configurationon fix(web): stop leaking upstream and Stripe error details to clients #1381 (8628b5e), docs: require the security scans gate 2 lists but never required #1410 (3f72b75), and this PR on both711f49aand65683bf. This PR carries zero labels and was skipped identically.Auto-review observed firing. Not verifiable from this PR: CodeRabbit reads
.coderabbit.yamlfrom the pull request's base branch, so the change governs reviews only once it is onmain. The skip on65683bfis expected for exactly that reason. The check afterwards is to open a non-draft PR and confirm theCodeRabbitstatus is a real review rather than a skip.Production evidence
Not applicable — one configuration file, no runtime or deployed surface. Gate 4 of
MERGE_POLICY.mdscopes previews toapps/web/**, which this does not touch. Vercel preview deployed green regardless.Agent handoff