specpipe 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -1220
- package/package.json +3 -2
- package/src/cli.js +16 -6
- package/src/commands/diff.js +1 -1
- package/src/commands/init-agents.js +40 -20
- package/src/commands/init-global.js +88 -33
- package/src/commands/init-interactive.js +71 -0
- package/src/commands/init.js +61 -22
- package/src/commands/remove.js +159 -49
- package/src/commands/upgrade.js +21 -56
- package/src/lib/agent-guards.js +34 -78
- package/src/lib/agent-install.js +38 -25
- package/src/lib/agents.js +53 -11
- package/src/lib/claude-global.js +50 -77
- package/src/lib/hooks.js +203 -0
- package/src/lib/installer.js +73 -61
- package/src/lib/reconcile.js +13 -8
- package/templates/{.claude/hooks → hooks}/file-guard.js +26 -21
- package/templates/hooks/specpipe-read-guard.sh +94 -21
- package/templates/hooks/specpipe-shell-guard.sh +121 -29
- package/templates/rules/specpipe-rules.md +77 -0
- package/templates/skills/sp-build/SKILL.md +101 -1
- package/templates/skills/sp-build-behavior-matrix/SKILL.md +876 -0
- package/templates/skills/sp-challenge/SKILL.md +34 -0
- package/templates/skills/sp-challenge-behavior-matrix/SKILL.md +289 -0
- package/templates/skills/sp-explore/SKILL.md +132 -0
- package/templates/skills/sp-explore-behavior-matrix/SKILL.md +862 -0
- package/templates/skills/sp-fix/SKILL.md +73 -1
- package/templates/skills/sp-fix-behavior-matrix/SKILL.md +338 -0
- package/templates/skills/sp-investigate/SKILL.md +70 -0
- package/templates/skills/sp-investigate-behavior-matrix/SKILL.md +718 -0
- package/templates/skills/sp-plan/SKILL.md +90 -0
- package/templates/skills/sp-plan-behavior-matrix/SKILL.md +1037 -0
- package/templates/skills/sp-review/SKILL.md +29 -3
- package/templates/skills/sp-review-behavior-matrix/SKILL.md +294 -0
- package/templates/.claude/CLAUDE.md +0 -79
- package/templates/.claude/hooks/path-guard.sh +0 -118
- package/templates/.claude/hooks/self-review.sh +0 -27
- package/templates/.claude/hooks/sensitive-guard.sh +0 -227
- package/templates/.claude/settings.json +0 -68
- package/templates/docs/WORKFLOW.md +0 -325
- package/templates/docs/specs/.gitkeep +0 -0
- package/templates/rules/specpipe-guards.md +0 -40
- package/templates/scripts/test-hooks.sh +0 -66
- /package/templates/{.claude/hooks → hooks}/comment-guard.js +0 -0
- /package/templates/{.claude/hooks → hooks}/glob-guard.js +0 -0
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# sensitive-guard.sh — PreToolUse hook for Claude Code
|
|
3
|
-
#
|
|
4
|
-
# Blocks access to sensitive files: .env, private keys, credentials, tokens.
|
|
5
|
-
# Supports .agentignore for project-specific patterns.
|
|
6
|
-
#
|
|
7
|
-
# Exit codes:
|
|
8
|
-
# 0 — access allowed
|
|
9
|
-
# 2 — access blocked (sensitive file)
|
|
10
|
-
#
|
|
11
|
-
# Environment:
|
|
12
|
-
# SENSITIVE_GUARD_EXTRA — additional pipe-separated filename patterns to block
|
|
13
|
-
|
|
14
|
-
set -euo pipefail
|
|
15
|
-
|
|
16
|
-
# Windows note: this hook requires bash (WSL or Git Bash).
|
|
17
|
-
# On Windows without bash, Claude Code will fail to run this hook and skip it silently.
|
|
18
|
-
# Install WSL or Git Bash and ensure `bash` is in PATH to activate protection.
|
|
19
|
-
|
|
20
|
-
# ─── Read hook payload from stdin ───────────────────────────────────
|
|
21
|
-
|
|
22
|
-
INPUT=$(cat)
|
|
23
|
-
[[ -z "$INPUT" ]] && exit 0
|
|
24
|
-
|
|
25
|
-
# Check Node.js availability — security hook should warn loudly if disabled
|
|
26
|
-
if ! command -v node &>/dev/null; then
|
|
27
|
-
echo "WARNING: sensitive-guard disabled — Node.js not found. Sensitive files are NOT protected." >&2
|
|
28
|
-
exit 0
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
# Extract file path and/or command using inline Node.js
|
|
32
|
-
PARSED=$(printf '%s' "$INPUT" | node -e "
|
|
33
|
-
try {
|
|
34
|
-
const d = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
|
|
35
|
-
const fp = d.tool_input?.file_path || d.tool_input?.path || '';
|
|
36
|
-
const cmd = d.tool_input?.command || '';
|
|
37
|
-
const pat = d.tool_input?.pattern || '';
|
|
38
|
-
process.stdout.write(fp + '\n' + cmd + '\n' + pat);
|
|
39
|
-
} catch { process.exit(0); }
|
|
40
|
-
" 2>/dev/null) || exit 0
|
|
41
|
-
|
|
42
|
-
FILE_PATH=$(printf '%s' "$PARSED" | sed -n '1p')
|
|
43
|
-
COMMAND=$(printf '%s' "$PARSED" | sed -n '2p')
|
|
44
|
-
PATTERN=$(printf '%s' "$PARSED" | sed -n '3p')
|
|
45
|
-
|
|
46
|
-
# ─── Sensitive filename patterns ────────────────────────────────────
|
|
47
|
-
|
|
48
|
-
# Returns 0 (true) if the path matches a sensitive pattern
|
|
49
|
-
is_sensitive() {
|
|
50
|
-
local filepath="$1"
|
|
51
|
-
local basename
|
|
52
|
-
basename=$(basename "$filepath" 2>/dev/null) || return 1
|
|
53
|
-
|
|
54
|
-
# Exact filenames (basename match)
|
|
55
|
-
case "$basename" in
|
|
56
|
-
.env|.env.local|.env.development|.env.production|.env.staging|.env.test)
|
|
57
|
-
return 0 ;;
|
|
58
|
-
.npmrc|.pypirc|.netrc)
|
|
59
|
-
return 0 ;;
|
|
60
|
-
id_rsa|id_ecdsa|id_ed25519|id_dsa)
|
|
61
|
-
return 0 ;;
|
|
62
|
-
serviceAccountKey.json|service-account*.json)
|
|
63
|
-
return 0 ;;
|
|
64
|
-
config.json)
|
|
65
|
-
# config.json only sensitive inside .docker/
|
|
66
|
-
[[ "$filepath" == *".docker/config.json"* ]] && return 0
|
|
67
|
-
;;
|
|
68
|
-
esac
|
|
69
|
-
|
|
70
|
-
# Extension patterns
|
|
71
|
-
case "$basename" in
|
|
72
|
-
*.pem|*.key|*.p12|*.pfx|*.jks|*.keystore|*.truststore)
|
|
73
|
-
return 0 ;;
|
|
74
|
-
*_rsa|*_ecdsa|*_ed25519|*_dsa)
|
|
75
|
-
return 0 ;;
|
|
76
|
-
esac
|
|
77
|
-
|
|
78
|
-
# Substring patterns (case-insensitive via bash)
|
|
79
|
-
local lower
|
|
80
|
-
lower=$(echo "$basename" | tr '[:upper:]' '[:lower:]')
|
|
81
|
-
case "$lower" in
|
|
82
|
-
*credential*|*secret*|*private_key*|*privatekey*)
|
|
83
|
-
return 0 ;;
|
|
84
|
-
firebase-adminsdk*)
|
|
85
|
-
return 0 ;;
|
|
86
|
-
esac
|
|
87
|
-
|
|
88
|
-
# .env.* but NOT .env.example or .env.sample or .env.template
|
|
89
|
-
if [[ "$basename" =~ ^\.env\. ]]; then
|
|
90
|
-
case "$basename" in
|
|
91
|
-
.env.example|.env.sample|.env.template) return 1 ;;
|
|
92
|
-
*) return 0 ;;
|
|
93
|
-
esac
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# Extra patterns from env var
|
|
97
|
-
if [[ -n "${SENSITIVE_GUARD_EXTRA:-}" ]]; then
|
|
98
|
-
if printf '%s\n' "$filepath" | grep -qE "$SENSITIVE_GUARD_EXTRA"; then
|
|
99
|
-
return 0
|
|
100
|
-
fi
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
return 1
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
# ─── Check .agentignore ────────────────────────────────────────────
|
|
107
|
-
|
|
108
|
-
check_agentignore() {
|
|
109
|
-
local filepath="$1"
|
|
110
|
-
local ignorefile=""
|
|
111
|
-
|
|
112
|
-
# Look for ignore files in project root
|
|
113
|
-
for candidate in .agentignore .aiignore .cursorignore; do
|
|
114
|
-
if [[ -f "$candidate" ]]; then
|
|
115
|
-
ignorefile="$candidate"
|
|
116
|
-
break
|
|
117
|
-
fi
|
|
118
|
-
done
|
|
119
|
-
|
|
120
|
-
[[ -z "$ignorefile" ]] && return 1
|
|
121
|
-
|
|
122
|
-
# Simple line-by-line match (not full gitignore glob, but covers common cases)
|
|
123
|
-
local relpath
|
|
124
|
-
# Normalize separators to forward slash before stripping prefix (handles Git Bash on Windows)
|
|
125
|
-
local normalized_fp normalized_pwd
|
|
126
|
-
normalized_fp=$(printf '%s' "$filepath" | tr '\\' '/')
|
|
127
|
-
normalized_pwd=$(pwd | tr '\\' '/')
|
|
128
|
-
relpath=$(printf '%s' "$normalized_fp" | sed "s|^${normalized_pwd}/||") 2>/dev/null || relpath="$filepath"
|
|
129
|
-
|
|
130
|
-
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
|
131
|
-
# Skip comments and empty lines
|
|
132
|
-
[[ -z "$pattern" || "$pattern" == \#* ]] && continue
|
|
133
|
-
# Simple glob match
|
|
134
|
-
if [[ "$relpath" == $pattern ]] || [[ "$(basename "$relpath")" == $pattern ]]; then
|
|
135
|
-
return 0
|
|
136
|
-
fi
|
|
137
|
-
done < "$ignorefile"
|
|
138
|
-
|
|
139
|
-
return 1
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
# ─── Check file path access ────────────────────────────────────────
|
|
143
|
-
|
|
144
|
-
block_with_message() {
|
|
145
|
-
local filepath="$1"
|
|
146
|
-
echo "Blocked: '$filepath' is a sensitive file (secrets, keys, or credentials). Access denied to protect sensitive data. Use .env.example for templates instead." >&2
|
|
147
|
-
exit 2
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
warn_with_message() {
|
|
151
|
-
local filepath="$1"
|
|
152
|
-
echo "Warning: '$filepath' is a sensitive file. If the user approved this access, proceed. Otherwise, ask the user for permission first via AskUserQuestion before reading sensitive files." >&2
|
|
153
|
-
# Warn only — exit 0 allows the command to proceed
|
|
154
|
-
# This enables the flow: Block Read → Claude asks user → User approves → Claude uses bash cat
|
|
155
|
-
exit 0
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
# ─── Fast-path: skip obviously safe files ──────────────────────────
|
|
159
|
-
|
|
160
|
-
fast_path_safe() {
|
|
161
|
-
local ext="${1##*.}"
|
|
162
|
-
case "$ext" in
|
|
163
|
-
md|ts|tsx|js|jsx|css|scss|html|svg|json|yaml|yml|toml|xml|txt|sh|py|rb|rs|go|java|kt|swift|c|cpp|h|hpp|cs|vue|svelte|astro)
|
|
164
|
-
# But json could be sensitive — check name
|
|
165
|
-
if [[ "$ext" == "json" ]]; then
|
|
166
|
-
return 1 # not fast-path safe, need full check
|
|
167
|
-
fi
|
|
168
|
-
return 0 ;;
|
|
169
|
-
esac
|
|
170
|
-
return 1
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
# ─── Check direct file access (Read/Write/Edit) → BLOCK ────────────
|
|
174
|
-
|
|
175
|
-
if [[ -n "$FILE_PATH" ]]; then
|
|
176
|
-
if ! fast_path_safe "$FILE_PATH"; then
|
|
177
|
-
if is_sensitive "$FILE_PATH" || check_agentignore "$FILE_PATH"; then
|
|
178
|
-
block_with_message "$FILE_PATH"
|
|
179
|
-
fi
|
|
180
|
-
fi
|
|
181
|
-
fi
|
|
182
|
-
|
|
183
|
-
# ─── Check bash commands → WARN only (allows approved access) ──────
|
|
184
|
-
|
|
185
|
-
if [[ -n "$COMMAND" ]]; then
|
|
186
|
-
# Extract .env file references from commands
|
|
187
|
-
SENSITIVE_IN_CMD=$(printf '%s\n' "$COMMAND" | grep -oE '[\./[:alnum:]_-]*\.env[\.[:alnum:]_-]*' | head -5) || true
|
|
188
|
-
|
|
189
|
-
if [[ -n "$SENSITIVE_IN_CMD" ]]; then
|
|
190
|
-
while IFS= read -r match; do
|
|
191
|
-
case "$match" in
|
|
192
|
-
*.example|*.sample|*.template) continue ;;
|
|
193
|
-
esac
|
|
194
|
-
if is_sensitive "$match"; then
|
|
195
|
-
warn_with_message "$match"
|
|
196
|
-
fi
|
|
197
|
-
done <<< "$SENSITIVE_IN_CMD"
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
|
-
# Check for key/cert file references in commands → also warn only
|
|
201
|
-
KEY_IN_CMD=$(printf '%s\n' "$COMMAND" | grep -oE '[[:alnum:]_./-]*\.(pem|key|p12|pfx|jks|keystore)' | head -3) || true
|
|
202
|
-
if [[ -n "$KEY_IN_CMD" ]]; then
|
|
203
|
-
while IFS= read -r match; do
|
|
204
|
-
warn_with_message "$match"
|
|
205
|
-
done <<< "$KEY_IN_CMD"
|
|
206
|
-
fi
|
|
207
|
-
|
|
208
|
-
# Check for SSH keys, credentials, service accounts in commands
|
|
209
|
-
SENSITIVE_NAMES=$(printf '%s\n' "$COMMAND" | grep -oiE '(id_rsa|id_ecdsa|id_ed25519|id_dsa|serviceAccountKey\.json|service-account[[:alnum:]_-]*\.json|\.npmrc|\.pypirc|\.netrc)' | head -3) || true
|
|
210
|
-
if [[ -n "$SENSITIVE_NAMES" ]]; then
|
|
211
|
-
while IFS= read -r match; do
|
|
212
|
-
warn_with_message "$match"
|
|
213
|
-
done <<< "$SENSITIVE_NAMES"
|
|
214
|
-
fi
|
|
215
|
-
|
|
216
|
-
# Check for credential/secret keywords in file arguments
|
|
217
|
-
CRED_FILES=$(printf '%s\n' "$COMMAND" | grep -oiE '[[:alnum:]_./-]*(credential|secret|private_key|privatekey)[[:alnum:]_./-]*' | head -3) || true
|
|
218
|
-
if [[ -n "$CRED_FILES" ]]; then
|
|
219
|
-
while IFS= read -r match; do
|
|
220
|
-
warn_with_message "$match"
|
|
221
|
-
done <<< "$CRED_FILES"
|
|
222
|
-
fi
|
|
223
|
-
fi
|
|
224
|
-
|
|
225
|
-
# ─── All checks passed ─────────────────────────────────────────────
|
|
226
|
-
|
|
227
|
-
exit 0
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"hooks": {
|
|
3
|
-
"PreToolUse": [
|
|
4
|
-
{
|
|
5
|
-
"matcher": "Bash",
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/path-guard.sh"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"type": "command",
|
|
13
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/sensitive-guard.sh"
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"matcher": "Read|Write|Edit|MultiEdit|Grep",
|
|
19
|
-
"hooks": [
|
|
20
|
-
{
|
|
21
|
-
"type": "command",
|
|
22
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/sensitive-guard.sh"
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"matcher": "Edit|MultiEdit",
|
|
28
|
-
"hooks": [
|
|
29
|
-
{
|
|
30
|
-
"type": "command",
|
|
31
|
-
"command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/comment-guard.js"
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"matcher": "Glob",
|
|
37
|
-
"hooks": [
|
|
38
|
-
{
|
|
39
|
-
"type": "command",
|
|
40
|
-
"command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/glob-guard.js"
|
|
41
|
-
}
|
|
42
|
-
]
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
"PostToolUse": [
|
|
46
|
-
{
|
|
47
|
-
"matcher": "Write|Edit|MultiEdit",
|
|
48
|
-
"hooks": [
|
|
49
|
-
{
|
|
50
|
-
"type": "command",
|
|
51
|
-
"command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/file-guard.js"
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
|
-
"Stop": [
|
|
57
|
-
{
|
|
58
|
-
"matcher": "",
|
|
59
|
-
"hooks": [
|
|
60
|
-
{
|
|
61
|
-
"type": "command",
|
|
62
|
-
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/self-review.sh"
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
# Development Workflow Reference
|
|
2
|
-
|
|
3
|
-
> Spec-first development: every change follows SPEC (with acceptance scenarios) → CODE + TESTS → BUILD PASS.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Workflow Types
|
|
8
|
-
|
|
9
|
-
### New Project (Greenfield)
|
|
10
|
-
|
|
11
|
-
When: Brand-new project — no codebase yet (empty repo, no package manager / `src/`).
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
Step 1 → /sp-explore "what you're building"
|
|
15
|
-
Detects greenfield → ALSO decides app-type + stack (versions researched,
|
|
16
|
-
current — not recalled from memory) and emits a Bootstrap Brief.
|
|
17
|
-
Output: docs/explore/<feature>.md (with ## Bootstrap Brief)
|
|
18
|
-
|
|
19
|
-
Step 2 → /sp-scaffold
|
|
20
|
-
Reads the Bootstrap Brief → generator-first runnable skeleton:
|
|
21
|
-
core/ + ONE pattern-demonstrating module + co-located tests.
|
|
22
|
-
Smoke-gated (install → build → start/smoke must be GREEN, ≥1 real test —
|
|
23
|
-
this resolves TEST_CMD for /sp-build). Writes ARCHITECTURE.md + ADRs.
|
|
24
|
-
Hands off ONLY when it actually runs; otherwise BLOCKED.
|
|
25
|
-
|
|
26
|
-
Step 3 → /sp-plan → /sp-build
|
|
27
|
-
Normal New Feature flow, now on a runnable base. /sp-build's Foundation
|
|
28
|
-
Gate confirms the harness exists before the first RED.
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Explore Before Planning
|
|
32
|
-
|
|
33
|
-
When: Requirements are unclear, multiple approaches are possible, or it's a brownfield feature with existing code to understand first.
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
Step 1 → /sp-explore "feature description"
|
|
37
|
-
Clarifies: why the feature is needed, desired behavior, boundaries,
|
|
38
|
-
edge cases, business rules, permissions, UI expectations.
|
|
39
|
-
Asks questions as a Client Technical Lead — one topic at a time.
|
|
40
|
-
Output: docs/explore/<feature>.md
|
|
41
|
-
|
|
42
|
-
Step 2 → /sp-plan "feature description"
|
|
43
|
-
Auto-detects docs/explore/<feature>.md → skips redundant codebase
|
|
44
|
-
discovery, uses explore findings as direct input for the spec.
|
|
45
|
-
Continue with the normal New Feature flow from Step 2.
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### New Feature
|
|
49
|
-
|
|
50
|
-
When: Building something that doesn't exist yet (no code, no spec).
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
Step 1 → /sp-plan "description of feature"
|
|
54
|
-
Generates: docs/specs/<feature>/<feature>.md (spec with acceptance scenarios)
|
|
55
|
-
Runs Scope Challenge: reuse check, complexity smell (8+ files = flag),
|
|
56
|
-
framework built-in search, distribution check.
|
|
57
|
-
Adds "What Already Exists" and "Not in Scope" sections to the spec.
|
|
58
|
-
Answers validation questions with effort scales (human: X / CC: Y).
|
|
59
|
-
At the end, suggests /sp-spec-render if you want a scannable HTML view.
|
|
60
|
-
Review before proceeding.
|
|
61
|
-
|
|
62
|
-
Step 1.5 → (Optional) /sp-spec-render <feature>
|
|
63
|
-
Generates <feature>.html next to the .md — sidebar TOC, story cards,
|
|
64
|
-
collapsible Given/When/Then, dark/light theme. Useful when the spec
|
|
65
|
-
is long and you want to scan it visually or share it with stakeholders.
|
|
66
|
-
Source .md remains canonical; .html is regenerable, never hand-edit.
|
|
67
|
-
For non-spec markdown (investigation, explore, RFC, retro, README),
|
|
68
|
-
use /sp-md-render <file.md> instead — same idea, generic content.
|
|
69
|
-
|
|
70
|
-
Step 2 → (Optional) /sp-challenge docs/specs/<feature>/<feature>.md
|
|
71
|
-
Adversarial review: spawns hostile reviewers to find flaws.
|
|
72
|
-
Recommended for complex features, auth, data pipelines.
|
|
73
|
-
Skip for simple CRUD or small features.
|
|
74
|
-
|
|
75
|
-
Step 3 → Implement in chunks. After each chunk:
|
|
76
|
-
/sp-build
|
|
77
|
-
Checks 8 edge case categories (null, empty, invalid types, boundary,
|
|
78
|
-
error paths, race conditions, large data, special chars).
|
|
79
|
-
Draws Coverage Map before writing tests: traces code paths + user flows,
|
|
80
|
-
marks [GAP], [GAP][→E2E], [GAP][→EVAL] (with pass@1/pass@3 guidance).
|
|
81
|
-
Regression rule enforced.
|
|
82
|
-
Repeat until chunk is green.
|
|
83
|
-
|
|
84
|
-
Step 4 → /sp-review (before merge)
|
|
85
|
-
Checks API/Backend patterns (rate limiting, timeouts, CORS, error leakage).
|
|
86
|
-
Extra layer for AI-generated code: regressions, trust boundaries, cost escalation.
|
|
87
|
-
|
|
88
|
-
Step 4.5 → (Optional) /sp-voices
|
|
89
|
-
Multi-LLM second opinion: sends the diff (or spec) to 2–3 different LLMs,
|
|
90
|
-
synthesizes consensus + disagreements. Use when: high-stakes change
|
|
91
|
-
(auth/payment/data), mixed-confidence findings from /sp-review, or
|
|
92
|
-
you want cross-model verification before merge. Skip for routine changes.
|
|
93
|
-
|
|
94
|
-
Step 5 → /sp-commit
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Update Existing Feature
|
|
98
|
-
|
|
99
|
-
When: Changing behavior, adding options, refactoring logic.
|
|
100
|
-
|
|
101
|
-
```
|
|
102
|
-
Step 1 → /sp-plan docs/specs/<feature>/<feature>.md "description of changes"
|
|
103
|
-
Mode C handles everything: snapshot → classification → change report → apply.
|
|
104
|
-
Do NOT manually edit the spec before running /sp-plan — it creates the
|
|
105
|
-
snapshot first, then applies changes. Manual edits bypass snapshot protection.
|
|
106
|
-
At the end, suggests /sp-spec-render to refresh <feature>.html if you
|
|
107
|
-
have an HTML view (it's stale after this update).
|
|
108
|
-
|
|
109
|
-
Step 2 → Implement code changes.
|
|
110
|
-
/sp-build
|
|
111
|
-
Fix until green.
|
|
112
|
-
|
|
113
|
-
Step 4 → /sp-review → /sp-commit
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Bug Fix
|
|
117
|
-
|
|
118
|
-
When: Something is broken and needs fixing.
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
Step 0 → (OPTIONAL) /sp-investigate "description of the bug"
|
|
122
|
-
Use ONLY when: bug is complex, ambiguous, production outage, data
|
|
123
|
-
corruption, regression with unclear cause, or user wants diagnosis
|
|
124
|
-
before any code change. Skip for trivial/obvious bugs.
|
|
125
|
-
Read-only: traces data flow, maps blast radius, lists hypotheses
|
|
126
|
-
with confidence levels. Writes docs/investigate/<slug>-<date>.md.
|
|
127
|
-
No code changes — hands off the report to /sp-fix.
|
|
128
|
-
|
|
129
|
-
Step 1 → /sp-fix "description" (or /sp-fix docs/investigate/<slug>-<date>.md)
|
|
130
|
-
Auto-detects investigation file if passed → skips redundant discovery.
|
|
131
|
-
Draws Bug Path Diagram to confirm hypothesis ([GAP] must be locatable).
|
|
132
|
-
Regression rule: if diff broke existing behavior with no test → CRITICAL test required.
|
|
133
|
-
Writes failing test → fixes code → confirms green → runs full suite.
|
|
134
|
-
|
|
135
|
-
Step 2 → /sp-commit
|
|
136
|
-
|
|
137
|
-
Optional → If the bug reveals an undocumented edge case, update the spec.
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Remove Feature
|
|
141
|
-
|
|
142
|
-
When: Deleting a feature, removing deprecated code.
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
Step 1 → /sp-plan docs/specs/<feature>/<feature>.md "remove stories S-XXX"
|
|
146
|
-
Mode C creates a snapshot (removing stories = M2 = Major),
|
|
147
|
-
then marks stories and AS as removed in the spec.
|
|
148
|
-
(Or if removing the entire feature: archive the directory.)
|
|
149
|
-
|
|
150
|
-
Step 2 → Delete production code and related test code.
|
|
151
|
-
|
|
152
|
-
Step 3 → Run the full test suite with the project's native test command.
|
|
153
|
-
Fix any cascading breakage.
|
|
154
|
-
|
|
155
|
-
Step 4 → /sp-commit
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 2. Decision Tree
|
|
161
|
-
|
|
162
|
-
Use this to decide which workflow to follow:
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
Is there a runnable project yet (package manager / src / build)?
|
|
166
|
-
├─ No → New Project (Greenfield). /sp-explore (greenfield) → /sp-scaffold → then /sp-plan.
|
|
167
|
-
└─ Yes ↓
|
|
168
|
-
|
|
169
|
-
Is this a brand new feature (no existing spec or code)?
|
|
170
|
-
├─ Yes
|
|
171
|
-
│ ├─ Are requirements clear and approach decided?
|
|
172
|
-
│ │ ├─ Yes → New Feature workflow. Start with /sp-plan.
|
|
173
|
-
│ │ │ └─ Is the feature complex (auth, data pipeline, multi-service)?
|
|
174
|
-
│ │ │ ├─ Yes → Run /sp-challenge after /sp-plan, before coding.
|
|
175
|
-
│ │ │ └─ No → Skip /sp-challenge, go straight to implementation.
|
|
176
|
-
│ │ └─ No → Explore Before Planning. Start with /sp-explore.
|
|
177
|
-
│ │ Then /sp-plan using the explore output.
|
|
178
|
-
└─ No
|
|
179
|
-
├─ Is this a bug fix?
|
|
180
|
-
│ ├─ Yes → Bug Fix workflow.
|
|
181
|
-
│ │ ├─ Complex / outage / ambiguous cause / data corruption?
|
|
182
|
-
│ │ │ ├─ Yes → /sp-investigate first, then /sp-fix.
|
|
183
|
-
│ │ │ └─ No → /sp-fix directly.
|
|
184
|
-
│ └─ No
|
|
185
|
-
│ ├─ Are you removing/deprecating code?
|
|
186
|
-
│ │ ├─ Yes → Remove Feature workflow.
|
|
187
|
-
│ │ └─ No → Update Feature workflow. Start with /sp-plan.
|
|
188
|
-
│ │
|
|
189
|
-
│ └─ Is the change very small (< 5 lines, behavior unchanged)?
|
|
190
|
-
│ └─ Yes → Skip spec update. Just /sp-build and /sp-commit.
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## 3. Prompt Templates
|
|
196
|
-
|
|
197
|
-
Copy-paste these when working with your agent.
|
|
198
|
-
|
|
199
|
-
### Template A — Implement + Test Together
|
|
200
|
-
|
|
201
|
-
```
|
|
202
|
-
I just implemented [brief description].
|
|
203
|
-
Files changed: [list files]
|
|
204
|
-
|
|
205
|
-
Based on:
|
|
206
|
-
- Spec: docs/specs/<feature>/<feature>.md (section §X)
|
|
207
|
-
- Acceptance scenarios: docs/specs/<feature>/<feature>.md (section ## Stories)
|
|
208
|
-
|
|
209
|
-
Write tests for the part I just implemented.
|
|
210
|
-
Only tests related to this change — not the entire feature.
|
|
211
|
-
Build and run until all pass.
|
|
212
|
-
If the spec seems incomplete, note what's missing but don't change it.
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Template B — Update Feature + Tests
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
I'm about to change [description of change].
|
|
219
|
-
Affected files: [list]
|
|
220
|
-
|
|
221
|
-
1. /sp-plan docs/specs/<feature>/<feature>.md "description of changes"
|
|
222
|
-
(handles snapshot + spec update + acceptance scenarios)
|
|
223
|
-
2. Implement the code change
|
|
224
|
-
3. Update tests to match
|
|
225
|
-
4. Build and run → fix until green
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Template C — Test-First Bug Fix
|
|
229
|
-
|
|
230
|
-
```
|
|
231
|
-
Bug: [description]
|
|
232
|
-
Steps to reproduce: [steps]
|
|
233
|
-
Expected: [correct behavior]
|
|
234
|
-
Actual: [broken behavior]
|
|
235
|
-
|
|
236
|
-
1. Write a test that reproduces this bug (must fail currently)
|
|
237
|
-
2. Fix the production code to make the test pass
|
|
238
|
-
3. Run the full test suite — nothing else should break
|
|
239
|
-
4. Update the spec if this is an undocumented edge case
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Template D — Remove Feature
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
Removing: [feature name]
|
|
246
|
-
Files to delete: [list]
|
|
247
|
-
|
|
248
|
-
1. /sp-plan docs/specs/<feature>/<feature>.md "remove stories S-XXX, S-YYY"
|
|
249
|
-
(handles snapshot + marks stories and AS as removed)
|
|
250
|
-
2. Delete production code
|
|
251
|
-
3. Delete test code
|
|
252
|
-
4. Run full test suite → fix cascading breaks
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## 4. Token Cost Guide
|
|
258
|
-
|
|
259
|
-
| Workflow | Estimated Tokens | When |
|
|
260
|
-
|----------|-----------------|------|
|
|
261
|
-
| `/sp-explore` | 10–20k | Before /sp-plan when requirements are unclear |
|
|
262
|
-
| `/sp-scaffold` | 15–40k + real install/build time | Greenfield only — once, to stand up a runnable skeleton before the first spec |
|
|
263
|
-
| `/sp-build` (incremental) | 5–10k | Daily, after each code chunk |
|
|
264
|
-
| `/sp-investigate` (complex bug) | 8–15k | OPTIONAL before /sp-fix — complex/outage only |
|
|
265
|
-
| `/sp-fix` (single bug) | 3–5k | As bugs arise |
|
|
266
|
-
| `/sp-commit` | 2–4k | Each commit |
|
|
267
|
-
| `/sp-review` (diff-based) | 10–20k | Before merge |
|
|
268
|
-
| `/sp-plan` (new feature) | 20–40k | Start of new feature |
|
|
269
|
-
| `/sp-challenge` (adversarial) | 15–30k | After /sp-plan, for complex features |
|
|
270
|
-
| `/sp-spec-render` (HTML view) | 3–8k | User-invoked after `/sp-plan` if HTML view wanted, or to refresh stale `.html` |
|
|
271
|
-
| `/sp-md-render` (HTML view, any md) | 3–8k | User-invoked for non-spec markdown — investigation, explore, RFC, retro, README |
|
|
272
|
-
| `/sp-voices` (multi-LLM review) | 10–30k + external API cost | Optional — after /sp-review for high-stakes changes |
|
|
273
|
-
| `/sp-humanize` (rephrase text) | 2–6k | User-invoked — rephrase plan/notes/AI output into send-ready text. Outside the dev cycle |
|
|
274
|
-
| Full audit (manual) | 100k+ | Before release, quarterly |
|
|
275
|
-
|
|
276
|
-
**Rule of thumb:** Daily work uses templates + `/sp-build` → low token cost.
|
|
277
|
-
Save `/sp-plan` and full audits for significant milestones.
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
## 5. CI Integration Checklist
|
|
282
|
-
|
|
283
|
-
Use this as a PR review checklist (enforce manually or via CI):
|
|
284
|
-
|
|
285
|
-
- [ ] **Spec updated?** If production behavior changed, `docs/specs/<feature>/` should have changes.
|
|
286
|
-
- [ ] **Acceptance scenarios updated?** If spec behavior changed, AS in spec should reflect it.
|
|
287
|
-
- [ ] **Tests pass?** The project's test command exits 0.
|
|
288
|
-
- [ ] **No dead tests?** Removed production code → removed corresponding tests.
|
|
289
|
-
- [ ] **Coverage not decreased?** (Optional, per-team decision.)
|
|
290
|
-
- [ ] **No secrets in diff?** No API keys, tokens, passwords in committed code.
|
|
291
|
-
- [ ] **Commit messages conventional?** `type(scope): description` format.
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
## 6. Spec-Test-Code Sync Rules
|
|
296
|
-
|
|
297
|
-
| Change | Must Also Update |
|
|
298
|
-
|--------|-----------------|
|
|
299
|
-
| Production code behavior changed | Spec (including acceptance scenarios) + tests |
|
|
300
|
-
| Spec updated | Acceptance scenarios + tests (if behavior changed) |
|
|
301
|
-
| Code removed | Remove related tests. Mark spec and AS as removed. |
|
|
302
|
-
| Bug fix | Add test. Update spec if edge case was undocumented. |
|
|
303
|
-
|
|
304
|
-
**Never acceptable:**
|
|
305
|
-
- Code changed, spec not updated (spec drift)
|
|
306
|
-
- Code changed, tests not updated (untested code)
|
|
307
|
-
- Spec changed, acceptance scenarios or tests not updated (AS drift)
|
|
308
|
-
- Code removed, dead tests remain (orphaned tests)
|
|
309
|
-
|
|
310
|
-
**Acceptable shortcut** for changes under 5 lines with no behavior change:
|
|
311
|
-
- Code + tests together, skip spec update (same PR).
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
## 7. Common Pitfalls
|
|
316
|
-
|
|
317
|
-
| Pitfall | Symptom | Prevention |
|
|
318
|
-
|---------|---------|------------|
|
|
319
|
-
| **Spec drift** | Code does X, spec says Y | Always update spec before coding |
|
|
320
|
-
| **Dead tests** | Tests pass but test removed functionality | Delete tests when removing features |
|
|
321
|
-
| **Over-testing** | 50 tests for simple CRUD, slow suite | Focus on behavior, not implementation details |
|
|
322
|
-
| **Mock abuse** | Tests pass with mocks, fail in production | Use real implementations; mock only external services |
|
|
323
|
-
| **Big-bang testing** | All tests written after all code is done | Test incrementally after each chunk |
|
|
324
|
-
| **Ignoring flaky tests** | Tests pass sometimes, fail sometimes | Fix immediately — flaky tests erode trust |
|
|
325
|
-
| **Testing private methods** | Tests break on refactor | Test public API and behavior only |
|
|
File without changes
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
These are the always-on operating rules for working in this repository with specpipe.
|
|
2
|
-
On Claude Code the guardrails are enforced by hooks; on other agents this whole document
|
|
3
|
-
is an always-on rule you must self-enforce.
|
|
4
|
-
|
|
5
|
-
## Spec-first cycle
|
|
6
|
-
|
|
7
|
-
Every change follows: **SPEC (with acceptance scenarios) → CODE + TESTS → BUILD PASS**.
|
|
8
|
-
|
|
9
|
-
- Specs live in `docs/specs/<feature>/<feature>.md`; acceptance scenarios (Given/When/Then)
|
|
10
|
-
are embedded under `## Stories`.
|
|
11
|
-
- Never write code before the spec exists. Never auto-modify a spec from code.
|
|
12
|
-
- The spec is the source of truth — if code contradicts it, the code is wrong.
|
|
13
|
-
|
|
14
|
-
## Guardrails
|
|
15
|
-
|
|
16
|
-
- **Don't explore large directories.** Never grep/list/read inside `node_modules/`,
|
|
17
|
-
build/dist artifacts, or `.git/` internals — scope to specific paths.
|
|
18
|
-
- **Never touch secrets.** Do not read or write `.env*`, private keys, credentials, or
|
|
19
|
-
token stores. Respect any `.agentignore` patterns.
|
|
20
|
-
- **Never drop real code.** Don't replace implementation with placeholder comments like
|
|
21
|
-
`// ... existing code ...`. Reproduce the full code when editing.
|
|
22
|
-
- **Avoid broad globs.** No `**/*.ts` at the project root; scope globs to a directory.
|
|
23
|
-
- **Keep files focused.** Don't let a source file grow past a few hundred lines — split.
|
|
24
|
-
|
|
25
|
-
## Testing
|
|
26
|
-
|
|
27
|
-
- Run the project's native test command (`npx vitest run`, `pytest`, `cargo test`,
|
|
28
|
-
`go test ./...`, `swift test`, …). Compile/typecheck before running tests.
|
|
29
|
-
- Max 3 fix loops on a failure, then stop and report.
|
|
30
|
-
- **Never edit production code to make a test pass** — ask first.
|
|
31
|
-
- No mocks/fakes/stubs to pass builds; real implementations only. Test doubles are for
|
|
32
|
-
external services (APIs, DBs) that can't run locally.
|
|
33
|
-
|
|
34
|
-
## Conventions
|
|
35
|
-
|
|
36
|
-
- Commits: conventional — `type(scope): description` (`feat`, `fix`, `docs`, `refactor`,
|
|
37
|
-
`test`, `chore`, `perf`, `build`, `ci`).
|
|
38
|
-
- File names: kebab-case, descriptive enough to understand purpose from the path.
|
|
39
|
-
- Never `git push --force` to `main`/`master`; never commit `.env`, certs, or keys.
|
|
40
|
-
- Self-review before finishing: tests pass, no secrets, no debug code, matches the spec.
|