| name | deft-directive-triage |
| description | Triage-cache hygiene and "what's next?" work selection (ordered plan or ranked queue) -- the agent-facing playbook for syncing the triage cache, classifying candidates, presenting a ranked queue or binding to an active plan-sequence, walking per-item decisions (accept / reject / defer / needs-ac / mark-duplicate), and auditing the session. Use when the operator asks what to work on next, wants to build a cohort, work the cache, or run a triage hygiene pass. |
| triggers | ["triage","triage hygiene","work the cache","what's next","whats next","what should I work on","queue","build a cohort","build cohort"] |
Deft Directive Triage
Triage-cache hygiene + "what's next?" work selection (ordered plan or ranked queue). Operates against the unified .deft-cache/github-issue/ mirror (#883 Story 2) and the append-only xbrief/.eval/candidates.jsonl audit log (#845 Story 2); writes only via the canonical task triage:* verbs.
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
Platform Requirements
! Requires GitHub as the SCM platform and the GitHub CLI (gh) authenticated against the active project's repo -- the cache surface (task cache:fetch-all) and the read-side gate (task verify:cache-fresh) both depend on it.
Deterministic Questions Contract
! Every numbered-menu prompt rendered in this skill (Phase 2 candidate selection, Phase 3 per-item decision walk) ! MUST follow ../../contracts/deterministic-questions.md: render the canonical numbered menu in chat unless the host UI visibly preserves numeric option labels and returns numeric selections or exact displayed option text. The final two numbered options are Discuss and Back, in that order, and the Discuss-pause semantic from the contract applies verbatim -- on Discuss the agent halts the in-progress sequence and resumes only on an explicit user signal.
Work selection fork (#2542 / #2402)
Directive does not guess your mix: ordered plan (task plan-sequence:*) when you know the next units in order, or ranked queue (task triage:queue) when picking from the backlog. Labels bias the queue; they do not override an active plan.
! Before Phase 2 on bare "what's next?", run task plan-sequence:current. Active sequence → that entry only; exhausted → fail closed. Explicit "what's the queue?" / "build a cohort" → Phase 2. See commands.md § Backlog Triage → Two paths.
Phase 0 -- Sync
! Probe cache freshness before doing any classification or selection. Stale cache reads produce stale decisions; the gate is the contract.
- ! Run
task verify:cache-fresh (D5 / #1127). Exit 0 -> proceed to Phase 1. Exit 1 (stale or blocked) -> refresh per the printed remediation. Exit 2 (no bootstrap) -> run task triage:bootstrap first. When the cache has zero entries, read paths auto-fetch from GitHub first (#2575).
- ~ Refresh path:
task cache:fetch-all -- --source=github-issue --repo OWNER/NAME for an already-bootstrapped project (idempotent, TTL-aware, re-applies the #883 scanner v2 quarantine rules); task triage:bootstrap for a first-time seed.
- ~ If
xbrief/active/*.xbrief.json references are in play, run task triage:refresh-active to compare cached meta.json.fetched_at against live upstream updatedAt and surface drift before the queue is rendered.
- ~ When the one-liner emitted by the session-start ritual carries a
[scope-drift] N segment (D14 / #1133), run task triage:scope-drift to see the per-label / per-milestone breakdown of upstream signals on cached open issues that fall outside the active plan.policy.triageScope[] subscription. The output documents both opt-in (task triage:subscribe -- --label=<L>) and opt-out (task triage:scope-drift -- --ignore-label=<L>) paths -- pick one before walking the queue so the cohort reflects the operator's current intent rather than a stale subscription.
- ⊗ Walk the queue against a stale cache -- the audit log will record decisions against bodies the operator never actually saw.
Phase 1 -- Classify
! Inspect the auto-classification audit log so manually-decided items are not re-walked, and surface anomalies before the queue render.
- ! Run
task triage:classify --list (D10 / #1129) to render the effective universal + consumer auto-classification rules and the active hold-marker list.
- ! Walk recent entries in
xbrief/.eval/candidates.jsonl for anomalies: classifier disagreements against the operator's prior decisions, repeated defer cycles on the same issue, or needs-ac records older than the freshness window. Surface anomalies to the operator before Phase 2; do NOT auto-fix.
- ~ When the operator wants to widen / narrow the corpus, consult
task triage:scope --list (D12 / #1131) to see the active plan.policy.triageScope[] subscription. Subscription edits belong in PROJECT-DEFINITION.xbrief.json, not in this skill.
- ~ Issue-label hygiene: labels feed triage queue ranking, issue gauges, hygiene sweeps, and lifecycle reconciliation. When this skill exposes an unlabeled issue or a downstream issue-creation step, recommend choosing one or more suitable labels from the repository's existing label set via
gh label list or the labels API, or explicitly note that no label was applied. This is a recommendation, not a gate.
- ⊗ Re-classify items already terminally decided (accept / reject / mark-duplicate) without explicit operator approval -- the audit log is append-only and supersession runs through Layer 5 (
task triage:reset <N>), not through silent re-walks.
- ⊗ Block issue creation solely because no label was selected, or invent ad hoc labels outside the repository's existing label set.
Phase 2 -- Present
! Apply the Work selection fork gate (#2542): when no ordered-plan is active, render task triage:queue before suggesting work (#1149). Active sequence yields to the ordered-plan entry (#2402).
- ! Run
task triage:queue --limit=N (D11 / #1128) -- default N=10 per the umbrella Current Shape v3 WIP cap. Output is grouped [RESUME] -> [URGENT] -> untriaged -> other; within-group ordering follows the consumer-supplied plan.policy.triageRankingLabels[] (framework default empty per §12 boundary), tiebroken by updated_at descending.
- ! For per-item detail, run
task triage:show <N> -- prints the cached upstream payload, the latest triage decision, the audit timeline, and the active-xBRIEF reference flag. Exit 0 on hit, 1 on cache miss (re-sync per Phase 0).
- ~ Present the ranked queue verbatim; do NOT silently re-rank, drop, or annotate beyond what the canonical renderer emits. If the operator wants a different ordering they edit
plan.policy.triageRankingLabels[] and re-run.
- ⊗ Recommend a specific issue without consulting
task triage:queue first, or recommend an issue absent from the queue without first running task triage:show to surface why (cache miss / outside subscription / terminal decision).
Phase 3 -- Decide
! Walk per-item decisions through the canonical task triage:* verbs. The skill does NOT reimplement the audit-log append, schema validation, or xbrief/proposed/ write inline -- the tasks are the canonical implementation (mirrors the #537 ingest-task discipline).
For each candidate the operator selects from the Phase 2 queue, render the canonical numbered action menu and dispatch the matching verb:
What would you like to do with this candidate?
1. Accept -- `task triage:accept <N>` (writes proposed/ xBRIEF + audit-log entry)
2. Reject -- `task triage:reject <N>` (audit-log entry only; terminal)
3. Defer -- `task triage:defer <N> [--resume-on <event>]` (non-terminal; resurfaces)
4. Needs-AC -- `task triage:needs-ac <N>` (non-terminal; flags missing acceptance criteria)
5. Mark duplicate -- `task triage:mark-duplicate <N> <of-issue>` (terminal; cross-links target)
6. Discuss
7. Back
- !
--resume-on <event> on task triage:defer (D3 / #1123 -- ships in parallel; reference but do not hard-depend) records a resume condition with the defer entry; the resume condition surfaces in task triage:queue once met. When D3 has not landed yet, omit the flag -- the verb stays terminal-shape-compatible.
- ! Map user replies only to the displayed number (
1-7) or exact displayed option text. ⊗ Do NOT infer from alphabetic host affordances or bare letters such as d / b unless those letters were visibly rendered as choices.
- ! On
Discuss, halt the action sequence immediately, prompt What would you like to discuss?, and resume only on an explicit user signal. ⊗ Implicit resumption.
- ! On
Back, un-buffer the prior candidate's selection and re-render its action menu -- permitted only before the action has dispatched to a task triage:* command. Once dispatched, the audit entry is committed; revisions go through Layer 5 (task triage:reset).
- ~ Bulk patterns:
task triage:bulk-{accept,reject,defer,needs-ac} (#845 Story 4) for clear label-driven sweeps; bulk results still flow through the audit log so history stays coherent.
- ⊗ Write to
xbrief/proposed/ directly -- only task triage:accept (which delegates to task issue:ingest) is authorised for that surface.
Phase 4 -- Audit
! Confirm the session's decisions landed coherently before exiting the skill.
- ! Run
task triage:audit --format=json (D11 / #1128) -- emits the stable {generated_at, repo, vbrief_staleness, entry_count, entries: [...]} schema; pipe through jq to surface this session's appended entries. For historical look-back, add the #1180 filters: task triage:audit --since=30d --action=demote --format=json | jq answers "how many demotes in the last 30 days?" in one call. --since=<window> accepts the framework duration grammar (Nd / Nh / Nm / Nw / Ns or ISO-8601 PnDTnHnMnS); --action=<verb> filters to a single decision verb (accept / reject / defer / needs-ac / mark-duplicate / reset / resume-eligible). Both filters compose with --format=text and --format=json. The framework deliberately does NOT compute trend lines or apply falsification gates -- the contract is read raw, transform with jq.
- ! Run
task triage:summary (D2 / #1122) -- prints the canonical one-liner [triage] N untriaged · S stale-defer · M in-flight · WIP X/Y [⚠] [· [scope-drift] N]. The WIP cap default is 20 per #2319, raised from the original 10 per the umbrella Current Shape v3 (overridable via typed plan.policy.wipCap). The ⚠ glyph fires only at-or-above cap. The [scope-drift] N segment (D14 / #1133) appears only when at least one unsubscribed label/milestone meets the framework _DRIFT_MIN_ISSUES = 3 threshold; suppressed at zero.
- ~ When the summary surfaces a non-zero
[scope-drift] N (D14 / #1133), surface it to the operator alongside task triage:scope-drift output and the matching task triage:subscribe / task triage:unsubscribe / task triage:scope-drift -- --ignore-label=<L> remediation. Subscription mutations record a subscription-change audit entry under xbrief/.eval/subscription-history.jsonl (sidecar of the existing candidates.jsonl audit surface) so future operators can replay how the subscription evolved. After every mutation, run task triage:bootstrap -- --resume to backfill newly-subscribed entries / mark newly-out-of-scope entries.
- ~ When the audit surfaces a stale acceptance (
accept decision whose issue is no longer referenced by any xbrief/active/), surface it to the operator -- the typical fix is a fresh ingest via task issue:ingest -- <N> or a task triage:reset <N> if the acceptance was in error.
- ⊗ Skip the Phase 4 audit -- silent exit leaves the operator without a record of what landed in
xbrief/proposed/ this session, which is the typical recurrence vector for "what did I just accept?" confusion.
! Before reporting an umbrella or epic's current status during triage (what is done, what blocks, wave order), fetch repos/<owner>/<repo>/issues/<N>/comments via REST, read the ## Current shape (as of pass-N) comment and any linked context/LockedDecisions xBRIEF — never conclude status from the issue body alone (claim-cites-state-surface, #2066 / AGENTS.md #1152).
Reversibility
! To undo a decision, run task triage:reset <N>. This writes a reset audit entry referencing the prior decision id; history is never deleted. task triage:reset is the canonical Layer 5 reversibility verb (resolves the V3 audit from 2026-05-13). After a reset, the candidate re-enters the untriaged group on the next task triage:queue render so it can be re-walked through Phase 3.
⊗ Edit or delete prior entries in xbrief/.eval/candidates.jsonl to "undo" a decision -- the log is append-only by design and any external mutation breaks the merge=union rebase ergonomic (#1144 / N4).
Anti-Patterns
- ⊗ Recommend a specific issue without first consulting
task triage:queue (binding under AGENTS.md ## Cache-as-authoritative work selection (#1149)).
- ⊗ Conclude "nothing to do" from
xbrief/{pending,active} scans or live GitHub reads alone — task triage:queue is the ranked superset (#2576).
- ⊗ Walk the queue against a stale cache (Phase 0 gate skipped).
- ⊗ Reimplement audit-log append /
proposed/ write inline -- the task triage:* verbs own those surfaces (#845, #883).
- ⊗ Treat
defer / needs-ac as terminal -- they intentionally resurface on the next pass.
- ⊗ Edit
xbrief/.eval/candidates.jsonl directly to revoke a decision -- use task triage:reset <N>.
EXIT
! When the operator opts out (queue exhausted, mid-session stop, or explicit "done"), confirm skill exit with the canonical phrasing: deft-directive-triage complete -- exiting skill.
! Provide chaining instructions:
- Ingestion / evaluation of accepted items: chain into
skills/deft-directive-refinement/SKILL.md -- refinement's Phase 1 ingests the xbrief/proposed/ items this skill just wrote into the rest of the lifecycle.
- Cohort dispatch: chain into
skills/deft-directive-swarm/SKILL.md -- swarm Phase 0 is queue-driven (N2 / #1142) and consumes the same task triage:queue ordering you just walked.
- Fresh-state refresh before re-entry: run
task cache:fetch-all -- --source=github-issue --repo OWNER/NAME then re-enter this skill when ready to continue.
⊗ Exit silently without the canonical confirmation + chaining instruction -- the Skill Completion Gate in AGENTS.md is binding.
References
- Umbrella: #1119 (Wave-1 D6, this skill)
- D2 #1122 (
task triage:summary), D3 #1123 (--resume-on, parallel), D5 #1127 (task verify:cache-fresh), D10 #1129 (auto-classification), D11 #1128 (task triage:queue / triage:show / triage:audit), D12 #1131 (subscription scope)
- Layer 5 reversibility verb:
scripts/triage_actions.py::reset (already shipped under #845)
- Sibling skills:
skills/deft-directive-refinement/SKILL.md, skills/deft-directive-swarm/SKILL.md, skills/deft-directive-sync/SKILL.md
- Stub author (replaced): #1149 (N9)