feat(pr-automation): add PR automation orchestrator with label state machine#1874
Merged
feat(pr-automation): add PR automation orchestrator with label state machine#1874
Conversation
added 30 commits
March 26, 2026 15:21
… and PID-based lock
…ariable in Step 4
… and new label state machine
…ude, timeout kill, detailed logging)
…p comments, auto-rebase, remove status board
…ushing to any branch
…o 60s - Add --output-format stream-json --verbose to capture structured output - Extract session_id from first JSON message and log with each iteration - Change process poll interval from 5s to 60s to reduce unnecessary CPU usage
added 28 commits
March 26, 2026 22:15
Each EXIT point in the skill now logs a [pr-automation:exit] line with action, PR number, and reason. The daemon script parses this line and duration_ms from the session log after each Claude run, producing a single-line summary in the main log. Falls back to ELAPSED if duration_ms is unavailable.
Worst-case exit detection latency was 60s, causing up to 90s gap between iterations (60s poll + 30s sleep). is negligible overhead, so 10s is a reasonable balance.
LOW issues are non-blocking and low priority — skip them during automated fix runs. Add a note in the verification report explaining why they are skipped.
Add [pr-automation:skip] log markers to all 'find next PR' paths in the skill (ci_running, ci_failure_dedup, merge_unknown, conflict_dedup), and update the daemon script to collect all exit/skip markers instead of only the last one, printing multi-action summaries when a session processes multiple PRs.
- Fix skill table: replace cron/Chinese description with accurate English - Fix run mode: daemon loop, not cron job - Fix label name: bot:needs-fix -> bot:ready-to-fix - Remove operational 'how to block' detail (covered in pr-automation.md)
- Add NEEDS_HUMAN_REVIEW gate: PRs with >50 files changed or matching CRITICAL_PATH_PATTERN skip auto-merge and get bot:ready-to-merge instead - Add bot:ready-to-merge label for PRs that are code-clean but need human confirmation before merging (distinct from bot:needs-human-review) - Clear CRITICAL_PATH_PATTERN (empty by default, define when needed) - Apply NEEDS_HUMAN_REVIEW check in both APPROVED path (Step 7) and post-fix path (Step 3b) - Sync IS_CRITICAL_PATH detection in pr-review to use CRITICAL_PATH_PATTERN - Update docs/conventions/pr-automation.md and AGENTS.md with new label
- Move REPO_DIR definition before LOG_FILE so it can be referenced
- Default LOG_FILE to <repo>/logs/pr-automation-{date}.log (daily rotation)
- Move PID_FILE to <repo>/logs/pr-automation-daemon.pid
- Auto-create logs/ directory with mkdir -p on startup
- Replace repo-relative logs/ with ~/Library/Logs/AionUi (macOS convention) - Add LOG_DIR env var to override the log directory at startup - LOG_FILE env var still overrides the full path if needed - PID file moves alongside logs under LOG_DIR
- Detect isCrossRepository and maintainerCanModify in pre-flight checks - For fork PRs with canModify=true: use gh pr checkout + push to fork remote - For fork PRs with canModify=false (fallback): - Create bot/fix-pr-N branch on main repo with fork code + fixes - Open replacement PR with bot:done label and auto-merge enabled - Immediately close original fork PR with explanatory comment - Update pr-automation Step 3b to detect fork fallback (PR state=CLOSED) and exit early instead of running merge gate on closed PR
…ed PRs - Add Step 0 to wake up snoozed PRs when new commits are detected - Add bot:ci-waiting to Step 3 skip conditions - Step 4 ci_failure_dedup now swaps bot:reviewing → bot:ci-waiting instead of plain skip - Clarify that CI failure check covers any job (required or not) - Clarify that CI running check covers required jobs only - Align pr-review Step 2 failure detection to cover all jobs, not just required ones - Update docs/conventions/pr-automation.md and AGENTS.md with new label
…rmal queue exhausted Previously Step 0 always checked all bot:ci-waiting PRs upfront, making N API calls per session even when other eligible PRs existed. Now the wake-up check only runs as a fallback when no eligible PR is found in the normal queue, reducing unnecessary API overhead in the common case.
…early exit Previously, a BEHIND branch caused an early EXIT in Step 4.5, wasting one full CI cycle before review even started. Now review runs first regardless of BEHIND status. update-branch is triggered only when the PR is approved (or fixed) and ready to merge, reducing CI wait cycles from 2 to 1 for the CONDITIONAL path.
…_LOOKBACK env var Default remains 7 days. Override by setting PR_DAYS_LOOKBACK=N before starting the daemon (e.g. PR_DAYS_LOOKBACK=30 ./scripts/pr-automation.sh).
In the update-branch path (APPROVED+BEHIND or fix+BEHIND), the PR ends up with no bot: labels after triggering update-branch. The next session would pick it up as a fresh PR and run a full review again. Add a pre-check at the start of Step 6: if an existing pr-review-bot comment is newer than the latest commit, load its cached conclusion and skip directly to Step 7 instead of running pr-review again.
…eview check When checking if a cached review is still valid, the previous logic used the last commit time regardless of whether it was an update-branch merge commit. GitHub's update-branch API creates a merge commit *after* the review comment is posted, causing a false 'new commits since review' detection and triggering an unnecessary re-review. Fix: filter out commits whose messageHeadline matches '^Merge branch '<base>' into ' before taking the last committedDate. These commits are automatically generated when syncing the PR branch with base and contain no new author code.
…erge flow Disabled 'Require branches to be up to date' in GitHub branch protection (strict: false), so BEHIND branches can be merged directly via --squash --auto. Removed all three BEHIND check blocks from the skill.
- pr-review: LOW-only issues now emit CONCLUSION=APPROVED in automation
mode (was CONDITIONAL), preventing a wasteful fix session since pr-fix
skips LOW issues entirely
- pr-fix: add early abort when all issues are LOW after filtering, guard
against empty commit / stuck bot:fixing label when called after a
LOW-only review
- pr-fix: unify commit message wording in Mandatory Rules to match Step 6
template ('Review follow-up for #N')
…detection - Step 2: codecov/patch and codecov/project are informational: true in codecov.yml and must not trigger CI_FAILED conclusion or block review; excluded from 情形 1 full-pass check and 情形 3 failure check - Step 9: add codecov/patch FAILURE as LOW-level test coverage signal in the testing review dimension (patch target is 50%, informational only)
…ure detection - Step 3b re-check CI: Any job FAILURE/CANCELLED → non-informational only - Step 4 CI check: both the full-pass condition and the failure-trigger row now exclude codecov/* (informational: true in codecov.yml)
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
pr-automationskill: full PR automation lifecycle orchestrator using a label-based state machine (bot:reviewing→bot:ready-to-fix→bot:fixing→bot:ready-to-merge/bot:done)scripts/pr-automation.shdaemon entry script with PID-based lock, per-iteration Claude session streaming, and configurable log directory (~/Library/Logs/AionUi/default)pr-reviewandpr-fixskills with automation mode support, codecov exclusion, aligned severity thresholds, and per-PR dedup comment guardsTest plan
scripts/pr-automation.shagainst a test PR and verify label transitions: fresh PR →bot:reviewing→bot:ready-to-fixorbot:ready-to-mergebot:ready-to-fixPRs are picked up next iteration and transition throughbot:fixingbot:ci-waitingand wake up automatically after author pushes new commits~/Library/Logs/AionUi/for per-iteration and per-PR session filespr-reviewandpr-automation