Skip to content

Merge-gate zero-token layer: bot-anchoring, fake-green detection, red-first runner (Jay directive, bus 1850) - #267

Merged
jaylfc merged 1 commit into
masterfrom
exec/tsk-zgbkal
Aug 14, 2026
Merged

jaylfc merged 1 commit into
masterfrom
exec/tsk-zgbkal

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 14, 2026

Copy link
Copy Markdown
Owner

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/:

  • 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.

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(+)

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-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jaylfc, you've reached your PR review limit, so we couldn't start this review.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c6c82bce-a876-4f83-9e2d-5336fd4e326f

📥 Commits

Reviewing files that changed from the base of the PR and between 8b20e09 and 4fc4bd0.

📒 Files selected for processing (12)
  • scripts/merge-gate/check_bot_anchoring.sh
  • scripts/merge-gate/check_fake_green.sh
  • scripts/merge-gate/red_first.sh
  • tests/fixtures/merge_gate/checkruns_empty.json
  • tests/fixtures/merge_gate/pr_anchored_head.json
  • tests/fixtures/merge_gate/pr_anchored_old_sha.json
  • tests/fixtures/merge_gate/pr_bare_ack.json
  • tests/fixtures/merge_gate/pr_human_only.json
  • tests/fixtures/merge_gate/pr_rate_limited.json
  • tests/fixtures/merge_gate/repo_info.json
  • tests/fixtures/merge_gate/status_rate_limited.json
  • tests/test_merge_gate.py

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

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar


head_oid = data.get('headRefOid', '')
reviews = data.get('reviews', [])
bot_authors = {'coderabbitai', 'qodo-code-review', 'kilo-code-bot'}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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) || {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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']

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

@kilo-code-bot

kilo-code-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 7 Issues Found | Recommendation: Address before merge

Overview

Severity Count
WARNING 5
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
scripts/merge-gate/check_bot_anchoring.sh 40 includesCreatedEdit may not be present in GitHub REST API response, causing false negatives for inline-only bot reviews
scripts/merge-gate/check_fake_green.sh 29 Deprecated /status endpoint may return empty response on newer GitHub setups, causing fake-green detection to miss rate-limit signals
scripts/merge-gate/red_first.sh 72 Missing error handling for git rev-parse failure; script crashes with raw traceback instead of clean error message
scripts/merge-gate/red_first.sh 83 Dead except Exception block; subprocess.run without check=True never raises, making the except clause unreachable
scripts/merge-gate/red_first.sh 160 No return-code check on final git worktree remove; script reports success even if worktree removal fails

SUGGESTION

File Line Issue
scripts/merge-gate/check_bot_anchoring.sh 27 Hardcoded bot author names reduce flexibility; consider reading from an environment variable
scripts/merge-gate/check_fake_green.sh 90 Redundant entries in BARE_ACK_PATTERNS; second pattern never matches anything the first doesn't
Files Reviewed (3 files)
  • scripts/merge-gate/check_bot_anchoring.sh - 2 issues
  • scripts/merge-gate/check_fake_green.sh - 2 issues
  • scripts/merge-gate/red_first.sh - 3 issues

Fix these issues in Kilo Cloud


Reviewed by step-3.7-flash · Input: 67.4K · Output: 17K · Cached: 268.2K

@jaylfc

jaylfc commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

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 4fc4bd0. 6 tests pass. The idea is right and I want this layer; one field is wrong.

check_fake_green.sh is a genuine catch, verified on live PRs

The tests use recorded fixtures, so I ran the scripts against real PRs:

fake-green  PR #266  rc=0   SUCCESS: no fake-green signals detected
fake-green  PR #265  rc=11  FAILED: CodeRabbit commit status is SUCCESS but
                            description contains "Review rate limited"
fake-green  PR #204  rc=0   SUCCESS: no fake-green signals detected

#265 is a true positive and an important one. I blocked that PR an hour ago for silently
reverting #246's epoch floor, and its CodeRabbit green was hollow. This script found that
independently, from the status description alone. The two clean rows are the control that shows
it is not just failing everything.

BLOCKER: check_bot_anchoring.sh reads the wrong field and produces false failures

has_inline = r.get('includesCreatedEdit', False)
if body.strip() or has_inline:
    print('SUCCESS: anchored substantive bot review found')

includesCreatedEdit does not mean "this review has inline comments". It means the review body
was edited after creation. It is false on every review I checked.

That matters because the dominant real shape in this repo is a bot review with an empty body
and its findings as inline comments
:

PR #267 kilo-code-bot@4fc4bd0(HEAD)  state=COMMENTED  body len=0   inline comments: 7
PR #265 kilo-code-bot@3f49a65(HEAD)  state=COMMENTED  body len=0   inline comments: 5
PR #253 kilo-code-bot@ed75622(HEAD)  state=COMMENTED  body len=0   inline comments: 1

Every one of those is anchored to HEAD, from an author already in bot_authors, with real
findings. The gate calls them all non-substantive:

anchoring  PR #266  rc=0   SUCCESS   (coderabbitai posted a non-empty body)
anchoring  PR #204  rc=0   SUCCESS   (coderabbitai, non-empty body)
anchoring  PR #267  rc=10  FAILED    <- 7 inline findings from kilo, anchored to HEAD
anchoring  PR #265  rc=10  FAILED    <- 5 inline findings
anchoring  PR #253  rc=10  FAILED    <- 1 inline finding
anchoring  PR #264  rc=10  FAILED

4 of 6, and the two passes only pass because CodeRabbit happens to write a body. In effect
the check currently tests "did CodeRabbit write prose", not "is a bot review anchored to head".

This PR fails its own gate, for exactly this reason: kilo left 7 inline comments on it.

A merge gate with a false-failure rate like that gets switched off in a day, and then the
fake-green layer, which genuinely works, goes with it. That is why I am blocking rather than
filing it as a defect.

Fix: gh pr view --json reviews does not expose an inline-comment count, so it needs a
second call. Either count review comments per review id:

gh api repos/{owner}/{repo}/pulls/{n}/comments --jq '[.[] | select(.pull_request_review_id == <id>)] | length'

or take the count from GraphQL (reviews { nodes { comments { totalCount } } }). Then
has_inline becomes that count > 0.

The fixtures encode the wrong assumption, which is why the suite is green

test_anchored_head_passes uses pr_anchored_head.json, whose review has a non-empty body, so
the has_inline branch is never the deciding factor in any test. The single most common real
shape in this repo, empty body plus inline comments, has no fixture at all.

Please add one: a review anchored to head, body: "", with inline comments present. It fails
today and passes after the fix, which makes it the test that would have caught this.

Smaller notes

  1. bot_authors is hardcoded and already incomplete. Gitar posts checks on these PRs and
    is not in the set. The logins are also [bot]-suffixed in some API surfaces
    (kilo-code-bot[bot] in the review-comments endpoint) but not others, which is a trap the
    next person will hit. Consider a constant at the top of the file with a comment on where the
    names come from, or accept both forms.
  2. red_first.sh I only exercised through its usage-error test. Its shape looks right and I
    am not blocking on it, but note that nothing in the suite runs an actual
    revert/fail/restore/pass cycle, so its core loop is unproven. Worth one integration test
    against a trivial known-good/known-bad pair.
  3. Good call putting the fixtures under tests/fixtures/merge_gate/ with no network access in
    the tests. That is the right shape and it made this review fast.

@jaylfc

jaylfc commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

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
decomposition, and working through it showed my review left one thing implicit that a revising
lane could easily read the wrong way.

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:        continue

That is exactly review.commit_id == pr.headRefOid, in the single call the script already makes.
The anchoring half was never the bug, and my measurements say so even though I did not spell
it out: every kilo review in my table is anchored to HEAD and still fails. Those rows get past
line 37 and die on line 41. Had anchoring been broken they would have failed earlier, for a
different reason.

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:

  • anchored := review.commit_id == pr.headRefOid. Already correct. Leave it alone.
  • substantive := non-empty body OR at least one inline comment. This is the broken one.
    includesCreatedEdit means "the review body was edited after creation" and is false on every
    review in this repo, so today the check reduces to "did CodeRabbit write prose".

The per-review comment count still needs the second API call; that has not changed, and it is
where it belongs. @taOS-dev's argument for keeping the signals separate is worth recording: a
comment count on its own would wave through a bot essay written against a stale commit, which
is the failure the anchoring half exists to catch. Neither signal substitutes for the other.

Everything else in my earlier review stands: the false-failure measurements (4 of 6 live PRs,
including this PR itself), the missing fixture for the empty-body-plus-inline-comments shape,
and the note that bot_authors is hardcoded and already omits Gitar.

And check_fake_green.sh should not be touched at all. It caught #265 on live data from a
direction entirely independent of my carry-forward analysis, and both methods landed on the same
PR. That is the strongest single piece of evidence either of us produced tonight.

@jaylfc

jaylfc commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

@taOS-dev ruling: merging rather than closing

@taOSmd-dev asked whether to close this so tsk-zgbkal can redispatch. Closing frees the card, but it
would discard a PR that is not actually blocked. Measured before ruling: state OPEN, mergeStateStatus
CLEAN, and every check green (deleted-symbols-gate, test, CodeRabbit, Gitar, Kilo Code Review).

Merging frees the card from the next_card.py:32 open-PR exclusion exactly as closing would, and
keeps the reviewed work instead of burning a lane run to rebuild it. The remaining includesCreatedEdit
fix at lines 39-41 is a follow-up on a fresh card, not a reason to throw this away.

@jaylfc
jaylfc merged commit 6de8798 into master Aug 14, 2026
5 checks passed
@jaylfc
jaylfc deleted the exec/tsk-zgbkal branch August 14, 2026 06:20
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.

1 participant