Skip to content

feat(pr-automation): add PR automation orchestrator with label state machine#1874

Merged
piorpua merged 58 commits intomainfrom
zynx/feat/pr-automation-v2
Mar 29, 2026
Merged

feat(pr-automation): add PR automation orchestrator with label state machine#1874
piorpua merged 58 commits intomainfrom
zynx/feat/pr-automation-v2

Conversation

@piorpua
Copy link
Copy Markdown
Contributor

@piorpua piorpua commented Mar 29, 2026

Summary

  • Add pr-automation skill: full PR automation lifecycle orchestrator using a label-based state machine (bot:reviewingbot:ready-to-fixbot:fixingbot:ready-to-merge/bot:done)
  • Add scripts/pr-automation.sh daemon entry script with PID-based lock, per-iteration Claude session streaming, and configurable log directory (~/Library/Logs/AionUi/ default)
  • Enhance pr-review and pr-fix skills with automation mode support, codecov exclusion, aligned severity thresholds, and per-PR dedup comment guards

Test plan

  • Run scripts/pr-automation.sh against a test PR and verify label transitions: fresh PR → bot:reviewingbot:ready-to-fix or bot:ready-to-merge
  • Verify bot:ready-to-fix PRs are picked up next iteration and transition through bot:fixing
  • Confirm CI-failed PRs receive bot:ci-waiting and wake up automatically after author pushes new commits
  • Check log output under ~/Library/Logs/AionUi/ for per-iteration and per-PR session files
  • Verify PID lock prevents concurrent daemon instances
  • Confirm codecov checks are excluded from CI failure detection in both pr-review and pr-automation

zynx added 30 commits March 26, 2026 15:21
…p comments, auto-rebase, remove status board
…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
zynx 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)
@piorpua piorpua merged commit 7e6576e into main Mar 29, 2026
21 checks passed
@piorpua piorpua deleted the zynx/feat/pr-automation-v2 branch March 29, 2026 07:57
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