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 0e836ea..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 8076982..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\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 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. |