/sdlc:project-cleanup
Generated from solutions/ontological/skills/project-cleanup/SKILL.md.
Description
Section titled “Description”Sweep local branches, worktrees, remote branches, and SDLC task linkage to
identify what can safely be cleaned up. The deterministic sdlc project cleanup
scanner gathers facts and pre-classifies each item; this skill dispatches
sub-agents in parallel to investigate ambiguous cases, then presents a single
batched plan for one-shot approval before executing.
Allowed tools
Section titled “Allowed tools”ReadBashAgentAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:project-cleanup— full scan + investigation + batched approval + execute./sdlc:project-cleanup --dry-run— same as above but never executes; reports the plan and stops./sdlc:project-cleanup --scope <list>— restrict to one or more oflocal-branches,worktrees,remote-branches,task-linkage./sdlc:project-cleanup --no-gh— skip GitHub PR lookups./sdlc:project-cleanup --no-investigate— skip sub-agent investigation; ambiguous items remain unclassified and are listed for the user to handle manually.
Project context (don’t re-derive every run):
- The deterministic scanner is
sdlc project cleanup. It only reads state — it never deletes branches, removes worktrees, or pushes anything. - The scanner pre-classifies every artifact into a
safe-to-delete/safe-to-keep/needs-investigationbucket; Step 2 resolves theneeds-investigationones. See the op doc-comment (solutions/ontological/lib/services/project/ops/cleanup.ts) andsdlc project cleanup --help. - The skill never deletes anything until the user has approved the full plan in one prompt.
1. Scan
Section titled “1. Scan”Run the deterministic scanner and capture its JSON:
${CLAUDE_PLUGIN_ROOT}cli/sdlc project cleanup --json <scope/flags>Pass through any --scope / --no-gh flags from the user invocation. Always use --json here
— the structured payload is what the rest of the skill consumes.
Parse the JSON. For the full output shape see the op doc-comment
(solutions/ontological/lib/services/project/ops/cleanup.ts) and sdlc project cleanup --help. The
keys this skill drives directly:
markdownReport: a full pre-rendered markdown report (repo header, a per-category## Summary, then the items grouped by classification) — print this verbatim to the user. Do not re-derive or reformat it; the op owns the wording so successive runs read consistently.summary: per-category totals (safe-to-delete/safe-to-keep/needs-investigation) — drive the empty-backlog check below off this.items: each item hascategory,id,classification,action,reason,facts,commands, and optionallyinvestigation_prompt— Step 2 reads these.
If summary shows zero safe-to-delete AND zero needs-investigation across all categories, print
Nothing to clean up. and exit.
2. Investigate ambiguous items in parallel
Section titled “2. Investigate ambiguous items in parallel”For every item where classification == "needs-investigation", dispatch one sub-agent per item
in a single message so they run concurrently.
Skip this step entirely if --no-investigate was passed. In that case, treat every
needs-investigation item as if the agent had returned verdict: defer (see below) — they pass
through to Step 3 as “leave alone, surface to user.”
Each sub-agent prompt must include:
- Repo root (
repo.rootfrom the JSON). - The single item this agent owns (its
id,category,facts, andinvestigation_prompt). - The verdict contract (below).
- Permission to read files and run read-only git/gh commands. Sub-agents must not delete, push, or otherwise mutate state.
Per-item investigation contract
Section titled “Per-item investigation contract”The agent does, in this order:
-
Read the item’s
factsandinvestigation_prompt. -
Run the full required probe set for the item’s category — every probe listed, not a subset, so the verdict rests on all available evidence and stays consistent across runs.
local_branch(always run):git log <branch> --oneline -10— what’s on the branch?git log <main>..<branch> --oneline— what’s unique vs main?git diff <main>...<branch> --stat— divergence size.- If
facts.pris present:gh pr view <pr.number> --json state,reviewDecision,mergedAt,closedAt,comments. - If
facts.taskis present: read the task file end-to-end (status, completion_note, blocked sections).
worktree(always run):git -C <path> status --porcelain(re-verify dirty state at investigation time — the script’s count may be stale).git -C <path> diff --stat— what’s actually been changed.git -C <path> log <compare_against>..HEAD --onelinewherecompare_againstisfacts.compare_against.ls <path>— recognise abandoned scaffolding vs real work.- If
facts.pris present:gh pr view <pr.number> --json state,reviewDecision,mergedAt,closedAt,comments. - If
facts.taskis present: read the task file end-to-end.
remote_branch(always run):git log <remote>/<main>..<remote>/<branch> --oneline— unique commits on the remote branch.git diff <remote>/<main>...<remote>/<branch> --stat.- If
facts.pris present:gh pr view <pr.number> --json state,reviewDecision,mergedAt,closedAt,comments. - If
facts.taskis present: read the task file end-to-end.
task_linkage(always run):- Read the task file end-to-end (status, completion_note, body — especially any
<blocked>section). git log --all --oneline -- <relative path of task file>— has the task itself been touched recently?git log --all --oneline --grep '<task.slug>'— any commits referencing the slug?- For each candidate ref (
task/<basename>,task/<slug>,<basename>):git rev-parse --verify --quiet refs/heads/<ref>andgit ls-remote --heads <remote> <ref>to double-check the script’s branch-existence inference.
-
Form a verdict from this menu (one only):
delete— safe to delete; the apparent disposability outweighs any remaining ambiguity. Must includecommands(literal shell). Be explicit if force-delete (-D/--force) is required.keep— worth preserving. Often “open PR pending”, “uncommitted work that should be pushed”, “task in-progress with a real direction”.escalate— surface to the user with a specific question. Use when the choice depends on user intent the agent can’t infer (e.g. “this worktree has 4 uncommitted files; user may still want them”). Include a one-line question.defer— leave it alone for this run; not worth either deleting or asking. Use sparingly.
-
Return a strict JSON object (no surrounding prose) so the orchestrator can aggregate cleanly:
{ "id": "<the item id verbatim>", "category": "<the item category verbatim>", "verdict": "delete | keep | escalate | defer", "reason": "<one sentence>", "commands": ["<shell line>", "..."], "question": "<only when verdict=escalate, else omit>", "evidence": ["<bullet>", "..."]}Keep each agent’s response under 250 words. Use general-purpose for the subagent type unless the
item is clearly code-review-shaped.
Send all Agent tool calls in a single message.
Aggregate verdicts
Section titled “Aggregate verdicts”When every sub-agent returns, merge their verdicts back into the items list:
safe-to-deleteitems are unchanged.safe-to-keepitems are unchanged.needs-investigationitems adopt their agent’s verdict (delete/keep/escalate/defer). Replacereasonandcommandsfrom the verdict.- If any sub-agent failed to return parseable JSON, treat that item as
deferand note the failure in the plan.
3. Build the batched plan
Section titled “3. Build the batched plan”Render a single markdown plan for the user. Group strictly by action so review is easy:
# Cleanup plan
## Will delete (<N>)For each `delete` item across all categories:- `<id>` — <reason> - <command 1> - <command 2>
## Needs your decision (<N>)For each `escalate` item:- `<id>` — <reason> - Question: <question>
## Leaving alone (<N>)For each `keep` and `defer` item, one line each — no commands.
## Final command list (will run on approval)A fenced bash block containing every command from the "Will delete" section, in order.Note any item where the proposed command is -D / --force explicitly — e.g.
(force delete; branch not merged) — so the user can see the risk before approving.
4. Approve in one shot
Section titled “4. Approve in one shot”Show the plan above, then ask the user one AskUserQuestion with these options:
- Run the plan as shown (Recommended if the plan looks right) — executes every command in the final list.
- Run only the safe-to-delete subset — executes only commands that came from the script’s
deterministic
safe-to-deleteclassification (skip sub-agent-promoted ones). - Cancel — don’t run anything — exit without mutating state.
If there are any escalate items, append a fourth option:
- Walk escalations one-by-one first — drives a follow-up AskUserQuestion per escalation, then re-builds the plan with those answers folded in.
If --dry-run was passed, skip this prompt entirely and exit after Step 3.
5. Execute approved commands
Section titled “5. Execute approved commands”Run each approved command via Bash, in order, from the repo root (repo.root from the JSON, not
the worktree the skill is running in — git worktree remove etc. operate against the primary repo).
If a command fails:
- Do NOT silently continue. Print the failure, the command, and the remaining queue.
- Ask the user via AskUserQuestion whether to continue with the rest, retry, or stop. Default: stop.
When complete, re-run the scanner (--json again) and report the new summary so the user can see
what shifted. If anything that was supposed to be deleted is still present, surface it.
6. Escalation walkthrough (only if the user chose that option in Step 4)
Section titled “6. Escalation walkthrough (only if the user chose that option in Step 4)”For each escalate item, in order:
- Show the item’s
id,reason, and the agent’squestion. - AskUserQuestion with three options:
delete(run the proposed commands),keep(skip), orprovide guidance(free-text via “Other”). - Update the item’s verdict accordingly.
After walking all escalations, go back to Step 3 (rebuild the plan) and Step 4 (single approval).
- Read-only by default everywhere except Step 5. Until the user approves the plan, no branch is deleted, no worktree is removed, no remote ref is touched.
- Force-deletes are explicit. When the scanner’s proposed command uses
-D/--force, the plan always labels it so the user can override (see the op doc-comment insolutions/ontological/lib/services/project/ops/cleanup.ts). - The current worktree is always kept. If you’re running the skill from inside
.sdlc/worktrees/<x>/, that worktree is classified as safe-to-keep — it can be cleaned in a future run from main. - Sub-agents are read-only. They investigate and return a verdict; the orchestrator runs every mutating command.
- Parallelism comes from one message. Step 2 dispatches every Agent call in a single response.
- When in doubt, ask via AskUserQuestion rather than guessing — mis-deleting a branch is worse than asking one extra question, and the user can override any verdict.
- Committing model-generated messages. If any approved command constructs a commit message,
follow
${CLAUDE_PLUGIN_ROOT}conventions/commit-messages.mdfor the authoring mechanism. - Branch naming. When the scanner reports merged
task/,docs/, andchore/branches for cleanup, see${CLAUDE_PLUGIN_ROOT}conventions/branch-naming.mdfor what each prefix means — adocs/<basename>spec branch may still have atask/<basename>implementation branch in flight. - Orphaned worktrees from a closed task. This skill is the recovery path for a worktree/feat
branch left behind after its task was already marked
closed/done./sdlc:task-close-outno-ops on an already-closed task (it emitsALREADY-CLOSEDand tears nothing down), so the leftover scaffolding lands here: theworktreescan classifies aclosed/done-backed worktree assafe-to-deleteand proposes its teardown for approval. Use--scope worktreesto target just that case.