diff --git a/plugins/work-items/.claude-plugin/plugin.json b/plugins/work-items/.claude-plugin/plugin.json index 02efba761..38f923635 100644 --- a/plugins/work-items/.claude-plugin/plugin.json +++ b/plugins/work-items/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "work-items", - "version": "0.18.0", + "version": "0.18.1", "description": "Manages development work items through a provider-neutral tracker seam that ships with the plugin (bundled dispatcher plus github and local-markdown adapters; seam plugin-dir canonical, adapters consumer-local-first): dashboard, taxonomy-labeled creation, a race-safe assignee-plus-lease claim protocol, recurring-schedule checks, TODO scanning, stale-lease auditing, plan decomposition into vertical-slice items, and raw-intake triage (issues and unsolicited PRs through raw, verified, briefed, autonomous-eligible states). The re-runnable setup skill binds the provider (.work-item-tracker.json), seeds the recurring-schedule seam (.github/recurring-schedule.json), and remaps canonical role labels.", "author": { "name": "Melodic Software", diff --git a/plugins/work-items/CHANGELOG.md b/plugins/work-items/CHANGELOG.md index ce9d1dbe9..a2eda36ec 100644 --- a/plugins/work-items/CHANGELOG.md +++ b/plugins/work-items/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to the `work-items` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.18.1] + +### Changed + +- **`triage` scope now keys on triage state, not authorship (`#486`).** The "Scope: raw intake + only" section, the Purpose, and the frontmatter `description` defined raw intake as "items the + team did not author," which contradicted the plugin's own self-observation filing contract: dogfood + issues the team files carry only the raw marker, surface in the same attention view, and genuinely + need triage. Raw intake is now defined as *any untriaged item carrying the raw marker, whoever + authored it*; the "did not author" phrasing is demoted to an illustrative list of common sources. + The paired exclusion is re-keyed too — "never re-triage already-triaged output" now turns on + absence of the raw marker (decompose output, or a `track add` that leaves no raw marker) rather than + `track add` authorship. The raw marker wins over coexisting default labels, so a team-authored dogfood + issue filed with a default `priority:` label *and* the raw marker is correctly in scope while + born-triaged items stay out. No routing-logic change. + ## [0.18.0] Extract the cross-lane self-observation filing rule ("file what you will not fix: dedupe → categorize diff --git a/plugins/work-items/skills/triage/SKILL.md b/plugins/work-items/skills/triage/SKILL.md index 7030b8aa2..c9d7d6b39 100644 --- a/plugins/work-items/skills/triage/SKILL.md +++ b/plugins/work-items/skills/triage/SKILL.md @@ -1,6 +1,6 @@ --- name: triage -description: "Evaluate raw intake — items the team did not author (bug reports, incoming feature requests, unsolicited PRs) — through a small state machine: raw → verified → briefed → autonomous-eligible, with side exits to needs-info, human-gated, and close. A PR is an item with attached code and enters the same intake as an issue. Use when: 'triage', 'what needs triage', 'triage this issue', 'triage this PR', 'evaluate this bug report', 'is this bug real', 'should we merge this unsolicited PR', 'attention view', 'what intake needs attention'. No number = attention view (untriaged intake). Sibling skills: /work-items:track (backlog CRUD), /work-items:work (auto-select + execute), /work-items:decompose (plan → tickets), /work-items:scan-todos (TODO sweep)." +description: "Evaluate raw intake — any untriaged item carrying the raw marker, whoever authored it (external bug reports, incoming feature requests, unsolicited PRs, and team-authored self-observation/dogfood issues) — through a small state machine: raw → verified → briefed → autonomous-eligible, with side exits to needs-info, human-gated, and close. A PR is an item with attached code and enters the same intake as an issue. Use when: 'triage', 'what needs triage', 'triage this issue', 'triage this PR', 'evaluate this bug report', 'is this bug real', 'should we merge this unsolicited PR', 'attention view', 'what intake needs attention'. No number = attention view (untriaged intake). Sibling skills: /work-items:track (backlog CRUD), /work-items:work (auto-select + execute), /work-items:decompose (plan → tickets), /work-items:scan-todos (TODO sweep)." argument-hint: "[] — issue OR pull request number to triage; empty = attention view" user-invocable: true disable-model-invocation: false @@ -21,7 +21,7 @@ closes route through the bound adapter's write mechanics; item creation goes thr ## Purpose -Evaluate **raw intake** — items the team did not author (bug reports, incoming feature requests, unsolicited PRs) — through a small state machine: raw → verified → briefed → autonomous-eligible, with side exits to needs-info, human-gated, and close. +Evaluate **raw intake** — any untriaged item carrying the raw marker, whoever authored it (external bug reports, incoming feature requests, unsolicited PRs, and team-authored self-observation/dogfood issues) — through a small state machine: raw → verified → briefed → autonomous-eligible, with side exits to needs-info, human-gated, and close. ## Usage @@ -32,10 +32,12 @@ Evaluate **raw intake** — items the team did not author (bug reports, incoming ## Scope: raw intake only +**Raw intake is defined by triage state, not authorship.** An item is raw intake when it is untriaged — unlabeled, or carrying the raw marker (`status:needs-triage` / `priority:needs-triage`, whichever axis the repo files it under) — regardless of who authored it. External bug reports, incoming feature requests, and unsolicited PRs are the common sources, but a **team-authored self-observation / dogfood issue** filed with only the raw marker ([`${CLAUDE_PLUGIN_ROOT}/reference/dogfood-filing.md`](${CLAUDE_PLUGIN_ROOT}/reference/dogfood-filing.md)) is raw intake too: it carries no routing decision yet, surfaces in the same attention view, and needs the same evaluation (priority normalization, tier routing, brief drafting). The boundary is *untriaged vs. already-triaged*, never *external vs. team-authored*. + Two rules bound what enters this flow: - **A PR is an item with attached code.** An unsolicited or external PR enters the same intake as an issue: same states, same machine. Its diff is an **attachment to evaluate** — check it out, run the relevant tests — never an obligation to merge. Read the state names against the code: briefed means a brief exists for what to do with the diff; human-gated means a human should decide the merge. -- **Never re-triage `decompose` output.** Items published by `/work-items:decompose` (and team-authored `/work-items:track add` items) are born triaged — classified, role-labeled, and briefed at creation. They never re-enter this flow, and the attention view excludes them by construction (they carry labels from birth). If someone names one explicitly, say it is already triaged and stop. +- **Never re-triage already-triaged output.** Items born triaged — published by `/work-items:decompose`, or created by a `/work-items:track add` that leaves no raw marker — already carry a routing decision. They never re-enter this flow, and the attention view excludes them by construction (being neither unlabeled nor marked with the raw marker, they fall in none of its buckets). This exclusion keys on **absence of the raw marker**, not authorship and not the mere presence of classification labels: the raw marker (`status:needs-triage`, or being unlabeled) puts an item in scope even alongside default labels, so a team-authored dogfood issue filed with a default `priority:` label *and* the raw marker is in scope (the marker wins), while a `track add` item that carries classification labels but no raw marker is out of scope for the same reason decompose output is. If someone names an already-triaged item explicitly, say it is already triaged and stop. ## Triage states diff --git a/plugins/work-items/skills/triage/evals/evals.json b/plugins/work-items/skills/triage/evals/evals.json index 0078822fe..257f4d3c8 100644 --- a/plugins/work-items/skills/triage/evals/evals.json +++ b/plugins/work-items/skills/triage/evals/evals.json @@ -33,13 +33,13 @@ "id": 3, "name": "triage-never-reprocesses-decompose-output", "prompt": "/work-items:triage 53 — #53 was created last week by /work-items:decompose from our approved PLAN.md", - "expected_output": "Declines to re-triage: items published by decompose are born triaged — classified, role-labeled, and briefed at creation — and never re-enter the intake flow. Explains that triage covers raw intake only (items the team did not author) and points at the item's existing role label/brief instead of re-running the state machine.", + "expected_output": "Declines to re-triage: items published by decompose are born triaged — classified, role-labeled, and briefed at creation, leaving no raw marker — and never re-enter the intake flow. Explains that triage covers raw intake only (untriaged items carrying the raw marker, regardless of authorship) and that the exclusion keys on absence of the raw marker, then points at the item's existing role label/brief instead of re-running the state machine.", "files": [], "expectations": [ "Does NOT re-run the triage state machine on a decompose-published item — such items are born triaged (classified, role-labeled, briefed at creation)", - "States the exclusion rule: triage covers raw intake only — items the team did not author", + "States the exclusion rule: triage covers raw intake only — untriaged items carrying the raw marker; the exclusion keys on absence of the raw marker (born triaged), not authorship and not the mere presence of classification labels", "Performs no triage writes on the item — no label changes, no needs-info comment, no close", - "Notes the attention view excludes decompose output by construction (born-labeled items never land in the unlabeled or needs-triage buckets)" + "Notes the attention view excludes decompose output by construction — it carries a routing decision and no raw marker, so being neither unlabeled nor raw-marked it falls in none of the view's buckets" ] }, {