agentleFS
greglas75greglas75/zuvo/skills/backlog/SKILL.md

backlog

Skill7 starsChanged 27 days agoMITView on GitHub

Manage the project's tech debt backlog. Add, list, fix, wontfix, delete, prioritize, and suggest batch actions on tracked issues, run by the user to manage accumulated debt (skills file their findings through ~/.zuvo/backlog-add themselves, never through this skill). Modes: list [category], add [description], fix B-<id>, wontfix B-<id> [reason], delete B-<id>, stats, prioritize, suggest, and the three grooming modes verify, groom and doc (whether each entry is still true, the dispositions that follow, and the ranked working document).

36 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use issue, changelog and 5 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • AWSSkill

    issue

    Implement a GitHub issue end-to-end — branch, code, test, docs, and commit.

    Also in 3 projects that use this

  • HashiCorpSkill

    changelog

    Add a `.changelog/<PR_NUMBER>.txt` entry for a GitHub Pull Request, commit, and push.

    Also in 3 projects that use this

  • Hugging FaceSkill

    implement

    Make tests pass. Invoke after /write-tests produces failing tests.

    Also in 4 projects that use this

  • NVIDIASkill

    research

    Before designing a feature, research how comparable libraries solve the problem, check best practices, known pitfalls, and upstream changes. Use when starting a new feature, investigating an unfamiliar area, or the user asks to research something.

    Also in 4 projects that use this

  • SentrySkill

    commit

    Create commit messages following Sentry conventions. Use when committing code changes, writing commit messages, or formatting git history. Follows conventional commits with Sentry-specific issue references.

    Also in 3 projects that use this

  • MicrosoftSkill

    handoff

    Compact the current conversation into a handoff document for another agent to pick up.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

23 rules. 0 are common, 9 are distinctive, and 14 are very specific to this project.

  • 0

    Common

    Most of the 35 edited versions we read keep these.

  • 9

    Distinctive

    This author's own choices. Worth a look.

  • 14

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add (through ~/.zuvo/backlog-add), list, and manage backlog items.

    line 16
  2. Distinctive:

    Use the mode word with a person and the real command at a shell.

    line 69
  3. Very specific:

    Every call passes --repo "$R", R being the repository root assigned in the same shell call (../../shared/includes/backlog-protocol.md "The …

    line 79
  4. Very specific:

    Read ../../shared/includes/backlog-grooming.md before using any of them.

    line 140
  5. Very specific:

    Read ../../shared/includes/run-logger.md for log format and file path resolution.

    line 184
  6. Very specific:

    Read ../../shared/includes/codesift-setup.md for initialization.

    line 189
  7. Distinctive:

    All interactions use these columns:

    line 206
  8. Very specific:

    All fingerprint components are lowercase, trimmed, with leading ./ stripped from paths.

    line 227
  9. Very specific:

    Default view shows: ID | Severity | File | Problem | Seen

    line 231
  10. Very specific:

    Every item the user adds is one ~/.zuvo/backlog-add call, made per "Persisting a finding: backlog-add" and "Filing from a skill" in …

    line 237
  11. Very specific:

    If the user provides several items (numbered list, bullets, or comma-separated), file each with its own backlog-add call in one pass, …

    line 291
  12. Distinctive:

    Do not ask per-item for batch adds, except for the file of a code defect that names none, or a line that reading the file cannot verify.

    line 297
  13. Very specific:

    Default (list): show OPEN items only.

    line 351
  14. Very specific:

    CodeSift-enhanced scoring: When indexed, use find_references(repo, symbol_name=<function>) to count callers.

    line 413
  15. Distinctive:

    CodeSift-enhanced discovery: Before analyzing existing items, scan for undiscovered debt:

    line 433
  16. Distinctive:

    If CodeSift unavailable, analyze only existing backlog items

    line 436
  17. Distinctive:

    If multiple patterns match the same items, show all matching suggestions.

    line 448
  18. Distinctive:

    No class maps to arch, dep, doc or infra.

    line 497
  19. Distinctive:

    After completing any action, print:

    line 503
  20. Very specific:

    Follow the retrospective protocol from retrospective.md.

    line 516
  21. Distinctive:

    If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

    line 518
  22. Very specific:

    After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

    line 520
  23. Very specific:

    When memory/backlog.md does not exist, create it from this template:

    line 529

“Common” is measured: kept by at least 6 in 10 of the 35 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

zuvo:backlog — Tech Debt Management

Add (through ~/.zuvo/backlog-add), list, and manage backlog items. The backlog tracks technical debt discovered by audit skills, review agents, and manual entries.

Backlog location: memory/backlog.md, resolved per ../../shared/includes/backlog-protocol.md ("Where the Backlog Lives"): when git tracks it in the checkout you are in, that checkout's copy is the backlog for its branch; otherwise it lives at the MAIN checkout root. The helper applies the rule — ~/.zuvo/backlog-archive.py path --repo "$R" prints the path — and every helper call below takes --repo "$R", R being the repository root assigned in the same shell call (backlog-protocol.md "The repository root"; never $PWD, which the harness resets). By hand, copy the protocol's whole resolution block (its fallback is mandatory: without it a non-git CWD yields an empty root and re-forks the backlog).

For an UNTRACKED backlog, NEVER create or write a memory/backlog.md inside a linked worktree — one backlog per repository. If memory/ does not exist at the resolved root, create it. If the file does not exist, create it from the template at the bottom of this skill. If a legacy untracked worktree-local copy exists, merge its unique entries (by the dedup key defined in ../../shared/includes/backlog-protocol.md) into the main copy before proceeding.

Scope: Managing the tech debt backlog -- viewing, adding, resolving, prioritizing, and suggesting batch actions. Out of scope: Actually fixing the issues (use zuvo:fix-tests, zuvo:refactor, or the suggested command from suggest mode).

Argument Parsing

InputAction
(empty) or listShow all OPEN items as a summary table
list category:[x]Show OPEN items filtered by category (code/test/arch/dep/doc/infra; an entry backlog-add wrote is matched by its class, Tech Debt Categories)
list allShow all items including RESOLVED and WONTFIX
addInteractive: ask what to file, then file it with one backlog-add call (Adding Items)
add [description]Parse the description and file it with one backlog-add call (Adding Items)
fix B-<id>Mark item as RESOLVED
wontfix B-<id> [reason]Mark item as WONTFIX with reason
delete B-<id>Remove item (show details, ask confirmation)
delete B-<id> --forceRemove without confirmation
archive [--dry-run]Move ticked, resolution-marked entries to memory/backlog-done.md
regression B-<id>Re-open an archived entry under the same id (lookup said ARCHIVED)
statsShow counts by severity and category
prioritizeScore and rank all OPEN items by urgency
suggestGroup items by pattern, propose batch fix commands
verifyDecide whether every entry is still TRUE, before anything is closed, ranked, grouped or rendered — see Mode: verify
groom [--dry-run]Apply the dispositions those verdicts license; refuses on partial verification — see Mode: groom
doc [--partial]Render the groomed working document under zuvo/reports/ — see Mode: doc

The three mode words, and the commands they actually run

verify, groom and doc are this skill's words. The helper underneath has different ones: scripts/zuvo-home/backlog-groom.py --help is the authority, and it answers {plan, dispatch, ingest, apply, render, coverage}. The mapping lives here, once — a second copy is two names drifting apart:

ModeRunsPhase section
verifyplan, then dispatch + ingest once per chunkMode: verify
groomapplyMode: groom
docrenderMode: doc

coverage is not a mode: it is the read-only count ~/.zuvo/append-runlog prints at the end of a run when a verdict ledger exists and is short — never otherwise, because an unverified backlog is the steady state in most repos and a line on every run is a line nobody reads. Nobody types it.

verify --fleet and groom --fleet are not commands and never were. The plan that commissioned this feature named them four times each. plan --fleet is the read-only fleet verification (it reads ~/.zuvo/backlog-local.jsonl and writes only under ~/.zuvo/), and apply --fleet is rejected by design — grooming needs each repo's own lock, realpath, ignore status and backlog-done.md, and doing that across 88 checkouts is the 2026-07-19 fork-the-backlog incident with 88x the blast radius. Use the mode word with a person and the real command at a shell; never invent a third name for either.

Mode: verify

Nothing is closed, ranked, grouped or rendered until every entry carries a verdict backed by an evidence line. Not a sample — the whole set. Read ../../shared/includes/backlog-grooming.md first; it holds the closed five-token vocabulary, the four evidence shapes, the ledger schema and the fan-out contract, and this file deliberately does not paraphrase any of them.

Every call passes --repo "$R", R being the repository root assigned in the same shell call (../../shared/includes/backlog-protocol.md "The repository root"): a relative path would resolve against a working directory the harness may have reset.

backlog-groom.py plan --repo "$R" [--dry-run]       # mint, decide the deterministic classes, queue the rest
backlog-groom.py dispatch --repo "$R" --chunk N     # hand ONE chunk to the lane, seeds mixed in
backlog-groom.py ingest --repo "$R" --dispatch <D> --response <R>

plan --fleet is the read-only variant: it verifies from the collector's snapshot, writes ~/.zuvo/backlog-verdicts/<host>-<repo>.jsonl, and touches no checkout. Its rows carry source=index because the snapshot truncates each entry at 400 characters, and a disposition on such a row is refused rather than performed.

A verdict survives between runs: it expires with the entry's text, not with the clock. So a second verify over an unchanged backlog dispatches nothing at all, and the resolution marker groom itself writes costs nothing either.

Mode: groom

backlog-groom.py apply --repo "$R" [--dry-run]

apply refuses unless every entry carries a current verdict, naming the shortfall by id and exiting outside {0,1,2,10,11,12}. That refusal is the mechanism behind the rule above; it is not a warning to read past. It writes nothing to memory/backlog.md — closures are delegated to backlog-archive.py archive / drop-stale, ordering stays in the ledger and the rendered document, and where no helper will act the entry is reported no-remedy with its reason rather than a false archived.

apply --fleet is rejected naming the per-repo command, before the repo is even resolved.

Mode: doc

backlog-groom.py render --repo "$R" [--partial]

The working document — clustered by theme, ranked by the prioritize score above, with per-cluster batch commands and an explicit not-verifiable section — lands under zuvo/reports/. It refuses below full coverage unless --partial, which stamps the coverage ratio into the header, omits the ranking entirely, and names the entries it did not render. Its header carries the source backlog's sha256, the coverage count and the generating version, plus the command that re-checks all three, so a reader can tell from the document alone whether it still describes the file.


The verification lane (agents/backlog-verifier.md)

Deciding whether an entry is still true is not one of the modes above, and it is not done inline. It is dispatched, one byte-capped CHUNK at a time, to agents/backlog-verifier.md — a read-only lane that returns one verdict and one evidence line per row.

The orchestration is in scripts/zuvo-home/backlog-groom.py, never in this file's prose:

StepCommand
mint, decide the deterministic classes, write the queuebacklog-groom.py plan --repo "$R" [--dry-run]
hand one chunk to the lane, seeds mixed inbacklog-groom.py dispatch --repo "$R" --chunk N
check the response and append only if nothing refusedbacklog-groom.py ingest --repo "$R" --dispatch <D> --response <R>

Read ../../shared/includes/backlog-grooming.md before using any of them. Two things about this lane that are easy to get wrong and expensive to get wrong:

  • A chunk is all-or-nothing. ingest writes ledger rows only when the rejection list is empty. One bad record writes zero rows for every row the lane got right, so the check after a run is the ledger's byte count, not the presence of one verdict.
  • The four mechanical controls do not validate a verdict. Shape, resolvability and keyword overlap establish that the evidence is well-formed and points at a real line — they cannot say the verdict is correct. Only the seeded known-answers measure judgement, on K=4 rows per chunk. Never report a lane result as verified or cross-checked.

Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing authorization within that policy; session restrictions take precedence. Run each required gate and report its actual independence or an unmet requirement.

Inline verification is NOT a substitute for the lane. Deciding the rows yourself and recording the result as if the lane had run is the substitution no-gate-substitution describes: it produces verdicts with no agent: provenance for the cross-model spot check to select on, and it bypasses controls (a)-(d) entirely while reporting that they ran. If the harness genuinely cannot dispatch, say so and record the rows as unverified — groom then refuses, which is the correct outcome rather than a blocked one.


Mandatory File Loading

PHASE 0 — Bootstrap (before reading the backlog)

env-compat.md is here for one measured reason: this skill scans repositories and waits on the commands that do it, and it accounted for 485 of 11,690 Codex poll calls while referencing that include nowhere — so the "do not enter the poll loop" rule could not reach it however well written. Each poll re-sends the whole context (~108K tokens median) to learn one bit.

  1. ../../shared/includes/codesift-setup.md      -- [READ | MISSING -> WARN]
  2. ../../shared/includes/backlog-protocol.md    -- [READ | MISSING -> STOP] (the file format is the contract)
  3. ../../shared/includes/env-compat.md          -- [READ | MISSING -> WARN] (waiting rule; see below)
  4. ../../shared/includes/backlog-grooming.md    -- [READ for verify/groom/doc | MISSING -> STOP for those three modes]

retrospective.md and run-logger.md are END-of-run includes — they are loaded at completion, not here.

Run Logging

Read ../../shared/includes/run-logger.md for log format and file path resolution. Read ../../shared/includes/retrospective.md for log format and file path resolution.

CodeSift Integration

Read ../../shared/includes/codesift-setup.md for initialization.

Key tools for this skill:

CommandTaskCodeSift toolFallback
suggestFind undiscovered TODO/FIXME debtsearch_text(repo, query="TODO|FIXME|HACK", regex=true)Grep
suggestContext around TODO markersfind_and_show(repo, query=<function>, include_refs=true)Read the file
prioritizeCount references to affected functionfind_references(repo, symbol_name=<fn>)Skip (score from description only)
prioritizeBlast radius of recent itemsimpact_analysis(repo, since="HEAD~10", depth=2)Skip
fixFind related code when planning a fixsearch_symbols(repo, query=<keyword>)Grep
fixBatch-read related functionsget_symbols(repo, symbol_ids=[...])Multiple Read calls

Backlog Schema

All interactions use these columns:

ColumnDescriptionSet by
IDB-<id>, minted by backlog-addAuto
StatusOPEN, RESOLVED, WONTFIXAuto (default: OPEN)
FingerprintDedup key (see format below)Auto
FileFile pathRequired
ProblemShort descriptionRequired
SeverityCRITICAL, HIGH, MEDIUM, LOWRequired
CategoryCode, Test, Architecture, Dependency, Documentation, InfrastructureLegacy rows only; an entry backlog-add writes has none and is mapped from its [<CLASS>] (Tech Debt Categories)
SourceWhich skill added itAuto
SeenOccurrence countAuto
AddedDate first added (YYYY-MM-DD)Auto

Fingerprint Formats

  • From audit skills: file|rule_id|signature (e.g., auth.service.ts|cq8|missing-try-catch)
  • From test audit: file|pattern_id|signature (e.g., auth.test.ts|p-41|loading-only)
  • Manual add: file|manual|first-3-words-slugified (e.g., auth.ts|manual|missing-rate-limiting)

All fingerprint components are lowercase, trimmed, with leading ./ stripped from paths.

Listing View (compact)

Default view shows: ID | Severity | File | Problem | Seen


Adding Items

Every item the user adds is one ~/.zuvo/backlog-add call, made per "Persisting a finding: backlog-add" and "Filing from a skill" in ../../shared/includes/backlog-protocol.md. The helper mints the id, runs the duplicate check across backlog.md, backlog-done.md and the findings ledger, and writes. In this add flow the skill never mints an id, runs the lookup or appends a line itself.

  1. From the description (or by asking, in interactive mode), take:
    • Site: the file and line. A code defect the user describes without naming a file: ask for the file. With the file known, find the line by reading the file and confirm the defect is at it; when the line cannot be verified that way, ask the user for it. Never guess a line. Only a process or decision item (a gate, a follow-up, an open question) has no file.
    • Class: BUG only when the user states both the input and the wrong result; otherwise CQ, or the class the item plainly is (SEC, PERF, ...); PROCESS for a process or decision item. The Auto-Inference keywords are hints, never a substitute for the input and the wrong result.
    • Confidence: derived from what the user stated and what this run checked, never a fixed number: the cited line read and the defect seen there, or the behaviour reproduced → 80-95; stated by the user but not checked → 50-75.
    • Title in one sentence, and a severity when the description implies one (Auto-Inference Rules).
  2. File it with --source user, one call per item. The user's words are free text, so every "$X" argument below is assigned just before the call, one assignment per value, as "Filing from a skill" says (the form works in bash 3.2 and zsh). R is the repository root, not free text: a literal, or git rev-parse --show-toplevel of the run's checkout, assigned in the same shell call as the command, never $PWD (the harness resets the working directory between calls):

    R='<the absolute path of the repository root the run works in>'
    read -r -d '' T <<'ZUVO_TXT' || true
    <the title, verbatim>
    ZUVO_TXT
    read -r -d '' F <<'ZUVO_TXT' || true
    <the file path, repo-relative>
    ZUVO_TXT
    read -r -d '' A <<'ZUVO_TXT' || true
    <the anchor, copied from the cited line>
    ZUVO_TXT
    read -r -d '' S <<'ZUVO_TXT' || true
    <the slug, a process or decision item only>
    ZUVO_TXT
    • BUG, SEC, DATA: ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source user --file "$F" --line <n> --anchor "$A" --title "$T" [--severity <level>]
    • any other class with a file: ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source user --file "$F" --line <n> --title "$T" [--severity <level>]
    • a process or decision item: ~/.zuvo/backlog-add --repo "$R" --class PROCESS --conf <N> --source user --target "subject:$S" --title "$T" [--severity <level>], where S is a slug of the title: kebab-case, ASCII [a-z0-9-] only (transliterate letters such as ł or ą, drop any other character), cut to 40 characters. A title with no ASCII letters or digits leaves it empty, and backlog-add refuses an empty target: ask the user for a slug

    Prefix the call with ZUVO_BACKLOG_ADMIT=1 only when the user ran this add mode themselves in this message: their request for the item is the explicit request the override exists for, so a CQ or PROCESS item lands in the backlog instead of only the ledger. Never when a skill or an agent invokes this mode, and never for an item the user did not ask to file.

  3. Report the verdict backlog-add printed: the B-id it filed or bumped, REGRESSION for REOPENED, the F-id for a ledger record. A refusal is corrected only when the input was mistyped (a path, a line, the anchor text) and then resubmitted once; never by changing --class or --conf to get past a bar. Anything else is reported as NOT PERSISTED (<reason>), except the outcomes the protocol's "Verdicts and exit codes" lists as no failure (DISCARDED below-floor, a refusal a re-read resolves, the exit-1 partial write reported as filed). Never append the item by hand.

Batch Add

If the user provides several items (numbered list, bullets, or comma-separated), file each with its own backlog-add call in one pass, without pausing for confirmation, then show one summary table: item, class, site and the verdict each call printed.

Auto-Inference Rules

Do not ask per-item for batch adds, except for the file of a code defect that names none, or a line that reading the file cannot verify. Infer the rest; the keywords are hints:

  • Class: a wrong behaviour stated with its input (returns, crashes, loses, wrong) -> BUG; a process or decision item -> PROCESS; otherwise CQ.
  • Severity (--severity): race condition, security, data loss -> high. any type, missing test -> medium. typo, naming -> low.
  • Source: user
  • The id, seen and the date are set by backlog-add.

Resolving Items

fix and wontfix record the resolution on the entry and then ARCHIVE it. Neither removes the record: the archive is what lets a later sighting be recognised as a regression instead of being re-filed as new work.

Finding the entry a mode acts on, or answering "is this already known?" without filing anything, is the lookup across both files — run it, do not re-implement it: ~/.zuvo/backlog-archive.py lookup --repo "$R" -- "$Q" (R is the repository root, assigned in the same shell call: backlog-protocol.md "The repository root"; Q is the B-id or the candidate text, assigned through the heredoc of "Free text goes through a variable" there, since candidate text is the user's own words). It answers OPEN (exit 10), ARCHIVED (exit 11: the regression path), ABSENT (exit 0), or NO-SIGNATURE (exit 13: the query keys on nothing — empty, or stripped to nothing as resolution markers; nothing was looked up, so rewrite it to name the file and the defect, or pass the B-id). Checking only backlog.md is not a check: an entry that exists solely in backlog-done.md reads as ABSENT.

  • fix B-<id>: verify exists (error if not), tick the box and append [FIXED <sha7>] to the existing text — never write over the problem description, because the description is what the content key is computed from.
  • wontfix B-<id> [reason]: verify exists, tick the box and append WONTFIX — <reason>.
  • archive [--dry-run]: move every ticked, marker-carrying entry into backlog-done.md via ~/.zuvo/backlog-archive.py archive --repo "$R". Entries holding a live [ ] sub-item are refused, not moved — split them first.
  • regression B-<id>: the ARCHIVED path of the lookup. Re-open under the same id with the back-link, severity one band higher, and the word REGRESSION in the report.
  • delete B-<id>: destructive and rarely right. Print "this destroys the record — archive is what you want", show the item, ask "Delete? (y/n)". With --force, skip the confirmation only.

Never archive by hand. ~/.zuvo/backlog-archive.py archive does it — with a lock, byte conservation, minted ids and the git-tracking refusal. What a hand-written archive breaks, and the measured incident behind the rule, are in backlog-protocol.md → "Archiving is done by the helper, never by hand" (kept there once rather than paraphrased here).

Order, not growth control: archive; never prune. A resolved entry does not stay in the open backlog — it moves verbatim to backlog-done.md, so the record survives. There is no size threshold: one resolved entry is already reason enough, and ~/.zuvo/append-runlog does the move automatically at the end of every run. backlog-archive.py status answers "is anything done still sitting here?" — exit 12 yes, 0 no. A tick with no resolution marker also moves, into a section whose heading says the reason was never recorded; only an entry with a live [ ] sub-item is held back. See "When to archive" in the protocol.


Listing Items

Default (list): show OPEN items only.

TECH DEBT BACKLOG -- [project name]
-----
| ID   | Severity | File                    | Problem                  | Seen |
|------|----------|-------------------------|--------------------------|------|
| B-1  | MEDIUM   | auth.service.ts         | catch(err: any)          | 3x   |
| B-2  | HIGH     | payout.service.ts       | Race condition in claim  | 1x   |
-----
OPEN: X items (C: _, H: _, M: _, L: _)

Stats

BACKLOG STATS
-----
OPEN:      X items
  CRITICAL:  _
  HIGH:      _
  MEDIUM:    _
  LOW:       _

By category:
  Code: _  Test: _  Architecture: _
  Dependency: _  Documentation: _  Infrastructure: _

Top files (by item count, top 5):
  1. services/payout.service.ts (3 items)
  2. handlers/webhook.ts (2 items)
-----

Prioritize

Score each OPEN item to produce a ranked list. The scoring formula:

Priority Score = (Impact + Risk) x (6 - Effort)
Dimension135
ImpactRarely slows workSometimes blocks developmentSlows the team every day
RiskNice to haveRegressions possibleSecurity or data loss risk
EffortMultiple daysAbout a weekA month or more

Score range: 2 (low priority) to 50 (fix immediately).

What doc DERIVES, and the one thing it cannot. The rendered document computes all three dimensions from the bytes — Impact from the entry's declared severity word, Risk from a small named vocabulary in its own text, Effort from its block size — and says so in the table's own caveat. When a dimension's vocabulary is absent the answer is the neutral 3, for Risk exactly as for Impact. Risk is never a copy of Impact: it was, and a critical entry naming no risk at all then printed Risk 5, indistinguishable from one that says "data loss", while the score counted one signal twice. A derived score is a reading order, not an assessment — the table above is what a HUMAN means by these dimensions.

CodeSift-enhanced scoring: When indexed, use find_references(repo, symbol_name=<function>) to count callers. Higher reference count means larger blast radius, which increases Impact and Risk scores.

Output:

PRIORITIZED BACKLOG
-----
| Rank | ID   | Score | Impact | Risk | Effort | Problem               |
|------|------|-------|--------|------|--------|-----------------------|
| 1    | B-2  | 40    | 5      | 5    | 2      | Race condition payout |
| 2    | B-1  | 24    | 4      | 4    | 3      | catch(err: any)       |
-----

Suggest

Analyze all OPEN items by pattern and propose batch actions.

CodeSift-enhanced discovery: Before analyzing existing items, scan for undiscovered debt:

  • search_text(repo, query="TODO|FIXME|HACK|WORKAROUND", regex=true) to find inline markers not yet tracked
  • Cross-reference with existing fingerprints to avoid duplicates
  • If CodeSift unavailable, analyze only existing backlog items

Pattern Matching

ConditionSuggested action
3+ items with the same CQ gate failurezuvo:code-audit [files] or direct batch fix
3+ items from test-audit with same pattern IDzuvo:fix-tests --pattern [ID] [path]
3+ items in the same modulezuvo:refactor [module]
5+ low-tier itemszuvo:code-audit --deep [path]
No OPEN items"Backlog is clear. Consider a periodic audit."

If multiple patterns match the same items, show all matching suggestions.

Output:

BACKLOG SUGGESTIONS
-----
Pattern: CQ8=0 in 5 files          -> zuvo:code-audit src/services/
Pattern: P-41 in 4 test files       -> zuvo:fix-tests --pattern P-41 src/
Hotspot: offer.service.ts (6 items) -> zuvo:refactor src/offer/offer.service.ts
-----

Error Handling

SituationResponse
fix B-99 but B-99 not found"B-99 not found. Run zuvo:backlog list to see current items."
list but backlog is empty"Backlog is empty. Use the add mode to track issues."
add with vague description (no file)Ask for the file and the specific problem; only a process or decision item is filed without one, as PROCESS (Adding Items)
prioritize with 0-1 items"Only N item(s) -- no ranking needed."
suggest with 0 items"Backlog is clear. Consider scheduling a periodic audit."

Tech Debt Categories

AliasCategoryExamples
codeCodeDuplicated logic, magic numbers, any-types
archArchitectureWrong data store, monolith boundaries
testTestLow coverage, flaky tests, missing integration tests
depDependencyOutdated libraries, CVEs, unmaintained packages
docDocumentationMissing runbooks, outdated READMEs
infraInfrastructureManual deploys, no monitoring, missing IaC

An entry backlog-add writes carries no Category column: its line holds the class in brackets after the location (- [ ] B-<id> <path>:<line> — [<CLASS>] <title> | …). list category:[x] and stats read a legacy table row's Category column as written, and map an entry backlog-add wrote by that class:

ClassCategory
BUG, SEC, DATA, DUP, CPLX, SIZE, PERF, DEAD, READ, CQcode
TEST-GAP, MUTATIONtest
PROCESS, ADVISORYnone: shown by an unfiltered list only

No class maps to arch, dep, doc or infra; those filters match legacy rows only.


Completion

After completing any action, print:

BACKLOG COMPLETE
-----
Action: [list | add | fix | wontfix | delete | stats | prioritize | suggest | verify | groom | doc]
Run: <ISO-8601-Z>	backlog	<project>	-	-	<VERDICT>	-	<DURATION>	<NOTES>	<BRANCH>	<SHA7>	<INCLUDES>	<TIER>
-----

Retrospective (REQUIRED)

Follow the retrospective protocol from retrospective.md. Gate check → structured questions → TSV emit → markdown append. If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

<DURATION>: use the action label (list, add, fix, wontfix, delete, stats, prioritize, suggest, verify, groom, or doc).


Backlog Template

When memory/backlog.md does not exist, create it from this template:

# Tech Debt Backlog

> Maintained by zuvo:review, zuvo:build, zuvo:code-audit, zuvo:test-audit, zuvo:write-tests, zuvo:fix-tests, zuvo:backlog.

| ID | Status | Fingerprint | File | Problem | Severity | Category | Source | Seen | Added |
|----|--------|-------------|------|---------|----------|----------|--------|------|-------|

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.