/sdlc:capability-map
Generated from solutions/ontological/plugin/plugins/sdlc/skills/capability-map/capability-map.md.
Description
Section titled “Description”Map out the capability graph for one scope of the project: survey the
code (or the product’s capability-map table), propose new Capability
entities where the map has gaps, enrich existing ones with locations,
grain, audience and related links, and report retire candidates. Runs
sdlc capability coverage and sdlc capability graph read-only,
dispatches one read-only sub-agent per candidate, renders one batched plan
for approval, then writes through sdlc capability create /
sdlc capability update and opens a PR. Invoke when capabilities are
missing, ungraded, unanchored, or when the System page’s capability view
looks empty for an area. Usage: /sdlc:capability-map <dir|C-NNNN|areas> [--dry-run] [--auto].
Allowed tools
Section titled “Allowed tools”ReadGlobGrepBashEditAgentAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:capability-map <dir>— survey the packages and crates under a directory and reconcile the capability corpus against them./sdlc:capability-map C-NNNN— re-map one capability’s subtree: enrich its members and survey the units they anchor./sdlc:capability-map areas— seed the top level: every row of the product entity’s capability-map table with no entity file becomes asystemroot.--dry-run— stop after the batched plan. Never creates a worktree, branch, or file.--auto— skip the confirmation prompt and run every non-skip verdict.
A scope is required. With no scope, print
ERROR reason="scope required: <dir>, C-NNNN, or areas" and stop. A whole-project sweep
produces a plan too large to review; run one directory at a time.
Project context (don’t re-derive every run):
- The read-only substrate is two ops.
sdlc capability coverage --scope <scope>joins the corpus against the manifest walk’s packages and crates:units(with the capabilities anchored to each),unanchored_units,unanchored_capabilities,anchor_rot, and a per-capabilityattachmentscount (inbound wikilinks plus resolved locations).sdlc capability graphis the corpus as a tree withrelatededges and a warning per danglingparent_key. - Writes go through
sdlc capability createandsdlc capability update. Their--helpis the contract. Never hand-roll capability frontmatter. - The rubric is
${CLAUDE_PLUGIN_ROOT}/conventions/capability-rubric.md, shared with/sdlc:capability-review; 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. - Links between capabilities are untyped
relatedwikilinks. Containment isparent_keyonly; children are derived. - Retirement is report-only. A zero-attachment capability lands in the plan’s 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>, --dry-run, --auto. Classify the scope: a path that exists is a dir; a
string matching C-NNNN is a subtree; the literal areas is a seed.
Pre-flight with the report-only probe:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc project preflight-worktree capability-map-<stem> \ --branch chore/capability-map-<stem> \ --project-root .<stem> is the scope’s last path segment, the capability id in lower case, or areas. 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 areas. Keep the warnings array from graph as the run’s baseline; Step 7d
compares against it.
For seed, run coverage with no --scope and read the product entity’s capability-map table
(docs/planning/products/PR-*.md, the section headed “the capability map”). Read
definition.md (see Project context).
Build the candidate list:
| Scope | Candidates |
|---|---|
dir | each id in unanchored_units; each id in unanchored_capabilities; each capability in capabilities whose kind is null |
subtree | each capability in capabilities; each id in unanchored_units |
seed | each table row whose “Capability entity” cell is not shipped and names no [[C-…]], unless an existing capability title already matches the area name |
If the list is empty, print CAPABILITY-MAP-NOOP scope=<scope> and stop.
3. Create the worktree
Section titled “3. Create the worktree”Skip under --dry-run. Otherwise:
git worktree add .sdlc/worktrees/capability-map-<stem> -b chore/capability-map-<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 candidate (single message, parallel)
Section titled “4. Dispatch one sub-agent per candidate (single message, parallel)”For every candidate, 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 one candidate it owns: for a unit, its
id,dir,kind,ecosystem; for a capability, its file path and coverage row; for a seed row, the table row and the matching “Areas in detail” row verbatim. - 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 parent or arelatedtarget is chosen from what exists. - The verdict contract below.
Per-candidate verdict contract
Section titled “Per-candidate verdict contract”Each sub-agent, in order:
- Read the unit (README, manifest, entry points, skill files) or the capability file.
- Decide the verdict:
new— the unit or row names an ability no capability describes.enrich— an existing capability describes it; supply the missinglocations,kind,audience,parent,related.fold— the unit belongs under an existing capability’slocationsrather than being its own.skip— scaffolding, a fixture, a build artifact, or already covered.
- Grade with the rubric: anchors decide the grain, the surface test decides the audience,
the state table decides the state. Low confidence sets
need_human_review. - Return a strict JSON object, no surrounding prose:
{ "candidate": "<id or path verbatim>", "verdict": "new | enrich | fold | skip", "target": "<C-NNNN for enrich/fold, else null>", "title": "<for new>", "kind": "<a grain from definition.md, or null>", "kind_confidence": "high | low", "audience": "user | system", "parent": "<C-NNNN or null>", "locations": ["<five-form Location>", "..."], "related": ["[[C-NNNN]]", "..."], "body": { "Summary": ["<first bullet, ends with ^summary>", "<second bullet>"], "Statement": "<one or two paragraphs>", "What it provides": ["<deliverable>", "..."], "Underlying implementation": ["<realizing path or skill>", "..."] }, "reason": "<one sentence>"}Omit body keys the evidence does not support. Keep each response under ~400 words.
Single message — every Agent call goes in one assistant turn.
Aggregate verdicts
Section titled “Aggregate verdicts”Merge into one list. A sub-agent that returned non-JSON becomes a skip with reason
malformed verdict, listed in the plan.
5. Reconcile (in-session)
Section titled “5. Reconcile (in-session)”Apply these checks to the merged list before rendering the plan:
- Dedupe. Two
newverdicts with the same title, or with overlappinglocations, merge into one. Anewwhose title or locations match an existing capability becomesenrichof it. - Tree. Every
parentis an existing id or anewin this plan. Aseedrow is a root (parentnull,kindsystem,titlethe area name verbatim). No product-level root above the areas. - Grain. A
neworenrichwithkind_confidencelow carriesneed_human_review: true. - Audience.
audience: userwith no user-facing location is flagged in the plan row. - Retire candidates. Every capability in scope, other than
open/plannedones and this plan’snewentries, whoseattachmentsis zero after the planned enrichment is listed for the reader. Nothing is closed. - Rot. Every
anchor_rotrow in scope becomes part of the owning capability’senrich(drop or replace the location), or is listed under skip with the reason.
6. Build the batched plan and confirm
Section titled “6. Build the batched plan and confirm”Render one markdown plan:
# Capability map plan — scope <scope>
<N> candidates → <A> new, <B> enrich, <F> fold, <S> skip, <R> retire candidates.
## New (<A>)- `<title>` — kind <kind>[?] · audience <audience> · parent <C-NNNN|root> - Locations: <n> · Related: <n> · Review: <yes|no>
## Enrich (<B>)- C-NNNN <title> — sets: <kind|audience|parent_key|locations(+n)|related(+n)>
## Fold (<F>)- <unit id> → C-NNNN (adds <location>)
## Retire candidates (<R>)- C-NNNN <title> — attachments 0
## Skip (<S>)- <candidate> — <reason>Under --dry-run, stop here and print the plan. Under --auto, proceed to Step 7.
Otherwise ask via AskUserQuestion:
-
Run the plan as shown — proceed with every non-skip verdict.
-
Walk one-by-one first — one follow-up question per new/enrich/fold item (
apply,drop,change verdict), then re-render and ask again. -
Cancel — tear down and stop:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc project teardown-worktree capability-map-<stem> \--branch chore/capability-map-<stem> \--project-root <worktree-parent-repo-root>
7. Write entities
Section titled “7. Write entities”From inside the worktree, in this order: roots before children, so a child’s --parent-key
names a minted id.
7a. New
Section titled “7a. New”${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability create \ --project-root <worktree-absolute-path> \ --title "<title>" \ [--kind <grain>] \ --audience <user|system> \ [--parent-key "[[C-NNNN]]"] \ [--locations <location>]... \ [--related "[[C-NNNN]]"]... \ [--tags <tag>]... \ [--need-human-review] \ --provenance "sdlc:capability-map <scope>" \ --created-at <ISO 8601 UTC timestamp>The slug positional is omitted: create derives it from --title. Pass --need-human-review
when the verdict set it. --provenance and --created-at mark the file as authored by this
run; one timestamp (date -u +%Y-%m-%dT%H:%M:%SZ) serves every create in the plan. Capture
the printed path and the minted id; later children reference it, and Step 8 stages exactly
these paths. To preview the slug and id first, or check a
collision, call sdlc capability preview-id "<title>".
7b. Enrich and fold
Section titled “7b. Enrich and fold”${CLAUDE_PLUGIN_ROOT}/cli/sdlc capability update <C-NNNN-slug> \ --project-root <worktree-absolute-path> \ --set '{"kind": "<grain>", "locations": [...], "related": [...], "need_human_review": true}'The positional is the file basename without .md (id plus slug, as capability graph lists it); a
bare id resolves only for unslugged files. --set replaces a list field whole: pass the merged
locations (existing minus rot plus new), not only the additions. Merge related by resolved
id, not by string: the corpus spells links slugged ([[C-V44L-priority-ordering-sorters]]) and
verdicts spell them bare ([[C-V44L]]); when a target is already present, keep the file’s
spelling and do not add a second entry. A fold is an update adding the unit’s directory to
locations.
7c. Fill body sections (applies under —auto too)
Section titled “7c. Fill body sections (applies under —auto too)”Each created file carries <...> placeholders. For every created path, Edit each section the
verdict’s body supplied: replace the placeholder block, keep the ## <Heading> line, keep the
first Summary bullet’s ^summary tag. Delete every optional section the verdict left unfilled
(Inputs, Outputs, Hook points, Underlying implementation, Notes); no placeholder
survives to the commit. The only sections that may be added are the optional
Contained sub-features and Lifecycle map: a root with children in this plan gets
Contained sub-features, listing them as wikilinks, in place of Inputs / Outputs.
7d. Validate
Section titled “7d. Validate”For every created or 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 (a dangling parent, an
unresolved related) is a defect in the plan: 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 Steps 7a and 7b, 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 <created path>... <updated path>... <generated page>...${CLAUDE_PLUGIN_ROOT}/cli/sdlc commit create --message - <<'EOF'docs(capabilities): map <scope>: <A> new, <B> enriched
Via /sdlc:capability-map.
New:- C-NNNN — <title> (<kind>)
Enriched:- C-NNNN — <fields set>EOFgit push -u origin chore/capability-map-<stem>gh pr create --title "Capability map: <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 map for `<scope>`: <A> new, <B> enriched, <F> folded, <S> skipped.<R> retire candidates listed below; none closed.
## New- C-NNNN — <title> · <kind> · <audience> · parent <C-NNNN|root>
## Enriched- C-NNNN — <fields>
## Retire candidates (not closed)- C-NNNN — <title>, attachments 0
## Needs human review- C-NNNN — <why the grain was uncertain>
## Skipped- <candidate> — <reason>
## How this was generated
`/sdlc:capability-map <scope>`: `sdlc capability coverage` and `sdlc capability graph`read-only, one read-only sub-agent per candidate in a single message, in-sessionreconciliation, one batched plan, then `sdlc capability create` / `update`, `entities validate`on every file, and `capability graph` with no new warnings.9. Report
Section titled “9. Report”Print CAPABILITY-MAP-DONE pr=<url> new=<A> enriched=<B> retire_candidates=<R> and tell the
user the PR URL, the new ids and titles, the enriched ids, 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. - Steps 1, 2, 4, 5 and 6 are read-only; the first write is Step 3’s worktree, after the
candidate list is non-empty, and the first entity write follows plan approval (or
--auto). - Every created or updated file passes
sdlc entities validate, andsdlc capability graphin the worktree reports no warning beyond the Step 2 baseline. - Every
newcarrieskindorneed_human_review: true; every low-confidence grain carriesneed_human_review: true. - No capability is closed or deleted; retire candidates appear only in the plan and PR body.
- One commit contains exactly the touched capability files; the branch is pushed; the PR URL
is reported with the
CAPABILITY-MAP-DONEmarker.
Failure modes
Section titled “Failure modes”capability coverageorcapability graphfails — stop, print stderr verbatim asERROR reason="...". Nothing else runs.- Sub-agent returned non-JSON — treat as
skipwith reasonmalformed verdict; the batch continues. capability create/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 parent or related target in the plan was wrong. Fix withcapability updateand re-run the check; do not commit with a new warning.
- No entity writes until Step 7. Step 3 creates only the worktree; sub-agents read; the orchestrator writes entities only after approval.
- Parallelism comes from one message. Step 4 dispatches every Agent call in a single response.
- One rubric.
${CLAUDE_PLUGIN_ROOT}/conventions/capability-rubric.mdis shared with/sdlc:capability-review; a decision this skill makes is the one review would make. - Untyped links.
relatedis the only capability-to-capability link this skill writes; a typed Relation entity is not activated by this skill. - Scope, not sweep. A directory at a time keeps the plan reviewable. Run
areasfirst on a corpus whose top level is prose; later runs hang code under those roots. - Retirement is a report. Attachments of zero go in a table; the reader decides.
- Committing model-generated messages. See
${CLAUDE_PLUGIN_ROOT}/conventions/commit-messages.md. - Branch naming.
chore/capability-map-<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.