Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
212 commits
Select commit Hold shift + click to select a range
b4cf3d2
Add scheduled PR review agent
Apr 8, 2026
52f75c6
Use Claude Code OAuth token instead of API key
Apr 9, 2026
2b8e593
Enforce single-PR scope and default to dry-run
Apr 9, 2026
51a5e68
Add 3-model council + commit-SHA-aware iterative review
Apr 9, 2026
7260226
Upgrade maintainability lens from Haiku 4.5 to Sonnet 4.6
Apr 9, 2026
3b52fde
Go-live improvements for PR review agent (#2)
don-petry Apr 9, 2026
2e610a0
Add Claude delegation, auto-merge, and rebase handling (#3)
don-petry Apr 10, 2026
112be95
Optimize review: small-PR and incremental fast paths (#4)
don-petry Apr 10, 2026
011fefb
Add Claude Code workflow (#8)
don-petry Apr 16, 2026
8ee26c0
feat: add Copilot engine support via REVIEW_ENGINE toggle (#5)
don-petry Apr 16, 2026
5221173
feat: inline Claude Code workflow to access repo secrets directly (#9)
don-petry Apr 16, 2026
1097c2a
feat: cross-engine adversarial rubber duck review (#11)
don-petry Apr 16, 2026
1803b9a
fix: filter already-reviewed PRs from backlog to unblock queue
Apr 16, 2026
36344dd
docs: clarify PR review batching issue
Apr 16, 2026
f6a32e9
fix: complete PR #10 fix - don't count no-ops toward MAX_PRS budget
Apr 16, 2026
74ecefc
feat: CI gate + poll-loop rebase wait across all review prompts (#14)
don-petry Apr 18, 2026
430bd84
fix: replace --checks passing with --checks success in list-prs.sh (#15)
don-petry Apr 19, 2026
7cd441a
docs: update repo references from self to pr-review-agent
Apr 21, 2026
d0f17d1
feat: add car-hunt skill for used vehicle research and ranking
Apr 25, 2026
66489b1
fix: fix FB Marketplace links, improve AutoTrader fetch, add Sheets e…
Apr 25, 2026
e31218c
fix: add Craigslist as explicit source, enforce real-URL-only link rule
Apr 25, 2026
ba0e0dc
fix: split zip/radius questions, rename MAX_MILES to MAX_ODOMETER
Apr 25, 2026
cf954e3
fix: include self-authored PRs awaiting review in agent enumeration (…
don-petry Apr 25, 2026
451c5a2
feat: add doors/transmission fields, update-mode sheet, fix CarGurus/…
Apr 25, 2026
57a0acb
feat: add hard disqualification filters for finance-speak, title issu…
Apr 25, 2026
7eb9f3c
feat: add Distance to Car field using Nominatim geocoding + Haversine…
Apr 25, 2026
4315cd9
fix: address low result count — batch URL extraction, preview-filter …
Apr 25, 2026
e9b3ee0
fix: make cascade-action prompt explicit about gh pr review --approve
Apr 25, 2026
cc87f3e
improve: make cascade-action body composition and escalation more exp…
Apr 25, 2026
42981b3
refactor: move review posting logic from agent prompts to bash script
Apr 25, 2026
c7e0a0c
add: cleanup script to fix PRs with comment approvals instead of revi…
Apr 25, 2026
8df6533
fix: cleanup script now requires bot account token
Apr 25, 2026
810075a
add: workflow to fix stuck PRs using bot account token
Apr 25, 2026
8c30e3c
fix: pass GH_PAT to checkout action so workflow uses bot account
Apr 25, 2026
b24562e
debug: simplify account check, add authentication debug output
Apr 25, 2026
d991daf
docs: add comprehensive petry-review-bot setup instructions
Apr 25, 2026
887fd36
docs: add GitHub App setup guide (recommended approach)
Apr 26, 2026
089dd0d
docs: add comprehensive GitHub App setup documentation
Apr 26, 2026
3e634cc
fix: silence auth check in fix-stuck-prs when using GitHub App token
Apr 26, 2026
0ef47ad
fix: use explicit author instead of @me in stuck PR search
Apr 26, 2026
9cae703
fix: avoid subshell in while loop to preserve variable state
Apr 26, 2026
79d7a98
docs: add comprehensive status report for GitHub App setup
Apr 27, 2026
676886b
docs: document stuck PR cleanup status and script fixes
Apr 28, 2026
b19f930
fix: update list-prs.sh to search all repos by owner instead of @me
Apr 28, 2026
fc2e295
docs: add investigation report for PR review agent workflow failures
Apr 28, 2026
cbb660c
fix: move env section before steps in workflow to fix YAML structure
Apr 28, 2026
b8d4cc4
script: add backfill-approvals to retroactively apply real approvals
Apr 28, 2026
3d1a8c5
feat: add backfill-approvals workflow to run as GitHub App bot
Apr 28, 2026
e749b9f
fix: convert inner while loop to process substitution to preserve cou…
Apr 28, 2026
a358f26
car-hunt: add VIN-deep-dive flow, printable checklists, location-tier…
Apr 28, 2026
ba194c8
fix: re-approve PRs where approval predates last commit (stale approval)
Apr 28, 2026
77b40b0
fix: robustly extract JSON verdict from mixed claude --print output (…
don-petry Apr 28, 2026
5cd2c7a
fix: extract_verdict_json — check dest file first (agent Bash-write s…
don-petry Apr 29, 2026
f683c3c
Enforce MAX_REVIEW_CYCLES cap before running the cascade (#18)
don-petry Apr 29, 2026
b6bd1a3
Reliability hardening: session circuit breaker, timeouts, retry, dedu…
don-petry Apr 29, 2026
182cdb3
Remove car-hunt skill and scheduled tasks (moved to don-petry/don-pet…
don-petry Apr 30, 2026
19ed210
fix: apply Copilot fallback hardening and reuse GH_PAT for Copilot auth
don-petry May 3, 2026
bf08cd5
fix: switch Copilot engine to gh built-in and fix app-id deprecation
don-petry May 3, 2026
0e55239
fix: harden Copilot fallback path and remove stale worktrees (#25)
claude[bot] May 3, 2026
eb5c956
ci: add pre-flight dedup check to prevent duplicate claude-issue PRs …
don-petry May 3, 2026
b98ac4b
refactor: migrate to machine user PAT auth (closes #27) (#28)
don-petry May 5, 2026
3d2ab92
refactor: merge approval repair scripts into single automation
don-petry May 5, 2026
e6556fd
feat: add @mention trigger for on-demand PR reviews (#30)
don-petry May 6, 2026
ca5e3ce
fix: harden rebase, review dismissal, and health log diagnostics (#40)
don-petry May 7, 2026
abe60ed
refactor: migrate to org-wide .github-private convention (#41)
don-petry May 7, 2026
9d4fee2
ci: add dependabot-automerge.yml workflow (#73)
don-petry May 10, 2026
cf6bd36
fix(pr-review): unblock queue starvation from self-authored PRs (#96)…
don-petry May 10, 2026
da6e047
chore: rename GH_PAT_WORKFLOWS secret to DON_PETRY_BOT_GH_PAT (#99)
don-petry May 10, 2026
2dd930f
chore: remove frameworks directory (#101)
don-petry May 10, 2026
8134ab0
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
72fb9e2
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
8b99bed
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
0fd43dc
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
6eabaa1
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
a665c8f
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
d352347
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
7e887d2
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
ba955a6
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
eab7c42
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
d7cca26
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
7963c8d
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
8181ba4
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
0c835df
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
5cd0bf2
chore: deprecate pr-review-agent — remove all traces
don-petry May 11, 2026
c684af5
revert: restore all erroneously deleted files (items 4-34) (#104)
don-petry May 11, 2026
339c78c
feat: add Gemini Pro support and optimize PR review fallback chain (#…
don-petry May 11, 2026
363d479
fix(pr-review): gate rate-limit detection on non-zero exit code
May 11, 2026
3d1df0d
fix(claude): sync inlined workflow with org standard (#109)
don-petry May 11, 2026
c0464a1
ci: replace inlined claude.yml with standard thin-caller stub
don-petry May 11, 2026
9a978b3
ci: pin dependabot-automerge reusable workflow to SHA (#130)
don-petry May 12, 2026
714592b
fix: replace gh copilot suggest with GitHub Models REST API (#151)
don-petry May 12, 2026
e83c31f
feat: prioritise .github/.github-private PRs, oldest-first within tie…
don-petry May 13, 2026
d820f07
fix: restore pr-review.yml content (accidentally emptied in revert)
don-petry May 13, 2026
3cde2ec
fix: restore pr-review.yml (file was accidentally emptied)
don-petry May 13, 2026
998b1ba
chore(deps): bump petry-projects/.github/.github/workflows/dependency…
dependabot[bot] May 13, 2026
dffdda4
chore(deps): bump actions/cache from 4 to 5 (#165)
dependabot[bot] May 13, 2026
5e1bfad
chore(deps): bump petry-projects/.github/.github/workflows/claude-cod…
dependabot[bot] May 13, 2026
e2b0d81
chore(deps): bump petry-projects/.github/.github/workflows/dependabot…
dependabot[bot] May 13, 2026
e9ff8ad
fix(list-prs): search DELEGATION_ORGS and drop --checks success pre-f…
don-petry May 13, 2026
16d1661
chore(deps): bump petry-projects/.github/.github/workflows/dependabot…
dependabot[bot] May 14, 2026
44b89fb
feat(prompts/dev-lead): add human prompt template
don-petry May 15, 2026
e01e770
feat(prompts/dev-lead): add human-pr prompt template
don-petry May 15, 2026
bde841b
feat(dev-lead): implement dev-lead agent Phases 0-6
don-petry May 15, 2026
4264782
feat(dev-lead): Phase 1.5 — reusable workflow for cross-repo adoption…
don-petry May 15, 2026
95e5220
fix(dev-lead): PR-level exhaustion guard prevents token waste on larg…
don-petry May 15, 2026
9cebc09
fix(dev-lead): rate-limit detection, separate status, and retry cron …
don-petry May 16, 2026
6a17262
fix(pr-review): handle Gemini trust-mode failure and properly route e…
don-petry May 17, 2026
3d126b7
fix: resolve YAML syntax error in dev-lead-reusable workflow
May 17, 2026
63c024c
fix: address automated feedback from PR 217 (#219)
don-petry May 17, 2026
3c28380
chore: remove Phase 7 shadow period comment from dev-lead.yml
don-petry May 17, 2026
f5de7b8
feat: skip PRs with CHANGES_REQUESTED review (+ FORCE_REVIEW and stal…
don-petry May 17, 2026
d8a7f17
fix(dev-lead): resolve context loss, missing checkout, and push logic…
don-petry May 17, 2026
6d415c7
test: bypass CI check
May 17, 2026
3a03ab6
fix(pr-review): remove CI bypass hack
May 17, 2026
f83143b
fix(dev-lead): use heredoc for multiline environment variables (#224)
don-petry May 17, 2026
d6b5da7
fix(dev-lead): detect engine-committed changes and remove commit inst…
May 18, 2026
03574db
fix(dev-lead): address PR review findings — untracked files, upstream…
May 18, 2026
61acaa1
fix(pr-review): robust engine fallback and context optimization (#227)
don-petry May 18, 2026
c141a9a
fix(dev-lead): handle SonarQube Quality Gate failures (issue #279) (#…
don-petry May 19, 2026
847a7a2
fix(dev-lead): configure git identity, surface commit/push failures, …
don-petry May 19, 2026
022c063
fix(dev-lead): resolve review threads after fixing + notify CodeRabbi…
don-petry May 19, 2026
2ee58e5
fix(dev-lead): post @coderabbitai resolve on no-changes + enable auto…
don-petry May 20, 2026
eb29802
fix(dev-lead): relay check_run id, verify engine CLI, improve SonarCl…
don-petry May 20, 2026
13caa32
ci: add required ci.yml workflow
don-petry May 20, 2026
bd7d290
feat: implement issue #233 — Phase 2: CI Failure Analyst gh-aw workfl…
don-petry May 20, 2026
37ea531
chore(deps): bump actions/cache from 4.3.0 to 5.0.5 (#310)
dependabot[bot] May 20, 2026
7771467
fix: address open review findings from PR #102 (#108)
don-petry May 20, 2026
5c03b51
fix(ci): move shopt before yamllint call (fixes syntax error)
don-petry May 20, 2026
f573d01
fix(dev-lead): configure git user identity in fix-issue script (#326)
don-petry May 20, 2026
b1fea8a
feat: implement issue #232 — Phase 1: Issue Triage gh-aw workflow (#284)
don-petry May 20, 2026
733a7dc
style(ci): remove trailing blank line to fix yamllint recurring failure
don-petry May 20, 2026
29d6afd
feat: implement issue #183 — Compliance: non-stub-claude.yml (#328)
don-petry May 20, 2026
1c0aa1b
feat: implement issue #135 — Compliance: unpinned-actions-claude.yml …
don-petry May 21, 2026
82ac9e6
feat: token cost observatory — ET metric + JSONL logging (#334)
don-petry May 21, 2026
1830685
feat: implement issue #184 — Compliance: non-stub-dependency-audit.ym…
don-petry May 21, 2026
ac70389
chore(deps): bump petry-projects/.github/.github/workflows/dependency…
dependabot[bot] May 21, 2026
c27be01
feat(fleet-monitor): summarize token usage by workflow (#343)
don-petry May 21, 2026
eb22b6a
feat(dev-lead): harden agent instructions with Plan→TDD→Verify→Rubber…
don-petry May 23, 2026
627ea68
feat: implement issue #365 — dev-lead: preserve session output in Act…
don-petry May 23, 2026
5939abc
fix(dev-lead): visible no-changes comments, ACTOR strip, full secret …
don-petry May 23, 2026
cbc307f
add: force-deploy-pr-review workflow for branch-protection bypass
Jun 3, 2026
d8c7113
add: pr-review-reusable.yml wrapper for workflow_call pattern
Jun 4, 2026
93b06f4
fix: explicitly pass secrets in pr-review-reusable.yml workflow_call
Jun 4, 2026
d93cc2b
feat: implement issue #425 — dev-lead: Incomplete issue resolution - …
don-petry Jun 4, 2026
7847b04
debug: pr-review enumeration logging (#410)
don-petry Jun 4, 2026
dfa53e8
chore(deps): bump actions/checkout from 4 to 6 (#433)
dependabot[bot] Jun 4, 2026
7ad76ad
merge: PR #353 - PR Review Agent diagnostics and transient failure ha…
Jun 4, 2026
12aa711
merge: PR #422 - Add deploy-pr-review.yml workflow for branch protect…
Jun 4, 2026
65e22e9
fix(ci): strip trailing whitespace from deploy-pr-review workflows (#…
don-petry Jun 6, 2026
5bbfb8a
fix: support fine-grained tokens in pr-review scope validation (#443)
don-petry Jun 6, 2026
4d5667d
fix(dev-lead): auto-resolve outdated bot threads and treat unresolved…
don-petry Jun 6, 2026
240bf30
feat(dev-lead): enable auto-merge (squash) by default on every PR it …
don-petry Jun 6, 2026
f2f5a58
fix(dev-lead): check out PR branches in an isolated worktree (#448) (…
don-petry Jun 7, 2026
e4f1000
feat(token-report): org-wide weekly Token Cost Observatory report (#456)
don-petry Jun 7, 2026
c102582
fix(token-metrics): key usage sidecar per-call, not by $$ (concurrenc…
don-petry Jun 7, 2026
d07af0d
fix(dev-lead): hold auto-merge while working a PR + push defensively …
don-petry Jun 7, 2026
0c71f79
fix(dev-lead): stop false "rate-limited" claims; dedupe superseded ch…
don-petry Jun 7, 2026
c179acc
fix(engine): handle gemini quota exhaustion and capture stderr (#226)
don-petry Jun 8, 2026
ad037da
feat: implement issue #396 — Compliance: non-stub-dependency-audit.ym…
don-petry Jun 8, 2026
3ee2e2a
feat: implement issue #438 — Compliance: unpinned-actions-deploy-pr-r…
don-petry Jun 8, 2026
eaa3a5a
feat: implement issue #400 — petry-projects — workflow failures detec…
don-petry Jun 8, 2026
412d588
feat: implement issue #402 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 8, 2026
4745781
feat: implement issue #404 — PR Review Agent — failures detected 2026…
don-petry Jun 8, 2026
d0c8092
feat: implement issue #407 — PR Review Agent — failures detected 2026…
don-petry Jun 9, 2026
727fb74
feat: implement issue #511 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 10, 2026
bcb864d
feat: implement issue #272 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 10, 2026
480c95e
feat: implement issue #512 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 10, 2026
feedeb4
feat: implement issue #140 — Compliance: non-stub-dependabot-automerg…
don-petry Jun 10, 2026
45f9e90
feat: implement issue #408 — petry-projects — workflow failures detec…
don-petry Jun 10, 2026
5a8a76d
feat: implement issue #395 — Compliance: non-stub-dev-lead.yml (#488)
don-petry Jun 10, 2026
f4c1bb8
chore: retire deploy-pr-review, force-deploy, and pr-review-reusable …
don-petry Jun 10, 2026
c05eaad
feat: implement issue #545 — Compliance: non-stub-dependency-audit.ym…
don-petry Jun 10, 2026
b40306d
feat: implement issue #195 — bug(dev-lead): engine.sh defines multi-t…
don-petry Jun 11, 2026
3d34849
chore(frameworks): vendor BMAD Method v6.8.0 + Test Architect v1.19.0…
don-petry Jun 11, 2026
e9f3c80
feat: implement issue #244 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 11, 2026
fdc9271
fix(engine): reorder cross-provider fallback to claude → copilot → ge…
don-petry Jun 12, 2026
d232a10
feat: implement issue #574 — pr-review: PRs with >300 changed files h…
don-petry Jun 12, 2026
091b261
chore(deps): bump the actions group across 1 directory with 8 updates…
dependabot[bot] Jun 13, 2026
ef28203
fix(initiative-planner): restore discussion→workflow_dispatch redispa…
don-petry Jun 13, 2026
4def9f6
feat: implement issue #677 — [Phase 1] Thread an optional MCP config …
don-petry Jun 14, 2026
fc49088
feat: implement issue #678 — [Phase 1] Graceful degradation: warn (ne…
don-petry Jun 14, 2026
20ae2c1
feat: implement issue #582 — [Phase 1] Define held-out eval-case form…
don-petry Jun 14, 2026
539b1a4
feat: implement issue #691 — Held-out hygiene: dev/holdout eval split…
don-petry Jun 14, 2026
df41891
feat: implement issue #583 — deterministic eval scorer (triage) over …
don-petry Jun 14, 2026
c577b05
feat: implement issue #382 — Enhance dev-lead and pr-review engines f…
don-petry Jun 15, 2026
609879d
feat: implement issue #547 — Compliance: secret_scan_ci_job_present (…
don-petry Jun 16, 2026
bf28fc6
feat: implement issue #143 — Compliance: secret_scanning_non_provider…
don-petry Jun 16, 2026
d658d57
feat: implement issue #695 — [Fleet Monitor] petry-projects/.github-p…
don-petry Jun 17, 2026
83222af
feat: implement issue #773 — pr-review: rubber-duck tier broken under…
Jun 18, 2026
40db5f1
chore: apply manual instructions [skip ci-relay]
donpetry-bot Jun 18, 2026
b1e76e8
feat: implement issue #796 — Compliance: non-stub-dependency-audit.ym…
don-petry Jun 19, 2026
23b7a09
feat: implement issue #797 — Compliance: non-stub-dependabot-automerg…
don-petry Jun 19, 2026
7d73e08
feat(dev-lead): retry failed initial issue implementations, never sil…
don-petry Jun 20, 2026
b89c8f8
test(dogfood): comment-only touch to exercise downstream-impact on ne…
don-petry Jun 21, 2026
7851eac
revert(dogfood): remove ci-status.sh dogfood comment + re-prove downs…
don-petry Jun 21, 2026
a539f12
fix(ci): auto-fix for .github/dependabot.yml [skip ci-relay]
donpetry-bot Jun 21, 2026
048bc15
chore: apply manual instructions [skip ci-relay]
donpetry-bot Jun 21, 2026
c9abcc0
fix: remove duplicate function definitions and gemini case arms from …
donpetry-bot Jun 21, 2026
e828e2b
chore: apply manual instructions [skip ci-relay]
donpetry-bot Jun 21, 2026
502dd64
fix(reviews): address review comments [skip ci-relay]
donpetry-bot Jun 21, 2026
d6de64b
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 21, 2026
03a02c8
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 21, 2026
0a30413
fix(bot): address bot feedback [skip ci-relay]
donpetry-bot Jun 22, 2026
8688def
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 22, 2026
0717856
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 22, 2026
8dfc291
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 22, 2026
5ee5409
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 22, 2026
1a3f9b4
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 23, 2026
5401830
chore: apply manual instructions [skip ci-relay]
donpetry-bot Jun 23, 2026
af82806
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 23, 2026
f1b68bb
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 23, 2026
57e5fb4
Merge branch 'main' into dev-lead/issue-773-20260618-0037
don-petry Jun 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions prompts/cascade-action.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ cat > /tmp/cascade/review-body.txt << 'BODYEOF'
### Summary
PLACEHOLDER_SUMMARY

### Cross-engine agreement (if deep+duck)
<If tier is deep+duck and agreement field exists, include this section>

### Findings
PLACEHOLDER_FINDINGS_LIST

Expand Down
17 changes: 17 additions & 0 deletions scripts/dev-lead-fix-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,23 @@ ${details}"
fi
}

post_exhaustion() {
local reason="$1"
local body="${EXHAUSTION_MARKER}
## Dev-Lead Fix CI — exhausted

This PR has had **${MAX_FAIL_ATTEMPTS}** consecutive engine failures (timeouts or errors). Automated CI fixing has been paused to avoid consuming further tokens.

**Reason for last failure:** ${reason}

To re-enable, delete this comment or push a new commit with a substantially different change."
if [ "${DEV_LEAD_DRY_RUN:-false}" = "true" ]; then
echo "[dry-run] would post exhaustion comment"
else
gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$body"
fi
}

main() {
if [ -z "$PR_NUMBER" ] || [ -z "$HEAD_SHA" ]; then
echo "::error::PR_NUMBER and HEAD_SHA are required"
Expand Down
338 changes: 338 additions & 0 deletions scripts/dev-lead-fix-reviews.sh

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions scripts/engine.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ set -euo pipefail
REVIEW_ENGINE="${REVIEW_ENGINE:-claude}"
export REVIEW_ENGINE

# Cross-engine rubber-duck model (issue #773). The duck deliberately routes to
# Copilot/o4-mini even when the primary engine is NOT copilot (e.g. the default
# claude engine sets DUCK_ENGINE=copilot for adversarial diversity), so
# copilot_chat() may dereference COPILOT_API_MODEL regardless of REVIEW_ENGINE.
# Default it here — engine-agnostic — so the duck always has a model under
# `set -u`. The `copilot)` arm in set_engine_config re-applies the same default
# (idempotent) for the primary-engine path.
DEFAULT_COPILOT_API_MODEL="openai/o4-mini"
COPILOT_API_MODEL="${COPILOT_API_MODEL:-$DEFAULT_COPILOT_API_MODEL}"
export COPILOT_API_MODEL

# Per-tier timeouts (seconds). The job-level 60min cap is a backstop — without
# per-tier timeouts a single hung model invocation burns the whole hour and
# blocks every subsequent PR in the session.
Expand Down
18 changes: 18 additions & 0 deletions scripts/list-prs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@
# 2. All other repos (priority 1)
# Within each priority tier, PRs are sorted oldest-first by createdAt.
#
# Filters:
# --draft=false — skip work-in-progress PRs
#
# CI filtering is intentionally omitted here — review-one-pr.sh enforces it
# per-PR as a second layer. Filtering by --checks success would exclude repos
# with no CI configured (GitHub treats "no checks" as not matching --checks
# success), causing their PRs to never enter the candidate pool.
#
# Self-authored PRs (PRs whose author is $BOT_USER) are excluded here, because
# GitHub's GraphQL API rejects self-approval unconditionally — including such a
# PR in the queue previously triggered a fatal session abort that starved every
# subsequent candidate (see issue #96).
#
# Output ordering (stable, deterministic):
# 1. .github and .github-private PRs first (priority 0)
# 2. All other repos (priority 1)
# Within each priority tier, PRs are sorted oldest-first by createdAt.
#
# Output: one PR URL per line on stdout.

set -euo pipefail
Expand Down
130 changes: 68 additions & 62 deletions scripts/pr_review_health.sh
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
#!/usr/bin/env bash
# Daily health check for the PR Review Agent workflow.
# Daily telemetry check for the PR Review Agent workflow.
#
# Fetches recent pr-review.yml run logs, feeds them to Claude for pattern
# analysis, and writes a markdown report to pr_review_health_report.md.
# Sets HAS_FAILURES=true in $GITHUB_ENV when failed runs are detected.
# Fetches recent pr-review.yml run data, computes health metrics, and
# writes a structured markdown report to both GITHUB_STEP_SUMMARY and
# pr_review_health_report.md. Sets HAS_FAILURES=true in GITHUB_ENV when
# failed runs are detected.
#
# Env vars consumed:
# GH_TOKEN — primary (GitHub App; must have actions:read on this repo)
# GH_PAT_FALLBACK — fallback PAT if App token lacks access
# CLAUDE_CODE_OAUTH_TOKEN — passed through to claude CLI
# LOOKBACK_DAYS — days of history to consider (default: 1, ~24 hours)
# Set higher to examine longer windows (e.g., LOOKBACK_DAYS=7 for weekly review)
# GITHUB_ENV — written by Actions runner; used to export HAS_FAILURES
# GH_TOKEN — must have actions:read on WORKFLOW_REPO
# LOOKBACK_DAYS — days of history to consider (default: 1)
# GITHUB_ENV — written by Actions runner
# GITHUB_STEP_SUMMARY — written by Actions runner

set -euo pipefail

LOOKBACK_DAYS="${LOOKBACK_DAYS:-1}"
WORKFLOW_REPO="${AGENT_REPO:-petry-projects/.github-private}"
WORKFLOW_FILE="pr-review-trigger.yml"
REPORT_FILE="pr_review_health_report.md"
LOG_DIR="health_run_logs"
TODAY=$(date -u +%Y-%m-%d)

echo "=== PR Review Agent — Daily Health Check ==="
Expand All @@ -30,41 +28,42 @@ echo " Date: $TODAY"
echo ""

# ---------------------------------------------------------------------------
# 0. Token selection — verify GH_TOKEN has access to workflow run logs
# 0. Token selection
# ---------------------------------------------------------------------------
if ! gh api "repos/${WORKFLOW_REPO}/actions/workflows/${WORKFLOW_FILE}/runs?per_page=1" \
>/dev/null 2>&1; then
if [ -n "${GH_PAT_FALLBACK:-}" ]; then
echo "::warning::App token cannot access ${WORKFLOW_REPO} run logs — using GH_PAT_FALLBACK"
echo "::warning::GH_TOKEN cannot access ${WORKFLOW_REPO} — using GH_PAT_FALLBACK"
export GH_TOKEN="$GH_PAT_FALLBACK"
else
echo "::error::App token cannot access ${WORKFLOW_REPO} run logs and GH_PAT_FALLBACK is not set."
echo "::error::Grant the GitHub App access to ${WORKFLOW_REPO} or set the DON_PETRY_BOT_GH_PAT secret."
echo "::error::GH_TOKEN cannot access ${WORKFLOW_REPO} and GH_PAT_FALLBACK is not set."
exit 1
fi
fi

# ---------------------------------------------------------------------------
# 1. Fetch recent run metadata
# 1. Fetch run metadata
# ---------------------------------------------------------------------------
# GNU date: date -d "N days ago"; macOS: date -v-Nd
CUTOFF=$(date -u -d "${LOOKBACK_DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -v-"${LOOKBACK_DAYS}"d +%Y-%m-%dT%H:%M:%SZ)

echo "Fetching all runs since: $CUTOFF"
# Fetch with per_page=100 (GitHub API max) to capture all runs in the lookback window.
# Time-based filtering ensures we get every run created at or after CUTOFF, regardless of quantity.
echo "Fetching runs since: $CUTOFF"

runs_json=$(gh api \
"repos/${WORKFLOW_REPO}/actions/workflows/${WORKFLOW_FILE}/runs?per_page=100&created=>=${CUTOFF}" \
--jq '.workflow_runs | map({
id: .id,
run_number: .run_number,
status: .status,
conclusion: .conclusion,
created_at: .created_at,
html_url: .html_url,
run_number: .run_number
duration_s: ((.updated_at | fromdate) - (.created_at | fromdate))
})' 2>/dev/null || echo '[]')

# ---------------------------------------------------------------------------
# 2. Compute aggregate stats
# ---------------------------------------------------------------------------
read -r total_runs failed_runs success_runs cancelled_runs < <(echo "$runs_json" | jq -r '
[
length,
Expand All @@ -73,56 +72,63 @@ read -r total_runs failed_runs success_runs cancelled_runs < <(echo "$runs_json"
([.[] | select(.conclusion == "cancelled")] | length)
] | @tsv')

echo " Total runs: $total_runs"
echo " Successful: $success_runs"
echo " Failed: $failed_runs"
echo " Cancelled: $cancelled_runs"
echo ""
echo " Total: $total_runs"
echo " Success: $success_runs"
echo " Failed: $failed_runs"
echo " Cancelled: $cancelled_runs"

# ---------------------------------------------------------------------------
# 2. Early exit when no failures
# ---------------------------------------------------------------------------
if [ "$failed_runs" -eq 0 ]; then
echo "No failed runs in the last ${LOOKBACK_DAYS} days. Health check passed."
printf '# PR Review Agent Health Check — %s\n\nAll %d run(s) inspected over the last %d days succeeded. No action required.\n' \
"$TODAY" "$total_runs" "$LOOKBACK_DAYS" > "$REPORT_FILE"
exit 0
if [ "$total_runs" -gt 0 ]; then
failure_rate=$(echo "scale=1; $failed_runs * 100 / $total_runs" | bc)
else
failure_rate="0.0"
fi

# Export flag for workflow step condition
[ -n "${GITHUB_ENV:-}" ] && echo "HAS_FAILURES=true" >> "$GITHUB_ENV"
# Duration percentiles across all completed runs (computed but not surfaced in the
# LLM prompt — reserved for future structured-report use).
# shellcheck disable=SC2034
read -r dur_min dur_p50 dur_p95 dur_max < <(echo "$runs_json" | jq -r '
[.[] | select(.conclusion != null and .duration_s > 0) | .duration_s] | sort |
if length == 0 then "0 0 0 0"
else . as $d | ($d | length) as $n |
"\($d | min) \($d[$n * 50 / 100 | floor]) \($d[$n * 95 / 100 | floor]) \($d | max)"
end')

# ---------------------------------------------------------------------------
# 3. Download logs for failed runs
# 3. Helpers
# ---------------------------------------------------------------------------
mkdir -p "$LOG_DIR"
failed_run_ids=$(echo "$runs_json" | jq -r '.[] | select(.conclusion == "failure") | .id')

for run_id in $failed_run_ids; do
{
gh run view "$run_id" --repo "$WORKFLOW_REPO" --log 2>/dev/null \
| head -c 200000 \
> "${LOG_DIR}/run_${run_id}.txt" \
|| echo "(log unavailable for run $run_id)" > "${LOG_DIR}/run_${run_id}.txt"
} &
done
wait

# Surface log-retrieval failures so the operator knows the diagnosis may be incomplete.
missing_logs=0
for run_id in $failed_run_ids; do
if grep -q "^(log unavailable" "${LOG_DIR}/run_${run_id}.txt" 2>/dev/null; then
echo "::warning::Failed run $run_id: log could not be retrieved — diagnosis will be incomplete for this run"
missing_logs=$((missing_logs + 1))
fmt_dur() {
local s=$1
if [ "$s" -ge 60 ]; then
printf '%dm%ds' $((s / 60)) $((s % 60))
else
printf '%ds' "$s"
fi
done
if [ "$missing_logs" -gt 0 ]; then
echo " $missing_logs of $failed_runs failed run log(s) could not be retrieved"
}

conclusion_icon() {
case "$1" in
success) echo "✅" ;;
failure) echo "❌" ;;
cancelled) echo "⚪" ;;
skipped) echo "⏭️" ;;
*) echo "⏳" ;;
esac
}

# overall is the pre-computed status fed as a hint to the LLM prompt below.
# shellcheck disable=SC2034
if [ "$failed_runs" -eq 0 ]; then
overall="HEALTHY"
elif [ "$(echo "$failure_rate > 50" | bc)" -eq 1 ]; then
overall="CRITICAL"
elif [ "$(echo "$failure_rate > 20" | bc)" -eq 1 ]; then
overall="DEGRADED"
else
overall="WARNING"
fi
echo ""

# ---------------------------------------------------------------------------
# 4. Fetch workflow source for token/permission context
# 4. Build report
# ---------------------------------------------------------------------------
[ -n "${GITHUB_ENV:-}" ] && {
if [ "$failed_runs" -gt 0 ]; then
Expand Down Expand Up @@ -242,4 +248,4 @@ rm -f "$logs_file"

echo ""
echo "Report written to $REPORT_FILE ($(wc -c < "$REPORT_FILE") bytes)"
echo "=== Health check complete ==="
echo "=== Health check complete ==="
18 changes: 18 additions & 0 deletions scripts/review-one-pr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,24 @@ fi
fi
}

# Skip when a human has requested changes, with two guards:
# 1. FORCE_REVIEW bypasses the skip — mention-triggered runs always proceed so
# authors can request a re-review after addressing feedback.
# 2. Only skip when a CHANGES_REQUESTED review targets the current head SHA.
# On repos that don't dismiss stale reviews, reviewDecision can stay
# CHANGES_REQUESTED after the author pushes new commits; in that case the
# review is stale and the cascade should re-engage with the updated code.
if [ "$REVIEW_DECISION" = "CHANGES_REQUESTED" ] && [ "${FORCE_REVIEW:-false}" != "true" ]; then
CHANGES_REQUESTED_AT_HEAD=$(echo "$PR_SNAPSHOT" | jq -r --arg sha "$PR_HEAD_SHA" '
[.reviews[] | select(.state == "CHANGES_REQUESTED" and .commit.oid == $sha)]
| if length > 0 then "true" else "false" end
')
if [ "$CHANGES_REQUESTED_AT_HEAD" = "true" ]; then
echo " skip: changes requested at current head — awaiting author response before reviewing"
echo "{\"pr\":\"$PR_URL\",\"sha\":\"$PR_HEAD_SHA\",\"decision\":\"skip\",\"reason\":\"changes-requested\"}"
exit 100
fi
fi
# Skip when a human has requested changes, with two guards:
# 1. FORCE_REVIEW bypasses the skip — mention-triggered runs always proceed so
# authors can request a re-review after addressing feedback.
Expand Down
Loading
Loading