From 7a16c795cac604ff60c9bbed4eb318803f5e2222 Mon Sep 17 00:00:00 2001 From: Kartik Jain Date: Sun, 26 Jul 2026 16:20:47 +0200 Subject: [PATCH 1/2] Fix stale component counts in session-start and PR template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SessionStart reminder announced "Seven skills" and "Five commands" when the plugin has had eight and six since 0.9.0, and its lists omitted ui-craft and /craftsman:orchestrate entirely — so every session started without being told two components existed. CI never caught this. The count validator skips any line containing "commands" when checking skill counts, and only matches the literal phrase "N slash commands" for command counts. The whole reminder is a single line reading "Five commands", so it evaded both checks. The PR template's example output was stale on two counts as well (5 commands, 2 hook events; actual: 6 and 4). Co-Authored-By: Claude Opus 5 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- craftsman-plugin/hooks/session-start | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0e836ea..2377613 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,7 @@ **Checklist** diff --git a/craftsman-plugin/hooks/session-start b/craftsman-plugin/hooks/session-start index 8076982..0f937e5 100644 --- a/craftsman-plugin/hooks/session-start +++ b/craftsman-plugin/hooks/session-start @@ -21,7 +21,7 @@ escape_for_json() { # converts actual newline bytes to \n exactly once. Embedding literal \n text # directly in this string would get its backslash doubled by escape_for_json's # backslash pass, producing a broken double-escaped \\n in the JSON output. -reminder=$'You have the craftsman plugin.\n\nSeven skills back the agents in this plugin — invoke them directly with the Skill tool when relevant, don\'t wait for an agent to reference them:\n- ideation-first: before planning an underspecified feature/greenfield refactor, ask a few clarifying questions and emit a Scope brief.\n- smallest-change-first: walk this before writing any new code, file, or dependency.\n- logging-tradeoffs: the KNOWN_ISSUES.md convention for documented shortcuts.\n- environment-memory: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a failed command/approach; append new quirks there.\n- caveats-and-status: every completed nontrivial task ends with separate Status and Caveats sections.\n- graphify-recurring-bugs: if graphify-out/graph.json exists in this project, use it during bug investigation before raw grep, to check whether a new bug is really a duplicate of an existing KNOWN_ISSUES.md entry, and to recall a resolved entry\'s known-good fix.\n- commit-craft: git/PR conventions — atomic commits, message format, branch naming, PR hygiene; only commits/pushes/PRs when asked.\n\nFive commands: /craftsman:init (project-level CLAUDE.md/KNOWN_ISSUES.md scaffold — always shows proposed content and asks before writing), /craftsman:quick (routes a small, explicitly-scoped change straight to the coder agent, skipping the full pipeline), /craftsman:doctor (checks the local install for known silent-failure conditions), /craftsman:review (routes a code-review task directly to the reviewer agent), and /craftsman:security (routes a security audit directly to the security agent).\n\nAt the start of any task, proactively: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a command or approach that failed, and if graphify-out/graph.json exists prefer graphify for navigation over raw browsing.\n\nHard rule across every agent in this plugin: never add a file, dependency, or code beyond the literal request without asking first.' +reminder=$'You have the craftsman plugin.\n\nEight skills back the agents in this plugin — invoke them directly with the Skill tool when relevant, don\'t wait for an agent to reference them:\n- ideation-first: before planning an underspecified feature/greenfield refactor, ask a few clarifying questions and emit a Scope brief.\n- smallest-change-first: walk this before writing any new code, file, or dependency.\n- logging-tradeoffs: the KNOWN_ISSUES.md convention for documented shortcuts.\n- environment-memory: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a failed command/approach; append new quirks there.\n- caveats-and-status: every completed nontrivial task ends with separate Status and Caveats sections.\n- ui-craft: before writing or changing any UI in any framework — design tokens, accessibility, responsive layout, motion restraint.\n- graphify-recurring-bugs: if graphify-out/graph.json exists in this project, use it during bug investigation before raw grep, to check whether a new bug is really a duplicate of an existing KNOWN_ISSUES.md entry, and to recall a resolved entry\'s known-good fix.\n- commit-craft: git/PR conventions — atomic commits, message format, branch naming, PR hygiene; only commits/pushes/PRs when asked.\n\nSix commands: /craftsman:init (project-level CLAUDE.md/KNOWN_ISSUES.md scaffold — always shows proposed content and asks before writing), /craftsman:orchestrate (runs the full pipeline on a task: classify, pick the minimal agent set, gate each stage on fresh evidence), /craftsman:quick (routes a small, explicitly-scoped change straight to the coder agent, skipping the full pipeline), /craftsman:doctor (checks the local install for known silent-failure conditions), /craftsman:review (routes a code-review task directly to the reviewer agent), and /craftsman:security (routes a security audit directly to the security agent).\n\nAt the start of any task, proactively: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a command or approach that failed, and if graphify-out/graph.json exists prefer graphify for navigation over raw browsing.\n\nHard rule across every agent in this plugin: never add a file, dependency, or code beyond the literal request without asking first.' reminder_escaped=$(escape_for_json "$reminder") session_context="\n${reminder_escaped}\n" From e6b9e6084c9a674f2336b304f0b57c378ce87c29 Mon Sep 17 00:00:00 2001 From: Kartik Jain Date: Sun, 26 Jul 2026 16:21:25 +0200 Subject: [PATCH 2/2] Add /craftsman:discover requirements interview (0.10.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turning a vague idea into something plannable had only one path: the shallow end of ideation-first — 3-5 questions and a three-line brief, with no way to invoke it deliberately. A substantially open request ("build a notifications system") got the same treatment as a merely fuzzy one, and the planner ran against guesses either way. Split across two surfaces because of a hard constraint: a subagent cannot conduct an interview. It gets one cold prompt and returns one result, which is why orchestrator already has to bounce underspecified features back to its caller. So the interview runs in the main thread as /craftsman:discover, and only the half a subagent is genuinely good at — reading the codebase — is delegated to the new read-only requirements-analyst, which drafts questions grounded in file:line evidence with an assumption default each, so the interview never stalls. ideation-first now runs at two depths. Quick is unchanged and still the default. Deep asks in 3-4 sequenced rounds of 2-4 questions rather than one per turn — one at a time is right for five questions and punishing for fifteen, and what that rule protects (later questions adapting to earlier answers) survives in sequenced rounds. It ends by writing a numbered spec, proposed and confirmed first, per the same ask-before-writing rule /craftsman:init follows. Deep mode carries an explicit "expand the questions, bound the scope" rule. Without it, raising error states and migration paths would have quietly contradicted smallest-change-first: a deep interview should end with the same scope as a quick one, held with more confidence and a longer out-of-scope list. The Scope brief is still emitted at both depths and remains the machine handoff the planner and the ideation gate consume; the spec file is additive. Verified: claude plugin validate --strict -> "Validation passed"; counts check reports 15 agents, 8 skills, 7 commands with no mismatches; frontmatter parses for every agent/skill/command; codespell clean; bash -n on both hooks; router emits one nudge naming /craftsman:discover; testbed checks 7 passed, 0 failed. Co-Authored-By: Claude Opus 5 --- .claude-plugin/marketplace.json | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- CHANGELOG.md | 58 +++++++++ README.md | 2 +- craftsman-plugin/.claude-plugin/plugin.json | 2 +- craftsman-plugin/README.md | 44 ++++++- craftsman-plugin/agents/orchestrator.md | 15 ++- .../agents/requirements-analyst.md | 83 +++++++++++++ craftsman-plugin/commands/discover.md | 59 ++++++++++ craftsman-plugin/commands/orchestrate.md | 5 +- craftsman-plugin/hooks/session-start | 2 +- .../hooks/userpromptsubmit-task-router | 2 +- .../skills/ideation-first/SKILL.md | 111 ++++++++++++++++-- 13 files changed, 357 insertions(+), 30 deletions(-) create mode 100644 craftsman-plugin/agents/requirements-analyst.md create mode 100644 craftsman-plugin/commands/discover.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 1118a7d..d7a1e5b 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "craftsman", "source": "./craftsman-plugin", "description": "Agent-discipline toolkit: portable agent set plus skills enforcing minimal-diff coding, root-cause debugging, recurring-bug detection via graphify, environment-quirk memory, and an ask-before-writing project scaffolder", - "version": "0.9.0", + "version": "0.10.0", "license": "MIT", "author": { "name": "bufferbrew", diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2377613..e23ffb2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,7 @@ **Checklist** diff --git a/CHANGELOG.md b/CHANGELOG.md index 21b3261..1b0b557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,64 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Version numbers track `.claude-plugin/plugin.json` (kept in sync with the root `marketplace.json`). +## [0.10.0] - 2026-07-26 + +### Added +- `/craftsman:discover `: a requirements-discovery interview that turns an + underspecified request into a numbered, testable spec. It exists because the shallow end of + `ideation-first` was the only option — 3–5 questions and a three-line brief, with no way to invoke + it deliberately, so a substantially open request ("build a notifications system") got the same + treatment as a merely fuzzy one. + + The work is split across two surfaces because of a hard constraint: **a subagent cannot conduct an + interview.** It receives one cold prompt and returns one result, which is why `orchestrator` already + has to bounce underspecified features back to its caller. So the interview runs in the main thread + as a command, and only the half a subagent is genuinely good at — reading the codebase — is + delegated. +- `requirements-analyst` agent (read-only: Read/Glob/Grep, Opus): drafts the clarifying questions a + request leaves unanswered, grounded in prior art and existing abstractions rather than a generic + checklist. Every question carries a `file:line` or an explicit "gap" label, plus an assumption + default so the interview never stalls on a declined question; questions the code already settles + come back as *constraints* instead. Capped at 10–20 questions — past that, it is asking things the + codebase already answers. It never asks the user anything itself and never writes files. + +### Changed +- `ideation-first`: now runs at two depths. **Quick** is unchanged and still the default (3–5 + questions, one per turn, Scope brief). **Deep** grounds 10–20 questions in the analyst's dossier and + asks them in **3–4 sequenced rounds of 2–4 questions** via `AskUserQuestion` — a deliberate + divergence from the one-question-per-turn rule, which is right for five questions and punishing for + fifteen. What the rule actually protects is that later questions adapt to earlier answers, and + sequenced *rounds* preserve that; batching all fifteen at once does not. + + Deep mode ends by writing a numbered requirements spec (`R1`, `R2`, … each with an acceptance + criterion, so `tester` and `reviewer` can trace coverage back to a requirement) at + `docs/requirements/.md` — proposed, shown in full, and written only on confirmation, per the + same ask-before-writing rule `/craftsman:init` follows. The **Scope brief** is still emitted inline + at both depths and remains the machine handoff the planner and the orchestrator's ideation gate + consume; the spec file is additive, and the brief gained a `Spec:` line pointing at it. + + New explicit rule: **expand the questions, bound the scope.** Deep mode raises error states, empty + states, migration, and offline behavior — then still recommends the smallest build that satisfies + the request, with everything surfaced but unagreed recorded under Out of scope. A deep interview + that ends with a *bigger* scope than a quick one has failed; it should end with the same scope, held + with more confidence and a longer out-of-scope list. Without this, deep mode would have quietly + contradicted `smallest-change-first`. +- `orchestrator`: the ideation gate now accepts either an inline Scope brief or a path to a + requirements spec, and instructs the planner to read the spec when one is named. Availability table + gains `requirements-analyst`. +- `/craftsman:orchestrate`: the ideation-gate step routes substantially open requests to deep mode + rather than a three-line brief. +- `userpromptsubmit-task-router`: the feature-shaped nudge names `/craftsman:discover` for + substantially open requests. Still one nudge per prompt; no new `case` branch. + +### Fixed +- `session-start` announced "Seven skills" and "Five commands" — both already wrong before this + release (8 and 6), and both invisible to CI: the count validator skips any line containing + "commands" when checking skills, and only matches the literal phrase "N slash commands" for + commands. The whole reminder is a single line, so both slipped through every check. The skill list + was also missing `ui-craft` and the command list was missing `/craftsman:orchestrate` — a session + therefore started without being told two components existed. + ## [0.9.0] - 2026-07-25 ### Added diff --git a/README.md b/README.md index e196e5a..d805fd0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ **craftsman** makes engineering discipline the default in [Claude Code](https://code.claude.com): the smallest correct change, no fix without a root cause, and an honest report of what was -actually verified. It bundles fourteen agents, eight skills, six slash commands, and a cross-platform +actually verified. It bundles fifteen agents, eight skills, seven slash commands, and a cross-platform hook system — installable in two commands.

diff --git a/craftsman-plugin/.claude-plugin/plugin.json b/craftsman-plugin/.claude-plugin/plugin.json index 1298cfc..e574f47 100644 --- a/craftsman-plugin/.claude-plugin/plugin.json +++ b/craftsman-plugin/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "craftsman", "description": "Agent-discipline toolkit: a portable agent set plus skills enforcing minimal-diff coding, root-cause debugging, recurring-bug detection via graphify, environment-quirk memory, and an ask-before-writing project scaffolder", - "version": "0.9.0", + "version": "0.10.0", "author": { "name": "bufferbrew", "email": "bufferbrew@gmail.com" diff --git a/craftsman-plugin/README.md b/craftsman-plugin/README.md index 4b90d06..172af11 100644 --- a/craftsman-plugin/README.md +++ b/craftsman-plugin/README.md @@ -12,8 +12,8 @@

A Claude Code plugin that makes engineering discipline the default: the smallest correct change, -no fix without a root cause, and an honest report of what was actually verified. Fourteen agents, eight -skills, six slash commands, and a cross-platform hook system. +no fix without a root cause, and an honest report of what was actually verified. Fifteen agents, eight +skills, seven slash commands, and a cross-platform hook system. ## Why craftsman @@ -51,11 +51,12 @@ Worked examples in [docs/use-cases.md](../docs/use-cases.md); contributions welc ``` craftsman-plugin/ ├── .claude-plugin/plugin.json Plugin manifest -├── agents/ Fourteen agents (see Agents reference) +├── agents/ Fifteen agents (see Agents reference) ├── skills/ Eight skills (see Skills reference) ├── commands/ │ ├── init.md /craftsman:init — project scaffolder │ ├── orchestrate.md /craftsman:orchestrate — full pipeline, end to end +│ ├── discover.md /craftsman:discover — requirements interview → numbered spec │ ├── quick.md /craftsman:quick — small-change fast path │ ├── doctor.md /craftsman:doctor — install health check (--fix to remediate) │ ├── review.md /craftsman:review — direct reviewer routing @@ -111,7 +112,7 @@ Or from inside a session: `/plugin marketplace add bufferBrew/craftsman` then `/plugin install craftsman@craftsman`. Restart Claude Code (or start a new session) after installing. Verify with `claude plugin list` -and inspect the loaded components with `claude plugin details craftsman` — it should report 14 agents. Claude Code counts commands as skills in the plugin details output: 8 skill files + 6 command files = 14 under the skills heading, and 4 hook events +and inspect the loaded components with `claude plugin details craftsman` — it should report 15 agents. Claude Code counts commands as skills in the plugin details output: 8 skill files + 7 command files = 15 under the skills heading, and 4 hook events (SessionStart, UserPromptSubmit, PreToolUse, Stop). Only SessionStart has an always-on cost (roughly 1.2k tokens per session); the other three are event-driven and inject a short nudge only when a real signal matches — no idle cost. ### Option C — install from a local marketplace checkout @@ -181,6 +182,34 @@ and the ideation gate needs interactive Q&A, which the main thread can hold and `@craftsman:orchestrator ` still works and is the right choice when you want the pipeline run in its own context. +### `/craftsman:discover ` + +Turns an idea that isn't specified well enough to plan into a numbered, testable requirements spec. +Runs the `ideation-first` skill's **deep mode**: + +1. Dispatches the read-only `requirements-analyst`, which reads the codebase and drafts the questions + the request leaves unanswered — each grounded in a `file:line` or labelled an explicit gap, with an + assumption default so the interview never stalls. Questions the code already answers come back as + *constraints*, not questions. +2. Interviews you in the main thread: 3–4 sequenced rounds of 2–4 related questions, via + `AskUserQuestion` so each is a click rather than an essay. Rounds are sequenced — purpose and scope, + then behavior and integration, then acceptance criteria — so later questions adapt to earlier + answers. +3. Proposes a spec at `docs/requirements/.md` (redirectable), shows the full content, and writes + only on confirmation. Every requirement is numbered `R1`, `R2`, … with an acceptance criterion, so + `tester` and `reviewer` can trace coverage back to a requirement. +4. Emits the `ideation-first` **Scope brief** inline as well — that block, not the spec file, is what + `planner` and the orchestrator's ideation gate consume. + +The interview runs in the main thread by necessity: a subagent gets one cold prompt and returns one +result, so it cannot hold a conversation. Only the question-drafting half is delegated. Use plain +`ideation-first` (3–5 questions, scope brief, no file) when the request is merely fuzzy rather than +substantially open — deep mode on a small feature is ceremony. + +**It expands the questions, not the scope.** The interview deliberately raises error states, empty +states, migration, and offline behavior — then still recommends the smallest build that satisfies the +request. Everything surfaced but not agreed lands under **Out of scope**, recorded rather than built. + ### `/craftsman:quick ` Fast path for genuinely small, well-understood edits — typo fixes, one-line logic changes, small @@ -205,6 +234,7 @@ Invoke any agent with `@craftsman: ` — plugin agents are namespace | Agent | Model | Writes files? | Use for | |---|---|---|---| | `orchestrator` | Opus | No (delegates) | Any multi-step task; picks the smallest pipeline, enforces gates, max 2 repairs per gate, structured report | +| `requirements-analyst` | Opus | No | Drafting the clarifying questions an underspecified request leaves open — grounded in prior art and `file:line` evidence, with an assumption default each. Returns a question dossier for a main-thread interviewer; asks the user nothing itself. Normally reached via `/craftsman:discover` | | `planner` | Haiku | No | Decomposing a feature/bug into ordered steps before coding | | `coder` | Opus | Yes | The implementation itself — minimal diff, runs the build, asks before adding anything extra | | `ui-designer` | Opus | Yes | UI-flavored implementation — detects the UI framework (Compose, Flutter, React, SwiftUI, web), applies design-system tokens, a11y, responsive layout per the `ui-craft` skill; minimal diff, runs the build | @@ -223,7 +253,9 @@ Invoke any agent with `@craftsman: ` — plugin agents are namespace - `quick` → `coder` alone - `feature` → *ideation gate* (if underspecified, main-thread `ideation-first` skill produces a - scope brief first) → `researcher?` → `planner` → `coder` → `tester` → `reviewer` → `docs-writer?` + scope brief first — or `/craftsman:discover` a full spec, via `requirements-analyst`, when the + request is substantially open) → `researcher?` → `planner` → `coder` → `tester` → `reviewer` → + `docs-writer?` - `bugfix` → `debugger` (read-only root-cause 4-phase method + quirks/KNOWN_ISSUES/graphify; hands off fix location + repro recipe) → `coder` → `tester` → `reviewer` - UI-flavored `feature`/`bugfix`/`quick` (screens, components, styling, layout) → same pipeline @@ -242,7 +274,7 @@ directly. | Skill | When it applies | |---|---| -| `ideation-first` | Before planning a new feature or greenfield refactor whose requirements aren't pinned down. Asks 3–5 clarifying questions one at a time, then emits a **Scope brief** (Goal / In scope / Out of scope / Key decisions / Open questions) the planner builds on. Skipped for well-specified requests, `quick`, and `bugfix`. Runs in the main thread (interactive). `/craftsman:orchestrate` runs it directly; the `@craftsman:orchestrator` subagent gates on the brief's presence rather than running it itself. | +| `ideation-first` | Before planning a new feature or greenfield refactor whose requirements aren't pinned down. Two depths: **quick** (default) asks 3–5 questions one at a time and emits a **Scope brief** (Goal / In scope / Out of scope / Key decisions / Open questions); **deep** (`/craftsman:discover`) grounds 10–20 questions in a `requirements-analyst` dossier, asks them in 3–4 sequenced rounds, and writes a numbered requirements spec — still emitting the brief, which stays the machine handoff. Expands the *questions*, not the scope: extra findings land in Out of scope. Skipped for well-specified requests, `quick`, and `bugfix`. Runs in the main thread (interactive). `/craftsman:orchestrate` runs it directly; the `@craftsman:orchestrator` subagent gates on the brief's presence rather than running it itself. | | `smallest-change-first` | Before writing any new code/file/dependency. Seven-step ladder: needs to exist? → already in codebase? → stdlib? → platform feature? → existing dependency? → one line? → only then write the minimum. Source of the "ask before anything extra" rule. | | `logging-tradeoffs` | When taking a deliberate shortcut, investigating a possibly-logged bug, or resolving an entry. Defines the `KNOWN_ISSUES.md` format: what changed / ceiling / upgrade trigger / status. | | `environment-memory` | Before retrying anything that failed once; after discovering an OS/shell/tool quirk. Reads/appends `~/.claude/craftsman-memory/environment-quirks.md`. | diff --git a/craftsman-plugin/agents/orchestrator.md b/craftsman-plugin/agents/orchestrator.md index 6883a08..1aa4aa2 100644 --- a/craftsman-plugin/agents/orchestrator.md +++ b/craftsman-plugin/agents/orchestrator.md @@ -109,11 +109,13 @@ researcher (only if APIs, libraries, or MCP-server coverage are unknown) → docs-writer (only if public API surface changed) ``` **Ideation gate (before planner):** if the request is underspecified — goal, boundaries, or -success criteria open to interpretation — and no **Scope brief** was supplied in your invocation, -**stop**. You are a subagent and cannot hold the interactive Q&A this needs. Instruct the caller to -run the `ideation-first` skill in the main thread first, then re-invoke you with the resulting scope -brief. Do **not** dispatch the planner against guesses. When a scope brief *is* present (or the -request is already well-specified), proceed and pass the brief into the planner's prompt verbatim. +success criteria open to interpretation — and neither a **Scope brief** nor a path to a requirements +spec was supplied in your invocation, **stop**. You are a subagent and cannot hold the interactive +Q&A this needs. Instruct the caller to run the `ideation-first` skill in the main thread first (or +`/craftsman:discover` for a substantially open request, which produces a numbered spec), then +re-invoke you with the resulting scope brief. Do **not** dispatch the planner against guesses. When a +brief *is* present (or the request is already well-specified), proceed and pass the brief into the +planner's prompt verbatim; if it names a spec file, tell the planner to read that path too. **bugfix** ``` @@ -232,7 +234,7 @@ ran did not verify anything. Never infer a passing build from an agent's confide | Agent | Gate — must pass before proceeding | |---|---| -| `ideation-first` (feature/greenfield refactor) | A **Scope brief** is present — either supplied in your invocation or produced by the main-thread skill — before the planner runs. If the request is underspecified and no brief exists, do not proceed; bounce back per the ideation gate. Well-specified requests pass this trivially. | +| `ideation-first` (feature/greenfield refactor) | A **Scope brief** is present — either supplied in your invocation or produced by the main-thread skill — before the planner runs, or the invocation names a requirements spec file the planner can read. If the request is underspecified and neither exists, do not proceed; bounce back per the ideation gate. Well-specified requests pass this trivially. | | `planner` | Output contains numbered steps and at least one "Files to change" entry. | | `debugger` | Root cause is stated in one sentence, the failure was reproduced (fresh output shown), and the hand-off names a fix location + failing-test spec. Read-only — it does not apply the fix. | | `coder` / `ui-designer` | Build passes — the project's declared build/verify command succeeds, AND the report shows fresh command output, not just a claim (verification-before-completion — no completion claim without evidence run in this session). | @@ -325,6 +327,7 @@ Read this before building any pipeline. Do not use agents marked "unavailable". ### Available — have .md files in this plugin's `agents/` directory | Agent | Role | Read-only? | |---|---|---| +| `requirements-analyst` | Drafts codebase-grounded clarifying questions for an underspecified request; returns a question dossier, asks the user nothing | Yes | | `planner` | Decomposes tasks into ordered steps | Yes | | `debugger` | Root-cause diagnosis: reproduce, trace, hand off fix location + repro recipe | Yes (+ Bash to reproduce) | | `coder` | Minimal-diff implementation, runs build | No | diff --git a/craftsman-plugin/agents/requirements-analyst.md b/craftsman-plugin/agents/requirements-analyst.md new file mode 100644 index 0000000..ac57ec2 --- /dev/null +++ b/craftsman-plugin/agents/requirements-analyst.md @@ -0,0 +1,83 @@ +--- +name: requirements-analyst +description: "Reads the codebase and drafts the clarifying questions an underspecified request leaves unanswered — grounded in prior art, existing abstractions, and declared constraints rather than a generic checklist. Returns a question dossier for a main-thread interviewer to ask; it never asks the user anything itself and never writes files. Normally invoked by /craftsman:discover rather than directly. Invoke for: 'what should I be asking about', 'what's unclear in this request', 'draft requirements questions for'." +tools: + - Read + - Glob + - Grep +model: opus +--- + +You are a read-only requirements analyst. You never edit or write files, and you never ask the user +a question directly — you are a subagent, so you cannot hold a conversation. Your entire deliverable +is a set of questions for someone else to ask. + +## Purpose + +Given a vague or underspecified request, work out what the codebase already answers and what it +does not, then produce the questions whose answers would make the request concrete enough to plan. + +The value you add over a generic requirements checklist is **grounding**. "How should errors be +handled?" is worthless. "`src/payment.js:42` retries on network failure but not on a 4xx — should +this new path follow the same rule?" is a question the user can answer in five seconds, and the +answer is a requirement. + +## Process + +1. **Locate the feature area.** Use Glob/Grep to find the files the request would touch. If you + cannot find them, say so — an analyst guessing at file layout produces questions about code that + doesn't exist. +2. **Find prior art.** Look for a feature that already does something similar, and for existing + abstractions the request could reuse. Anything reusable is a question: "reuse this, or is it + deliberately separate?" +3. **Read the project's CLAUDE.md (or AGENTS.md).** It may already answer questions you were about + to ask, and it declares constraints the request must fit inside. +4. **Trace the boundaries.** For the area you found, identify: who owns the data/state involved, + what the integration points are, and which error paths exist today. Each boundary the request + crosses without specifying behavior is a question. +5. **Derive questions from the gaps** — specifically from what the code does *not* determine. If the + code already fixes an answer, that is a constraint to report, not a question to ask. + +## Output format + +``` +**Prior art** +- + +**Detected constraints** +- + +**Candidate questions** + +** +1. + Why it matters: + Evidence: + +**Assumption defaults** +- Q: +``` + +Group questions under the categories that actually apply: purpose & users, scope boundaries, data & +state, error & edge behavior, integration & dependencies, non-functional (performance, +accessibility, security, offline), acceptance criteria, rollout & migration. Omit a category +entirely rather than padding it. + +Order questions within each category by how much the answer changes the implementation — the +question that forks the design goes first. + +## Constraints + +- **10–20 questions maximum.** Past that the interview stops being answerable. If you have more, + you are asking things the code already settles. +- **Every question needs evidence** — a `file:line`, or an explicit "gap" label. A question you + cannot ground is a question from a template, and it belongs in a checklist, not in your output. +- **Never ask what the code already answers.** That is a constraint to report under **Detected + constraints**, not a question. +- **Never propose an implementation.** Not a plan, not a file list, not an approach. Questions and + findings only — the planner runs later, after the answers exist. +- **Always supply an assumption default for every question.** The interviewer needs somewhere to go + when the user says "you decide" — an interview that stalls on an unknown is worse than one that + proceeds on a recorded assumption. +- **Report absence honestly.** If the codebase gives no signal on a topic, label it a gap. Do not + invent a plausible-sounding question to fill out a category. diff --git a/craftsman-plugin/commands/discover.md b/craftsman-plugin/commands/discover.md new file mode 100644 index 0000000..786d13e --- /dev/null +++ b/craftsman-plugin/commands/discover.md @@ -0,0 +1,59 @@ +--- +description: Turn a vague idea into concrete requirements — a codebase-grounded question interview ending in a numbered, testable spec. +argument-hint: +--- + +The user has an idea that isn't specified well enough to plan yet. This runs the `ideation-first` +skill's **deep mode**: a read-only agent reads the codebase and drafts the questions the request +leaves unanswered, then you conduct the interview here and produce a numbered requirements spec. + +Request: $ARGUMENTS + +This runs in the **main thread**, not as a subagent, and that is the whole point — an interview needs +back-and-forth with the user, and a subagent gets one cold prompt and returns one result. Only the +question-drafting half is delegated. + +1. **Check it's actually underspecified.** If the goal, boundaries, and done-condition are already + clear, say so and stop — point the user at `/craftsman:orchestrate` instead. Interrogating a clear + request wastes their time, and this command is easy to reach for by reflex. + +2. **Dispatch `requirements-analyst`** (one `Agent` call, `subagent_type: requirements-analyst`) with + the request and enough context to find the right code. It starts cold, so include the request + verbatim and the project root. Read back its dossier: prior art, detected constraints, candidate + questions with `file:line` evidence, and an assumption default per question. + + Note which questions it says the code *already* answers — those are constraints to state, not + questions to ask. + +3. **Read `${CLAUDE_PLUGIN_ROOT}/skills/ideation-first/SKILL.md`** and follow its deep process. + +4. **Interview in 3–4 rounds of 2–4 related questions**, using `AskUserQuestion` so each is a click + rather than an essay. Sequence the rounds — purpose and scope first, then behavior and + integration, then non-functional and acceptance criteria — so later rounds adapt to earlier + answers. Do not batch every question at once; that defeats the sequencing. + + When the user says "you decide" or "don't know": take the analyst's assumption default, record it + under **Assumptions**, and move on. Never stall the interview on a declined question. + +5. **Hold the scope while expanding the questions.** Ask about error states, empty states, migration, + offline, concurrency — then still recommend the *smallest* build that satisfies the request. + Everything surfaced but not agreed goes under **Out of scope**, recorded rather than built. A deep + interview should end with the same small scope as a quick one, held with more confidence and a + longer out-of-scope list. + +6. **Propose the spec, then write it.** Show the full content and the path + (`docs/requirements/.md` by default, redirectable) and wait for explicit confirmation before + writing anything. Never create the file or its parent directory unprompted. Number every + requirement `R1`, `R2`, … and give each an acceptance criterion — that numbering is what lets + `tester` and `reviewer` trace coverage back to a requirement later. + +7. **Emit the Scope brief block inline as well**, including its `Spec:` line. The spec file is for + humans; the brief is the handoff `planner` and `orchestrator` consume, and the orchestrator's + ideation gate checks for it. + +8. **Hand off.** Close by telling the user they can now run `/craftsman:orchestrate` (or + `@craftsman:orchestrator` with the brief pasted in, since a subagent can't see this conversation). + +Constraints: never write code or implement anything here — this command settles the *what*, and the +planner and coder handle the *how* afterwards. Never write the spec, or any other file, without +showing the content and getting confirmation first. diff --git a/craftsman-plugin/commands/orchestrate.md b/craftsman-plugin/commands/orchestrate.md index 2014d03..e632327 100644 --- a/craftsman-plugin/commands/orchestrate.md +++ b/craftsman-plugin/commands/orchestrate.md @@ -29,7 +29,10 @@ with the deviations noted above. The operational spine: boundaries, or success criteria open to interpretation — run the `craftsman:ideation-first` skill *first* and carry its Scope brief verbatim into the planner's prompt. Unlike the orchestrator subagent, which must bounce this back to its caller, you can hold that conversation - directly. Well-specified requests skip it. + directly. Well-specified requests skip it. If the request is *substantially* open — a whole new + surface, with real integration and error-handling questions — use the skill's deep mode (or send + the user to `/craftsman:discover`) for a numbered requirements spec instead of a three-line brief, + and pass the spec's path to the planner alongside the brief. 4. **Select the minimal pipeline** for the task type. Do not add agents the task doesn't require — more agents means more latency and noise. Parallel dispatch means multiple `Agent` calls in a diff --git a/craftsman-plugin/hooks/session-start b/craftsman-plugin/hooks/session-start index 0f937e5..56adb59 100644 --- a/craftsman-plugin/hooks/session-start +++ b/craftsman-plugin/hooks/session-start @@ -21,7 +21,7 @@ escape_for_json() { # converts actual newline bytes to \n exactly once. Embedding literal \n text # directly in this string would get its backslash doubled by escape_for_json's # backslash pass, producing a broken double-escaped \\n in the JSON output. -reminder=$'You have the craftsman plugin.\n\nEight skills back the agents in this plugin — invoke them directly with the Skill tool when relevant, don\'t wait for an agent to reference them:\n- ideation-first: before planning an underspecified feature/greenfield refactor, ask a few clarifying questions and emit a Scope brief.\n- smallest-change-first: walk this before writing any new code, file, or dependency.\n- logging-tradeoffs: the KNOWN_ISSUES.md convention for documented shortcuts.\n- environment-memory: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a failed command/approach; append new quirks there.\n- caveats-and-status: every completed nontrivial task ends with separate Status and Caveats sections.\n- ui-craft: before writing or changing any UI in any framework — design tokens, accessibility, responsive layout, motion restraint.\n- graphify-recurring-bugs: if graphify-out/graph.json exists in this project, use it during bug investigation before raw grep, to check whether a new bug is really a duplicate of an existing KNOWN_ISSUES.md entry, and to recall a resolved entry\'s known-good fix.\n- commit-craft: git/PR conventions — atomic commits, message format, branch naming, PR hygiene; only commits/pushes/PRs when asked.\n\nSix commands: /craftsman:init (project-level CLAUDE.md/KNOWN_ISSUES.md scaffold — always shows proposed content and asks before writing), /craftsman:orchestrate (runs the full pipeline on a task: classify, pick the minimal agent set, gate each stage on fresh evidence), /craftsman:quick (routes a small, explicitly-scoped change straight to the coder agent, skipping the full pipeline), /craftsman:doctor (checks the local install for known silent-failure conditions), /craftsman:review (routes a code-review task directly to the reviewer agent), and /craftsman:security (routes a security audit directly to the security agent).\n\nAt the start of any task, proactively: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a command or approach that failed, and if graphify-out/graph.json exists prefer graphify for navigation over raw browsing.\n\nHard rule across every agent in this plugin: never add a file, dependency, or code beyond the literal request without asking first.' +reminder=$'You have the craftsman plugin.\n\nEight skills back the agents in this plugin — invoke them directly with the Skill tool when relevant, don\'t wait for an agent to reference them:\n- ideation-first: before planning an underspecified feature/greenfield refactor, ask clarifying questions and emit a Scope brief. Two depths — quick (3-5 questions) by default, deep (a full requirements interview producing a numbered spec) for a substantially open request.\n- smallest-change-first: walk this before writing any new code, file, or dependency.\n- logging-tradeoffs: the KNOWN_ISSUES.md convention for documented shortcuts.\n- environment-memory: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a failed command/approach; append new quirks there.\n- caveats-and-status: every completed nontrivial task ends with separate Status and Caveats sections.\n- ui-craft: before writing or changing any UI in any framework — design tokens, accessibility, responsive layout, motion restraint.\n- graphify-recurring-bugs: if graphify-out/graph.json exists in this project, use it during bug investigation before raw grep, to check whether a new bug is really a duplicate of an existing KNOWN_ISSUES.md entry, and to recall a resolved entry\'s known-good fix.\n- commit-craft: git/PR conventions — atomic commits, message format, branch naming, PR hygiene; only commits/pushes/PRs when asked.\n\nSeven commands: /craftsman:init (project-level CLAUDE.md/KNOWN_ISSUES.md scaffold — always shows proposed content and asks before writing), /craftsman:orchestrate (runs the full pipeline on a task: classify, pick the minimal agent set, gate each stage on fresh evidence), /craftsman:discover (turns a vague idea into a numbered requirements spec — a codebase-grounded question interview), /craftsman:quick (routes a small, explicitly-scoped change straight to the coder agent, skipping the full pipeline), /craftsman:doctor (checks the local install for known silent-failure conditions), /craftsman:review (routes a code-review task directly to the reviewer agent), and /craftsman:security (routes a security audit directly to the security agent).\n\nAt the start of any task, proactively: check ~/.claude/craftsman-memory/environment-quirks.md before retrying a command or approach that failed, and if graphify-out/graph.json exists prefer graphify for navigation over raw browsing.\n\nHard rule across every agent in this plugin: never add a file, dependency, or code beyond the literal request without asking first.' reminder_escaped=$(escape_for_json "$reminder") session_context="\n${reminder_escaped}\n" diff --git a/craftsman-plugin/hooks/userpromptsubmit-task-router b/craftsman-plugin/hooks/userpromptsubmit-task-router index ad28a5b..d90968a 100644 --- a/craftsman-plugin/hooks/userpromptsubmit-task-router +++ b/craftsman-plugin/hooks/userpromptsubmit-task-router @@ -45,7 +45,7 @@ case "$low" in *"pull request"*|*" commit"*|*"git push"*) emit "Version-control request: apply craftsman:commit-craft (atomic commits, message format, branch naming). Commit/push/PR only when asked." ;; *implement*|*"add a "*|*"add support"*|*"new screen"*|*"build a "*|*"new feature"*|*"let users"*) - emit "Feature-shaped request: if underspecified, run craftsman:ideation-first for a scope brief first; then plan, then walk craftsman:smallest-change-first before writing. Close with Status + Caveats." ;; + emit "Feature-shaped request: if underspecified, run craftsman:ideation-first for a scope brief first (or /craftsman:discover for a substantially open request — it grounds the questions in the codebase and produces a numbered spec); then plan, then walk craftsman:smallest-change-first before writing. Close with Status + Caveats." ;; esac exit 0 diff --git a/craftsman-plugin/skills/ideation-first/SKILL.md b/craftsman-plugin/skills/ideation-first/SKILL.md index 8d14898..fa0ccf2 100644 --- a/craftsman-plugin/skills/ideation-first/SKILL.md +++ b/craftsman-plugin/skills/ideation-first/SKILL.md @@ -1,6 +1,6 @@ --- name: ideation-first -description: Use before planning a new feature or greenfield refactor whose requirements aren't yet pinned down — clarifies intent through a few questions and ends with a short scope brief the planner can build on. +description: "Use before planning a new feature or greenfield refactor whose requirements aren't yet pinned down — clarifies intent through questions and ends with a scope brief the planner can build on. Runs at two depths: quick (3–5 questions, the default) and deep (a full requirements interview producing a numbered spec, used by /craftsman:discover or when asked for thorough requirements)." --- # Ideation First @@ -31,25 +31,108 @@ down** — the goal, the boundaries, or the success criteria are open to interpr If you find yourself asking questions whose answers you already have, stop — you're past the point this skill is for. -## The process +## Two depths -Keep it lightweight. The value is a locked scope, not ceremony. +| | **Quick** (default) | **Deep** | +|---|---|---| +| When | Any underspecified feature; the model routes here on its own | `/craftsman:discover`, or the user asks for thorough/complete requirements | +| Questions | 3–5, one per turn | 10–20, batched into 3–4 rounds | +| Grounding | Whatever context you already have | A `requirements-analyst` dossier read from the codebase first | +| Output | **Scope brief** | Numbered requirements spec written to a file, **plus** the scope brief | + +Quick is the default. Escalate to deep only when the request is substantially open — a whole new +surface, a feature with real integration and error-handling questions, something a three-line brief +would visibly under-serve. Deep mode on a small feature is ceremony, and ceremony is the failure mode +this skill is most likely to fall into. + +## Expand the questions, bound the scope + +These pull in opposite directions and both are required. + +**Expand the questions.** Ask about the things the user hasn't thought about — error states, empty +states, concurrent access, migration of existing data, what happens offline. Surfacing a requirement +is free; discovering it after implementation is not. + +**Bound the scope.** Surfacing a requirement is not the same as agreeing to build it. When the +request is open-ended, propose the *smallest* thing that satisfies it and confirm — don't quietly +scope in an ambitious version. Everything surfaced but not agreed goes in **Out of scope**, where it +is recorded rather than built. + +This is `smallest-change-first` applied to requirements: ask broadly, build narrowly. A deep +interview that ends with a bigger scope than a quick one has failed, not succeeded — it should end +with the *same* small scope, held with more confidence and a longer out-of-scope list. + +## The quick process 1. **Ask 3–5 clarifying questions, one at a time.** One question per turn — each answer informs the next. Cover **purpose** (what problem does this solve, for whom), **constraints** (what must it fit within — existing patterns, platforms, non-negotiables), and **success criteria** (how do we know it's done and right). -2. **Prefer the minimal interpretation.** When the request is open-ended, propose the smallest thing - that satisfies it and confirm — don't quietly scope in an ambitious version. This is - `smallest-change-first` applied to requirements: don't build features nobody asked for (YAGNI). +2. **Prefer the minimal interpretation** — see above. 3. **Propose 2–3 approaches** when there's a real design fork, each with its trade-off and your recommendation. Lead with the one you'd pick and say why. -4. **Confirm, then write the scope brief.** Once the user agrees, produce the brief below — it - becomes the planner's input. +4. **Confirm, then write the scope brief.** + +## The deep process + +1. **Ground the questions first.** Dispatch `@craftsman:requirements-analyst` with the request and + read back its dossier: prior art, detected constraints, candidate questions with evidence, and an + assumption default per question. Questions derived from code beat questions derived from a + template — and the analyst also tells you which questions *not* to ask because the code already + settles them. +2. **Ask in rounds, not one at a time.** Group the dossier's questions into **3–4 rounds of 2–4 + related questions**, and use `AskUserQuestion` so each is a choice rather than an essay. Sequence + the rounds so later ones adapt to earlier answers: purpose and scope first, then behavior and + integration, then non-functional and acceptance criteria last (they depend on everything above). + + > This is a deliberate divergence from quick mode's one-question-per-turn rule. One at a time is + > right for 3–5 questions and punishing for fifteen. What matters is that the *rounds* are + > sequenced — batching all fifteen at once means nothing adapts, which is the actual thing the + > one-at-a-time rule exists to prevent. + +3. **Never stall on an unknown.** "You decide", "don't know", "not sure yet" → take the analyst's + assumption default, record it under **Assumptions** in the spec, and move on. Do not re-ask, and + do not block the interview on a question the user has declined. +4. **Fill the categories that apply**: purpose & users, scope boundaries, data & state, error & edge + behavior, integration & dependencies, non-functional (performance, accessibility, security, + offline), acceptance criteria, rollout & migration. Skip a category rather than padding it. +5. **Propose the spec, confirm, then write it.** Show the full proposed content and the path, wait + for explicit confirmation, then write. Never create the file or its directory unprompted — this is + the same ask-before-writing rule `/craftsman:init` follows. +6. **Emit the scope brief too**, inline. The spec is the human artifact; the brief is the machine + handoff, and the planner and orchestrator both consume it. + +## The requirements spec (deep mode) + +Default path: `docs/requirements/.md` in the target project. Offer it as a default the user can +redirect. + +``` +# — requirements + +**Context** — the problem, who's affected, what prompted this. +**Goals** — what this must achieve. +**Non-goals** — what it deliberately does not achieve. + +**Requirements** +- R1 (MUST) — +- R2 (SHOULD) — + +**Acceptance criteria** +- R1: Given , when , then . + +**Out of scope** — surfaced during the interview, deliberately not built. +**Assumptions** — questions the user declined, and the default taken for each. +**Key decisions** — choices made during the interview, and why. +``` + +Number every requirement (`R1`, `R2`, …) and keep each one independently testable. The numbering is +what lets `tester` and `reviewer` trace coverage back to a specific requirement — a spec written as +prose paragraphs can't be checked off. ## The scope brief -End by producing this block. It is the hand-off to the planner; keep it compact. +End by producing this block — at both depths. It is the hand-off to the planner; keep it compact. ``` **Scope brief** @@ -58,18 +141,24 @@ End by producing this block. It is the hand-off to the planner; keep it compact. - Out of scope: - Key decisions: - Open questions: +- Spec: ``` When routing through `@craftsman:orchestrator`, pass this brief in the invocation so the planner receives it — a cold subagent can't see the conversation it wasn't part of. (`/craftsman:orchestrate` -runs in the main thread, so it already has the brief.) +and `/craftsman:discover` run in the main thread, so they already have the brief.) ## Red flags | Thought | Reality | |---|---| | "I get the gist, I'll just start coding" | A gist is not an agreed scope. Confirm the what first. | -| "I'll ask all my questions at once" | One at a time — each answer changes what you'd ask next. | +| "I'll ask all my questions at once" | Quick mode: one at a time. Deep mode: 3–4 sequenced rounds. Either way, later questions must be able to adapt to earlier answers. | | "The request was vague, so I'll pick something ambitious" | Pick the *minimal* interpretation and confirm it. Scope creep starts here. | | "This feature is obviously simple, skip the brief" | Simple-looking features are where unexamined assumptions cost the most. The brief can be three lines, but write it. | | "The out-of-scope list is empty" | If nothing is out of scope, you haven't bounded anything. Name what you're deliberately not doing. | +| "Deep mode means fifteen questions, so I'll find fifteen" | Questions the code already answers are noise. Ten grounded questions beat twenty padded ones — and the analyst's dossier tells you which are which. | +| "I batched all the rounds to save time" | Then nothing adapted, and you asked round 3's questions without round 1's answers. Sequence the rounds. | +| "The user didn't know, so I'll come back to it" | Take the assumption default, record it under Assumptions, move on. A stalled interview ships nothing. | +| "The spec captures the requirements, criteria can come later" | A requirement with no acceptance criterion isn't testable, so nobody can tell whether it was met. They come from the same conversation — write them now. | +| "Deep mode surfaced more, so the scope grew" | Ask broadly, build narrowly. Extra findings belong in Out of scope, not in the build. |