claude-devkit-cli 1.0.0
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/bin/devkit.js +3 -0
- package/package.json +36 -0
- package/src/cli.js +72 -0
- package/src/commands/check.js +33 -0
- package/src/commands/diff.js +90 -0
- package/src/commands/init.js +232 -0
- package/src/commands/list.js +50 -0
- package/src/commands/remove.js +74 -0
- package/src/commands/upgrade.js +108 -0
- package/src/lib/detector.js +93 -0
- package/src/lib/hasher.js +21 -0
- package/src/lib/installer.js +175 -0
- package/src/lib/logger.js +16 -0
- package/src/lib/manifest.js +79 -0
- package/templates/.claude/CLAUDE.md +74 -0
- package/templates/.claude/commands/challenge.md +210 -0
- package/templates/.claude/commands/commit.md +97 -0
- package/templates/.claude/commands/fix.md +95 -0
- package/templates/.claude/commands/plan.md +141 -0
- package/templates/.claude/commands/review.md +109 -0
- package/templates/.claude/commands/test.md +99 -0
- package/templates/.claude/hooks/comment-guard.js +114 -0
- package/templates/.claude/hooks/file-guard.js +120 -0
- package/templates/.claude/hooks/glob-guard.js +96 -0
- package/templates/.claude/hooks/path-guard.sh +73 -0
- package/templates/.claude/hooks/self-review.sh +29 -0
- package/templates/.claude/hooks/sensitive-guard.sh +214 -0
- package/templates/.claude/settings.json +68 -0
- package/templates/docs/WORKFLOW.md +231 -0
- package/templates/docs/specs/.gitkeep +0 -0
- package/templates/docs/test-plans/.gitkeep +0 -0
- package/templates/scripts/build-test.sh +260 -0
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
# ─── Read hook payload from stdin ───────────────────────────────────
|
|
17
|
+
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
[[ -z "$INPUT" ]] && exit 0
|
|
20
|
+
|
|
21
|
+
# Check Node.js availability — security hook should warn loudly if disabled
|
|
22
|
+
if ! command -v node &>/dev/null; then
|
|
23
|
+
echo "WARNING: sensitive-guard disabled — Node.js not found. Sensitive files are NOT protected." >&2
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Extract file path and/or command using inline Node.js
|
|
28
|
+
PARSED=$(printf '%s' "$INPUT" | node -e "
|
|
29
|
+
try {
|
|
30
|
+
const d = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
|
|
31
|
+
const fp = d.tool_input?.file_path || d.tool_input?.path || '';
|
|
32
|
+
const cmd = d.tool_input?.command || '';
|
|
33
|
+
const pat = d.tool_input?.pattern || '';
|
|
34
|
+
process.stdout.write(fp + '\n' + cmd + '\n' + pat);
|
|
35
|
+
} catch { process.exit(0); }
|
|
36
|
+
" 2>/dev/null) || exit 0
|
|
37
|
+
|
|
38
|
+
FILE_PATH=$(printf '%s' "$PARSED" | sed -n '1p')
|
|
39
|
+
COMMAND=$(printf '%s' "$PARSED" | sed -n '2p')
|
|
40
|
+
PATTERN=$(printf '%s' "$PARSED" | sed -n '3p')
|
|
41
|
+
|
|
42
|
+
# ─── Sensitive filename patterns ────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
# Returns 0 (true) if the path matches a sensitive pattern
|
|
45
|
+
is_sensitive() {
|
|
46
|
+
local filepath="$1"
|
|
47
|
+
local basename
|
|
48
|
+
basename=$(basename "$filepath" 2>/dev/null) || return 1
|
|
49
|
+
|
|
50
|
+
# Exact filenames (basename match)
|
|
51
|
+
case "$basename" in
|
|
52
|
+
.env|.env.local|.env.development|.env.production|.env.staging|.env.test)
|
|
53
|
+
return 0 ;;
|
|
54
|
+
.npmrc|.pypirc|.netrc)
|
|
55
|
+
return 0 ;;
|
|
56
|
+
id_rsa|id_ecdsa|id_ed25519|id_dsa)
|
|
57
|
+
return 0 ;;
|
|
58
|
+
serviceAccountKey.json|service-account*.json)
|
|
59
|
+
return 0 ;;
|
|
60
|
+
.mcp.json|config.json)
|
|
61
|
+
# config.json only sensitive inside .docker/ — check full path
|
|
62
|
+
if [[ "$basename" == "config.json" ]]; then
|
|
63
|
+
[[ "$filepath" == *".docker/config.json"* ]] && return 0
|
|
64
|
+
else
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
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
|
+
relpath=$(echo "$filepath" | sed "s|^$(pwd)/||") 2>/dev/null || relpath="$filepath"
|
|
125
|
+
|
|
126
|
+
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
|
127
|
+
# Skip comments and empty lines
|
|
128
|
+
[[ -z "$pattern" || "$pattern" == \#* ]] && continue
|
|
129
|
+
# Simple glob match
|
|
130
|
+
if [[ "$relpath" == $pattern ]] || [[ "$(basename "$relpath")" == $pattern ]]; then
|
|
131
|
+
return 0
|
|
132
|
+
fi
|
|
133
|
+
done < "$ignorefile"
|
|
134
|
+
|
|
135
|
+
return 1
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# ─── Check file path access ────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
block_with_message() {
|
|
141
|
+
local filepath="$1"
|
|
142
|
+
echo "Blocked: '$filepath' is a sensitive file (secrets, keys, or credentials). Access denied to protect sensitive data. Use .env.example for templates instead." >&2
|
|
143
|
+
exit 2
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
warn_with_message() {
|
|
147
|
+
local filepath="$1"
|
|
148
|
+
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
|
|
149
|
+
# Warn only — exit 0 allows the command to proceed
|
|
150
|
+
# This enables the flow: Block Read → Claude asks user → User approves → Claude uses bash cat
|
|
151
|
+
exit 0
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# ─── Check direct file access (Read/Write/Edit) → BLOCK ────────────
|
|
155
|
+
|
|
156
|
+
if [[ -n "$FILE_PATH" ]]; then
|
|
157
|
+
if is_sensitive "$FILE_PATH" || check_agentignore "$FILE_PATH"; then
|
|
158
|
+
block_with_message "$FILE_PATH"
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# ─── Check bash commands → WARN only (allows approved access) ──────
|
|
163
|
+
|
|
164
|
+
if [[ -n "$COMMAND" ]]; then
|
|
165
|
+
# Extract .env file references from commands
|
|
166
|
+
SENSITIVE_IN_CMD=$(printf '%s\n' "$COMMAND" | grep -oE '[\./[:alnum:]_-]*\.env[\.[:alnum:]_-]*' | head -5) || true
|
|
167
|
+
|
|
168
|
+
if [[ -n "$SENSITIVE_IN_CMD" ]]; then
|
|
169
|
+
while IFS= read -r match; do
|
|
170
|
+
case "$match" in
|
|
171
|
+
*.example|*.sample|*.template) continue ;;
|
|
172
|
+
esac
|
|
173
|
+
if is_sensitive "$match"; then
|
|
174
|
+
warn_with_message "$match"
|
|
175
|
+
fi
|
|
176
|
+
done <<< "$SENSITIVE_IN_CMD"
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
# Check for key/cert file references in commands → also warn only
|
|
180
|
+
KEY_IN_CMD=$(printf '%s\n' "$COMMAND" | grep -oE '[[:alnum:]_./-]*\.(pem|key|p12|pfx|jks|keystore)' | head -3) || true
|
|
181
|
+
if [[ -n "$KEY_IN_CMD" ]]; then
|
|
182
|
+
while IFS= read -r match; do
|
|
183
|
+
warn_with_message "$match"
|
|
184
|
+
done <<< "$KEY_IN_CMD"
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Check for SSH keys, credentials, service accounts in commands
|
|
188
|
+
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
|
|
189
|
+
if [[ -n "$SENSITIVE_NAMES" ]]; then
|
|
190
|
+
while IFS= read -r match; do
|
|
191
|
+
warn_with_message "$match"
|
|
192
|
+
done <<< "$SENSITIVE_NAMES"
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Check for credential/secret keywords in file arguments
|
|
196
|
+
CRED_FILES=$(printf '%s\n' "$COMMAND" | grep -oiE '[[:alnum:]_./-]*(credential|secret|private_key|privatekey)[[:alnum:]_./-]*' | head -3) || true
|
|
197
|
+
if [[ -n "$CRED_FILES" ]]; then
|
|
198
|
+
while IFS= read -r match; do
|
|
199
|
+
warn_with_message "$match"
|
|
200
|
+
done <<< "$CRED_FILES"
|
|
201
|
+
fi
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
# ─── Check Grep pattern for sensitive file paths ───────────────────
|
|
205
|
+
|
|
206
|
+
if [[ -n "$PATTERN" ]]; then
|
|
207
|
+
if is_sensitive "$PATTERN"; then
|
|
208
|
+
block_with_message "$PATTERN"
|
|
209
|
+
fi
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
# ─── All checks passed ─────────────────────────────────────────────
|
|
213
|
+
|
|
214
|
+
exit 0
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Development Workflow Reference
|
|
2
|
+
|
|
3
|
+
> Spec-first development: every change follows SPEC → TEST PLAN → CODE + TESTS → BUILD PASS.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Four Workflow Types
|
|
8
|
+
|
|
9
|
+
### New Feature
|
|
10
|
+
|
|
11
|
+
When: Building something that doesn't exist yet (no code, no spec).
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Step 1 → /plan "description of feature"
|
|
15
|
+
Generates: docs/specs/<feature>.md (spec)
|
|
16
|
+
docs/test-plans/<feature>.md (test plan)
|
|
17
|
+
Answers validation questions about assumptions.
|
|
18
|
+
Review both before proceeding.
|
|
19
|
+
|
|
20
|
+
Step 2 → (Optional) /challenge docs/test-plans/<feature>.md
|
|
21
|
+
Adversarial review: spawns hostile reviewers to find flaws.
|
|
22
|
+
Recommended for complex features, auth, data pipelines.
|
|
23
|
+
Skip for simple CRUD or small features.
|
|
24
|
+
|
|
25
|
+
Step 3 → Implement in chunks. After each chunk:
|
|
26
|
+
/test
|
|
27
|
+
Repeat until chunk is green.
|
|
28
|
+
|
|
29
|
+
Step 4 → /review (before merge)
|
|
30
|
+
|
|
31
|
+
Step 5 → /commit
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Update Existing Feature
|
|
35
|
+
|
|
36
|
+
When: Changing behavior, adding options, refactoring logic.
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Step 1 → Update spec FIRST: docs/specs/<feature>.md
|
|
40
|
+
Describe what's changing and why.
|
|
41
|
+
|
|
42
|
+
Step 2 → /plan docs/specs/<feature>.md
|
|
43
|
+
Updates the test plan with new/modified/removed test cases.
|
|
44
|
+
|
|
45
|
+
Step 3 → Implement code changes.
|
|
46
|
+
/test
|
|
47
|
+
Fix until green.
|
|
48
|
+
|
|
49
|
+
Step 4 → /review → /commit
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Bug Fix
|
|
53
|
+
|
|
54
|
+
When: Something is broken and needs fixing.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
Step 1 → /fix "description of the bug"
|
|
58
|
+
Writes failing test → fixes code → confirms green → runs full suite.
|
|
59
|
+
|
|
60
|
+
Step 2 → /commit
|
|
61
|
+
|
|
62
|
+
Optional → If the bug reveals an undocumented edge case, update the spec.
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Remove Feature
|
|
66
|
+
|
|
67
|
+
When: Deleting a feature, removing deprecated code.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Step 1 → Mark spec sections as removed in docs/specs/<feature>.md
|
|
71
|
+
(Or archive the entire file if the feature is fully removed.)
|
|
72
|
+
|
|
73
|
+
Step 2 → Delete production code and related test code.
|
|
74
|
+
|
|
75
|
+
Step 3 → Run full test suite: bash scripts/build-test.sh
|
|
76
|
+
Fix any cascading breakage.
|
|
77
|
+
|
|
78
|
+
Step 4 → /commit
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 2. Decision Tree
|
|
84
|
+
|
|
85
|
+
Use this to decide which workflow to follow:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Is this a brand new feature (no existing spec or code)?
|
|
89
|
+
├─ Yes → New Feature workflow. Start with /plan.
|
|
90
|
+
│ └─ Is the feature complex (auth, data pipeline, multi-service)?
|
|
91
|
+
│ ├─ Yes → Run /challenge after /plan, before coding.
|
|
92
|
+
│ └─ No → Skip /challenge, go straight to implementation.
|
|
93
|
+
└─ No
|
|
94
|
+
├─ Is this a bug fix?
|
|
95
|
+
│ ├─ Yes → Bug Fix workflow. Start with /fix.
|
|
96
|
+
│ └─ No
|
|
97
|
+
│ ├─ Are you removing/deprecating code?
|
|
98
|
+
│ │ ├─ Yes → Remove Feature workflow.
|
|
99
|
+
│ │ └─ No → Update Feature workflow. Start by editing the spec.
|
|
100
|
+
│ │
|
|
101
|
+
│ └─ Is the change very small (< 5 lines, behavior unchanged)?
|
|
102
|
+
│ └─ Yes → Skip spec update. Just /test and /commit.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 3. Prompt Templates
|
|
108
|
+
|
|
109
|
+
Copy-paste these when working with Claude Code.
|
|
110
|
+
|
|
111
|
+
### Template A — Implement + Test Together
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
I just implemented [brief description].
|
|
115
|
+
Files changed: [list files]
|
|
116
|
+
|
|
117
|
+
Based on:
|
|
118
|
+
- Spec: docs/specs/<feature>.md (section §X)
|
|
119
|
+
- Test plan: docs/test-plans/<feature>.md
|
|
120
|
+
|
|
121
|
+
Write tests for the part I just implemented.
|
|
122
|
+
Only tests related to this change — not the entire feature.
|
|
123
|
+
Build and run until all pass.
|
|
124
|
+
If the spec seems incomplete, note what's missing but don't change it.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Template B — Update Feature + Tests
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
I'm about to change [description of change].
|
|
131
|
+
Affected files: [list]
|
|
132
|
+
|
|
133
|
+
1. Update the spec: docs/specs/<feature>.md
|
|
134
|
+
2. Update the test plan: docs/test-plans/<feature>.md (only affected test cases)
|
|
135
|
+
3. Implement the code change
|
|
136
|
+
4. Update tests to match
|
|
137
|
+
5. Build and run → fix until green
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Template C — Test-First Bug Fix
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
Bug: [description]
|
|
144
|
+
Steps to reproduce: [steps]
|
|
145
|
+
Expected: [correct behavior]
|
|
146
|
+
Actual: [broken behavior]
|
|
147
|
+
|
|
148
|
+
1. Write a test that reproduces this bug (must fail currently)
|
|
149
|
+
2. Fix the production code to make the test pass
|
|
150
|
+
3. Run the full test suite — nothing else should break
|
|
151
|
+
4. Update the spec if this is an undocumented edge case
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Template D — Remove Feature
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Removing: [feature name]
|
|
158
|
+
Files to delete: [list]
|
|
159
|
+
|
|
160
|
+
1. Mark relevant spec sections as removed
|
|
161
|
+
2. Mark related test plan entries as removed
|
|
162
|
+
3. Delete production code
|
|
163
|
+
4. Delete test code
|
|
164
|
+
5. Run full test suite → fix cascading breaks
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 4. Token Cost Guide
|
|
170
|
+
|
|
171
|
+
| Workflow | Estimated Tokens | When |
|
|
172
|
+
|----------|-----------------|------|
|
|
173
|
+
| `/test` (incremental) | 5–10k | Daily, after each code chunk |
|
|
174
|
+
| `/fix` (single bug) | 3–5k | As bugs arise |
|
|
175
|
+
| `/commit` | 2–4k | Each commit |
|
|
176
|
+
| `/review` (diff-based) | 10–20k | Before merge |
|
|
177
|
+
| `/plan` (new feature) | 20–40k | Start of new feature |
|
|
178
|
+
| `/challenge` (adversarial) | 15–30k | After /plan, for complex features |
|
|
179
|
+
| Full audit (manual) | 100k+ | Before release, quarterly |
|
|
180
|
+
|
|
181
|
+
**Rule of thumb:** Daily work uses templates + `/test` → low token cost.
|
|
182
|
+
Save `/plan` and full audits for significant milestones.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 5. CI Integration Checklist
|
|
187
|
+
|
|
188
|
+
Use this as a PR review checklist (enforce manually or via CI):
|
|
189
|
+
|
|
190
|
+
- [ ] **Spec updated?** If production behavior changed, `docs/specs/` should have changes.
|
|
191
|
+
- [ ] **Test plan updated?** If spec changed, `docs/test-plans/` should have changes.
|
|
192
|
+
- [ ] **Tests pass?** `bash scripts/build-test.sh` exits 0.
|
|
193
|
+
- [ ] **No dead tests?** Removed production code → removed corresponding tests.
|
|
194
|
+
- [ ] **Coverage not decreased?** (Optional, per-team decision.)
|
|
195
|
+
- [ ] **No secrets in diff?** No API keys, tokens, passwords in committed code.
|
|
196
|
+
- [ ] **Commit messages conventional?** `type(scope): description` format.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 6. Spec-Test-Code Sync Rules
|
|
201
|
+
|
|
202
|
+
| Change | Must Also Update |
|
|
203
|
+
|--------|-----------------|
|
|
204
|
+
| Production code behavior changed | Spec + test plan + tests |
|
|
205
|
+
| Spec updated | Test plan + tests (if behavior changed) |
|
|
206
|
+
| Test plan updated | Tests (implement new/modified test cases) |
|
|
207
|
+
| Code removed | Remove related tests. Mark spec as removed. |
|
|
208
|
+
| Bug fix | Add test. Update spec if edge case was undocumented. |
|
|
209
|
+
|
|
210
|
+
**Never acceptable:**
|
|
211
|
+
- Code changed, spec not updated (spec drift)
|
|
212
|
+
- Code changed, tests not updated (untested code)
|
|
213
|
+
- Spec changed, tests not updated (plan drift)
|
|
214
|
+
- Code removed, dead tests remain (orphaned tests)
|
|
215
|
+
|
|
216
|
+
**Acceptable shortcut** for changes under 5 lines with no behavior change:
|
|
217
|
+
- Code + tests together, skip spec update (same PR).
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 7. Common Pitfalls
|
|
222
|
+
|
|
223
|
+
| Pitfall | Symptom | Prevention |
|
|
224
|
+
|---------|---------|------------|
|
|
225
|
+
| **Spec drift** | Code does X, spec says Y | Always update spec before coding |
|
|
226
|
+
| **Dead tests** | Tests pass but test removed functionality | Delete tests when removing features |
|
|
227
|
+
| **Over-testing** | 50 tests for simple CRUD, slow suite | Focus on behavior, not implementation details |
|
|
228
|
+
| **Mock abuse** | Tests pass with mocks, fail in production | Use real implementations; mock only external services |
|
|
229
|
+
| **Big-bang testing** | All tests written after all code is done | Test incrementally after each chunk |
|
|
230
|
+
| **Ignoring flaky tests** | Tests pass sometimes, fail sometimes | Fix immediately — flaky tests erode trust |
|
|
231
|
+
| **Testing private methods** | Tests break on refactor | Test public API and behavior only |
|
|
File without changes
|
|
File without changes
|