groom-issues
Skill bundle for the phil:groom-issues, phil:groom-fix, phil:groom-set and phil:groom-ask commands — reads a whole issue board in one list call per forge —…
Skill by pmvanev
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/pmvanev-groom-issues
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: backend
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/groom-issues
What's inside
- Skill name
groom-issues- Description
- Skill bundle for the phil:groom-issues, phil:groom-fix, phil:groom-set and phil:groom-ask commands — reads a whole issue board in one list call per forge — plus one GraphQL call on GitHub for the parent/child edges that call cannot return — and reports what is wrong with it against a stated standard, applies the mechanical fixes inside a scope the user picks, resolves the defects between issues (merge, split, close, group, consolidate a feature decomposed under retired rules or a story spread across feature cards) by asking before each one, and fills in a card that says too little from the user's answers and its own suggestions, labelling where every field's words came from. Derives the defect table fresh every run and stores no grooming marker, so a declined candidate returns. For where the board STANDS rather than what is wrong with it — what is blocked, what is in flight, the next few queued — use phil:board-snapshot instead.
- License
- MIT
- Instructions
- 462 lines in SKILL.md · view on GitHub
Agent Skills spec issues
- files: referenced but missing: references/gitlab-cli.md, references/hierarchy.md
Files (96)
- SKILL.md
- ask.md · references/
- fix.md · references/
- scan.md · references/
- set.md · references/
- expected.md · self-test/01-scan-and-report/
- manifest.json · self-test/01-scan-and-report/
- expected.md · self-test/02-partial-read-no-claim/
- manifest.json · self-test/02-partial-read-no-claim/
- expected.md · self-test/03-clean-board/
- manifest.json · self-test/03-clean-board/
- expected.md · self-test/04-generated-line-not-a-defect/
- manifest.json · self-test/04-generated-line-not-a-defect/
- expected.md · self-test/05-session-scratch-is-a-defect/
- manifest.json · self-test/05-session-scratch-is-a-defect/
- expected.md · self-test/06-no-marker-anywhere/
- manifest.json · self-test/06-no-marker-anywhere/
- expected.md · self-test/07-surface-not-act/
- manifest.json · self-test/07-surface-not-act/
- expected.md · self-test/08-read-only/
- manifest.json · self-test/08-read-only/
- expected.md · self-test/09-unevaluated-is-not-clean/
- manifest.json · self-test/09-unevaluated-is-not-clean/
- expected.md · self-test/10-one-sided-chain/
- manifest.json · self-test/10-one-sided-chain/
- expected.md · self-test/11-scope-before-write/
- manifest.json · self-test/11-scope-before-write/
- expected.md · self-test/12-apply-reports-its-reason/
- manifest.json · self-test/12-apply-reports-its-reason/
- expected.md · self-test/13-semantic-untouched-same-issue/
- manifest.json · self-test/13-semantic-untouched-same-issue/
- expected.md · self-test/14-stale-since-scan/
- manifest.json · self-test/14-stale-since-scan/
- expected.md · self-test/15-generated-region-refused/
- manifest.json · self-test/15-generated-region-refused/
- expected.md · self-test/16-population-of-one/
- manifest.json · self-test/16-population-of-one/
- expected.md · self-test/17-partial-overlap-three-outcomes/
- manifest.json · self-test/17-partial-overlap-three-outcomes/
- expected.md · self-test/18-merge-survivor-is-a-choice/
- manifest.json · self-test/18-merge-survivor-is-a-choice/
- expected.md · self-test/19-split-second-pass/
- manifest.json · self-test/19-split-second-pass/
- expected.md · self-test/20-obe-unverified/
- manifest.json · self-test/20-obe-unverified/
- expected.md · self-test/21-declined-leaves-no-trace/
- manifest.json · self-test/21-declined-leaves-no-trace/
- expected.md · self-test/22-rederive-between-candidates/
- manifest.json · self-test/22-rederive-between-candidates/
- expected.md · self-test/23-ungrouped-effort-container/
- manifest.json · self-test/23-ungrouped-effort-container/
- expected.md · self-test/24-wave-family-needs-no-declaration/
- manifest.json · self-test/24-wave-family-needs-no-declaration/
- expected.md · self-test/25-elicit-and-write/
- manifest.json · self-test/25-elicit-and-write/
- expected.md · self-test/26-elicit-declined/
- manifest.json · self-test/26-elicit-declined/
- expected.md · self-test/27-elicit-body-moved/
- manifest.json · self-test/27-elicit-body-moved/
- expected.md · self-test/28-partial-answer-stays-partial/
- …and 36 more
SKILL.md (first lines)
# Groom issues — say what is wrong with a board
A board accumulates cards that someone filed half-finished. Reading them one at a time finds the
sloppy ones and misses the expensive ones, because the costly defects live *between* issues.
**Four commands, and the splits between them are the guarantee.**
- `/phil:groom-issues` reads and reports. It holds no `Write` and no `Edit`, so it cannot touch a file.
Its forge calls must be reads, and since 2026-09-04 that half is a promise, not a scoping: reading a
parent/child edge needs `gh api graphql`, which also accepts a mutation document. The scan's invariants,
in `references/scan.md`, carry that promise, and nothing else does. Wound: without the grant, the decomposed-feature check
reported clean on every board it was written for.
- `/phil:groom-fix` applies the mechanical column inside a scope the user picks, and changes no card's
existence.
- `/phil:groom-set` resolves the defects between issues — merge, split, close, group, consolidate — and
asks before every one.
- `/phil:groom-ask` fills in a card that says too little, asking, suggesting, and writing what the user
sanctions.
Run each exactly as its section or file says; improvise none of them.
**The splits buy three things.**
- **A structural re-read.** One command carrying the report in context computes writes against
remembered text. Separate commands must re-read.
- **Separate blast radii.** `/phil:groom-fix`'s edits each undo in one edit; `/phil:groom-set` changes
**which cards exist**, and neither a merge nor a split reverses cleanly. One consent over both trains
the habit formed on the many reversible changes onto the few irreversible ones.
- **Separate provenance.** `/phil:groom-ask` writes what no artifact holds — why a card is wanted. It
needs consent **plus provenance**: did the human sanction this claim, and does the card record whose
words carried it. No scoping enforces either.
**REQUIRED BACKGROUND: `phil:issue-board`.** Every forge mechanic — `-R` targeting, label semantics,
absolute-URL rules, dependency links, generated blocks — lives there. Do not guess any of it here.
## The four commands
Each command runs from one place. **Read the command's file whole before its first step**; this file
governs all four.
| Command | Runs | Read |
|---|---|---|
| `/phil:groom-issues` | the scan and its report | `references/scan.md` |
| `/phil:groom-fix` | the mechanical column | `references/fix.md` |
| `/phil:groom-set` | the set-level candidates | `references/set.md` |
| `/phil:groom-ask` | the semantic column | `references/ask.md` |
**Every ask in this skill follows `${CLAUDE_PLUGIN_ROOT}/skills/shared/decision-request.md`. Load it
before the first `AskUserQuestion` call.**
## The standard — what a well-formed issue contains
Without this, "appropriate description" is not checkable and grooming is taste. This is the house
default. **A project may override it in its own `CLAUDE.md`**, beside the per-project setup block
`phil:issue-board` already prescribes; where it does, that override wins and this section is ignored.
A well-formed issue has:
1. **A purpose readable without context** — what and why, in the body. A title is not a purpose, and
the next reader is a stranger or a forgetful you.
2. **A way to tell when it is done** — acceptance criteria, or an outcome concrete enough to check.
3. **Links that resolve.** Absolute URLs for files, because GitHub emits relative paths verbatim and
they 404. Bare `#N` for issues, because a bare reference renders live title and state where a
markdown link freezes both. **This rule is about the form, and the form is fully checkable here** —
a relative path is a finding whether or not its target exists, because the form 404s either way.
Whether a correctly-formed link *reaches* something is a different question, and it belongs to the
cross-reference row of the defect table below, which is where it goes dark.
4. **Correct labels**, with single-valued families carrying exactly one value. Nothing in a label's
name says whether it excludes a sibling; GitHub has no scoped labels at all. `documentation` +
`enhancement` on one issue is a defect or two orthogonal facts depending on a convention no forge
records — so for a **project-local** family this is checkable only where the project declares it,
and absent a declaration you report the rule **unevaluated**.
**`wave: *` is single-valued by default, with no declaration.** In a repo holding `.nwave/` or
`docs/feature/`, `phil:nwave-issue-board` makes it so: *"the wave label is single-valued and must be
swapped, not added"*. A feature walked DISCUSS→DELIVER otherwise carries four wave labels, and every
command reports success while the record of where it stands becomes unreadable. Report the
accumulation as a mechanical defect. A project overrides this only by declaring `wave: *`
multi-valued in as many words.
Match a family on the prefix before `::` or `: ` — `wave::deliver` where scoped labels exist and
`wave: deliver` where they do not are the same family, and a board may carry both spellings.
**A declaration is a bullet under the project's `## Issue board` section in `CLAUDE.md`** naming a
family and calling it single-valued or multi-valued, per the setup block in `phil:issue-board`.
Neither a label's own description nor the labels in use counts: the first is not authoritative, and
inferring the rule from the board's habits lets the board audit itself.
5. **A `## Chain` section when blocked or related** — the edge *and* the reason it exists, **on both
ends**. `phil:issue-board` puts the prose line on both issues even where the forge writes the
reverse edge itself, because the forge records the edge and never the reason. A chain naming an
issue that does not name back is therefore half-written, and it is the half a reader lands on that
decides whether they learn why. Cheap to check: the reciprocal is derivable from the same payload.
And it does **not** contain:
- **Session scratch or working state *typed outside a generated region*.** A board is world-readable, and
hand-written scratch belongs in the git-ignored local surface (ADR-013). Session state **inside** the
`nwave:status` markers is intended: `/phil:handoff` projects the why, the next action and the
diversion stack there. Reporting that generated projection as a body defect flags the correct shape.
- **Hand-written content inside a generated region** — anything between `nwave:status` markers is
regenerated, so a hand edit is destroyed on the next refresh and disagrees with its source until
then.
- **A second copy of something the forge already keeps** — a roster where sub-issues exist, an order
where position holds it. The copy is the one that goes stale.
**A dated observation is not a copy.** The defect is a body asserting the forge's *present* state —
"this board currently shows two cards In Progress" — which is wrong the moment the board moves and
says nothing about when it was true. An observation stamped with its date, and pointing at the forge
for the live answer, is history: it stays true, and a reader knows what to distrust. Prefer the
observation where the state is the argument and deleting it would remove the argument.
### Judging prose is taste; composing it is not
**Rules 1, 2 and 5 check that a purpose, a done-condition and a reason are PRESENT. None of the five
items asks how anything READS.** The discriminator is who composed the words:
- **Judging prose a human wrote is taste. It stays out.** A scan that flagged someone's style would be
the taste-policing this standard's opening sentence refuses, and no rule here licenses it. Presence is
all those rules check — never whether what is present is well written.From pmvanev/phil-claude-plugin, MIT.
More from pmvanev/phil-claude-plugin
- 0.570score
issue-board
pmvanev
Use when driving a GitLab or GitHub issue tracker or board from the command line with `glab` or `gh` — moving a card between board columns, reordering a…
SkillAFreshness: AClaude Code +9 - 0.570score
board-snapshot
pmvanev
Use when asked where an issue board stands right now rather than what is wrong with it — "summarise my board", "what's on the board", "where does the board…
SkillAFreshness: AClaude Code +9 - 0.570score
board-setup
pmvanev
Use when recording a repo's issue-board constants in its `CLAUDE.md` — the forge and repo, the project and Status field ids, every option id, the enabled…
SkillAFreshness: AClaude Code +9 - 0.570score
nwave-slice-status
pmvanev
Use when the user asks where an nWave feature stands — "how many steps are in this slice", "which ones are done", "which one are we on", "what's next", "is…
SkillAFreshness: AClaude Code +9 - 0.566score
nwave-wave-summary
pmvanev
Use when asked what finished work decided, rather than where it stands or what you were doing — "what did DISCUSS decide", "what did that stage settle"…
SkillAFreshness: AClaude Code +9 - 0.566score
nwave-issue-board
pmvanev
Use for any GitLab or GitHub board or tracker work in an nWave repo — one holding `.nwave/` or `docs/feature/` — including putting a feature on the tracker as…
SkillAFreshness: AClaude Code +9 - 0.565score
adversarial-review
pmvanev
Skill bundle for phil:adversarial-review command — a general-purpose independent adversarial critic.
SkillAFreshness: AClaude Code +9 - 0.565score
edd
pmvanev
Skill bundle for phil:edd command — Expectation-Driven Development front-door.
SkillAFreshness: AClaude Code +9 - 0.565score
red-team-prose
pmvanev
Skill bundle for phil:red-team-prose command — reviews a doc, README, or release note for AI-generated tells, Elements of Style clarity, and fitness for its…
SkillAFreshness: AClaude Code +9 - 0.561score
ai-eos
pmvanev
Skill bundle for phil:ai-eos command — detects the stylistic tells that mark technical prose as AI-generated, with a density verdict and ranked findings.
SkillAFreshness: AClaude Code +9 - 0.561score
redesign-tests
pmvanev
Skill bundle for phil:redesign-tests command — human-approved, behaviour-changing test redesign loop with a coverage-equivalence claim per rewrite
SkillAFreshness: AClaude Code +9 - 0.561score
refactor-loop
pmvanev
Skill bundle for phil:refactor-loop command — gated closed-loop refactoring with a separate proposer and correctness critic, hard test gates, and a DAG ledger
SkillAFreshness: AClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 10
- Last commit (this folder)
- Oct 14, 2026 (14 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/pmvanev/phil-claude-plugin
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from pmvanev
- 0.570score
issue-board
pmvanev
Use when driving a GitLab or GitHub issue tracker or board from the command line with `glab` or `gh` — moving a card between board columns, reordering a…
SkillAFreshness: AClaude Code +9 - 0.570score
board-snapshot
pmvanev
Use when asked where an issue board stands right now rather than what is wrong with it — "summarise my board", "what's on the board", "where does the board…
SkillAFreshness: AClaude Code +9 - 0.570score
board-setup
pmvanev
Use when recording a repo's issue-board constants in its `CLAUDE.md` — the forge and repo, the project and Status field ids, every option id, the enabled…
SkillAFreshness: AClaude Code +9 - 0.570score
nwave-slice-status
pmvanev
Use when the user asks where an nWave feature stands — "how many steps are in this slice", "which ones are done", "which one are we on", "what's next", "is…
SkillAFreshness: AClaude Code +9 - 0.566score
nwave-issue-board
pmvanev
Use for any GitLab or GitHub board or tracker work in an nWave repo — one holding `.nwave/` or `docs/feature/` — including putting a feature on the tracker as…
SkillAFreshness: AClaude Code +9 - 0.566score
nwave-wave-summary
pmvanev
Use when asked what finished work decided, rather than where it stands or what you were doing — "what did DISCUSS decide", "what did that stage settle"…
SkillAFreshness: AClaude Code +9
Cite this page
groom-issues skill. Agent Mart. https://agentmart.dev/skills/pmvanev-groom-issues (last updated 2026-10-24)