aped-method 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/aped-method.js +8 -0
- package/package.json +31 -0
- package/src/index.js +348 -0
- package/src/scaffold.js +21 -0
- package/src/templates/commands.js +65 -0
- package/src/templates/config.js +230 -0
- package/src/templates/data/domain-complexity.csv +15 -0
- package/src/templates/data/project-types.csv +11 -0
- package/src/templates/guardrail.js +171 -0
- package/src/templates/index.js +17 -0
- package/src/templates/references.js +549 -0
- package/src/templates/scripts.js +345 -0
- package/src/templates/skills.js +412 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
export function scripts(c) {
|
|
2
|
+
const a = c.apedDir;
|
|
3
|
+
const o = c.outputDir;
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
path: `${a}/aped-a/scripts/validate-brief.sh`,
|
|
7
|
+
executable: true,
|
|
8
|
+
content: `#!/usr/bin/env bash
|
|
9
|
+
# Validate product brief has all required sections
|
|
10
|
+
# Usage: validate-brief.sh <brief-file>
|
|
11
|
+
# Exit 0 if valid, exit 1 with missing sections listed
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
if [[ $# -ne 1 ]]; then
|
|
16
|
+
echo "Usage: $0 <brief-file>"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
FILE="$1"
|
|
21
|
+
|
|
22
|
+
if [[ ! -f "$FILE" ]]; then
|
|
23
|
+
echo "ERROR: File not found: $FILE"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
REQUIRED_SECTIONS=(
|
|
28
|
+
"## Executive Summary"
|
|
29
|
+
"## Core Vision"
|
|
30
|
+
"## Target Users"
|
|
31
|
+
"## Success Metrics"
|
|
32
|
+
"## MVP Scope"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
MISSING=()
|
|
36
|
+
|
|
37
|
+
for section in "\${REQUIRED_SECTIONS[@]}"; do
|
|
38
|
+
if ! grep -q "$section" "$FILE"; then
|
|
39
|
+
MISSING+=("$section")
|
|
40
|
+
fi
|
|
41
|
+
done
|
|
42
|
+
|
|
43
|
+
if [[ \${#MISSING[@]} -gt 0 ]]; then
|
|
44
|
+
echo "VALIDATION FAILED — Missing sections:"
|
|
45
|
+
for m in "\${MISSING[@]}"; do
|
|
46
|
+
echo " - $m"
|
|
47
|
+
done
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
echo "VALIDATION PASSED — All required sections present"
|
|
52
|
+
exit 0
|
|
53
|
+
`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
path: `${a}/aped-p/scripts/validate-prd.sh`,
|
|
57
|
+
executable: true,
|
|
58
|
+
content: `#!/usr/bin/env bash
|
|
59
|
+
# Validate PRD has required sections, FR format, and no anti-patterns
|
|
60
|
+
# Usage: validate-prd.sh <prd-file>
|
|
61
|
+
# Exit 0 if valid, exit 1 with issues listed
|
|
62
|
+
|
|
63
|
+
set -euo pipefail
|
|
64
|
+
|
|
65
|
+
if [[ $# -ne 1 ]]; then
|
|
66
|
+
echo "Usage: $0 <prd-file>"
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
FILE="$1"
|
|
71
|
+
|
|
72
|
+
if [[ ! -f "$FILE" ]]; then
|
|
73
|
+
echo "ERROR: File not found: $FILE"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
ISSUES=()
|
|
78
|
+
|
|
79
|
+
# Check required sections
|
|
80
|
+
REQUIRED_SECTIONS=(
|
|
81
|
+
"## Executive Summary"
|
|
82
|
+
"## Success Criteria"
|
|
83
|
+
"## Product Scope"
|
|
84
|
+
"## User Journeys"
|
|
85
|
+
"## Functional Requirements"
|
|
86
|
+
"## Non-Functional Requirements"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for section in "\${REQUIRED_SECTIONS[@]}"; do
|
|
90
|
+
if ! grep -q "$section" "$FILE"; then
|
|
91
|
+
ISSUES+=("MISSING SECTION: $section")
|
|
92
|
+
fi
|
|
93
|
+
done
|
|
94
|
+
|
|
95
|
+
# Check FR format
|
|
96
|
+
FR_LINES=$(grep -E '^FR[0-9]+:' "$FILE" 2>/dev/null || true)
|
|
97
|
+
FR_COUNT=0
|
|
98
|
+
if [[ -n "$FR_LINES" ]]; then
|
|
99
|
+
FR_COUNT=$(echo "$FR_LINES" | wc -l | tr -d ' ')
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
if [[ "$FR_COUNT" -lt 10 ]]; then
|
|
103
|
+
ISSUES+=("FR COUNT TOO LOW: Found $FR_COUNT FRs (minimum 10)")
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if [[ "$FR_COUNT" -gt 80 ]]; then
|
|
107
|
+
ISSUES+=("FR COUNT TOO HIGH: Found $FR_COUNT FRs (maximum 80)")
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Check for anti-pattern words in FR lines
|
|
111
|
+
ANTI_PATTERNS=("easy" "intuitive" "fast" "responsive" "simple" "multiple" "several" "various")
|
|
112
|
+
|
|
113
|
+
for pattern in "\${ANTI_PATTERNS[@]}"; do
|
|
114
|
+
MATCHES=$(grep -inE "^FR[0-9]+:.*\\b\${pattern}\\b" "$FILE" 2>/dev/null || true)
|
|
115
|
+
if [[ -n "$MATCHES" ]]; then
|
|
116
|
+
ISSUES+=("ANTI-PATTERN '$pattern' found in FR: $MATCHES")
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
# Report results
|
|
121
|
+
if [[ \${#ISSUES[@]} -gt 0 ]]; then
|
|
122
|
+
echo "VALIDATION FAILED — Issues found:"
|
|
123
|
+
for issue in "\${ISSUES[@]}"; do
|
|
124
|
+
echo " - $issue"
|
|
125
|
+
done
|
|
126
|
+
exit 1
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
echo "VALIDATION PASSED — PRD is valid ($FR_COUNT FRs, all sections present, no anti-patterns)"
|
|
130
|
+
exit 0
|
|
131
|
+
`,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
path: `${a}/aped-e/scripts/validate-coverage.sh`,
|
|
135
|
+
executable: true,
|
|
136
|
+
content: `#!/usr/bin/env bash
|
|
137
|
+
# Validate that all FRs from PRD are covered in epics
|
|
138
|
+
# Usage: validate-coverage.sh <epics-file> <prd-file>
|
|
139
|
+
# Exit 0 if all covered, exit 1 with missing FRs listed
|
|
140
|
+
|
|
141
|
+
set -euo pipefail
|
|
142
|
+
|
|
143
|
+
if [[ $# -ne 2 ]]; then
|
|
144
|
+
echo "Usage: $0 <epics-file> <prd-file>"
|
|
145
|
+
exit 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
EPICS_FILE="$1"
|
|
149
|
+
PRD_FILE="$2"
|
|
150
|
+
|
|
151
|
+
if [[ ! -f "$EPICS_FILE" ]]; then
|
|
152
|
+
echo "ERROR: Epics file not found: $EPICS_FILE"
|
|
153
|
+
exit 1
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
if [[ ! -f "$PRD_FILE" ]]; then
|
|
157
|
+
echo "ERROR: PRD file not found: $PRD_FILE"
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Extract FR numbers
|
|
162
|
+
PRD_FRS=$(grep -oE 'FR[0-9]+' "$PRD_FILE" | sort -u || true)
|
|
163
|
+
EPIC_FRS=$(grep -oE 'FR[0-9]+' "$EPICS_FILE" | sort -u || true)
|
|
164
|
+
|
|
165
|
+
if [[ -z "$PRD_FRS" ]]; then
|
|
166
|
+
echo "WARNING: No FRs found in PRD file"
|
|
167
|
+
exit 0
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# Find missing FRs
|
|
171
|
+
MISSING=()
|
|
172
|
+
for fr in $PRD_FRS; do
|
|
173
|
+
[[ -z "$fr" ]] && continue
|
|
174
|
+
if ! echo "$EPIC_FRS" | grep -q "^\${fr}$"; then
|
|
175
|
+
MISSING+=("$fr")
|
|
176
|
+
fi
|
|
177
|
+
done
|
|
178
|
+
|
|
179
|
+
PRD_COUNT=$(echo "$PRD_FRS" | grep -c . || echo 0)
|
|
180
|
+
EPIC_COUNT=$(echo "$EPIC_FRS" | grep -c . || echo 0)
|
|
181
|
+
|
|
182
|
+
if [[ \${#MISSING[@]} -gt 0 ]]; then
|
|
183
|
+
echo "COVERAGE VALIDATION FAILED"
|
|
184
|
+
echo "PRD FRs: $PRD_COUNT | Epics FRs: $EPIC_COUNT"
|
|
185
|
+
echo "Missing FRs (in PRD but not in epics):"
|
|
186
|
+
for fr in "\${MISSING[@]}"; do
|
|
187
|
+
echo " - $fr"
|
|
188
|
+
done
|
|
189
|
+
exit 1
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
echo "COVERAGE VALIDATION PASSED — All $PRD_COUNT FRs covered in epics"
|
|
193
|
+
exit 0
|
|
194
|
+
`,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
path: `${a}/aped-d/scripts/run-tests.sh`,
|
|
198
|
+
executable: true,
|
|
199
|
+
content: `#!/usr/bin/env bash
|
|
200
|
+
# Auto-detect test framework and run tests
|
|
201
|
+
# Usage: run-tests.sh [test-path]
|
|
202
|
+
# Exit code matches the test runner's exit code
|
|
203
|
+
|
|
204
|
+
set -euo pipefail
|
|
205
|
+
|
|
206
|
+
TEST_PATH="\${1:-}"
|
|
207
|
+
|
|
208
|
+
# Auto-detect test framework
|
|
209
|
+
if [[ -f "package.json" ]]; then
|
|
210
|
+
echo "Detected: Node.js project"
|
|
211
|
+
if grep -q '"vitest"' package.json 2>/dev/null; then
|
|
212
|
+
echo "Runner: vitest"
|
|
213
|
+
npx vitest run \${TEST_PATH:+"$TEST_PATH"}
|
|
214
|
+
elif grep -q '"jest"' package.json 2>/dev/null; then
|
|
215
|
+
echo "Runner: jest"
|
|
216
|
+
npx jest \${TEST_PATH:+"$TEST_PATH"}
|
|
217
|
+
else
|
|
218
|
+
echo "Runner: npm test"
|
|
219
|
+
npm test \${TEST_PATH:+-- "$TEST_PATH"}
|
|
220
|
+
fi
|
|
221
|
+
elif [[ -f "setup.py" ]] || [[ -f "pyproject.toml" ]] || [[ -f "setup.cfg" ]]; then
|
|
222
|
+
echo "Detected: Python project"
|
|
223
|
+
if [[ -n "$TEST_PATH" ]]; then
|
|
224
|
+
python -m pytest "$TEST_PATH" -v
|
|
225
|
+
else
|
|
226
|
+
python -m pytest -v
|
|
227
|
+
fi
|
|
228
|
+
elif [[ -f "Cargo.toml" ]]; then
|
|
229
|
+
echo "Detected: Rust project"
|
|
230
|
+
if [[ -n "$TEST_PATH" ]]; then
|
|
231
|
+
cargo test "$TEST_PATH"
|
|
232
|
+
else
|
|
233
|
+
cargo test
|
|
234
|
+
fi
|
|
235
|
+
elif [[ -f "go.mod" ]]; then
|
|
236
|
+
echo "Detected: Go project"
|
|
237
|
+
if [[ -n "$TEST_PATH" ]]; then
|
|
238
|
+
go test "$TEST_PATH" -v
|
|
239
|
+
else
|
|
240
|
+
go test ./... -v
|
|
241
|
+
fi
|
|
242
|
+
else
|
|
243
|
+
echo "ERROR: No recognized test framework found"
|
|
244
|
+
echo "Supported: package.json (Node), setup.py/pyproject.toml (Python), Cargo.toml (Rust), go.mod (Go)"
|
|
245
|
+
exit 1
|
|
246
|
+
fi
|
|
247
|
+
`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
path: `${a}/aped-r/scripts/git-audit.sh`,
|
|
251
|
+
executable: true,
|
|
252
|
+
content: `#!/usr/bin/env bash
|
|
253
|
+
# Compare git changes vs story file list
|
|
254
|
+
# Usage: git-audit.sh <story-file> [commits-back]
|
|
255
|
+
# Exit 0 if clean, exit 1 if HIGH severity discrepancies
|
|
256
|
+
|
|
257
|
+
set -euo pipefail
|
|
258
|
+
|
|
259
|
+
if [[ $# -lt 1 ]]; then
|
|
260
|
+
echo "Usage: $0 <story-file> [commits-back]"
|
|
261
|
+
exit 1
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
STORY_FILE="$1"
|
|
265
|
+
COMMITS_BACK="\${2:-10}"
|
|
266
|
+
|
|
267
|
+
if [[ ! -f "$STORY_FILE" ]]; then
|
|
268
|
+
echo "ERROR: Story file not found: $STORY_FILE"
|
|
269
|
+
exit 1
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
# Check if we're in a git repo
|
|
273
|
+
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
|
|
274
|
+
echo "WARNING: Not a git repository. Skipping git audit."
|
|
275
|
+
exit 0
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
# Extract file list from story's Dev Agent Record section
|
|
279
|
+
STORY_FILES=$(sed -n '/^### File List/,/^##/p' "$STORY_FILE" | grep -E '^\\s*[-*]' | sed 's/^[[:space:]]*[-*][[:space:]]*//' | sort -u)
|
|
280
|
+
|
|
281
|
+
# Get git changed files
|
|
282
|
+
GIT_FILES=$(git diff --name-only "HEAD~\${COMMITS_BACK}" HEAD 2>/dev/null | sort -u)
|
|
283
|
+
|
|
284
|
+
if [[ -z "$GIT_FILES" ]]; then
|
|
285
|
+
echo "WARNING: No git changes found in last $COMMITS_BACK commits"
|
|
286
|
+
exit 0
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
# Compare
|
|
290
|
+
IN_GIT_NOT_STORY=()
|
|
291
|
+
IN_STORY_NOT_GIT=()
|
|
292
|
+
|
|
293
|
+
while IFS= read -r file; do
|
|
294
|
+
if [[ -n "$file" ]] && ! echo "$STORY_FILES" | grep -qF "$file"; then
|
|
295
|
+
IN_GIT_NOT_STORY+=("$file")
|
|
296
|
+
fi
|
|
297
|
+
done <<< "$GIT_FILES"
|
|
298
|
+
|
|
299
|
+
while IFS= read -r file; do
|
|
300
|
+
if [[ -n "$file" ]] && ! echo "$GIT_FILES" | grep -qF "$file"; then
|
|
301
|
+
IN_STORY_NOT_GIT+=("$file")
|
|
302
|
+
fi
|
|
303
|
+
done <<< "$STORY_FILES"
|
|
304
|
+
|
|
305
|
+
# Report
|
|
306
|
+
echo "=== GIT AUDIT REPORT ==="
|
|
307
|
+
echo "Story: $STORY_FILE"
|
|
308
|
+
echo "Git range: HEAD~\${COMMITS_BACK}..HEAD"
|
|
309
|
+
echo ""
|
|
310
|
+
|
|
311
|
+
HAS_ISSUES=false
|
|
312
|
+
|
|
313
|
+
if [[ \${#IN_GIT_NOT_STORY[@]} -gt 0 ]]; then
|
|
314
|
+
echo "[MEDIUM] Files changed in git but NOT listed in story:"
|
|
315
|
+
for f in "\${IN_GIT_NOT_STORY[@]}"; do
|
|
316
|
+
echo " - $f"
|
|
317
|
+
done
|
|
318
|
+
echo ""
|
|
319
|
+
HAS_ISSUES=true
|
|
320
|
+
fi
|
|
321
|
+
|
|
322
|
+
if [[ \${#IN_STORY_NOT_GIT[@]} -gt 0 ]]; then
|
|
323
|
+
echo "[HIGH] Files listed in story but NO git changes:"
|
|
324
|
+
for f in "\${IN_STORY_NOT_GIT[@]}"; do
|
|
325
|
+
echo " - $f"
|
|
326
|
+
done
|
|
327
|
+
echo ""
|
|
328
|
+
HAS_ISSUES=true
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
if [[ "$HAS_ISSUES" == "false" ]]; then
|
|
332
|
+
echo "No discrepancies found. Git changes match story file list."
|
|
333
|
+
exit 0
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
# Exit 1 if HIGH severity items found
|
|
337
|
+
if [[ \${#IN_STORY_NOT_GIT[@]} -gt 0 ]]; then
|
|
338
|
+
exit 1
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
exit 0
|
|
342
|
+
`,
|
|
343
|
+
},
|
|
344
|
+
];
|
|
345
|
+
}
|