Skip to main content

triage

Move user-story files in the wiki through a triage state machine (`needs-triage` → `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`). Reads and writes `triage_state` and `category` in story frontmatter. Recommends transitions, grills (chains to `$grill-with-docs`) when story bodies are too thin, posts agent briefs for `ready-for-agent`, and writes `adr-no-{slug}.md` when rejecting an enhancement. In `github`/`gitlab` mode also mirrors state to remote labels. Use when the user says "$triage", "what needs my attention", "triage the new stories", "move story X to ready-for-agent", "evaluate the cart story", or similar.

Jump to install

Source facts

Repository
bartolli/kmd
Last source activity
August 11, 2026 at 01:48
Detected SKILL.md language
English
Stars
7
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
triage
description
Move user-story files in the wiki through a triage state machine (`needs-triage` → `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`). Reads and writes `triage_state` and `category` in story frontmatter. Recommends transitions, grills (chains to `$grill-with-docs`) when story bodies are too thin, posts agent briefs for `ready-for-agent`, and writes `adr-no-{slug}.md` when rejecting an enhancement. In `github`/`gitlab` mode also mirrors state to remote labels. Use when the user says "$triage", "what needs my attention", "triage the new stories", "move story X to ready-for-agent", "evaluate the cart story", or similar.
metadata
{"version":"0.16.1"}
# Triage — Move Stories Through the State Machine A small state machine over wiki story files. Lifts Matt Pocock's triage pedagogy onto the wiki's `kind: story` artifact. ## Prerequisites - `WIKI_SCOPE: <scope>` declared in the project instructions. If missing, suggest `$wiki`. - At least one story file exists under `projects/<scope>/plan/<plan-name>/`. If none, suggest `$to-prd`. ## Roles Two **category** roles (story has exactly one): - `bug` — something is broken - `enhancement` — new feature or improvement Five **state** roles (story has exactly one, lives in `triage_state` frontmatter): - `needs-triage` — story needs evaluation - `needs-info` — agent waits on user clarification (in solo+Codex context: Codex is blocked on a user decision) - `ready-for-agent` — fully specified, AFK-ready (an agent can pick it up with no human context) - `ready-for-human` — needs human implementation (judgment, external access, hardware, design review) - `wontfix` — will not be actioned State transitions: an unlabeled or `needs-triage` story moves to `needs-info`, `ready-for-agent`, `ready-for-human`, or `wontfix`. `needs-info` returns to `needs-triage` once the user provides the missing input. The user can override at any time — flag transitions that look unusual and confirm before proceeding. ## AI disclaimer (GH/GitLab mode only) When `WIKI_ISSUE_TRACKER` is `github` or `gitlab`, every comment posted to the remote tracker during triage **must** start with: ``` > *This was generated by AI during triage.* ``` In `local` mode, no remote comments are posted; the disclaimer doesn't apply. ## Invocation patterns The user invokes `$triage` and describes what they want in natural language. Examples: - *"Show me anything that needs my attention"* → bucket view - *"Let's look at story 2 of plan-billing-mvp"* → triage a specific story - *"Move story 3 to ready-for-agent"* → quick state override - *"What's ready for agents to pick up?"* → filtered view ## Pattern A — Show what needs attention Query the wiki index for stories in actionable states. Present three buckets, oldest first. Query (via the `wiki` MCP `search` tool): ```sql SELECT path, title, scope, meta->>'triage_state' AS state, meta->>'category' AS category, updated FROM pages WHERE kind = 'story' AND scope = '<scope>' AND meta->>'triage_state' IN ('needs-triage', 'needs-info') ORDER BY meta->>'triage_state', updated; ``` Bucket the results: 1. **`needs-triage`** — never evaluated, oldest first 2. **`needs-info`** — blocked on user input, oldest first 3. **`ready-for-agent`** — concrete count + one-line summary per story (so user sees the AFK queue) Show counts and a one-line summary per story. Let the user pick. ## Pattern B — Triage a specific story ### Step 1 — Gather context - Read the full story file (frontmatter + body). - Read the parent `plan/plan-{name}.md` for context. - Read `spec-context.md` for vocabulary. - Read any wikilinked specs/ADRs the story references. - Check existing `adr-no-*.md` files in the scope — if a similar enhancement was previously rejected, surface it. (This is the wiki-native equivalent of Matt's `.out-of-scope/` knowledge base.) - If the story is `bug` category, attempt reproduction: trace the relevant code, run tests if needed. ### Step 2 — Recommend Tell the user your category and state recommendation with reasoning. Wait for direction. Format: > "**Recommendation: `category: enhancement`, `triage_state: needs-info`.** > > Reasoning: > - Acceptance criteria are clear (3 scenarios). > - But Slice 2 references a payment-gateway integration that isn't specified anywhere — needs an ADR or a spec stub before this can be AFK. > > Specifically I need from you: > 1. Which payment gateway? (Stripe, Adyen, …) > 2. Are we using their hosted form or building our own? > > Confirm and I'll update the story frontmatter and post triage notes." ### Step 3 — Reproduce (bugs only) For `bug` stories, attempt repro before grilling. Read the reporter's steps, trace the relevant code, run tests or commands. Report what happened: - **Successful repro with code path** — strong signal toward `ready-for-agent` or `ready-for-human` - **Failed repro** — strong `needs-info` signal - **Insufficient detail** — strong `needs-info` signal A confirmed repro makes a much stronger agent brief. ### Step 4 — Grill (if needed) If the story body is too thin for `ready-for-agent`, chain into `$grill-with-docs` to flesh it out. Don't try to grill within `$triage` — separation of concerns. ### Step 5 — Apply the outcome **`ready-for-agent`:** - Verify scenarios are concrete (Given/When/Then, not free-form). - Verify slices are vertical (each cuts through every layer). - Verify `blocked_by:` is populated correctly (no missing dependencies). - Update frontmatter: `triage_state: ready-for-agent`. - Append an *agent brief* to the body (see template below) — short, durable, sufficient for an AFK agent to pick up cold. - In GH/GitLab mode: create a remote issue with the story body inlined and a wikilink back; apply the `ready-for-agent` label. **`ready-for-human`:** - Same brief structure as `ready-for-agent`. - Add a "Why human" section explaining what makes this non-AFK (judgment, external access, hardware, design decision, manual testing). - Update frontmatter: `triage_state: ready-for-human`. **`needs-info`:** - Update frontmatter: `triage_state: needs-info`. - Post triage notes to the body (see template below). - In GH/GitLab mode: comment on the remote issue with the same notes (with AI disclaimer). **`wontfix-bug`:** - Polite explanation in the body's `## Triage Notes` section. - Update frontmatter: `triage_state: wontfix`, `status: archived`. - In GH/GitLab mode: close the remote issue with the explanation. **`wontfix-enhancement`:** - Write `projects/<scope>/adr/adr-no-<slug>.md` capturing the rejection rationale (see template below). - Update story frontmatter: `triage_state: wontfix`, `status: archived`. - Add wikilink to the new ADR in the story body's `## Triage Notes`. - In GH/GitLab mode: close the remote issue with a link to the ADR. **`needs-triage`:** - Apply the role. Optional comment on partial progress. ### Step 6 — Update parent plan Update the Story Index table in `plan/plan-{name}.md` to reflect the new state column. Don't drift — the parent plan's table is canonical for the at-a-glance view. ### Step 7 — Update `updated:` field Bump the `updated:` field in the story's frontmatter. ### Step 8 — Confirm the resync Harnesses with the posttool hook validate and sync automatically. Check `kmd config`: if the `synced` line did not advance past your edits, the hook is not wired — run `kmd validate`, fix findings, then `kmd sync`. ## Pattern C — Quick state override If the user says "move story X to `ready-for-agent`", trust them. Confirm what you're about to do (frontmatter changes, comment, plan-table update), then act. Skip grilling. If moving to `ready-for-agent` without a grilling session, ask whether the body needs an agent brief appended. ## Templates ### Agent brief (append to story body when transitioning to `ready-for-agent` or `ready-for-human`) ```markdown ## Agent Brief **What to build:** <one-sentence description of the slice path> **Acceptance criteria** (lifted from scenarios above): - [ ] <criterion 1 — derived from Scenario 1> - [ ] <criterion 2 — derived from Scenario 2> **Relevant code paths:** - `<path/to/file.ts>` — <one line on what it does> **Out of scope:** - <bullet> **Definition of done:** - All scenarios pass as integration tests - `<plan/{name}/story-N>` slice checkboxes all ticked - No unresolved [[spec-X]] divergence ``` ### Triage notes (append when transitioning to `needs-info`) ```markdown ## Triage Notes **What we've established so far:** - <point 1> - <point 2> **What we still need from you:** - <specific actionable question 1> - <specific actionable question 2> ``` Capture everything resolved during triage under "established so far" so the work isn't lost. Questions must be specific and actionable, not "please provide more info". ### `adr-no-{slug}.md` (when rejecting an enhancement) Use `wiki://template/project/adr` with frontmatter: ```yaml --- title: "<Negative title — e.g., 'No multi-currency in v1'>" kind: adr scope: <scope> status: active summary: "Why <enhancement> was rejected from <plan-name>." tags: [out-of-scope, ...] supersedes: superseded_by: sources: - projects/<scope>/plan/<plan-name>/story-N-<slug>.md created: "<today>" updated: <today> --- ``` Body: ```markdown # <Title> ## Status active ## Context The story `[[story-N-<slug>]]` proposed <enhancement>. Triage rejected this for v1. ## Decision We will not <enhancement> in <plan-name>. ## Rationale - <reason 1> - <reason 2> ## Consequences What stays simple. What's deferred. Conditions under which we'd revisit. ## Reconsider when Specific signals that should re-open this decision (e.g., "if >5 customers ask for it", "if a related story emerges"). ``` ## Resuming a previous session If prior triage notes exist in a story body, read them, check whether the user has answered any outstanding questions, and present an updated picture before continuing. Don't re-ask resolved questions. ## Rules - **Every triaged story must carry exactly one category and one state.** If labels conflict, flag it and ask the user. - **Always show your recommendation with reasoning before transitioning.** Don't move state silently. - **For `wontfix-enhancement`, always write `adr-no-{slug}.md`.** Rejection without rationale loses institutional memory. - **Always update the parent plan's Story Index table** when state changes. - **Confirm the resync after frontmatter changes** — the posttool hook syncs automatically; if `kmd config`'s `synced` line did not advance, run `kmd validate` then `kmd sync`. - **In GH/GitLab mode, always lead remote comments with the AI disclaimer.** - **Never grill within `$triage`** — chain to `$grill-with-docs` if needed. - **Quote prose-bearing frontmatter scalars** to avoid breaking the sync walker.
View on GitHub