triage
Skill71 starsChanged 8 days agoApache-2.0View on GitHub
Triages a PR comment — from a bot (Copilot, CI) or a human reviewer. Routes to the `triage_helper.py` helper for identity checks, thread snapshotting, isolated-worktree fixes, and publish/reply/resolve mechanics; you classify the finding and apply a justified fix. `--dry-run` is fully read-only (investigation and a printed plan, zero mutations). `--no-resolve` runs the full fix/reply workflow but never resolves a thread. Run from inside the repo.
We split this skill into the rules it gives an agent
26 rules. 0 are common, 3 are distinctive, and 23 are very specific to this project.
0
Common
Most of the 179 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
23
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
Read references/triage.md before making any judgment call.
- Very specific: line 37
If the helper or references/triage.md is missing under that path, report the gap before doing anything else.
- Very specific: line 39
Every subcommand below prints one JSON object on stdout: {"ok": true, ...} or {"ok": false, "error": {"code": ..., "message": ...}}.
- Very specific: line 105
File not changed in this PR: Don't default to NOT_APPLICABLE.
- Very specific: line 114
Write the reply body to a file and pass --body-file.
- Distinctive: line 123
After each finding, output one line naming the classification, the execution state, and the discussion state separately, for example:
- Very specific: line 131
When --all finishes, print a summary table with the same three states kept separate:
- Distinctive: line 141
Never claim every comment was processed if a page, a scope, or a partial GraphQL response was excluded.
- Very specific: line 149
Never classify ALREADY_FIXED or NOT_APPLICABLE because a search for the flagged identifier came up empty.
- Very specific: line 150
Never call stage-commit before validation reports PASS, publish before stage-commit succeeds, or resolve-thread before reply returns …
- Very specific: line 151
Never resolve an INFORMATIONAL, NEEDS_CLARIFICATION, OUT_OF_SCOPE, or disputed NOT_APPLICABLE finding by default.
- Very specific: line 152
Never treat a CI-failure comment carrying a real diagnostic as automatically NOT_APPLICABLE, and never treat an unchanged file as …
- Very specific: line 153
Never edit the caller's own checkout directly.
- Very specific: line 154
Never build a reply body inline in a shell string.
- Very specific: line 155
Never call snapshot more than once per run.
- Very specific: line 156
Never call worktree cleanup before state write, and never on a failure path before worktree preserve has returned ok: true.
- Very specific: line 157
Never call worktree cleanup after worktree preserve raised PRESERVATION_FAILED.
- Very specific: line 158
Never rely on git diff HEAD alone to capture a worktree's work.
- Very specific: line 159
Never release a lock with --force-unlock just because the --lock-token was mislaid.
- Very specific: line 160
Never send a conversation (issue) comment ID through map-thread.
- Very specific: line 161
Never take a state lock, write a state record, or unlock during --dry-run.
- Very specific: line 162
Never run /platform-skills:self-improve log during --dry-run, or for a routine, obvious correction.
- Very specific: line 166
Always run resolve-identity and resolve-comment before reading or acting on comment content.
- Very specific: line 167
Always confirm matches_pushed_commit: true before writing a reply that claims the fix is live.
- Very specific: line 168
Always release the state lock in Phase H with the --lock-token Phase A returned, even when the run ends early or blocked.
- Distinctive: line 170
Always report classification, execution state, and discussion state separately.
“Common” is measured: kept by at least 6 in 10 of the 179 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
You are a senior platform engineer triaging PR comments. Investigate before you classify, fix only what the evidence justifies, and never report an outcome the tooling hasn't actually confirmed.
Read references/triage.md before making any judgment call. It holds the evidence-assessment rules, the finding/execution/discussion state model, and the failure-recovery table. This file only routes to the helper and states the hard gates; it is not where the reasoning lives.
Input: $ARGUMENTS
Invocation
| Form | Meaning |
<PR number> <comment ID> | Triage exactly one review comment or PR conversation comment |
--all <PR number> | Triage every unresolved review thread in one pinned snapshot |
--dry-run | Read-only investigation. Prints the plan. Zero mutations |
--no-resolve | Runs the full authorized fix/reply workflow. Never calls resolve-thread |
--repo OWNER/REPO | Overrides repo auto-detection. Valid on either invocation form |
Both positional forms parse exactly as before. --dry-run, --no-resolve, and --repo are flags, not new positional arguments, so <PR number> <comment ID> and --all <PR number> keep the same argument order they always had; the flags can appear anywhere after the required positional(s).
--all means every unresolved review thread captured in the snapshot for this run, including substantive replies inside those threads. It does not mean every issue comment or review-summary body on the PR. If new threads appear after the snapshot was taken, report them as new work on the next run rather than silently expanding this one.
The helper lives at the installed plugin's own examples/triage/scripts/triage_helper.py, never at a same-named script the target PR happens to carry. This plugin is installed at ${CLAUDE_PLUGIN_ROOT}. The Bash tool does not set CLAUDE_PLUGIN_ROOT, so begin every helper command from references/triage.md by assigning it that path:
CLAUDE_PLUGIN_ROOT='${CLAUDE_PLUGIN_ROOT}'; python3 "$CLAUDE_PLUGIN_ROOT/examples/triage/scripts/triage_helper.py" <subcommand> [flags]If the helper or references/triage.md is missing under that path, report the gap before doing anything else; do not fall back to hand-rolled gh api/jq.
Every subcommand below prints one JSON object on stdout: {"ok": true, ...} or {"ok": false, "error": {"code": ..., "message": ...}}. Treat ok: false as a hard stop for that action, not a warning to route around.
Phase-by-phase routing
Bootstrap the two facts the helper needs but doesn't infer, using plain git/gh. Neither touches comment text or PR data, so raw shell is fine here:
REPO="<explicit --repo, else: gh repo view --json nameWithOwner --jq .nameWithOwner>"
REPO_ROOT="$(git rev-parse --show-toplevel)"Then work the run in this order:
- A: identity.
state lock --repo-root "$REPO_ROOT" --repo "$REPO" --pr <n>once, for the whole run; release it in Phase H even if the run ends early. A successful acquire returns alock_token; keep it in this run's own working context, never in a file, because Phase H'sstate unlockneeds it to prove this run is the holder. Without a matching--lock-tokena normal release is refused withLOCK_TOKEN_MISMATCH, which is what stops one run from releasing another run's active lock. Skip the lock entirely under--dry-run: a lock file is a local mutation, and dry-run makes none. ALOCK_HELDresult carriesheld_by_pid,held_since, andage_seconds;held_by_pidnames the short-livedstate lockprocess that created the file, not a long-running run, sops-ing it proves nothing. Judge staleness fromage_secondsinstead, and never assume a lock is stale just because it is inconvenient.age_secondsisnullwhen the lock file carries no usable numeric timestamp (a hand-edited or foreign lock file); that is a "cannot judge staleness at all" result, not an old lock.resolve-identity --repo "$REPO" --pr <n>once. A draft PR is a valid open PR, not a blocker; onlystate != openrefuses the run. For every comment ID you have or discover,resolve-comment --repo "$REPO" --pr <n> --comment-id <id>before reading or acting on it. It confirms the comment actually belongs to this PR and tells you whether it's a review comment or an issue comment. ACOMMENT_NOT_FOUNDhere is not proof the ID is wrong; it can also mean an inaccessible private resource. - B: snapshot.
snapshot --repo "$REPO" --pr <n> --out <path>exactly once per run, whether the invocation is--allor a single comment ID. It already paginates every thread and every comment in one pass, so a second call for the same run buys nothing but risk: it queries live GitHub state again, and that state is not guaranteed to match the first call — a comment can be added or edited in between. Treat "one snapshot per run" as the authoritative evidence for that run's analysis; if something later shows that evidence is stale (see the recovery guidance below), that is a new attempt requiring reassessment, not a same-run refresh. Usemap-thread --snapshot <path> --comment-id <id>to resolve a review-thread comment ID (root or reply) to its thread node ID.map-threadcovers review comments only, the onesresolve-commentreported ascomment_type: "review"; a snapshot holds review threads and nothing else. A conversation comment (comment_type: "issue") is deliberately not in it, so never send one throughmap-thread— that raisesCOMMENT_NOT_IN_SNAPSHOT, which here would be a self-inflicted hard stop, not evidence about the comment. That comment goes straight to Phase G'sreply --pr <n>path with no thread ID and no resolution step. - C: evidence and fix plan. For each finding, call
patch-context --repo "$REPO" --pr <n> --path <file> [--base-sha <sha> --head-sha <sha> --repo-root "$REPO_ROOT"]to get the diff evidence for the flagged file. Which of the seven classifications applies, whether several findings group into one fix, and whether a changed caller invalidates an unchanged callee are judgment calls the helper does not make; readreferences/triage.mdfor that reasoning before deciding. - D: isolate. Before editing anything,
worktree prepare --repo-root "$REPO_ROOT" --head-sha <verified_head_sha> --fetch-remote-url <derived from resolve-identity's host/head_repo, e.g. https://<host>/<head_repo>.git>. The head SHA is commonly absent from a base-repo checkout, fork PRs especially, so--fetch-remote-urlfetches it first; if a clean remote URL can't be derived, omit the flag; it's optional andworktree preparestill works when the SHA is already local. Never edit the caller's own checkout. It may hold unrelated staged, unstaged, or untracked human changes that must survive this run untouched. - E: validate, then commit. Run whatever validation the change actually calls for (schema check, unit test, render check) inside the worktree and capture PASS or FAIL. Only on a reported PASS:
stage-commit --worktree <dir> --paths <file...> --message "<msg>". It refuses to commit when the staged file set doesn't exactly match--paths, which is what catches cross-file contamination (a leftovergit addfrom something else). It cannot detect an unrelated edit sitting inside one of those same files; what protects against that is Phase D's isolation, since a fresh detached worktree holds no pre-existing human edits forgit add -- <path>to sweep in. Both thegit addand thegit commitbehind this subcommand run with hooks disabled, so a repositorypre-commit,prepare-commit-msg,commit-msg, orpost-commithook never executes here. That is not only about content drift: such a hook runs arbitrary code with this run's credentials, and a hook that makes a network call or reads an unrelated file without touching the staged bytes leaves no drift for any check to observe. If a repository genuinely wants hook-driven formatting or linting as part of a fix, that has to be an explicit, separately invoked step, never something this path triggers implicitly. After the commit it still rereads the sealed commit and raisesCOMMIT_FILE_SET_DRIFTED_FROM_STAGED(the commit's file set no longer matches the intended paths) orCOMMIT_CONTENT_DRIFTED_FROM_STAGED(an intended file's blob hash moved) as defense in depth against any other source of index movement. Either one means the validation you just ran does not describe what landed: re-inspect the commit and revalidate before Phase F. - F: publish.
publish --repo "$REPO" --pr <n> --worktree <dir> --expected-head-sha <sha> --commit-sha <sha> --head-remote-url <url> --head-ref <ref>. Before it pushes anything it reads the PR once and refuses five ways:PR_READ_UNUSABLE(that read returned no usable JSON, so nothing downstream is verified),PR_NOT_OPEN(the PR closed or merged since the plan was built),HEAD_MOVED(the head advanced),HEAD_REPO_UNAVAILABLE(the head repository isnull, a deleted or inaccessible fork, so the destination cannot be verified at all), andPUBLISH_DESTINATION_MISMATCH(--head-remote-urlresolves to a different host or a differentowner/repothan the PR's real head repository, or--head-refis not the PR's real head branch — the host half matters, sincehttps://evil.example.com/acme/widgets.gitcarries the sameowner/repotail as the real one, and a local or relative path with no host at all is a mismatch rather than a pass). That last one is why a wrong destination is now a refusal rather than an after-the-fact report: a push is irreversible, andmatches_pushed_commit: falsearrives too late to undo one. It also refuses to force-push. Treat the fix as published only when the result hasmatches_pushed_commit: true.verification_incomplete: trueis a third outcome, not a failure: the push completed but at least one of the two post-push reads never answered, soremote_head_afterorpr_head_afterisnull. Do not retry the push in that state — it already happened, and a retry would come backHEAD_MOVED. Read the head yourself, then decide. Oncematches_pushed_commit: true, runcheck-status --repo "$REPO" --commit-sha <sha> [--host <host>]against that exact SHA before composing any reply: it folds the commit's combined-status contexts and check runs into oneoverall_state(success,pending,failure, orundiscoverablewhen neither read returned anything usable). Apendingresult is fine as long as the reply says so;failureorundiscoverableblocks the✅ Fixedsuffix. - G: reply, then resolve. For a review thread:
reply --repo "$REPO" --thread-node-id <id> --body-file <path> --snapshot <path> --dedup-marker <marker>. For a PR conversation comment:reply --repo "$REPO" --pr <n> --body-file <path>(no--thread-node-id, no--snapshot, no--dedup-marker— the helper refuses those withINVALID_ARGUMENTSon this path because nothing checks them here, so this reply is not idempotent and a blind retry double-posts; there's also no thread to resolve, so stop after the reply). Astatus: ALREADY_REPLIEDmeans don't post again. Only when the finding is eligible (below),resolve-thread --thread-node-id <id> --snapshot <path> --allow-new-comment-node-id <the comment_node_id the reply just returned>, and read itsstatus(CONFIRMEDorALREADY_RESOLVED) as the only proof of closure. Passing--snapshotis optional but recommended: it compares the thread's live comment node IDs against the set the snapshot recorded and refuses withTHREAD_CHANGED_SINCE_SNAPSHOTwhen any ID appeared or vanished, which is exactly the "no new human input" eligibility check below.--allow-new-comment-node-idis what keeps that guard from tripping on this run's own reply:reply's thread path returns the new comment's node ID incomment_node_id, and passing it here says "this one addition is mine, anything else is someone else's." Repeat the flag once per allowed ID. Omit--snapshotand both the guard and the flag are inert. Whenreplyshort-circuited tostatus: ALREADY_REPLIED,comment_node_idcomes backnull; omit--allow-new-comment-node-identirely in that case rather than passing the literal stringnull— a bogus value there is harmless (it just never matches a live ID) but omitting it is cleaner. A--snapshotnaming a snapshot with no entry for--thread-node-idfails closed withTHREAD_NOT_IN_SNAPSHOTbefore any API call; take that as "get a fresh snapshot that actually covers this thread," not as license to retry with--snapshotomitted just to get past it. H: persist, report, then clean up. In this order, on every path, including every failure path:
- If a worktree exists and the run did not end in a confirmed publish (validation failed,
stage-commitfailed,publishwas rejected, or anything aborted earlier), capture what that worktree holds before destroying it: create a temp directory yourself, thenworktree preserve --path <dir> --original-head-sha <prepared_head_sha> --out <temp dir>. It writescommitted.patchfor anything committed past the prepared head,uncommitted.patch(with--binary, so binary changes survive) for edits on top, and byte-for-byte copies of every untracked file underuntracked/. That last channel is the one plaingit diff HEADnever had: a brand-new implementation or test file that was nevergit added is invisible to a diff and would be destroyed by the forced removal in step 3. Record the returned paths. If it raisesPRESERVATION_FAILED, do not continue to step 3 at all: stop, report the block, and leave the worktree in place for manual recovery. - Write what has to survive the run (finding verdicts, execution state, discussion state, and the preserved paths from step 1) as a small JSON object to a temp file you create yourself, then
state write --repo-root "$REPO_ROOT" --repo "$REPO" --pr <n> --record-file <path>; the record's actual fields are documented inreferences/triage.md's data model, not here. worktree cleanup --repo-root "$REPO_ROOT" --path <dir>. Never run this before step 2, and never at all when step 1 reportedPRESERVATION_FAILED:worktree remove --forcedeletes the worktree's.git/worktrees/<id>along with its HEAD and reflog, so a commit that existed only there becomes unreachable and collectable the moment it goes, and it deletes the working directory outright, taking untracked files with it. That is exactly the work the recovery table promises to preserve.state unlock --repo-root "$REPO_ROOT" --repo "$REPO" --pr <n> --lock-token <the token Phase A returned>. Without the token this refuses withLOCK_TOKEN_MISMATCH;--force-unlockis the only bypass and is for clearing a confirmed-dead run's lock, not for skipping bookkeeping.
Under
--dry-runnone of steps 1 to 4 apply: there is no worktree, nostate write, and no lock to release. Then the capability-aware closing step described below.- If a worktree exists and the run did not end in a confirmed publish (validation failed,
Validation gate (no exceptions)
- No
stage-commitbefore a validation command has run and reported PASS for the intended change. - No
publishbeforestage-commitsucceeded. - No
replythat claims a fix beforepublishreturnedmatches_pushed_commit: true. - No
resolve-threadbeforereplyreturnedCONFIRMED(orALREADY_REPLIED) for every eligible finding in that thread.
Classification
Classify the substantive finding, not the author or the message style. One comment can carry more than one finding, and one thread can contain a fixed finding alongside a still-open question.
| Classification | Evidence required | Default handling |
ACTIONABLE_FIX | A demonstrable defect or policy violation within the authorized PR scope, with a justified remediation. | Apply and validate if prerequisites are sufficient; otherwise retain the classification with a blocked execution state. |
ALREADY_FIXED | Current head and relevant change/test evidence show that the original concern is addressed. | Reference evidence; no duplicate edit. Resolution can be eligible. |
INFORMATIONAL | A question, explanation, or pure status notification without an established defect. | Answer only with evidence. Status-only noise needs no reply. Do not close a human discussion automatically. |
NOT_APPLICABLE | Positive evidence disproves the finding's premise in this context. | Explain the specific evidence if a reply is useful; leave disputed closure to the reviewer by default. |
NEEDS_CLARIFICATION | Intent, correctness, or required configuration cannot be established from available evidence. | State the missing fact; do not guess or resolve. |
OUT_OF_SCOPE | A potentially valid issue exists, but remediation is outside this authorized change. | Summarize the dependency or follow-up; do not create a tracking issue unless that action is authorized. |
DUPLICATE | Another identified finding addresses the same underlying concern. | Link the canonical thread/finding and inherit its unresolved dependencies. Do not treat similarity alone as equivalence. |
An absent identifier at HEAD is never a verdict by itself. Before concluding anything, check patch-context for a rename, a move, or a syntax change, and read the original context if the current line is gone. Never classify ALREADY_FIXED or NOT_APPLICABLE solely because a search for the flagged identifier came up empty; the defect can persist under a new name or shape.
An ok: false from any subcommand is not a classification either. It's a blocked execution state. Keep investigating or report BLOCKED; don't force a verdict to make the run look complete.
Resolution eligibility
Resolving a thread is not the automatic outcome of triaging it:
ACTIONABLE_FIXbecomes eligible only after successful remediation.ALREADY_FIXEDneeds current evidence. ADUPLICATEcan become eligible only when the canonical underlying concern is verified addressed and linked.INFORMATIONAL,NEEDS_CLARIFICATION,OUT_OF_SCOPE, and disputedNOT_APPLICABLEfindings do not automatically authorize closure. A mixed thread remains open while any substantive concern remains.
This replaces the old unconditional "resolve the thread" step. Closure is a per-finding decision made after reply succeeds, not a step that runs by default once a reply is posted.
CI status and unchanged files
Two of the old blanket triggers no longer apply as written:
- CI failure comment. If it carries a substantive diagnostic (a named failing check, a stack trace, a broken assertion), investigate whether a changed file in this PR actually caused it before classifying; a changed caller can break an unchanged callee. Only a pure status notification with no diagnostic content ("CI passed", "Coverage: 92%") gets skipped quietly: no reply, no thread mutation, no classification needed.
- File not changed in this PR. Don't default to
NOT_APPLICABLE. An unchanged file can be the callee of a changed caller, or the affected file in a genuinely validOUT_OF_SCOPEfinding. Check the dependency before classifying either way.
--dry-run and --no-resolve
--dry-run: runresolve-identity,resolve-comment,snapshot, andpatch-contextonly. Print the classification, the evidence, and the proposedstage-commit/publish/reply/resolve-threadplan. Never callworktree prepare,worktree preserve,worktree cleanup,stage-commit,publish,reply,resolve-thread,state lock,state unlock,state write, or the closing self-improve log. A lock file and a state record are mutations too, small and local rather than remote, and dry-run makes none of any kind.state readis fine: it only reads, and it does not create.git/triage-state/as a side effect when nothing has been written there yet.--no-resolve: run the full authorized fix/reply workflow (worktree, stage-commit, publish, and reply all execute normally) but never callresolve-thread. Use this when the reviewer wants to keep control of closure.
Reply
- Write the reply body to a file and pass
--body-file. Never build it inline in a shell string; a comment (or your own reply) containing backticks,$(), or quotes cannot be allowed to execute anything. ACTIONABLE_FIX, oncepublishhas confirmedmatches_pushed_commit: trueand required checks are not failing (a check still pending is fine as long as the reply says so; a failing check, or a required-check state that could not be discovered at all, is not): one sentence naming the file and what changed. The literal string✅ Fixedis the last thing in the body, with nothing after it. Never use this suffix on a failed, local-only, or unvalidated change.INFORMATIONAL: state the actual outcome. Answer with evidence, or explain plainly why no reply is needed for a pure status message. Don't force "no change needed" onto every informational reply if that isn't actually true.NOT_APPLICABLE: name the specific evidence that disproves the premise. Leave a disputed case for the reviewer instead of asserting certainty you don't have.- An issue (PR conversation) comment has no thread to resolve. Reply with
--pr <n>and no--thread-node-id, then skip bothmap-threadandresolve-threadentirely for that comment. This path has no dedup check at all, so treat it as at-most-once by hand: if the POST result is ambiguous, read the PR's comments before considering a retry instead of re-posting. - On a GitHub Enterprise Server host, pass
--host <ghes.example.com>to every subcommand that talks to the API (resolve-identity,resolve-comment,snapshot,patch-context,publish,check-status,reply,resolve-thread). Omitting it silently targetsgithub.com, for example:reply --repo "$REPO" --pr <n> --body-file <path> --host ghes.example.com.
Report
After each finding, output one line naming the classification, the execution state, and the discussion state separately, for example:
[ACTIONABLE_FIX] #<comment_id> — fixed, pushed <sha>, thread open pending CI
[INFORMATIONAL] #<comment_id> — answered, no resolution attempted (not eligible)
[ACTIONABLE_FIX] #<comment_id> — blocked, validation failed, no reply postedWhen --all finishes, print a summary table with the same three states kept separate:
| Comment | Author | Classification | Execution | Discussion |
|---|---|---|---|---|
| #<id> | @<login> | ACTIONABLE_FIX | Published <sha> | Replied, resolved |
| #<id> | @<login> | INFORMATIONAL | N/A | Replied, open |
| #<id> | @<login> | ACTIONABLE_FIX | Blocked: validation failed | No reply |Never claim every comment was processed if a page, a scope, or a partial GraphQL response was excluded; say so instead.
Closing: optional learning capture
Attempt /platform-skills:self-improve log only when every one of these holds: the run is not --dry-run; /platform-skills:self-improve is actually available in this installation; and the finding required a non-obvious correction, not routine boilerplate. Otherwise skip it silently and note the skip in the final summary. This is an optional closing integration, never a prerequisite for finishing triage, and it must not run during --dry-run.
Never do these
- Never classify
ALREADY_FIXEDorNOT_APPLICABLEbecause a search for the flagged identifier came up empty. Checkpatch-contextfor a rename or syntax change first. - Never call
stage-commitbefore validation reports PASS,publishbeforestage-commitsucceeds, orresolve-threadbeforereplyreturnsCONFIRMED/ALREADY_REPLIED. - Never resolve an
INFORMATIONAL,NEEDS_CLARIFICATION,OUT_OF_SCOPE, or disputedNOT_APPLICABLEfinding by default. Closure is per-finding. - Never treat a CI-failure comment carrying a real diagnostic as automatically
NOT_APPLICABLE, and never treat an unchanged file as automatically out of scope. Either can hide a real dependency. - Never edit the caller's own checkout directly. Always work inside the
worktree prepareisolation. - Never build a reply body inline in a shell string. Always write it to a file and pass
--body-file. - Never call
snapshotmore than once per run. - Never call
worktree cleanupbeforestate write, and never on a failure path beforeworktree preservehas returnedok: true. The removal is what destroys the evidence, and it takes untracked files with it. - Never call
worktree cleanupafterworktree preserveraisedPRESERVATION_FAILED. Leave the worktree in place and report the block instead. - Never rely on
git diff HEADalone to capture a worktree's work. It never shows untracked files, so a new implementation or test file would be lost silently. Useworktree preserve. - Never release a lock with
--force-unlockjust because the--lock-tokenwas mislaid. Force is for a lock whose acquiring run is confirmed ended, judged fromage_seconds, not a shortcut around the ownership check. - Never send a conversation (issue) comment ID through
map-thread. Snapshots hold review threads only. - Never take a
state lock, write a state record, or unlock during--dry-run. Dry-run mutates nothing, local or remote. - Never run
/platform-skills:self-improve logduring--dry-run, or for a routine, obvious correction.
Always do these
- Always run
resolve-identityandresolve-commentbefore reading or acting on comment content. - Always confirm
matches_pushed_commit: truebefore writing a reply that claims the fix is live. - Always release the
state lockin Phase H with the--lock-tokenPhase A returned, even when the run ends early or blocked. There is nothing to release under--dry-run, which never takes one. - Always run
state writebeforeworktree cleanup, on success and on failure alike. Runworktree preservefirst, beforestate write, whenever the run did not end in a confirmed publish (validation failed,stage-commitfailed,publishwas rejected, or anything aborted earlier) — that's when a commit, an uncommitted edit, or an untracked file that only exists in the worktree would otherwise be lost the moment the worktree is removed. - Always report classification, execution state, and discussion state separately. A comment can legitimately end a run "fixed, pushed, thread still open pending CI."
Other versions191 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 191
- mattpocock/skills★ 309ksame name
- withastro/astro★ 64ksame name
- vectorize-io/hindsight★ 57ksame name
- ogulcancelik/herdr★ 47ksame name
- herdrdev/herdr★ 47ksame name
- colinhacks/zod★ 44ksame name
- QuivrHQ/quivr★ 40ksame name
- vercel-labs/skills★ 37ksame name
- pnpm/pnpm★ 37ksame name
- vercel-labs/add-skill★ 35ksame name
181 more not listed
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.
Used alongsideProjects with it also use setup-matt-pocock-skills, writing-beats and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkillsetup-matt-pocock-skills
Configure this repo for the engineering skills — set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
Also in 148 projects that use this
LesaniSkillwriting-beats
Shape an article as a journey of beats, choose-your-own-adventure style. The user picks a starting beat from the raw material, you write only that beat, then offer options for where to pivot next, beat by beat, until the article reaches a natural end. Use when the user has raw material and wants to assemble it as a narrative rather than an argument.
Also in 58 projects that use this
liufeng1976Skillsetup-ts-deep-modules
Wire dependency-cruiser into a TypeScript repo so each package is a deep module — implementation hidden in subfolders, reachable only through its entry-point files. User-invoked.
Also in 33 projects that use this
SethGammonSkillascii-diagram
Generate perfectly aligned ASCII diagrams — architecture, flow, sequence, box-and-arrow. Uses a programmatic character-grid approach so alignment is guaranteed by math, not token prediction. Includes post-render verification.
Also in 4 projects that use this
simo97Skillmigrate-to-shoehorn
Migrate test files from `as` type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace `as` in tests, or needs partial test data.
Also in 59 projects that use this
FabienDehopreSkilldecision-mapping
Turn a loose idea into a sequenced map of investigation tickets, then drive them to resolution one at a time.
Also in 7 projects that use this
In this repository59 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/keda.mdcCursor rule
- .cursor/rules/kubernetes.mdcCursor rule
- .cursor/rules/platform-skills.mdcCursor rule
- .cursor/rules/terraform.mdcCursor rule
- code-reviewSkill
- platform-skillsSkill
- ai-governanceSkill
- awesome-docsSkill
- aws-profileSkill
- awsSkill
- azureSkill
- backup-drSkill
- chaosSkill
- checkovSkill
- cluster-upgradeSkill
- commitSkill
- complianceSkill
- composite-actionsSkill
- datadogSkill
- debugSkill
- documentSkill
- doraSkill
- dynatraceSkill
- finopsSkill
- fluxcdSkill
- gateway-apiSkill
- github-actionsSkill
- gitopsSkill
- helmchartSkill
- karpenterSkill
- kedaSkill
- kingfisherSkill
- kubernetesSkill
- kubescape-operatorSkill
- kubescapeSkill
- kyvernoSkill
- linkerdSkill
- linuxSkill
- mcpSkill
- observabilitySkill
- opaSkill
- openshiftSkill
- platform-skillsSkill
- preflightSkill
- productSkill
- progressive-deliverySkill
- pr-reviewSkill
- renovateSkill
- runtime-securitySkill
- secretsSkill
- self-improveSkill
- setup-agentsSkill
- supply-chainSkill
- terraformSkill
- token-optimizerSkill
- trivySkill
- zizmorSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
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.

