Debt triage
EM-PM conversation to review and prioritize the technical debt backlog. Triggers on demand or when open item count exceeds 20.From its SKILL.md
npx -y skills add dbc-oduffy/coordinator-claude --skill debt-triageAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
14.1 KB, ~3.4k tokens by cl100k_base, as published. Nobody here has run it
Debt Triage — Backlog Review and Prioritization
Overview
Review the debt backlog, verify items are still relevant, re-prioritize based on current state, close resolved items, and present recommendations to the PM.
Announce at start: "I'm using the coordinator:debt-triage skill to review the debt backlog."
When to Trigger
- On demand (PM or EM invocation)
- When debt backlog exceeds 20 open items (surfaced by weekly-architecture-audit with escalating insistence — mild concern at >20, visible the Staff Engineer disappointment at >30, coffee-down intervention at >40 — and by workstream-start)
- After a major refactor that may have resolved multiple debt items
The Process
This is an EM-PM conversation, not a dispatched agent. The EM reads the backlog, applies judgment, and presents recommendations.
Step 0: Surface Prior Rejections
Before reading the backlog, check tasks/out-of-scope/*.md (if the directory exists — skip silently if absent). For each file present, note the concept and rejection reason. During triage, when any incoming item or discussion overlaps a known rejection, surface it:
"This is similar to
tasks/out-of-scope/<concept>.md— we rejected this because [reason]. Still feel the same?"
The maintainer can:
- Confirm — append the new instance under "Prior requests" in the file
- Reconsider — delete the file and proceed to evaluate normally
- Override — proceed with implementation despite the prior rejection
Step 1: Read Current State
- Read
state/debt-backlog/entries viabin/query-records.js --type debt(each entry is an individual YAML file withseverity,status, and related frontmatter fields perdocs/wiki/debt-backlog-schema.md— identity key is the filename<date>-<slug>.yaml— noid:field)
- Summarize: total open items, breakdown by severity (P0/P1/P2), breakdown by system
- Identify the oldest open items (stalest debt)
Step 1b: Cross-reference bug backlog
Also read state/bug-backlog/*.yaml via bin/query-records.js --type bug (each entry is a YAML file with severity, status, etc. as frontmatter — identity key is the filename <date>-<slug>.yaml — no id: field).
Pre-Dispatch: Verify Backlog Against Current Code (example-repo T1.1, single landing across 3 files)
Before dispatching any Haiku verification agents, do a quick staleness pre-check on the full item list.
For each item in state/debt-backlog/, note its cited file path and the date it was logged (created field in frontmatter). Items where git log --since="<finding-date>" -- <file-path> shows relevant commits are candidates for already-fixed status and should be confirmed first.
This pre-check prevents dispatching agents to verify debt that has already been resolved. In one measured run, 11 of 20 backlog items were already fixed before dispatch — the same failure mode applies to debt backlogs that drift behind active development.
Why pre-dispatch rather than during Step 2: Step 2 Haiku agents do the full per-line verification; this pre-check is the EM's own lightweight scan (date + git log) that prunes obviously-stale items before agent dispatch, reducing cost.
Step 1c: Analyst brief — structural probes
When evaluating whether a debt item or proposed enhancement is worth acting on, the debt-triage analyst may apply two concrete structural probes:
Deletion test. Imagine deleting the module, class, or abstraction in question. If complexity vanishes (callers simplify, the code reads more directly), the abstraction was a pass-through — it was not earning its keep. If complexity reappears across N callers (each must now handle what the module was hiding), the abstraction was load-bearing. Use this as a single-sentence verdict: "Deletion test: complexity would [vanish / reappear at N callers]."
One-adapter / two-adapter rule. One adapter is a hypothetical seam. Two adapters is a real seam that pays its abstraction cost. A single adapter wrapping one concrete implementation is usually premature — the deletion test confirms this. Two independent adapters in production justify the interface.
These probes apply when evaluating YAGNI calls, scope-change proposals, and deepening candidates. Pair any deletion-test finding with the convergence rule (≥2 independent agents before acting on a "shallow module" verdict) — single-agent subjective verdicts have elevated false-positive rates.
Step 1d: Read Improvement Queue
Also read state/improvement-queue/ entries via bin/query-records.js --type improvement
- Universal — would apply if a different project type used the coordinator pipeline? → routing note: "should be in lessons-outbox — surface to next
/learn-lessonslocal run." Do NOT pull these into the debt triage path; flag them for the EM to route at the end of this session. - Project-specific — structural or implementation debt scoped to this repo → flow into the standard triage path alongside
state/debt-backlog/entries. These are candidates for migration tostate/debt-backlog/at Step 6b.
Present the classification summary to the PM before proceeding:
"Improvement queue: N entries total — M universal (flagged for lessons-outbox routing), K project-specific (flowing into triage)."
If the queue is absent or empty, note this and proceed without block.
Doctrine refs: CLAUDE.md § Improvement Queue (admission rule + routing contract); docs/wiki/lessons-outbox-schema.md (universal entry routing schema).
Step 2: Verify Relevance (Haiku agents)
Dispatch Haiku agents to verify each open item against the current code. This is mechanical read-and-confirm work — no judgment needed. Group items by system for efficient dispatch (one Haiku per system).
Each Haiku agent receives a list of items for its system and:
- Checks if the referenced code has changed since the finding was logged
git log --since="<finding-date>" -- <file-path> - Reads the cited file:line to confirm the issue still exists
- Returns a verdict per item:
still-open/already-fixed/partially-addressed
The coordinator then categorizes:
- Items the Haiku marked
already-fixed: mark asno-longer-applicable - Items marked
still-open: item remains open - Items marked
partially-addressed: update the description based on Haiku's report
Why Haiku: 12 of 16 items in the 2026-03-19 triage were already fixed. Haiku verification costs minutes; dispatching Sonnet executors on ghost debt costs significantly more.
Step 3: Re-Prioritize
Based on current state:
- Items blocking other work → escalate to P0
- Items in systems with grade D/F → escalate to P1
- Items in systems recently audited as A/B → may deprioritize to P2
- Items >30 days old with no activity → flag for PM attention
Step 3b: LoE-weighted hot-zone identification
Before grouping items, query the completion log for historical nature: tech-debt entries to surface which areas have consumed significant effort recently versus which have been avoided:
query-completions.sh --where "nature=tech-debt" --since "90d" --sort "-loe.tshirt" --format markdown-list
Interpret the output with two lenses:
- High-LoE areas (L/XL entries in last 90d): Repeated large tech-debt sessions in the same subsystem indicate festering complexity — the root cause was not resolved, only managed. Escalate any open backlog items in this area: they are likely blocking or near-blocking.
- Zero-activity areas: Backlog items that cite a subsystem with no recent
nature: tech-debtcompletions may reflect avoidance. Flag these for PM attention: "We have carried this debt for N days without touching it — is that intentional?"
Present a one-paragraph hot-zone summary to the PM before the Step 4 grouping. Example framing:
"The completion log shows three XL tech-debt sessions in
src/indexer/over the last 90 days — that area is festering. Two open backlog items cite it; I'm escalating both.src/cache/has two open items but no recent debt sessions — possible avoidance."
Zero-row rendering: If the query returns no results (fresh repo or no tech-debt completions logged yet), render: (no tech-debt completions logged in last 90d — hot-zone analysis unavailable) and proceed without escalating.
Step 4: Group for Execution
Group remaining items by system for efficient batch execution:
## Triage Results
### Closed (no longer applicable): N items
| ID | Reason |
|----|--------|
### Recommended for immediate action: N items
| ID | System | Severity | Description | Effort |
|----|--------|----------|-------------|--------|
### Can defer: N items
| ID | System | Severity | Reason to defer |
|----|--------|----------|----------------|
### Needs PM decision (YAGNI/scope): N items
| ID | System | Description | Question |
|----|--------|-------------|----------|
Step 5: Present to PM
Present the triage results and ask for:
- Approval to close no-longer-applicable items
- YAGNI/scope decisions on flagged items
- Prioritization of immediate-action items
- Agreement on deferral reasoning
Step 6: Update Backlog
After PM decisions:
-
Close resolved items: for each item to close, stamp
status: closed,closed_at: <ISO date>, andclosed_by: <commit-sha>in the entry's YAML frontmatter, then archive it:# For each closed entry: mkdir -p archive/debt-backlog/<YYYY-MM> git mv state/debt-backlog/<id>.yaml archive/debt-backlog/<YYYY-MM>/<id>.yaml # After all archive moves, clean up an empty source dir if it becomes empty: rmdir state/debt-backlog/ 2>/dev/null || true -
Update priorities per PM direction (edit
severityfield in the relevant YAML files) -
Remove items PM declares YAGNI (archive via
git mvas above, withstatus: closedand aclosed_byreferencing PM decision) -
For any item rejected with a load-bearing reason (scope conflict, doctrine conflict, cost-benefit rejection, architectural veto): write
tasks/out-of-scope/<concept>.mdusing the template below. One file per concept, not per item — if a matching file already exists, append a new entry under "Prior requests" instead of creating a duplicate. Bugs do NOT go to.out-of-scope/— only enhancement rejections. Create the directory on first use; never scaffold it empty.# Out of scope: <concept> **First raised:** YYYY-MM-DD **Status:** Rejected (open to reconsideration) ## What was proposed [One sentence describing the enhancement.] ## Why we rejected it [Load-bearing reason. Cost, scope, doctrine conflict, etc.] ## Prior requests - YYYY-MM-DD: [Brief description of how this came up] ## What would change our minds [Conditions under which this should be reconsidered. Optional but useful.] -
Commit:
git add archive/debt-backlog/ state/debt-backlog/ tasks/out-of-scope/ git commit -m "debt-triage: reviewed N items, closed M, N remain open"
Step 6b: Migrate project-specific improvement-queue entries
After the Step 6 commit, migrate any project-specific entries identified in Step 1d from state/improvement-queue/ into state/debt-backlog/:
- For each project-specific entry from Step 1d that survived triage (not YAGNI'd):
- Capture a new debt-backlog entry via
coordinator-queue-append --schema debt-backlog(mechanical capture using the CLI — do not manually author YAML). The CLI writes a newstate/debt-backlog/<id>.yamlfile. - Close the source improvement-queue YAML by stamping
status: closed,closed_at: <ISO date>, andclosed_by: <migrated-to-debt-backlog>in its frontmatter, then archive viagit mv:mkdir -p archive/improvement-queue/<YYYY-MM> git mv state/improvement-queue/<source-id>.yaml archive/improvement-queue/<YYYY-MM>/<source-id>.yaml rmdir state/improvement-queue/ 2>/dev/null || true
- Capture a new debt-backlog entry via
- Commit the new debt-backlog entries and the improvement-queue archive moves in two dedicated commits (do not bundle with Step 6 closure commits):
git add state/debt-backlog/ git commit -m "debt-triage: migrate N improvement-queue entries to debt-backlog" git add archive/improvement-queue/ state/improvement-queue/ git commit -m "debt-triage: archive migrated improvement-queue entries" - Universal entries flagged in Step 1d are NOT migrated to
state/debt-backlog/— they stay instate/improvement-queue/until the EM routes them via/learn-lessonslocal run (seedocs/wiki/lessons-outbox-schema.md). Only project-specific entries migrate.
If no project-specific entries were identified in Step 1d, skip this step entirely.
Notes
- The EM triages severity; only the PM removes items (YAGNI call)
- Items verified as no-longer-applicable can be closed by EM without PM approval
- This skill produces no code changes — it's a backlog management activity
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.