@axis-bootstrap/cli 0.1.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/README.md +90 -0
- package/package.json +42 -0
- package/src/commands/audit.js +53 -0
- package/src/commands/cleanup.js +42 -0
- package/src/commands/doctor.js +137 -0
- package/src/commands/init.js +297 -0
- package/src/commands/link.js +31 -0
- package/src/commands/spdd.js +139 -0
- package/src/commands/state.js +21 -0
- package/src/index.js +113 -0
- package/src/lib/copy.js +19 -0
- package/src/lib/detect.js +70 -0
- package/src/lib/i18n.js +147 -0
- package/src/lib/paths.js +45 -0
- package/src/lib/ui.js +29 -0
- package/templates/CANVAS.md +48 -0
- package/templates/CONVENTIONS.md +43 -0
- package/templates/INSTRUCTIONS.md +49 -0
- package/templates/STATE.md +27 -0
- package/templates/bootstrap-skill/PLANNER.md +221 -0
- package/templates/bootstrap-skill/PROMPT-TEMPLATE.md +128 -0
- package/templates/bootstrap-skill/SKILL.md +56 -0
- package/templates/bootstrap-skill/references/CANVAS-REASONS.md +111 -0
- package/templates/bootstrap-skill/references/PATTERNS.md +372 -0
- package/templates/bootstrap-skill/references/PHASE-1-DISCOVERY.md +120 -0
- package/templates/bootstrap-skill/references/PHASE-2-SPEC.md +250 -0
- package/templates/bootstrap-skill/references/PHASE-3-HARNESS.md +331 -0
- package/templates/bootstrap-skill/references/PHASE-4-MEMORY.md +187 -0
- package/templates/bootstrap-skill/references/PHASE-5-VALIDATION.md +194 -0
- package/templates/bootstrap-skill/references/QUICKSTART.md +144 -0
- package/templates/bootstrap-skill/references/TEMPLATES.md +602 -0
- package/templates/bootstrap-skill/references/UNIVERSAL-MAP.md +216 -0
- package/templates/settings.json +29 -0
- package/templates/setup-ide-links.sh +33 -0
- package/templates/skills/abstraction-first.md +55 -0
- package/templates/skills/alignment.md +53 -0
- package/templates/skills/iterative-review.md +55 -0
- package/templates/skills/story-decompose.md +54 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
All copy-paste templates used by the bootstrap. Each has a linkable anchor (e.g., `#skillmd-index`) referenced from other phases.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## INSTRUCTIONS.md
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
# <Project Name>
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
<1-2 sentences describing what the project does, for whom, and why.>
|
|
15
|
+
|
|
16
|
+
## Stack / Tools
|
|
17
|
+
|
|
18
|
+
- **Language:** <e.g., TypeScript 5.4>
|
|
19
|
+
- **Framework:** <e.g., NestJS 10>
|
|
20
|
+
- **Database:** <e.g., PostgreSQL 16 + TypeORM>
|
|
21
|
+
- **Infra:** <e.g., Docker, AWS ECS>
|
|
22
|
+
- **Test:** <e.g., Jest, Supertest>
|
|
23
|
+
|
|
24
|
+
## How to Run
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
<exact command to start local environment>
|
|
28
|
+
<exact command to run tests>
|
|
29
|
+
<exact command to build>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
| Component | Responsibility | Technology | Location |
|
|
35
|
+
| ---------- | ---------------- | ------------- | -------------- |
|
|
36
|
+
| <e.g. API> | <e.g. HTTP REST> | <e.g. NestJS> | <e.g. src/api> |
|
|
37
|
+
|
|
38
|
+
Details: [docs/architecture.md](docs/architecture.md)
|
|
39
|
+
|
|
40
|
+
## Design Principles
|
|
41
|
+
|
|
42
|
+
- **<Principle 1>:** <short rationale>
|
|
43
|
+
- **<Principle 2>:** <short rationale>
|
|
44
|
+
|
|
45
|
+
## Conventions
|
|
46
|
+
|
|
47
|
+
Summary here; details in [.ai/rules/](rules/):
|
|
48
|
+
|
|
49
|
+
- Naming: <rule>
|
|
50
|
+
- Error handling: <rule>
|
|
51
|
+
- Tests: <rule>
|
|
52
|
+
|
|
53
|
+
## Available Skills
|
|
54
|
+
|
|
55
|
+
| Skill | When to use |
|
|
56
|
+
| -------------------------------------- | ------------- |
|
|
57
|
+
| [<skill-1>](skills/<skill-1>/SKILL.md) | <when to use> |
|
|
58
|
+
| [<skill-2>](skills/<skill-2>/SKILL.md) | <when to use> |
|
|
59
|
+
|
|
60
|
+
## Links
|
|
61
|
+
|
|
62
|
+
- [Architecture](docs/architecture.md)
|
|
63
|
+
- [Database Schema](docs/database-schema.md)
|
|
64
|
+
- [State](docs/STATE.md)
|
|
65
|
+
- [Conventions](CONVENTIONS.md)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Target size:** 100-180 lines after real content is filled in.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## SKILL.md (index)
|
|
73
|
+
|
|
74
|
+
```markdown
|
|
75
|
+
---
|
|
76
|
+
name: skill-name
|
|
77
|
+
description: <2-4 lines>. Use when implementing X, debugging Y,
|
|
78
|
+
or understanding Z of the domain. Mention specific domain terms that act
|
|
79
|
+
as triggers: term1, term2, term3.
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
# Skill Title
|
|
83
|
+
|
|
84
|
+
<Purpose in 1-2 sentences.>
|
|
85
|
+
|
|
86
|
+
## When to Use
|
|
87
|
+
|
|
88
|
+
- <Specific scenario 1>
|
|
89
|
+
- <Specific scenario 2>
|
|
90
|
+
- <Specific scenario 3>
|
|
91
|
+
|
|
92
|
+
## Quick Summary
|
|
93
|
+
|
|
94
|
+
| Item | Value | Notes |
|
|
95
|
+
| ---- | ----- | ----- |
|
|
96
|
+
| ... | ... | ... |
|
|
97
|
+
|
|
98
|
+
## References
|
|
99
|
+
|
|
100
|
+
- [GUIDE.md](references/GUIDE.md) — step-by-step operational guide
|
|
101
|
+
- [REFERENCE.md](references/REFERENCE.md) — tables and reference data
|
|
102
|
+
- [PROMPT-TEMPLATE.md](references/PROMPT-TEMPLATE.md) — output contract (if generates artifacts)
|
|
103
|
+
- [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md) — common errors (optional)
|
|
104
|
+
|
|
105
|
+
## Final Validation
|
|
106
|
+
|
|
107
|
+
Before finishing work using this skill:
|
|
108
|
+
|
|
109
|
+
- [ ] <domain-specific gate 1>
|
|
110
|
+
- [ ] <domain-specific gate 2>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Target size:** 40-60 lines.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Code Rule
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
---
|
|
121
|
+
applyTo: "**/*.{ext}"
|
|
122
|
+
paths:
|
|
123
|
+
- "src/**"
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
# <Rule Name>
|
|
127
|
+
|
|
128
|
+
## <Section 1>
|
|
129
|
+
|
|
130
|
+
- <Concise guideline with context (why do it this way)>
|
|
131
|
+
- <Concise guideline with context>
|
|
132
|
+
|
|
133
|
+
## <Section 2>
|
|
134
|
+
|
|
135
|
+
- <Concise guideline>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## STATE.md
|
|
141
|
+
|
|
142
|
+
```markdown
|
|
143
|
+
# Project State
|
|
144
|
+
|
|
145
|
+
## Active Decisions
|
|
146
|
+
<!-- [YYYY-MM-DD] Decision X made because Y -->
|
|
147
|
+
|
|
148
|
+
## In Progress
|
|
149
|
+
<!-- Feature Z: 70% complete, missing integration with API X -->
|
|
150
|
+
|
|
151
|
+
## Blockers
|
|
152
|
+
<!-- API X returning 429 in staging — awaiting vendor response -->
|
|
153
|
+
|
|
154
|
+
## Deferred Ideas
|
|
155
|
+
<!-- Migrate to gRPC — evaluate when volume exceeds 10k req/min -->
|
|
156
|
+
|
|
157
|
+
## Lessons Learned
|
|
158
|
+
<!-- Bulk insert with TypeORM: use createQueryBuilder instead of save() for >100 records -->
|
|
159
|
+
|
|
160
|
+
## Pending TODOs
|
|
161
|
+
- [ ]
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Handoff Protocol
|
|
166
|
+
|
|
167
|
+
At the end of any session with relevant changes, update this file with:
|
|
168
|
+
- What was done
|
|
169
|
+
- What remains
|
|
170
|
+
- Any context that would otherwise be lost
|
|
171
|
+
|
|
172
|
+
At the start of a session, read this file **before** anything else.
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## CONVENTIONS.md
|
|
178
|
+
|
|
179
|
+
```markdown
|
|
180
|
+
# Conventions
|
|
181
|
+
|
|
182
|
+
## Single Source of Truth
|
|
183
|
+
|
|
184
|
+
All content lives in `.ai/`. IDE-specific folders contain symlinks only.
|
|
185
|
+
|
|
186
|
+
## Symlink Map
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
CLAUDE.md → .ai/INSTRUCTIONS.md
|
|
190
|
+
AGENTS.md → .ai/INSTRUCTIONS.md
|
|
191
|
+
.claude/ → ../.ai/{rules,skills,INSTRUCTIONS.md}
|
|
192
|
+
.cursor/ → ../.ai/{rules,skills}
|
|
193
|
+
.agents/ → ../.ai/{rules,skills}
|
|
194
|
+
.github/ → ../.ai/{rules,skills,INSTRUCTIONS.md}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
To add a new IDE: edit `setup-ide-links.sh` (3-4 lines) and run it.
|
|
198
|
+
|
|
199
|
+
## Templates
|
|
200
|
+
|
|
201
|
+
- **New skill:** copy `<skill>/SKILL.md` from any existing skill as a base
|
|
202
|
+
- **New rule:** copy the format from `code-style.md`
|
|
203
|
+
|
|
204
|
+
## Agent Rules
|
|
205
|
+
|
|
206
|
+
- Never duplicate content between IDEs
|
|
207
|
+
- Always create files inside `.ai/`
|
|
208
|
+
- Keep `SKILL.md` ≤ 60 lines
|
|
209
|
+
- Keep `INSTRUCTIONS.md` between 100-180 lines
|
|
210
|
+
- Update `STATE.md` at the end of sessions with changes
|
|
211
|
+
|
|
212
|
+
## Knowledge Verification Chain
|
|
213
|
+
|
|
214
|
+
Before asserting:
|
|
215
|
+
1. Codebase
|
|
216
|
+
2. Project docs
|
|
217
|
+
3. MCP/Context7 (official docs)
|
|
218
|
+
4. Web search
|
|
219
|
+
5. Mark as uncertain — never fabricate
|
|
220
|
+
|
|
221
|
+
## Maintenance
|
|
222
|
+
|
|
223
|
+
| Event | Action |
|
|
224
|
+
| --------------------------- | ------------------------------ |
|
|
225
|
+
| Code changes a skill's flow | Update the corresponding skill |
|
|
226
|
+
| Session paused | Update STATE.md |
|
|
227
|
+
| New integration | Evaluate new skill |
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## settings.json
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"permissions": {
|
|
237
|
+
"allow": [
|
|
238
|
+
"Read",
|
|
239
|
+
"Bash(git *)",
|
|
240
|
+
"Bash(<build-tool> *)",
|
|
241
|
+
"Edit(/src/**)",
|
|
242
|
+
"Edit(/test/**)",
|
|
243
|
+
"Edit(/.ai/**)"
|
|
244
|
+
],
|
|
245
|
+
"deny": [
|
|
246
|
+
"Bash(rm -rf *)",
|
|
247
|
+
"Bash(git push --force*)"
|
|
248
|
+
],
|
|
249
|
+
"ask": [
|
|
250
|
+
"Bash(git push *)",
|
|
251
|
+
"Edit(/.env*)"
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
"hooks": {
|
|
255
|
+
"PostToolUse": [
|
|
256
|
+
{
|
|
257
|
+
"matcher": "Edit|Write",
|
|
258
|
+
"hooks": [
|
|
259
|
+
{
|
|
260
|
+
"type": "command",
|
|
261
|
+
"command": "bash scripts/format-file.sh \"$CLAUDE_TOOL_INPUT_FILE_PATH\""
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
],
|
|
266
|
+
"PreToolUse": [
|
|
267
|
+
{
|
|
268
|
+
"matcher": "Bash",
|
|
269
|
+
"hooks": [
|
|
270
|
+
{
|
|
271
|
+
"type": "command",
|
|
272
|
+
"command": "bash scripts/validate-bash.sh"
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
"Stop": [
|
|
278
|
+
{
|
|
279
|
+
"hooks": [
|
|
280
|
+
{
|
|
281
|
+
"type": "command",
|
|
282
|
+
"command": "bash scripts/run-tests-if-changed.sh"
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Replace `<build-tool>` with:
|
|
292
|
+
|
|
293
|
+
| Stack | Command |
|
|
294
|
+
| ----------- | ------------------------------------------------- |
|
|
295
|
+
| Node.js | `Bash(npm *)`, `Bash(npx *)` |
|
|
296
|
+
| Python | `Bash(pip *)`, `Bash(pytest *)`, `Bash(poetry *)` |
|
|
297
|
+
| Go | `Bash(go *)` |
|
|
298
|
+
| Java/Maven | `Bash(mvn *)` |
|
|
299
|
+
| Java/Gradle | `Bash(gradle *)`, `Bash(./gradlew *)` |
|
|
300
|
+
| Ruby | `Bash(bundle *)`, `Bash(rake *)` |
|
|
301
|
+
| PHP | `Bash(composer *)` |
|
|
302
|
+
| Rust | `Bash(cargo *)` |
|
|
303
|
+
| .NET | `Bash(dotnet *)` |
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## format-file.sh
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
#!/bin/bash
|
|
311
|
+
# scripts/format-file.sh
|
|
312
|
+
# Formats the file passed as argument. Stack-aware via case.
|
|
313
|
+
# Never fails — missing formatter does not block the agent.
|
|
314
|
+
|
|
315
|
+
FILE="$1"
|
|
316
|
+
[ -z "$FILE" ] && exit 0
|
|
317
|
+
|
|
318
|
+
case "$FILE" in
|
|
319
|
+
*.ts|*.js|*.json|*.css) npx prettier --write "$FILE" 2>/dev/null ;;
|
|
320
|
+
*.py) black "$FILE" 2>/dev/null ;;
|
|
321
|
+
*.go) gofmt -w "$FILE" 2>/dev/null ;;
|
|
322
|
+
*.java) google-java-format --replace "$FILE" 2>/dev/null ;;
|
|
323
|
+
*.rb) rubocop --auto-correct "$FILE" 2>/dev/null ;;
|
|
324
|
+
*.php) php-cs-fixer fix "$FILE" 2>/dev/null ;;
|
|
325
|
+
*.rs) rustfmt "$FILE" 2>/dev/null ;;
|
|
326
|
+
esac
|
|
327
|
+
exit 0
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## validate-bash.sh
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
#!/bin/bash
|
|
336
|
+
# scripts/validate-bash.sh
|
|
337
|
+
# Blocks destructive patterns. Universal — install in any project.
|
|
338
|
+
|
|
339
|
+
INPUT=$(cat)
|
|
340
|
+
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
|
|
341
|
+
|
|
342
|
+
# Patterns never allowed without explicit confirmation
|
|
343
|
+
if echo "$CMD" | grep -qE '(rm -rf /|DROP TABLE|TRUNCATE |DELETE FROM [^W])'; then
|
|
344
|
+
echo '{"action": "deny", "reason": "Potentially destructive command. Run manually if intentional."}'
|
|
345
|
+
exit 0
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
echo '{"action": "allow"}'
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## run-tests-if-changed.sh
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
#!/bin/bash
|
|
357
|
+
# scripts/run-tests-if-changed.sh
|
|
358
|
+
# Detects changed code extensions and runs the corresponding tests.
|
|
359
|
+
|
|
360
|
+
CHANGED=$(git diff --name-only HEAD 2>/dev/null)
|
|
361
|
+
[ -z "$CHANGED" ] && exit 0
|
|
362
|
+
|
|
363
|
+
if echo "$CHANGED" | grep -qE '\.(ts|js)$'; then npm test -- --passWithNoTests 2>&1 | tail -10; fi
|
|
364
|
+
if echo "$CHANGED" | grep -qE '\.py$'; then pytest --tb=short -q 2>&1 | tail -10; fi
|
|
365
|
+
if echo "$CHANGED" | grep -qE '\.go$'; then go test ./... 2>&1 | tail -10; fi
|
|
366
|
+
if echo "$CHANGED" | grep -qE '\.java$'; then mvn test -q 2>&1 | tail -10; fi
|
|
367
|
+
if echo "$CHANGED" | grep -qE '\.rb$'; then bundle exec rspec --format progress 2>&1 | tail -10; fi
|
|
368
|
+
if echo "$CHANGED" | grep -qE '\.(cs|csproj)$'; then dotnet test --nologo 2>&1 | tail -10; fi
|
|
369
|
+
exit 0
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## setup-ide-links.sh
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
#!/bin/bash
|
|
378
|
+
# Idempotent — can run as many times as needed without error.
|
|
379
|
+
set -e
|
|
380
|
+
|
|
381
|
+
# Root
|
|
382
|
+
ln -sf .ai/INSTRUCTIONS.md CLAUDE.md
|
|
383
|
+
ln -sf .ai/INSTRUCTIONS.md AGENTS.md
|
|
384
|
+
|
|
385
|
+
# Claude Code
|
|
386
|
+
mkdir -p .claude
|
|
387
|
+
ln -sf ../.ai/INSTRUCTIONS.md .claude/CLAUDE.md
|
|
388
|
+
ln -sf ../.ai/rules .claude/rules
|
|
389
|
+
ln -sf ../.ai/skills .claude/skills
|
|
390
|
+
|
|
391
|
+
# Cursor
|
|
392
|
+
mkdir -p .cursor
|
|
393
|
+
ln -sf ../.ai/rules .cursor/rules
|
|
394
|
+
ln -sf ../.ai/skills .cursor/skills
|
|
395
|
+
|
|
396
|
+
# Windsurf / Generic Agents
|
|
397
|
+
mkdir -p .agents
|
|
398
|
+
ln -sf ../.ai/rules .agents/rules
|
|
399
|
+
ln -sf ../.ai/skills .agents/skills
|
|
400
|
+
|
|
401
|
+
# GitHub Copilot
|
|
402
|
+
mkdir -p .github
|
|
403
|
+
ln -sf ../.ai/INSTRUCTIONS.md .github/copilot-instructions.md
|
|
404
|
+
ln -sf ../.ai/rules .github/instructions
|
|
405
|
+
ln -sf ../.ai/skills .github/skills
|
|
406
|
+
|
|
407
|
+
echo "Symlinks created/updated successfully."
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Comment/remove** the sections for IDEs not used by the team, to reduce noise in `git status`.
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## architecture.md (stub)
|
|
415
|
+
|
|
416
|
+
```markdown
|
|
417
|
+
# System Architecture
|
|
418
|
+
|
|
419
|
+
## Overview
|
|
420
|
+
|
|
421
|
+
<ASCII or Mermaid diagram showing components and connections.>
|
|
422
|
+
|
|
423
|
+
## Components
|
|
424
|
+
|
|
425
|
+
| Component | Responsibility | Technology | Location |
|
|
426
|
+
| --------- | -------------- | ---------- | -------- |
|
|
427
|
+
| ... | ... | ... | ... |
|
|
428
|
+
|
|
429
|
+
## Key Architectural Decisions
|
|
430
|
+
|
|
431
|
+
- **Why <technology>:** <rationale>
|
|
432
|
+
- **Why <pattern>:** <rationale>
|
|
433
|
+
|
|
434
|
+
## Constraints and Trade-offs
|
|
435
|
+
|
|
436
|
+
- **<Constraint>:** <consequence and mitigation>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## database-schema.md (stub)
|
|
442
|
+
|
|
443
|
+
```markdown
|
|
444
|
+
# Database Schema
|
|
445
|
+
|
|
446
|
+
## Table: <name>
|
|
447
|
+
|
|
448
|
+
| Column | Type | Nullable | Description |
|
|
449
|
+
| ------ | ---- | -------- | ------------ |
|
|
450
|
+
| id | UUID | N | Generated PK |
|
|
451
|
+
| ... | ... | ... | ... |
|
|
452
|
+
|
|
453
|
+
**Indexes:** `idx_xxx` (col1, col2) — used in <query>
|
|
454
|
+
**Constraints:** `uq_xxx` (col) — ensures <invariant>
|
|
455
|
+
|
|
456
|
+
**Business rules:**
|
|
457
|
+
- <rule 1>
|
|
458
|
+
- <rule 2>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## REASONS Canvas (feature-level spec)
|
|
464
|
+
|
|
465
|
+
Use when specifying a complex feature before generating code. Follows the SPDD structure: abstract parts (intent & design) → specific parts (execution) → governance parts.
|
|
466
|
+
|
|
467
|
+
```markdown
|
|
468
|
+
# REASONS Canvas — <Feature Name>
|
|
469
|
+
|
|
470
|
+
**ID:** <YYYY-MM-DD-feature-slug>
|
|
471
|
+
**Status:** draft | reviewed | locked
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## R — Requirements
|
|
476
|
+
<!-- What problem are we solving? What is the Definition of Done? -->
|
|
477
|
+
|
|
478
|
+
**Problem:** <1-2 sentences>
|
|
479
|
+
|
|
480
|
+
**Acceptance Criteria (Given/When/Then):**
|
|
481
|
+
- Given <context>, When <action>, Then <expected result with concrete values>
|
|
482
|
+
- Given <context>, When <action>, Then <expected result with concrete values>
|
|
483
|
+
|
|
484
|
+
**Out of scope:**
|
|
485
|
+
- <explicit exclusion 1>
|
|
486
|
+
- <explicit exclusion 2>
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## E — Entities
|
|
491
|
+
<!-- Domain entities, their attributes, and relationships relevant to this feature -->
|
|
492
|
+
|
|
493
|
+
| Entity | Key Attributes | Relationships |
|
|
494
|
+
| ------ | -------------- | -------------------------- |
|
|
495
|
+
| <name> | <attr1, attr2> | <belongs to X, has many Y> |
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## A — Approach
|
|
500
|
+
<!-- Strategic direction: which pattern/design solves the problem? Why? -->
|
|
501
|
+
|
|
502
|
+
**Selected approach:** <e.g., Strategy pattern for billing calculator>
|
|
503
|
+
|
|
504
|
+
**Rationale:** <why this approach over alternatives>
|
|
505
|
+
|
|
506
|
+
**Key architectural decisions:**
|
|
507
|
+
- <decision 1>
|
|
508
|
+
- <decision 2>
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## S — Structure
|
|
513
|
+
<!-- Where does the change fit? Which components are affected? Dependencies? -->
|
|
514
|
+
|
|
515
|
+
**Components affected:**
|
|
516
|
+
| Component | File/Path | Type of change |
|
|
517
|
+
| --------- | --------- | --------------------- |
|
|
518
|
+
| <name> | <path> | new / modify / delete |
|
|
519
|
+
|
|
520
|
+
**External dependencies:** <APIs, libs, services>
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## O — Operations
|
|
525
|
+
<!-- Concrete, testable implementation steps (method-level precision) -->
|
|
526
|
+
|
|
527
|
+
1. **<Step name>**
|
|
528
|
+
- Input: <params>
|
|
529
|
+
- Logic: <what to do>
|
|
530
|
+
- Output: <return/side effect>
|
|
531
|
+
- Test: <how to verify>
|
|
532
|
+
|
|
533
|
+
2. **<Step name>**
|
|
534
|
+
- Input: <params>
|
|
535
|
+
- Logic: <what to do>
|
|
536
|
+
- Output: <return/side effect>
|
|
537
|
+
- Test: <how to verify>
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## N — Norms
|
|
542
|
+
<!-- Cross-cutting engineering standards that apply to this feature -->
|
|
543
|
+
|
|
544
|
+
- Naming: <convention>
|
|
545
|
+
- Error handling: <pattern>
|
|
546
|
+
- Logging/observability: <what to log>
|
|
547
|
+
- Test coverage: <minimum requirement>
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
## S — Safeguards
|
|
552
|
+
<!-- Non-negotiable invariants, performance limits, security rules -->
|
|
553
|
+
|
|
554
|
+
- [ ] <invariant 1 — e.g., never persist without validating X>
|
|
555
|
+
- [ ] <invariant 2 — e.g., latency must stay under Xms for Y operation>
|
|
556
|
+
- [ ] <security rule — e.g., sanitize input before passing to query>
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
**When to use:** features with >3 steps, business logic with multiple paths, or any change that touches more than 2 components. Skip for trivial fixes (<3 files, 1 obvious step).
|
|
560
|
+
|
|
561
|
+
**Sync protocol (inviolable):**
|
|
562
|
+
|
|
563
|
+
| Change type | Direction | Action |
|
|
564
|
+
| ------------------------------------ | ----------- | ------------------------------------------------------------ |
|
|
565
|
+
| Requirements changed | spec → code | Update Canvas first, then regenerate affected Operations |
|
|
566
|
+
| Code refactored (no behavior change) | code → spec | Refactor code, then sync Operations/Structure back to Canvas |
|
|
567
|
+
|
|
568
|
+
> **Rule:** when reality diverges, fix the Canvas first — then update the code. The Canvas is the source of truth.
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## Test Spec (derived from REASONS Canvas)
|
|
573
|
+
|
|
574
|
+
Generated from the Canvas Operations + Acceptance Criteria. Use alongside or after `/spdd-api-test` equivalent.
|
|
575
|
+
|
|
576
|
+
```markdown
|
|
577
|
+
# Test Spec — <Feature Name>
|
|
578
|
+
|
|
579
|
+
**Source Canvas:** <canvas file or ID>
|
|
580
|
+
|
|
581
|
+
## Scenarios
|
|
582
|
+
|
|
583
|
+
### Normal flow
|
|
584
|
+
| # | Given | When | Then | Priority |
|
|
585
|
+
| --- | --------- | -------- | ---------- | -------- |
|
|
586
|
+
| 1 | <context> | <action> | <expected> | high |
|
|
587
|
+
|
|
588
|
+
### Boundary conditions
|
|
589
|
+
| # | Given | When | Then | Priority |
|
|
590
|
+
| --- | ----------- | -------- | ---------- | -------- |
|
|
591
|
+
| 1 | <edge case> | <action> | <expected> | medium |
|
|
592
|
+
|
|
593
|
+
### Error scenarios
|
|
594
|
+
| # | Given | When | Then | Priority |
|
|
595
|
+
| --- | --------------- | -------- | -------------------- | -------- |
|
|
596
|
+
| 1 | <invalid input> | <action> | <HTTP 4xx + message> | high |
|
|
597
|
+
|
|
598
|
+
## Coverage Gate
|
|
599
|
+
- [ ] All Acceptance Criteria from Canvas covered
|
|
600
|
+
- [ ] At least 1 boundary test per numeric/date input
|
|
601
|
+
- [ ] All error paths in Safeguards covered
|
|
602
|
+
```
|