Auto-fix GitHub issues labeled as bugs: fetch open bug issues, analyze feasibility, fix code, and submit PRs. One issue per invocation. Use when: (1) User says "/fix-issues", (2) User asks to fix GitHub issues.
Automated workflow: GitHub bug issues → analyze → fix → PR.
Announce at start: "I'm using fix-issues skill to find and fix a GitHub bug issue."
Invocation: /fix-issues
Invocation: /fix-issues limit=1 (from daemon script)
limit parameter), then exits[NO_FIXABLE_ISSUES] and exitsgit status --porcelain
git branch --show-current
If working directory has staged or modified tracked files, stash them and proceed:
git stash -m "fix-issues: auto-stash before starting"
Do NOT use --include-untracked — untracked files (like skill files not yet merged to main)
must remain in the working directory.
Then switch to main:
git checkout main
git pull origin main
In daemon mode (limit > 0), load the skip list to avoid re-analyzing issues that were already
triaged in previous sessions. The skip list is stored at:
~/.aionui-fix-issues/skip-list.json
Format:
{
"1782": { "reason": "already_fixed", "summary": "PR #1800 merged" },
"1707": { "reason": "environment_issue", "summary": "Kaspersky antivirus blocking" },
"1697": {
"reason": "needs_more_info",
"summary": "Missing reproduction steps",
"commented_at": "2026-03-27T12:00:00Z"
},
"1774": {
"reason": "fix_failed",
"summary": "Type check failed after 3 attempts",
"commented_at": "2026-03-27T14:00:00Z"
}
}
Entries never expire. Re-analysis is triggered only by concrete signals.
On load:
During Phase 1.2 (Fetch Issues):
When iterating through fetched issues, if an issue number is in the active skip list, check whether re-analysis is warranted based on the reason:
| Reason | Re-analyze condition | How to check |
|---|---|---|
needs_more_info | New comment on issue since commented_at | gh api check (see below) |
fix_failed | New comment on issue since commented_at | gh api check (see below) |
already_fixed | Issue was reopened (state changed back to open) | Already filtered by --state open in fetch |
fix_pending_merge | Linked PR was closed without merge | gh pr list --state closed --search "<keyword>" |
environment_issue | Always — re-run Classification Gate (Grep) | Run Step 1.4 gate on every environment_issue |
unclear_unfixable | Always — re-run Classification Gate (Grep) | Run Step 1.4 gate on every unclear_unfixable |
Re-analysis for environment_issue / unclear_unfixable (MANDATORY):
These classifications are error-prone and must be re-verified every session. For each
environment_issue or unclear_unfixable entry in the skip list:
summary fieldGrep against src/ with those keywordsdirect_fix or defensive_fixThis prevents misclassifications from becoming permanent. The Grep check is cheap and ensures issues with code paths in our repo are never permanently skipped.
Comment check for needs_more_info / fix_failed:
First, get the authenticated user login (the bot account):
BOT_LOGIN=$(gh api user --jq '.login')
Then check for comments from other users after commented_at:
gh api repos/iOfficeAI/AionUi/issues/<number>/comments \
--jq '[.[] | select(.created_at > "<commented_at>" and .user.login != "'$BOT_LOGIN'")] | length'
Re-analyzing #1697 (new comments from other users since last attempt)Skipping #1697 (needs_more_info — no new comments from others)This ensures:
In batch mode (limit=0): skip list is ignored — always analyze everything fresh.
gh issue list --repo iOfficeAI/AionUi --state open --label bug --limit 50 \
--json number,title,body,labels,assignees,comments,createdAt
Apply these filters in order to narrow down candidates:
Filter 1 — No assignee:
assignees == [] (nobody is working on it)
Filter 2 — Has sufficient description:
Issue body must contain at least ONE of:
Issues with empty body, only a title, or body like [Bug]: with no content → skip.
Note: Issues with screenshots as the only detail should NOT be skipped here. Pass them through to Step 1.3e for image analysis before deciding.
Filter 3 — No linked PR (open or merged):
# Check if this issue already has a linked PR (via "Closes #N" or manual link)
gh api repos/iOfficeAI/AionUi/issues/<number>/timeline --jq \
'[.[] | select(.event == "cross-referenced" and .source.issue.pull_request != null)] | length'
If the issue has any linked PR (open or merged) → skip (classify as "fix pending merge" or "already fixed").
This catches PRs created by this skill (which use Closes #N) as well as manually linked PRs.
In daemon mode, evaluate candidates in this priority order:
For each tier, attempt triage (Step 1.4). If a fixable issue is found, proceed. If all issues in a tier are unfixable, move to the next tier.
If all tiers are exhausted with no fixable issues, output:
[NO_FIXABLE_ISSUES] All tiers exhausted, no actionable issues found.
After selecting a candidate issue to fix, search for sibling issues that describe the same underlying problem. Multiple users often file separate issues for the same bug.
Step 1.3a: Extract signature from the candidate issue:
Pull distinctive identifiers from the issue body:
TypeError: Cannot read properties of null (reading 'addInstance'))JsonImportModal, OfficeDocViewer)src/renderer/components/McpManager.ts)Step 1.3b: Search for sibling issues:
# Search by error message fragment
gh issue list --repo iOfficeAI/AionUi --state open --label bug --limit 50 \
--search "<error-message-fragment>" --json number,title,body
# Search by component name
gh issue list --repo iOfficeAI/AionUi --state open --label bug --limit 50 \
--search "<component-name>" --json number,title,body
Step 1.3c: Confirm same root cause:
For each candidate sibling, verify it describes the same code-level problem (not just similar symptoms). Two issues are siblings if they share at least TWO of:
Step 1.3d: Merge into one fix group:
Group all confirmed siblings. The PR will:
Closes #1786, closes #1771, closes #1778fix/issue-1771Example: #1786 and #1771 are both JsonImportModal + "invalid JSON" crashes
→ One fix group, one branch, one PR closing both issues.
Issue bodies often contain screenshots as the only source of error information (especially
for UI bugs, error dialogs, and Chinese-language reports). Before triaging, extract and analyze
all images to avoid misclassifying issues as needs_more_info.
When to analyze: If the issue body contains image markdown ( or
<img ... src="url" ...>) AND the text description alone is insufficient for triage.
How to analyze:
# Extract image URL from issue body (GitHub user-attachments format)
curl -sL -o /tmp/issue-<number>-<index>.png "<image-url>"
Then use Read to view the downloaded image. Claude can understand screenshots and extract:
Important rules:
/tmp/ — do NOT commit them to the repogithub.com or user-attachments domains (trusted sources)Example: Issue #1298 has only a screenshot. Downloading and reading it reveals: "Internal error" on first message with Sonnet + Claude Code backend → searchable error path.
Classify each issue/group using the detailed decision flow in references/triage-rules.md.
For EVERY candidate issue, you MUST complete this gate before assigning a classification:
Grep against src/ for each keyword[MATCH] or [NO MATCH]Gate rule — code match blocks skip classifications:
Grep found matching code in src/ → classification MUST be direct_fix or defensive_fix.
You CANNOT classify as environment_issue or unclear_unfixable when our code handles the
relevant path. Even if the root cause is external (third-party API, packaged app, platform),
our code can add guards, fallbacks, or adapter logic.Grep found NO matching code → may classify as environment_issue or unclear_unfixableInclude the gate result in the triage report for each issue:
#1619: keywords=["cowork", "ENOENT", "rules"] → [MATCH] fsBridge.ts:748 → direct_fix
#1707: keywords=["Kaspersky", "antivirus"] → [NO MATCH] → environment_issue
| Category | Action |
|---|---|
| Direct fix | Error + code path identified → fix |
| Defensive fix | Pattern matches our code → fix with guards |
| Pending merge | Open PR exists → skip or improve |
| Already fixed | Recent commit addresses it → skip |
| Environment | Zero matching code in src/, entirely external → skip |
| Needs more info | Cannot construct any search query from description → skip+comment |
| Unclear/unfixable | Zero matching code, AND needs new system design → skip |
Output a triage report (see references/report-template.md for format), then proceed immediately — do not wait for user confirmation.
needs_more_info Issues (Mandatory)After triage, before moving to Phase 2, comment on EVERY issue classified as needs_more_info.
This step is mandatory — without a comment, the skip-list commented_at field is meaningless
and re-analysis will never be triggered.
gh issue comment <number> --repo iOfficeAI/AionUi --body "$(cat <<'EOF'
🔍 **Automated analysis — needs more info**
This issue was analyzed but cannot be fixed automatically due to insufficient detail.
**What would help:**
- <specific missing info>
Once the above is provided, this issue will be re-analyzed automatically.
EOF
)"
Record the current UTC timestamp as commented_at for the skip-list entry.
Do NOT comment on issues skipped by filters (has assignee, has linked PR, etc.).
Comment on the issue at key stages to keep reporters informed and enable follow-up.
Use gh issue comment — all comments should be concise and actionable.
Comment 1 — Start (after triage selects this issue):
gh issue comment <number> --repo iOfficeAI/AionUi --body "$(cat <<'EOF'
🔍 **Automated analysis started**
Analyzing this issue for an automated fix. Will update with results.
EOF
)"
Comment 2a — Success (after PR is created):
gh issue comment <number> --repo iOfficeAI/AionUi --body "$(cat <<'EOF'
✅ **Fix submitted**
PR: <pr-url>
- Root cause: <one-line summary>
- Fix: <one-line summary of what changed>
- Tests: passing
EOF
)"
Comment 2b — Abandoned (if fix fails after 3 attempts):
gh issue comment <number> --repo iOfficeAI/AionUi --body "$(cat <<'EOF'
❌ **Automated fix unsuccessful**
Attempted to fix this issue but could not produce a passing solution.
**What was tried:** <brief description of approach>
**Why it failed:** <type check failure / test failure / could not locate code>
<If missing info — add specific questions:>
**To help with a future fix attempt, it would be useful to have:**
- <specific missing info, e.g., "full stack trace", "steps to reproduce", "Electron version">
A future attempt will be made if more information is provided.
EOF
)"
Comment 2c — Skipped during triage (insufficient info):
gh issue comment <number> --repo iOfficeAI/AionUi --body "$(cat <<'EOF'
🔍 **Automated analysis — needs more info**
This issue was analyzed but cannot be fixed automatically due to insufficient detail.
**What would help:**
- <specific missing info>
Once the above is provided, this issue will be re-analyzed automatically.
EOF
)"
Important: Only comment on issues that were actually analyzed or attempted. Do NOT comment on issues that were skipped by filters (no assignee, has linked PR, etc.).
git checkout main
git pull origin main
git checkout -b fix/issue-<number>
Branch naming: fix/issue-<number> using the primary issue number.
Architecture rules (must follow):
src/process/ = main process — no DOM APIssrc/renderer/ = renderer — no Node.js APIssrc/process/worker/ = fork workers — no Electron APIssrc/preload.ts)@/*, @process/*, @renderer/*, @worker/*@arco-design/web-react for UI components, @icon-park/react for iconstype over interface, no any, no implicit returnsGrep for the exact stringGlob to locate the fileEvery bug fix MUST have a corresponding unit test. No exceptions — if you cannot write a test for the fix, the issue is not fixable by this skill. Skip it and move to the next candidate.
foo.test.ts for foo.ts)Test conventions (from project rules):
vitest.config.ts)*.test.ts next to source filebun run testRun all checks in order. Every check must pass before proceeding to Step 2.6.
# 1. Lint + auto-fix
bun run lint:fix
# 2. Format + auto-fix
bun run format
# 3. Type check — MUST pass
bunx tsc --noEmit
# 4. Tests — MUST pass
bun run test
i18n check (run if any src/renderer/, locales/, or src/common/config/i18n files were modified):
bun run i18n:types
node scripts/check-i18n.js
i18n:types must run before check-i18n.jscheck-i18n.js exits with errors → fix them before proceedingcheck-i18n.js exits with warnings only → may proceedFinal CI verification — replicate the exact CI check locally:
prek run --from-ref origin/main --to-ref HEAD
prek reports issues → fix them (run bun run lint:fix and bun run format again), then re-run prekprek uses check-only commands (lint, format:check) — it will catch anything the auto-fix missedGate rules:
| Check | Result | Action |
|---|---|---|
| Type check | FAIL | Fix type errors and re-run. Max 3 attempts, then abandon issue. |
| Tests | FAIL | Adjust fix/test and re-run. Max 3 attempts, then abandon issue. |
| i18n | FAIL | Fix missing keys and re-run. |
| prek | FAIL | Fix reported issues and re-run. |
"Abandon issue" means:
git checkout main (discard the branch)git branch -D fix/issue-<number> (clean up)fix_failed and commented_at timestampNo partial passes. If tests or type check don't pass after 3 attempts, the fix is not ready and must NOT be submitted as a PR.
Delegate to existing skills — do not manually construct commit messages or PR bodies.
Pre-flight duplicate check (safety net):
gh pr list --repo iOfficeAI/AionUi --state open --search "<error-keyword-or-file>" --json number,title
If an existing OPEN PR addresses the same root cause, skip this issue — do not create a duplicate. Log it as "fix pending merge" in the triage report and proceed to Phase 3.
Commit directly (do NOT invoke /commit — it may prompt for confirmation):
git add <changed-files>
git commit -m "<type>(<scope>): <subject>"
Follow project commit conventions: <type>(<scope>): <subject> in English.
No AI signatures. Reference the issue number in the commit body if needed.
Push branch and create PR (do NOT invoke /pr — it may prompt for confirmation):
git push -u origin fix/issue-<number>
gh pr create --title "<pr-title>" --body "$(cat <<'EOF'
## Summary
<1-3 bullet points>
## Related Issues
Closes #<number>, closes #<number>
## Test Plan
- [x] Unit tests pass
- [x] Type check passes
- [x] Lint and format pass
EOF
)"
The PR body MUST include Closes #<number> for every issue in the fix group
(e.g., Closes #1786, closes #1771, closes #1778). This auto-closes all sibling
issues on merge and prevents them from being picked up by future daemon cycles.
PR is always created as a regular (non-draft) PR — by this point all tests, type checks, and quality checks have already passed. The fix is complete and ready for review.
git checkout main
After the issue is fixed, output a summary report. See references/report-template.md for the exact format.
In daemon mode (limit > 0), after the summary report, update ~/.aionui-fix-issues/skip-list.json
with all issues that were skipped in this session.
TTL by classification:
| Classification | Re-trigger condition |
|---|---|
environment_issue | Always — re-run Classification Gate (Grep) |
already_fixed | Issue reopened (detected by --state open fetch) |
fix_pending_merge | Linked PR closed without merge |
unclear_unfixable | Always — re-run Classification Gate (Grep) |
fix_failed | New comment on issue since commented_at |
needs_more_info | New comment on issue since commented_at |
Write rules:
Default parameters (can be overridden via skill args):
| Parameter | Default | Description |
|---|---|---|
| repo | iOfficeAI/AionUi | GitHub repository (owner/repo) |
| limit | 0 | Max issues to fix per invocation (0 = batch mode, >0 = daemon mode) |
| label | bug | Issue label to filter by |
Override examples:
/fix-issues/fix-issues limit=1NEVER add any AI-related signatures to commits, PRs, or issues.
Fix the reported error. Do NOT refactor, add features, or "improve" surrounding code.
The entire workflow runs end-to-end without stopping for user confirmation. Output the triage report for transparency, then proceed immediately. The goal is uninterrupted automation — questions block the flow.
Before creating a new PR/issue, always check for existing OPEN PRs addressing the same root cause. If found, improve the existing PR instead of creating a duplicate.
Group duplicate issues by root cause. Each unique root cause gets one branch and one PR.
Do NOT include changes to .claude/skills/ in bug-fix branches. Skill updates should go through
their own branch and PR.