with one click
issue-planner
// Select GitHub issues, check for already-solved ones, audit CI health, and create an implementation plan. Use when starting work on a project to pick what to work on next.
// Select GitHub issues, check for already-solved ones, audit CI health, and create an implementation plan. Use when starting work on a project to pick what to work on next.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | issue-planner |
| description | Select GitHub issues, check for already-solved ones, audit CI health, and create an implementation plan. Use when starting work on a project to pick what to work on next. |
| user-invocable | true |
| disable-model-invocation | true |
Any previous plan, task list, or implementation context from this session is NOW CLOSED. Do not carry forward assumptions, partial work, or "remaining items" from earlier work. You are starting fresh.
deleted ā they belong to the old context./issue-planner because they want to pick NEW work. Treat this as a clean slate.Before looking at issues, check if the project's CI meets airuleset standards:
# Mutation testing
grep -rE "cargo-mutants|cargo mutants|stryker|StrykerJS" .github/workflows/ 2>/dev/null
# Playwright E2E tests
ls e2e/ tests/e2e/ playwright/ 2>/dev/null
# Assertion density / test-integrity gates
grep -rE "assertion|mutation|test-integrity" .github/workflows/ 2>/dev/null
Cold-compile CI is one of the top sources of wasted developer time. A Rust workspace with no cache costs 5ā15 min per push; with cache it's 30sā2 min. Detect by language and verify cache is wired up on EVERY job that compiles, not just one.
# Detect project language(s)
ls Cargo.toml package.json pyproject.toml go.mod 2>/dev/null
# Inspect ALL workflow files
ls .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null
# Rust: needs Swatinem/rust-cache@v2 on every Rust job (test, build, coverage, mutants, tauri, wasm)
grep -E "Swatinem/rust-cache|actions/cache.*\.cargo|actions/cache.*target" .github/workflows/*.y*ml 2>/dev/null
# Node.js: needs setup-node with cache: 'npm'|'yarn'|'pnpm', OR actions/cache for node_modules / .pnpm-store
grep -E "setup-node.*cache|cache: ['\"](npm|yarn|pnpm)|actions/cache.*node_modules|actions/cache.*pnpm-store" .github/workflows/*.y*ml 2>/dev/null
# Python: needs setup-python with cache: 'pip'|'poetry', OR actions/cache for ~/.cache/pip / .venv
grep -E "setup-python.*cache|cache: ['\"](pip|poetry|pipenv)|actions/cache.*\.cache/pip|actions/cache.*\.venv" .github/workflows/*.y*ml 2>/dev/null
# Go: needs setup-go with cache: true (default in v4+) OR actions/cache for ~/go/pkg/mod and ~/.cache/go-build
grep -E "setup-go|actions/cache.*go-build|actions/cache.*go/pkg" .github/workflows/*.y*ml 2>/dev/null
# Per-job verification: count compile jobs vs cache steps
grep -cE "runs-on:|^ [a-z].*:$" .github/workflows/*.y*ml | head
Audit each compile-heavy job individually. A workflow can have cache on the test job but not the coverage job ā that means coverage still cold-compiles every run. For Rust: every job that calls cargo (build, test, clippy, llvm-cov, mutants, tauri build, trunk build, cross) MUST have Swatinem/rust-cache@v2 BEFORE the cargo step.
If cache is missing or partial, present the gap with concrete numbers:
"CI cache audit: 4 of 5 Rust jobs missing
Swatinem/rust-cache@v2(Test ā , Build Windows ā, Coverage ā, Build Tauri ā, Build WASM ā). Estimated waste: ~12 min per push. Fix proposal: addSwatinem/rust-cache@v2step before each cargo invocation, withkey: ${{ runner.os }}-${{ matrix.target }}so different targets don't collide."
If quality gates OR cache are missing, you MUST use AskUserQuestion before proceeding:
Do NOT proceed to Step 2 until the user has answered. A one-line mention like "cache is missing" without AskUserQuestion is NOT acceptable ā block and ask. Bad CI compounds: every issue you plan will pay the cold-compile tax until the cache is fixed.
If the project has a web UI (frontend, dashboard, admin panel), check whether it displays the deployed version. This is a global rule ā see version-on-dashboard.md. Without a visible version label, post-deploy verification is impossible and frontend/backend drift ships silently.
Detection (run silently):
# Heuristic: project has a web UI?
HAS_FRONTEND=$(test -d frontend -o -d web -o -d ui -o -f index.html -o -f vite.config.* -o -f next.config.* && echo yes || echo no)
[ -f package.json ] && grep -qE '"(react|vue|svelte|leptos|preact|next|nuxt|remix|astro)"' package.json && HAS_FRONTEND=yes
[ -f Cargo.toml ] && grep -qE '(leptos|yew|dioxus|sycamore)' Cargo.toml && HAS_FRONTEND=yes
# If web UI: check if a version display exists
if [ "$HAS_FRONTEND" = "yes" ]; then
HAS_VERSION_DISPLAY=$(grep -rE 'data-testid="version"|class="version"|id="version"|build_version|gitDescribe|GIT_VERSION|VERSION_LABEL' --include='*.tsx' --include='*.jsx' --include='*.ts' --include='*.js' --include='*.html' --include='*.rs' --include='*.svelte' --include='*.vue' . 2>/dev/null | head -1 | wc -l)
HAS_VERSION_TEST=$(grep -rE 'version.*toMatch.*\\\\d.*\\\\d.*\\\\d|expect.*version.*v\\\\d' --include='*.spec.*' --include='*.test.*' tests/ e2e/ 2>/dev/null | head -1 | wc -l)
fi
Decision rules:
version-on-dashboard.md template, plan that as the next PR before feature workIssue body template (when filing the foundation issue):
Add a version display to the dashboard per the global version-on-dashboard.md rule.
Format: `v<semver>(-dev.<n>)?` (e.g. `v1.0.97-dev.9`), build-time injected from `git describe`, matching the deployed binary. Place it in a footer or navbar visible on every route.
Add a Playwright test asserting the label exists, is visible, and matches the format. The frontend version must equal the backend `/api/version` (or equivalent) ā single git-tag source.
Without this, post-deploy verification cannot confirm new code is live and frontend/backend drift ships invisibly. See ~/devel/airuleset/modules/quality/version-on-dashboard.md.
Do NOT proceed to Step 2 until the foundation gate is resolved (either issue filed and queued, or user explicitly chose skip).
Per no-local-builds.md, the dev machine is for editing ā CI compiles. Stale target/, node_modules/, dist/ directories are silent disk hogs that fill the machine over time. Audit them before any new work.
Before any purge, identify projects with <!-- airuleset:local-builds=allowed --> in their CLAUDE.md ā those are EXEMPT from purge (their target/ is a working asset, not waste).
# Find exempt projects (the HTML comment is the canonical machine-readable marker)
EXEMPT=$(grep -rlE '<!--\s*airuleset:local-builds=allowed\s*-->' \
~/devel/*/CLAUDE.md ~/devel/*/repo/CLAUDE.md ~/devel/*/.claude/CLAUDE.md 2>/dev/null \
| xargs -I{} dirname {} | sort -u)
echo "Exempt projects (local builds allowed):"
echo "$EXEMPT"
# Per-project waste (current project) ā only if NOT in $EXEMPT
du -sh target node_modules dist .next .nuxt build 2>/dev/null
# Cross-project waste (entire ~/devel) ā exclude exempt
for d in ~/devel/*/target ~/devel/*/node_modules ~/devel/*/dist ~/devel/*/.next ~/devel/*/build; do
proj=$(echo "$d" | awk -F/ '{print "/" $2 "/" $3 "/" $4 "/" $5}')
echo "$EXEMPT" | grep -q "$proj" && continue
[ -d "$d" ] && du -sh "$d" 2>/dev/null
done | sort -h
# Total disk pressure on home
df -h ~ | tail -1
Decision rules (applied to NON-exempt projects only):
target/ (or equivalent) exists AND is older than 24 h ā propose purge.~/devel/*/target etc. ā propose multi-project purge.Exempt-project handling: If the CURRENT project is exempt, skip the purge gate entirely for it ā but still audit cross-project waste in OTHER non-exempt projects, and still block on the < 20 GB free rule (purging non-exempt projects).
If any of the above triggers, AskUserQuestion BEFORE Step 2:
rm -rf (current project only, OR cross-project sweep if total > 10 GB), report freed space, then continuePurge commands (run after explicit user approval ā rm -rf is destructive):
# Current project
rm -rf target/ node_modules/ dist/ .next/ .nuxt/ build/ .turbo/ .svelte-kit/
# Cross-project Rust sweep
find ~/devel -maxdepth 3 -type d -name target -exec rm -rf {} +
# Cross-project Node sweep
find ~/devel -maxdepth 3 -type d \( -name node_modules -o -name dist -o -name .next -o -name build \) -exec rm -rf {} +
# Python caches
find ~/devel -type d \( -name __pycache__ -o -name .pytest_cache -o -name .mypy_cache -o -name .ruff_cache \) -exec rm -rf {} +
Do NOT proceed to Step 2 until disk hygiene is resolved (either purged or user explicitly chose skip). Cross-project waste compounds ā every issue you plan adds more if the baseline isn't clean.
gh issue list --state open --limit 30 --json number,title,labels,assignees,createdAt,updatedAt
This step runs FOR EVERY OPEN ISSUE ā not a sample, not a spot-check. Old issues are the most common to be silently solved by unrelated refactors, dependency bumps, or feature work. Skipping this wastes a planning cycle.
For each open issue from Step 2:
# 1. Read the full issue (title, body, recent comments)
gh issue view <number> --json title,body,comments,labels,createdAt
# 2. Extract 2ā4 keywords from the title and body (function names, file paths, error strings)
# 3. Search recent commits that touched the relevant area
git fetch origin
git log --oneline --since="$(gh issue view <number> --json createdAt -q .createdAt)" -- <relevant-paths>
git log --oneline -50 --grep="<keyword>" --all
# 4. Search merged PRs since the issue was opened
gh pr list --state merged --limit 30 --search "<keyword>" --json number,title,mergedAt,body
gh pr list --state merged --search "fixes #<number> OR closes #<number> OR resolves #<number>" --json number,title,mergedAt
# 5. If the issue references specific code (file:line, function name), VERIFY the current state
# ā old issue says "function X panics on empty input"; check if X still exists, still panics
grep -rn "<function or symbol>" src/ 2>/dev/null
# For Rust: cargo check; for behavioral claims: write a quick repro test
Decision rules per issue:
#X (180d old, no related work) so the user can deprioritizeBlock before Step 4: if any issues are flagged "likely solved" or "partially overlaps", resolve them via AskUserQuestion FIRST. Do not present issues for selection while there are unconfirmed-solved ones in the queue. Never close an issue without explicit user approval.
Use AskUserQuestion to present the open (unsolved) issues as options. Group by priority/labels if available. Let the user select which issue(s) to work on.
Include for each issue:
For each selected issue:
gh issue view <number>/superpowers:brainstorming to design the approach/superpowers:writing-plans to create the implementation plan/superpowers:executing-plans to start worktarget/ / node_modules/ directories must be purged or explicitly skipped before issue selection