Skip to main content

triage

This skill should be used to move intents and user-story files through the wiki's triage state machine. Intents (`draft` → `active` / archived with `promoted_to`, `dismissed`, or `fixed_by`) are triaged first, ordered by sightings; stories move `needs-triage` → `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`. Reads and writes frontmatter, recommends transitions, promotes an intent into a story via the elaboration skill, dismisses with a recorded reason, writes `adr-no-{slug}.md` when rejecting an enhancement with design rationale, and in `github`/`gitlab` mode mirrors story state to remote labels. Use when the user says "$triage", "what needs my attention", "triage the intents", "what's in the intent queue", "promote intent X", "dismiss intent X", "triage the new stories", "move story X to ready-for-agent", or similar.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
bartolli/kmd
آخر نشاط في المصدر
٥ سبتمبر ٢٠٢٦ في ١٣:٤٨
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
triage
description
This skill should be used to move intents and user-story files through the wiki's triage state machine. Intents (`draft` → `active` / archived with `promoted_to`, `dismissed`, or `fixed_by`) are triaged first, ordered by sightings; stories move `needs-triage` → `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`. Reads and writes frontmatter, recommends transitions, promotes an intent into a story via the elaboration skill, dismisses with a recorded reason, writes `adr-no-{slug}.md` when rejecting an enhancement with design rationale, and in `github`/`gitlab` mode mirrors story state to remote labels. Use when the user says "$triage", "what needs my attention", "triage the intents", "what's in the intent queue", "promote intent X", "dismiss intent X", "triage the new stories", "move story X to ready-for-agent", or similar.
metadata
{"version":"0.21.2"}
# 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 intent under `projects/<scope>/intent/` or one story file under `projects/<scope>/plan/<plan-name>/`. With neither, suggest `$to-stories`. ## Roles Intents carry no triage labels; their state is `status` plus one outcome field ([[adr-intent-kind]]): - `draft` — filed, unread by triage - `active` — scheduled: accepted, story not yet written - `archived` with exactly one of `promoted_to` (story slug), `dismissed` (reason), `fixed_by` (regression test path) - `superseded` with `superseded_by` — merged into another intent, whose `sightings` absorbed the count Stories carry two label 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 a solo-operator context: the agent 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, intents first - *"Promote intent X"* / *"Dismiss intent X — it's covered by story Y"* → intent outcome - *"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 Read state from the vault filesystem, never from an index query: the index is disposable and the `search` tool returns ranked candidates, not frontmatter. - Intents: every `projects/<scope>/intent/intent-*.md`; read `status`, `sightings`, `origin`, `updated`. - Stories: every `projects/<scope>/plan/*/story-*.md`; read `triage_state`, `category`, `updated`, and the slice tick counts. - `search(query, scope, kind="intent")` (MCP) or `kmd search "<terms>" --scope <scope> --kind intent` (CLI) finds related candidates by content when a finding needs a twin check — the walk above is still the state source. Present the buckets in this order, each with counts and one line per item: 1. **Intents, `draft`** — ordered by `sightings` descending, then `updated` ascending. Two sightings, or a confirmed falsification, is the promotion threshold; flag those first. 2. **Intents, `active`** — scheduled and waiting for a story; oldest first. 3. **Stale AFK stories** — `triage_state: ready-for-agent`, `status: active`, zero ticked slices, and `updated` more than thirty days before the clock. Accepted work nobody started is the backlog's debt; it is offered three actions, never left in the queue by default: - **Demote** — `triage_state: needs-triage`, a Triage Notes line naming the age; the story re-enters evaluation. - **Dismiss** — `triage_state: wontfix`, `status: archived`, the reason in Triage Notes. A capacity call, not a design rejection: no `adr-no-*` unless the operator wants rationale on record. - **Keep** — the operator affirms it; `updated` moves from the clock and the story leaves the band for another thirty days. 4. **`needs-triage` stories** — never evaluated, oldest first. 5. **`needs-info` stories** — blocked on user input, oldest first. 6. **`ready-for-agent` stories** — count plus a one-line summary each, so the AFK queue is visible. 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 `glossary.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 `$intent` 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 Set the story's `updated:` from the clock — `date -u +%Y-%m-%dT%H:%M:%SZ`, quoted — never composed. ### 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. ## Pattern D — Triage an intent ### Step 1 — Gather context - Read the intent: the six sections, `origin`, `sightings`, the Falsification path. - Twin check across every status, archived included: `search` with `kind="intent"` on the intent's distinctive terms, then read the hits. A dismissed twin carries its reason in `dismissed` — surface it before recommending anything. - Read any story or spec the intent links; if a story already covers the finding, the outcome is dismiss with that story named. - If the Falsification path is cheap to run, run it and report the result. A confirmed path meets the promotion threshold on its own. ### Step 2 — Recommend One of three outcomes, with reasoning, then wait for direction: - **Promote** — `sightings` ≥ 2, or the falsification confirmed, or the operator calls it. The story gets written now. - **Hold** — worth doing, not yet; `status: active` marks it scheduled. - **Dismiss** — covered elsewhere, not worth the fix, or falsified. The reason is the record. ### Step 3 — Apply **Promote:** - Chain to the elaboration skill (`$to-stories`) with the intent as input: the story's problem, scenarios, and first slices derive from the intent's sections, under the active plan. - Intent frontmatter: `status: archived`, `promoted_to: <story slug>`, `updated` from the clock. - Parent plan: add the Story Index row. The new story's `triage_state` is whatever the operator chose at promotion — `ready-for-agent` when the brief is complete, `needs-triage` otherwise. **Hold:** - Intent frontmatter: `status: active`, `updated` from the clock. Nothing else moves. **Dismiss:** - Intent frontmatter: `status: archived`, `dismissed: "<one-line reason>"`, `updated` from the clock. - No ADR unless the operator wants design rationale on record; then `adr-no-<slug>.md` as for a rejected enhancement, linked from `dismissed`. **Merge** (two intents for one finding): - The later one: `status: superseded`, `superseded_by: <survivor slug>`. The survivor's `sightings` absorbs the count and its `updated` moves. ### Step 4 — Confirm the resync As for stories: the posttool hook validates and syncs; if `kmd config`'s `synced` line did not advance, run `kmd validate` then `kmd sync`. ## 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` (MCP resource, or `kmd resource <uri>`) 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 - **Intents before stories.** The intent queue is the loop's entry; a session that triages stories while draft intents wait is working the wrong end. - **An archived intent carries exactly one outcome field** — `promoted_to`, `dismissed`, or `fixed_by`. A dismissal without a reason is not a dismissal. - **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` on design grounds, always write `adr-no-{slug}.md`.** Rejection without rationale loses institutional memory. A stale-band dismissal is a capacity call and records its reason in Triage Notes instead. - **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 `$intent` if needed. - **Quote prose-bearing frontmatter scalars** to avoid breaking the sync walker.
عرض على GitHub