-
Notifications
You must be signed in to change notification settings - Fork 0
Spec Prompt Format
Every improvement the advisor identifies becomes a spec prompt: a markdown
file written to be processed by the spec-kit lifecycle. The prompt is the
input /speckit.specify uses to generate the feature spec; /speckit.clarify,
/speckit.plan, /speckit.tasks, and /speckit.implement take it from
there.
The consumer of a spec prompt has zero context: it has not seen the advisor session, the audit, the other prompts, or any prior conversation. The format exists so the prompt works with nothing else.
The authoritative template ships with the extension:
templates/improve-spec-prompt-template.md.
For a filled-in prompt, see Examples.
- Self-contained context. Everything needed is in the file: affected files, code excerpts, conventions, commands. If anything requires knowledge from the advisor session, that knowledge gets inlined.
- Testable requirements. Every requirement and acceptance criterion can be checked, not judged.
- Hard boundaries. An explicit out-of-scope list, so the spec generated from the prompt does not sprawl into adjacent code.
Prompts live inside specs/, scoped to the spec they belong to:
specs/<spec-name>/improve/<NNN>-<plan-name>.md
- If an existing feature directory
specs/<NNN-name>/covers the area the improvement touches, the prompt goes in that directory'simprove/folder. - Otherwise the advisor creates a dedicated theme directory:
specs/<theme-slug>/improve/. Related improvements share the theme directory, for examplespecs/harden-auth/improve/001-rotate-session-tokens.mdandspecs/harden-auth/improve/002-add-csrf-protection.md. -
<plan-name>is a short imperative slug.<NNN>is a zero-padded execution-order prefix, applied to a folder'sTODOprompts only when it holds two or more: a topological sort ofdepends(dependencies first), tie-broken bypriority. It is derived from the frontmatter, never contradicts it, and is reassigned on each re-run; a lone prompt takes no prefix.dependsreferences siblings by their<plan-name>slug, so renumbering never breaks a link. - The prefix is scoped to its own
improve/folder (contiguous001..Nthere, and two folders may each start at001). It is not spec-kit's globalspecs/<NNN>-name/feature number, which/speckit.specifyassigns from its own sequential counter when a prompt becomes a spec, so it never aligns with the existing spec directories and cannot collide with them.
There is no central index file. Commands discover the backlog by globbing
specs/*/improve/*.md and reading frontmatter.
Every prompt starts with YAML frontmatter. It is the prompt's status record:
---
status: TODO # TODO | DONE | REJECTED
priority: P1 # P1 | P2 | P3
effort: M # S | M | L
risk: LOW # LOW | MED | HIGH
category: perf # bug | security | perf | tests | tech-debt | migration | dx | docs | direction
depends: [] # <plan-name> slugs of sibling prompts that must be DONE first
planned_at: abc1234 # short SHA of the commit the prompt was written against
issue: "" # GitHub issue URL, only when published via --issues
---Status meanings:
| Status | Meaning |
|---|---|
| TODO | Written and ready to hand to /speckit.specify. |
| DONE | Optional. You set it once the implementation has landed; nothing sets it automatically. |
| REJECTED | A re-run of /speckit.improve sets this when a finding no longer holds, with one line of rationale. |
The planned_at SHA is the drift contract: a re-run of /speckit.improve can
mechanically check whether the codebase changed under the prompt with one
git diff --stat <planned_at>..HEAD -- <affected paths>.
An imperative title: what will be true after the improvement lands.
What this improvement achieves and why it matters. 2 to 5 sentences: the
problem, its concrete cost today, and the measurable outcome once the spec
generated from this prompt is implemented. Written so /speckit.specify can
derive user scenarios and success criteria directly from it.
The facts about the code as it exists today, inlined. Never "as discussed" or "see audit":
- The affected components and files, each with one line on its role.
- Short excerpts of the current code (with
file:linemarkers), enough to confirm the right location and to survive a drift check. - The repo conventions that apply, with one exemplar file to match.
- The exact build / test / lint / typecheck commands for this repo (verified during recon, not guessed); these become verification gates in the generated spec and tasks.
The requirements and acceptance criteria the generated spec must encode, in four parts:
Requirements. Numbered, testable statements of WHAT must change, not how:
- R1: The order-list endpoint resolves customer names in a single query.
- R2: The public response shape does not change; clients depend on it.Acceptance criteria. Machine-checkable where possible. All must hold for the prompt to be DONE:
- [ ] `pnpm test -- orders` passes, including a new regression test for <X>
- [ ] `grep -rn "<old pattern>" src/` returns no matches
- [ ] <observable behavior>: <command or check> -> <expected result>Scope boundaries. Two lists. In scope: the only areas the implementation should touch. Out of scope: things that look related but must not change, each with a one-line reason (deprecated paths, behavior other code depends on, public contracts).
Risks and notes. Anything the spec author and implementer should know: assumptions that could be false (and what to do if they are), future changes that will interact with this, what a reviewer should scrutinize.
Every prompt is checked against this list before it is finished. The handoff
relies on it: /speckit.specify consumes the prompt with zero context, so any
gap here becomes a gap in the generated spec for /speckit.clarify to catch.
- Could
/speckit.specifygenerate a correct spec from this file plus the repo alone? If anything requires knowledge from the advisor session, inline that knowledge. - Is every requirement a testable statement, and every acceptance criterion a command or check with an expected result, not a judgment ("make sure it works")?
- Does the Current context name exact files and symbols with
file:linemarkers, and do the excerpts match the live code atplanned_at? - Are the scope boundaries explicit enough that the generated spec will not sprawl into adjacent code?
- No secret values anywhere in the file; locations and credential types only.
- The
planned_atSHA is filled in, and every slug independsresolves to a sibling prompt in the sameimprove/folder.