Setup Skill Discovery Wizard
You are the skill discovery wizard for the development-harness plugin. Your purpose is to
generate or regenerate .dh/skill_discovery.yaml — the project-local config file that drives
config-driven skill injection in add-new-feature Phase 3.
This wizard replaces the hardcoded keyword-to-skill mapping table with a per-project, customisable configuration that Phase 3 reads directly.
When This Skill Activates
User-invoked (/dh:setup-skill-discovery): Run the full interactive wizard (Steps 1–6).
Programmatic invocation from Phase 3 ($ARGUMENTS contains --auto): Run AUTO_MODE —
skip Step 5 (interactive questions), write best-effort draft immediately after Step 4.
References
All detailed lookup material lives in the references subdirectory. Consult the appropriate file at the workflow step where it is needed — do not pre-load all references at once.
references/skill_discovery-schema.md— canonical schema, field definitions, validation rules, examplesreferences/repo-inference-patterns.md— file presence → stack signal → candidate skills mapping tablereferences/wizard-questions.md— scripted question flows for each detected project typereferences/skill-marketplace-search.md— npx skills search invocation, output parsing, and install instructions
AUTO_MODE vs Interactive Mode
flowchart TD
Start([Skill invoked]) --> ArgCheck{"$ARGUMENTS contains --auto?"}
ArgCheck -->|Yes| AutoMode[AUTO_MODE active\nSkip Step 5\nWrite best-effort draft at end of Step 4]
ArgCheck -->|No| Interactive[Interactive mode\nAll 6 steps run\nUser confirms before write]
AutoMode --> S1
Interactive --> S1
S1([Step 1: Scan repo])
AUTO_MODE annotation: In AUTO_MODE, every entry added to the draft YAML config MUST be
annotated with the comment # AUTO_MODE: review and adjust as needed.
Wizard Flow — 6 Steps
Step 1: Scan Repo
Entry: Wizard has been invoked (interactive or AUTO_MODE).
Purpose: Infer the project's technology stack and purpose so skill candidates can be matched to real signals rather than guessed.
Actions:
-
Use the Read tool to attempt to read each of the following files (skip missing ones without error):
README.mdCLAUDE.mdpyproject.tomlpackage.jsonCargo.tomlGemfileVagrantfileDockerfiledocker-compose.yml(also checkdocker-compose.yaml)*.tf(find via Glob — read first match only)
-
Consult
references/repo-inference-patterns.mdto map file presence and content signals to:- Primary language(s)
- Frameworks and tooling
- Project purpose (plugin, CLI tool, web app, infrastructure, etc.)
-
Record inferred stack as
stack_signals— a list of plain-language strings used in Step 3.
Exit criteria: stack_signals list is populated (may be empty if no recognisable files
found; wizard proceeds with empty signals).
Error handling: If no project files are readable (e.g., run from wrong directory), record
stack_signals = [], emit a warning: "Warning: No recognisable project files found. Wizard
will produce a minimal template config. Adjust after creation." Continue to Step 2.
Step 2: Inventory Installed Skills
Entry: Step 1 complete. stack_signals known.
Purpose: Determine which skills are already installed so suggestions can be split into "ready to use" vs "requires installation".
Actions:
-
Run via Bash:
npx skills listParse the output: extract
provider:skill-nametokens (pattern:[a-z0-9-]+:[a-z0-9-]+) from each non-header line. Store asinstalled_skillslist. -
Also try
npx skills list -gif the first command returns empty output — some environments use-gfor the global registry.
Exit criteria: installed_skills list is populated (may be empty).
Error handling:
- If
npxis not available or command fails: setinstalled_skills = []. Annotate all skill suggestions in subsequent steps as# install status unknown — verify with: npx skills list. - If command succeeds but returns no parseable tokens: set
installed_skills = []. Continue.
For npx invocation details and output parsing, consult references/skill-marketplace-search.md.
Step 3: Search Marketplace for Skill Candidates
Entry: Step 2 complete. stack_signals and installed_skills known.
Purpose: Identify skill candidates relevant to this project's stack. Load candidate skill content to understand what each skill actually does before recommending it.
Actions:
-
For each signal in
stack_signals, consultreferences/repo-inference-patterns.mdto determine which skill names are associated with that signal. -
Assemble a
candidate_skillslist — de-duplicated, ordered by relevance. Cap at 8 candidates. Prefer installed skills over uninstalled ones. -
For each candidate in
candidate_skills: load its content using:Skill(skill="{provider:skill-name}")Read the skill description and first section to understand what it covers. Do NOT include the full loaded content in the wizard response — use it only for internal reasoning about whether to suggest this skill.
-
After loading, classify each candidate:
installed: present ininstalled_skillsavailable: not ininstalled_skills(will need install instructions in draft)
Exit criteria: candidate_skills list assembled with installed/available classification.
At least one candidate identified, OR candidate_skills = [] with a note that no relevant
skills were found for the inferred stack.
Error handling: If Skill() invocation fails for a candidate (skill not found): remove it
from candidate_skills. Continue with remaining candidates.
For marketplace search syntax, consult references/skill-marketplace-search.md.
Step 4: Build Draft Config
Entry: Step 3 complete. Classified candidate_skills list ready.
Purpose: Produce a draft skill_discovery.yaml that maps inferred stack signals to skill
candidates, annotated with reasoning.
Actions:
-
Read
references/skill_discovery-schema.mdto confirm current schema field names and validation rules before writing any YAML. -
Build the draft config using this structure (see full schema in
references/skill_discovery-schema.md):# .dh/skill_discovery.yaml # Generated by /dh:setup-skill-discovery wizard # Review and adjust entries as needed. skill_discovery: auto # auto | suggest | off always_use_skills: # unconditional; 0-2 recommended [] prefer_skills: # tiebreaker advisory; not added unconditionally [] avoid_skills: # never inject; overrides all rules [] skill_rules: # Each entry: when: <natural language condition> # use: [provider:skill-name, ...] -
Populate
skill_rulesentries based oncandidate_skills:- Group candidates by the stack signal that triggered them.
- Write one
skill_rulesentry per signal group, with a clearwhen:condition describing the scenario and ause:list of relevant skills. - Include only signal groups where at least one candidate was found.
- For uninstalled candidates: add an inline YAML comment with the install command.
Consult
references/skill-marketplace-search.mdfor install syntax. - Annotate each entry with a
# Reason:comment explaining why this skill was suggested.
-
If
candidate_skillsis empty: produce the minimal template only (all lists empty). -
In AUTO_MODE: annotate every populated entry with
# AUTO_MODE: review and adjust as needed.
Exit criteria: Draft YAML string produced and held in memory. In AUTO_MODE: skip to Step 6. In interactive mode: continue to Step 5.
Step 5: Interactive Questions (Interactive Mode Only — Skip in AUTO_MODE)
Entry: Step 4 complete. Draft YAML string ready. NOT in AUTO_MODE.
Purpose: Gather project-specific conventions from the user before writing the final config.
Actions:
-
Present the draft YAML to the user with an explanation:
Here is the proposed .dh/skill_discovery.yaml based on what I found in your repo: [draft YAML] I have a few questions to refine this before writing the file. -
Ask targeted questions filtered by detected stack, consulting
references/wizard-questions.mdfor the question bank and skip logic. Typically 4–7 questions apply per project. -
Apply user responses to the draft YAML.
-
Before writing, confirm meta-preferences:
- "Any additional
always_use_skillsyou want injected on every feature, regardless of type? (e.g., a code-review skill or a project-conventions skill)" - "Preferred mode — automatic injection (auto), advisory only (suggest), or disabled (off)? Default is auto."
- "Any additional
-
Ask for final confirmation: "Ready to write
.dh/skill_discovery.yaml? (yes / no / edit)" -
If user declines (responds "no" or "cancel" without requesting edits): emit the literal string
WIZARD_DECLINEDin the response and return immediately. Do NOT write any file. -
If user requests edits: apply the requested changes and return to sub-step 5 (re-present for confirmation). Maximum 3 edit cycles before writing as-is with a note.
Exit criteria: User confirms, OR WIZARD_DECLINED emitted and wizard returns.
Step 6: Write .dh/skill_discovery.yaml
Entry: Draft YAML confirmed (interactive: user said yes; AUTO_MODE: Step 4 complete).
Purpose: Atomically write the final config file to disk.
Actions:
-
Ensure the
.dh/directory exists. Create it if absent (it is a Tier 1 path — commit to git). -
Write the complete YAML string to
.dh/skill_discovery.yamlin a single Write tool operation. Do not append — write the entire file at once. -
Confirm success to the user:
.dh/skill_discovery.yaml written successfully. Next steps: - Review the file and adjust entries as needed. - Commit it to git — this file is project-local and should be version controlled. - Run /dh:add-new-feature on a test feature to verify skill injection works.In AUTO_MODE: omit the "Next steps" prompt — Phase 3 continues automatically.
Exit criteria: File exists at .dh/skill_discovery.yaml and is valid YAML.
Error handling: If Write fails: report the error. Do not retry silently. Let the caller (Phase 3 or user) decide how to proceed.
Suggest-Mode Fallback
When Phase 3 invokes this wizard and the wizard returns WIZARD_DECLINED, or if this wizard
is not invoked and no .dh/skill_discovery.yaml exists, Phase 3 operates in suggest mode:
Note: No .dh/skill_discovery.yaml configured. Skills that may be relevant: [judgment-based list].
To configure: /dh:setup-skill-discovery. Continuing without domain skill injection.
In suggest mode: domain_skills = []. Phase 3 continues without blocking. No error is raised.
Output Schema
The wizard writes a YAML file conforming to the schema in references/skill_discovery-schema.md.
The top-level fields are:
skill_discovery— mode:auto|suggest|off(default:auto)always_use_skills— list ofprovider:skill-namestrings; injected unconditionallyprefer_skills— tiebreaker advisory; not injected unconditionallyavoid_skills— never injected; overrides all rulesskill_rules— list of{when: <condition>, use: [provider:skill-name, ...]}entries
Unknown top-level keys are silently ignored for forward compatibility.
Malformed config (Phase 3 treats as empty): invalid YAML, skill_discovery value not in
{auto, suggest, off}, any list field is not a sequence, any skill_rules entry missing use
key, any use is not a sequence.
WIZARD_DECLINED Signal
If the user explicitly declines config creation in Step 5, emit the literal string
WIZARD_DECLINED as part of your response text before returning. This is the signal Phase 3
checks for to activate suggest-mode fallback. Do not write any partial file.
Success Criteria
The wizard succeeds when:
.dh/skill_discovery.yamlexists and contains valid YAML conforming to the schema inreferences/skill_discovery-schema.md.- Each
skill_rulesentry has a clearwhen:condition and at least oneuse:skill. - The file is committed to git (prompted to user; not enforced by wizard).
- Phase 3 can read and parse the file without error on the next
add-new-featurerun.