Skip to content

/sdlc:find-quality-checks

Generated from solutions/ontological/skills/find-quality-checks/SKILL.md.

Interactively populate or update the quality_checks: list in a project’s top-level sdlc.yaml. Probes the project root via sdlc quality detect, presents the detected runners through AskUserQuestion (multiSelect), and writes the approved subset back to sdlc.yaml. Idempotent — re-running with the same selection is a no-op. Runs standalone or as a called step of /sdlc:setup.

  • Read
  • Write
  • Edit
  • Bash
  • AskUserQuestion

Usage:

  • /sdlc:find-quality-checks — probe the current project, present detected quality-check candidates, write the user-approved subset to <project-root>/sdlc.yaml.

Read ${CLAUDE_PLUGIN_ROOT}conventions/sdlc-yaml.md once before running this skill — it documents the schema and execution semantics of quality_checks:.

Edit only <project-root>/sdlc.yaml; touch no other file.

Read the current list deterministically:

${CLAUDE_PLUGIN_ROOT}cli/sdlc config get-quality-checks --config <project-root>/sdlc.yaml

Parse 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 runner candidates

Section titled “2. Probe the project for runner candidates”

Shell out to the detector:

${CLAUDE_PLUGIN_ROOT}cli/sdlc quality detect --project-root <project-root>

Parse the JSON on stdout (the op defaults to --output json). Runners are under the runners key; each entry has {kind, name, command, source} fields; command is the shell verb a user would type. The detector is deterministic and best-effort — missing runners are simply absent from the report, not errors.

If the detector exits non-zero, surface its stderr to the user and stop.

If the runners array is empty, tell the user no runners were detected (no Justfile, no package.json scripts, no Makefile, no Python check scripts, no eval harnesses, no pyproject [tool.*] sections) and offer two options via AskUserQuestion:

  • “Open the empty sdlc.yaml in an editor” — run sdlc config set-quality-checks --verbs '[]' --config <project-root>/sdlc.yaml to write a starter file with an explicit empty quality_checks: [] and the canonical header (the op stamps it on create); then go to Step 5 to report and exit.
  • “Stop” — do nothing.

If the detector returned at least one runner, 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.).

Pre-select any option whose command appears in the existing quality_checks: list from Step 1 — this is what makes the skill idempotent under repeat runs.

Phrase the question something like: “Which of the detected commands should run as quality gates for this project? (Select all that apply — these will be written to sdlc.yaml’s quality_checks: list and executed in order by /sdlc:task-work Step 7.)”

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.

Hand the ordered selection from Step 3 to the write op as a JSON array:

${CLAUDE_PLUGIN_ROOT}cli/sdlc config set-quality-checks --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 top-level keys (worktree_init:, orchestrator:, …) and comments untouched — it mutates the quality_checks: key in place rather than re-dumping a plain object;
  • writes an explicit quality_checks: [] on an empty selection (the documented 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:true and 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.

Print a one-line summary to stdout, driven by the op’s output from Step 4 (unchanged, count, path):

FIND-QUALITY-CHECKS-WROTE quality_checks=<count> path=<path>

(or FIND-QUALITY-CHECKS-UNCHANGED quality_checks=<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-QUALITY-CHECKS- (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 — the quality_checks: section documents the list shape, the /sdlc:task-work Step 7 executor, and why an empty/missing list warns rather than silently passing.
  • Related surfaces. /sdlc:setup creates an empty starter sdlc.yaml if absent and invokes this skill as its Step 6; sdlc quality run executes the configured verbs; /sdlc:find-worktree-init is the twin configurator for the worktree_init: bootstrap list (setup’s Step 7).
  • Idempotent. Re-running with no detector changes and the same user selection is a no-op (the FIND-QUALITY-CHECKS-UNCHANGED branch 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.