cap-pro 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/.claude-plugin/README.md +26 -0
- package/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +24 -0
- package/LICENSE +21 -0
- package/README.ja-JP.md +834 -0
- package/README.ko-KR.md +823 -0
- package/README.md +806 -0
- package/README.pt-BR.md +452 -0
- package/README.zh-CN.md +800 -0
- package/agents/cap-architect.md +269 -0
- package/agents/cap-brainstormer.md +207 -0
- package/agents/cap-curator.md +276 -0
- package/agents/cap-debugger.md +365 -0
- package/agents/cap-designer.md +246 -0
- package/agents/cap-historian.md +464 -0
- package/agents/cap-migrator.md +291 -0
- package/agents/cap-prototyper.md +197 -0
- package/agents/cap-validator.md +308 -0
- package/bin/install.js +5433 -0
- package/cap/bin/cap-tools.cjs +853 -0
- package/cap/bin/lib/arc-scanner.cjs +344 -0
- package/cap/bin/lib/cap-affinity-engine.cjs +862 -0
- package/cap/bin/lib/cap-anchor.cjs +228 -0
- package/cap/bin/lib/cap-annotation-writer.cjs +340 -0
- package/cap/bin/lib/cap-checkpoint.cjs +434 -0
- package/cap/bin/lib/cap-cluster-detect.cjs +945 -0
- package/cap/bin/lib/cap-cluster-display.cjs +52 -0
- package/cap/bin/lib/cap-cluster-format.cjs +245 -0
- package/cap/bin/lib/cap-cluster-helpers.cjs +295 -0
- package/cap/bin/lib/cap-cluster-io.cjs +212 -0
- package/cap/bin/lib/cap-completeness.cjs +540 -0
- package/cap/bin/lib/cap-deps.cjs +583 -0
- package/cap/bin/lib/cap-design-families.cjs +332 -0
- package/cap/bin/lib/cap-design.cjs +966 -0
- package/cap/bin/lib/cap-divergence-detector.cjs +400 -0
- package/cap/bin/lib/cap-doctor.cjs +752 -0
- package/cap/bin/lib/cap-feature-map-internals.cjs +19 -0
- package/cap/bin/lib/cap-feature-map-migrate.cjs +335 -0
- package/cap/bin/lib/cap-feature-map-monorepo.cjs +885 -0
- package/cap/bin/lib/cap-feature-map-shard.cjs +315 -0
- package/cap/bin/lib/cap-feature-map.cjs +1943 -0
- package/cap/bin/lib/cap-fitness-score.cjs +1075 -0
- package/cap/bin/lib/cap-impact-analysis.cjs +652 -0
- package/cap/bin/lib/cap-learn-review.cjs +1072 -0
- package/cap/bin/lib/cap-learning-signals.cjs +627 -0
- package/cap/bin/lib/cap-loader.cjs +227 -0
- package/cap/bin/lib/cap-logger.cjs +57 -0
- package/cap/bin/lib/cap-memory-bridge.cjs +764 -0
- package/cap/bin/lib/cap-memory-confidence.cjs +452 -0
- package/cap/bin/lib/cap-memory-dir.cjs +987 -0
- package/cap/bin/lib/cap-memory-engine.cjs +698 -0
- package/cap/bin/lib/cap-memory-extends.cjs +398 -0
- package/cap/bin/lib/cap-memory-graph.cjs +790 -0
- package/cap/bin/lib/cap-memory-migrate.cjs +2015 -0
- package/cap/bin/lib/cap-memory-pin.cjs +183 -0
- package/cap/bin/lib/cap-memory-platform.cjs +490 -0
- package/cap/bin/lib/cap-memory-prune.cjs +707 -0
- package/cap/bin/lib/cap-memory-schema.cjs +812 -0
- package/cap/bin/lib/cap-migrate-tags.cjs +309 -0
- package/cap/bin/lib/cap-migrate.cjs +540 -0
- package/cap/bin/lib/cap-pattern-apply.cjs +1203 -0
- package/cap/bin/lib/cap-pattern-pipeline.cjs +1034 -0
- package/cap/bin/lib/cap-plugin-manifest.cjs +80 -0
- package/cap/bin/lib/cap-realtime-affinity.cjs +399 -0
- package/cap/bin/lib/cap-reconcile.cjs +570 -0
- package/cap/bin/lib/cap-research-gate.cjs +218 -0
- package/cap/bin/lib/cap-scope-filter.cjs +402 -0
- package/cap/bin/lib/cap-semantic-pipeline.cjs +1038 -0
- package/cap/bin/lib/cap-session-extract.cjs +987 -0
- package/cap/bin/lib/cap-session.cjs +445 -0
- package/cap/bin/lib/cap-snapshot-linkage.cjs +963 -0
- package/cap/bin/lib/cap-stack-docs.cjs +646 -0
- package/cap/bin/lib/cap-tag-observer.cjs +371 -0
- package/cap/bin/lib/cap-tag-scanner.cjs +1766 -0
- package/cap/bin/lib/cap-telemetry.cjs +466 -0
- package/cap/bin/lib/cap-test-audit.cjs +1438 -0
- package/cap/bin/lib/cap-thread-migrator.cjs +307 -0
- package/cap/bin/lib/cap-thread-synthesis.cjs +545 -0
- package/cap/bin/lib/cap-thread-tracker.cjs +519 -0
- package/cap/bin/lib/cap-trace.cjs +399 -0
- package/cap/bin/lib/cap-trust-mode.cjs +336 -0
- package/cap/bin/lib/cap-ui-design-editor.cjs +642 -0
- package/cap/bin/lib/cap-ui-mind-map.cjs +712 -0
- package/cap/bin/lib/cap-ui-thread-nav.cjs +693 -0
- package/cap/bin/lib/cap-ui.cjs +1245 -0
- package/cap/bin/lib/cap-upgrade.cjs +1028 -0
- package/cap/bin/lib/cli/arg-helpers.cjs +49 -0
- package/cap/bin/lib/cli/frontmatter-router.cjs +31 -0
- package/cap/bin/lib/cli/init-router.cjs +68 -0
- package/cap/bin/lib/cli/phase-router.cjs +102 -0
- package/cap/bin/lib/cli/state-router.cjs +61 -0
- package/cap/bin/lib/cli/template-router.cjs +37 -0
- package/cap/bin/lib/cli/uat-router.cjs +29 -0
- package/cap/bin/lib/cli/validation-router.cjs +26 -0
- package/cap/bin/lib/cli/verification-router.cjs +31 -0
- package/cap/bin/lib/cli/workstream-router.cjs +39 -0
- package/cap/bin/lib/commands.cjs +961 -0
- package/cap/bin/lib/config.cjs +467 -0
- package/cap/bin/lib/convention-reader.cjs +258 -0
- package/cap/bin/lib/core.cjs +1241 -0
- package/cap/bin/lib/feature-aggregator.cjs +423 -0
- package/cap/bin/lib/frontmatter.cjs +337 -0
- package/cap/bin/lib/init.cjs +1443 -0
- package/cap/bin/lib/manifest-generator.cjs +383 -0
- package/cap/bin/lib/milestone.cjs +253 -0
- package/cap/bin/lib/model-profiles.cjs +69 -0
- package/cap/bin/lib/monorepo-context.cjs +226 -0
- package/cap/bin/lib/monorepo-migrator.cjs +509 -0
- package/cap/bin/lib/phase.cjs +889 -0
- package/cap/bin/lib/profile-output.cjs +989 -0
- package/cap/bin/lib/profile-pipeline.cjs +540 -0
- package/cap/bin/lib/roadmap.cjs +330 -0
- package/cap/bin/lib/security.cjs +394 -0
- package/cap/bin/lib/session-manager.cjs +292 -0
- package/cap/bin/lib/skeleton-generator.cjs +179 -0
- package/cap/bin/lib/state.cjs +1032 -0
- package/cap/bin/lib/template.cjs +231 -0
- package/cap/bin/lib/test-detector.cjs +62 -0
- package/cap/bin/lib/uat.cjs +283 -0
- package/cap/bin/lib/verify.cjs +889 -0
- package/cap/bin/lib/workspace-detector.cjs +371 -0
- package/cap/bin/lib/workstream.cjs +492 -0
- package/cap/commands/gsd/workstreams.md +63 -0
- package/cap/references/arc-standard.md +315 -0
- package/cap/references/cap-agent-architecture.md +101 -0
- package/cap/references/cap-gitignore-template +9 -0
- package/cap/references/cap-zero-deps.md +158 -0
- package/cap/references/checkpoints.md +778 -0
- package/cap/references/continuation-format.md +249 -0
- package/cap/references/contract-test-templates.md +312 -0
- package/cap/references/feature-map-template.md +25 -0
- package/cap/references/git-integration.md +295 -0
- package/cap/references/git-planning-commit.md +38 -0
- package/cap/references/model-profiles.md +174 -0
- package/cap/references/phase-numbering.md +126 -0
- package/cap/references/planning-config.md +202 -0
- package/cap/references/property-test-templates.md +316 -0
- package/cap/references/security-test-templates.md +347 -0
- package/cap/references/session-template.json +8 -0
- package/cap/references/tdd.md +263 -0
- package/cap/references/user-profiling.md +681 -0
- package/cap/references/verification-patterns.md +612 -0
- package/cap/templates/UAT.md +265 -0
- package/cap/templates/claude-md.md +175 -0
- package/cap/templates/codebase/architecture.md +255 -0
- package/cap/templates/codebase/concerns.md +310 -0
- package/cap/templates/codebase/conventions.md +307 -0
- package/cap/templates/codebase/integrations.md +280 -0
- package/cap/templates/codebase/stack.md +186 -0
- package/cap/templates/codebase/structure.md +285 -0
- package/cap/templates/codebase/testing.md +480 -0
- package/cap/templates/config.json +44 -0
- package/cap/templates/context.md +352 -0
- package/cap/templates/continue-here.md +78 -0
- package/cap/templates/copilot-instructions.md +7 -0
- package/cap/templates/debug-subagent-prompt.md +91 -0
- package/cap/templates/discussion-log.md +63 -0
- package/cap/templates/milestone-archive.md +123 -0
- package/cap/templates/milestone.md +115 -0
- package/cap/templates/phase-prompt.md +610 -0
- package/cap/templates/planner-subagent-prompt.md +117 -0
- package/cap/templates/project.md +186 -0
- package/cap/templates/requirements.md +231 -0
- package/cap/templates/research-project/ARCHITECTURE.md +204 -0
- package/cap/templates/research-project/FEATURES.md +147 -0
- package/cap/templates/research-project/PITFALLS.md +200 -0
- package/cap/templates/research-project/STACK.md +120 -0
- package/cap/templates/research-project/SUMMARY.md +170 -0
- package/cap/templates/research.md +552 -0
- package/cap/templates/roadmap.md +202 -0
- package/cap/templates/state.md +176 -0
- package/cap/templates/summary.md +364 -0
- package/cap/templates/user-preferences.md +498 -0
- package/cap/templates/verification-report.md +322 -0
- package/cap/workflows/add-phase.md +112 -0
- package/cap/workflows/add-tests.md +351 -0
- package/cap/workflows/add-todo.md +158 -0
- package/cap/workflows/audit-milestone.md +340 -0
- package/cap/workflows/audit-uat.md +109 -0
- package/cap/workflows/autonomous.md +891 -0
- package/cap/workflows/check-todos.md +177 -0
- package/cap/workflows/cleanup.md +152 -0
- package/cap/workflows/complete-milestone.md +767 -0
- package/cap/workflows/diagnose-issues.md +231 -0
- package/cap/workflows/discovery-phase.md +289 -0
- package/cap/workflows/discuss-phase-assumptions.md +653 -0
- package/cap/workflows/discuss-phase.md +1049 -0
- package/cap/workflows/do.md +104 -0
- package/cap/workflows/execute-phase.md +846 -0
- package/cap/workflows/execute-plan.md +514 -0
- package/cap/workflows/fast.md +105 -0
- package/cap/workflows/forensics.md +265 -0
- package/cap/workflows/health.md +181 -0
- package/cap/workflows/help.md +660 -0
- package/cap/workflows/insert-phase.md +130 -0
- package/cap/workflows/list-phase-assumptions.md +178 -0
- package/cap/workflows/list-workspaces.md +56 -0
- package/cap/workflows/manager.md +362 -0
- package/cap/workflows/map-codebase.md +377 -0
- package/cap/workflows/milestone-summary.md +223 -0
- package/cap/workflows/new-milestone.md +486 -0
- package/cap/workflows/new-project.md +1250 -0
- package/cap/workflows/new-workspace.md +237 -0
- package/cap/workflows/next.md +97 -0
- package/cap/workflows/node-repair.md +92 -0
- package/cap/workflows/note.md +156 -0
- package/cap/workflows/pause-work.md +176 -0
- package/cap/workflows/plan-milestone-gaps.md +273 -0
- package/cap/workflows/plan-phase.md +857 -0
- package/cap/workflows/plant-seed.md +169 -0
- package/cap/workflows/pr-branch.md +129 -0
- package/cap/workflows/profile-user.md +449 -0
- package/cap/workflows/progress.md +507 -0
- package/cap/workflows/quick.md +757 -0
- package/cap/workflows/remove-phase.md +155 -0
- package/cap/workflows/remove-workspace.md +90 -0
- package/cap/workflows/research-phase.md +82 -0
- package/cap/workflows/resume-project.md +326 -0
- package/cap/workflows/review.md +228 -0
- package/cap/workflows/session-report.md +146 -0
- package/cap/workflows/settings.md +283 -0
- package/cap/workflows/ship.md +228 -0
- package/cap/workflows/stats.md +60 -0
- package/cap/workflows/transition.md +671 -0
- package/cap/workflows/ui-phase.md +298 -0
- package/cap/workflows/ui-review.md +161 -0
- package/cap/workflows/update.md +323 -0
- package/cap/workflows/validate-phase.md +170 -0
- package/cap/workflows/verify-phase.md +254 -0
- package/cap/workflows/verify-work.md +637 -0
- package/commands/cap/annotate.md +165 -0
- package/commands/cap/brainstorm.md +393 -0
- package/commands/cap/checkpoint.md +106 -0
- package/commands/cap/completeness.md +94 -0
- package/commands/cap/continue.md +72 -0
- package/commands/cap/debug.md +588 -0
- package/commands/cap/deps.md +169 -0
- package/commands/cap/design.md +479 -0
- package/commands/cap/init.md +354 -0
- package/commands/cap/iterate.md +249 -0
- package/commands/cap/learn.md +459 -0
- package/commands/cap/memory.md +275 -0
- package/commands/cap/migrate-feature-map.md +91 -0
- package/commands/cap/migrate-memory.md +108 -0
- package/commands/cap/migrate-tags.md +91 -0
- package/commands/cap/migrate.md +131 -0
- package/commands/cap/prototype.md +510 -0
- package/commands/cap/reconcile.md +121 -0
- package/commands/cap/review.md +360 -0
- package/commands/cap/save.md +72 -0
- package/commands/cap/scan.md +404 -0
- package/commands/cap/start.md +356 -0
- package/commands/cap/status.md +118 -0
- package/commands/cap/test-audit.md +262 -0
- package/commands/cap/test.md +394 -0
- package/commands/cap/trace.md +133 -0
- package/commands/cap/ui.md +167 -0
- package/hooks/dist/cap-check-update.js +115 -0
- package/hooks/dist/cap-context-monitor.js +185 -0
- package/hooks/dist/cap-learn-review-hook.js +114 -0
- package/hooks/dist/cap-learning-hook.js +192 -0
- package/hooks/dist/cap-memory.js +299 -0
- package/hooks/dist/cap-prompt-guard.js +97 -0
- package/hooks/dist/cap-statusline.js +157 -0
- package/hooks/dist/cap-tag-observer.js +115 -0
- package/hooks/dist/cap-version-check.js +112 -0
- package/hooks/dist/cap-workflow-guard.js +175 -0
- package/hooks/hooks.json +55 -0
- package/package.json +58 -0
- package/scripts/base64-scan.sh +262 -0
- package/scripts/build-hooks.js +93 -0
- package/scripts/cap-removal-checklist.md +202 -0
- package/scripts/prompt-injection-scan.sh +199 -0
- package/scripts/run-tests.cjs +181 -0
- package/scripts/secret-scan.sh +227 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# Continuation Format
|
|
2
|
+
|
|
3
|
+
Standard format for presenting next steps after completing a command or workflow.
|
|
4
|
+
|
|
5
|
+
## Core Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ▶ Next Up
|
|
11
|
+
|
|
12
|
+
**{identifier}: {name}** — {one-line description}
|
|
13
|
+
|
|
14
|
+
`{command to copy-paste}`
|
|
15
|
+
|
|
16
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
**Also available:**
|
|
21
|
+
- `{alternative option 1}` — description
|
|
22
|
+
- `{alternative option 2}` — description
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Format Rules
|
|
28
|
+
|
|
29
|
+
1. **Always show what it is** — name + description, never just a command path
|
|
30
|
+
2. **Pull context from source** — ROADMAP.md for phases, PLAN.md `<objective>` for plans
|
|
31
|
+
3. **Command in inline code** — backticks, easy to copy-paste, renders as clickable link
|
|
32
|
+
4. **`/clear` explanation** — always include, keeps it concise but explains why
|
|
33
|
+
5. **"Also available" not "Other options"** — sounds more app-like
|
|
34
|
+
6. **Visual separators** — `---` above and below to make it stand out
|
|
35
|
+
|
|
36
|
+
## Variants
|
|
37
|
+
|
|
38
|
+
### Execute Next Plan
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ▶ Next Up
|
|
44
|
+
|
|
45
|
+
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
|
|
46
|
+
|
|
47
|
+
`/gsd:execute-phase 2`
|
|
48
|
+
|
|
49
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
**Also available:**
|
|
54
|
+
- Review plan before executing
|
|
55
|
+
- `/gsd:list-phase-assumptions 2` — check assumptions
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Execute Final Plan in Phase
|
|
61
|
+
|
|
62
|
+
Add note that this is the last plan and what comes after:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## ▶ Next Up
|
|
68
|
+
|
|
69
|
+
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
|
|
70
|
+
<sub>Final plan in Phase 2</sub>
|
|
71
|
+
|
|
72
|
+
`/gsd:execute-phase 2`
|
|
73
|
+
|
|
74
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
**After this completes:**
|
|
79
|
+
- Phase 2 → Phase 3 transition
|
|
80
|
+
- Next: **Phase 3: Core Features** — User dashboard and settings
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Plan a Phase
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ▶ Next Up
|
|
91
|
+
|
|
92
|
+
**Phase 2: Authentication** — JWT login flow with refresh tokens
|
|
93
|
+
|
|
94
|
+
`/gsd:plan-phase 2`
|
|
95
|
+
|
|
96
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
**Also available:**
|
|
101
|
+
- `/gsd:discuss-phase 2` — gather context first
|
|
102
|
+
- `/gsd:research-phase 2` — investigate unknowns
|
|
103
|
+
- Review roadmap
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Phase Complete, Ready for Next
|
|
109
|
+
|
|
110
|
+
Show completion status before next action:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## ✓ Phase 2 Complete
|
|
116
|
+
|
|
117
|
+
3/3 plans executed
|
|
118
|
+
|
|
119
|
+
## ▶ Next Up
|
|
120
|
+
|
|
121
|
+
**Phase 3: Core Features** — User dashboard, settings, and data export
|
|
122
|
+
|
|
123
|
+
`/gsd:plan-phase 3`
|
|
124
|
+
|
|
125
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
**Also available:**
|
|
130
|
+
- `/gsd:discuss-phase 3` — gather context first
|
|
131
|
+
- `/gsd:research-phase 3` — investigate unknowns
|
|
132
|
+
- Review what Phase 2 built
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Multiple Equal Options
|
|
138
|
+
|
|
139
|
+
When there's no clear primary action:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## ▶ Next Up
|
|
145
|
+
|
|
146
|
+
**Phase 3: Core Features** — User dashboard, settings, and data export
|
|
147
|
+
|
|
148
|
+
**To plan directly:** `/gsd:plan-phase 3`
|
|
149
|
+
|
|
150
|
+
**To discuss context first:** `/gsd:discuss-phase 3`
|
|
151
|
+
|
|
152
|
+
**To research unknowns:** `/gsd:research-phase 3`
|
|
153
|
+
|
|
154
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Milestone Complete
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 🎉 Milestone v1.0 Complete
|
|
165
|
+
|
|
166
|
+
All 4 phases shipped
|
|
167
|
+
|
|
168
|
+
## ▶ Next Up
|
|
169
|
+
|
|
170
|
+
**Start v1.1** — questioning → research → requirements → roadmap
|
|
171
|
+
|
|
172
|
+
`/gsd:new-milestone`
|
|
173
|
+
|
|
174
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Pulling Context
|
|
180
|
+
|
|
181
|
+
### For phases (from ROADMAP.md):
|
|
182
|
+
|
|
183
|
+
```markdown
|
|
184
|
+
### Phase 2: Authentication
|
|
185
|
+
**Goal**: JWT login flow with refresh tokens
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Extract: `**Phase 2: Authentication** — JWT login flow with refresh tokens`
|
|
189
|
+
|
|
190
|
+
### For plans (from ROADMAP.md):
|
|
191
|
+
|
|
192
|
+
```markdown
|
|
193
|
+
Plans:
|
|
194
|
+
- [ ] 02-03: Add refresh token rotation
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Or from PLAN.md `<objective>`:
|
|
198
|
+
|
|
199
|
+
```xml
|
|
200
|
+
<objective>
|
|
201
|
+
Add refresh token rotation with sliding expiry window.
|
|
202
|
+
|
|
203
|
+
Purpose: Extend session lifetime without compromising security.
|
|
204
|
+
</objective>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Extract: `**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry`
|
|
208
|
+
|
|
209
|
+
## Anti-Patterns
|
|
210
|
+
|
|
211
|
+
### Don't: Command-only (no context)
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
## To Continue
|
|
215
|
+
|
|
216
|
+
Run `/clear`, then paste:
|
|
217
|
+
/gsd:execute-phase 2
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
User has no idea what 02-03 is about.
|
|
221
|
+
|
|
222
|
+
### Don't: Missing /clear explanation
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
`/gsd:plan-phase 3`
|
|
226
|
+
|
|
227
|
+
Run /clear first.
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Doesn't explain why. User might skip it.
|
|
231
|
+
|
|
232
|
+
### Don't: "Other options" language
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
Other options:
|
|
236
|
+
- Review roadmap
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Sounds like an afterthought. Use "Also available:" instead.
|
|
240
|
+
|
|
241
|
+
### Don't: Fenced code blocks for commands
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
```
|
|
245
|
+
/gsd:plan-phase 3
|
|
246
|
+
```
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Fenced blocks inside templates create nesting ambiguity. Use inline backticks instead.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Contract Test Templates
|
|
2
|
+
|
|
3
|
+
Reference document for the cap-validator agent (test mode) when generating contract tests between monorepo apps or microservices. Contract tests verify that producer and consumer agree on API shape, event format, and shared types.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. API Contract Tests (Schema Validation)
|
|
8
|
+
|
|
9
|
+
Verify that API responses match the expected schema. Use when one app consumes another app's API.
|
|
10
|
+
|
|
11
|
+
### Response schema validation
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { describe, it, expect } from 'vitest';
|
|
15
|
+
import Ajv from 'ajv';
|
|
16
|
+
|
|
17
|
+
// Define the contract schema (shared between producer and consumer)
|
|
18
|
+
const userSchema = {
|
|
19
|
+
type: 'object',
|
|
20
|
+
required: ['id', 'email', 'name', 'created_at'],
|
|
21
|
+
properties: {
|
|
22
|
+
id: { type: 'string', format: 'uuid' },
|
|
23
|
+
email: { type: 'string', format: 'email' },
|
|
24
|
+
name: { type: 'string', minLength: 1 },
|
|
25
|
+
created_at: { type: 'string', format: 'date-time' },
|
|
26
|
+
role: { type: 'string', enum: ['user', 'admin', 'moderator'] },
|
|
27
|
+
},
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('API Contract: GET /api/users/:id', () => {
|
|
32
|
+
const ajv = new Ajv({ allErrors: true, formats: { uuid: true, email: true, 'date-time': true } });
|
|
33
|
+
|
|
34
|
+
it('response matches user schema', async () => {
|
|
35
|
+
const response = await fetch(`${API_URL}/api/users/${testUserId}`);
|
|
36
|
+
expect(response.status).toBe(200);
|
|
37
|
+
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
const validate = ajv.compile(userSchema);
|
|
40
|
+
const valid = validate(data);
|
|
41
|
+
expect(valid).toBe(true);
|
|
42
|
+
if (!valid) console.error('Schema violations:', validate.errors);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('list response matches array of user schema', async () => {
|
|
46
|
+
const response = await fetch(`${API_URL}/api/users`);
|
|
47
|
+
expect(response.status).toBe(200);
|
|
48
|
+
|
|
49
|
+
const data = await response.json();
|
|
50
|
+
expect(Array.isArray(data)).toBe(true);
|
|
51
|
+
|
|
52
|
+
const validate = ajv.compile(userSchema);
|
|
53
|
+
for (const item of data) {
|
|
54
|
+
expect(validate(item)).toBe(true);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Request contract validation (producer side)
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
describe('API Contract: POST /api/bookings (request validation)', () => {
|
|
64
|
+
it('rejects request missing required fields', async () => {
|
|
65
|
+
const response = await fetch(`${API_URL}/api/bookings`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
68
|
+
body: JSON.stringify({ /* missing required fields */ }),
|
|
69
|
+
});
|
|
70
|
+
expect(response.status).toBe(400);
|
|
71
|
+
const body = await response.json();
|
|
72
|
+
expect(body.errors).toBeDefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('rejects request with wrong field types', async () => {
|
|
76
|
+
const response = await fetch(`${API_URL}/api/bookings`, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
start_time: 'not-a-date',
|
|
81
|
+
duration: 'not-a-number',
|
|
82
|
+
resource_id: 123, // should be string
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
expect(response.status).toBe(400);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('accepts valid request matching contract', async () => {
|
|
89
|
+
const response = await fetch(`${API_URL}/api/bookings`, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
start_time: '2026-04-01T10:00:00Z',
|
|
94
|
+
duration: 60,
|
|
95
|
+
resource_id: 'room-a',
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
expect([200, 201]).toContain(response.status);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Version compatibility
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
describe('API Contract: version compatibility', () => {
|
|
107
|
+
it('v1 response is backward-compatible with v2 consumer', async () => {
|
|
108
|
+
const response = await fetch(`${API_URL}/api/v1/users/${testUserId}`);
|
|
109
|
+
const data = await response.json();
|
|
110
|
+
|
|
111
|
+
// v2 consumer expects these fields exist
|
|
112
|
+
expect(data).toHaveProperty('id');
|
|
113
|
+
expect(data).toHaveProperty('email');
|
|
114
|
+
// v2 added 'avatar_url' -- should handle absence gracefully
|
|
115
|
+
const avatarUrl = data.avatar_url ?? null;
|
|
116
|
+
expect(avatarUrl === null || typeof avatarUrl === 'string').toBe(true);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 2. Event Contract Tests (Message Format)
|
|
124
|
+
|
|
125
|
+
Verify that events/messages emitted by one service match the format expected by consumers.
|
|
126
|
+
|
|
127
|
+
### Event payload validation
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { describe, it, expect } from 'vitest';
|
|
131
|
+
|
|
132
|
+
// Shared event contract
|
|
133
|
+
const bookingCreatedSchema = {
|
|
134
|
+
type: 'booking.created',
|
|
135
|
+
version: '1.0',
|
|
136
|
+
payload: {
|
|
137
|
+
booking_id: 'string:uuid',
|
|
138
|
+
user_id: 'string:uuid',
|
|
139
|
+
resource_id: 'string',
|
|
140
|
+
start_time: 'string:iso-datetime',
|
|
141
|
+
end_time: 'string:iso-datetime',
|
|
142
|
+
status: 'string:enum(pending,confirmed,cancelled)',
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
describe('Event Contract: booking.created', () => {
|
|
147
|
+
it('emitted event matches contract schema', async () => {
|
|
148
|
+
// Arrange: create a booking (producer action)
|
|
149
|
+
const booking = await createBooking({
|
|
150
|
+
user_id: testUserId,
|
|
151
|
+
resource_id: 'room-a',
|
|
152
|
+
start_time: '2026-04-01T10:00:00Z',
|
|
153
|
+
end_time: '2026-04-01T11:00:00Z',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Act: capture the emitted event
|
|
157
|
+
const event = await captureEvent('booking.created');
|
|
158
|
+
|
|
159
|
+
// Assert: event matches contract
|
|
160
|
+
expect(event.type).toBe('booking.created');
|
|
161
|
+
expect(event.version).toBe('1.0');
|
|
162
|
+
expect(event.payload).toBeDefined();
|
|
163
|
+
expect(typeof event.payload.booking_id).toBe('string');
|
|
164
|
+
expect(typeof event.payload.user_id).toBe('string');
|
|
165
|
+
expect(typeof event.payload.resource_id).toBe('string');
|
|
166
|
+
expect(typeof event.payload.start_time).toBe('string');
|
|
167
|
+
expect(typeof event.payload.end_time).toBe('string');
|
|
168
|
+
expect(['pending', 'confirmed', 'cancelled']).toContain(event.payload.status);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('consumer can deserialize event payload', async () => {
|
|
172
|
+
const rawEvent = JSON.stringify({
|
|
173
|
+
type: 'booking.created',
|
|
174
|
+
version: '1.0',
|
|
175
|
+
payload: {
|
|
176
|
+
booking_id: '550e8400-e29b-41d4-a716-446655440000',
|
|
177
|
+
user_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
178
|
+
resource_id: 'room-a',
|
|
179
|
+
start_time: '2026-04-01T10:00:00Z',
|
|
180
|
+
end_time: '2026-04-01T11:00:00Z',
|
|
181
|
+
status: 'confirmed',
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Consumer deserialization
|
|
186
|
+
const parsed = JSON.parse(rawEvent);
|
|
187
|
+
const startTime = new Date(parsed.payload.start_time);
|
|
188
|
+
expect(startTime.getTime()).toBeGreaterThan(0);
|
|
189
|
+
expect(parsed.payload.booking_id).toMatch(
|
|
190
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Event ordering and idempotency
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
describe('Event Contract: idempotency', () => {
|
|
200
|
+
it('processing same event twice produces same result', async () => {
|
|
201
|
+
const event = {
|
|
202
|
+
type: 'booking.created',
|
|
203
|
+
idempotency_key: 'test-key-001',
|
|
204
|
+
payload: { booking_id: 'b-001', user_id: 'u-001', resource_id: 'room-a' },
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const result1 = await processEvent(event);
|
|
208
|
+
const result2 = await processEvent(event);
|
|
209
|
+
expect(result1).toEqual(result2);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('events with different versions are handled gracefully', async () => {
|
|
213
|
+
const eventV2 = {
|
|
214
|
+
type: 'booking.created',
|
|
215
|
+
version: '2.0',
|
|
216
|
+
payload: {
|
|
217
|
+
booking_id: 'b-002',
|
|
218
|
+
user_id: 'u-001',
|
|
219
|
+
resource_id: 'room-a',
|
|
220
|
+
// v2 adds new field
|
|
221
|
+
recurring: true,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// v1 consumer should not crash
|
|
226
|
+
const result = await processEvent(eventV2);
|
|
227
|
+
expect(result).toBeDefined();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 3. Shared Type Contract Tests (TypeScript)
|
|
235
|
+
|
|
236
|
+
When apps share types via a `packages/shared` or similar, test that the types match reality.
|
|
237
|
+
|
|
238
|
+
### Type-to-runtime validation
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { describe, it, expect } from 'vitest';
|
|
242
|
+
import type { Booking, User, BookingStatus } from '@myapp/shared';
|
|
243
|
+
|
|
244
|
+
describe('Shared Type Contract: Booking', () => {
|
|
245
|
+
it('runtime booking object satisfies Booking type shape', () => {
|
|
246
|
+
// Simulate what the API actually returns
|
|
247
|
+
const apiResponse = {
|
|
248
|
+
id: 'b-001',
|
|
249
|
+
user_id: 'u-001',
|
|
250
|
+
resource_id: 'room-a',
|
|
251
|
+
start_time: '2026-04-01T10:00:00Z',
|
|
252
|
+
end_time: '2026-04-01T11:00:00Z',
|
|
253
|
+
status: 'confirmed' as BookingStatus,
|
|
254
|
+
created_at: '2026-03-31T00:00:00Z',
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Runtime checks matching the TypeScript interface
|
|
258
|
+
const booking: Booking = apiResponse;
|
|
259
|
+
expect(typeof booking.id).toBe('string');
|
|
260
|
+
expect(typeof booking.user_id).toBe('string');
|
|
261
|
+
expect(typeof booking.resource_id).toBe('string');
|
|
262
|
+
expect(typeof booking.start_time).toBe('string');
|
|
263
|
+
expect(typeof booking.end_time).toBe('string');
|
|
264
|
+
expect(['pending', 'confirmed', 'cancelled']).toContain(booking.status);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('required fields are never null in production data', async () => {
|
|
268
|
+
const bookings = await fetchBookings();
|
|
269
|
+
for (const booking of bookings) {
|
|
270
|
+
expect(booking.id).not.toBeNull();
|
|
271
|
+
expect(booking.user_id).not.toBeNull();
|
|
272
|
+
expect(booking.start_time).not.toBeNull();
|
|
273
|
+
expect(booking.end_time).not.toBeNull();
|
|
274
|
+
expect(booking.status).not.toBeNull();
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Cross-package import validation
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
describe('Shared Type Contract: cross-package imports', () => {
|
|
284
|
+
it('shared types can be imported by consumer package', async () => {
|
|
285
|
+
// This test verifies the build/bundling doesn't break type exports
|
|
286
|
+
const shared = await import('@myapp/shared');
|
|
287
|
+
expect(shared).toBeDefined();
|
|
288
|
+
expect(typeof shared.BookingStatusEnum).toBeDefined();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('shared constants match between packages', () => {
|
|
292
|
+
// Both producer and consumer should use same status values
|
|
293
|
+
const validStatuses = ['pending', 'confirmed', 'cancelled'];
|
|
294
|
+
expect(validStatuses).toEqual(expect.arrayContaining(['pending', 'confirmed', 'cancelled']));
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Usage Notes
|
|
302
|
+
|
|
303
|
+
When generating contract tests:
|
|
304
|
+
|
|
305
|
+
1. **Define the contract first** -- write the expected schema before writing the test
|
|
306
|
+
2. **Test both sides** -- producer should validate it emits correctly, consumer should validate it can parse
|
|
307
|
+
3. **Version contracts** -- include version in schema, test backward compatibility
|
|
308
|
+
4. **Use fixture data** -- keep test payloads close to real production data shapes
|
|
309
|
+
5. **For monorepos**: put contract definitions in `packages/shared/contracts/`
|
|
310
|
+
6. **For microservices**: each service owns its producer contract, consumers write their own consumer tests
|
|
311
|
+
7. **Test evolution**: when adding fields, verify old consumers still work
|
|
312
|
+
8. **Idempotency**: always test that duplicate message processing is safe
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Feature Map
|
|
2
|
+
|
|
3
|
+
<!-- @gsd-context Template for FEATURE-MAP.md -- the single source of truth in CAP v2.0. Generated by /cap:init, populated by /cap:brainstorm, updated by /cap:scan. -->
|
|
4
|
+
<!-- @gsd-decision Markdown table format: human-readable, git-diffable, machine-parseable via regex. Each feature is a section with an AC table. -->
|
|
5
|
+
|
|
6
|
+
**Last scan:** _never_
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
_No features defined yet. Run `/cap:brainstorm` to discover features or add them manually below._
|
|
11
|
+
|
|
12
|
+
<!--
|
|
13
|
+
## Feature Template
|
|
14
|
+
|
|
15
|
+
### Feature Name
|
|
16
|
+
|
|
17
|
+
**Group:** Group Name
|
|
18
|
+
**Status:** draft
|
|
19
|
+
**Dependencies:** none
|
|
20
|
+
|
|
21
|
+
| AC | Description | Status |
|
|
22
|
+
|----|-------------|--------|
|
|
23
|
+
| AC-1 | Imperative description of acceptance criterion | pending |
|
|
24
|
+
| AC-2 | Another acceptance criterion | pending |
|
|
25
|
+
-->
|