/sdlc:capability-review
Generated from solutions/ontological/plugin/plugins/sdlc/skills/capability-review/capability-review.md.
Description
Section titled “Description”Review existing Capability entities for accuracy against the code they
anchor: do the locations still realize the Statement, do kind,
audience and state match the shared rubric, do parent_key and
related still resolve, does the body describe what the code does. Runs
sdlc capability coverage and sdlc capability graph read-only,
dispatches one read-only sub-agent per capability, and prints a report.
With --fix it also corrects frontmatter through sdlc capability update and stamps last_reviewed; with --rewrite it also rewrites
drifted body sections; both open a PR. Invoke after a mapping run, after
a refactor that moved packages, or when the System page’s capability
view looks wrong. Usage: /sdlc:capability-review <dir|C-NNNN|all> [--fix] [--rewrite] [--auto].
Allowed tools
Section titled “Allowed tools”ReadGlobGrepBashEditAgentAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:capability-review <dir>— review every capability whoselocationstouch a directory./sdlc:capability-review C-NNNN— review one capability and its subtree./sdlc:capability-review all— review the whole corpus.--fix— write frontmatter corrections (kind,audience,state,parent_key,locations,related,need_human_review) and stamplast_reviewedon every reviewed capability, on a branch with a PR.--rewrite—--fixplus a rewrite of every body section the review found drifted.--body— judge the body sections too. Without it a review checks locations and frontmatter only.--rewriteimplies it.--auto— skip the confirmation prompt. Only meaningful with--fixor--rewrite.
Without --fix or --rewrite the skill is a report: it prints the review table and writes
nothing, not even a worktree. A scope is required. With no scope, print
ERROR reason="scope required: <dir>, C-NNNN, or all" and stop.
Project context (don’t re-derive every run):
- The read-only substrate is two ops.
sdlc capability coverage --scope <scope>lists the capabilities in scope withattachments(inbound wikilinks plus resolved locations) andanchor_rot.sdlc capability graphis the corpus as a tree with a warning per danglingparent_keyor unresolvedrelated. - Writes go through
sdlc capability update. Its--helpis the contract. Never hand-roll capability frontmatter. - The rubric is
${CLAUDE_PLUGIN_ROOT}/conventions/capability-rubric.md, shared with/sdlc:capability-map; it points at the grain table, audience rubric, locations grammar and body shape in${CLAUDE_PLUGIN_ROOT}/lib/model/entities/capability/definition.md. Read both once per run and point sub-agents at them; do not restate them. - Retirement is report-only. A
stalecapability with zero attachments lands in the retire table; closing it is a separate human decision.
1. Parse args and pre-flight
Section titled “1. Parse args and pre-flight”Parse <scope>, --fix, --rewrite, --body, --auto. --rewrite implies --fix and
--body. Classify the scope: a path that exists is a dir; a string matching C-NNNN is a
subtree; the literal all is the corpus. <stem> is the scope’s last path segment, the
capability id in lower case, or all.
In report mode (neither flag) skip the pre-flight. Otherwise probe:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc project preflight-worktree capability-review-<stem> \ --branch chore/capability-review-<stem> \ --project-root .If dirty is true, ask via AskUserQuestion whether to proceed (the worktree branches from
main, so uncommitted changes stay behind) or stop; default stop, showing the porcelain
lines. If anyCollision is true, stop and ask; a prior run may be unfinished.
2. Gather (read-only)
Section titled “2. Gather (read-only)”${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability coverage [--scope <scope>] --project-root . --output json${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability graph --project-root . --output jsonOmit --scope for all. Keep the warnings array from graph as the run’s baseline; Step
7d compares against it. Read the rubric and definition.md (see Project context).
The candidates are the capabilities in coverage.capabilities: for dir, those whose
locations touch the directory; for subtree, the capability and every descendant; for all,
the corpus. Candidates without locations are reviewed too: a planned capability is checked
for realizing code the same way map surveys it.
If the list is empty, print CAPABILITY-REVIEW-NOOP scope=<scope> and stop.
3. Create the worktree
Section titled “3. Create the worktree”Skip in report mode. Otherwise:
git worktree add .sdlc/worktrees/capability-review-<stem> -b chore/capability-review-<stem> mainUse absolute paths under the worktree for every write from here on. Do not cd the parent
session into it.
4. Dispatch one sub-agent per group (single message, parallel)
Section titled “4. Dispatch one sub-agent per group (single message, parallel)”Group the candidates by parent so each capability sits in exactly one group: the group keyed by
its parent when that parent is in scope, otherwise the group keyed by itself. Sort each group’s
members by capability id and split it into chunks of at most five, so the same scope groups the
same way on every run. A review reads a file and its anchors, so one agent per capability is
more agents than the work needs. For every group, dispatch one sub-agent in a single message
so they run concurrently. Use the general-purpose subagent type with the sonnet model; these
are well-briefed reads. Sub-agents are read-only: they read files and run git log; they
never write.
Each sub-agent prompt carries:
- The project root (absolute).
- The capabilities it owns: for each, its file path and its coverage row (
attachments, rot entries). - The paths to the rubric and
definition.md, and the instruction to apply them. - The current tree from
capability graph(ids, titles, parents), so a proposed parent orrelatedtarget is chosen from what exists. - Whether to judge body sections (
--bodyor--rewrite) and whether to draft replacement text (--rewriteonly; a report needs the finding, not the prose). - The verdict contract below.
Per-capability verdict contract
Section titled “Per-capability verdict contract”Each sub-agent, for each capability in its group, in order:
- Read the capability file. Open every
locationsentry; for a symbol form, grep the symbol in that file. Read enough of each location (README, manifest, entry points) to judge whether it delivers the Statement. - Judge each check against the rubric:
locations(resolve and realize the Statement),kind,audience,state,parent_key,related, and, when the prompt asked for body checks, each body section (Summary,Statement,What it provides,Underlying implementation). - Decide the verdict:
accurate— every check holds.drift— a field or section disagrees with the code; the capability is still provided.stale— the ability is no longer provided: locations gone, package deleted, or the Statement describes something the code no longer does.
- Return a strict JSON array, one object per capability in the group, no surrounding prose:
[{ "candidate": "C-NNNN", "verdict": "accurate | drift | stale", "checks": { "locations": { "ok": true, "found": "<what the code shows>", "proposed": ["<location>"] }, "kind": { "ok": false, "found": "module", "proposed": "component" }, "audience": { "ok": true }, "state": { "ok": false, "found": "open/planned", "proposed": "open/verified" }, "parent_key": { "ok": true }, "related": { "ok": true, "proposed": ["[[C-NNNN]]"] }, "body": { "Summary": { "ok": true }, "Statement": { "ok": false, "found": "<one line: what is wrong>", "proposed": "<text>" } } }, "kind_confidence": "high | low", "need_human_review": false, "reason": "<one sentence naming the evidence>"}]A check with ok: true may omit found and proposed. checks.body is absent when body
checks were not asked for. proposed for locations and
related is the full replacement list. proposed body text appears only when the prompt
asked for it. Keep each object under ~300 words.
Single message — every Agent call goes in one assistant turn.
Aggregate verdicts
Section titled “Aggregate verdicts”Merge every array into one list. A sub-agent that returned non-JSON marks every capability in
its group unreviewed with reason malformed verdict.
5. Reconcile (in-session)
Section titled “5. Reconcile (in-session)”Apply these checks to the merged list before rendering the report:
- Grain. A proposed
kindwithkind_confidencelow is not written; the row keeps the stored grain and gainsneed_human_review: true. - Audience. A proposed
audiencefollows the rubric’s surface test; a proposal without a named surface is dropped. - State. A proposed state follows the rubric’s table.
closed/retiredis never proposed or written. - Tree. A proposed
parent_keyorrelatedtarget must be an existing id, else the proposal is dropped and noted. - Rot. Every
anchor_rotrow in scope is part of its capability’slocationsproposal (drop or replace), or the row isstale. - Retire candidates. Every
stalecapability, and every capability whoseattachmentsis zero, is listed for the reader. Nothing is closed.
6. Render the report and confirm
Section titled “6. Render the report and confirm”Render one markdown report:
# Capability review — scope <scope>
<N> reviewed → <A> accurate, <D> drift, <S> stale, <U> unreviewed. <R> retire candidates.
| Capability | Verdict | Failing checks | Proposed ||---|---|---|---|| C-NNNN <title> | drift | kind, state | kind module→component; state planned→verified || C-NNNN <title> | drift | body: Statement | <one line> || C-NNNN <title> | stale | locations | package removed in <commit> |
## Retire candidates (<R>)- C-NNNN <title> — <stale reason | attachments 0>
## Needs human review (<H>)- C-NNNN — <why>In report mode, print the report, then print
CAPABILITY-REVIEW-REPORT scope=<scope> reviewed=<N> accurate=<A> drift=<D> stale=<S> and
stop. Body findings appear as one line each; the report never carries replacement prose.
Under --auto, proceed to Step 7. Otherwise ask via AskUserQuestion:
-
Apply the fixes as shown — every frontmatter proposal, and under
--rewriteevery body proposal. -
Walk one-by-one first — one follow-up question per drift/stale row (
apply,drop,mark need_human_review), then re-render and ask again. -
Cancel — tear down and stop:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc project teardown-worktree capability-review-<stem> \--branch chore/capability-review-<stem> \--project-root <worktree-parent-repo-root>
7. Write entities
Section titled “7. Write entities”From inside the worktree.
7a. Frontmatter (--fix)
Section titled “7a. Frontmatter (--fix)”For every reviewed capability, accurate rows included:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability update <C-NNNN-slug> \ --project-root <worktree-absolute-path> \ --set '{"last_reviewed": "<today>", "kind": "<grain>", "state": "<state>", "locations": [...], "related": [...], "need_human_review": true}'The positional is the file basename without .md. --set carries last_reviewed for every
row and only the fields the row’s accepted proposals change. It replaces a list field whole:
pass the full proposed locations or related, not the additions. Merge related by resolved
id, not by string: keep the file’s spelling for a target already present and never add a
second entry for it. Capture the path of every
updated file; Step 8 stages exactly these.
7b. Body sections (--rewrite only)
Section titled “7b. Body sections (--rewrite only)”For every accepted body proposal, Edit that section: replace its content, keep the
## <Heading> line, keep the first Summary bullet’s ^summary tag, wrap prose at 100
columns. Never add or delete a section; a missing optional section is a finding for the
reader, not a rewrite.
7c. Provenance
Section titled “7c. Provenance”A rewritten body is model text. Set provenance on that file to
sdlc:capability-review <scope> through the same capability update call as 7a, so the
stamp and the rewrite land together. Files whose body was not rewritten keep their
provenance.
7d. Validate
Section titled “7d. Validate”For every updated path:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc entities validate <path>Then:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability graph --project-root <worktree-absolute-path> --output jsonwarnings must contain nothing beyond the Step 2 baseline. A new warning is a defect in the
accepted proposals: fix the offending frontmatter with capability update and re-run. Do not
commit with a new warning; pre-existing corpus warnings are not this run’s to fix.
8. Commit, push, open PR
Section titled “8. Commit, push, open PR”Stage only the paths captured in Step 7, plus whatever git status --porcelain docs/ shows
after docs generate (it rewrites every index page; the pre-commit docs-drift check rejects a
stale one). Do not git add -A or glob the directory.
${CLAUDE_PLUGIN_ROOT}/cli/sdlc docs generate --project-root <worktree-absolute-path>git add <updated path>... <generated page>...${CLAUDE_PLUGIN_ROOT}/cli/sdlc commit create --message - <<'EOF'docs(capabilities): review <scope>: <N> reviewed, <F> fixed, <W> rewritten
Via /sdlc:capability-review.
Fixed:- C-NNNN — <fields set>
Rewritten:- C-NNNN — <sections>EOFgit push -u origin chore/capability-review-<stem>gh pr create --title "Capability review: <scope>" --body "<see below>"The message reaches git through the op’s temp file (the - sentinel). See
${CLAUDE_PLUGIN_ROOT}/conventions/commit-messages.md.
PR body shape:
## Summary
Capability review for `<scope>`: <N> reviewed, <A> accurate, <D> drift, <S> stale.<F> frontmatter fixes, <W> body rewrites, <R> retire candidates listed below; none closed.
## Fixed- C-NNNN — <field>: <before> → <after>
## Rewritten- C-NNNN — <section>: <one line on what changed>
## Retire candidates (not closed)- C-NNNN — <title>, <reason>
## Needs human review- C-NNNN — <why>
## How this was generated
`/sdlc:capability-review <scope> --fix [--rewrite]`: `sdlc capability coverage` and`sdlc capability graph` read-only, one read-only sub-agent per capability in a single messageapplying `conventions/capability-rubric.md`, one report, then `sdlc capability update`,`entities validate` on every file, and `capability graph` with no new warnings.9. Report
Section titled “9. Report”Print CAPABILITY-REVIEW-DONE pr=<url> reviewed=<N> fixed=<F> rewritten=<W> retire_candidates=<R>
and tell the user the PR URL, the fixed ids and fields, the rewritten ids and sections, the
retire candidates, the need_human_review set, and the worktree path.
Acceptance criteria
Section titled “Acceptance criteria”- With no scope the skill prints the
ERROR reason=line and writes nothing. - Without
--fixor--rewrite, the skill writes nothing: no worktree, no branch, no file. Its output is the report and theCAPABILITY-REVIEW-REPORTmarker. - Steps 2, 4, 5 and 6 are read-only; the first write is Step 3’s worktree, and the first
entity write follows the confirmation (or
--auto). - Under
--fix, every reviewed capability carries today’slast_reviewed; under--rewrite, every rewritten file carriesprovenance: sdlc:capability-review <scope>. - Every updated file passes
sdlc entities validate, andsdlc capability graphin the worktree reports no warning beyond the Step 2 baseline. - A low-confidence grain is never written; the row carries
need_human_review: true. - No capability is closed or deleted; retire candidates appear only in the report and PR body.
- One commit contains exactly the touched capability files; the branch is pushed; the PR URL
is reported with the
CAPABILITY-REVIEW-DONEmarker.
Failure modes
Section titled “Failure modes”capability coverageorcapability graphfails — stop, print stderr verbatim asERROR reason="...". Nothing else runs.- Sub-agent returned non-JSON — the row is
unreviewedwith reasonmalformed verdict; the batch continues, and the row is listed in the report. capability updatefails — stop and surface stderr. The worktree isolates the partial state; the user re-runs or cancels.- Validate fails after a body Edit — the Edit broke the body contract. Report the file’s findings, do not commit.
capability graphwarns anew after writes — a proposed parent or related target was wrong. Fix withcapability updateand re-run the check; do not commit with a new warning.
- A report by default. Writes need
--fixor--rewrite; the report never carries replacement prose, only findings. - Parallelism comes from one message. Step 4 dispatches every Agent call in a single response, one per group of up to five capabilities, not one per capability.
- One rubric.
${CLAUDE_PLUGIN_ROOT}/conventions/capability-rubric.mdis shared with/sdlc:capability-map; a decision this skill makes is the one map would make. - Retirement is a report. Stale rows and attachments of zero go in a table; the reader decides.
- Untyped links.
relatedis the only capability-to-capability link this skill writes. - Committing model-generated messages. See
${CLAUDE_PLUGIN_ROOT}/conventions/commit-messages.md. - Branch naming.
chore/capability-review-<stem>. See${CLAUDE_PLUGIN_ROOT}/conventions/branch-naming.md. - Worktree teardown is deferred. Cleanup after the PR merges;
/sdlc:project-cleanupsurfaces the merged branch and its worktree.