code-as-plan 2.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.
Files changed (188) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja-JP.md +834 -0
  3. package/README.ko-KR.md +823 -0
  4. package/README.md +1006 -0
  5. package/README.pt-BR.md +452 -0
  6. package/README.zh-CN.md +800 -0
  7. package/agents/cap-brainstormer.md +154 -0
  8. package/agents/cap-debugger.md +221 -0
  9. package/agents/cap-prototyper.md +170 -0
  10. package/agents/cap-reviewer.md +230 -0
  11. package/agents/cap-tester.md +193 -0
  12. package/bin/install.js +5002 -0
  13. package/cap/bin/gsd-tools.cjs +1141 -0
  14. package/cap/bin/lib/arc-scanner.cjs +341 -0
  15. package/cap/bin/lib/cap-feature-map.cjs +506 -0
  16. package/cap/bin/lib/cap-session.cjs +191 -0
  17. package/cap/bin/lib/cap-stack-docs.cjs +598 -0
  18. package/cap/bin/lib/cap-tag-scanner.cjs +458 -0
  19. package/cap/bin/lib/commands.cjs +959 -0
  20. package/cap/bin/lib/config.cjs +466 -0
  21. package/cap/bin/lib/convention-reader.cjs +180 -0
  22. package/cap/bin/lib/core.cjs +1230 -0
  23. package/cap/bin/lib/feature-aggregator.cjs +422 -0
  24. package/cap/bin/lib/frontmatter.cjs +336 -0
  25. package/cap/bin/lib/init.cjs +1442 -0
  26. package/cap/bin/lib/manifest-generator.cjs +381 -0
  27. package/cap/bin/lib/milestone.cjs +252 -0
  28. package/cap/bin/lib/model-profiles.cjs +68 -0
  29. package/cap/bin/lib/monorepo-context.cjs +224 -0
  30. package/cap/bin/lib/monorepo-migrator.cjs +507 -0
  31. package/cap/bin/lib/phase.cjs +888 -0
  32. package/cap/bin/lib/profile-output.cjs +952 -0
  33. package/cap/bin/lib/profile-pipeline.cjs +539 -0
  34. package/cap/bin/lib/roadmap.cjs +329 -0
  35. package/cap/bin/lib/security.cjs +382 -0
  36. package/cap/bin/lib/session-manager.cjs +290 -0
  37. package/cap/bin/lib/skeleton-generator.cjs +177 -0
  38. package/cap/bin/lib/state.cjs +1031 -0
  39. package/cap/bin/lib/template.cjs +222 -0
  40. package/cap/bin/lib/test-detector.cjs +61 -0
  41. package/cap/bin/lib/uat.cjs +282 -0
  42. package/cap/bin/lib/verify.cjs +888 -0
  43. package/cap/bin/lib/workspace-detector.cjs +369 -0
  44. package/cap/bin/lib/workstream.cjs +491 -0
  45. package/cap/commands/gsd/workstreams.md +63 -0
  46. package/cap/references/arc-standard.md +315 -0
  47. package/cap/references/cap-agent-architecture.md +102 -0
  48. package/cap/references/cap-gitignore-template +9 -0
  49. package/cap/references/cap-zero-deps.md +158 -0
  50. package/cap/references/checkpoints.md +778 -0
  51. package/cap/references/continuation-format.md +249 -0
  52. package/cap/references/decimal-phase-calculation.md +64 -0
  53. package/cap/references/feature-map-template.md +25 -0
  54. package/cap/references/git-integration.md +295 -0
  55. package/cap/references/git-planning-commit.md +38 -0
  56. package/cap/references/model-profile-resolution.md +36 -0
  57. package/cap/references/model-profiles.md +139 -0
  58. package/cap/references/phase-argument-parsing.md +61 -0
  59. package/cap/references/planning-config.md +202 -0
  60. package/cap/references/questioning.md +162 -0
  61. package/cap/references/session-template.json +8 -0
  62. package/cap/references/tdd.md +263 -0
  63. package/cap/references/ui-brand.md +160 -0
  64. package/cap/references/user-profiling.md +681 -0
  65. package/cap/references/verification-patterns.md +612 -0
  66. package/cap/references/workstream-flag.md +58 -0
  67. package/cap/templates/DEBUG.md +164 -0
  68. package/cap/templates/UAT.md +265 -0
  69. package/cap/templates/UI-SPEC.md +100 -0
  70. package/cap/templates/VALIDATION.md +76 -0
  71. package/cap/templates/claude-md.md +122 -0
  72. package/cap/templates/codebase/architecture.md +255 -0
  73. package/cap/templates/codebase/concerns.md +310 -0
  74. package/cap/templates/codebase/conventions.md +307 -0
  75. package/cap/templates/codebase/integrations.md +280 -0
  76. package/cap/templates/codebase/stack.md +186 -0
  77. package/cap/templates/codebase/structure.md +285 -0
  78. package/cap/templates/codebase/testing.md +480 -0
  79. package/cap/templates/config.json +44 -0
  80. package/cap/templates/context.md +352 -0
  81. package/cap/templates/continue-here.md +78 -0
  82. package/cap/templates/copilot-instructions.md +7 -0
  83. package/cap/templates/debug-subagent-prompt.md +91 -0
  84. package/cap/templates/dev-preferences.md +21 -0
  85. package/cap/templates/discovery.md +146 -0
  86. package/cap/templates/discussion-log.md +63 -0
  87. package/cap/templates/milestone-archive.md +123 -0
  88. package/cap/templates/milestone.md +115 -0
  89. package/cap/templates/phase-prompt.md +610 -0
  90. package/cap/templates/planner-subagent-prompt.md +117 -0
  91. package/cap/templates/project.md +186 -0
  92. package/cap/templates/requirements.md +231 -0
  93. package/cap/templates/research-project/ARCHITECTURE.md +204 -0
  94. package/cap/templates/research-project/FEATURES.md +147 -0
  95. package/cap/templates/research-project/PITFALLS.md +200 -0
  96. package/cap/templates/research-project/STACK.md +120 -0
  97. package/cap/templates/research-project/SUMMARY.md +170 -0
  98. package/cap/templates/research.md +552 -0
  99. package/cap/templates/retrospective.md +54 -0
  100. package/cap/templates/roadmap.md +202 -0
  101. package/cap/templates/state.md +176 -0
  102. package/cap/templates/summary-complex.md +59 -0
  103. package/cap/templates/summary-minimal.md +41 -0
  104. package/cap/templates/summary-standard.md +48 -0
  105. package/cap/templates/summary.md +248 -0
  106. package/cap/templates/user-profile.md +146 -0
  107. package/cap/templates/user-setup.md +311 -0
  108. package/cap/templates/verification-report.md +322 -0
  109. package/cap/workflows/add-phase.md +112 -0
  110. package/cap/workflows/add-tests.md +351 -0
  111. package/cap/workflows/add-todo.md +158 -0
  112. package/cap/workflows/audit-milestone.md +340 -0
  113. package/cap/workflows/audit-uat.md +109 -0
  114. package/cap/workflows/autonomous.md +891 -0
  115. package/cap/workflows/check-todos.md +177 -0
  116. package/cap/workflows/cleanup.md +152 -0
  117. package/cap/workflows/complete-milestone.md +767 -0
  118. package/cap/workflows/diagnose-issues.md +231 -0
  119. package/cap/workflows/discovery-phase.md +289 -0
  120. package/cap/workflows/discuss-phase-assumptions.md +653 -0
  121. package/cap/workflows/discuss-phase.md +1049 -0
  122. package/cap/workflows/do.md +104 -0
  123. package/cap/workflows/execute-phase.md +846 -0
  124. package/cap/workflows/execute-plan.md +514 -0
  125. package/cap/workflows/fast.md +105 -0
  126. package/cap/workflows/forensics.md +265 -0
  127. package/cap/workflows/health.md +181 -0
  128. package/cap/workflows/help.md +660 -0
  129. package/cap/workflows/insert-phase.md +130 -0
  130. package/cap/workflows/list-phase-assumptions.md +178 -0
  131. package/cap/workflows/list-workspaces.md +56 -0
  132. package/cap/workflows/manager.md +362 -0
  133. package/cap/workflows/map-codebase.md +377 -0
  134. package/cap/workflows/milestone-summary.md +223 -0
  135. package/cap/workflows/new-milestone.md +486 -0
  136. package/cap/workflows/new-project.md +1250 -0
  137. package/cap/workflows/new-workspace.md +237 -0
  138. package/cap/workflows/next.md +97 -0
  139. package/cap/workflows/node-repair.md +92 -0
  140. package/cap/workflows/note.md +156 -0
  141. package/cap/workflows/pause-work.md +176 -0
  142. package/cap/workflows/plan-milestone-gaps.md +273 -0
  143. package/cap/workflows/plan-phase.md +859 -0
  144. package/cap/workflows/plant-seed.md +169 -0
  145. package/cap/workflows/pr-branch.md +129 -0
  146. package/cap/workflows/profile-user.md +450 -0
  147. package/cap/workflows/progress.md +507 -0
  148. package/cap/workflows/quick.md +757 -0
  149. package/cap/workflows/remove-phase.md +155 -0
  150. package/cap/workflows/remove-workspace.md +90 -0
  151. package/cap/workflows/research-phase.md +82 -0
  152. package/cap/workflows/resume-project.md +326 -0
  153. package/cap/workflows/review.md +228 -0
  154. package/cap/workflows/session-report.md +146 -0
  155. package/cap/workflows/settings.md +283 -0
  156. package/cap/workflows/ship.md +228 -0
  157. package/cap/workflows/stats.md +60 -0
  158. package/cap/workflows/transition.md +671 -0
  159. package/cap/workflows/ui-phase.md +302 -0
  160. package/cap/workflows/ui-review.md +165 -0
  161. package/cap/workflows/update.md +323 -0
  162. package/cap/workflows/validate-phase.md +174 -0
  163. package/cap/workflows/verify-phase.md +254 -0
  164. package/cap/workflows/verify-work.md +637 -0
  165. package/commands/cap/annotate.md +165 -0
  166. package/commands/cap/brainstorm.md +238 -0
  167. package/commands/cap/debug.md +297 -0
  168. package/commands/cap/init.md +262 -0
  169. package/commands/cap/iterate.md +234 -0
  170. package/commands/cap/prototype.md +281 -0
  171. package/commands/cap/refresh-docs.md +37 -0
  172. package/commands/cap/review.md +272 -0
  173. package/commands/cap/scan.md +249 -0
  174. package/commands/cap/start.md +234 -0
  175. package/commands/cap/status.md +189 -0
  176. package/commands/cap/test.md +250 -0
  177. package/hooks/dist/gsd-check-update.js +114 -0
  178. package/hooks/dist/gsd-context-monitor.js +156 -0
  179. package/hooks/dist/gsd-prompt-guard.js +96 -0
  180. package/hooks/dist/gsd-statusline.js +119 -0
  181. package/hooks/dist/gsd-workflow-guard.js +94 -0
  182. package/package.json +51 -0
  183. package/scripts/base64-scan.sh +262 -0
  184. package/scripts/build-hooks.js +82 -0
  185. package/scripts/cap-removal-checklist.md +202 -0
  186. package/scripts/prompt-injection-scan.sh +198 -0
  187. package/scripts/run-tests.cjs +29 -0
  188. package/scripts/secret-scan.sh +227 -0
@@ -0,0 +1,249 @@
1
+ ---
2
+ name: cap:scan
3
+ description: "Scan codebase for @cap-feature and @cap-todo tags with monorepo support. Traverses all workspace packages, updates Feature Map, reports coverage gaps."
4
+ argument-hint: "[--features NAME] [--json] [--monorepo]"
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Bash
9
+ - Glob
10
+ - Grep
11
+ ---
12
+
13
+ <!-- @gsd-context CAP v2.0 scan command (final pass) -- adds monorepo workspace traversal and cross-package file references to the base scan flow. -->
14
+ <!-- @gsd-decision Monorepo detection is automatic -- checks package.json workspaces field and lerna.json. No --monorepo flag required (AC-80). -->
15
+ <!-- @gsd-decision Cross-package file references use full relative paths from project root (e.g., packages/core/src/auth.ts) to avoid ambiguity (AC-79). -->
16
+ <!-- @gsd-constraint Works seamlessly with normal single-repo projects -- monorepo features are additive, not blocking (AC-80). -->
17
+
18
+ <!-- @gsd-todo(ref:AC-78) /cap:scan shall traverse all packages in a monorepo -->
19
+ <!-- @gsd-todo(ref:AC-79) Feature Map entries shall support cross-package file references -->
20
+ <!-- @gsd-todo(ref:AC-80) CAP shall work seamlessly with normal single-repo projects with no monorepo-specific configuration required -->
21
+
22
+ <objective>
23
+ Scans the codebase for @cap-feature and @cap-todo tags. In monorepo projects, automatically detects and traverses all workspace packages. Cross-references against FEATURE-MAP.md, flags orphan tags, and auto-enriches Feature Map with discovered file references.
24
+
25
+ **Monorepo support:**
26
+ - Automatically detects npm/yarn/pnpm workspaces from package.json `workspaces` field
27
+ - Detects Lerna monorepos from lerna.json
28
+ - Traverses all workspace packages independently
29
+ - File references use full paths from project root (e.g., `packages/core/src/auth.ts`)
30
+
31
+ **Arguments:**
32
+ - `--features NAME` -- scope scan to specific Feature Map entries (comma-separated)
33
+ - `--json` -- output raw scan results as JSON instead of formatted report
34
+ </objective>
35
+
36
+ <context>
37
+ $ARGUMENTS
38
+
39
+ @FEATURE-MAP.md
40
+ </context>
41
+
42
+ <process>
43
+
44
+ ## Step 0: Parse flags
45
+
46
+ Check `$ARGUMENTS` for:
47
+ - `--features NAME` -- if present, store as `feature_filter`
48
+ - `--json` -- if present, set `json_output = true`
49
+
50
+ ## Step 1: Detect monorepo configuration
51
+
52
+ <!-- @gsd-decision Monorepo detection reads package.json workspaces and lerna.json. Supports npm, yarn, pnpm workspace patterns. Glob expansion uses Bash for simplicity. -->
53
+
54
+ ```bash
55
+ node -e "
56
+ const fs = require('node:fs');
57
+ const path = require('node:path');
58
+ const pkgPath = path.join(process.cwd(), 'package.json');
59
+ const lernaPath = path.join(process.cwd(), 'lerna.json');
60
+ const result = { isMonorepo: false, workspaces: [], packages: [] };
61
+
62
+ // Check package.json workspaces
63
+ if (fs.existsSync(pkgPath)) {
64
+ try {
65
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
66
+ if (pkg.workspaces) {
67
+ result.isMonorepo = true;
68
+ result.workspaces = Array.isArray(pkg.workspaces)
69
+ ? pkg.workspaces
70
+ : (pkg.workspaces.packages || []);
71
+ }
72
+ } catch (_e) {}
73
+ }
74
+
75
+ // Check lerna.json
76
+ if (!result.isMonorepo && fs.existsSync(lernaPath)) {
77
+ try {
78
+ const lerna = JSON.parse(fs.readFileSync(lernaPath, 'utf8'));
79
+ result.isMonorepo = true;
80
+ result.workspaces = lerna.packages || ['packages/*'];
81
+ } catch (_e) {}
82
+ }
83
+
84
+ // Resolve workspace globs to actual package directories
85
+ if (result.isMonorepo) {
86
+ for (const ws of result.workspaces) {
87
+ const wsBase = ws.replace('/*', '').replace('/**', '');
88
+ const wsDir = path.join(process.cwd(), wsBase);
89
+ if (fs.existsSync(wsDir) && fs.statSync(wsDir).isDirectory()) {
90
+ const entries = fs.readdirSync(wsDir, { withFileTypes: true });
91
+ for (const entry of entries) {
92
+ if (entry.isDirectory()) {
93
+ const pkgJsonPath = path.join(wsDir, entry.name, 'package.json');
94
+ if (fs.existsSync(pkgJsonPath)) {
95
+ result.packages.push(path.join(wsBase, entry.name));
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ console.log(JSON.stringify(result, null, 2));
104
+ "
105
+ ```
106
+
107
+ Store as `monorepo_info`. Log project type:
108
+ - Monorepo: "Detected monorepo with {N} workspace packages: {list}"
109
+ - Single repo: "Single repository project detected."
110
+
111
+ ## Step 2: Run tag scanner (with monorepo awareness)
112
+
113
+ If monorepo detected, scan each workspace package independently AND the root:
114
+
115
+ ```bash
116
+ node -e "
117
+ const scanner = require('./cap/bin/lib/cap-tag-scanner.cjs');
118
+ const fs = require('node:fs');
119
+ const path = require('node:path');
120
+
121
+ const monorepoInfo = JSON.parse(process.argv[1]);
122
+ const projectRoot = process.cwd();
123
+
124
+ if (monorepoInfo.isMonorepo) {
125
+ // Scan root first
126
+ const rootTags = scanner.scanDirectory(projectRoot, { projectRoot });
127
+ const allTags = [...rootTags];
128
+
129
+ // Scan each workspace package
130
+ for (const pkg of monorepoInfo.packages) {
131
+ const pkgDir = path.join(projectRoot, pkg);
132
+ if (fs.existsSync(pkgDir)) {
133
+ const pkgTags = scanner.scanDirectory(pkgDir, { projectRoot });
134
+ allTags.push(...pkgTags);
135
+ }
136
+ }
137
+
138
+ // Deduplicate by file+line
139
+ const seen = new Set();
140
+ const deduped = allTags.filter(t => {
141
+ const key = t.file + ':' + t.line;
142
+ if (seen.has(key)) return false;
143
+ seen.add(key);
144
+ return true;
145
+ });
146
+
147
+ console.log(JSON.stringify(deduped, null, 2));
148
+ } else {
149
+ const tags = scanner.scanDirectory(projectRoot);
150
+ console.log(JSON.stringify(tags, null, 2));
151
+ }
152
+ " '<MONOREPO_INFO_JSON>'
153
+ ```
154
+
155
+ Store as `all_tags`.
156
+
157
+ ## Step 3: Group tags by feature and by package
158
+
159
+ ```bash
160
+ node -e "
161
+ const tags = JSON.parse(process.argv[1]);
162
+ const groups = {};
163
+ const packageGroups = {};
164
+
165
+ for (const tag of tags) {
166
+ // Group by feature
167
+ const fid = (tag.metadata && tag.metadata.feature) || '(unassigned)';
168
+ if (!groups[fid]) groups[fid] = [];
169
+ groups[fid].push(tag);
170
+
171
+ // Group by package (first path segment if monorepo)
172
+ const parts = tag.file.split('/');
173
+ const pkg = parts.length > 2 && parts[0] === 'packages' ? parts[0] + '/' + parts[1] : '(root)';
174
+ if (!packageGroups[pkg]) packageGroups[pkg] = [];
175
+ packageGroups[pkg].push(tag);
176
+ }
177
+
178
+ console.log(JSON.stringify({ byFeature: groups, byPackage: packageGroups }, null, 2));
179
+ " '<ALL_TAGS_JSON>'
180
+ ```
181
+
182
+ ## Step 4: Cross-reference and detect orphans
183
+
184
+ Same as base scan -- run orphan detection against FEATURE-MAP.md.
185
+
186
+ ## Step 5: Auto-enrich Feature Map with cross-package file references
187
+
188
+ <!-- @gsd-decision Cross-package file refs are stored as full relative paths from project root. This means packages/core/src/auth.ts, not just src/auth.ts. Feature Map readers can identify the package from the path prefix. -->
189
+
190
+ ```bash
191
+ node -e "
192
+ const scanner = require('./cap/bin/lib/cap-tag-scanner.cjs');
193
+ const fm = require('./cap/bin/lib/cap-feature-map.cjs');
194
+ const tags = scanner.scanDirectory(process.cwd());
195
+ const updated = fm.enrichFromTags(process.cwd(), tags);
196
+ console.log(JSON.stringify({
197
+ features_enriched: updated.features.filter(f => f.files.length > 0).length,
198
+ total_file_refs: updated.features.reduce((sum, f) => sum + f.files.length, 0),
199
+ cross_package_refs: updated.features.reduce((sum, f) =>
200
+ sum + f.files.filter(fp => fp.startsWith('packages/')).length, 0)
201
+ }));
202
+ "
203
+ ```
204
+
205
+ ## Step 6: Output results
206
+
207
+ **Formatted report (default):**
208
+
209
+ ```
210
+ cap:scan complete.
211
+
212
+ {If monorepo:}
213
+ Monorepo: {workspace_count} packages scanned
214
+ {For each package:}
215
+ - {package_name}: {tag_count} tags
216
+
217
+ Tags found: {total_tags}
218
+ @cap-feature: {count}
219
+ @cap-todo: {count}
220
+ @cap-risk: {count}
221
+ @cap-decision:{count}
222
+
223
+ Coverage: {files_with_tags} of {total_source_files} source files ({percentage}%)
224
+
225
+ Feature Map enrichment:
226
+ Features with file refs: {N}
227
+ Total file references: {N}
228
+ {If monorepo:} Cross-package refs: {N}
229
+
230
+ {Orphan section same as base scan}
231
+
232
+ Feature breakdown:
233
+ {For each feature group:}
234
+ {feature_id}: {count} tags ({type breakdown})
235
+ ```
236
+
237
+ ## Step 7: Update session
238
+
239
+ ```bash
240
+ node -e "
241
+ const session = require('./cap/bin/lib/cap-session.cjs');
242
+ session.updateSession(process.cwd(), {
243
+ lastCommand: '/cap:scan',
244
+ lastCommandTimestamp: new Date().toISOString()
245
+ });
246
+ "
247
+ ```
248
+
249
+ </process>
@@ -0,0 +1,234 @@
1
+ ---
2
+ name: cap:start
3
+ description: Initialize a CAP session -- restore previous session state, detect project context, and get working immediately.
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <!-- @gsd-context CAP v2.0 start command -- session initialization at the start of a new conversation. Restores .cap/SESSION.json state, detects workspace type, and presents current Feature Map status. -->
12
+ <!-- @gsd-decision Start reads SESSION.json to restore context from previous conversation. This is critical for cross-conversation continuity since Claude Code conversations are stateless. -->
13
+ <!-- @gsd-decision Start auto-runs /cap:init if .cap/ directory does not exist -- first-time users get bootstrapped automatically. -->
14
+
15
+ <objective>
16
+ Initialize a CAP session at the start of a new conversation:
17
+ 1. Check if .cap/ exists -- if not, auto-initialize
18
+ 2. Auto-detect project info from package.json and directory structure
19
+ 3. Load .cap/SESSION.json for previous session state
20
+ 4. List features from FEATURE-MAP.md for user selection
21
+ 5. Present current status and suggest next action
22
+
23
+ No arguments needed -- always runs the same flow.
24
+ </objective>
25
+
26
+ <context>
27
+ $ARGUMENTS
28
+
29
+ @.cap/SESSION.json
30
+ @FEATURE-MAP.md
31
+ </context>
32
+
33
+ <process>
34
+
35
+ ## Step 1: Check for .cap/ directory and auto-initialize
36
+
37
+ <!-- @gsd-todo(ref:AC-34) /cap:start shall initialize a session by setting the active feature in SESSION.json and restoring context from the Feature Map. -->
38
+
39
+ ```bash
40
+ test -d .cap && echo "initialized" || echo "not_initialized"
41
+ ```
42
+
43
+ **If not initialized:**
44
+
45
+ Log: "First run detected. Initializing .cap/ directory..."
46
+
47
+ ```bash
48
+ node -e "
49
+ const session = require('./cap/bin/lib/cap-session.cjs');
50
+ session.initCapDirectory(process.cwd());
51
+ console.log('initialized');
52
+ "
53
+ ```
54
+
55
+ Check if FEATURE-MAP.md exists:
56
+
57
+ ```bash
58
+ test -f FEATURE-MAP.md && echo "exists" || echo "missing"
59
+ ```
60
+
61
+ If FEATURE-MAP.md does not exist, generate the template:
62
+
63
+ ```bash
64
+ node -e "
65
+ const fm = require('./cap/bin/lib/cap-feature-map.cjs');
66
+ const fs = require('node:fs');
67
+ const path = require('node:path');
68
+ const template = fm.generateTemplate();
69
+ fs.writeFileSync(path.join(process.cwd(), 'FEATURE-MAP.md'), template, 'utf8');
70
+ console.log('FEATURE-MAP.md created');
71
+ "
72
+ ```
73
+
74
+ Log: "Created .cap/ directory and FEATURE-MAP.md"
75
+
76
+ ## Step 2: Auto-detect project context
77
+
78
+ <!-- @gsd-todo(ref:AC-35) /cap:start shall auto-scope to the project by deriving project information from actual code (package.json, directory structure) rather than asking questions. -->
79
+
80
+ Detect project info from the filesystem -- no questions asked:
81
+
82
+ ```bash
83
+ node -e "
84
+ const fs = require('node:fs');
85
+ const path = require('node:path');
86
+ const cwd = process.cwd();
87
+ const info = { name: path.basename(cwd), language: 'unknown', framework: 'unknown', testFramework: 'unknown' };
88
+
89
+ // Read package.json if available
90
+ const pkgPath = path.join(cwd, 'package.json');
91
+ if (fs.existsSync(pkgPath)) {
92
+ try {
93
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
94
+ info.name = pkg.name || info.name;
95
+ info.language = 'javascript';
96
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
97
+ if (allDeps.typescript) info.language = 'typescript';
98
+ if (allDeps.react) info.framework = 'react';
99
+ if (allDeps.next) info.framework = 'next.js';
100
+ if (allDeps.express) info.framework = 'express';
101
+ if (allDeps.vitest) info.testFramework = 'vitest';
102
+ else if (allDeps.jest) info.testFramework = 'jest';
103
+ else if (pkg.scripts && pkg.scripts.test && pkg.scripts.test.includes('node --test')) info.testFramework = 'node:test';
104
+ } catch (e) {}
105
+ }
106
+
107
+ // Check for Python
108
+ if (fs.existsSync(path.join(cwd, 'requirements.txt')) || fs.existsSync(path.join(cwd, 'pyproject.toml'))) {
109
+ info.language = 'python';
110
+ if (fs.existsSync(path.join(cwd, 'pyproject.toml'))) {
111
+ const content = fs.readFileSync(path.join(cwd, 'pyproject.toml'), 'utf8');
112
+ if (content.includes('django')) info.framework = 'django';
113
+ if (content.includes('fastapi')) info.framework = 'fastapi';
114
+ if (content.includes('pytest')) info.testFramework = 'pytest';
115
+ }
116
+ }
117
+
118
+ // Check for Go
119
+ if (fs.existsSync(path.join(cwd, 'go.mod'))) {
120
+ info.language = 'go';
121
+ info.testFramework = 'go test';
122
+ }
123
+
124
+ // Check for Rust
125
+ if (fs.existsSync(path.join(cwd, 'Cargo.toml'))) {
126
+ info.language = 'rust';
127
+ info.testFramework = 'cargo test';
128
+ }
129
+
130
+ console.log(JSON.stringify(info));
131
+ "
132
+ ```
133
+
134
+ Store as `project_info`.
135
+
136
+ ## Step 3: Load session state
137
+
138
+ ```bash
139
+ node -e "
140
+ const session = require('./cap/bin/lib/cap-session.cjs');
141
+ const s = session.loadSession(process.cwd());
142
+ console.log(JSON.stringify(s));
143
+ "
144
+ ```
145
+
146
+ Store as `session`.
147
+
148
+ ## Step 4: Load Feature Map and present features
149
+
150
+ ```bash
151
+ node -e "
152
+ const fm = require('./cap/bin/lib/cap-feature-map.cjs');
153
+ const featureMap = fm.readFeatureMap(process.cwd());
154
+ const status = fm.getStatus(featureMap);
155
+ console.log(JSON.stringify({
156
+ features: featureMap.features.map(f => ({ id: f.id, title: f.title, state: f.state, acCount: f.acs.length })),
157
+ ...status
158
+ }));
159
+ "
160
+ ```
161
+
162
+ Store as `fm_data`.
163
+
164
+ ## Step 5: Present session context and select active feature
165
+
166
+ Display session restoration:
167
+
168
+ ```
169
+ === CAP Session Start ===
170
+
171
+ Project: {project_info.name} ({project_info.language} / {project_info.framework})
172
+ Test framework: {project_info.testFramework}
173
+
174
+ {If session.activeFeature:}
175
+ Previous session:
176
+ Active feature: {session.activeFeature}
177
+ Last step: {session.step}
178
+ Last command: {session.lastCommand}
179
+
180
+ {End if}
181
+
182
+ Features ({fm_data.totalFeatures} total):
183
+ planned: {count}
184
+ prototyped: {count}
185
+ tested: {count}
186
+ shipped: {count}
187
+ ```
188
+
189
+ **If features exist, list them and ask user to select:**
190
+
191
+ ```
192
+ Available features:
193
+ {For each feature:}
194
+ {feature.id}: {feature.title} [{feature.state}] ({feature.acCount} ACs)
195
+ ```
196
+
197
+ If `session.activeFeature` is set, offer to continue:
198
+
199
+ Use AskUserQuestion:
200
+ > "Continue working on {session.activeFeature} ({title})? Or enter a feature ID to switch (e.g., F-001). Type 'none' to work without a focused feature."
201
+
202
+ If no active feature:
203
+
204
+ Use AskUserQuestion:
205
+ > "Select a feature to focus on (enter feature ID, e.g., F-001), or type 'none' to skip."
206
+
207
+ **Process user response:**
208
+ - If a valid feature ID: set as active feature
209
+ - If `none` or `skip`: proceed without active feature
210
+ - If continuing previous: keep existing active feature
211
+
212
+ ```bash
213
+ node -e "
214
+ const session = require('./cap/bin/lib/cap-session.cjs');
215
+ session.startSession(process.cwd(), '{selected_feature_id}', 'start');
216
+ console.log('Session updated');
217
+ "
218
+ ```
219
+
220
+ ## Step 6: Suggest next action
221
+
222
+ Based on current state, suggest:
223
+
224
+ - If no features: "No features found. Run /cap:brainstorm to discover features."
225
+ - If active feature is `planned`: "Run /cap:prototype to build initial code for {feature}."
226
+ - If active feature is `prototyped`: "Run /cap:iterate to refine, or /cap:test to write tests."
227
+ - If active feature is `tested`: "Run /cap:review to verify {feature}."
228
+ - If active feature is `shipped`: "All done with {feature}. Select a different feature or run /cap:brainstorm."
229
+
230
+ ```
231
+ Session started. Suggested next: {action}
232
+ ```
233
+
234
+ </process>
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: cap:status
3
+ description: Show project status derived from Feature Map -- feature completion, test coverage, open risks, and next actions.
4
+ argument-hint: "[--features NAME] [--verbose]"
5
+ allowed-tools:
6
+ - Read
7
+ - Bash
8
+ - Glob
9
+ - Grep
10
+ ---
11
+
12
+ <!-- @gsd-context CAP v2.0 status command -- reads FEATURE-MAP.md and .cap/SESSION.json to present a compact project status dashboard. No agent spawning, no file writes. -->
13
+ <!-- @gsd-decision Status is read-only -- it presents information but never modifies Feature Map or session state. Safe to run at any time. -->
14
+ <!-- @gsd-decision Status derives from Feature Map, session state, AND live tag scan -- gives a complete picture without requiring a separate /cap:scan first. -->
15
+
16
+ <objective>
17
+ Presents a compact project status dashboard derived from FEATURE-MAP.md, SESSION.json, and a live tag count:
18
+ - Current session state (active feature, step, duration)
19
+ - Feature completion by state (planned, prototyped, tested, shipped)
20
+ - Tag coverage statistics (files with tags vs total source files)
21
+
22
+ **Arguments:**
23
+ - `--features NAME` -- show status for specific features only
24
+ - `--verbose` -- include per-AC breakdown
25
+ </objective>
26
+
27
+ <context>
28
+ $ARGUMENTS
29
+
30
+ @FEATURE-MAP.md
31
+ @.cap/SESSION.json
32
+ </context>
33
+
34
+ <process>
35
+
36
+ ## Step 0: Parse flags
37
+
38
+ Check `$ARGUMENTS` for:
39
+ - `--features NAME` -- if present, store as `feature_filter` (comma-separated)
40
+ - `--verbose` -- if present, set `verbose = true`
41
+
42
+ ## Step 1: Read session state
43
+
44
+ <!-- @gsd-todo(ref:AC-31) /cap:status shall display the current session state from SESSION.json (active feature, current step, session duration). -->
45
+
46
+ ```bash
47
+ node -e "
48
+ const session = require('./cap/bin/lib/cap-session.cjs');
49
+ const s = session.loadSession(process.cwd());
50
+ const duration = s.startedAt ? Math.round((Date.now() - new Date(s.startedAt).getTime()) / 60000) : null;
51
+ console.log(JSON.stringify({
52
+ activeFeature: s.activeFeature,
53
+ step: s.step,
54
+ startedAt: s.startedAt,
55
+ durationMinutes: duration,
56
+ lastCommand: s.lastCommand,
57
+ lastCommandTimestamp: s.lastCommandTimestamp,
58
+ activeDebugSession: s.activeDebugSession
59
+ }));
60
+ "
61
+ ```
62
+
63
+ Store as `session_state`.
64
+
65
+ ## Step 2: Read Feature Map status
66
+
67
+ <!-- @gsd-todo(ref:AC-32) /cap:status shall display a summary of FEATURE-MAP.md (count of features per state: planned, prototyped, tested, shipped). -->
68
+
69
+ ```bash
70
+ node -e "
71
+ const fm = require('./cap/bin/lib/cap-feature-map.cjs');
72
+ const featureMap = fm.readFeatureMap(process.cwd());
73
+ const status = fm.getStatus(featureMap);
74
+ const byState = { planned: 0, prototyped: 0, tested: 0, shipped: 0 };
75
+ for (const f of featureMap.features) {
76
+ byState[f.state] = (byState[f.state] || 0) + 1;
77
+ }
78
+ console.log(JSON.stringify({
79
+ ...status,
80
+ byState,
81
+ features: featureMap.features.map(f => ({
82
+ id: f.id,
83
+ title: f.title,
84
+ state: f.state,
85
+ acCount: f.acs.length,
86
+ acsImplemented: f.acs.filter(a => a.status === 'implemented').length,
87
+ acsTested: f.acs.filter(a => a.status === 'tested').length,
88
+ acsReviewed: f.acs.filter(a => a.status === 'reviewed').length,
89
+ fileCount: f.files.length,
90
+ dependencies: f.dependencies
91
+ })),
92
+ lastScan: featureMap.lastScan
93
+ }));
94
+ "
95
+ ```
96
+
97
+ Store as `fm_status`. If `feature_filter` is set, filter `fm_status.features` to matching IDs.
98
+
99
+ ## Step 3: Compute tag coverage
100
+
101
+ <!-- @gsd-todo(ref:AC-33) /cap:status shall display tag coverage statistics (files with tags vs. total source files). -->
102
+
103
+ ```bash
104
+ node -e "
105
+ const scanner = require('./cap/bin/lib/cap-tag-scanner.cjs');
106
+ const fs = require('node:fs');
107
+ const path = require('node:path');
108
+ const tags = scanner.scanDirectory(process.cwd());
109
+ const filesWithTags = new Set(tags.map(t => t.file));
110
+ let totalFiles = 0;
111
+ function walk(dir, exclude) {
112
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
113
+ for (const e of entries) {
114
+ if (e.isDirectory() && !exclude.includes(e.name)) walk(path.join(dir, e.name), exclude);
115
+ else if (e.isFile() && scanner.SUPPORTED_EXTENSIONS.includes(path.extname(e.name))) totalFiles++;
116
+ }
117
+ }
118
+ walk(process.cwd(), scanner.DEFAULT_EXCLUDE);
119
+ const byType = {};
120
+ for (const t of tags) { byType[t.type] = (byType[t.type] || 0) + 1; }
121
+ console.log(JSON.stringify({ filesWithTags: filesWithTags.size, totalFiles, totalTags: tags.length, byType }));
122
+ "
123
+ ```
124
+
125
+ Store as `tag_stats`.
126
+
127
+ ## Step 4: Present formatted dashboard
128
+
129
+ Display:
130
+
131
+ ```
132
+ === CAP Status ===
133
+
134
+ Session:
135
+ Active feature: {session_state.activeFeature or "none"}
136
+ Current step: {session_state.step or "none"}
137
+ Session duration: {session_state.durationMinutes} minutes {or "no active session"}
138
+ Last command: {session_state.lastCommand} ({session_state.lastCommandTimestamp})
139
+
140
+ Features ({fm_status.totalFeatures} total):
141
+ planned: {byState.planned}
142
+ prototyped: {byState.prototyped}
143
+ tested: {byState.tested}
144
+ shipped: {byState.shipped}
145
+
146
+ Acceptance Criteria:
147
+ Total: {fm_status.totalACs}
148
+ Implemented: {fm_status.implementedACs}
149
+ Tested: {fm_status.testedACs}
150
+ Reviewed: {fm_status.reviewedACs}
151
+
152
+ Tag Coverage:
153
+ Source files with @cap-* tags: {tag_stats.filesWithTags} of {tag_stats.totalFiles} ({percentage}%)
154
+ Total tags: {tag_stats.totalTags}
155
+ @cap-feature: {byType.feature or 0}
156
+ @cap-todo: {byType.todo or 0}
157
+ @cap-risk: {byType.risk or 0}
158
+ @cap-decision: {byType.decision or 0}
159
+
160
+ Last scan: {fm_status.lastScan or "never"}
161
+ ```
162
+
163
+ **If `verbose` is true:**
164
+
165
+ For each feature in scope, display:
166
+
167
+ ```
168
+ {feature.id}: {feature.title} [{feature.state}]
169
+ ACs: {feature.acCount} total, {feature.acsImplemented} implemented, {feature.acsTested} tested
170
+ Files: {feature.fileCount}
171
+ Dependencies: {feature.dependencies.join(', ') or 'none'}
172
+ ```
173
+
174
+ ## Step 5: Suggest next action
175
+
176
+ Based on current state, suggest the most useful next command:
177
+
178
+ - If no features exist: "Run /cap:brainstorm to discover features."
179
+ - If all features are `planned`: "Run /cap:prototype to build initial scaffolds."
180
+ - If active feature is `prototyped`: "Run /cap:test to write tests for {activeFeature}."
181
+ - If active feature is `tested`: "Run /cap:review to verify {activeFeature}."
182
+ - If tag coverage < 50%: "Run /cap:scan or /cap:annotate to improve tag coverage."
183
+ - Otherwise: "Run /cap:iterate to continue development."
184
+
185
+ ```
186
+ Suggested next: {action}
187
+ ```
188
+
189
+ </process>