pk-bug
Skill6 starsChanged 2 months agoMITView on GitHub
Bug pipeline — intake, reproduce, regression-test-first, fix, ship, postmortem. Wraps /work and pk ship with discipline gates. Invoke when a bug is reported or spotted. Linear is the source of truth — resume by passing the issue ID.
In this repository32 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- brainstorm-reviewSkill
- brainstormSkill
- conceptSkill
- defineSkill
- financial-reviewSkill
- light-spec-reviseSkill
- light-specSkill
- linear-hygieneSkill
- linearSkill
- phase-planSkill
- pipekit-helpSkill
- pipekit-updateSkill
- pk-exitSkill
- pk-expressSkill
- pr-fixSkill
- prod-readySkill
- pr-security-reviewSkill
- release-changelogSkill
- repo-security-reviewSkill
- review-planSkill
- roadmap-createSkill
- roadmap-reviewSkill
- security-gateSkill
- spec-preflightSkill
- startupSkill
- strategy-createSkill
- strategy-syncSkill
- sync-linearSkill
- tpmSkill
- verifySkill
- workSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 9 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 17
Do NOT use for:
- Distinctive: line 42
Before entering Phase 1 (new bug), or any resume that routes to Phase 2, check the current checkout:
- Very specific: line 57
When invoked with an existing <ISSUE-ID>, query Linear and enter the phase below:
- Distinctive: line 84
Goal: create a well-formed Linear issue.
- Very specific: line 86
Ask the user the questions in this skill's templates/intake.md.
- Very specific: line 92
Urgent fast path: if user picks Urgent, skip detailed intake — capture one-liner + priority, mark issue body with Fast-path: Urgent — fill …
- Very specific: line 93
Create Linear issue in one call — pk issue create --title "…" --description-file <intake.md> --state Backlog --priority N --label Bug …
- Distinctive: line 107
Read repro steps from the Linear issue body.
- Distinctive: line 135
Use the scientific method:
- Distinctive: line 137
Verify by reading the relevant code / logs / DB
- Very specific: line 141
If diagnosis takes more than ~30 minutes of investigation, consider spawning a dedicated debugging subagent (general-purpose) to …
- Distinctive: line 171
Run the test. It MUST fail for the right reason — the bug exists, not a setup error.
- Distinctive: line 184
Commit ONLY the test (from inside the worktree):
- Very specific: line 189
Verify: git log --oneline shows the test(<ISSUE-ID>) commit as the latest, and re-running the test still fails (the fix hasn't been written …
- Distinctive: line 202
Run the regression test alone — must pass
- Very specific: line 203
Run /verify — full pre-deploy gate
- Very specific: line 225
After main deploys, Linear should auto-transition to Done (per the existing automation).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/pk-bug Skill
You run the bug pipeline: a disciplined wrapper around the daily loop that enforces regression-test-first fixing. The point: a bug, once fixed, must never silently re-ship — there must be a test that would have caught it.
When to use
Invoke when:
- A bug is reported by a user
- You spot a bug during dev or QA
- You're resuming a bug already in flight (
/pk-bug <ISSUE-ID>)
Do NOT use for:
- New features (use
pk next→/work) - Spec work (use
/light-spec) - PR review of an unrelated change (use
/pr-fix)
Invocation forms
/pk-bug # new bug, prompts for everything
/pk-bug "<one-liner>" # new bug, description prefilled
/pk-bug <ISSUE-ID> # resume — reads Linear, routes to right phaseSource of truth
Linear is authoritative. This skill stores no local state. Every resume reads the Linear issue (status, body, comments) and routes to the correct phase. New session safe.
Read method.config.md for:
- Linear team ID, workflow state IDs
- Pre-deploy gate commands
Preflight — checkout guard (applies to Phases 1–2 only)
Phases 1–2 (intake + reproduce) run from the repo-root integration-branch checkout (main or the configured integration branch). The moment Phase 2 reproduces the bug, pk branch <ID> cuts an isolated worktree off origin/<integration> (see bin/pk) and every phase from 3 on runs inside that worktree — so diagnosis, the failing test, and the fix never touch the shared integration checkout and never collide with other agents working there. (Reproduce is read-mostly; the working-tree writes that used to sit on main — the test file especially — now land in the worktree, committed test-first.)
Before entering Phase 1 (new bug), or any resume that routes to Phase 2, check the current checkout:
current=$(git rev-parse --abbrev-ref HEAD)
# integration = `Integration branch` from method.config.md (pk falls back to origin/dev, else origin/HEAD)- You're in the repo-root checkout (not inside another
pk branchworktree) → proceed. Phase 2 cuts this bug's worktree for you once it reproduces;pk branchbases offorigin/<integration>regardless of which local branch you're on, so the baseline is always current integration HEAD. - You're inside an existing
pk branchworktree → STOP (running a new bug's intake/reproduce here would nest worktrees). Tell the user:/pk-bugintake + reproduce should run from the repo-root checkout, not inside the<other>worktree — Phase 2 cuts this bug's own worktree once it reproduces.cd <repo-root>and re-invoke, or finish/park the current worktree first. (To resume a bug already past Phase 2, pass its<ISSUE-ID>— that routes straight into its worktree.)
This guard does not apply to resume routing into Phases 3–8 — by then the worktree exists and running from inside it (statusType=started) is the correct location.
Resume routing
When invoked with an existing <ISSUE-ID>, query Linear and enter the phase below:
Routing keys off Linear's statusType (not display name) so projects with custom statuses like Parked route correctly. If the resolved phase is 1–4, run the Preflight checkout guard above first; phases 5–8 skip it (the worktree already exists).
| Linear state | Enter phase |
| Issue not yet created | 1 — Intake |
statusType=backlog, no "Reproduced:" comment | 2 — Reproduce (cuts the worktree on success) |
statusType=started, worktree exists, no test(<ID>) commit in branch | 3 — Diagnose + Test |
statusType=started, test(<ID>) commit exists, no fix commit | 4 — Commit/confirm test-first, then 5 — Fix |
statusType=started + PR open (or status named UAT/Review) | 6 — PR review + merge to dev |
| Merged to dev, not on main | 7 — Promote dev → main |
statusType=completed, no postmortem comment (priority ≤ Medium = 3) | 8 — Postmortem |
statusType=completed, postmortem present | report complete, exit |
Heuristics for state detection:
- "Reproduced" = Linear comment starting with
Reproduced:(you write this in Phase 2, just before cutting the worktree) - "Worktree exists" =
git worktree listshows a<ISSUE-ID>worktree (cut in Phase 2) - "Test commit exists" = from inside that worktree,
git log --onelineshows atest(<ISSUE-ID>):commit - "Postmortem present" = Linear comment containing
# Postmortemheading
For resume into Phases 3–8, cd into the existing <ISSUE-ID> worktree first (that's where the branch's work lives).
Phase 1 — Intake
Goal: create a well-formed Linear issue.
- Ask the user the questions in this skill's
templates/intake.md. If a one-liner was passed, prefill the description hint. - Priority heuristic to show the user (Linear
priorityfield — native, no custom labels):Urgent(1) — data loss / auth bypass / money / production downHigh(2) — core flow broken (e.g. sign-out failing for magic-link users)Medium(3) — degraded UX, workaround existsLow(4) — cosmetic / single-user / edge case
- Urgent fast path: if user picks
Urgent, skip detailed intake — capture one-liner + priority, mark issue body with**Fast-path: Urgent** — fill in details during postmortem. Postmortem becomes mandatory + reviewer sign-off in Phase 8. - Create Linear issue in one call —
pk issue create --title "…" --description-file <intake.md> --state Backlog --priority N --label Bug --label "Area: <area>" --label "Repo: <repo>"(verb table:sop/Linear_SOP.md § Linear transport):- Team: from
method.config.md - Status: backlog-type (e.g.
BacklogorParked— anything withstatusType=backlog) - Priority: 1–4 per the heuristic above
- Labels:
Bug(no severity labels — priority is the native field) plus anArea:label chosen for this bug's own work frommethod.config.md § Area Labels, and aRepo:label from§ Repo Labelswhere that section is populated.pk issue createrefuses a create with noArea:on a board that configures them; a bug filed as bareBugis the drift/linear-hygieneexists to catch (a consumer project, 2026-10). Full placement contract:sop/Linear_SOP.md § Filing a follow-up issue. - Body: the filled intake template
- Team: from
- Echo
<ISSUE-ID>to the user. Advance to Phase 2.
Phase 2 — Reproduce (GATE)
Goal: reproduce locally before any diagnosis.
- Read repro steps from the Linear issue body.
- Reproduce by the most direct path:
- UI bug: Playwright MCP, walk the steps
- Backend logic:
curl/ direct test invocation - Auth flow (e.g. magic-link sign-out): full e2e — sign in, observe state, sign out, assert state changed
- Gate decision:
- Reproduced → comment on Linear:
Then cut the worktree and move into it immediately — every phase from here runs in isolation, off the shared integration checkout:Reproduced: <one-line evidence> - Method: <Playwright | curl | manual> - Artifact: <screenshot path | log snippet | n/a>
Advance to Phase 3 (inside the worktree).pk branch <ISSUE-ID> # creates worktree + branch off origin/<integration>, Linear → In Progress cd <worktree-path> # pk prints the path; all of Phase 3+ runs here - Cannot reproduce → Linear status to
Triageor labelneeds-info, comment with everything tried. STOP. Do not guess-fix. Inform user, exit. (No worktree was cut — you're still on the integration checkout, nothing to clean up.)
- Reproduced → comment on Linear:
Phase 3 — Diagnose + Failing Regression Test (GATE)
Goal: find root cause AND write a test that fails because the bug exists. Done inside the worktree (cut in Phase 2) — the test file is written here and committed test-first in Phase 4.
3a — Diagnose
Use the scientific method:
- State a hypothesis (1 sentence)
- Verify by reading the relevant code / logs / DB
- Narrow until you have a one-paragraph root-cause statement
- Append the root cause to the Linear issue body under
## Root Cause
If diagnosis takes more than ~30 minutes of investigation, consider spawning a dedicated debugging subagent (general-purpose) to investigate in a fresh context. Don't burn the main context on a deep dive.
3b — Write the failing test
Pick the right test type for the bug:
| Bug type | Test type | Location convention |
| Logic / data layer | Unit or integration | colocated *.test.ts |
| UI behavior | Playwright e2e | tests/e2e/ |
| Pure visual / spacing | Playwright visual snapshot (toHaveScreenshot()) | tests/e2e/visual/ |
| Auth / session flow | Playwright e2e (full session lifecycle) | tests/e2e/auth/ |
Auth-flow test shape (illustrative — adapt to your stack):
test('user state is fully cleared after sign-out', async ({ page }) => {
await signIn(page, testUser);
await expect(page).toHaveURL('/dashboard');
await signOut(page);
await expect(page).toHaveURL('/login');
// Critical: session is actually gone, not just UI redirect
const cookies = await page.context().cookies();
expect(cookies.find(c => c.name.includes('auth'))).toBeUndefined();
await page.goto('/dashboard');
await expect(page).toHaveURL('/login'); // protected route bounces
});Gate
Run the test. It MUST fail for the right reason — the bug exists, not a setup error.
- ✅ Test imports cleanly, the bug-specific assertion fails → continue
- ❌ Import error / fixture missing / timeout / 500 from setup → fix the test, do not advance
Append test path to Linear issue body under ## Regression Test.
Phase 4 — Commit the failing test (test-first audit trail)
Goal: land the failing test as the first commit, before any fix. The worktree already exists (cut in Phase 2), so this is just the commit — no branch handoff, no stash.
- Commit ONLY the test (from inside the worktree):
git add <test-path> git commit -m "test(<ISSUE-ID>): add failing regression test for <one-liner>" - Verify:
git log --onelineshows thetest(<ISSUE-ID>)commit as the latest, and re-running the test still fails (the fix hasn't been written yet).
This commit is the audit trail. Anyone reading git log later sees the test landed before the fix — and because the test was authored in the worktree from the start, there's no orphaned-on-main / stash-handoff risk.
Phase 5 — Fix + Verify + Ship
Goal: make the test pass, ship.
- Hand off to
/work <ISSUE-ID>with this directive in the prompt:A regression test exists at
<test-path>and currently fails. Your job is to make it pass without modifying the test file. The root cause is documented in the issue body under## Root Cause. - After
/workcompletes:- Run the regression test alone — must pass
- Run
/verify— full pre-deploy gate
pk ship— opens PR, Linear →UAT- For auth / RLS / migration bugs:
pk ship --reviewto invoke the antagonistic reviewer
- For auth / RLS / migration bugs:
Phase 6 — PR review + merge to dev
- Optional but encouraged for priority ≤ Medium (1–3):
- Auth / security bugs →
/pr-security-review - General code quality →
/pr-fix
- Auth / security bugs →
- Address review feedback (commit on the same branch)
- Merge PR to
dev pk done <ISSUE-ID>— verifies merged, cleans worktree+branch, posts commit summary to Linear
Phase 7 — Promote dev → main
Urgent→ runpk promoteimmediately (solo promote, do not batch)High/Medium/Low→ leave for the next batched promote. Comment on Linear:Awaiting next dev → main promote.
After main deploys, Linear should auto-transition to Done (per the existing automation).
Phase 8 — Postmortem
Mandatory for priority ≤ Medium (1–3). Optional but recommended for low.
- Append a Linear comment using this skill's
templates/postmortem.md:- What broke (1 sentence)
- Which gate should have caught it
- One change to prevent recurrence
Urgent only: request reviewer sign-off in the comment thread. The bug is not closed out until that sign-off lands — whatever state Linear is showing.
Do not read this as "sign off before the issue reaches
Done." It almost never will.pk shipputs the issue ID at the front of the PR title (bin/pk:--title "${issue}: ${title}"), so wherever Linear's GitHub integration is configured to transition on merge, the issue flips toDoneback at Phase 6 — two phases before this one. (Phase 7's note about the deploy auto-transition is the same mechanism, one phase later.) A gate keyed on "beforeDone" is unreachable by construction: an Urgent bug arrives atDonewith no postmortem and no sign-off, and nothing anywhere reports it.Doneis not evidence that this phase ran.Gate on the artifact instead. An Urgent bug is closed out when its issue carries both a
# Postmortemcomment and a filled-in reviewer sign-off./linear-hygienePhase 2c reports issues missing either.Anchor: a consumer project, 2026-08 — an Urgent bug auto-closed on merge and sat
Donewith no postmortem. It got written a day later only because the operator went looking, and it was the postmortem that found the actual gate: an ESLint rule (no-inner-declarations) dropped fromeslint:recommendedin v9, silently off ever since. The fix alone would have left that open for the next occurrence.- If "one change to prevent recurrence" is concrete (e.g. "add Playwright e2e for every auth-method × sign-out combo"), create a follow-up Linear issue or add a rule to
.claude/rules/. The issue is filed tosop/Linear_SOP.md § Filing a follow-up issue:Source: <BUG-ID> postmortemas the body's first line, the bug'sArea:label, a Type label (usuallyTech DebtorChore— the prevention is rarely itself a Bug), priority from the floor table, state by that priority,relatesto the bug. Name the new identifier and its placement in the postmortem comment.
Invariants
| Rule | Enforcement |
| Phases 1–2 run from the integration checkout; Phases 3–8 run in the worktree | Preflight guard (STOP if invoked inside another worktree); Phase 2 cuts the worktree on repro |
| No fix code before failing test exists | Phase 3 writes the test; Phase 4 commits it test-first, before any fix |
| Cannot repro → STOP | Phase 2 gate; mark needs-info, exit (no worktree cut) |
| Linear is the source of truth | Resume always re-reads Linear, never local state |
| Postmortem mandatory for priority 1–3 | Phase 8; reviewer sign-off if Urgent. Gate on the artifact (a # Postmortem comment + filled sign-off), never on the issue reaching Done — the PR-title auto-transition beats Phase 8 to it |
| Urgent → solo promote | Phase 7 |
| Test commit lands before fix commit | Phase 4 commits the test; Phase 5 writes the fix |
Failure modes to avoid
- Don't skip Phase 2 because the bug "obviously" exists. Unrepro'd bugs get guess-fixed and ship as silent regressions.
- Don't write the test after the fix. A test written against passing code tests the fix, not the spec — it won't catch the same bug class re-introduced later.
- Don't fold test + fix into one commit. The audit trail is part of the value.
- Don't promote
Urgentbugs in a batch. Blast radius mismatch. - Don't treat
Doneas proof Phase 8 ran. The PR-title auto-transition closes the issue at merge, before the postmortem exists. Check for the# Postmortemcomment, not the state.
Common Rationalizations
| You're about to say… | The rebuttal |
| "The fix is obvious, repro is a waste of time" | Phase 2 is a GATE because unrepro'd bugs get guess-fixed and ship as silent regressions — and "this error is probably X" is a Red Flag, not a diagnosis. Can't repro → needs-info, not a guess-fix. |
| "I'll write the test after the fix" | A test written against passing code tests the fix, not the spec (Red Flags). Test-first is the audit trail — the failing commit is the repro record. |
| "It's urgent — skip the process" | Urgent changes the routing (solo promote, Phase 7), not the discipline. The postmortem stays mandatory for priority 1–3; urgency is when guess-fixes are most tempting and most expensive. |
"Linear already says Done — the bug is finished" | Done arrived from the PR-title auto-transition at Phase 6; nobody decided the work was complete. For priority 1–3 the postmortem is still owed, and for Urgent so is the sign-off. The state is a side effect of a merge — the artifact is the evidence. |
| "It's three small bugs, I'll batch them in one run" | One bug per run — a bundle gets one repro, one test, one postmortem, and two of the three bugs lose their audit trail. Split first (/linear-hygiene's bundle rule exists for the same reason). |
Origin
Built locally in rs-vault, dogfooded on RS-94 (magic-link Enter-key OAuth misroute, 2026-05-07), promoted to Pipekit upstream after the first clean run. The pattern: build a candidate skill in a consuming project under .claude/skills/<name>/, dogfood on a real ticket, promote to pipekit/skills/<name>/ once it earns its keep, sync back via sync-method.sh.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

