Skip to content

feat(auto-rebase-health): measure post-restriction fan-out reduction (#739) - #890

Closed
don-petry wants to merge 11 commits into
mainfrom
feat/auto-rebase-health-eligibility
Closed

feat(auto-rebase-health): measure post-restriction fan-out reduction (#739)#890
don-petry wants to merge 11 commits into
mainfrom
feat/auto-rebase-health-eligibility

Conversation

@don-petry

Copy link
Copy Markdown
Collaborator

What

Phase 2 instrumentation for epic #736. Adds a Post-restriction fan-out section to the auto-rebase health report so the report can show the reduction the review-ready eligibility gate (petry-projects/.github#468, issue #465) actually buys.

The Phase 1 report (#737) estimated fan-out as runs × ALL open non-Dependabot PRs — it never subtracted ineligible PRs, so it could not surface the reduction. This adds the eligible-PR multiplier and a like-for-like before/after.

How

  • New pure, unit-tested helpers in scripts/auto_rebase_health.sh:
    • pr_has_current_approval — reads actual review states (current-approval wins; a later CHANGES_REQUESTED/DISMISSED cancels an earlier APPROVED), mirroring the reusable's .github/scripts/auto-rebase/lib/eligibility.sh exactly.
    • count_eligible — non-draft AND (approved OR auto-rebase:ready label).
    • fmt_reduction — behind→eligible multiplier reduction, with a zero-base guard.
  • render_report gains an optional eligible-count arg and renders the new section (eligible multiplier, restricted re-run estimate, reduction %, explicit ≥50% success-metric verdict). Backward-compatible: the section renders only when an eligible count is supplied.
  • main() computes eligibility from per-PR reads (one pulls/{n} + pulls/{n}/reviews per open non-Dependabot PR). Best-effort: any failure leaves the section omitted rather than reported wrongly.

Sample output (live, 6-day post-change window)

## Post-restriction fan-out (review-ready eligibility)
- Eligible PRs (non-draft AND (current `APPROVED` review OR `auto-rebase:ready` label)): 2 of 8 open non-Dependabot PRs
- Estimated branch-update CI re-runs (restricted): ~96 (~16.0/day)
- Fan-out reduction (behind→eligible multiplier): 75%
- ≥50% reduction success metric (epic #736): ✅ met

Cost / safety

  • No new paid spend; no LLM calls; still ≤1 scheduled run/day. The extra per-PR reads use the workflow's existing pull-requests: read (no permission change).
  • shellcheck clean at the repo's --severity=warning gate; 28/28 bats pass (bats tests/auto_rebase_health.bats).

Context

🤖 Generated with Claude Code

…739)

Phase 2 instrumentation for epic #736. The Phase 1 report (#737) estimated
fan-out as runs × ALL open non-Dependabot PRs, which does not reflect the
review-ready eligibility gate that landed in petry-projects/.github#468
(issue #465) — so it could not show the reduction the gate buys.

Add a "Post-restriction fan-out" section that mirrors the reusable's
review-ready predicate against the current open PRs:
  - count eligible PRs (non-draft AND (current APPROVED review OR the
    auto-rebase:ready label)), reading actual review states (current-approval
    wins) exactly as the reusable's lib/eligibility.sh does
  - report the eligible-PR multiplier, the restricted re-run estimate, and the
    behind→eligible reduction, with an explicit ≥50% success-metric verdict

This is the cleaner before/after signal that feeds the Merge Queue go/no-go
decision record (#739). New pure helpers (fmt_reduction, pr_has_current_approval,
count_eligible) are unit-tested; main() does the per-PR read I/O (no CI re-runs,
no LLM cost, still ≤1 scheduled run/day). render_report stays backward-compatible
— the new section renders only when an eligible count is supplied.

shellcheck clean at the repo's --severity=warning gate; 28/28 bats pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019LUUSUQHqwLWZ583SAs41K
@don-petry
don-petry requested a review from a team as a code owner June 21, 2026 13:14
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@don-petry, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 26 minutes and 53 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4c573520-7cde-4f69-baf0-3bacbc22b293

📥 Commits

Reviewing files that changed from the base of the PR and between 11bf856 and ff20d9e.

📒 Files selected for processing (2)
  • scripts/auto_rebase_health.sh
  • tests/auto_rebase_health.bats
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auto-rebase-health-eligibility

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 and usage tips.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 13:15
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-21T14:15:55Z.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the auto-rebase health report by adding a "Post-restriction fan-out" section to track the reduction in CI re-runs when restricting updates to review-ready PRs. It introduces helper functions to determine PR eligibility based on draft status, approvals, and labels, along with corresponding unit tests. The review feedback suggests valuable improvements: optimizing GitHub API usage by fetching draft status and labels in the initial list call to reduce total requests, handling potential null-user exceptions in jq for deleted users, and utilizing a more idiomatic jq filter for label matching.

Comment thread scripts/auto_rebase_health.sh Outdated
Comment on lines +146 to +153
pr_has_current_approval() {
local json="${1:-}" result
[ -n "$json" ] || json='[]'
result=$(printf '%s' "$json" | jq -r '
reduce (.[] | select(.state == "APPROVED" or .state == "CHANGES_REQUESTED" or .state == "DISMISSED")) as $r ({}; .[$r.user.login] = $r.state)
| any(. == "APPROVED")')
[ "$result" = "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.

medium

If a review is submitted by a deleted user, the .user object in the GitHub API response can be null. Attempting to access .user.login directly will cause jq to throw a Cannot index null with string "login" error. We should safely navigate .user and ensure .user?.login is not null before indexing.

Suggested change
pr_has_current_approval() {
local json="${1:-}" result
[ -n "$json" ] || json='[]'
result=$(printf '%s' "$json" | jq -r '
reduce (.[] | select(.state == "APPROVED" or .state == "CHANGES_REQUESTED" or .state == "DISMISSED")) as $r ({}; .[$r.user.login] = $r.state)
| any(. == "APPROVED")')
[ "$result" = "true" ]
}
pr_has_current_approval() {
local json="${1:-}" result
[ -n "$json" ] || json='[]'
result=$(printf '%s' "$json" | jq -r '
reduce (.[] | select((.state == "APPROVED" or .state == "CHANGES_REQUESTED" or .state == "DISMISSED") and .user?.login != null)) as $r ({}; .[$r.user.login] = $r.state)
| any(. == "APPROVED")')
[ "$result" = "true" ]
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done in scripts/auto_rebase_health.sh pr_has_current_approval: added .user?.login != null to the select predicate so reviews from deleted users (where .user is null) are filtered out before the reduce accesses .user.login, preventing the Cannot index null with string "login" jq error. Added two new bats tests covering the null-user case in tests/auto_rebase_health.bats.

Comment on lines +160 to +168
count_eligible() {
local json="${1:-}" label="${2:-}"
[ -n "$json" ] || json='[]'
printf '%s' "$json" | jq --arg L "$label" '
[ .[]
| select(((.draft // false) | not)
and ((.approved // false) or ([.labels[]?.name] | any(. == $L)))) ]
| length'
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

low

We can make the jq filter more idiomatic and efficient by using any/2 directly on .labels[]? instead of constructing an intermediate array [.labels[]?.name] and piping it to any.

Suggested change
count_eligible() {
local json="${1:-}" label="${2:-}"
[ -n "$json" ] || json='[]'
printf '%s' "$json" | jq --arg L "$label" '
[ .[]
| select(((.draft // false) | not)
and ((.approved // false) or ([.labels[]?.name] | any(. == $L)))) ]
| length'
}
count_eligible() {
local json="${1:-}" label="${2:-}"
[ -n "$json" ] || json='[]'
printf '%s' "$json" | jq --arg L "$label" '
[ .[]
| select(((.draft // false) | not)
and ((.approved // false) or any(.labels[]?; .name == $L))) ]
| length'
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done in scripts/auto_rebase_health.sh count_eligible: replaced [.labels[]?.name] | any(. == $L) with the idiomatic any(.labels[]?; .name == $L), which skips the intermediate array allocation. All existing count_eligible bats tests continue to pass.

@don-petry
don-petry disabled auto-merge June 21, 2026 13:16
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
**Status:** No actionable issues  
**Issues addressed:** 0
The SonarCloud Quality Gate **passed** with:
- ✅ 0 new issues
- ✅ 0 accepted issues  
- ✅ 0 security hotspots
- ✅ All CI checks passing
There are no Tier 1 blockers (no failures, no `CHANGES_REQUESTED` reviews), and the SonarCloud comment contains only a passing quality gate report with no specific findings to address.
**Files changed:** `scripts/auto_rebase_health.sh`, `tests/auto_rebase_health.bats`  
**Action:** None needed — PR is ready to merge.

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 13:17
@don-petry
don-petry disabled auto-merge June 21, 2026 15:01
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 15:07
@don-petry
don-petry disabled auto-merge June 21, 2026 15:07
@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 15:11
@don-petry
don-petry disabled auto-merge June 21, 2026 15:12
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
- ✅ All variables properly quoted
- ✅ Safe jq patterns using `--arg` and `--argjson`
**CI & Review Status:**
- ✅ All 31 CI checks passing (no Tier 1 blockers)
- ✅ CodeRabbit approved
- ✅ No "CHANGES_REQUESTED" reviews
- ✅ Working tree clean
---
**Issues addressed: 0**
**Result:** No actionable issues found. The PR has a successful quality gate with no security hotspots, all CI passing, and clean code following safe shell scripting practices.

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 15:13

@donpetry-bot donpetry-bot 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.

Automated review — APPROVED ✓

Risk: LOW
Reviewed commit: 98fc98ec100b6993d9bb56ac688541dd712c2505
Review mode: triage-approved (single reviewer)

Summary

Phase 2 instrumentation for the auto-rebase health report (epic #736): adds a "Post-restriction fan-out" section that mirrors the reusable's review-ready eligibility predicate and reports the behind→eligible multiplier reduction with a ≥50% success verdict. Changes are confined to scripts/auto_rebase_health.sh (+117/-8) and tests/auto_rebase_health.bats (+118/-0). New helpers (fmt_reduction, pr_has_current_approval, count_eligible) are pure and unit-tested; main() does best-effort per-PR reads using existing pull-requests:read permission — no new spend, no LLM calls, render_report stays backward-compatible (section renders only when an eligible count is supplied).

Linked issue analysis

No formal closing-issue reference (closingIssuesReferences is empty). The PR is instrumentation feeding the Merge Queue go/no-go decision record (#739) for epic #736 / story #465; the body and commit message document this context clearly. No issue is meant to auto-close, so this is expected rather than a gap.

Findings

No blocking findings.

  • Logic is consistent: fmt_reduction and the inline ≥50% verdict both compute (behind - eligible) * 100 / behind, both guard the behind<=0 / divide-by-zero case.
  • pr_has_current_approval correctly reduces to last-decision-wins per reviewer and skips null users (.user?.login != null), with explicit unit tests for null-user, COMMENTED-only, and cross-user cases.
  • Gemini's earlier (non-blocking, COMMENTED) suggestions are addressed: draft+labels are fetched in the single gh pr list call (one reviews call per PR, not two), and null-user reviews are handled.
  • Secret-scan MCP tool (mcp__github__run_secret_scanning) is not exposed in this run; relying on the green gitleaks CI check. The diff contains no secrets — pure shell/jq report logic.
  • All variables are quoted; jq calls use --arg/--argjson safely.

CI status

All required checks green at 98fc98e: Lint/ShellCheck, bats unit-tests, CodeQL (actions+python), SonarCloud (Quality Gate passed — 0 issues/hotspots), Secret scan (gitleaks), AgentShield, holdout-guard, test-deletion guard. CodeRabbit APPROVED at head SHA. The CANCELLED dev-lead dispatch/ci-relay entries stem from the [skip ci-relay] commit and are expected; dependency-audit ecosystem subjobs are SKIPPED (no matching ecosystems). No failures. mergeStateStatus is BLOCKED pending the requested org-leads human review.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry
don-petry disabled auto-merge June 21, 2026 16:17
@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:19
@don-petry
don-petry disabled auto-merge June 21, 2026 16:24
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
Issues addressed: 0
Files changed: none
Skipped (informational): 0
```
The PR is ready to merge pending any remaining org-leads approval (which is noted as blocked in donpetry-bot's review for policy reasons, not technical ones).

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:24
@don-petry
don-petry disabled auto-merge June 21, 2026 16:34
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
Issues addressed: 0
- No new issues reported
- No security hotspots detected
- Code follows org standards
Files changed: scripts/auto_rebase_health.sh, scripts/engine.sh, tests/auto_rebase_health.bats, tests/dev-lead/unit/test_engine_duck_model.bats
Skipped (informational): 0
```
The PR is ready for merge once remaining CI checks complete (which are currently queued).

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:35
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-21T17:39:44Z.

@don-petry
don-petry disabled auto-merge June 21, 2026 16:40
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
- ✅ 0 Accepted issues  
- ✅ 0 Security Hotspots
- ✅ 0.0% Coverage/Duplication issues (new code)
**Tier 1 Blockers:** None
- No check failures, timeouts, or cancellations
- No `CHANGES_REQUESTED` reviews
- CodeRabbit approved; donpetry-bot (dev-lead) approved with detailed analysis
## Summary
**No actionable issues.** The SonarCloud quality gate passed with zero issues and zero security hotspots. There are no specific code issues to fix, no threads to resolve, and no changes needed in response to this bot comment.
The PR is clear from a code quality and security analysis perspective. Remaining CI checks (Lint, ShellCheck, bats, etc.) are queued/in-progress but not yet blocking.

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:40
@don-petry
don-petry disabled auto-merge June 21, 2026 16:47
@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:49
@don-petry
don-petry disabled auto-merge June 21, 2026 16:50
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
Issues addressed: 0
Files changed: (none — no fixes needed)
Skipped: 0
Status: Quality gate PASSED — no actionable issues found
```

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 16:50
@don-petry
don-petry disabled auto-merge June 21, 2026 23:33
@sonarqubecloud

Copy link
Copy Markdown

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: review-changes)

PR: #890
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-06-22T00:06:32Z

@don-petry

Copy link
Copy Markdown
Collaborator Author

Note

@don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically.
Next attempt after: 2026-06-22T00:06:32Z

@don-petry
don-petry enabled auto-merge (squash) June 21, 2026 23:36
@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-06-22T00:40:12Z.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Closing — overtaken by events. This PR's purpose was to produce a cleaner before/after fan-out measurement to feed the #739 decision record. #739 shipped via #891 (merged) using the snapshot/eligible-multiplier method, with the ≥50% success metric already verified and recorded. On review, the remaining standalone value is thin: the load-bearing gate signal (the agentic-conflict-resolution rate — sentinels/responses/status=applied) is already tracked by the existing #737 report, and the fan-out reduction is a one-time metric check rather than something that needs continuous re-display. The change itself was sound (28/28 bats, shellcheck clean) but isn't worth carrying. Reopen if we later want the eligible-multiplier surfaced automatically each run.

@don-petry don-petry closed this Jun 22, 2026
auto-merge was automatically disabled June 22, 2026 01:24

Pull request was closed

@don-petry
don-petry deleted the feat/auto-rebase-health-eligibility branch June 22, 2026 01:24
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