/sdlc:review-todos
Generated from solutions/ontological/skills/review-todos/SKILL.md.
Description
Section titled “Description”Scan the codebase for TODO / FIXME / HACK comments, judge each one’s
worth in context, and ask the user what to do per item: promote to a
task (immediate work), capture as a backlog item (defer triage), edit
the comment in place, or skip. Promotion to a task calls sdlc task create and commits on main; promotion to a backlog item calls sdlc backlog create, which lands it on the rolling backlog-capture PR.
Allowed tools
Section titled “Allowed tools”ReadEditBashAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:review-todos— scan the whole tracked codebase./sdlc:review-todos <path>— scan a single file or subtree (path relative to repo root, or absolute).
Project context (don’t re-derive every run):
- Tasks live at
docs/planning/tasks/<id>-<slug>.md(id minted bytask create). Backlog items atdocs/planning/backlog/<id>-<slug>.md. - Scanning is delegated to
sdlc project scan todos. Task creation is delegated tosdlc task create; backlog capture is delegated tosdlc backlog create(the rolling-PR tail). Don’t reimplement what they own. - Validation:
sdlc entities validate(the backlog tail validates its own output, so explicit validation only applies to the task-creation branch). - This skill commits directly on
main, one commit per decision that produces an artifact — except backlog capture, whichsdlc backlog createlands on the rollingbacklog-capturePR (and any source-TODO annotation that accompanies it still commits onmain). It is lightweight intake: no worktree. - The TODO comment itself stays in the source file by default. Optionally annotate it with a wikilink to the new artifact so the connection is discoverable from the code.
1. Scan
Section titled “1. Scan”Run the scanner:
${CLAUDE_PLUGIN_ROOT}cli/sdlc project scan todos --json [--path <path>]Under --json the op prints {hits: [...]} to stdout. Each hit has fields path, line,
marker, text (the verbatim matched source line), and stripped (the comment content after the
marker). For the hit schema and the flags it accepts (--path, --markers, --include-planning),
see sdlc project scan todos --help. How this skill consumes that output:
- Use each hit’s op-provided
strippedcontent for the derived slug and headline — do not re-derive it fromtext. The body seed still quotes the verbatim source line fromtext, so a reader sees the exact comment in context. - Pass
--include-planningonly if the user explicitly wants to triage the SDLC system’s own TODOs.
If a path argument was given to the skill, forward it via --path. Parse the JSON output; if the
hits array is empty, exit NO TODOs FOUND.
Otherwise, report a one-line summary at the start: N TODOs across M files. Then enter the per-item
loop in the order the script produced them.
2. Per-TODO loop
Section titled “2. Per-TODO loop”For each hit:
-
Read context. Use Read on the file with an offset that captures ~10 lines before and ~20 lines after the TODO line. The point is to understand what the comment is actually pointing at — the function it lives in, what’s incomplete, whether it’s a stub or a future enhancement.
-
Evaluate. Form a one- to two-sentence judgment covering:
- What the TODO is asking for (paraphrased — don’t just echo the comment).
- Whether it looks trivial (a few lines, no design questions), scoped (a real task — clear intent, bounded surface), vague (intent unclear or speculative — needs more thought before any work), or stale (the surrounding code looks like it already addressed this, or the referenced concern no longer applies).
- A recommended disposition: task, backlog, edit-in-place, or skip.
Present the file path with line number (
path/to/file.py:142), the raw TODO line, your evaluation, and your recommendation. Keep this block under 8 lines. -
Ask via AskUserQuestion. Header
Disposition. The first option should mirror your recommendation and be labelled(Recommended). Always offer all four:- Create task — promote to an immediate work item. Use when the TODO is concrete and worth
doing soon. Calls
sdlc task create. - Create backlog item — capture for later triage. Use when worth remembering but not urgent,
or when intent needs refining before it can be a task. Calls
sdlc backlog create. - Edit in place — open a brief follow-up to rewrite or remove the comment (e.g. it’s stale, or it should be reworded to be more precise). Useful when the right answer is just “this comment shouldn’t exist” or “the comment is wrong about why.”
- Skip — leave the TODO and source file untouched, continue to next item.
- Create task — promote to an immediate work item. Use when the TODO is concrete and worth
doing soon. Calls
-
Execute the choice (sections 3–6). Then continue the loop.
The user can interrupt at any time. Committed decisions stay. Unprocessed TODOs simply resurface on the next run.
3. Create task
Section titled “3. Create task”-
Preview the would-be slug and id with the read-only
task preview-idop, passing the hit’sstrippedcontent:${CLAUDE_PLUGIN_ROOT}cli/sdlc task preview-id "<stripped>" --output jsonIt derives the capped slug for you (the shared substrate derivation — don’t re-derive it) and reports the would-be
id, plus whether an identical (exists/exact_match) or similar (similar[]) task already exists. The marker form isPREVIEW-ID task slug=<slug> id=<id> exists=<bool> similar=<n>; on empty/bad input it exits 1 (INVALID_INPUT) — surface that and skip the item.Dedup gate. If
existsis true, orsimilar[]is non-empty, a matching task may already exist — ask via AskUserQuestion (Dispositionheader) whether to proceed anyway, point the source annotation at the existing task’s id instead, or skip. Only continue creating when the user confirms there’s no duplicate. -
Ask for a headline in plain text: “One-line headline for the task? (default:
<derived from TODO>)”. The default is the hit’sstrippedcontent, capitalized. Accept the default if the user replies empty / “y” / “ok”. -
Single AskUserQuestion for triage (3 questions): Status (planning/draft / planning/proposed / open/ready), Impact (high / medium / low), Complexity (small / medium / large). Recommend
planning/draftfor first capture unless you specifically judged the TODO as ready-to-pick-up. -
Create the task. Omit the positional slug —
createderives the same capped slug from--headline(the slugpreview-idshowed you), so there’s nothing to hand off:${CLAUDE_PLUGIN_ROOT}cli/sdlc task create \--headline "<headline>" \--status <status> \--impact <impact> \--complexity <complexity>Capture the printed absolute path. The basename is
<id>-<slug>(theidpreview-idshowed you, e.g.T-HXSS-<slug>). -
Body seed. The task body should record where the TODO came from, so it’s traceable. Use Edit to replace the
## Todayplaceholder block with:Surfaced by `/sdlc:review-todos` from `<source-path>:<line>`:> <verbatim TODO source line, trimmed>Leave the other placeholder sections alone — they’re for the author to fill in via
/sdlc:task-definelater. -
Optional annotation. Ask via AskUserQuestion: “Annotate the TODO in source with a pointer to the new task?” Two options:
Yes — append [[<basename>]] to the TODO line(default) andNo — leave source untouched.If yes: Edit the source file. Find the TODO line and append the wikilink at the end. Build the
[[...]]token withwrapWikilink(<basename-without-.md>)from${CLAUDE_PLUGIN_ROOT}lib/util/wikilinks.tsrather than hand-spelling the brackets. Keep the existing comment marker and text intact; just suffix the wikilink before any trailing comment-close characters if the language has them. Skip the annotation silently if the line already ends with[[...]]. -
Validate:
${CLAUDE_PLUGIN_ROOT}cli/sdlc entities validate <task-path> -
Commit. Stage the new task and (if annotated) the source file, then route the message through
sdlc commit create:git add <task-path> [<source-path>]${CLAUDE_PLUGIN_ROOT}cli/sdlc commit create \--subject "docs(planning): create task/<task-basename> from TODO" \--body "<source-path>:<line> — <headline>"
4. Create backlog item
Section titled “4. Create backlog item”Backlog capture is delegated to sdlc backlog create — the deterministic tail that lands the item
on the rolling backlog-capture PR and prints a PR: <url> marker. This skill only feeds it
structured args. See ${CLAUDE_PLUGIN_ROOT}cli/backlog_cli/README.md for the contract. Triage of
captured items is the separate /sdlc:backlog-triage flow.
-
Derive a headline the same way as in section 3.1 (
<headline>).backlog createderives the slug and id from--headline, so there’s no slug to hand off. -
Build the body seed so the captured item is traceable:
Surfaced by `/sdlc:review-todos` from `<source-path>:<line>`:> <verbatim TODO source line, trimmed><one-line evaluation from step 2.2, if non-trivial> -
Capture it on the rolling backlog PR:
${CLAUDE_PLUGIN_ROOT}cli/sdlc backlog create \--headline "<headline>" \--body "<body seed from step 2>"Omit
--status— backlog items born from this skill are untriaged on purpose, so/sdlc:backlog-triagepicks them up later. The tail prints onePR: <url>line; capture it. If the tail exits non-zero, surface its stderr verbatim (bad slug, schema-validation, orgh/giterror). -
Optional annotation. Same prompt and placement as 3.6 — build the token with
wrapWikilink(<backlog-slug>)and suffix it to the source TODO line. Commit that single source-file edit onmain:git add <source-path>${CLAUDE_PLUGIN_ROOT}cli/sdlc commit create \--subject "docs(planning): annotate TODO with backlog/<backlog-slug>" \--body "<source-path>:<line> — <headline>"Skip this commit entirely when the user declined the annotation — the backlog file itself already landed on the rolling PR in step 3.
5. Edit in place
Section titled “5. Edit in place”-
Ask the user in plain text: “What should the comment say now? (or ‘delete’ to remove the line entirely)”.
-
Use Edit on the source file:
- If the response is the literal word
delete, remove the TODO line (and a single trailing blank line if it leaves a stray gap). - Otherwise, replace the TODO line with the user’s text. Preserve the surrounding indentation and
the language’s comment prefix (
#,//,--, etc.) — infer the prefix from the original line.
- If the response is the literal word
-
Commit only the source file:
git add <source-path>${CLAUDE_PLUGIN_ROOT}cli/sdlc commit create \--subject "chore: tidy TODO at <source-path>:<line>" \--body "<short note: 'reworded' or 'removed stale TODO'>"
If the user’s intent for the edit is non-trivial (more than a reword — e.g. they want the code changed too), tell them this skill is intake-only and suggest re-running with Create task instead. Don’t try to do code changes here.
6. Skip
Section titled “6. Skip”Take no action. Move to the next TODO.
7. Wrap up
Section titled “7. Wrap up”After the loop finishes (or the user stops it), print:
- N TODOs considered.
- Per disposition: count of tasks created, backlog items created, comments edited, skipped.
- The basenames of any new artifacts so the user can
git log --onelineor open them.
Acceptance criteria
Section titled “Acceptance criteria”- Every “Create task” action produced exactly one new task file at
docs/planning/tasks/<id>-<slug>.md(id minted bytask create, slug derived from the headline), with its frontmatter passingsdlc entities validateand its body referencing the sourcepath:line. - Every “Create backlog item” action landed exactly one new backlog file at
docs/planning/backlog/B-NNNN-<slug>.md(id minted by the tail) on the rollingbacklog-capturePR, with nostatus:field set (so it’s picked up by/sdlc:backlog-triage) and its body referencing the sourcepath:line. The tail’sPR: <url>marker was reported back to the user. - Each created artifact landed in its own commit. If the user opted into source annotation, that commit also includes the single source-file edit.
- “Edit in place” commits modify exactly one source file and create no planning artifact.
- “Skip” actions leave the working tree byte-identical to its pre-decision state.
- No file outside the scanned source path and
docs/planning/was modified.
- “Worth it” is judgment, not a heuristic. Default to recommending backlog for vague / speculative TODOs and task only for ones with a clear, bounded ask. When in doubt, skip — the TODO is still there for next time.
- This skill is intake only: it records a TODO as an artifact and stops there, leaving the TODO’s
actual investigation and implementation to
/sdlc:task-worklater. Promotion to task captures the ask; it never works it. - The source annotation (
[[<artifact-basename>]]) is just a pointer for human readers; nothing in the tooling depends on it. It’s nice-to-have, not required. - Hits inside generated files, vendored dependencies, or fixtures are already skipped by
git grephonoring.gitignore. To suppress a noisy checked-in file, add it to.gitignore— don’t expand theproject scan todosscanner’s hard-coded exclusions. - Comment-marker detection in section 5 is best-effort. For languages with unusual comment styles (e.g. block comments), preserve the original prefix verbatim rather than guessing.
- Committing model-generated messages. Route the multi-line commits in steps 3, 4, and 5 through
the canonical pattern in
${CLAUDE_PLUGIN_ROOT}conventions/commit-messages.md(prefersdlc commit create; heredoc/git commit -Ffallback). Single-linegit commit -mdrops the body’s multi-paragraph context on conventional-commit parens.