Repository navigation
feat(#1894): answer "why isn't this PR approved?" from the real pr-review gate chain (+ why-not-approved agent) #1902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 33 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
3a2bc3e
feat: implement issue #1894 — 10 of 11 open PRs have never received a…
don-petry 951661a
fix(reviews): address review comments [skip ci-relay]
don-petry f9d7948
fix(reviews): address review comments [skip ci-relay]
don-petry 7eaab4f
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry cb2c706
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 0d9cab8
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 9eeea8e
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 4feac90
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 074cde5
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 23fad9b
docs: add docstrings to log and check_advisory_reviews functions
don-petry 963c48a
fix(reviews): document check_advisory_reviews exit code 2
don-petry 976fef7
fix(reviews): align approval-diagnostic advisory fallback with registry
don-petry 23bf5ae
fix(reviews): classify diagnostic advisory comments exactly like the …
don-petry e61b23b
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 05639f9
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry e6bf35b
fix(approval-diagnostic): validate comments field is present in snapshot
don-petry 8404cef
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 48eca91
fix(approval-diagnostic): pass FORCE_REVIEW bypass to suppress mainta…
don-petry c07b90f
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 9593b36
fix(approval-diagnostic): apply FORCE_REVIEW bypass to all verdict br…
don-petry 2d51698
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry f57758f
fix(approval-diagnostic): model quiescence timeout alongside head-age…
don-petry dbaffb0
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 2844959
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 51a280f
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 4175bc6
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 60e98be
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 6c686c5
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 1481356
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 640a3ee
fix(approval-diagnostic): detect UNSUPPORTED from bot comments, not j…
don-petry 3333ba5
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry f530385
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry 7dd295e
feat(#1894): answer "why isn't this PR approved?" from the real gate …
103ee82
feat(#1894): ship why-not-approved as an org-wide agent profile, not …
bdabfb5
test(#1894): make the diagnostic's read-only assertion able to fail
e47c14a
fix(#1894): diagnose mode refuses every GitHub write; no diagnosis fr…
35eb11a
fix(#1894): lead with the holding gate on an approved PR; keep adviso…
a5357e0
fix(#1894): diagnose-mode gh guard fails closed on unknown subcommands
0f685fa
fix(#1894): an approved PR held by the human escalation leads with th…
8b5d96b
Merge branch 'main' into dev-lead/issue-1894-20260923-0159
don-petry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| #!/usr/bin/env bash | ||
| # pr-approval-diagnostic.sh — "why isn't this PR approved?" (#1894) | ||
| # | ||
| # Answers from the REAL gate chain, not a model of it: runs scripts/review-one-pr.sh | ||
| # in diagnose mode (PR_REVIEW_DIAGNOSE=true — read-only, never forced, stops before | ||
| # any model runs) and reports the single verdict that run reaches — which gate holds | ||
| # the PR, and what would change the decision — together with the PR facts a reader | ||
| # needs (review decision, approvals at the head, hold labels, merge state). | ||
| # | ||
| # The previous attempt (#1902) re-implemented each gate in a separate library and | ||
| # drifted from the real ones (bot-comment handling, the unsupported-file regex, | ||
| # check-run participation, the thread-gate fail-closed path). Running the gate chain | ||
| # itself makes that drift impossible: a gate change is a diagnostic change. | ||
| # | ||
| # Usage: pr-approval-diagnostic.sh <pr-url> [--json] | ||
| # Needs the same environment a pr-review run needs to READ the PR (GH_TOKEN with | ||
| # repo read; BOT_USER defaults to donpetry-bot). Writes nothing to GitHub. | ||
| # Exit: 0 diagnosed · 2 the gate chain produced no verdict (its log tail is printed) | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| PR_URL="${1:-}" | ||
| FORMAT="markdown" | ||
| [ "${2:-}" = "--json" ] && FORMAT="json" | ||
| if [[ ! "$PR_URL" =~ ^https://github\.com/[^/]+/[^/]+/pull/[0-9]+$ ]]; then | ||
| echo "usage: pr-approval-diagnostic.sh https://github.com/<owner>/<repo>/pull/<n> [--json]" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| LOG="$(mktemp)" | ||
| trap 'rm -f "$LOG"' EXIT | ||
|
|
||
| set +e | ||
| PR_REVIEW_DIAGNOSE=true GITHUB_STEP_SUMMARY="" bash "$SCRIPT_DIR/review-one-pr.sh" "$PR_URL" >"$LOG" 2>&1 | ||
| rc=$? | ||
| set -e | ||
|
|
||
| # The run's verdict is its LAST emit_verdict line (a JSON object with .decision). | ||
| verdict=$(grep -E '^\{"pr":' "$LOG" | tail -n 1 || true) | ||
| if [ -z "$verdict" ] || ! jq -e '.decision' <<<"$verdict" >/dev/null 2>&1; then | ||
| echo "pr-approval-diagnostic: the gate chain produced no verdict (exit $rc); last lines:" >&2 | ||
| tail -n 20 "$LOG" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| facts=$(gh pr view "$PR_URL" --json state,isDraft,headRefOid,reviewDecision,mergeStateStatus,labels,reviews 2>/dev/null \ | ||
| | jq -c --arg holds "needs-human-review dev-lead:needs-human dev-lead:hands-off initiative:hold" ' | ||
|
don-petry marked this conversation as resolved.
Resolved
|
||
| .headRefOid as $head | ||
|
don-petry marked this conversation as resolved.
Resolved
|
||
| | {state, isDraft, reviewDecision, mergeStateStatus, | ||
| holds: [(.labels // [])[].name | select(. as $l | ($holds | split(" ") | index($l)))], | ||
| approvals_at_head: [(.reviews // [])[] | ||
| | select(.state == "APPROVED" and (.commit.oid // "") == $head) | ||
| | (.author.login // "?")] | unique}' 2>/dev/null || echo '{}') | ||
|
don-petry marked this conversation as resolved.
Resolved
|
||
|
|
||
| report=$(jq -cn --argjson v "$verdict" --argjson f "$facts" --arg log "$(grep -E '^ ' "$LOG" || true)" \ | ||
| '$v + {facts: $f, gate_log: $log}') | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
|
|
||
| if [ "$FORMAT" = "json" ]; then | ||
| printf '%s\n' "$report" | ||
| exit 0 | ||
| fi | ||
|
|
||
| jq -r ' | ||
| def code: "`" + (. // "") + "`"; | ||
| .facts as $f | ||
| | (if ($f.reviewDecision // "") == "APPROVED" | ||
| then "**Approved.** Merge state: " + (($f.mergeStateStatus // "unknown") | code) + "." | ||
| else "**Not approved** (review decision: " + (($f.reviewDecision // "none") | if . == "" then "none" else . end | code) + ")." | ||
| end) as $status | ||
| | [ "## pr-review approval diagnostic: " + .pr, | ||
| "", | ||
| $status, | ||
| "", | ||
| "| | |", | ||
| "|---|---|", | ||
| "| Head | " + ((.sha // "")[0:8] | code) + " |", | ||
| "| What pr-review would do now | " + (.decision | code) + " — " + (.reason | code) + " |", | ||
| "| What changes that | " + ((.would_change // "") | gsub("\\|"; "\\|")) + " |", | ||
| "| Hold labels | " + (if (($f.holds // []) | length) > 0 then ($f.holds | map(code) | join(", ")) else "none" end) + " |", | ||
| "| Approvals at head | " + (if (($f.approvals_at_head // []) | length) > 0 then ($f.approvals_at_head | join(", ")) else "none" end) + " |", | ||
| "", | ||
| (if .decision == "proceed" | ||
| then "No gate holds this PR: the next pr-review run reviews it, and that review decides." | ||
| else "This is the first gate that holds the PR, in the order a pr-review run checks them. Gates after it were not evaluated." | ||
| end), | ||
| "", | ||
| "<details><summary>Gate log</summary>", | ||
| "", | ||
| "```", | ||
| .gate_log, | ||
| "```", | ||
| "</details>" | ||
| ] | join("\n")' <<<"$report" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.