一键导入
pr-fixup
// Wait for CI checks and automated reviews (CodeRabbit, Greptile, Claude, cubic) on a PR, fix failures and address comments, then push.
// Wait for CI checks and automated reviews (CodeRabbit, Greptile, Claude, cubic) on a PR, fix failures and address comments, then push.
Write and run web E2E tests (Playwright) using TDD — locations, patterns, commands, and debugging.
Debug a running kandev development instance. Use when the user reports a bug, unexpected behavior, or asks to investigate an issue while kandev is running via `make dev`. Triages the bug class first (backend-logic → Go test, live-instance → /debug/export, UI → browser), launches an ISOLATED parallel instance when a running app is needed, and tears down only what it started.
Ensures UI feature work ships with desktop and mobile parity, responsive behavior, and mobile Playwright E2E coverage. Use when implementing, planning, reviewing, or testing any new feature, page, component, workflow, form, dialog, sidebar, navigation, dashboard, or visual UI change; if work touches frontend or user-facing UI, this skill must run even when user mentions only desktop or says "new feature".
Add debug logs (temporary console.log / structured Warn, or permanent namespaced loggers) to investigate or instrument runtime behaviour. Use whenever the user wants to add logs, log statements, console.logs, trace, instrument, or print runtime behaviour to debug a frontend or backend issue. Triggers include "add debug logs", "add some logs", "log this", "trace this", "instrument", "investigate why", "print", "console.log around". Temporary debug logs must be stripped before creating a PR; persistent ones (frontend `createDebugLogger`, backend tier-appropriate level) stay.
Commit, push, and create a PR. Default is ready-for-review with auto-fixup. Use --draft to skip review/fixup.
Stage and commit changes using Conventional Commits. Use when there are dirty/staged files to commit, the user says "commit", or before pushing a PR.
| name | pr-fixup |
| description | Wait for CI checks and automated reviews (CodeRabbit, Greptile, Claude, cubic) on a PR, fix failures and address comments, then push. |
Wait for CI and code review to complete on a pull request, fix any failures or valid comments, then push.
GitHub tool selection: This skill uses
ghCLI commands by default. Ifghis unavailable or fails, use any available GitHub tools in the environment (e.g. MCP GitHub tools) for PR checks, comments, replies, and reviews. Some operations (reactions, resolving threads, fetching CI logs) may not be available in all environments — skip gracefully.
pr-poller subagent (Sonnet) — Polls CI checks and the 4 review bots until terminal, returns a compact structured report. Replaces the old steps 1-3 and the post-push re-check (step 6).verify subagent (Sonnet) — Run the full verification pipeline (format, typecheck, test, lint) before pushing fixes./e2e — Read for debugging guidance when E2E tests fail in CI. Covers test patterns, run commands, failure triage, and local reproduction./commit — Use for staging and committing fixes with Conventional Commits format.git branch --show-currentgh pr view --json number,url,titleThe first thing you do — before fetching PR state, before reading logs, before any fixes — is create a task list for the full pipeline. This is non-negotiable because it keeps you accountable to the process and lets the user see where you are.
Create these tasks immediately (use your task/todo tracking tool if available):
pr-poller — Subagent gathers CI + bot review state, returns a compact reportscripts/run-quiet gh-run -- gh run view ...), fix issues, run E2E tests locally if neededverify subagent; commit fixes; pushpr-poller again. If new failures, loop back to task 2Then start with task 1. Mark each task in_progress when you begin it and completed when you finish it.
pr-pollerMark task 1 as in_progress.
Invoke the pr-poller subagent with the PR number (or let it resolve via gh pr view against the current branch). The subagent:
=== pr-poller report === and === end === markersParse the report. The fields you care about:
ci_failed — list of {name, run_id, conclusion, url}. Empty list ⇒ CI is green.ci_pending — anything still running when the 20-min cap hit. Decide whether to re-invoke pr-poller after a short delay, or proceed with what you have and re-check at step 6.bots.<name> — done / rate_limited / pending / timeout. Anything in done or rate_limited has had its chance; treat the rest as missing data, not a blocker.unresolved_review_threads and issue_comments_from_bots — drive steps 3-4. If both are 0 and ci_failed is empty, skip to step 5 (still run verify + push if you have fixes from earlier).Do not fetch poll output yourself — that is what burns context. The report is the only thing that enters your context.
Mark task 1 as completed.
Mark task 2 as in_progress.
For each entry in the report's ci_failed: list:
run_id from the report (the poller already extracted these — don't re-run gh pr checks).scripts/run-quiet — gh run view --log-failed dumps thousands of lines and will blow your context if it goes straight to stdout. The wrapper redirects to /tmp/kandev-run.gh-run.<random>.log and auto-greps for the relevant error lines:
scripts/run-quiet gh-run -- gh run view <run-id> --log-failed
If the printed summary is enough, stop. Only Read specific line ranges from the printed log path if you need surrounding context.Read with offset/limit, not cat)If the failure looks unfamiliar or the cause isn't obvious from the log, check CI history on the branch before diving into the code:
gh run list --branch <branch> --workflow "<workflow name>" --limit 10 --json conclusion,headSha,createdAt,databaseId
On long-lived PRs that get rebased/squashed, prior SHAs on the same branch often passed the same workflow. A passing → failing boundary tells you the regression is isolated to the most recent rework — diff against the last passing SHA (git diff <last-passing-sha>..HEAD) instead of against main to narrow the search dramatically.
E2E test failures require special handling:
If any failing check is an E2E test (Playwright):
/e2e skill (SKILL.md) for debugging guidance, test patterns, and run commandse2e/test-results/, classify the failure (test logic, frontend, backend)scripts/run-quiet:
scripts/run-quiet build -- make build-backend build-web
scripts/run-quiet e2e -- bash -c 'cd apps && pnpm --filter @kandev/web e2e -- tests/path/to/failing.spec.ts'
Run the specific failing test file(s), not the full suite. Only proceed to step 5 after the test passes locally.Don't dismiss a repeated failure as "flaky". If the same shard or test fails 2+ poll iterations in a row, stop polling and do two cheap checks instead:
main. gh run list --branch main --workflow "<name>" --limit 5 --json databaseId then gh run view <id> --json jobs and diff started/completed timestamps against the PR's run. A shard that takes e.g. 216s on main and 616s on the PR is real test failures + retries pushing past the job's timeout-minutes cap, not infrastructure variance. "Cancelled" at exactly the timeout boundary almost always means this.e2e/test-results/<test>/error-context.md. A single local run (~5-10 min) routinely unlocks fixes that would otherwise burn 3+ CI cycles of speculative "rerun and hope".Recommend a merge over green-pending-flake-rerun only after both checks pass.
Mark task 2 as completed.
Mark task 3 as in_progress.
Use the report's unresolved_review_threads and issue_comments_from_bots counts to know whether there's anything to triage. If both are 0, mark this step completed and move on.
Otherwise, fetch the actual comment bodies on demand — one bot or one set at a time, not all at once:
# Inline review threads (humans, Greptile, Claude same-repo, cubic):
gh api repos/:owner/:repo/pulls/<number>/comments
# Issue comments (CodeRabbit walkthrough, Claude fork findings):
gh pr view <number> --json comments
Verify before implementing. Do not blindly accept review feedback — evaluate each comment technically:
For each comment:
Then classify:
Push back when:
Mark task 3 as completed.
Mark task 4 as in_progress.
Every comment must get a response — either a fix or a reply explaining why it was skipped.
Per-thread engagement is mandatory. Do not take shortcuts:
reviewThreads(first: 100) { nodes { comments(first: 1) { nodes { databaseId } } } } query.isResolved == false set is still non-empty, you are not done.Important: issue comments vs review comments use different APIs:
gh api repos/:owner/:repo/pulls/<number>/comments) — use scripts/pr-resolve (below).gh pr view --json comments — e.g., CodeRabbit walkthrough) — reply by posting a new comment via gh pr comment <number> --body "...", react via gh api repos/:owner/:repo/issues/comments/<comment_id>/reactions -f content="+1". There's no "resolve" concept for issue comments.scripts/pr-resolveUse the script for every review thread, not just batches — it collapses reply + resolve + +1 reaction into a single call so you don't re-derive the graphql mutation each session.
# Dump every unresolved thread, TAB-separated (tid, cid, author, path, body_first_120):
scripts/pr-resolve list <PR>
# Reply + resolve + +1 (same call whether you're agreeing or pushing back —
# the body text conveys which):
scripts/pr-resolve reply <PR> <CID> <TID> "Fixed — monotonic counter via useRef. See commit abc1234."
scripts/pr-resolve reply <PR> <CID> <TID> "Acknowledged; the strict source check was relaxed for E2E. Tracking as a follow-up."
For valid comments: read the file, implement the fix, then call pr-resolve reply with a body that names the commit or the file:line of the fix.
For skipped comments (already addressed, nitpick, wrong, outdated): call pr-resolve reply with a body that explains why. Examples:
For dozens of threads grouped by topic, declare a bash associative array mapping thread IDs → category, then a reply_for case that returns the right body per category. Avoids retyping the same explanation across duplicate threads from multiple bots:
declare -A CAT=(
[PRRT_xxx1]=fixed_counter
[PRRT_xxx2]=fixed_counter
[PRRT_xxx3]=skipped_source_guard
)
declare -A CID=(
[PRRT_xxx1]=3253164429
[PRRT_xxx2]=3253168996
[PRRT_xxx3]=3253164669
)
reply_for() {
case "$1" in
fixed_counter) echo "Fixed — monotonic counter via useRef. See commit abc1234." ;;
skipped_source_guard) echo "Acknowledged; the strict source check was relaxed for E2E. Tracking as a follow-up." ;;
esac
}
for TID in "${!CAT[@]}"; do
scripts/pr-resolve reply <PR> "${CID[$TID]}" "$TID" "$(reply_for "${CAT[$TID]}")"
done
Mark task 4 as completed.
Mark task 5 as in_progress.
Delegate to the verify sub-agent to run the full verification pipeline (format, typecheck, test, lint). It will fix any issues it finds. Wait for it to complete.
Stage and commit the fixes directly. Use a descriptive Conventional Commits message, e.g.:
fix: address PR review feedback
fix: resolve CI lint failures
fix: address review feedback and fix CI failures
Push:
git push
Mark task 5 as completed.
pr-pollerMark task 6 as in_progress.
After the push, CI restarts and bots may re-review. Delegate to pr-poller again — same subagent, same contract, same 20-min cap. Parse the new report:
ci_failed: is empty AND unresolved_review_threads: 0 AND issue_comments_from_bots: 0 (no new bot comments to address) → mark task 6 completed and proceed to summary.in_progress as needed.recommendation: mentions "timed out") → surface the remaining pending items to the user and stop.Cap re-check loops at 3 iterations to prevent runaway sessions. After 3, surface the remaining state to the user and stop.
Mark task 6 as completed.
Mark task 7 as in_progress.
Report what was done:
Mark task 7 as completed.