spec-council Skill
You are running the /spec-council skill. Execute all phases in order. Do not skip phases.
Hard Rules
- Never modify source code
- Never write directly into
.specify/yourself — that's GitHub Spec Kit's own infrastructure (templates/,scripts/,memory/,feature.json,integration.json). If Spec Kit's own skills are installed (see Phase 0), delegate to them and let them manage that state; you never touch it directly. - The only directory you write into yourself is this run's feature directory (
<FEATURE_DIR>, resolved in Phase 0/1) — specifically itscouncil/subdirectory always, and itsspec.md/plan.md/tasks.mdonly when Spec Kit's own skills aren't installed and you're using the fallback templates. - Show the user spec.md before proceeding to plan, unless
--autoflag passed - Council agents run sequentially — never in parallel
- If any council agent outputs
BLOCK, stop and surface findings before continuing - A fixed BLOCKER must be re-verified by a fresh run of the same agent before continuing — don't take your own amendment's word for it. Feed the agent its own prior report plus the amended artifacts and have it explicitly confirm the fix against source, not just re-read the new prose.
- A fixed CONCERN does not require a full agent re-run, but never leave its origin report silently claiming the issue is still open — append a one-line addendum to that report noting what changed and that it wasn't independently re-verified. An unamended report is a stale record the next agent (or a human) will otherwise trust at face value.
Phase 0 — Bootstrap
-
Determine the project root (directory containing
CLAUDE.md/AGENTS.md, or the current working directory). -
Detect whether GitHub Spec Kit is installed in this project:
test -d .specify && echo "SPECKIT_PRESENT" || echo "NO_SPECKIT"Do not use
which specifyfor this — that only checks whether the CLI binary happens to be installed globally on this machine, which tells you nothing about whether this project uses Spec Kit. -
Detect whether Spec Kit's own agent-native workflow skills are installed (regardless of which agent you are — check both known roots, either counts):
test -f .claude/skills/speckit-specify/SKILL.md -o -f .cursor/skills/speckit-specify/SKILL.md && echo "HAS_SPECKIT_SKILLS" || echo "NO_SPECKIT_SKILLS"Store as
HAS_SPECKIT_SKILLS(true/false). These are real, comprehensive skills (git branch hooks,[NEEDS CLARIFICATION]handling, quality-checklist validation) — when present, Phases 1–3 below delegate to them entirely rather than reimplementing any of that. -
Get the feature description:
- If the skill was invoked with arguments (e.g.
/spec-council add password reset), use those as the description. - If no arguments, ask the user (via a structured-choice tool like Claude Code's
AskUserQuestionif available, otherwise plain chat text): "What feature or change should I spec out? Describe it in 1–3 sentences."
- If the skill was invoked with arguments (e.g.
-
Read
CLAUDE.mdand/orAGENTS.md(project root, and nested ones likeapi/CLAUDE.mdif present) to load project architecture context. Inject this into every generation prompt and hand it to every council agent below.
<FEATURE_DIR> is not known yet at this point — it's resolved during Phase 1, either by Spec Kit's own speckit-specify skill or by the fallback logic below.
Phase 1 — Spec (spec.md)
Goal: produce a feature spec and learn <FEATURE_DIR> for every phase after this one.
If HAS_SPECKIT_SKILLS = true:
Read the full contents of whichever of these exists — .claude/skills/speckit-specify/SKILL.md or .cursor/skills/speckit-specify/SKILL.md — and follow it as your instructions verbatim, passing the feature description as its input. Let it handle numbering, git branch hooks, [NEEDS CLARIFICATION] prompts, and quality-checklist validation entirely on its own terms; don't second-guess or reimplement any of it.
After it completes, read .specify/feature.json and take its feature_directory field as <FEATURE_DIR> (e.g. specs/012-quote-export-print). This is Spec Kit's own authoritative record of the current feature — use it, don't re-derive the path yourself.
If HAS_SPECKIT_SKILLS = false:
Resolve <FEATURE_DIR> yourself:
- If
specs/doesn't exist, it will be created below. - Scan
specs/for existingNNN-*directories, find the highestNNN, add 1 (zero-padded to 3 digits). If none exist, start at001. - Slugify the feature description into a short kebab-case name (2–4 words, e.g. "PDF/print-friendly rendering of a quote" →
quote-export-print). <FEATURE_DIR>=specs/<NNN>-<slug>mkdir -p <FEATURE_DIR>
Write <FEATURE_DIR>/spec.md directly. Use the following structure:
# Spec: <Feature Name>
## Overview
<What this feature does and why it is needed. 2–4 sentences.>
## Requirements
1. <Functional requirement>
2. ...
## Acceptance Criteria
1. <Verifiable criterion — "given X, when Y, then Z" format preferred>
2. ...
## Technical Constraints
- <Existing patterns, libraries, or rules this must respect>
- <Architectural boundaries this project enforces (isolation model, soft-delete-only, etc.), if any>
## Out of Scope
- <Explicit exclusions to prevent scope creep>
Use the project's CLAUDE.md/AGENTS.md context to populate Technical Constraints accurately.
After spec is written (either path):
Show the user <FEATURE_DIR>/spec.md. Ask (via a structured-choice tool if available, otherwise plain chat text):
"Spec is ready. Proceed to plan, or should I clarify requirements first?"
- If clarify: spawn a
forkagent with prompt: "Read<FEATURE_DIR>/spec.md. Ask the user up to 5 targeted clarifying questions about ambiguities, then rewrite it incorporating the answers. Do not change the structure." (IfHAS_SPECKIT_SKILLSand aspeckit-clarifyskill exists at the same root asspeckit-specify, prefer delegating to that instead — it's built for exactly this.) - If proceed: continue.
Phase 2 — Plan (plan.md)
Goal: produce <FEATURE_DIR>/plan.md
If HAS_SPECKIT_SKILLS = true:
Read and follow .claude/skills/speckit-plan/SKILL.md or .cursor/skills/speckit-plan/SKILL.md (whichever exists) verbatim. It self-resolves the current feature (via .specify/scripts/bash/setup-plan.sh or equivalent) — you don't need to pass it <FEATURE_DIR> yourself.
If HAS_SPECKIT_SKILLS = false:
Write <FEATURE_DIR>/plan.md using this structure, informed by <FEATURE_DIR>/spec.md and the project's CLAUDE.md/AGENTS.md:
# Plan: <Feature Name>
## Approach
<Architecture decisions. Which patterns/layers are used. Why.>
## Files / Modules Affected
- `path/to/file.ts` — <what changes>
- ...
## Implementation Steps
1. <Step title> (deps: none)
<1–2 line description>
2. <Step title> (deps: step 1)
...
## Risks
- <Risk> — <Mitigation>
Phase 3 — Tasks (tasks.md)
Goal: produce <FEATURE_DIR>/tasks.md
If HAS_SPECKIT_SKILLS = true:
Read and follow .claude/skills/speckit-tasks/SKILL.md or .cursor/skills/speckit-tasks/SKILL.md (whichever exists) verbatim. Same self-resolution as Phase 2.
If HAS_SPECKIT_SKILLS = false:
Write <FEATURE_DIR>/tasks.md. Every task must be atomic (1 PR or less) and independently testable:
# Tasks: <Feature Name>
## Checklist
- [ ] T1: <Title> — <1-line description> (deps: none)
- [ ] T2: <Title> — <1-line description> (deps: T1)
- [ ] T3: <Title> — <1-line description> (deps: T1)
- [ ] T4: <Title> — <1-line description> (deps: T2, T3)
## Notes
<Any sequencing or parallelism notes>
Phase 4 — Council Review
By this point <FEATURE_DIR> is known (from Phase 1, either via .specify/feature.json or your own fallback resolution). Create its council subdirectory:
mkdir -p <FEATURE_DIR>/council
Run 4 agents sequentially, one isolated subagent per reviewer. This is a design choice, not a tool limitation — each reviewer explicitly builds on the prior ones' findings, so later agents need earlier reports to already exist. Run them in parallel and you lose that (each would start from zero findings), even on a runtime that supports parallel spawns.
Each agent runs as its own isolated subagent, not inline in this thread:
- Claude Code: the
Agenttool withsubagent_type: "fork". - Cursor: the
Tasktool withsubagent_type: "generalPurpose"— confirmed to spawn a genuinely isolated subagent with no parent-context visibility, with no.cursor/agents/*.mdfile needing to exist for that type first.
Use whichever of these your runtime provides. Both give the same property this phase depends on: a subagent that only sees what's in its prompt, not this thread's history.
Persona files live in this skill's own personas/ directory, next to this file. Resolve the path relative to this SKILL.md — do not assume a working-directory-relative path.
For each agent, spawn the isolated subagent with the prompt template below. In each template, <PERSONA> means: read the full contents of the named persona file from this skill's personas/ directory and follow it as your instructions for that phase, including its own "before you start" and output sections. Tell each agent explicitly what <FEATURE_DIR> resolved to for this run — the personas expect to be told this, not to guess it. Because the subagent has no visibility into this thread, its prompt must be fully self-contained — don't reference anything by "as discussed above," restate it.
Agent 1 — Domain Reviewer
Prompt:
<PERSONA: personas/domain-reviewer.md>
Feature directory for this run: <FEATURE_DIR>
Also read, if present:
- <FEATURE_DIR>/spec.md
- <FEATURE_DIR>/plan.md
- <FEATURE_DIR>/tasks.md
- .specify/memory/constitution.md
After agent completes, read <FEATURE_DIR>/council/01-domain.md and check for BLOCK. If BLOCK found, stop Phase 4, show findings to user (via a structured-choice tool if available, otherwise plain chat text), and ask: "Domain Reviewer blocked this spec. Amend spec/plan/tasks and re-run, or override and continue?"
Agent 2 — Architecture Guardian
Prompt:
<PERSONA: personas/architecture-guardian.md>
Feature directory for this run: <FEATURE_DIR>
Also read:
- <FEATURE_DIR>/spec.md
- <FEATURE_DIR>/plan.md
- <FEATURE_DIR>/tasks.md
- <FEATURE_DIR>/council/01-domain.md
Check for BLOCK before continuing (same handling as Agent 1).
Agent 3 — Security Auditor
Prompt:
<PERSONA: personas/security-auditor.md>
Feature directory for this run: <FEATURE_DIR>
Also read, if present:
- <FEATURE_DIR>/spec.md
- <FEATURE_DIR>/plan.md
- <FEATURE_DIR>/tasks.md
- <FEATURE_DIR>/council/01-domain.md
- <FEATURE_DIR>/council/02-architecture.md
- .specify/memory/constitution.md
Check for BLOCK before continuing.
Agent 4 — QA Planner
Prompt:
<PERSONA: personas/qa-planner.md>
Feature directory for this run: <FEATURE_DIR>
Also read:
- <FEATURE_DIR>/spec.md
- <FEATURE_DIR>/plan.md
- <FEATURE_DIR>/tasks.md
- <FEATURE_DIR>/council/01-domain.md
- <FEATURE_DIR>/council/02-architecture.md
- <FEATURE_DIR>/council/03-security.md
Check for BLOCK before continuing.
Phase 5 — Synthesis
-
Read all four council reports from
<FEATURE_DIR>/council/:01-domain.md02-architecture.md03-security.md04-qa.md
Before tallying, check each report against the current state of
spec.md/plan.md/tasks.md: if a CONCERN was fixed by direct edit after that report was written and the report was never re-verified (see Hard Rules), don't count it as open in the summary table below — but say so explicitly ("functionally resolved, report not re-verified — see note") rather than silently dropping it or silently presenting it as still-open. Both are dishonest; only a labeled reconciliation is accurate. -
Collect every
BLOCKERandCONCERNitem across all reports. -
For each BLOCKER that requires a new implementation task (not just a spec edit), append it to
<FEATURE_DIR>/tasks.md:- [ ] TC1: [Council] <title> — <what to implement to resolve blocker> (deps: <relevant task>)Prefix council-added tasks with
[Council]. -
Write
<FEATURE_DIR>/council/REPORT.md:
# Council Report — Summary
| Agent | Verdict | Blockers | Concerns |
|-------|---------|----------|----------|
| Domain Reviewer | <verdict> | <count> | <count> |
| Architecture Guardian | <verdict> | <count> | <count> |
| Security Auditor | <verdict> | <count> | <count> |
| QA Planner | <verdict> | <count> | <count> |
## All Blockers
<list from all reports>
## All Concerns
<list from all reports>
## Tasks Added by Council
<list of TC* tasks added, or "None">
## Final Status
APPROVED | APPROVED_WITH_CONCERNS | BLOCKED
-
Show the user
<FEATURE_DIR>/tasks.md(final) and<FEATURE_DIR>/council/REPORT.md. -
Print:
"Council complete. Artifacts in
<FEATURE_DIR>. Pick up tasks in your task manager or your usual implementation flow."
Phase 6 — Implementation Tracking
This phase runs during and after implementation (not during the council run itself).
Rule: Every time a task from <FEATURE_DIR>/tasks.md is fully implemented (code written, tests passing), immediately update it:
Change:
- [ ] T<n>: <title> ...
To:
- [x] T<n>: <title> ...
Do this per task, as soon as it completes — not in a batch at the end. This keeps tasks.md as a live progress tracker throughout the implementation session.
If multiple tasks complete in a single step, update all of them before moving on.
Artifact Map
specs/<NNN>-<feature-slug>/ ← <FEATURE_DIR>. Number/slug chosen by Spec Kit's own
speckit-specify skill when installed, or by this
skill's own fallback numbering otherwise.
spec.md ← Phase 1
plan.md ← Phase 2
tasks.md ← Phase 3 + amended in Phase 5
council/ ← always created and owned by this skill, never by Spec Kit
01-domain.md ← Phase 4 Agent 1
02-architecture.md
03-security.md
04-qa.md
REPORT.md ← Phase 5
If Spec Kit's own skills are installed, spec.md/plan.md/tasks.md (and anything else it creates, like checklists/) are entirely its own output — this skill only ever adds the council/ subdirectory alongside them.