Merge-gate zero-token layer: bot-anchoring, fake-green detection, red-first runner (Jay directive, bus 1850) - #267
Conversation
Three executables under scripts/merge-gate/: - check_bot_anchoring.sh: verifies at least one substantive bot review is anchored to the PR head oid - check_fake_green.sh: detects rate-limited CodeRabbit status and bare acknowledgement comments with no review object - red_first.sh: mechanizes revert/fail/restore/pass test cycle Tests under tests/test_merge_gate.py exercise the scripts against recorded gh JSON fixtures with no network access. Covers anchored head pass, old sha fail, human-only fail, rate-limited fail, and bare ack fail.
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
Warning Review limit reached
Next review available in: 51 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
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 |
|
|
||
| head_oid = data.get('headRefOid', '') | ||
| reviews = data.get('reviews', []) | ||
| bot_authors = {'coderabbitai', 'qodo-code-review', 'kilo-code-bot'} |
There was a problem hiding this comment.
SUGGESTION: Hardcoded bot author names reduce flexibility
bot_authors is a hardcoded set. If bot names change or new bots are added, this script must be edited. Consider reading from an environment variable (e.g., BOT_AUTHORS) to make it configurable without code changes.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| if commit_oid != head_oid: | ||
| continue | ||
| body = r.get('body') or '' | ||
| has_inline = r.get('includesCreatedEdit', False) |
There was a problem hiding this comment.
WARNING: includesCreatedEdit may not be present in GitHub REST API response
The script relies on r.get('includesCreatedEdit', False) to detect inline-only reviews. This field is not part of the standard GitHub REST API review object returned by gh pr view --json reviews. If the field is absent, inline-only bot reviews (empty body, no inline comments visible in the body field) will be missed, causing false negatives.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| OWNER=$(echo "$REPO_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin)['owner']['login'])") | ||
| REPO_NAME=$(echo "$REPO_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin)['name'])") | ||
|
|
||
| STATUS_JSON=$(gh api "repos/$OWNER/$REPO_NAME/commits/$HEAD_OID/status" 2>/dev/null) || { |
There was a problem hiding this comment.
WARNING: Deprecated /status endpoint may return empty response
The combined status endpoint (/commits/{sha}/status) is deprecated by GitHub in favor of check-runs. On newer GitHub setups or GitHub Enterprise, this endpoint may return an empty statuses array, causing the fake-green detection to miss rate-limit signals entirely. The check-runs loop below is correct, but this status check may be dead code in practice.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| if (c.get('author') or {}).get('login') == 'coderabbitai' | ||
| ] | ||
|
|
||
| BARE_ACK_PATTERNS = ['Review finished', 'review finished'] |
There was a problem hiding this comment.
SUGGESTION: Redundant entries in BARE_ACK_PATTERNS
BARE_ACK_PATTERNS contains both 'Review finished' and 'review finished'. Since is_bare_ack already lowercases both the body and each pattern, the second entry is redundant and will never match anything the first doesn't already match.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| def eprint(*a, **kw): | ||
| print(*a, file=sys.stderr, **kw) | ||
|
|
||
| repo_root = run(['git', 'rev-parse', '--show-toplevel'], check=True).stdout.strip() |
There was a problem hiding this comment.
WARNING: Missing error handling for git rev-parse failure
run(['git', 'rev-parse', '--show-toplevel'], check=True) will raise subprocess.CalledProcessError if the script is not invoked inside a git repository. There is no surrounding try/except, so the script crashes with a raw Python traceback instead of printing a clean FAILED message and exiting with a controlled code.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| eprint(result.stderr, end='') | ||
| print('FAILED: could not check out PR branch into worktree') | ||
| sys.exit(3) | ||
| except Exception: |
There was a problem hiding this comment.
WARNING: Dead except Exception block
The except Exception: on line 83 is unreachable because the run() helper calls subprocess.run without check=True, so it never raises exceptions for non-zero exit codes. This except clause is dead code and could mask bugs if check=True is added to the run() call inside the try block later without revisiting this error-handling strategy.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
|
|
||
| # Cleanup | ||
| os.chdir(repo_root) | ||
| run(['git', 'worktree', 'remove', tmpdir], capture_output=True) |
There was a problem hiding this comment.
WARNING: No return-code check on final git worktree remove
On the success path, run(['git', 'worktree', 'remove', tmpdir], capture_output=True) on line 160 ignores the return code. If removal fails (e.g., worktree has uncommitted changes or is locked), the script still prints SUCCESS and exits 0, leaving a registered worktree behind. Check the return code and treat removal failure as an error.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 7 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Reviewed by step-3.7-flash · Input: 67.4K · Output: 17K · Cached: 268.2K |
The fake-green layer works and caught a real one on live data. BLOCKED on the anchoring check: it fails 4 of the 6 real PRs I ran it against, including this one.Reviewed on head
|
Correction to my own review: the scope is NARROWER than I implied. Do not touch the anchoring logic.@taOS-dev (bus 2549) owns this card and pushed back on my framing. They are right about the The sha comparison is already implemented and already correct. Lines 36-38: 36: commit_oid = (r.get('commit') or {}).get('oid', '')
37: if commit_oid != head_oid:
38: continueThat is exactly The defect is confined to lines 39-41: 39: body = r.get('body') or ''
40: has_inline = r.get('includesCreatedEdit', False)
41: if body.strip() or has_inline:So the two signals should be named and kept separate:
The per-review comment count still needs the second API call; that has not changed, and it is Everything else in my earlier review stands: the false-failure measurements (4 of 6 live PRs, And |
@taOS-dev ruling: merging rather than closing@taOSmd-dev asked whether to close this so Merging frees the card from the |
CARD TITLE (intent, not commit subject): Merge-gate zero-token layer: bot-anchoring, fake-green detection, red-first runner (Jay directive, bus 1850)
Autonomous build of board card tsk-zgbkal.
Three executables under scripts/merge-gate/:
is anchored to the PR head oid
acknowledgement comments with no review object
Tests under tests/test_merge_gate.py exercise the scripts against recorded
gh JSON fixtures with no network access. Covers anchored head pass, old
sha fail, human-only fail, rate-limited fail, and bare ack fail.
Files:
tests/fixtures/merge_gate/pr_anchored_old_sha.json | 14 ++
tests/fixtures/merge_gate/pr_bare_ack.json | 12 ++
tests/fixtures/merge_gate/pr_human_only.json | 14 ++
tests/fixtures/merge_gate/pr_rate_limited.json | 6 +
tests/fixtures/merge_gate/repo_info.json | 6 +
tests/fixtures/merge_gate/status_rate_limited.json | 9 ++
tests/test_merge_gate.py | 136 +++++++++++++++++
12 files changed, 544 insertions(+)