| 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. |
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+Claude context: Claude 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):
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:
needs-triage — never evaluated, oldest first
needs-info — blocked on user input, oldest first
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:
- Which payment gateway? (Stripe, Adyen, …)
- 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 — Sync the wiki
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)
## 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)
## 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:
---
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:
# <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.
- Always sync the wiki (
kmd sync) after frontmatter changes.
- 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.