agentleFS
vzhukovsvzhukovs/podman-desktop-kit/skills/triage/SKILL.md

triage

Skill0 starsChanged 12 days agoApache-2.0View on GitHub

Triage an upstream podman-desktop issue: dedup, classify, draft requirements, and pick a route. Without an issue number, shortlist what is worth taking.

189 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use writing-beats, setup-matt-pocock-skills 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.
  • LesaniSkill

    writing-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 66 projects that use this

  • GoogleSkill

    setup-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 167 projects that use this

  • liufeng1976Skill

    setup-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 42 projects that use this

  • SethGammonSkill

    ascii-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

  • simo97Skill

    migrate-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 68 projects that use this

  • LesaniSkill

    writing-shape

    Take a markdown file of raw material and shape it into an article through a conversational session — drafting candidate openings, growing the piece paragraph by paragraph, arguing about format (lists, tables, callouts, quotes) at each step. Use when the user has a pile of notes, fragments, or a rough draft and wants help turning it into something publishable.

    Also in 63 projects that use this

  • +1 more from Lesani

The file

We split this skill into the rules it gives an agent

1 rule. 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 176 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not read the code broadly yourself.

    line 110

“Common” is measured: kept by at least 6 in 10 of the 176 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Decide whether planning is needed at all. Half the value of this plugin is here — the other half is spent by people who skipped it.

0a. What came with the command

The first line is the invocation — the issue number or URL, and --label. Everything after it, in the same message, is prior context. It goes into ## Prior context of issue.md, and it goes there verbatim.

That is the whole rule, and it needs no parsing because it is a line boundary.

Verbatim rather than summarized, for the reason section 4 reads the [inferred] list back: a summary is this plugin's reading of what somebody told it, and a wrong reading does not stay where it was made — it reaches the plan, the tasks and the audit as a record everything downstream trusts.

What it is for is the thing that has no other home: work already related to this issue, an approach to repeat or to avoid, a trap the last attempt hit, pull requests worth reading before the code. Typed into a chat message that dies with the session, none of it reaches /pd:plan three days later — which is the whole argument for this plugin keeping state on disk at all.

A requirement drawn from it is tagged [operator] in section 4. Not [issue]: that tag means a maintainer can be pointed at the line that says it.

Nothing came with the command? Then ## Prior context says none given. Most triages will, and it is an answer — an empty section reads as forgotten.

0. No issue number? Then the question is which one

Skip this section when you were given an issue. When you were not, the job is scenario 6: not "take this issue" but "what is there to take".

pdkit issue list [--label a,b] [--limit 20] prints the open backlog with the facts that decide whether an issue can be started: pull requests that reference it in this repository, who it is assigned to, whether a maintainer answered, whether a bug carries a reproduction, and how long since a human — not the stale bot — last touched it. · marks the ones something blocks.

That listing is an order over facts. It does not know the thing that actually decides, and you do:

  1. Read the top few bodies, not all of them. Three to five, with pdkit issue fetch <n>. The listing exists so that you do not read twenty.
  2. Judge what no grep judges — whether the requirement is clear enough to plan against, whether the reported behavior is specific enough to verify, and roughly how big it looks. A well-formatted issue that says "improve the UX" is not ready; a free-hand one with a stack trace and a file path is.
  3. Say what is blocked and why, rather than silently dropping it. An issue with an open PR is not a bad issue, it is a taken one, and the difference matters when that PR goes stale.
  4. Offer a shortlist of three at most, each with one sentence on why it is on the list and one on what is unclear about it. Then ask which to triage.

Nothing here writes anything or moves any issue. Listing is a read; picking is the user's. When they pick, continue from section 1 with that number.

0b. Has this issue been triaged before?

pdkit state <n> in one line. Anything but new means the plugin already carries a record, and triaging over it is not a fresh start: the R-set, the route and research.md are already on disk, and everything downstream reads them.

Three different situations, and only one of them is this command's:

  • Continuing — the record is right and the work just stopped. /pd:resume <n>, not a second triage.
  • The review rejected the approach — pdkit issue rework <n> --reason "<what was refused>". It lands back on triaged with the pull request left open and requirements thawed, and the objection becomes a [review] requirement. Continue from section 1 after it.
  • The earlier run was wrong from the start — the issue was read as something it is not, or the scouts mapped the wrong package. Then nothing on disk is worth keeping, and starting over is /pd:reset <n>, which forgets this issue and no other. Do not do it silently: it is the user's call, and the pull request it will not close is theirs to think about.

1. Read, and dedup before anything else

pdkit issue fetch <n> prints the issue and every pull request that references it, in any state. The body is whole; of the comments, the newest fifteen, with a line saying how many earlier ones were left out. If the answer seems to hang on something said early in the thread, --full prints them all.

Act on that before analyzing anything:

  • an open PR → the work exists. Report it and stop. Duplicating it is the most expensive possible outcome.
  • a merged PR plus a revert → route redo, and the archaeology comes first. See section 5a: this is not a normal triage with extra reading.
  • a closed PR without a merge → read why it was closed. A maintainer who rejected the approach once will reject it again.

2. Locate, do not read

Two or three pd-scout agents in parallel, different questions each: where the behavior lives, what already exists that resembles the fix, how that area is tested. They return a map, ≤ 40 lines, every claim carrying file:line.

Do not read the code broadly yourself. The compression is the point — if you read what the scouts read, you have paid twice for one answer.

pdkit packages --of <path> turns a path into its package and layer.

3. Classify

Nature: bug, feature, enhancement, tech-debt, dep-bump, docs.

Size: trivial only when all of these hold — estimated diff ≤ 20 lines, ≤ 3 files, nothing under packages/extension-api, no schema change, no new dependency. Anything else is standard or larger.

4. Draft the requirements, with a source tag on every line

  • [issue] — stated in the issue, in its words
  • [paraphrase] — the same thing, reworded
  • [inferred] — you concluded it
  • [operator] — stated in the prior context that came with the command

Read the [inferred] list back to the user before writing anything to disk. Show it on its own, not buried in a summary. This is the cheap defense against requirements the plugin invented, and it only works if the list is short enough to actually read — if it is long, that is itself the finding.

Allocate with pdkit ids requirement <n> once the set is agreed. Not on the quickfix route: it allocates nothing there, and the CLI refuses if you try.

5. Verdict

State one route explicitly:

RouteWhen
quickfixtrivial by the thresholds above, and the fix is describable in one sentence
standardeverything ordinary
multi-slicethe change spans layers that different reviewers own
redoa previous attempt was reverted
invalidduplicate, already fixed, or not reproducible

invalid is a result, not a failure. Its output is a draft comment for the issue. Do not post it — publishing to someone else's tracker is a human action, and the gate refuses it anyway.

A valid, reproducible bug whose cause is outside this repository is not invalid. It is an ordinary route until the investigation says otherwise, and what changes is where it ends: the state answered, and a findings artefact instead of a diff. Do not decide this at triage: a report can read as a plain bug while the version skew behind it only appears once someone has built the machine and run the pull. Section 5b is where that lands.

5b. When the answer turns out not to be a diff

Some issues are real, reproducible, and not ours to fix in code: the cause sits in a dependency, in the host, or across a version boundary the product only drives. The deliverable is then a reproduction, a way to tell this problem from the ones it resembles, and a workaround — published as a comment.

The machine has a state for it, and it is guarded by the same rule as PASS:

pdkit validate attach --issue <n> --title "<what this step shows>" --run "<command>"
pdkit findings new --issue <n> --values <file.json>
pdkit state <n> --to answered --reason "<what the answer is>"

Three things this route asks that are easy to skip:

  1. Run the workaround, do not reason it out. answered is refused while nothing is captured, and that refusal is the point: a workaround nobody executed is a suggestion, and a suggestion posted in the voice of a finding costs the reporter their evening.
  2. Give them a detector. One command whose output separates this problem from its look-alikes. Without it, every reader with a similar symptom runs the workaround and half of them are fixing something else.
  3. Answer the product question. An environmental cause is a reason not to change this repository — not a reason for the repository to say nothing. If the client and the machine run different versions and Podman Desktop shows both without a word, name that, and whether it should be its own issue.

answered is not the end. It means the findings are out and the reporter has not spoken; from there the issue is resolved when someone confirms, back to planned if the answer implied product work, or abandoned if it goes quiet. Closing it on our own say-so would make the plugin the judge of whether someone else's problem went away.

5a. On the redo route only

Work that was landed and backed out is not ordinary work with more history attached. The reason it was reverted is a requirement, and it was written down at the time — rediscovering it by re-implementing is what this route exists to prevent.

pdkit issue history <n>

One call brings back the attempt, the pull request that reverted it, how long it lived in the base branch, what reviewers said, what merged in those files afterwards, and what could not be established. It writes archaeology.json, and pdkit refuses to leave triaged on this route until that file exists — not as ceremony: the ordering in scenario 10 is the whole point of the route, and an ordering held by a sentence in a prompt is an ordering.

Then dispatch pd-archaeologist with the issue number. It reads the facts and answers what they cannot: why it was reverted, what reviewers objected to, whether that objection still applies, and what this attempt has to do differently. Its report goes in archaeology.md.

Two things to carry into the requirements, and they are easy to lose:

  • The regression is a requirement too. Whatever the revert was filed against belongs in the R-set alongside the original ask, or the redo lands and is reverted for the same reason.
  • A blocking objection to the approach means the plan is different, not longer. If a reviewer said "this seems really hacky, it should not be merged", re-submitting the same approach with better tests is a slower way to be reverted again.

6. Record

Render ${CLAUDE_PLUGIN_ROOT}/templates/issue.md with pdkit render issue --issue <n> --values <f> --path issue.md, then pdkit state <n> --to triaged --route <route> --reason "<verdict, and whether prior context was given>".

Read ## Prior context back before rendering, the way section 4 reads the [inferred] list back. The render refuses without the section — render(issue): nothing given for {{priorContext}} — but nothing can check that what it holds is what you were told, and the moment to catch a dropped half is while it is still cheap. Show it as it will be written, not as a summary of it.

Say in the --reason whether context came with the command. That line reaches the journal, which pdkit issue rework and pdkit reset both leave alone — so it is what survives when issue.md is rendered a second time over the first.

The route is recorded there, not implied: standard, quickfix, multi-slice or redo. invalid is not a route — an issue that should not be worked on goes to pdkit state <n> --to abandoned with the reason, and the draft comment stays for a human to post.

When the phase runs long

budget.turns.triage is the ceiling for this phase, in turns. It is rough, and it has to be: you cannot count your own turns precisely, and nothing in the plugin counts them for you. Well past it, stop rather than finish — say what is settled and what is not, and ask for a restart. Whatever you would have carried over goes into the first message of the new triage, below the issue number, where section 0a puts it into ## Prior context verbatim.

Next

/pd:plan <issue> — or /pd:quickfix <issue> when the route is quickfix. The route decides which, and taking a quickfix into planning is what escalate exists to undo.

In a new session. Close this one first. Context is re-read whole on every call, so the duplicates weighed here, the files located and the issue thread would be paid for again on every turn of a phase that reads issue.md instead. What the conversation held and the file did not is what ## Prior context was for, and it has been written. pdkit next <issue> prints the line to run.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.