rk-skills 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: fix-pr-review
3
+ description: Use when the user asks to fix, address, or respond to a PR review — "fix the PR review", "address the review comments", "/fix-pr-review". Takes an optional PR number/URL (defaults to the current branch's PR). Fetches all unaddressed review feedback on the PR (formal reviews, review-style issue comments, and inline diff comments), RE-VALIDATES every finding against the actual code before touching anything (never blind-implements), fixes the findings that survive validation, and for judgment calls and optional improvements derives and implements the absolute-best solution autonomously without pausing, then commits and pushes, posts a per-finding disposition comment back to the PR, and triggers a fresh @claude re-review.
4
+ ---
5
+
6
+ # fix-pr-review
7
+
8
+ Take all unaddressed review feedback on a pull request and resolve it fully and autonomously: re-validate each finding against the code, fix the ones that are real, push back on the ones that aren't, and for the judgment calls the reviewer couldn't make — and for the optional improvements — derive and implement the absolute-best solution rather than pausing. Then report back on the PR and request a re-review. Don't stop to ask the user; do the work.
9
+
10
+ **The review is a hypothesis, not a work order.** A reviewer (human or `@claude`) can cite a stale line, misread a conditional, or flag a non-bug. Implementing a wrong suggestion ships a regression with a reviewer's blessing. So every finding is traced to current `file:line` and confirmed *before* you change anything. You are not performing agreement — you are verifying claims and acting only on the ones that hold.
11
+
12
+ ## Input
13
+
14
+ The user provides one of:
15
+ - Nothing — **default to the PR for the current branch** (`gh pr view`).
16
+ - `#<N>` / `<N>` / full URL / `owner/repo#N`.
17
+
18
+ If the current branch has no PR and none was given, say so and stop — there's nothing to fix.
19
+
20
+ ## Steps
21
+
22
+ ### 0. Resolve the PR and sync the branch
23
+
24
+ ```bash
25
+ gh pr view <N|--> --json number,headRefName,headRepositoryOwner,baseRefName,url,state,isDraft
26
+ git fetch origin
27
+ git branch --show-current
28
+ ```
29
+
30
+ - Confirm you are **on the PR's head branch** (`headRefName`). If not, check it out with `gh pr checkout <N>` — it handles fork-hosted head branches and sets upstream tracking. Fixes must land on the branch the PR tracks, never on `main` or a divergent branch. Never fix a review by committing to the base branch.
31
+ - Note whether the PR is from a **fork** (`headRepositoryOwner` differs from the base repo's owner) — the head branch then lives in the fork, so pulls and pushes go to the branch's tracked upstream, not `origin`.
32
+ - Pull the latest head so you fix against what the reviewer saw: `git pull --ff-only` on the tracked upstream (if it can't fast-forward, stop and tell the user the branch diverged).
33
+ - Note the PR state. If it's already `merged` or `closed`, stop and report — don't reopen work on a closed PR without the user.
34
+
35
+ ### 1. Fetch all unaddressed review feedback
36
+
37
+ Review feedback arrives through three channels: formal GitHub PR reviews, plain issue comments (the `@claude` bot posts the verdict-and-sections format as an issue comment), and **inline diff comments** (line-level threads, where human reviewers most often comment). Fetch all three:
38
+
39
+ ```bash
40
+ # PR reviews (formal review events) — state included so DISMISSED reviews can be skipped
41
+ gh api repos/{owner}/{repo}/pulls/<N>/reviews --paginate --jq '.[] | {id, user: .user.login, state, submitted_at, body}'
42
+ # Issue comments on the PR (where @claude review output usually lands) — REST + --paginate for completeness
43
+ gh api repos/{owner}/{repo}/issues/<N>/comments --paginate --jq '.[] | {author: .user.login, created_at, body}'
44
+ # Inline diff threads WITH resolution state — REST can't report isResolved, so use GraphQL
45
+ gh api graphql -F owner='{owner}' -F repo='{repo}' -F pr=<N> -f query='
46
+ query($owner:String!,$repo:String!,$pr:Int!){ repository(owner:$owner,name:$repo){ pullRequest(number:$pr){
47
+ reviewThreads(first:100){ pageInfo{hasNextPage endCursor} nodes{ isResolved isOutdated path line
48
+ comments(first:50){ nodes{ databaseId author{login} createdAt body } } } } } } }'
49
+ ```
50
+
51
+ (If `hasNextPage` is true, paginate with `endCursor` — don't silently drop threads past 100.)
52
+
53
+ Determine the **cutoff**: the timestamp of your most recent disposition comment on the PR (or the last commit you pushed addressing a review). Then collect:
54
+
55
+ - Every formal review or review-formatted issue comment **newer than the cutoff** (no cutoff → everything since the PR opened) — it opens with a `LGTM` / `Needs Updates` verdict, contains review sections like `### Needs Fixing`, or is otherwise clearly review feedback. **If multiple reviews landed — e.g. two reviewers — address all of them**, not just the latest. Skip `DISMISSED` reviews.
56
+ - Every **unresolved** inline thread (`isResolved: false`), **regardless of age** — resolution state, not timestamp, decides whether a thread is open work. A thread from before the cutoff that the reviewer never resolved is still open. Exception: if the thread's last comment is your own disposition reply and no one has responded since, it's awaiting the reviewer — skip it. `isOutdated` alone doesn't mean resolved. Treat each thread as one finding.
57
+ - Ignore your own prior disposition comments and `@claude review` trigger comments.
58
+
59
+ State what you picked (authors + timestamps) so the user can confirm it's the right set.
60
+
61
+ **Note whether the collected set contains any blocking finding** — a `Needs Fixing` or `Requires Human Review` item from any review, or an inline thread asserting a real defect (classified in step 2). This drives the re-review routing in step 7.
62
+
63
+ **If the only new feedback is `LGTM` with no blocking sections:** there's nothing blocking, but still address any non-blocking items the review raised — implement each `Recommended Optional` item with the absolute-best-solution standard (step 4), and file each `Create Follow-up Issue` item as a GitHub issue. Don't invent work the review never raised; if the feedback is a bare `LGTM` with no items at all and no open inline threads, report that the PR is approved and stop.
64
+
65
+ ### 2. Extract findings
66
+
67
+ Parse all collected feedback — structured reviews and inline diff threads alike — into discrete findings, tagged by section:
68
+ - **Needs Fixing** — blocking; reviewer asserts a real defect.
69
+ - **Requires Human Review** — blocking; reviewer couldn't decide (a genuine tradeoff or missing context).
70
+ - **Recommended Optional** — non-blocking improvement.
71
+ - **Create Follow-up Issue** — out-of-scope, track separately.
72
+
73
+ For free-form feedback with no sections — including inline diff comments — classify each point yourself into the same four buckets by its substance. Keep each finding atomic — split compound feedback ("fix X and also Y") into separate findings so each gets its own verdict. When the same defect is raised by more than one reviewer or thread, merge into one finding and note all sources.
74
+
75
+ ### 3. Re-validate each finding against the code (the core step)
76
+
77
+ For **every** finding — including ones that read as obviously correct — trace the claim to current code and assign a verdict. Endorsement is a verification act, not a relay: re-derive the finding from the code with your own `file:line`, don't transcribe the reviewer's reasoning.
78
+
79
+ | Verdict | Meaning | Action |
80
+ |---------|---------|--------|
81
+ | ✅ **Confirmed** | Code at `file:line` matches the finding; the defect/improvement is real | Fix it (step 4) |
82
+ | ❌ **Refuted** | Code does not do what the finding claims, or the suggested change would itself be wrong/regressive | Do **not** change; record a one-line, code-grounded rebuttal for the reply |
83
+ | ⚠️ **Partial** | Real but narrower/broader than stated, or true only on one path | Fix the true part; note the correction |
84
+ | ❓ **Judgment** | A real tradeoff or a decision the reviewer couldn't make (most `Requires Human Review` items) | Derive the absolute-best solution and **implement it** (see below) — don't pause, don't guess blindly, don't punt empty-handed |
85
+
86
+ Validation discipline (this is where fixing a review goes wrong):
87
+ - **Read the body, not just the cited line.** A name states intent; open the function and trace the conditional fully before agreeing.
88
+ - **Prove negatives by reading the path.** "X is never validated / never freed / not awaited" — confirm the absence across *all* relevant paths, not the one the reviewer looked at; the behavior may be produced elsewhere.
89
+ - **A suggested fix is its own claim.** "Just add a lock here" can deadlock; "default it to N" can break a caller. Verify the *remedy* is correct for this codebase, not only that the *problem* exists. Derive the right fix from first principles if the suggested one is suboptimal — correctness and safety outrank matching the reviewer's wording.
90
+ - **Safety carve-out:** any finding touching money, data integrity, security, or an auto-protective mechanism gets fixed or escalated to the user even at low confidence — never silently dropped as Refuted unless you can prove from code it's a non-issue.
91
+
92
+ **For every ❓ Judgment finding, do the analysis the reviewer couldn't and implement the result — don't hand the tradeoff back.** Trace the code, enumerate the viable approaches, and derive the **absolute-best solution**, evaluated as if cost, effort, time, resources, token spend, and code volume were unlimited — they are *not* factors and must never narrow the option space. The only things that can override "best" are correctness and safety. Choose the most correct, most robust design even when it's far more work, then implement it (step 4) in this same run. Do **not** pause to ask the user. Record the decision in the disposition comment — the chosen solution, the code-grounded reasoning (`file:line`), and the rejected alternatives in one line each — so the human can override after the fact if they disagree.
93
+
94
+ This same absolute-best-solution standard governs `Recommended Optional` improvements: implement them too, choosing the best design with cost/effort/time/resources treated as non-factors.
95
+
96
+ ### 3.5 Select the working model from the validated findings
97
+
98
+ Steps 2–3 always run inline in this session — validation is the hard thinking and doubles as the model-selection signal, so it never gets delegated. Now choose who implements, keyed to the **implementation complexity of the surviving work** — not its blocking/optional category (a blocking fix can be a trivial one-liner; an optional refactor can be genuinely hard).
99
+
100
+ First, two absolute inline gates that override any complexity read:
101
+ - Any ❓ Judgment call whose remedy is still open-ended, or any finding under the safety carve-out (money, data integrity, security, auto-protective mechanisms) — open decisions and high blast radius never get delegated.
102
+
103
+ Otherwise, rate each surviving fix's complexity from your validation (you just traced the code, so you know): **scope** (files/layers touched, cross-cutting vs. local), **subtlety** (concurrency, ordering, invariants, edge-case reasoning vs. mechanical edits), and **verification difficulty** (needs careful test design vs. existing suite covers it). The **most complex fix** sets the tier for the whole set (never the average, never split across subagents):
104
+
105
+ - **Opus subagent (`model: "opus"`)** — any fix is non-trivial: multi-file or cross-layer, touches subtle logic, or its correctness needs real reasoning to preserve.
106
+ - **Sonnet subagent (`model: "sonnet"`)** — every fix is simple and mechanical: localized edits with a pinned-down remedy, plus any `Create Follow-up Issue` filings and Refuted rebuttals to write up.
107
+
108
+ When in doubt between tiers, take the higher one — misrouting hard work down costs correctness; misrouting easy work up costs nothing that matters.
109
+
110
+ When dispatching, use the Agent tool (`subagent_type: general-purpose`, synchronous — `run_in_background: false`) with a prompt that tells the subagent to: read this SKILL.md file and execute steps 4 through 8 exactly (skipping steps 0–3.5 — no re-validation, no recursive dispatch), for PR `<N>`, using the validated findings and per-finding verdicts you produced in steps 2–3 (paste them into the prompt, including the pinned-down remedies for Confirmed/Partial findings and the derived best-solution designs for any Optional items, so it implements your analysis rather than re-deciding). The subagent's **LLM Attribution Footers** (commit + disposition comment) must name the model actually doing the work (e.g. `Opus 4.8` / `Sonnet 5`), not the session model. When the subagent returns, relay its step-8 report to the user verbatim plus which model ran; don't redo its work.
111
+
112
+ If the Agent tool's model override is unavailable in the current harness, fall back to running inline and note the intended model in the report.
113
+
114
+ ### 4. Implement the fixes
115
+
116
+ Implement every finding that calls for a change: ✅ Confirmed, ⚠️ Partial (the true part), ❓ Judgment (the absolute-best solution you derived), and `Recommended Optional` (best-solution standard). Skip only ❌ Refuted and `Create Follow-up Issue` items.
117
+
118
+ - Read the surrounding code and follow existing conventions before editing.
119
+ - Keep each fix scoped to its finding; don't smuggle in unrelated refactors. (Scope ≠ minimalism: for Judgment and Optional items, pick the *best* design, not the smallest diff — correctness and robustness outrank brevity.)
120
+ - After all fixes, **verify**: run the project's tests/build/lint (check the repo's `CLAUDE.md` / `package.json` / Makefile for the commands — e.g. `bun test`, `go test -race ./...`, `bun run build`). Evidence before assertions: do not claim a fix works without running verification, and report any failures honestly rather than papering over them.
121
+ - If a fix turns out infeasible or reveals the finding was actually Refuted, move it to the Refuted bucket with the reason.
122
+
123
+ ### 5. Commit and push
124
+
125
+ Only after verification passes:
126
+
127
+ ```bash
128
+ git status # confirm only the files you edited are dirty
129
+ git add <specific files> # stage each file you changed for the fixes — never `git add -A` or `git add .`
130
+ git commit -F <msg-file> # see footer below
131
+ git push # to the branch's tracked upstream — for a fork PR the head lives in the fork, so `git push origin <headRefName>` would be wrong
132
+ ```
133
+
134
+ If the branch has no upstream set (manual checkout instead of `gh pr checkout`), push explicitly to the PR's **head repository** remote — never assume `origin`.
135
+
136
+ Staging explicitly prevents sweeping in unrelated dirty files, scratch files, or untracked artifacts. If `git status` shows changes you didn't make, leave them unstaged and mention them in the report.
137
+
138
+ Commit message: a concise summary of what review findings were addressed (reference the PR, e.g. "Address review on #<N>: <one-line summary>"). This is a revision to an existing PR, so the footer uses the **Updated** verb:
139
+
140
+ ```
141
+ ---
142
+ Updated with LLM: <current model> | <effort> | Harness: Claude Code
143
+ ```
144
+
145
+ Fill `<current model>` (e.g. `Opus 4.8`) and `<effort>` (`high` by default). Per the user's workflow, never include time/effort estimates in the message body.
146
+
147
+ ### 6. Post the disposition comment back to the PR
148
+
149
+ Post one comment that tells the reviewer exactly what happened to each finding — this is how a refuted finding gets its pushback on the record. Write it as direct, scannable status:
150
+
151
+ ```
152
+ Addressed review feedback (<reviewer(s)> · <timestamp(s)>) in <commit-sha>.
153
+
154
+ ### Fixed
155
+ 1. **<finding title>** — <what changed> (`file:line`).
156
+
157
+ ### Corrected scope (partial)
158
+ 1. **<finding title>** — <what was real and fixed vs. what wasn't> (`file:line`).
159
+
160
+ ### Not changed (refuted)
161
+ 1. **<finding title>** — <code-grounded reason the suggestion doesn't apply> (`file:line`).
162
+
163
+ ### Resolved judgment calls (was Requires Human Review)
164
+ 1. **<finding title>** — implemented <the absolute-best solution and why, `file:line`>. Alternatives rejected: <one line each>. Override if you'd prefer one of these.
165
+
166
+ ### Deferred to follow-up
167
+ 1. **<finding title>** — <why it's out of scope; issue link filed>.
168
+ ```
169
+
170
+ Omit any empty section. Keep each item one line with a `file:line` anchor. For findings that came from inline diff threads, also post a one-line reply in the thread itself — use the root comment's `databaseId` from step 1's thread query: `gh api repos/{owner}/{repo}/pulls/<N>/comments/<databaseId>/replies -f body=...` — that's where the reviewer is watching. Post the main comment via:
171
+
172
+ ```bash
173
+ gh pr comment <N> --body-file <file>
174
+ ```
175
+
176
+ Footer on the comment uses the **Created** verb (it's a new comment):
177
+
178
+ ```
179
+ ---
180
+ Created with LLM: <current model> | <effort> | Harness: Claude Code
181
+ ```
182
+
183
+ ### 7. Trigger the @claude re-review
184
+
185
+ Route the re-review by whether the set you addressed contained **any blocking finding** (noted in step 1) — never by the newest review's verdict alone: with multiple reviewers, a later `LGTM` from one does not erase another's `Needs Updates`.
186
+
187
+ - **Any blocking finding addressed** (`Needs Fixing` / `Requires Human Review` from any review, or an inline thread that validated as a real defect): trigger plain — this repo's default (Opus) reviews the fix.
188
+ - **Only non-blocking items** (optional improvements / follow-ups): the PR was already in good shape, so route the re-review to Sonnet via the `@claude sonnet` shorthand instead.
189
+
190
+ Post a **separate** comment so the bot triggers cleanly on its own line:
191
+
192
+ ```bash
193
+ # blocking findings were addressed
194
+ gh pr comment <N> --body "@claude review"
195
+
196
+ # only non-blocking items were addressed
197
+ gh pr comment <N> --body "@claude sonnet review"
198
+ ```
199
+
200
+ (If this repo uses a different review trigger phrase or model-shorthand syntax, match it — check the repo's `.github/workflows/claude.yml` for how it resolves `@claude <shorthand>`, and recent PR comments for the convention.) A trigger comment is a one-line mention, not authored content — no footer.
201
+
202
+ ### 8. Report to the user
203
+
204
+ Terse summary: which reviews/threads you acted on, counts per disposition (fixed / partial / refuted / judgment-resolved / optional / deferred), the commit SHA, verification result, and that a re-review was requested (note which model it was routed to). Flag the resolved judgment calls so the user can override if they disagree — but the work is already done, not waiting on them.
205
+
206
+ ## Red Flags — STOP
207
+
208
+ | Situation | Action |
209
+ |-----------|--------|
210
+ | Finding cites a line that no longer matches current code | Re-validate against current `file:line`; it may already be fixed — mark Refuted with the reason |
211
+ | Suggested fix would touch money/data/security/auto-protective logic | Never blind-apply; verify the remedy from first principles and implement the safest correct design |
212
+ | Reviewer's remedy is plausible but you can't confirm it's correct here | Don't implement on faith — trace it, then implement the absolute-best solution you can stand behind from the code |
213
+ | A collected "review" is actually your own prior disposition comment or an `@claude review` trigger | Skip it; act only on *actual* review feedback |
214
+ | Only some feedback channels checked (e.g. formal reviews but not inline diff threads) | Fetch all three sources before extracting findings — inline threads are where human reviewers usually comment |
215
+ | `git status` shows dirty files you didn't edit | Stage only your fix files; leave the rest and mention them in the report |
216
+ | You're on `main` or a divergent branch, not the PR head | Check out the PR head first; never commit review fixes to the base branch |
217
+ | Branch can't fast-forward to its upstream head | Stop — the branch diverged; surface to the user, don't force anything |
218
+ | PR is from a fork | Check out with `gh pr checkout` and push to the tracked upstream — `origin` is the wrong remote for the head branch |
219
+ | All findings refuted | Still post the disposition comment with the rebuttals and request re-review — don't silently no-op |
220
+ | `Requires Human Review` item | Derive and **implement** the absolute-best solution (ignore cost/effort/time/resources; only correctness and safety override "best"); document the decision + rejected alternatives in the comment so the user can override. Never pause for confirmation, punt the bare tradeoff, or guess blindly |
221
+ | Tests/build fail after fixes | Report the failure; don't push or claim success |
222
+
223
+ ## Common Mistakes
224
+
225
+ - **Blind-implementing the review.** Performative agreement ships regressions. Validate first, every time.
226
+ - **Delegating validation.** Steps 2–3 always run inline — the model-selection gate keys off *validated* verdicts, and a lighter model triaging its own workload defeats the gate. Dispatch only steps 4–8, tiered by the most complex surviving fix (open judgment/safety → inline, any non-trivial fix → Opus, all-mechanical → Sonnet), and never split one review across subagents. The subagent's footers must name the model that actually ran, not the session model.
227
+ - **Missing inline diff comments.** Fetching only formal reviews and issue comments skips the line-level threads where human reviewers usually comment. Fetch all three channels.
228
+ - **Addressing only the latest review when several landed.** Every review newer than your last disposition and every unresolved inline thread (any age) gets addressed.
229
+ - **Routing the re-review by the newest verdict.** A later `LGTM` from one reviewer doesn't erase another's blocking findings — route by whether any blocking finding was addressed.
230
+ - **`git add -A`.** Stage the fix files explicitly; a blanket add can commit unrelated dirty or untracked files.
231
+ - **Dropping a refuted finding silently.** Push back on the record in the comment with a code-grounded reason — that's how the reviewer learns it was wrong.
232
+ - **Committing to the base branch.** Fixes land on the PR head branch only.
233
+ - **Skipping verification before push.** Run the tests/build; report real results.
234
+ - **Pausing or punting on a judgment call.** Do the analysis the reviewer couldn't and *implement* the absolute-best solution (cost/effort/time/resources are not factors; only correctness and safety override it); document it for override. Don't stop to ask, don't relay the bare tradeoff, don't guess blindly.
235
+ - **Skipping the optional improvements.** `Recommended Optional` items get implemented to the same best-solution standard, not deferred.
236
+ - **Bundling the re-review trigger into the disposition comment.** Keep `@claude review` as its own comment so the bot fires reliably.
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: fix-pr-review-loop
3
+ description: Use when the user asks to fix a PR review and drive it to approval autonomously — "fix the PR review and loop until approved", "fix-pr-review-loop", "keep addressing review comments until this PR is approved", or as the standalone counterpart to work-on-issue-loop's polling/resolving steps for a PR that already exists. Takes an optional PR number/URL (defaults to the current branch's PR). Repeatedly calls fix-pr-review to resolve the latest review, waits for the resulting @claude re-review, and repeats. Stops on a bare LGTM with nothing left to fix; once past 5 review cycles it stops at the first LGTM it sees even if non-blocking findings remain, rather than continuing to chase them.
4
+ ---
5
+
6
+ # fix-pr-review-loop
7
+
8
+ Drive an already-open PR from "has review feedback" to "reviewed to convergence" without stopping in between: resolve the latest review (fix-pr-review), wait for the bot's re-review, and repeat. Past 5 cycles the bar for "done" relaxes — any LGTM ends the loop — so a PR with recurring minor findings doesn't get fix-pr-review'd forever. This is the same convergence loop work-on-issue-loop runs after it opens a PR, factored out so it can be pointed at any PR directly.
9
+
10
+ ## Input
11
+
12
+ - Nothing — default to the PR for the current branch (`gh pr view`).
13
+ - `#<N>` / `<N>` / full URL / `owner/repo#N`.
14
+
15
+ ## Steps
16
+
17
+ ### 1. Resolve the PR and establish the starting state
18
+
19
+ ```bash
20
+ gh pr view <N|--> --json number,headRefName,headRepositoryOwner,baseRefName,url,state,isDraft
21
+ ```
22
+
23
+ - If the PR is already `merged` or `closed`, stop and report — there's nothing to drive.
24
+ - Fetch the current review feedback using fix-pr-review step 1's three-channel query (formal reviews, issue comments, inline diff threads) to see what has already landed.
25
+ - **Unaddressed feedback is already present** (a review/comment newer than any prior disposition comment, or an unresolved inline thread): treat it as the first landed review. Set `review_count = 1`, note its timestamp, and skip straight to step 3 — don't wait for a review that already arrived.
26
+ - **No review feedback at all yet** (fresh PR, or every existing comment is your own prior disposition/trigger): trigger one yourself:
27
+ ```bash
28
+ gh pr comment <N> --body "@claude review"
29
+ ```
30
+ Record the trigger timestamp, set `review_count = 1`, and go to step 2 to wait for it.
31
+
32
+ ### 2. Wait for the review to land
33
+
34
+ Poll the PR for a new review or issue comment posted **after** the last trigger timestamp — reviews can land as a formal PR review or as an issue comment (the `@claude` bot usually posts as an issue comment; see fix-pr-review step 1 for the `gh` calls to check — it also fetches inline diff threads, which matter when a human reviewer weighs in). An until-loop is the right shape here — you want to be notified once the condition is true, not to busy-poll inline:
35
+
36
+ ```bash
37
+ until gh pr view <N> --json comments,reviews --jq '
38
+ ([.comments[] | select(.createdAt > "<trigger_ts>")] |
39
+ any(.body | test("(^|\\n)(LGTM|Needs Updates)"))) or
40
+ ([.reviews[] | select(.submittedAt > "<trigger_ts>")] | length > 0)
41
+ ' | grep -q true; do sleep 60; done
42
+ ```
43
+
44
+ Two load-bearing details in that condition (both have silently broken monitors before — a wrong filter here reads as "no review yet" forever):
45
+
46
+ - **Match the verdict with `(^|\\n)`, not `^` + the `m` flag.** In jq's regex (Oniguruma), `m` means dot-matches-newline, NOT multiline anchoring — `^` only matches the very start of the body. The `@claude` GitHub Action buries its verdict below a `**Claude finished …**` header and a `---`, so an anchored-at-start pattern never matches. (The bot also *edits* its placeholder comment in place rather than posting a new one; `createdAt` stays at placeholder time, which is still after your trigger, so the timestamp filter is fine.)
47
+ - **Pipe through `grep -q true`.** `gh --jq` prints `true`/`false` but exits 0 either way, so a bare `until gh …; do` would exit the loop on the first poll regardless of the value.
48
+
49
+ Run this as a background until-loop (e.g. via the Monitor tool) so you're notified on completion instead of blocking synchronously. Cap the wait at roughly 30 minutes; if no review appears in that window, stop and report to the user that the `@claude` bot didn't respond — don't loop indefinitely on a bot that may be down or misconfigured. Before trusting a freshly armed monitor, sanity-check its condition once inline against the live PR — if a review is already present it must print `true`.
50
+
51
+ ### 3. Check the review against the stop conditions
52
+
53
+ Fetch the latest review and classify it exactly like fix-pr-review steps 1–2: verdict (`LGTM` / `Needs Updates`) and which sections are present (`Needs Fixing`, `Requires Human Review`, `Recommended Optional`, `Create Follow-up Issue`).
54
+
55
+ Evaluate in this order:
56
+
57
+ 1. **Clean pass — stop, success.** Verdict is `LGTM` and **no sections at all** — nothing under Recommended Optional or Create Follow-up Issue either. Nothing left to fix, at any `review_count`. Go to step 5.
58
+ 2. **Past the cap and it's an LGTM — stop, first one wins.** `review_count > 5` **and** verdict is `LGTM` (even with Recommended Optional / Create Follow-up Issue items still listed). Once the loop has run more than 5 cycles, the first LGTM it sees ends it — don't spend a 6th+ fix-pr-review cycle chasing non-blocking findings. Go to step 5.
59
+ 3. **Otherwise — keep going.** Verdict is `Needs Updates` (at any `review_count` — there is no cycle count that alone stops a `Needs Updates` PR; only an LGTM does, per rules 1–2), or verdict is `LGTM` with findings still listed and `review_count <= 5`. Continue to step 4.
60
+
61
+ ### 4. Resolve the review and loop
62
+
63
+ Invoke the `fix-pr-review` skill for the PR (Skill tool, `skill: fix-pr-review`). It re-validates every finding against the code, fixes what's real, implements the judgment calls and optional improvements to the best-solution standard, commits, pushes, posts the disposition comment, and triggers a fresh `@claude` review itself (routed to Sonnet when it addressed only non-blocking items, otherwise to the repo default, per fix-pr-review step 7).
64
+
65
+ fix-pr-review also picks its own working model dynamically (its step 3.5): it always validates the findings inline on the session model, then tiers implementation by the complexity of the most complex surviving fix — open judgment calls and safety-class findings stay inline, any non-trivial fix routes the set to an Opus subagent, and all-mechanical work goes to a Sonnet subagent. It decides from the validated findings itself, so don't override its choice — just record which model each cycle reported running on, for the step 5 report.
66
+
67
+ Increment `review_count`, record the new trigger timestamp from that comment, and go back to step 2.
68
+
69
+ ### 5. Report
70
+
71
+ Stop the loop and report the terminal state — don't claim blanket success:
72
+
73
+ | Terminal state | Report as |
74
+ |---|---|
75
+ | Clean `LGTM`, no findings, at or before `review_count` 5 | **Done.** PR is approved with nothing outstanding. |
76
+ | `review_count > 5` and an `LGTM` (with non-blocking items remaining) ended the loop | **Done, with leftovers.** PR is approved; note the remaining optional/follow-up items that were left unaddressed once the loop passed 5 cycles. |
77
+ | Bot never responded within the wait window | **Escalate.** Report that the PR is pushed but review never landed; the user should check the `@claude` GitHub Action / bot status. |
78
+ | PR was already `merged`/`closed` when the skill started | **Nothing to drive.** Report the state; zero review cycles ran. |
79
+
80
+ There is no "stuck on `Needs Updates` past the cap" case to report — per step 3, `Needs Updates` never stops the loop by cycle count alone; it keeps calling fix-pr-review until an LGTM appears (or the bot stops responding, the row above).
81
+
82
+ In every case, give: PR URL, number of review cycles run, final verdict, which model each fix cycle ran on (per fix-pr-review's findings-based selection), and (if escalating) exactly what's left.
83
+
84
+ **Cap the report at 55 words, ELI18** — plain language, no jargon, as if explaining the outcome to a smart 18-year-old with no context on this codebase or its internals.
85
+
86
+ ## Red Flags — STOP
87
+
88
+ | Situation | Action |
89
+ |---|---|
90
+ | `review_count > 5` and the latest verdict is `LGTM` | Stop right there — don't invoke fix-pr-review again just because non-blocking findings remain; report per step 5 |
91
+ | `review_count > 5` and the latest verdict is still `Needs Updates` | Keep going — invoke fix-pr-review and loop again; the cap only changes what counts as "done" on an LGTM, it never force-stops a `Needs Updates` PR |
92
+ | Latest "review" is your own prior fix-pr-review disposition comment or an `@claude review` trigger comment, not an actual review | Skip it — keep waiting/polling for the real next review, same rule as fix-pr-review step 1 |
93
+ | Review bot hasn't responded after ~30 minutes | Stop waiting; report that review didn't land rather than polling forever |
94
+ | Tempted to treat "LGTM with Recommended Optional items" as terminal at `review_count <= 5` | It isn't — below the cap, LGTM-with-findings still goes through fix-pr-review; only past the cap does the first LGTM end it regardless of findings |
95
+ | PR gets closed or merged mid-loop (e.g. by the user) | Stop immediately; don't keep pushing fixes to a closed/merged PR |
96
+ | PR already has unaddressed feedback when the skill starts | Don't trigger a redundant `@claude review` — step 1 evaluates existing feedback first and only triggers when none exists |
97
+
98
+ ## Common Mistakes
99
+
100
+ - **Treating any LGTM at or below `review_count` 5 as terminal.** Below the cap, only a *bare* LGTM (no sections) stops the loop; an LGTM with leftover optional/follow-up findings still goes through another fix-pr-review cycle.
101
+ - **Hard-stopping a `Needs Updates` PR once `review_count` passes 5.** There's no such rule — the cap only lowers the bar for what counts as "done" once an LGTM shows up; it never stops the loop on its own.
102
+ - **Losing count across cycles.** Track `review_count` explicitly — it's what distinguishes "full fix cycle" from "first-LGTM-wins" behavior.
103
+ - **Polling synchronously forever.** Use an until-loop with a timeout so a non-responding bot doesn't hang the whole run.
104
+ - **Re-triggering review on top of fix-pr-review's own trigger.** fix-pr-review already posts its own re-review trigger as a separate comment (its step 7) — don't add a second one here.
105
+ - **Triggering `@claude review` when feedback is already sitting on the PR.** Check for existing unaddressed feedback in step 1 first; a redundant trigger just delays convergence.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: new-issue
3
+ description: Use when the user says "new issue", "create an issue", "file an issue", "/new-issue", or asks to turn a bug, idea, or discussion into a GitHub issue. Takes an optional description of what the issue should cover; with no input, derives the issue from what was discussed in the current conversation. Verifies claims against the code before filing and produces a complete, complexity-scored issue — never a stub.
4
+ ---
5
+
6
+ # new-issue
7
+
8
+ Create a fully-specified GitHub issue from the user's prompt — or, when nothing is prompted, from what was just discussed in the conversation. The deliverable is a filed issue that someone (human or agent) could pick up cold and implement correctly: concrete problem statement, goal, approach, acceptance criteria, complexity score, attribution footer. **Never file a placeholder, stub, or empty-bodied issue — no exceptions.**
9
+
10
+ **Spec the absolute-best solution — full stop.** When the issue proposes an approach, derive it from first principles as if cost, compute, time, effort, manpower, token spend, code volume, and blast radius were unlimited — none of these are factors and none may narrow the option space. The only constraints that override "best" are correctness and safety (money, data integrity, security, auto-protective mechanisms — safety-class gaps are never acceptable, however "low-risk"). Don't spec the tidier/less-code design when it leaves a correctness or safety gap, and don't scope the issue down to what seems cheap to build.
11
+
12
+ ## Input
13
+
14
+ The user provides one of:
15
+ - A description of the bug/feature/task to file — use it as the source, but still ground it in code (below).
16
+ - **Nothing** — derive the issue from the current conversation: the bug just diagnosed, the design just discussed, the follow-up just named. If the conversation contains several distinct candidates, file the one the discussion converged on; name the others and offer to file them (each fully specified) rather than bundling.
17
+ - Optionally `owner/repo` or a repo path when the issue belongs somewhere other than the current checkout (`gh issue create -R owner/repo`).
18
+
19
+ ## Steps
20
+
21
+ ### 1. Establish the repo and check for duplicates
22
+
23
+ Confirm which repo the issue belongs to (`gh repo view --json nameWithOwner`). Then search for an existing issue or PR already covering it — filing a duplicate wastes a cycle:
24
+
25
+ ```bash
26
+ gh issue list --state open --search "<keywords>"
27
+ gh pr list --state open --search "<keywords>"
28
+ ```
29
+
30
+ A genuine hit → stop and surface it (offer to update/comment on the existing issue instead). A passing mention doesn't count.
31
+
32
+ ### 2. Ground every claim in the code — before writing a word
33
+
34
+ The issue's factual claims about *current* behavior are claims, not notes — the same standard validate-issue holds authors to applies to you as the author. For each behavior the issue will assert, trace the code path and keep the `file:line`; a claim you can't trace is phrased as unverified ("appears to…", "needs confirmation"), never stated as fact. If the issue came from this conversation, don't transcribe from memory — re-check the load-bearing citations against the actual files; conversation recollection goes stale exactly like an author's prose does.
35
+
36
+ If the working tree is on a divergent or stale branch, trace against `origin/<default>` (`git show "origin/$DEFAULT":<path>`) so citations match what an implementer will check out.
37
+
38
+ ### 3. Design the approach (non-trivial issues)
39
+
40
+ For anything beyond a localized bugfix, spec the approach the way validate-issue's architecture pass would judge it — so the issue passes its own future validation:
41
+
42
+ - **Placement and ownership** — which layer/component owns the change; for shared state name the owner, lifetime, medium, population timing, consumer contract, and failure policy.
43
+ - **Touch-set** — grep the affected symbols and name *every* site that must change (read/write/default/validate/serialize), not just the obvious one.
44
+ - **Conventions** — match the repo's existing patterns (`CLAUDE.md`, guardrails, existing helpers) over new infrastructure; respect documented invariants (single-writer, fail-closed, "X never into Y").
45
+ - **Best over cheap** — per the principle above: if the correct design is bigger than the convenient one, spec the correct design and let the complexity score say so.
46
+
47
+ Include **acceptance criteria** an implementer can verify: observable behavior, tests that must exist (regression test for a bug, red → green), parity surfaces that must match.
48
+
49
+ ### 4. Score complexity
50
+
51
+ Score the work to implement the fix **correctly, including tests** — five axes 0–4 (Scope, Coupling, Risk, Uncertainty, Verification), sum ×5 for a 0–100 base, risk floor: Risk 4 → ≥60, Risk 3 → ≥45. Derive the axes from the concrete touch-set in step 3, not vibes; count the surface that hides from the diff (tests, parity/offline paths, migrations, docs). This is complexity, **not** a time or effort estimate — never put durations in the issue.
52
+
53
+ ### 5. Scope check — one issue or several?
54
+
55
+ If the deliverables are separable — parts that each land in their own PR, pass their own tests, and deliver value alone — don't bundle: file the core issue and tell the user which parts warrant their own issues (each fully specified before filing, or tracked as a checklist in the parent until ready — never stubs).
56
+
57
+ ### 6. Compose and file
58
+
59
+ Title: `[C<score>] <title>` — the title is a clear, plain-language sentence understandable to an average 18-year-old (ELI18) — it states the bug or deliverable precisely (component + behavior) without unexplained jargon, no vague "improve X".
60
+
61
+ Body structure:
62
+
63
+ ```
64
+ **Complexity: <score>/100** — scope: <…>; risk: <…>; uncertainty: <…>
65
+
66
+ ## Problem
67
+ <Current behavior, grounded with file:line citations from step 2. What's wrong or missing and why it matters.>
68
+
69
+ ## Goal
70
+ <The outcome in plain language — what's true after this lands.>
71
+
72
+ ## Approach
73
+ <The optimal design from step 3: placement, touch-set, key decisions. Explicit that correctness/safety outrank diff size.>
74
+
75
+ ## Acceptance criteria
76
+ - <observable behavior / test that must pass>
77
+ - <…>
78
+
79
+ ---
80
+ Created with LLM: <current model> | <effort> | Harness: <harness>
81
+ ```
82
+
83
+ The complexity rationale is the **first line** of the body and matches the title prefix. The footer is the final lines, preceded by `---` on its own line — **Created** verb, `<effort>` one of `medium`/`high`/`xhigh` (default `high`, never low), `<harness>` = `Claude Code` for an interactive session. No `Co-authored-by`. **Project precedence:** a repo `CLAUDE.md` that defines its own issue/footer format overrides this default.
84
+
85
+ File it:
86
+
87
+ ```bash
88
+ gh issue create --title "[C<score>] <title>" --body-file <body-file>
89
+ ```
90
+
91
+ Add `--label`/`--assignee` only when the repo visibly uses them (`gh label list`) and the fit is unambiguous.
92
+
93
+ ### 7. Report
94
+
95
+ Terse: issue URL, number, one-line summary of what it covers, complexity score, and any candidate follow-ups you did **not** file (with why). Offer "validate issue" / "work on issue" as next steps in one line.
96
+
97
+ ## Guardrails
98
+
99
+ | Situation | Action |
100
+ |-----------|--------|
101
+ | Tempted to file with a thin body "to capture it quickly" | Don't — every issue is complete at creation; if it isn't ready to spec, tell the user and track it in notes/parent instead |
102
+ | No prompt and the conversation discussed several things | File the converged one; name the rest, don't bundle |
103
+ | A claim about current behavior you haven't traced | Trace it or phrase it as unverified — never state a guess as fact |
104
+ | Issue derived from conversation memory | Re-verify load-bearing file:line citations against the actual code before filing |
105
+ | An existing open issue/PR already covers it | Stop; surface it and offer to update/comment instead |
106
+ | The cheap design and the correct design diverge | Spec the correct one; cost, effort, and blast radius are not factors — only correctness and safety constrain |
107
+ | Touches money / data integrity / security / auto-protective logic | Spec the safest correct design from first principles; surface the risk in the body and Risk axis |
108
+ | Tempted to include a time/effort estimate | Don't — complexity score only, described via scope/risk/uncertainty |
109
+ | Repo has its own issue template or `CLAUDE.md` issue format | Follow the repo's format; it overrides this default |
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: new-issue-loop
3
+ description: Use when the user asks to file a GitHub issue and then autonomously drive it all the way to a reviewed PR in one shot — "new-issue-loop", "create the issue and run it to completion", "file this and fully automate it". Runs new-issue to create a fully-specified issue, then hands the new issue number to validate-issue-loop (validate → update → work-on-issue-loop) — stopping instead when new-issue finds a duplicate or the discussion hasn't converged on one issue.
4
+ ---
5
+
6
+ # new-issue-loop
7
+
8
+ Chain new-issue → validate-issue-loop into one autonomous run, so a bug/idea/discussion goes from "described" to "filed issue with a PR through N rounds of review" without a human in the loop between steps. This is new-issue's normal interactive handoff (`Offer "validate issue" / "work on issue"`) made unattended: the loop takes the issue it just filed and feeds it straight into the validate-and-implement pipeline.
9
+
10
+ **Do not skip filing a complete issue.** The downstream loop validates and implements *the issue text* — a thin or unverified body propagates straight into the PR. Every step of new-issue still runs (grounding, approach design, complexity score); only the "offer next steps and wait" step is replaced by the handoff.
11
+
12
+ ## Input
13
+
14
+ Same as new-issue: an optional description of what the issue should cover; with no input, derive it from the current conversation. Optionally `owner/repo` when the issue belongs elsewhere.
15
+
16
+ ## Steps
17
+
18
+ ### 1. Run new-issue
19
+
20
+ Invoke the `new-issue` skill (Skill tool, `skill: new-issue`) with the user's description (or conversation-derived scope). Let it run its full process — duplicate check, code grounding, approach, complexity score, filing. Capture the created issue number from its report.
21
+
22
+ ### 2. Stop gate — cases the loop can't safely continue
23
+
24
+ | Condition | Action |
25
+ |---|---|
26
+ | new-issue found an existing open issue/PR already covering it (no issue filed) | **STOP.** Report the duplicate and new-issue's offer to update/comment instead — whether to merge scopes is a human call. |
27
+ | The conversation held several distinct candidates | If one clearly converged, file it and **continue the chain with it**; the unfiled candidates go in the final report. If none clearly converged, **STOP** — report the candidates and ask which to file. Never bundle, never auto-file the extras. |
28
+ | new-issue split the work and named unfiled follow-ups | Continue with the **core issue only**; relay the unfiled follow-ups in the final report. |
29
+
30
+ Otherwise (one issue filed cleanly), continue.
31
+
32
+ ### 3. Hand off to validate-issue-loop
33
+
34
+ Invoke the `validate-issue-loop` skill (Skill tool, `skill: validate-issue-loop`) with the issue from step 1 passed explicitly — don't let it default to "latest open issue" and risk racing another just-filed issue. If new-issue filed to a repo other than the current checkout (`-R owner/repo`), pass the full `owner/repo#N` reference, not the bare number — a bare number resolves against the current repo and would target the wrong issue. Its own scope gate (too large / infeasible / already-addressed) still applies and may stop the run; that's the designed behavior, not a failure.
35
+
36
+ Validating an issue this same session just wrote is not redundant: validate-issue re-traces the claims against the code independently, catching anything the filing pass got wrong.
37
+
38
+ ### 4. Report
39
+
40
+ Relay validate-issue-loop's final summary (PR URL, review cycles, verdict), prefixed with one line covering the front of the chain: issue number/URL filed, complexity score, and any unfiled follow-ups from step 2.
41
+
42
+ **Cap the whole report at 55 words, ELI18** — plain language, no jargon, as if explaining the outcome to a smart 18-year-old with no context on this codebase.
43
+
44
+ ## Red Flags — STOP
45
+
46
+ | Situation | Action |
47
+ |---|---|
48
+ | Tempted to skip new-issue's grounding/duplicate check to get to implementation faster | Never — a fabricated or duplicate issue poisons the whole chain |
49
+ | new-issue stopped on a duplicate | Stop and report per step 2 — don't file anyway |
50
+ | Tempted to hand off without an explicit issue reference | Always pass the issue from step 1 — `owner/repo#N` if filed cross-repo — "latest issue" can race |
51
+ | validate-issue-loop's scope gate stops the run | Report its disposition faithfully — don't override and implement anyway |
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: sync-docs
3
+ description: Use when the user asks to sync, update, or refresh CLAUDE.md, AGENTS.md, SKILL.md, and README.md to reflect recent commits or PRs. Triggers on phrases like "sync docs", "update CLAUDE.md", "update AGENTS.md", "update SKILL.md", "update README", "reflect recent changes", or "document the recent PRs".
4
+ ---
5
+
6
+ # sync-docs
7
+
8
+ **This skill is a dispatch shim. Do not perform the work yourself.**
9
+
10
+ Immediately invoke the `sync-docs-runner` subagent via the Agent tool, which runs on Opus and contains the full sync-docs workflow.
11
+
12
+ ## Required invocation
13
+
14
+ Call the Agent tool with:
15
+
16
+ - `subagent_type`: `sync-docs-runner`
17
+ - `description`: `Sync docs to recent commits`
18
+ - `prompt`: Pass through the user's request verbatim, plus any context the user already provided in this session (target branch, last-sync SHA, specific files to focus on, etc.). The agent has its own copy of the workflow — do not paste workflow steps into the prompt. Include only the inputs it needs.
19
+ - `model`: Omit by default — the agent runs on Opus via its pinned frontmatter. **Override only if the user explicitly names a different LLM** when invoking the skill (e.g. "sync docs with sonnet", "/sync-docs use haiku"). Map the request to the matching `model` value (`opus`, `sonnet`, or `haiku`) and pass it; the Agent tool's `model` parameter takes precedence over the agent's frontmatter. Do not infer an override from anything other than an explicit model name.
20
+
21
+ After the agent returns, relay its summary to the user. Do not re-execute its work.
22
+
23
+ ## Why this exists
24
+
25
+ The full sync-docs workflow lives in `~/.claude/agents/sync-docs-runner.md` with `model: opus` pinned in frontmatter. Routing through the agent keeps doc-sync runs on Opus by default — but an explicit user LLM choice overrides it via the Agent tool's `model` parameter.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: sync-docs-release
3
+ description: Use when the user wants to sync docs and then cut a release in one shot. Combines sync-docs → commit → create-release in sequence. Triggers on phrases like "sync docs and release", "sync and cut a release", "update docs and publish a release".
4
+ ---
5
+
6
+ # sync-docs-release
7
+
8
+ Runs three operations in strict sequence. Do not skip steps or reorder them.
9
+
10
+ ## Step 1 — Sync docs
11
+
12
+ Invoke the `sync-docs-runner` subagent via the Agent tool:
13
+
14
+ - `subagent_type`: `sync-docs-runner`
15
+ - `description`: `Sync docs to recent commits`
16
+ - `prompt`: Pass through the user's request verbatim plus any session context (target branch, last-sync SHA, specific files, etc.). Do not paste workflow steps into the prompt.
17
+ - `model`: Omit by default. Override only if the user explicitly names a different LLM.
18
+
19
+ Wait for the agent to return. Relay its summary to the user before proceeding.
20
+
21
+ ## Step 2 — Commit the doc changes
22
+
23
+ After sync-docs completes, commit any doc changes it produced using the Haiku model. Spawn an Agent with `model: haiku` and the following prompt:
24
+
25
+ > Create a git commit for the doc changes just produced by sync-docs. Steps:
26
+ > 1. Run `git status` and `git diff` to see all changes.
27
+ > 2. Run `git log --oneline -10` to understand the commit message style used in this repo.
28
+ > 3. Stage only documentation files changed by sync-docs (CLAUDE.md, AGENTS.md, SKILL.md, README.md, and any other .md files that were modified — never stage .env, secrets, or unrelated files).
29
+ > 4. If there is nothing staged after step 3 (nothing changed), skip the commit and report "no doc changes to commit".
30
+ > 5. Otherwise, draft a concise commit message focused on the "why" and create the commit: `git commit -m "$(cat <<'EOF'\n<message>\nEOF\n)"`.
31
+ > 6. Run `git status` to verify.
32
+ > Do not push.
33
+
34
+ Wait for the agent to return. Relay its result (commit SHA or "no changes") to the user before proceeding.
35
+
36
+ ## Step 3 — Create a release
37
+
38
+ Invoke the `create-release-runner` subagent via the Agent tool:
39
+
40
+ - `subagent_type`: `create-release-runner`
41
+ - `description`: `Cut and publish a release`
42
+ - `prompt`: Pass through the user's original request verbatim plus any context they provided (target version or bump type, release-notes specifics, etc.). Do not paste workflow steps.
43
+ - `model`: Omit by default. Override only if the user explicitly names a different LLM.
44
+
45
+ After the agent returns, relay its summary and the release URL to the user.