pm-autofix-pr/SKILL.md
This skill should be used when the user asks to "autofix pr", "fix pr locally", "fix ci failures", "fix review comments", "iterate on pr", "fix failing checks", "fix pr comments", "make ci green", "fix the build", "address reviewer feedback", or wants to iteratively fix CI failures and review comments on a GitHub PR from the local CLI.
npx skillsauth add pmatos/skills pm-autofix-prInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Iteratively fix CI failures and address reviewer feedback on a GitHub PR until a true fixed point is reached — all CI green, every feedback item triaged into one of three outcomes (FIX, DEFER, REJECT), and every feedback item has a reply documenting the outcome. A single invocation handles everything end-to-end without user input.
Not every review comment deserves a code change in this PR, and not every rejected comment is worthless. Before touching code, evaluate every review thread, review summary, and PR conversation comment on its merits with two independent AI reviewers — the local host model (whichever harness you are running in) and a cross-harness model (Claude ↔ Codex; whichever one you are not). Each item is triaged into exactly one of:
DEFER is the safety valve that lets the skill say "not now" to legitimate-but-low-value feedback without losing it. Use it for: pickiness on naming/style where the current code is reasonable, micro-optimizations, refactor requests for working code, doc requests for internal helpers, and anything correct but outside the PR's stated scope.
Every reviewer feedback item must get an explicit reply before the skill can converge. FIX gets a reply that says what was fixed, where it was fixed, and the commit that contains it. DEFER gets a reply with the rejection rationale plus a link to the filed tracking issue. REJECT gets a reply that says no code change was made and why. A missing reply is still unfinished work, even if the code and CI are already green.
This skill runs end-to-end without asking the user anything once invoked. There is no "begin fixing?" confirmation, no "ambiguous feedback, how should I handle it?", no "pre-commit failed, retry?", no "stale loop, continue?", no "CI timeout, keep waiting?". Every decision point has a deterministic auto-action defined below; uncertain feedback defaults to DEFER (file an issue and let humans resolve later); unrecoverable conditions exit cleanly with a final summary. The only way the skill stops mid-flight is by reaching the fixed point, hitting a hard precondition failure (missing GitHub MCP, missing cross-harness CLI, no PR for the branch), or hitting an unrecoverable error (rebase conflict, persistent push failure). Each exit goes through Step 7's summary.
gh CLI is still required for one thing only: fetching failed-job log tails (gh run view --job <id> --log-failed). The MCP has no equivalent. All other GitHub interaction goes through the MCP.claude (Claude Code, npm install -g @anthropic-ai/claude-code) and codex (Codex CLI, npm install -g @openai/codex). The dual-evaluator step calls whichever one is not the host. The skill stops at preflight if the cross-harness CLI is missing.Override via prompt arguments (e.g., /pm-autofix-pr 10 --ci-timeout 30 --monitor 0).
| Parameter | Default | Description |
|-----------|---------|-------------|
| MONITOR_DURATION | 10 | Minutes to watch for new issues after convergence. 0 to skip. |
| CI_TIMEOUT | 20 | Minutes to wait for CI before aborting (no user prompt — exits through Step 7 with ci-timeout). |
| POLL_INTERVAL | 30 | Seconds between PR-state re-fetches while waiting for CI or monitoring. |
| LOG_TAIL_LINES | 500 | Lines of CI failure log to inspect. |
There is no iteration limit. The loop runs until one of: fixed point reached, stale loop detected, CI timeout, rebase conflict, persistent push failure, or monitoring window elapsed. Every exit goes through Step 7. The skill never prompts the user.
All GitHub interaction is direct MCP tool calls — no bundled scripts.
| Tool | Purpose |
|------|---------|
| mcp__github__get_me | Preflight gate; also returns the current user's login for self-comment filtering. |
| mcp__github__list_pull_requests | Auto-detect the PR for the current branch. |
| mcp__github__pull_request_read | Fetch PR details, check runs, review comments/threads, reviews, conversation comments, status. Polled every POLL_INTERVAL seconds while waiting on CI or in the monitoring window. |
| mcp__github__add_reply_to_pull_request_comment | Post replies on inline review threads (FIX, DEFER, and REJECT replies). |
| mcp__github__add_issue_comment | Post PR-level replies for review summaries and PR conversation comments. |
| mcp__github__pull_request_review_write (method="resolve_thread") | Resolve threads after a fix is pushed. |
| mcp__github__issue_write (method="create") | File a tracking issue for each DEFER outcome (out-of-scope, diminishing-returns, ambiguous, or automated-fix-failed). |
This skill runs under either Claude Code or Codex CLI. The orchestrator (you) is the local host; the dual-evaluator step delegates the second opinion to the cross-harness CLI.
Self-identify before doing anything else:
claude, cross-harness is codex.codex, cross-harness is claude.Verify the cross-harness CLI is installed: run command -v <cross-harness-binary> via Bash. If it's missing, stop immediately with:
<cross-harness>CLI not installed. This skill needs both harnesses to run the dual-evaluator step. Install it withnpm install -g @anthropic-ai/claude-code(Claude) ornpm install -g @openai/codex(Codex), then re-run.
Capture for use in evaluator prompts and rejection bodies:
LOCAL_LABEL — e.g. "Claude Opus 4.6" or "Codex GPT-5.4". Use the most specific identifier you know about yourself; fall back to the family name ("Claude", "Codex GPT-5.x") if unsure.REMOTE_LABEL — the cross-harness model label. Same precision rule.Per-host invocation table (referenced by Step 4):
| Host | Local Evaluator (clean-context spawn of own model) | Cross-harness Evaluator |
|------|---------------------------------------------------|-------------------------|
| claude | Agent tool with model="opus" | Skill tool with skill="codex-2nd-opinion" |
| codex | Bash: codex exec --full-auto --sandbox read-only --ephemeral - < /tmp/eval-XXXX (10-min timeout) | Bash: claude -p --permission-mode auto --output-format text < /tmp/eval-XXXX (10-min timeout) |
For Bash-based evaluator spawns, write the prompt to a mktemp /tmp/eval-XXXXXX file, run the command with stdin redirection, capture stdout, then rm -f the temp file.
Call mcp__github__get_me. If the tool is unavailable in the session or the call errors, stop immediately with this message:
GitHub MCP not available. This skill requires the GitHub MCP server. Enable it in your host's MCP settings (
.mcp.json,~/.claude/settings.json, or the Codex equivalent) and re-run. See https://github.com/github/github-mcp-server for setup.
Do not fall back to gh for the workflow. On success, capture login as GH_USER (used to filter out self-authored comments later).
git rev-parse --abbrev-ref HEAD.mcp__github__pull_request_read method=get (requires owner/repo — derive them from origin as in step 3a; if the resolved PR's head.ref doesn't match the local branch, warn and continue with the user's explicit number). Skip to step 5.head.ref matches the local branch:
git remote get-url origin to {owner}/{repo} (strip [email protected]:, https://github.com/, trailing .git). Call mcp__github__list_pull_requests with head={owner}:{branch}, state=open, perPage=5.git remote get-url upstream exists, parse it the same way to {upstream_owner}/{upstream_repo} and call mcp__github__list_pull_requests against that repo with head={origin_owner}:{branch} (PRs from a fork use the fork owner as the head prefix).gh pr view fallback. If both MCP lookups fail and gh is available, run gh pr view --json number,headRepositoryOwner,headRepository,baseRepositoryOwner,baseRepository,url to let gh resolve the base repo via git config. On success, treat the returned baseRepositoryOwner.login / baseRepository.name as the PR's owner/repo. If gh is not installed or returns nothing, stop and tell the user there is no open PR for the current branch.mcp__github__pull_request_read method=get on the resolved {owner, repo, pullNumber} to retrieve title, body, head.ref, head.sha, base.ref, url. Confirm head.ref matches the local branch. Capture base.ref for use in Step 5d's first-push fallback.Find CLAUDE.md (or AGENTS.md) by walking from working directory to repo root. Extract only explicitly stated pre-commit commands: format, lint, type-check, test, build. If none are stated, skip pre-commit checks entirely.
Issue these MCP calls (paginate where applicable) and merge into a single state object:
| State field | Source |
|---|---|
| head_sha | pull_request_read method=get → head.sha |
| ci_failures | pull_request_read method=get_check_runs → keep entries whose conclusion ∈ {failure, timed_out, cancelled, startup_failure, action_required}. For each failure whose app.slug == "github-actions", mark fixable=true and fetch the log tail via Bash: gh run view --job <check_run.id> --log-failed 2>&1 | tail -<LOG_TAIL_LINES>. Other failure types are non-fixable — report them. |
| review_threads | pull_request_read method=get_review_comments (paginate via perPage=100, after). Split into unresolved = [t for t in threads if not t.isResolved] and resolved_thread_ids = [t.id for t in threads if t.isResolved]. For each unresolved thread, take the last non-self element of comments (sorted by createdAt if order is not guaranteed and author.login != GH_USER) as latestReviewerComment. Drop self-only threads whose latestReviewerComment is absent from feedback_items; they are author notes, not reviewer feedback, and must not be dereferenced later. |
| review_summaries | pull_request_read method=get_reviews. Apply supersession (see below). |
| pr_comments | pull_request_read method=get_comments. Drop entries where user.login == GH_USER. |
Supersession algorithm for reviews: group reviews by user.login. Within each group, sort by submitted_at ascending. Find the index of the latest APPROVED or DISMISSED review (or -1 if none). Discard everything at or before that index. From the remainder, keep only CHANGES_REQUESTED or COMMENTED reviews with non-empty body and user.login != GH_USER. The result is the actionable summary list.
Errors: if any MCP call fails, accumulate the error message into an errors list. Do not abort — downstream steps tolerate partial state and re-fetch.
Build feedback_items from:
latestReviewerComment, keyed as thread:<thread.id>review_summaries, keyed as review:<review.id>pr_comments, keyed as comment:<comment.id>Initialize ADDRESSED_THREAD_IDS with resolved_thread_ids. Initialize REPLIED_ITEM_KEYS = {} for review summaries and PR conversation comments that already received an outcome reply during this invocation. Initialize OUTCOME_MARKERS = {} (item_key → latest_reviewer_marker_at_outcome) covering both REJECTED and DEFERRED items so a later reviewer edit re-enters evaluation. Initialize DEFERRED_ITEMS = [] (one entry per filed tracking issue, used by Step 7's summary).
Print the initial assessment as a status line — Found N CI failures and M reviewer feedback items. Begin processing. — and proceed unconditionally. Never wait for a confirmation: the skill is fully automatic from this point on.
If nothing to fix, report the PR is clean and proceed to Step 6 (monitoring).
This is the most important step. Every time PR state is fetched, evaluate reviewer feedback before waiting on CI. Do not defer review handling until checks finish.
For each feedback item not already answered, gather context, then spawn two subagents in parallel. Inline threads are already answered when thread.id ∈ ADDRESSED_THREAD_IDS; review summaries and PR conversation comments are already answered when item_key ∈ REPLIED_ITEM_KEYS; previously rejected or deferred feedback is already answered when item_key ∈ OUTCOME_MARKERS and its reviewer marker has not changed.
latestReviewerComment, then read the referenced file and code context.Local Evaluator — runs the host model in a clean context. Use the row from Step 0a's per-host invocation table that matches your host:
model="opus".codex exec --full-auto --sandbox read-only --ephemeral - < /tmp/eval-XXXXXX (10-minute timeout). Write the prompt via mktemp first; rm -f after.Provide the comment, code context, PR title/description, and changed files summary. Ask for a FIX / DEFER / REJECT verdict with category, confidence, and reasoning. See references/comment-evaluation.md for the full prompt template.
Cross-harness Evaluator — runs the other model. Use the matching row from Step 0a's invocation table:
skill="codex-2nd-opinion" (the user-level skill in this repo, frontmatter name: codex-2nd-opinion).claude -p --permission-mode auto --output-format text < /tmp/eval-XXXXXX (10-minute timeout; --permission-mode auto keeps claude from prompting when run headless inside the loop). Same mktemp / rm -f discipline as above.Pass the same evaluation prompt as the Local Evaluator. Ask for the same verdict format.
Claude host — DO NOT invoke any of the following — they look superficially related but are the wrong tool and will produce different output:
codex:rescue / Skill tool with skill="codex:rescue" — this delegates rescue/fix work, not opinion-gathering.codex:codex-rescue — the rescue subagent in the Agent tool, same problem.codex:setup, codex:codex-cli-runtime, codex:gpt-5-4-prompting, codex:codex-result-handling — internal helpers, not user-facing review tools.The only correct invocation is the Skill tool with skill="codex-2nd-opinion". If codex-2nd-opinion is not in the available-skills list, stop and report — do not substitute another skill.
Codex host — DO NOT call codex exec again as the cross-harness evaluator (that is the Local Evaluator). The cross-harness step must be claude -p, never another codex exec.
Decision logic (from references/comment-evaluation.md):
| Local | Cross-harness | Action | |-------|---------------|--------| | FIX | FIX | FIX — apply code change in this PR | | REJECT | REJECT | REJECT — reply with rationale, no code change, no issue | | DEFER | DEFER | DEFER — file tracking issue, reply with link | | any other combination | | DEFER — file tracking issue (any disagreement defaults to DEFER) |
The rule is conservative on purpose: only fix when both evaluators agree the change belongs in this PR; only reject when both agree there is no concern worth tracking; otherwise file an issue so nothing is silently dropped. This matches the "Three Outcomes" core principle.
Ambiguous feedback (open questions, architectural suggestions with multiple alternatives, requests that depend on undocumented context) is auto-classified as DEFER without consulting the user. The filed issue is the durable artifact a human can resolve later; the PR reply tells the reviewer where the discussion has moved. Do not block the loop on user input.
Loop until fixed point or unrecoverable abort. Process each feedback item exactly once per fetch cycle through the outcome flow that matches its Step 4 verdict.
5a. REJECT flow (verdict = REJECT). Compose a rejection body using the prefix table below and reply through the right channel:
mcp__github__add_reply_to_pull_request_comment with commentId = latestReviewerComment.databaseId.mcp__github__add_issue_comment with issue_number = pullNumber. Start the body with @reviewer Regarding your <review/comment> (<short identifier>): and quote or summarize the specific ask being rejected.Do not resolve rejected inline threads — they stay unresolved so the reviewer can push back. Record the item in OUTCOME_MARKERS as item_key → latest_reviewer_marker_at_outcome using a mutable marker: latestReviewerComment.databaseId + updatedAt for inline threads, review.id + updated_at for review summaries when available, review.id + body_hash(body) for review summaries when no update timestamp exists, and comment.id + updated_at for PR conversation comments. Do not add it to ADDRESSED_THREAD_IDS; suppression depends on the recorded reviewer marker staying current.
Rejection body format:
{prefix} {reason}
_This assessment was made by two independent AI reviewers ({LOCAL_LABEL} and {REMOTE_LABEL}). If you disagree, please reply and we'll re-evaluate._
Substitute {LOCAL_LABEL} / {REMOTE_LABEL} with the values captured in Step 0a (e.g. "Claude Opus 4.6" and "Codex GPT-5.4", in either order depending on the host).
Prefixes by REJECT category:
| Category | Prefix |
|---|---|
| not-an-issue | **Not an issue** — |
| unrelated | **Unrelated to this PR** — |
| not-relevant | **Not applicable** — |
| style-preference | **Style preference (no change)** — |
| already-handled | **Already handled (no change)** — |
| (default) | **No action taken** — |
5a'. DEFER flow (verdict = DEFER). The feedback is legitimate but does not belong in this PR — file a tracking issue, then reply with a link.
Build the issue title from the feedback's primary ask: a short imperative phrase, e.g. Refactor extractTokens() to share parser state or Add retry logic to HTTP client.
Build the issue body:
Deferred from #{pullNumber}: {one-line summary}.
Original feedback by @{reviewer} on PR #{pullNumber} ({pr_url}):
> {quoted feedback, blockquoted}
**Context:** {file path:line, or short note on where this applies}.
**Why deferred:** {scope-creep | diminishing-returns | ambiguous} — {one-sentence rationale from the evaluators}.
_Filed automatically by `pm-autofix-pr` after dual-evaluator triage by {LOCAL_LABEL} and {REMOTE_LABEL}._
Call mcp__github__issue_write with method="create", owner, repo, title, body, and (if applicable) labels=["deferred-from-pr"]. Capture the returned number and html_url.
Compose the PR reply with the matching prefix below, ending with Tracked as #{new_issue_number} ({issue_html_url}).
Prefixes by DEFER category:
| Category | Prefix |
|---|---|
| scope-creep | **Out of scope for this PR** — |
| diminishing-returns | **Deferred (diminishing returns)** — |
| ambiguous | **Deferred for separate discussion** — |
| automated-fix-failed | **Deferred (automated fix failed pre-commit)** — |
| (default) | **Deferred** — |
Reply through the same channel as REJECT (inline thread → add_reply_to_pull_request_comment; review summary / PR comment → add_issue_comment). Do not resolve inline threads — the reviewer can push back if the deferral is wrong.
Record the item in OUTCOME_MARKERS (same marker scheme as REJECT). Append {item_key, issue_number, issue_url, category, title} to DEFERRED_ITEMS for the Step 7 summary.
Issue-creation failure fallback. If mcp__github__issue_write fails (rate limit, permissions, transient error) — retry once after 60 seconds. If the retry also fails, do not block the loop: post the DEFER reply with TODO: file as a separate issue — automated issue creation failed (<error summary>). instead of the tracked-issue link, and append {item_key, issue_number=null, ...} to DEFERRED_ITEMS so the final summary surfaces the gap. The reviewer's concern is still acknowledged in writing.
5b. FIX flow (verdict = FIX) and CI failures. Process each FIX item individually — apply, check, commit — before moving to the next. This isolates each item in its own commit so a pre-commit failure can be reverted cleanly without touching earlier successful fixes (the revert combines git restore for tracked changes and git clean -fd for untracked files the FIX created — both are safe because only the in-flight item's changes are in the worktree).
Precondition before entering 5b: the worktree must be clean (git status --porcelain empty). If it is not, fail loudly and jump to Step 7 with exit reason: dirty-worktree — there is no safe way to attribute the existing changes to a specific FIX item.
For each FIX item in feedback_items whose verdict is FIX (CI failures included), in sequence:
Snapshot the worktree. Run git status --porcelain and record it as pre_fix_status — at this point it must be empty (the 5b precondition).
Apply the change. Read the relevant source/error context and edit files:
Categorize what this FIX touched. Run git status --porcelain again. Capture:
modified_paths — entries with status codes M, A, D, R, T (tracked changes/renames/deletes).untracked_paths — entries with status code ?? (new files this FIX created).Run pre-commit checks for this item (Step 5c).
On pre-commit success: stage the touched files by name (never git add -A) — staging both modified_paths and untracked_paths. Commit with a descriptive message that names the feedback item (e.g. Fix null check in extractTokens (review thread #PRRT_xxx)), capture the resulting short-sha, and add the FIX item to COMMITTED_ITEMS = [] with {item_key, sha, files, validation}.
On pre-commit failure (5c returned a hard fail after the sub-fix attempt): revert this item completely so the next FIX starts from a clean worktree:
git restore --source=HEAD --staged --worktree -- <modified_paths> to undo tracked modifications/renames/deletions (also unstages anything pre-commit staged).git clean -fd -- <untracked_paths> to delete files this FIX created (-fd so newly-created subdirectories are removed too).git status --porcelain that the worktree is once again empty; if it is not, abort the entire loop with exit reason: dirty-worktree rather than risk contaminating later FIXes.Record the item under BLOCKED_ITEMS = [] with {item_key, files, pre_commit_error_tail}. Continue with the next FIX item; blocked items will be turned into automated-fix-failed DEFER entries (with their own tracking issues) at the end of the loop iteration.
After all FIX items have been processed, the worktree is clean and COMMITTED_ITEMS lists every successful fix with its own sha. Each entry's sha is what 5e quotes in the corresponding "Fixed in <sha>" reply.
Convert each blocked FIX into an automated-fix-failed DEFER before leaving 5b. For every entry in BLOCKED_ITEMS (the items 5b reverted because pre-commit refused them), run the Step 5a' DEFER flow with category="automated-fix-failed":
Auto-fix failed pre-commit: <one-line summary of the original feedback>.pre_commit_error_tail captured in 5b. Set the **Why deferred:** line to automated-fix-failed — <one-line of the pre-commit error>.mcp__github__issue_write, post the DEFER reply on the original thread / review summary / PR conversation comment using the automated-fix-failed prefix from Step 5a' and ending with Tracked as #<issue_number> (<issue_html_url>)., then record the item in OUTCOME_MARKERS and append it to DEFERRED_ITEMS — exactly like an evaluator-driven DEFER. Apply the same retry + TODO: file as a separate issue fallback if issue_write fails.After this conversion, every blocked item has an explicit PR reply and (best-effort) a tracking issue, so the "Always Reply" core principle holds for blocked FIXes too. Clear BLOCKED_ITEMS for the iteration; do not include their entries in 5e (which only iterates COMMITTED_ITEMS).
5c. Pre-commit checks (from Step 2) — invoked by 5b for the current in-flight item only. Run in order: format → lint → type-check → test → build. If a formatter modifies files, stage them. If a check fails, attempt one sub-fix (does not count as a loop iteration). If the sub-fix also fails, do not ask the user — return a hard fail to 5b, which handles the revert and continues with the next FIX item. The check is bounded to this single item because earlier successful items are already committed and out of the worktree.
5d. Push the iteration's commits. After 5b finishes, decide whether there is anything to push without depending on undefined refs:
COMMITTED_ITEMS is empty for this iteration (no FIX produced a commit), there is nothing to push — skip directly to Step 5g (re-fetch and check fixed point), not 5f. An iteration that only emits REJECT replies, DEFER replies, or automated-fix-failed DEFER conversions creates no new commits and therefore no new CI events, so waiting for CI in 5f would just spin until CI_TIMEOUT and exit as a failure even when we have actually reached the fixed point.git rev-parse --abbrev-ref --symbolic-full-name @{u} exits 0), run git push.git push -u origin <head.ref> using the branch name captured in Step 1. Do not consult any base-branch ref; the upstream gets set during this push.On rejected push (upstream has new commits), auto-recover without prompting:
git pull --rebase.git rebase --exec is acceptable, or by replaying 5b's checks on the rebased tree), then push again.git rebase --abort to leave the worktree clean, record the abort in the final summary, jump straight to Step 7. Exit with summary; the user must resolve the divergence manually.On network error during push, retry with exponential backoff (2s, 4s, 8s, 16s). After the fourth failure, jump to Step 7 with the failure recorded — do not prompt.
5e. Reply to every addressed feedback item. For each entry in COMMITTED_ITEMS (the per-item commits 5b/5d produced this iteration), post an outcome reply that quotes that item's own short-sha — never a different item's sha, since each FIX has its own commit. An item only counts as addressed once its reply is posted.
Reply body format:
Fixed in `<short-sha>`.
Changed: <file/function/behavior summary>.
Validation: <pre-commit check, targeted test, or reason validation was not run>.
Use the right channel:
mcp__github__add_reply_to_pull_request_comment with commentId = latestReviewerComment.databaseId (the numeric REST ID of the thread's most recent reviewer comment — not the thread's GraphQL id). After the reply succeeds, call mcp__github__pull_request_review_write with method="resolve_thread" and threadId = <thread.id> (the GraphQL node ID from get_review_comments). If both calls succeed, add the thread to ADDRESSED_THREAD_IDS.mcp__github__add_issue_comment with issue_number = pullNumber. Start the body with @reviewer Regarding your <review/comment> (<short identifier>):, then include the fixed outcome. If the reply succeeds, add the item key to REPLIED_ITEM_KEYS.This step is mandatory — never skip it. If a reply or resolve call fails with 403/429, wait 60s and retry once. After a failed retry, continue the code loop if needed, but do not count that feedback item as addressed and do not declare convergence; it must reappear on the next fetch/retry cycle until a reply is posted.
5f. Wait for CI only after feedback is answered. If any fetched feedback item still lacks an evaluation decision and an outcome reply, re-enter Step 4 immediately instead of polling. Once feedback is answered, poll for change:
POLL_INTERVAL seconds (via Bash with sleep <n>).head_sha changed (new push from another contributor).conclusion transitioned from null/in_progress to a terminal value, or any check run was added/removed.updated_at (or per-comment updatedAt) timestamps advanced past the previous snapshot. This catches new comments, edited comments, and new reviews uniformly.Track wall-clock elapsed time since the last commit was pushed. If CI_TIMEOUT minutes elapse with no terminal CI conclusion for at least one previously-pending check, abort the loop — record ci_timeout in the final summary and jump to Step 7. Do not prompt the user.
This polling path is the only mechanism the skill uses to detect new state. It does not depend on <github-webhook-activity> envelopes or any subscription tool; those are not available in the standard Claude Code CLI or Codex CLI sessions this skill targets.
5g. Re-fetch state and check for fixed point. Re-run Step 3's MCP calls. Filter out threads whose ID is in ADDRESSED_THREAD_IDS and PR-level feedback whose key is in REPLIED_ITEM_KEYS. For each item in OUTCOME_MARKERS, suppress it only if its latest reviewer marker still matches the value recorded at the prior REJECT/DEFER outcome; if a later reviewer reply exists, remove the item from OUTCOME_MARKERS and treat it as fresh feedback to re-evaluate in Step 4. If the merged state has a non-empty errors list, do not declare a fixed point — report the fetch failures and retry after 30 seconds.
Fixed point reached if:
ci_failures is empty after filtering out cancelled (the only non-success conclusion treated as informational). Any remaining entry — including timed_out, startup_failure, action_required, and non-github-actions failure — blocks convergence and is reported to the user.→ Proceed to Step 6.
Stale loop detected if the same CI checks are failing with similar error patterns as the previous iteration → record stale_loop in the final summary and jump to Step 7. Do not prompt the user. (BLOCKED_ITEMS cannot accumulate across iterations because Step 5b now converts each blocked FIX into an automated-fix-failed DEFER and clears the list.)
New issues found → run Step 4 (evaluate new feedback) and continue the loop.
Skip if MONITOR_DURATION is 0 or if there are CI failures or unanswered feedback items.
Report: "All issues resolved. Monitoring for {MONITOR_DURATION} minutes..."
Poll for change for up to MONITOR_DURATION minutes using the same loop as Step 5f: sleep POLL_INTERVAL seconds, re-run Step 3's MCP calls, compare counts and updated_at markers (and head_sha) against the previous snapshot. If a change is detected within the window, re-enter the evaluate + fix loop (Step 4 → Step 5) with a fresh sub-loop. After fixing, resume monitoring with the remaining time. If the window elapses without a change, proceed to Step 7.
Print:
## Autofix PR Summary
### PR: #<number> — <title>
### Iterations: N
### Exit reason: fixed-point | stale-loop | ci-timeout | rebase-conflict | push-failure | dirty-worktree | monitoring-timeout
### Changes Made (FIX outcomes)
| Iteration | Commit | Fixes Applied | Replies Posted |
|-----------|--------|---------------|----------------|
| 1 | abc123 | Fixed lint error in foo.ts, addressed review on bar.ts | @reviewer fixed thread in bar.ts via abc123 |
| 2 | def456 | Fixed test failure in baz_test.py | n/a |
### Deferred Feedback (DEFER outcomes — issue filed)
| Feedback | Category | Tracking Issue | Reply |
|----------|----------|----------------|-------|
| @reviewer on file.ts:42 | scope-creep | #123 | Posted DEFER reply with link |
| @reviewer (review summary) | diminishing-returns | #124 | Posted DEFER reply with link |
| @reviewer on util.ts:88 | scope-creep | _none — issue creation failed_ | Posted DEFER reply with TODO note |
### Rejected Feedback (REJECT outcomes — no change, no issue)
| Feedback | Category | Reason | Reply |
|----------|----------|--------|-------|
| @reviewer on file.ts:42 | not-an-issue | Code is correct as-is | Posted no-change rationale |
### Blocked Items (FIX attempted but pre-commit failed)
| Item | Pre-commit failure | Tracking Issue |
|------|--------------------|----------------|
| @reviewer on parser.ts:201 | type-check: tsc TS2322 | #125 |
### Current Status
- CI: All passing / N failures remaining (list each: name, conclusion, log link)
- Reviewer feedback: All answered / M items still missing replies (list each)
- Issue creation failures: 0 / K (each requires manual filing — see Deferred table)
Do not ask the user anything at the end. The skill exits unconditionally after printing the summary:
fixed-point (CI green, all feedback answered) or monitoring-timeout (reached only by passing through the same green-CI / answered-feedback gate before entering Step 6, so a clean window-elapse is also success): print "PR is ready for re-review."stale-loop, ci-timeout, rebase-conflict, push-failure, dirty-worktree: print "Autofix exited without converging — see summary above for required follow-up." Do not loop again, do not prompt.references/api-patterns.md — MCP tool signatures, expected response shapes, polling-loop semantics, supersession algorithm, push and rebase handling, issue-creation flow, log-fetching gapreferences/comment-evaluation.md — Full evaluation prompt templates, FIX/DEFER/REJECT decision matrix, DEFER and REJECT taxonomies, ambiguity-to-DEFER policydata-ai
Upscale raster images with a local OpenCV EDSR super-resolution model, then produce an exact target pixel size. Use when the user asks to upscale, enlarge, super-resolve, make a higher-resolution version, or create a wallpaper/print-size raster from an existing image while preserving the original artwork.
tools
This skill should be used when the user asks to "investigate issue", "investigate
development
This skill should be used when the user asks "what's going on", "wigo", "status", "where was I", "what were we doing", "catch me up", "tree status", "branch status", or wants a comprehensive situational briefing on the current git tree, session history, and associated PR. Also triggered by the /wigo command.
development
This skill should be used when the user asks to "plan this", "make a plan", "create an implementation plan", "how should I implement", "design the implementation", "plan the refactor", "plan the migration", "plan the feature", "break this down into steps", "implementation strategy", "deep plan", "thorough plan", or wants a thorough, multi-phase implementation plan with codebase exploration before writing any code.