work-issue
Skill2 starsChanged 25 days agoApache-2.0View on GitHub
Run this repo's issue -> feature branch -> PR -> review -> merge -> cleanup SDLC (SDLC.md) end to end for one GitHub issue -- pick or accept an issue, label it in-progress, create a feature branch and worktree, implement it, open a PR, independently review it, and merge per SDLC.md's policy. Use whenever the user says "work on issue N", "implement the next ticket/issue", "pick up the next backlog item", "/work-issue", or similar -- this is the standard way backlog issues in this repo get turned into shipped code, not an ad hoc one-off.
- Commits and pushes
2 other projects use a version of this.
Adopted by
Most recently taken up by
- prsolans/claude-skillstheir own version, first seen Oct 15, 2026
- Domek-Labs/stagecrew-osstheir own version, first seen Sep 23, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- Domek-Labs/stagecrew-oss★ 0same name
- prsolans/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- announce-releaseSkill
- issue-summarySkill
- sdlcifySkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
30 rules. About 0 are common, 8 are distinctive, and 22 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
22
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
Follow the steps in order, exactly.
- Distinctive: line 14
When a step says Read X now, read that whole file (path from the repo root) before running the step's commands.
- Very specific: line 18
Every Bash call is a fresh shell, so variables do not survive.
- Very specific: line 20
After step 3, work only inside $WORKTREE_DIR.
- Very specific: line 26
If it fails with "No such file or directory": stop, never mkdir the lock dir.
- Distinctive: line 32
Never end a run with CI pending unless step 8.12's "pending CI" rule applies.
- Very specific: line 33
Read the top of .claude/skills/work-issue/references/pitfalls.md now (its contents list names the sections: find one with grep -n '^#' …
- Very specific: line 67
Claim: run this ONE command with <N> filled in.
- Very specific: line 72
Run it in the foreground; it returns at once (no waits or retries since #297).
- Distinctive: line 94
Do not recompute the branch name from the title.
- Very specific: line 96
Otherwise: run this from the main checkout, filling in SLUG and PREFIX:
- Very specific: line 114
Read the issue: gh issue view <N> --json title,body,comments, noting its Why / design intent and Perceptual acceptance check.
- Distinctive: line 119
Write the plan in your reply: files, approach, what you are not doing.
- Very specific: line 126
Read every file before you Edit it.
- Very specific: line 127
If a human could look at the result (art, template, chart, font), read .claude/skills/work-issue/references/demo-surfaces.md now.
- Distinctive: line 128
Commit at checkpoints; heartbeat at each.
- Distinctive: line 130
If measurement disproves the premise: comment the data on the issue, say so atop the PR, propose the follow-up.
- Very specific: line 136
If it brought in only docs, skill or CI files, redo nothing.
- Very specific: line 142
Do pitfalls.md "Step 5 checklist" (cheap checks first).
- Very specific: line 147
Wait for the completion notification or a Monitor (ToolSearch select:Monitor).
- Very specific: line 176
Won't-change outcome or a partial fix: write Refs #<N> instead, because merging Closes #<N> closes the issue as completed (won't-change: …
- Very specific: line 187
If the diff touches .claude/skills/work-issue/, say so in every review comment.
- Very specific: line 191
Run the review as a foreground blocking Bash call (timeout 600000), never run_in_background, never ScheduleWakeup in this turn, never from …
- Very specific: line 202
Check it succeeded; if not, do not post from the file (as in 3): jq -e '.codex.status == 0 and (.codex.stdout // "" | length > 0)' …
- Distinctive: line 204
Read every finding. Decide for each: fix it, or state why not.
- Distinctive: line 206
If you fixed anything: commit, git push (no force), re-run the gate (5.5), go back to 4 with R+1.
- Very specific: line 217
Write <SCRATCH>/issue-<N>-summary.md, starting ## Summary of work (PR #<PR#>) with the sections in codex-review.md, then gh issue comment …
- Very specific: line 223
If a check is pending, heartbeat, then run this with run_in_background: true (~2-3 min.
- Very specific: line 229
Wait for the notification.
- Very specific: line 249
Read
.claude/skills/work-issue/references/finish.mdnow: if you have not (runs that stop at 8.10, a no-merge dispatch, pending CI or a …
≈ “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
work-issue — one issue, start to finish
Goals, in order (#674). (1) Correctness and output quality, judged by the issue's perceptual acceptance check and
docs/dev/TASTE.md; never trade them for a metric. (2) Finish the ticket. pscat performance is a guard, not a goal: report
numbers, never block or retune on noisy local timings. Ghostscript is a correctness reference only: never time it or report
its timing. Don't stop early: wait for CI to finish before handing back.
Follow the steps in order, exactly. Argument: optional issue number <N>.
When a step says Read X now, read that whole file (path from the repo root) before running the step's commands.
Rules for every step:
- Replace
<N>,<PR#>,<PR URL>,<R>,<SCRATCH>with real values. Never type the angle brackets. - Every Bash call is a fresh shell, so variables do not survive. Start each Bash call
that needs them with
WORKTREE_DIR=<absolute path>; BRANCH=<branch>. - After step 3, work only inside
$WORKTREE_DIR. Never edit the main checkout. Nevergit stashthere (refs/stashis shared by all worktrees): usegit show origin/main:pathorcp. - Never
pkill/killall/kill $(pgrep ...)by a pattern (pkill -f pscathas killed other agents' renders). Record$!when you start a process and kill only that PID. - Heartbeat (from step 3 on) — run this when a step says "heartbeat", and before any long command:
bash "$WORKTREE_DIR/.claude/skills/work-issue/scripts/heartbeat.sh" <N>If it fails with "No such file or directory": stop, nevermkdirthe lock dir. Re-run the claim (step 1); continue only if it saysclaimed. - Scratch files go in
<SCRATCH>: the scratchpad directory your system prompt names, else${TMPDIR:-/tmp}(write the literal path). Name them<kind>-<N>.*(gate-,ci-,codex-review-,pr-body-,issue-<N>-summary.md); never a relative path escaping the worktree. They die with the session: decide a resume from GitHub state. - macOS has no
timeout, and foregroundsleepmay be blocked: pitfalls.md "Waiting and timeouts". - Never end a run with CI pending unless step 8.12's "pending CI" rule applies.
- Read the top of
.claude/skills/work-issue/references/pitfalls.mdnow (its contents list names the sections: find one withgrep -n '^#' .claude/skills/work-issue/references/pitfalls.md, read it with Readoffset/limit; onecattruncates).references/rationale.mdsays why each step is shaped so; read it before editing this skill.
1. Pick and claim the issue
Record the start time for the final report: date '+%Y-%m-%d %H:%M:%S %Z'.
The open-PR list (numbers already claimed by an open PR's Closes #N) is used below:
gh pr list --state open --json body --jq \
'[.[].body | scan("(?:Closes|Fixes|Resolves) #([0-9]+)"; "gi") | .[0] | tonumber]'If <N> was given: gh issue view <N> --json state,title,labels, then the open-PR list.
- Closed, or
in-progressAND in the open-PR list → stop, tell the user. in-reviewAND in the open-PR list → a resume: claim below, skip step 2 (never re-addin-progress), follow pitfalls.md "Resume paths" (restores the PR worktree; step 3's new-branch route would lose the PR's work), then step 8 where it says.- Otherwise claim
<N>(below).
If no <N> was given: first look for an abandoned run to resume:
# in-progress issues with no open PR claiming them = crashed-or-still-live prior runs
gh issue list --state open --label in-progress --json number,titleFor each in-progress issue not in the open-PR list, lowest number first, claim it.
Resume the first that says claimed (step 3 reuses its worktree). If none, pick a fresh one:
# candidates: open, not in-progress, lowest number first
gh issue list --state open --search "-label:in-progress" \
--json number,title,labels --jq 'sort_by(.number)'Claim the first candidate not in the open-PR list. None → report "backlog clear", stop.
Claim: run this ONE command with <N> filled in. Never paste, retype or abbreviate the
lock commands: the script is the race-tested protocol, and a partial copy has failed before.
bash "$(git rev-parse --show-toplevel)/.claude/skills/work-issue/scripts/claim.sh" <N>Run it in the foreground; it returns at once (no waits or retries since #297).
(references/claim-protocol.md is the rationale; read it only to edit the script.) Then:
RESULT=claimed*→ you own<N>. Continue.RESULT=live*orRESULT=lost*on a resume candidate → claim the next one (then the fresh picker). On an explicit<N>or a fresh pick → stop, report<N>is being worked on, try nothing else.
2. Mark it in-progress
gh label create in-progress --color FBCA04 --description "Actively being worked on" 2>/dev/null || true
gh label create in-review --color 0E8A16 --description "Implementation done, PR open, awaiting human review" 2>/dev/null || true
gh issue edit <N> --add-label in-progress3. Branch and worktree
If a worktree for <N> already exists (git worktree list shows a
path ending -issue-<N>): set WORKTREE_DIR to that absolute path and run:
BRANCH="$(git -C "$WORKTREE_DIR" branch --show-current)"
bash "$WORKTREE_DIR/.claude/skills/work-issue/scripts/heartbeat.sh" <N>Do not recompute the branch name from the title. Skip to step 4 (resume: step 8).
Otherwise run this from the main checkout, filling in SLUG and PREFIX:
git fetch origin main
REPO_DIR=$(basename "$(git rev-parse --show-toplevel)")
SLUG=<kebab-case slug of the issue title, ~40 chars, no leading/trailing hyphens>
PREFIX=feature # or "fix" if the issue carries the `bug` label — AGENTS.md's convention
BRANCH="${PREFIX}/<N>-${SLUG}"
WORKTREE_DIR="../${REPO_DIR}-issue-<N>"
git worktree add --no-track -b "$BRANCH" "$WORKTREE_DIR" origin/main
# Optional (#1033): build on another disk. A no-op unless PSCAT_TARGET_ROOT names an existing folder.
[ -n "${PSCAT_TARGET_ROOT:-}" ] && [ -d "$PSCAT_TARGET_ROOT" ] && mkdir -p "$PSCAT_TARGET_ROOT/issue-<N>" && ln -s "$PSCAT_TARGET_ROOT/issue-<N>" "$WORKTREE_DIR/target"
(cd "$WORKTREE_DIR" && pwd) # note this absolute path: it is WORKTREE_DIR from now on
bash "$WORKTREE_DIR/.claude/skills/work-issue/scripts/heartbeat.sh" <N>Then re-read $WORKTREE_DIR/.claude/skills/work-issue/SKILL.md (it may have changed since invocation) and follow that copy.
4. Plan, then get the plan reviewed
- Read the issue:
gh issue view <N> --json title,body,comments, noting itsWhy / design intentandPerceptual acceptance check. Make design calls yourself; flag only what is hard to reverse. - Estimate size from the whole diff (code, tests, notes). Small = 20 lines or fewer AND no API change (no new/changed public Rust item, PostScript operator, CLI flag or lib procedure name). Otherwise full. The only definition of small, except that a won't-change PR (step 7) is always small.
- Write the plan in your reply: files, approach, what you are not doing.
- Hard gate, no code before it. Heartbeat, then call the
advisortool (small: one short call, or skip and say so). If it objects, revise the plan. Heartbeat. The report'sPlan reviewline must saydoneorskipped (small). After it a throwaway measurement prototype is allowed (pitfalls.md "Prototypes and timing").
5. Implement
- Read every file before you Edit it. Follow AGENTS.md's "Code quality bar"; write notes in
notes/<N>-<slug>.md(never docs/archive/NOTES.md), update docs/dev/HANDOFF.md and the matchingdocs/guides/page (README.md is a short front door; edit it only for a headline change). - If a human could look at the result (art, template, chart, font), read
.claude/skills/work-issue/references/demo-surfaces.mdnow. - Commit at checkpoints; heartbeat at each. Evidence sweeps, scratch dirs: pitfalls.md "Evidence runs and scratch hygiene".
- Never
gh issue create. Propose follow-ups in the final report (finish.md "Proposed follow-ups"). If measurement disproves the premise: comment the data on the issue, say so atop the PR, propose the follow-up. Nothing worth committing (not even notes): no PR, finish.md "Close without a PR" instead of steps 6-9. - Quality gate. Rebase as late as possible, right before the identity check and the gate, and
before the first push:
git -C "$WORKTREE_DIR" fetch origin main && git -C "$WORKTREE_DIR" rebase origin/main(a no-op when up to date; conflicts, or a PR that exists: pitfalls.md "Rebase and merge rules"). After a rebase that movedHEAD, re-read$WORKTREE_DIR/.claude/skills/work-issue/SKILL.mdand follow that copy. If it brought in only docs, skill or CI files, redo nothing; if it brought inlib/,src/or tests, redo the identity base, the identity check and the full gate (same entry); a later merge ofmain(the 8.12 local merge forDIRTY) that brings those in after the gate: re-run it, or write "CI covers it". Alib/change that must render identically:scripts/identity_check.sh --loader <lib>; asrc/one: add--base-bin/--head-bin(checklist item 4); an intended visible change: add--expect-diff LIST(tier b, 8.10). List its base worktree in step 9'sEXTRA_WORKTREES. A diff entirely inside SDLC.md'slight_gate.paths(docs, notes) runs its command instead of the full gate (checklist item 7). Do pitfalls.md "Step 5 checklist" (cheap checks first). Heartbeat, then run withrun_in_background: true(over 120s; run it in the foreground if the last gate took under ~60 s):
Wait for the completion notification or a Monitor (rm -f <SCRATCH>/gate-<N>.log && cd "${WORKTREE_DIR:?}" && { PSCAT_PROFILE=ci ./scripts/selftest.sh && cargo test --profile ci && cargo clippy --all-targets -- -D warnings && cargo fmt --all -- --check; } > <SCRATCH>/gate-<N>.log 2>&1; echo "GATE_EXIT=$?" >> <SCRATCH>/gate-<N>.logToolSearch select:Monitor); neversleeporScheduleWakeup.tail -40 <SCRATCH>/gate-<N>.logmust end withGATE_EXIT=0; else fix, re-run. Heartbeat.
6. Review the implementation
git -C "$WORKTREE_DIR" diff --numstat origin/main...HEAD— measure the size.- Small (step 4): one short self-check or
advisorcall. Otherwise heartbeat, thenadvisor, asking it to check state mutated across branches (gsave/dict unwinding on every error path, font/graphics state changed mid-loop), multi-byte/encoding edge cases, hidden side effects (non-PostScript diff: say "not applicable"). - Fix real findings, re-run the gate (5.5), heartbeat. Don't loop on subjective feedback.
7. Open the PR
cat > <SCRATCH>/pr-body-<N>.md <<'EOF'
## Summary
<what changed and why, in a few bullets>
Closes #<N>
## Test plan
- [x] PSCAT_PROFILE=ci ./scripts/selftest.sh && cargo test --profile ci && cargo clippy --all-targets -- -D warnings && cargo fmt --all -- --check
<+ whatever else was actually run/verified>
EOF
python3 scripts/pr_body_lint.py <SCRATCH>/pr-body-<N>.md --git-range origin/main..HEAD && git push -u origin "$BRANCH" && \
gh pr create --title "<summary>" --body-file <SCRATCH>/pr-body-<N>.md # lint exit 1: fix the body (or reword the commit: nothing is pushed yet), rerunThe body must contain Closes #<N> on its own line even when you write it without this template.
Won't-change outcome or a partial fix: write Refs #<N> instead, because merging Closes #<N> closes the issue as completed
(won't-change: step 9 closes it as not planned). A close keyword in a negated or partial sentence ("does not fix #12") still
closes the issue: the lint above catches it. A PR that needs the owner (8.10 tier c, or b failed) opens with the Decision block (perceptual-review.md). Then:
gh issue edit <N> --remove-label in-progress --add-label in-review
gh issue comment <N> --body "Opened <PR URL>."8. Independent review, then merge
- Read
.claude/skills/work-issue/references/codex-review.mdnow (full policy), andmerge_policyfromgit show origin/main:SDLC.md. - If the diff touches
.claude/skills/work-issue/, say so in every review comment. Codex reviews read-only and cannot run harnesses: for concurrency or shell changes the advisor plus real load runs are the review that counts. - Find Codex:
CODEX_SCRIPT=$(find "$HOME/.claude/plugins" -path "*/codex/scripts/codex-companion.mjs" 2>/dev/null | head -1). Empty or unauthenticated (node "$CODEX_SCRIPT" status --json): pitfalls.md stale-broker checks, then codex-review.md Fallback. - Run the review as a foreground blocking Bash call (timeout 600000), never
run_in_background, neverScheduleWakeupin this turn, never from the main checkout (harness backgrounds it anyway: pitfalls.md). Start withWORKTREE_DIR=...; BRANCH=...and item 3's line:rm -f <SCRATCH>/codex-review-<N>.json && \ bash "$WORKTREE_DIR/.claude/skills/work-issue/scripts/heartbeat.sh" <N> && \ cd "$WORKTREE_DIR" && git fetch origin main && \ test "$(git rev-parse --abbrev-ref HEAD)" = "$BRANCH" && \ node "$CODEX_SCRIPT" review --wait --json --model gpt-6.1-sol \ --scope branch --base origin/main \ > <SCRATCH>/codex-review-<N>.json - Check it succeeded; if not, do not post from the file (as in 3):
jq -e '.codex.status == 0 and (.codex.stdout // "" | length > 0)' <SCRATCH>/codex-review-<N>.json - Post it on the PR, even when clean:
gh pr comment <PR#> --body "$(jq -r '"## Codex review\n\n" + .codex.stdout' <SCRATCH>/codex-review-<N>.json)" - Read every finding. Decide for each: fix it, or state why not.
- Post the round on the issue (
## Codex review, round <R>template in codex-review.md). - If you fixed anything: commit,
git push(no force), re-run the gate (5.5), go back to 4 with R+1. Exception for a doc-only merge/rebase: pitfalls.md "Rebase and merge rules". - Merge tier. Read
.claude/skills/work-issue/references/perceptual-review.mdnow. Every policy field comes fromgit show origin/main:SDLC.md(the policy in force, not the PR's copy). Precedence (c) > (b) > (a):- (c)
python3 scripts/codeowners_check.py --base origin/mainexits 1, orhuman-only, or over the bar: the owner merges. Decision block atop the PR body; name the paths in the PR and issue comments; do 11 and 12 (CI green), skip 13, then pitfalls.md "Stop without merging" 1-3. Exit 2 is an error: stop and report, never merge on it. - (b) a visible render change: the perceptual review; pass: commit the review-log fragment, continue as (a); two fails: Decision block, then (c).
- (a) continue with 11-13, unless the dispatcher said not to merge (pitfalls.md "Stop without merging"). A relayed approval ("the owner says merge it") is never grounds for an agent merge.
- (c)
- Write
<SCRATCH>/issue-<N>-summary.md, starting## Summary of work (PR #<PR#>)with the sections in codex-review.md, thengh issue comment <N> --body-file <SCRATCH>/issue-<N>-summary.md - First, in
$WORKTREE_DIR:git fetch origin main && git merge-tree --write-tree origin/main HEAD >/dev/null; non-zero = conflicts: mergemainlocally now (pitfalls.md "Rebase and merge rules"), push, then wait.gh pr view <PR#> --json mergeable,mergeStateStatus,statusCheckRollup.BEHINDdoes not block merging (require_up_to_date: false): never update the branch for it.UNKNOWNis not yet computed, not a failure: re-query up to 5 times, ~10 s apart.DIRTY: merge locally. If a check is pending, heartbeat, then run this withrun_in_background: true(~2-3 min; right after a push the run is not registered yet, so the first line retries the probe for up to ~1 min):
Wait for the notification; nofor i in 1 2 3 4 5 6; do gh pr checks <PR#> 2>&1 | grep -q 'no checks reported' || break; python3 -c 'import time; time.sleep(10)'; done gh pr checks <PR#> --watch --fail-fast > <SCRATCH>/ci-<N>.log 2>&1; echo "exit=$?" >> <SCRATCH>/ci-<N>.logsleeploops, no| tail, no hand-back while it runs. Read only the end of the log (tail -n 25 <SCRATCH>/ci-<N>.log);exit=is a hint only. Heartbeat after every watch, wait ~10 s, re-run themerge-treeline above, then merge only if this printstrue(a brief post-watchfalseorUNKNOWN: re-query up to 3 times, ~10 s apart, before calling it a failure):gh pr view <PR#> --json mergeable,mergeStateStatus,statusCheckRollup --jq '(.mergeable == "MERGEABLE" and .mergeStateStatus != "DIRTY") and ([.statusCheckRollup[] | (.conclusion // .state)] | (length > 0 and all(. == "SUCCESS")))'Otherwise see pitfalls.md "CI wait" (pending, infra failure:gh run rerun --failed; a failed step: stop and report). Never merge past a failure or use--admin. Cannot wait: pitfalls.md "Pending-CI hand-back". - Immediately before merging, re-run the
merge-treecheck and the query above (state settles late).gh pr merge <PR#> --squash(no--delete-branch: the repo deletes the remote branch; step 9 the local).
9. Post-merge cleanup
Read .claude/skills/work-issue/references/finish.md now and run its "Step 9" block as one Bash call. It runs from the
main checkout (not the worktree) and starts by re-declaring WORKTREE_DIR and BRANCH. It aborts unless the PR is MERGED;
if the issue is still OPEN it closes it with a comment linking the PR (won't-change: finish.md's variant), and removes any
extra worktrees you recorded. Then confirm main CI for your merge commit (pitfalls.md "Main CI after merge"). Red: stop,
report it first, start no other work.
10. Final report
Read .claude/skills/work-issue/references/finish.md now if you have not (runs that stop at
8.10, a no-merge dispatch, pending CI or a close without a PR skip step 9). End the run by printing its "Step 10" report
template, filled in, none where empty. Its lines: PR, Merge, Plan review, Checks, Wall time, Review rounds, Steps skipped or failed,
Proposed follow-ups, Cleanup, Friction.
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.

