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.
Files changed (275) hide show
  1. package/.claude-plugin/README.md +26 -0
  2. package/.claude-plugin/marketplace.json +24 -0
  3. package/.claude-plugin/plugin.json +24 -0
  4. package/LICENSE +21 -0
  5. package/README.ja-JP.md +834 -0
  6. package/README.ko-KR.md +823 -0
  7. package/README.md +806 -0
  8. package/README.pt-BR.md +452 -0
  9. package/README.zh-CN.md +800 -0
  10. package/agents/cap-architect.md +269 -0
  11. package/agents/cap-brainstormer.md +207 -0
  12. package/agents/cap-curator.md +276 -0
  13. package/agents/cap-debugger.md +365 -0
  14. package/agents/cap-designer.md +246 -0
  15. package/agents/cap-historian.md +464 -0
  16. package/agents/cap-migrator.md +291 -0
  17. package/agents/cap-prototyper.md +197 -0
  18. package/agents/cap-validator.md +308 -0
  19. package/bin/install.js +5433 -0
  20. package/cap/bin/cap-tools.cjs +853 -0
  21. package/cap/bin/lib/arc-scanner.cjs +344 -0
  22. package/cap/bin/lib/cap-affinity-engine.cjs +862 -0
  23. package/cap/bin/lib/cap-anchor.cjs +228 -0
  24. package/cap/bin/lib/cap-annotation-writer.cjs +340 -0
  25. package/cap/bin/lib/cap-checkpoint.cjs +434 -0
  26. package/cap/bin/lib/cap-cluster-detect.cjs +945 -0
  27. package/cap/bin/lib/cap-cluster-display.cjs +52 -0
  28. package/cap/bin/lib/cap-cluster-format.cjs +245 -0
  29. package/cap/bin/lib/cap-cluster-helpers.cjs +295 -0
  30. package/cap/bin/lib/cap-cluster-io.cjs +212 -0
  31. package/cap/bin/lib/cap-completeness.cjs +540 -0
  32. package/cap/bin/lib/cap-deps.cjs +583 -0
  33. package/cap/bin/lib/cap-design-families.cjs +332 -0
  34. package/cap/bin/lib/cap-design.cjs +966 -0
  35. package/cap/bin/lib/cap-divergence-detector.cjs +400 -0
  36. package/cap/bin/lib/cap-doctor.cjs +752 -0
  37. package/cap/bin/lib/cap-feature-map-internals.cjs +19 -0
  38. package/cap/bin/lib/cap-feature-map-migrate.cjs +335 -0
  39. package/cap/bin/lib/cap-feature-map-monorepo.cjs +885 -0
  40. package/cap/bin/lib/cap-feature-map-shard.cjs +315 -0
  41. package/cap/bin/lib/cap-feature-map.cjs +1943 -0
  42. package/cap/bin/lib/cap-fitness-score.cjs +1075 -0
  43. package/cap/bin/lib/cap-impact-analysis.cjs +652 -0
  44. package/cap/bin/lib/cap-learn-review.cjs +1072 -0
  45. package/cap/bin/lib/cap-learning-signals.cjs +627 -0
  46. package/cap/bin/lib/cap-loader.cjs +227 -0
  47. package/cap/bin/lib/cap-logger.cjs +57 -0
  48. package/cap/bin/lib/cap-memory-bridge.cjs +764 -0
  49. package/cap/bin/lib/cap-memory-confidence.cjs +452 -0
  50. package/cap/bin/lib/cap-memory-dir.cjs +987 -0
  51. package/cap/bin/lib/cap-memory-engine.cjs +698 -0
  52. package/cap/bin/lib/cap-memory-extends.cjs +398 -0
  53. package/cap/bin/lib/cap-memory-graph.cjs +790 -0
  54. package/cap/bin/lib/cap-memory-migrate.cjs +2015 -0
  55. package/cap/bin/lib/cap-memory-pin.cjs +183 -0
  56. package/cap/bin/lib/cap-memory-platform.cjs +490 -0
  57. package/cap/bin/lib/cap-memory-prune.cjs +707 -0
  58. package/cap/bin/lib/cap-memory-schema.cjs +812 -0
  59. package/cap/bin/lib/cap-migrate-tags.cjs +309 -0
  60. package/cap/bin/lib/cap-migrate.cjs +540 -0
  61. package/cap/bin/lib/cap-pattern-apply.cjs +1203 -0
  62. package/cap/bin/lib/cap-pattern-pipeline.cjs +1034 -0
  63. package/cap/bin/lib/cap-plugin-manifest.cjs +80 -0
  64. package/cap/bin/lib/cap-realtime-affinity.cjs +399 -0
  65. package/cap/bin/lib/cap-reconcile.cjs +570 -0
  66. package/cap/bin/lib/cap-research-gate.cjs +218 -0
  67. package/cap/bin/lib/cap-scope-filter.cjs +402 -0
  68. package/cap/bin/lib/cap-semantic-pipeline.cjs +1038 -0
  69. package/cap/bin/lib/cap-session-extract.cjs +987 -0
  70. package/cap/bin/lib/cap-session.cjs +445 -0
  71. package/cap/bin/lib/cap-snapshot-linkage.cjs +963 -0
  72. package/cap/bin/lib/cap-stack-docs.cjs +646 -0
  73. package/cap/bin/lib/cap-tag-observer.cjs +371 -0
  74. package/cap/bin/lib/cap-tag-scanner.cjs +1766 -0
  75. package/cap/bin/lib/cap-telemetry.cjs +466 -0
  76. package/cap/bin/lib/cap-test-audit.cjs +1438 -0
  77. package/cap/bin/lib/cap-thread-migrator.cjs +307 -0
  78. package/cap/bin/lib/cap-thread-synthesis.cjs +545 -0
  79. package/cap/bin/lib/cap-thread-tracker.cjs +519 -0
  80. package/cap/bin/lib/cap-trace.cjs +399 -0
  81. package/cap/bin/lib/cap-trust-mode.cjs +336 -0
  82. package/cap/bin/lib/cap-ui-design-editor.cjs +642 -0
  83. package/cap/bin/lib/cap-ui-mind-map.cjs +712 -0
  84. package/cap/bin/lib/cap-ui-thread-nav.cjs +693 -0
  85. package/cap/bin/lib/cap-ui.cjs +1245 -0
  86. package/cap/bin/lib/cap-upgrade.cjs +1028 -0
  87. package/cap/bin/lib/cli/arg-helpers.cjs +49 -0
  88. package/cap/bin/lib/cli/frontmatter-router.cjs +31 -0
  89. package/cap/bin/lib/cli/init-router.cjs +68 -0
  90. package/cap/bin/lib/cli/phase-router.cjs +102 -0
  91. package/cap/bin/lib/cli/state-router.cjs +61 -0
  92. package/cap/bin/lib/cli/template-router.cjs +37 -0
  93. package/cap/bin/lib/cli/uat-router.cjs +29 -0
  94. package/cap/bin/lib/cli/validation-router.cjs +26 -0
  95. package/cap/bin/lib/cli/verification-router.cjs +31 -0
  96. package/cap/bin/lib/cli/workstream-router.cjs +39 -0
  97. package/cap/bin/lib/commands.cjs +961 -0
  98. package/cap/bin/lib/config.cjs +467 -0
  99. package/cap/bin/lib/convention-reader.cjs +258 -0
  100. package/cap/bin/lib/core.cjs +1241 -0
  101. package/cap/bin/lib/feature-aggregator.cjs +423 -0
  102. package/cap/bin/lib/frontmatter.cjs +337 -0
  103. package/cap/bin/lib/init.cjs +1443 -0
  104. package/cap/bin/lib/manifest-generator.cjs +383 -0
  105. package/cap/bin/lib/milestone.cjs +253 -0
  106. package/cap/bin/lib/model-profiles.cjs +69 -0
  107. package/cap/bin/lib/monorepo-context.cjs +226 -0
  108. package/cap/bin/lib/monorepo-migrator.cjs +509 -0
  109. package/cap/bin/lib/phase.cjs +889 -0
  110. package/cap/bin/lib/profile-output.cjs +989 -0
  111. package/cap/bin/lib/profile-pipeline.cjs +540 -0
  112. package/cap/bin/lib/roadmap.cjs +330 -0
  113. package/cap/bin/lib/security.cjs +394 -0
  114. package/cap/bin/lib/session-manager.cjs +292 -0
  115. package/cap/bin/lib/skeleton-generator.cjs +179 -0
  116. package/cap/bin/lib/state.cjs +1032 -0
  117. package/cap/bin/lib/template.cjs +231 -0
  118. package/cap/bin/lib/test-detector.cjs +62 -0
  119. package/cap/bin/lib/uat.cjs +283 -0
  120. package/cap/bin/lib/verify.cjs +889 -0
  121. package/cap/bin/lib/workspace-detector.cjs +371 -0
  122. package/cap/bin/lib/workstream.cjs +492 -0
  123. package/cap/commands/gsd/workstreams.md +63 -0
  124. package/cap/references/arc-standard.md +315 -0
  125. package/cap/references/cap-agent-architecture.md +101 -0
  126. package/cap/references/cap-gitignore-template +9 -0
  127. package/cap/references/cap-zero-deps.md +158 -0
  128. package/cap/references/checkpoints.md +778 -0
  129. package/cap/references/continuation-format.md +249 -0
  130. package/cap/references/contract-test-templates.md +312 -0
  131. package/cap/references/feature-map-template.md +25 -0
  132. package/cap/references/git-integration.md +295 -0
  133. package/cap/references/git-planning-commit.md +38 -0
  134. package/cap/references/model-profiles.md +174 -0
  135. package/cap/references/phase-numbering.md +126 -0
  136. package/cap/references/planning-config.md +202 -0
  137. package/cap/references/property-test-templates.md +316 -0
  138. package/cap/references/security-test-templates.md +347 -0
  139. package/cap/references/session-template.json +8 -0
  140. package/cap/references/tdd.md +263 -0
  141. package/cap/references/user-profiling.md +681 -0
  142. package/cap/references/verification-patterns.md +612 -0
  143. package/cap/templates/UAT.md +265 -0
  144. package/cap/templates/claude-md.md +175 -0
  145. package/cap/templates/codebase/architecture.md +255 -0
  146. package/cap/templates/codebase/concerns.md +310 -0
  147. package/cap/templates/codebase/conventions.md +307 -0
  148. package/cap/templates/codebase/integrations.md +280 -0
  149. package/cap/templates/codebase/stack.md +186 -0
  150. package/cap/templates/codebase/structure.md +285 -0
  151. package/cap/templates/codebase/testing.md +480 -0
  152. package/cap/templates/config.json +44 -0
  153. package/cap/templates/context.md +352 -0
  154. package/cap/templates/continue-here.md +78 -0
  155. package/cap/templates/copilot-instructions.md +7 -0
  156. package/cap/templates/debug-subagent-prompt.md +91 -0
  157. package/cap/templates/discussion-log.md +63 -0
  158. package/cap/templates/milestone-archive.md +123 -0
  159. package/cap/templates/milestone.md +115 -0
  160. package/cap/templates/phase-prompt.md +610 -0
  161. package/cap/templates/planner-subagent-prompt.md +117 -0
  162. package/cap/templates/project.md +186 -0
  163. package/cap/templates/requirements.md +231 -0
  164. package/cap/templates/research-project/ARCHITECTURE.md +204 -0
  165. package/cap/templates/research-project/FEATURES.md +147 -0
  166. package/cap/templates/research-project/PITFALLS.md +200 -0
  167. package/cap/templates/research-project/STACK.md +120 -0
  168. package/cap/templates/research-project/SUMMARY.md +170 -0
  169. package/cap/templates/research.md +552 -0
  170. package/cap/templates/roadmap.md +202 -0
  171. package/cap/templates/state.md +176 -0
  172. package/cap/templates/summary.md +364 -0
  173. package/cap/templates/user-preferences.md +498 -0
  174. package/cap/templates/verification-report.md +322 -0
  175. package/cap/workflows/add-phase.md +112 -0
  176. package/cap/workflows/add-tests.md +351 -0
  177. package/cap/workflows/add-todo.md +158 -0
  178. package/cap/workflows/audit-milestone.md +340 -0
  179. package/cap/workflows/audit-uat.md +109 -0
  180. package/cap/workflows/autonomous.md +891 -0
  181. package/cap/workflows/check-todos.md +177 -0
  182. package/cap/workflows/cleanup.md +152 -0
  183. package/cap/workflows/complete-milestone.md +767 -0
  184. package/cap/workflows/diagnose-issues.md +231 -0
  185. package/cap/workflows/discovery-phase.md +289 -0
  186. package/cap/workflows/discuss-phase-assumptions.md +653 -0
  187. package/cap/workflows/discuss-phase.md +1049 -0
  188. package/cap/workflows/do.md +104 -0
  189. package/cap/workflows/execute-phase.md +846 -0
  190. package/cap/workflows/execute-plan.md +514 -0
  191. package/cap/workflows/fast.md +105 -0
  192. package/cap/workflows/forensics.md +265 -0
  193. package/cap/workflows/health.md +181 -0
  194. package/cap/workflows/help.md +660 -0
  195. package/cap/workflows/insert-phase.md +130 -0
  196. package/cap/workflows/list-phase-assumptions.md +178 -0
  197. package/cap/workflows/list-workspaces.md +56 -0
  198. package/cap/workflows/manager.md +362 -0
  199. package/cap/workflows/map-codebase.md +377 -0
  200. package/cap/workflows/milestone-summary.md +223 -0
  201. package/cap/workflows/new-milestone.md +486 -0
  202. package/cap/workflows/new-project.md +1250 -0
  203. package/cap/workflows/new-workspace.md +237 -0
  204. package/cap/workflows/next.md +97 -0
  205. package/cap/workflows/node-repair.md +92 -0
  206. package/cap/workflows/note.md +156 -0
  207. package/cap/workflows/pause-work.md +176 -0
  208. package/cap/workflows/plan-milestone-gaps.md +273 -0
  209. package/cap/workflows/plan-phase.md +857 -0
  210. package/cap/workflows/plant-seed.md +169 -0
  211. package/cap/workflows/pr-branch.md +129 -0
  212. package/cap/workflows/profile-user.md +449 -0
  213. package/cap/workflows/progress.md +507 -0
  214. package/cap/workflows/quick.md +757 -0
  215. package/cap/workflows/remove-phase.md +155 -0
  216. package/cap/workflows/remove-workspace.md +90 -0
  217. package/cap/workflows/research-phase.md +82 -0
  218. package/cap/workflows/resume-project.md +326 -0
  219. package/cap/workflows/review.md +228 -0
  220. package/cap/workflows/session-report.md +146 -0
  221. package/cap/workflows/settings.md +283 -0
  222. package/cap/workflows/ship.md +228 -0
  223. package/cap/workflows/stats.md +60 -0
  224. package/cap/workflows/transition.md +671 -0
  225. package/cap/workflows/ui-phase.md +298 -0
  226. package/cap/workflows/ui-review.md +161 -0
  227. package/cap/workflows/update.md +323 -0
  228. package/cap/workflows/validate-phase.md +170 -0
  229. package/cap/workflows/verify-phase.md +254 -0
  230. package/cap/workflows/verify-work.md +637 -0
  231. package/commands/cap/annotate.md +165 -0
  232. package/commands/cap/brainstorm.md +393 -0
  233. package/commands/cap/checkpoint.md +106 -0
  234. package/commands/cap/completeness.md +94 -0
  235. package/commands/cap/continue.md +72 -0
  236. package/commands/cap/debug.md +588 -0
  237. package/commands/cap/deps.md +169 -0
  238. package/commands/cap/design.md +479 -0
  239. package/commands/cap/init.md +354 -0
  240. package/commands/cap/iterate.md +249 -0
  241. package/commands/cap/learn.md +459 -0
  242. package/commands/cap/memory.md +275 -0
  243. package/commands/cap/migrate-feature-map.md +91 -0
  244. package/commands/cap/migrate-memory.md +108 -0
  245. package/commands/cap/migrate-tags.md +91 -0
  246. package/commands/cap/migrate.md +131 -0
  247. package/commands/cap/prototype.md +510 -0
  248. package/commands/cap/reconcile.md +121 -0
  249. package/commands/cap/review.md +360 -0
  250. package/commands/cap/save.md +72 -0
  251. package/commands/cap/scan.md +404 -0
  252. package/commands/cap/start.md +356 -0
  253. package/commands/cap/status.md +118 -0
  254. package/commands/cap/test-audit.md +262 -0
  255. package/commands/cap/test.md +394 -0
  256. package/commands/cap/trace.md +133 -0
  257. package/commands/cap/ui.md +167 -0
  258. package/hooks/dist/cap-check-update.js +115 -0
  259. package/hooks/dist/cap-context-monitor.js +185 -0
  260. package/hooks/dist/cap-learn-review-hook.js +114 -0
  261. package/hooks/dist/cap-learning-hook.js +192 -0
  262. package/hooks/dist/cap-memory.js +299 -0
  263. package/hooks/dist/cap-prompt-guard.js +97 -0
  264. package/hooks/dist/cap-statusline.js +157 -0
  265. package/hooks/dist/cap-tag-observer.js +115 -0
  266. package/hooks/dist/cap-version-check.js +112 -0
  267. package/hooks/dist/cap-workflow-guard.js +175 -0
  268. package/hooks/hooks.json +55 -0
  269. package/package.json +58 -0
  270. package/scripts/base64-scan.sh +262 -0
  271. package/scripts/build-hooks.js +93 -0
  272. package/scripts/cap-removal-checklist.md +202 -0
  273. package/scripts/prompt-injection-scan.sh +199 -0
  274. package/scripts/run-tests.cjs +181 -0
  275. package/scripts/secret-scan.sh +227 -0
@@ -0,0 +1,69 @@
1
+ // @cap-feature(feature:F-011) Legacy GSD Modules — model profile mapping (quality/balanced/budget per agent)
2
+ /**
3
+ * Mapping of GSD agent to model for each profile.
4
+ *
5
+ * Should be in sync with the profiles table in `cap/references/model-profiles.md`. But
6
+ * possibly worth making this the single source of truth at some point, and removing the markdown
7
+ * reference table in favor of programmatically determining the model to use for an agent (which
8
+ * would be faster, use fewer tokens, and be less error-prone).
9
+ */
10
+ const MODEL_PROFILES = {
11
+ 'gsd-planner': { quality: 'opus', balanced: 'opus', budget: 'sonnet' },
12
+ 'gsd-roadmapper': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
13
+ 'gsd-executor': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
14
+ 'gsd-phase-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
15
+ 'gsd-project-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
16
+ 'gsd-research-synthesizer': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
17
+ 'gsd-debugger': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
18
+ 'gsd-codebase-mapper': { quality: 'sonnet', balanced: 'haiku', budget: 'haiku' },
19
+ 'gsd-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
20
+ 'gsd-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
21
+ 'gsd-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
22
+ 'gsd-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
23
+ 'gsd-ui-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
24
+ 'gsd-ui-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
25
+ 'gsd-ui-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
26
+ };
27
+ const VALID_PROFILES = Object.keys(MODEL_PROFILES['gsd-planner']);
28
+
29
+ /**
30
+ * Formats the agent-to-model mapping as a human-readable table (in string format).
31
+ *
32
+ * @param {Object<string, string>} agentToModelMap - A mapping from agent to model
33
+ * @returns {string} A formatted table string
34
+ */
35
+ function formatAgentToModelMapAsTable(agentToModelMap) {
36
+ const agentWidth = Math.max('Agent'.length, ...Object.keys(agentToModelMap).map((a) => a.length));
37
+ const modelWidth = Math.max(
38
+ 'Model'.length,
39
+ ...Object.values(agentToModelMap).map((m) => m.length)
40
+ );
41
+ const sep = '─'.repeat(agentWidth + 2) + '┼' + '─'.repeat(modelWidth + 2);
42
+ const header = ' ' + 'Agent'.padEnd(agentWidth) + ' │ ' + 'Model'.padEnd(modelWidth);
43
+ let agentToModelTable = header + '\n' + sep + '\n';
44
+ for (const [agent, model] of Object.entries(agentToModelMap)) {
45
+ agentToModelTable += ' ' + agent.padEnd(agentWidth) + ' │ ' + model.padEnd(modelWidth) + '\n';
46
+ }
47
+ return agentToModelTable;
48
+ }
49
+
50
+ /**
51
+ * Returns a mapping from agent to model for the given model profile.
52
+ *
53
+ * @param {string} normalizedProfile - The normalized (lowercase and trimmed) profile name
54
+ * @returns {Object<string, string>} A mapping from agent to model for the given profile
55
+ */
56
+ function getAgentToModelMapForProfile(normalizedProfile) {
57
+ const agentToModelMap = {};
58
+ for (const [agent, profileToModelMap] of Object.entries(MODEL_PROFILES)) {
59
+ agentToModelMap[agent] = profileToModelMap[normalizedProfile];
60
+ }
61
+ return agentToModelMap;
62
+ }
63
+
64
+ module.exports = {
65
+ MODEL_PROFILES,
66
+ VALID_PROFILES,
67
+ formatAgentToModelMapAsTable,
68
+ getAgentToModelMapForProfile,
69
+ };
@@ -0,0 +1,226 @@
1
+ // @cap-context Monorepo context resolver -- assembles per-app planning paths and agent context for scoped operations
2
+ // @cap-decision Separate module from workspace-detector to keep detection (read-only) separate from planning structure (write operations)
3
+ // @cap-constraint Zero external dependencies -- uses only Node.js built-ins (fs, path)
4
+ // @cap-ref(ref:AC-3) Each scoped app gets its own .planning/ directory with independent CODE-INVENTORY.md, PRD.md, and FEATURES.md
5
+ // @cap-ref(ref:AC-7) Root .planning/ holds global decisions; app .planning/ holds app-specific work
6
+ // @cap-pattern Two-level planning: root .planning/ for global context, app-path/.planning/ for scoped work
7
+
8
+ 'use strict';
9
+
10
+ // @cap-feature(feature:F-012) Monorepo Support — per-app planning context resolution
11
+
12
+ const fs = require('node:fs');
13
+ const path = require('node:path');
14
+
15
+ // @cap-api resolveAppPlanningDir(rootPath, appRelativePath) -- returns absolute path to app-scoped .planning/ directory
16
+
17
+ /**
18
+ * @typedef {Object} MonorepoContext
19
+ * @property {string} rootPlanningDir - Absolute path to root .planning/
20
+ * @property {string} appPlanningDir - Absolute path to app-scoped .planning/
21
+ * @property {string} appRoot - Absolute path to the scoped app directory
22
+ * @property {string} appName - Name of the scoped app
23
+ * @property {string[]} manifestPaths - Paths to relevant package manifests for this app
24
+ * @property {Object} globalContext - Parsed global planning docs (lightweight refs)
25
+ */
26
+
27
+ /**
28
+ * Resolve the .planning/ directory for an app-scoped operation.
29
+ *
30
+ * @param {string} rootPath - Monorepo root
31
+ * @param {string} appRelativePath - Relative path to the app (e.g., 'apps/dashboard')
32
+ * @returns {string} Absolute path to app .planning/ directory
33
+ */
34
+ function resolveAppPlanningDir(rootPath, appRelativePath) {
35
+ return path.join(rootPath, appRelativePath, '.planning');
36
+ }
37
+
38
+ /**
39
+ * Initialize the per-app .planning/ directory structure.
40
+ * Creates the directory and placeholder files mirroring root .planning/.
41
+ *
42
+ * @param {string} rootPath - Monorepo root
43
+ * @param {string} appRelativePath - Relative path to the app
44
+ * @param {Object} [options]
45
+ * @param {string} [options.appName] - Display name for headers
46
+ * @returns {string} Path to created .planning/ directory
47
+ */
48
+ function initAppPlanning(rootPath, appRelativePath, options) {
49
+ options = options || {};
50
+ const appPlanningDir = resolveAppPlanningDir(rootPath, appRelativePath);
51
+ const appName = options.appName || path.basename(appRelativePath);
52
+
53
+ fs.mkdirSync(appPlanningDir, { recursive: true });
54
+ fs.mkdirSync(path.join(appPlanningDir, 'prototype'), { recursive: true });
55
+
56
+ // @cap-decision Create stub PRD.md and FEATURES.md in app .planning/ -- agents expect these files to exist
57
+ const prdPath = path.join(appPlanningDir, 'PRD.md');
58
+ if (!fs.existsSync(prdPath)) {
59
+ fs.writeFileSync(prdPath, `# ${appName} -- PRD\n\nApp-scoped PRD. Generated by monorepo-init.\n`, 'utf-8');
60
+ }
61
+
62
+ const featuresPath = path.join(appPlanningDir, 'FEATURES.md');
63
+ if (!fs.existsSync(featuresPath)) {
64
+ fs.writeFileSync(featuresPath, `# ${appName} -- Feature Map\n\nAuto-generated. Run extract-plan --app ${appRelativePath} to populate.\n`, 'utf-8');
65
+ }
66
+
67
+ // Create prototype/CODE-INVENTORY.md stub
68
+ const codeInventoryPath = path.join(appPlanningDir, 'prototype', 'CODE-INVENTORY.md');
69
+ if (!fs.existsSync(codeInventoryPath)) {
70
+ fs.writeFileSync(codeInventoryPath, `# CODE-INVENTORY.md\n\nRun /gsd:extract-plan --app ${appRelativePath} to populate.\n`, 'utf-8');
71
+ }
72
+
73
+ return appPlanningDir;
74
+ }
75
+
76
+ /**
77
+ * Build the full MonorepoContext for an app-scoped operation.
78
+ * This is the primary function agents consume to get focused context.
79
+ *
80
+ * @param {string} rootPath - Monorepo root
81
+ * @param {string} appRelativePath - Relative path to app
82
+ * @param {Object} [options]
83
+ * @param {string} [options.appName] - App display name
84
+ * @param {string[]} [options.appDependencies] - Package names this app depends on
85
+ * @returns {MonorepoContext}
86
+ */
87
+ // @cap-api buildMonorepoContext(rootPath, appRelativePath, options) -- returns MonorepoContext with local + global planning refs
88
+ function buildMonorepoContext(rootPath, appRelativePath, options) {
89
+ options = options || {};
90
+ const appAbsPath = path.join(rootPath, appRelativePath);
91
+ const appPlanningDir = resolveAppPlanningDir(rootPath, appRelativePath);
92
+ const rootPlanningDir = path.join(rootPath, '.planning');
93
+ const manifestsDir = path.join(rootPlanningDir, 'manifests');
94
+
95
+ const manifestPaths = resolveRelevantManifests(manifestsDir, appAbsPath, options.appDependencies || []);
96
+
97
+ // @cap-decision Load global context lazily -- only read file headers, not full content, to minimize token usage
98
+ const globalContext = loadGlobalContextRefs(rootPlanningDir);
99
+
100
+ return {
101
+ rootPlanningDir,
102
+ appPlanningDir,
103
+ appRoot: appAbsPath,
104
+ appName: options.appName || path.basename(appRelativePath),
105
+ manifestPaths,
106
+ globalContext,
107
+ };
108
+ }
109
+
110
+ /**
111
+ * Find package manifests relevant to a specific app based on its dependencies.
112
+ *
113
+ * @param {string} manifestsDir - Path to .planning/manifests/
114
+ * @param {string} appAbsPath - Absolute path to the app
115
+ * @param {string[]} knownDeps - Package names from workspace detection
116
+ * @returns {string[]} Paths to relevant manifest .md files
117
+ */
118
+ function resolveRelevantManifests(manifestsDir, appAbsPath, knownDeps) {
119
+ // @cap-risk If app package.json is missing or malformed, no manifests are resolved -- agent gets no package context
120
+ const manifestPaths = [];
121
+
122
+ if (!fs.existsSync(manifestsDir)) return manifestPaths;
123
+
124
+ // Read app's package.json for its dependencies
125
+ const appPkgPath = path.join(appAbsPath, 'package.json');
126
+ let appDeps = [...knownDeps];
127
+
128
+ try {
129
+ const appPkg = JSON.parse(fs.readFileSync(appPkgPath, 'utf-8'));
130
+ const allDeps = { ...(appPkg.dependencies || {}), ...(appPkg.devDependencies || {}) };
131
+ for (const [name, version] of Object.entries(allDeps)) {
132
+ if (typeof version === 'string' && version.startsWith('workspace:')) {
133
+ if (!appDeps.includes(name)) appDeps.push(name);
134
+ }
135
+ }
136
+ } catch {
137
+ // No package.json or malformed -- use knownDeps only
138
+ }
139
+
140
+ // Match dependency names to manifest files
141
+ try {
142
+ const manifestFiles = fs.readdirSync(manifestsDir).filter(f => f.endsWith('.md'));
143
+ for (const file of manifestFiles) {
144
+ const baseName = file.replace('.md', '').replace(/__/g, '/');
145
+ // Check if any app dependency matches this manifest (with or without @ prefix)
146
+ const matches = appDeps.some(dep => {
147
+ const depNorm = dep.replace(/^@/, '');
148
+ return baseName === depNorm || baseName === dep;
149
+ });
150
+ if (matches) {
151
+ manifestPaths.push(path.join(manifestsDir, file));
152
+ }
153
+ }
154
+ } catch {
155
+ // manifestsDir not readable
156
+ }
157
+
158
+ return manifestPaths;
159
+ }
160
+
161
+ /**
162
+ * Load lightweight references from global .planning/ docs.
163
+ * Reads only headers and first paragraphs to minimize context size.
164
+ *
165
+ * @param {string} rootPlanningDir - Path to root .planning/
166
+ * @returns {Object} Global context references
167
+ */
168
+ function loadGlobalContextRefs(rootPlanningDir) {
169
+ const refs = {
170
+ hasProject: false,
171
+ hasRoadmap: false,
172
+ hasRequirements: false,
173
+ projectSummary: null,
174
+ };
175
+
176
+ const projectPath = path.join(rootPlanningDir, 'PROJECT.md');
177
+ if (fs.existsSync(projectPath)) {
178
+ refs.hasProject = true;
179
+ try {
180
+ const content = fs.readFileSync(projectPath, 'utf-8');
181
+ // Extract first 5 lines as summary
182
+ refs.projectSummary = content.split('\n').slice(0, 5).join('\n');
183
+ } catch {
184
+ // Ignore
185
+ }
186
+ }
187
+
188
+ refs.hasRoadmap = fs.existsSync(path.join(rootPlanningDir, 'ROADMAP.md'));
189
+ refs.hasRequirements = fs.existsSync(path.join(rootPlanningDir, 'REQUIREMENTS.md'));
190
+
191
+ return refs;
192
+ }
193
+
194
+ /**
195
+ * Modify extract-tags scan path to scope to an app directory.
196
+ * Used by the --app flag in cap-tools.cjs extract-tags case.
197
+ *
198
+ * @param {string} rootPath - Monorepo root
199
+ * @param {string} appRelativePath - App-scoped path
200
+ * @param {Object} originalOpts - Original extract-tags options
201
+ * @returns {Object} Modified options with scoped targetPath and outputFile
202
+ */
203
+ // @cap-api scopeExtractTags(rootPath, appRelativePath, originalOpts) -- returns modified options for app-scoped tag extraction
204
+ function scopeExtractTags(rootPath, appRelativePath, originalOpts) {
205
+ const appAbsPath = path.join(rootPath, appRelativePath);
206
+ const appPlanningDir = resolveAppPlanningDir(rootPath, appRelativePath);
207
+
208
+ return {
209
+ ...originalOpts,
210
+ // Override target path to scan only the app directory
211
+ targetPath: appAbsPath,
212
+ // Write output to app-scoped .planning/prototype/
213
+ outputFile: originalOpts.outputFile
214
+ ? path.join(appPlanningDir, 'prototype', path.basename(originalOpts.outputFile))
215
+ : originalOpts.outputFile,
216
+ };
217
+ }
218
+
219
+ module.exports = {
220
+ resolveAppPlanningDir,
221
+ initAppPlanning,
222
+ buildMonorepoContext,
223
+ resolveRelevantManifests,
224
+ loadGlobalContextRefs,
225
+ scopeExtractTags,
226
+ };