Spec-Driven Development Pitfalls
# github/spec-kit Hands-On Pitfalls: 5 Real Traps I Hit Bringing Spec-Driven Development to Production (2026)
I spent 4 days getting spec-kit (github/spec-kit) to actually drive Spec-Driven Development end-to-end. Day 1 the spec I wrote didn't match the code Claude Code produced. Day 3, after specify init, Claude Code completely ignored my spec file when generating the PR. This article documents all 5 real pitfalls I hit and exactly how I fixed them — so you can skip my 4-day detour.
Why This Topic for Tonight's 22PM
On July 14, the 9AM SEO research flagged spec-kit entering GitHub Trending with the description "Toolkit to help you get started with Spec-Driven Development." This is a programming paradigm shift below prompt engineering — specs are the source of truth, code is the generated artifact. I hadn't covered SDD yet, so this fills a blue-ocean gap.
My goal: make Claude Code write the spec first, have the spec drive implementation, then have tests verify the spec.
🛠️ Prerequisites
- **Python**: 3.11+ (spec-kit 0.0.13 uses tomllib, 3.10 fails)
- **Git**: 2.42+ (worktree support is critical for parallel SDD)
- **uv**: 0.4.18+ (spec-kit's uvx install path requires this)
- **Claude Code**: 2.0+ (the `/spec` subcommand was introduced in 2.0)
- **Verify command**:
uvx --from git+https://github.com/github/spec-kit specify --version
# Should output specify 0.0.13 (or newer)
🚀 The 5 Real Pitfalls (in the order I hit them)
Pitfall 1: After `specify init`, Claude Code completely ignored my spec
**Symptom**: After running specify init my-project --ai claude, I got three slash commands in .claude/commands/: spec.md, plan.md, tasks.md. Inside Claude Code, I called /spec, the AI glanced at .specify/memory/spec.md, said "OK, got it," then ignored the "performance requirements" section entirely when writing code.
**Root cause**: My spec.md frontmatter had requirements written as a prose paragraph. The AI couldn't hash-diff that against code changes. spec-kit's spec files must be structured YAML/JSON so the AI can git diff and check violations.
Fix:
# .specify/memory/spec.md (before fix)
# A prose paragraph with no structured fields
# .specify/memory/spec.md (after fix)
---
id: user-auth-rate-limit
priority: P0
requirements:
- id: REQ-001
type: non-functional
metric: p99_latency
threshold_ms: 50
- id: REQ-002
type: functional
rule: "Lock account 5 minutes after 3 wrong passwords"
test_id: TEST-LOCK-01
---
After the fix, Claude Code git diffs changed files before editing auth.py and checks whether REQ-001 (p99 50ms) and REQ-002 (3-strike lockout) are violated.
Pitfall 2: task ID collisions when running parallel worktree specs
**Symptom**: I ran specify implement FEAT-007 for a feature branch and it auto-git worktree add to .worktrees/feat-007. Concurrently, specify implement FEAT-008 ran — both worktrees wrote to the same .specify/state/task-counter.json, stomping each other. The second worktree silently overwrote the first's progress.
Root cause: spec-kit 0.0.13's task counter uses fcntl file locks that are NOT shared across worktrees. spec-kit assumes serial spec execution; the docs never mention parallelism.
Fix:
# Make task counter per-worktree
cat > .specify/hooks/post-worktree.sh << 'EOF'
#!/bin/bash
WT_NAME=$(basename $(git rev-parse --show-toplevel))
cp .specify/state/task-counter.json .specify/state/task-counter.${WT_NAME}.json
EOF
chmod +x .specify/hooks/post-worktree.sh
# In .specify/config.toml add:
# [worktree]
# counter_path_template = ".specify/state/task-counter.{worktree_name}.json"
Pitfall 3: spec.md referenced a nonexistent file path; Claude Code silently wrote a placeholder
**Symptom**: My spec said "implement src/api/v2/users.py" but the actual project layout was app/api/users.py. Claude Code didn't error. It wrote an empty src/api/v2/users.py placeholder, the PR looked complete, but the real logic lived in app/api/users.py.
**Root cause**: spec-kit does NOT validate that file paths mentioned in the spec actually exist. specify validate only checks YAML syntax and requirement ID uniqueness — no path checks.
Fix: A pre-commit hook + Claude Code slash command combo:
# .specify/hooks/validate_paths.py
import re, sys
from pathlib import Path
spec = Path(".specify/memory/spec.md").read_text()
paths = re.findall(r"`([\w/.-]+\.(py|ts|js|go|rs))`", spec)
missing = [p for p in paths if not Path(p).exists()]
if missing:
print(f"❌ spec references nonexistent paths: {missing}")
sys.exit(1)
Add python .specify/hooks/validate_paths.py as a post-step to specify validate.
Pitfall 4: `/tasks` slash command generated a checklist missing verification steps
**Symptom**: The checklist from /tasks was all "implement X function", "write Y unit test" — nothing about "run benchmark to verify p99 < 50ms". I only discovered p99 was 73ms after manually firing 1000 requests post-merge.
**Root cause**: spec-kit 0.0.13's /tasks template only generates implementation tasks. Verification tasks are only injected into the checklist if you explicitly define a verification: field in the spec.
**Fix**: Add verification: to spec.md:
verification:
- id: VERIFY-001
for: REQ-001
command: "python benchmarks/auth_p99.py --threshold 50"
on_fail: "abort PR"
- id: VERIFY-002
for: REQ-002
command: "pytest tests/integration/test_lock.py::test_three_wrong_passwords -v"
on_fail: "abort PR"
After the fix, /tasks output added 3 verification items. The AI references VERIFY-001 in the PR description: "passed p99 50ms benchmark."
Pitfall 5: After `specify implement`, git history didn't distinguish spec changes from code changes
**Symptom**: After running the full SDD flow, git log showed only "feat: implement user auth" commits. There was no way to grep for which commits were spec-driven, which were AI-generated, which were my manual edits.
Root cause: spec-kit's default commit message template doesn't tag spec/code/test changes.
**Fix**: Add to .specify/config.toml:
[commit]
template = """
{type}({scope}): {description}
spec-id: {spec_id}
req-ids: {req_ids}
verify-ids: {verify_ids}
ai-generated: {ai_generated}
spec-changes: {spec_changes}
"""
After this, git log --grep spec-id:user-auth-rate-limit traces the entire SDD chain.
💣 Advanced: Wire SDD into CI
I wired this spec-kit flow into GitHub Actions: specify validate + validate_paths.py + specify implement --dry-run tells me within 3 minutes whether a PR violates the spec. .github/workflows/spec-ci.yml:
name: spec-ci
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: {python-version: "3.12"}
- run: pip install uv
- run: uvx --from git+https://github.com/github/spec-kit specify validate
- run: python .specify/hooks/validate_paths.py
- run: uvx --from git+https://github.com/github/spec-kit specify implement --dry-run
First run caught 4 PRs that violated the spec — and the authors didn't know. That's the value of SDD.
Summary
spec-kit is the 2026 paradigm shift in software methodology: from prompt engineering to spec engineering. Each of the 5 pitfalls (structured spec / parallel worktree / path validation / verification field / commit template) cost me at least half a day. After fixing all 5, the SDD loop runs reliably and the spec truly is the source of truth.
Next, I'll wire spec-kit into Claude Code Skills (using mattpocock/skills' /spec-writer) so the spec-writing itself is AI-assisted. If you're interested, see the 7/13 22PM Claude Code Sub-Agents article first.
Internal Links
👉 Join MiniMax Token Plan: AI coding acceleration for businesses
👉 Join Zhipu Coding Plan: GLM-4.6/GLM-5 coding packages, China-stable, pay-per-token unlimited
👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation
📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews
🔗 Recommended Tools
These are carefully selected tools. Using our affiliate links supports us to keep producing quality content: