/sdlc:find-verbs
Generated from solutions/ontological/plugin/plugins/sdlc/skills/find-verbs/find-verbs.md.
Description
Section titled “Description”Interactively populate or update named verb lists (setup, check, or
custom) in a project’s top-level sdlc.yaml. For check and setup, probes
the project root via sdlc quality detect and sdlc project detect-setup
respectively, presents the detected candidates through AskUserQuestion
(multiSelect), and writes the approved subset back to sdlc.yaml. For other
names, edits the current list without probing. Idempotent — re-running with
the same selection is a no-op. Runs standalone or as a called step of
/sdlc:setup.
Allowed tools
Section titled “Allowed tools”ReadWriteEditBashAskUserQuestion
Source
Section titled “Source”Usage:
/sdlc:find-verbs --name <verb>— probe the current project (if<verb>ischeckorsetup), present detected candidates, write the user-approved subset to<project-root>/sdlc.yaml’sworkflows.<verb>entry.
Read ${CLAUDE_PLUGIN_ROOT}/conventions/sdlc-yaml.md once before running this
skill — it documents the schema and execution semantics of workflows:.
Edit only <project-root>/sdlc.yaml; touch no other file.
1. Read the existing workflows.<name> list
Section titled “1. Read the existing workflows.<name> list”Read the current list deterministically:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc config get-verbs --name <verb> --config <project-root>/sdlc.yamlParse the JSON on stdout: verbs is the configured list in file order,
fileExists is whether sdlc.yaml is present. Remember verbs — those
entries pre-select in Step 3 so re-runs preserve prior choices.
A missing file is not an error (fileExists:false, verbs:[]); treat
the existing list as empty and Step 4 creates the file from scratch. If
the op exits non-zero (a present-but-malformed sdlc.yaml), surface its
stderr to the user and stop.
2. Probe the project for candidates (if applicable)
Section titled “2. Probe the project for candidates (if applicable)”If <verb> is check, shell out to the quality detector:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc quality detect --project-root <project-root>Parse the JSON on stdout (the op defaults to --output json). Detected tasks are under the tasks
key. The fields that matter here:
display— the shell verb a user would type. This is what goes intoworkflows.check:.runner— which tool owns it (just,node-scripts,make,cargo,python).source— the file that declares it, project-relative.origin—declaredwhen a config file states the task,synthesizedwhen it follows from a convention (cargo clippyandruff check .are not written down anywhere). Both are worth offering; mention which is which if the user asks why a command appears.
If <verb> is setup, shell out to the setup detector:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc project detect-setup --project-root <project-root>Parse the JSON on stdout. Candidates are under the candidates key; each entry has
{kind, name, command, source} fields, where kind is the family (deps,
git-hooks, tool-trust) and command is the shell verb a user would type.
If <verb> is neither check nor setup, skip probing entirely and proceed
directly to Step 3 (present the current list from Step 1 for editing).
A diagnostics array may be present in the quality detect output. Entries are
{runner, severity, message, source?}. Surface warning and error entries to
the user — a common one is that just is not installed, so recipe documentation
and parameters are missing from the report.
If the detector exits non-zero, surface its stderr to the user and stop.
If the tasks or candidates array is empty, tell the user no candidates were detected
and offer two options via AskUserQuestion:
- “Record ‘no verbs needed’ explicitly” — run
sdlc config set-verbs --name <verb> --verbs '[]' --config <project-root>/sdlc.yamlto write a starter file with an explicit emptyworkflows.<verb>: [](the op stamps the canonical header on create); then go to Step 5 to report and exit. - “Stop” — do nothing.
3. Present candidates to the user (if probed) or existing list for review
Section titled “3. Present candidates to the user (if probed) or existing list for review”If probed (Step 2 ran), call AskUserQuestion with a multiSelect field
listing every detected command as an option. Each option’s label is the command
itself (e.g. just full-check, bun run scripts/lint.ts); the option’s
description can cite the source and kind (“from Justfile”, “Bun script
under scripts/”, etc.).
If not probed (Step 2 skipped for custom verb names), present the existing list
from Step 1 and ask the user if they want to update it. Phrase as:
“Edit the verbs for <verb>? (current list has N entries)” or similar.
Pre-select any option whose command appears in the existing workflows.<verb>
list from Step 1 — this is what makes the skill idempotent under repeat runs.
For the probed case, phrase the question something like:
“Which of the detected commands should run as part of the <verb> lifecycle
for this project? (Select all that apply — these will be written to
sdlc.yaml’s workflows.<verb>: entry and executed in order.)”
Capture the user’s selection. Order the resulting list to match the order entries appear in the detector’s report (the detector already sorts deterministically), not the AskUserQuestion-return order.
4. Write sdlc.yaml
Section titled “4. Write sdlc.yaml”Hand the ordered selection from Step 3 to the write op as a JSON array:
${CLAUDE_PLUGIN_ROOT}/cli/sdlc config set-verbs --name <verb> --verbs '<json-array>' --config <project-root>/sdlc.yaml<json-array> is the detector-ordered selection (e.g. ["just ci","bun run scripts/lint.ts"]). The op:
- round-trips sibling
workflows.*names and comments untouched — it mutates theworkflows.<verb>key in place rather than re-dumping a plain object; - writes an explicit
workflows.<verb>: []on an empty selection (an explicit opt-out — never a key-delete); - stamps the canonical header when creating the file from scratch;
- is idempotent: a write whose list matches the existing one reports
unchanged:trueand leaves the file byte-for-byte untouched.
Parse the JSON on stdout: count is the configured verb count,
unchanged is the idempotent no-op flag, created is true on a
from-scratch write, path is the absolute file written. If the op exits
non-zero, surface its stderr and stop.
5. Report
Section titled “5. Report”Print a one-line summary to stdout, driven by the op’s output from Step 4
(unchanged, count, path):
FIND-VERBS-WROTE name=<verb> count=<count> path=<path>(or FIND-VERBS-UNCHANGED name=<verb> count=<count> path=<path> when the
op reported unchanged:true — the idempotent no-op case).
Tell the user the file path and remind them they can re-run this skill any time to update the list.
- Slug-namespaced markers. This skill’s terminal markers are prefixed
FIND-VERBS-(per${CLAUDE_PLUGIN_ROOT}/skills/CLAUDE.md) so a parent reading its output can’t mistake them for its own verdict. - Schema + execution semantics. See
${CLAUDE_PLUGIN_ROOT}/conventions/sdlc-yaml.md— theworkflows:section documents the map shape, verb names, executor paths, and cascade semantics. - Related surfaces.
/sdlc:setupcreates an empty startersdlc.yamlif absent and invokes this skill twice as Steps 6 and 7 (forcheckandsetuprespectively);sdlc quality run --name <verb>executes a configured list, andresolveWorkflowCommandsinlib/config/workflows.tsis what every consumer resolves a name through. - Idempotent. Re-running with no detector changes and the same user
selection is a no-op (the
FIND-VERBS-UNCHANGEDbranch above). The write op owns byte-for-byte parity; the skill’s only ordering obligation is to hand it the detector-sorted selection (Step 3), not the AskUserQuestion return order. - No commits. Write
sdlc.yaml; do not stage or commit it — leave that to the user. - Branch naming. When invoked inside a worktree (e.g. as part of
bootstrapping a new project’s planning setup), follow the existing
branch convention rather than inventing one. See
${CLAUDE_PLUGIN_ROOT}/conventions/branch-naming.md.