scm-method 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/.claude-plugin/marketplace.json +77 -0
  2. package/AGENTS.md +12 -0
  3. package/LICENSE +30 -0
  4. package/README.md +109 -0
  5. package/README_CN.md +108 -0
  6. package/package.json +110 -0
  7. package/src/bmm-skills/1-analysis/research/scm-domain-research/SKILL.md +6 -0
  8. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-01-init.md +137 -0
  9. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-02-domain-analysis.md +229 -0
  10. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-03-competitive-landscape.md +238 -0
  11. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-04-regulatory-focus.md +206 -0
  12. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-05-technical-trends.md +234 -0
  13. package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-06-research-synthesis.md +444 -0
  14. package/src/bmm-skills/1-analysis/research/scm-domain-research/research.template.md +29 -0
  15. package/src/bmm-skills/1-analysis/research/scm-domain-research/workflow.md +51 -0
  16. package/src/bmm-skills/1-analysis/research/scm-market-research/SKILL.md +6 -0
  17. package/src/bmm-skills/1-analysis/research/scm-market-research/research.template.md +29 -0
  18. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-01-init.md +184 -0
  19. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-02-customer-behavior.md +239 -0
  20. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-03-customer-pain-points.md +251 -0
  21. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-04-customer-decisions.md +261 -0
  22. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-05-competitive-analysis.md +173 -0
  23. package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-06-research-completion.md +478 -0
  24. package/src/bmm-skills/1-analysis/research/scm-market-research/workflow.md +51 -0
  25. package/src/bmm-skills/1-analysis/research/scm-technical-research/SKILL.md +6 -0
  26. package/src/bmm-skills/1-analysis/research/scm-technical-research/research.template.md +29 -0
  27. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-01-init.md +137 -0
  28. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-02-technical-overview.md +239 -0
  29. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-03-integration-patterns.md +248 -0
  30. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-04-architectural-patterns.md +202 -0
  31. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-05-implementation-research.md +233 -0
  32. package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-06-research-synthesis.md +487 -0
  33. package/src/bmm-skills/1-analysis/research/scm-technical-research/workflow.md +52 -0
  34. package/src/bmm-skills/1-analysis/scm-agent-analyst/SKILL.md +59 -0
  35. package/src/bmm-skills/1-analysis/scm-agent-analyst/scm-skill-manifest.yaml +11 -0
  36. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/SKILL.md +57 -0
  37. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/explain-concept.md +20 -0
  38. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/mermaid-gen.md +20 -0
  39. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/scm-skill-manifest.yaml +11 -0
  40. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/validate-doc.md +19 -0
  41. package/src/bmm-skills/1-analysis/scm-agent-tech-writer/write-document.md +20 -0
  42. package/src/bmm-skills/1-analysis/scm-document-project/SKILL.md +6 -0
  43. package/src/bmm-skills/1-analysis/scm-document-project/checklist.md +245 -0
  44. package/src/bmm-skills/1-analysis/scm-document-project/documentation-requirements.csv +12 -0
  45. package/src/bmm-skills/1-analysis/scm-document-project/instructions.md +128 -0
  46. package/src/bmm-skills/1-analysis/scm-document-project/templates/deep-dive-template.md +345 -0
  47. package/src/bmm-skills/1-analysis/scm-document-project/templates/index-template.md +169 -0
  48. package/src/bmm-skills/1-analysis/scm-document-project/templates/project-overview-template.md +103 -0
  49. package/src/bmm-skills/1-analysis/scm-document-project/templates/project-scan-report-schema.json +160 -0
  50. package/src/bmm-skills/1-analysis/scm-document-project/templates/source-tree-template.md +135 -0
  51. package/src/bmm-skills/1-analysis/scm-document-project/workflow.md +25 -0
  52. package/src/bmm-skills/1-analysis/scm-document-project/workflows/deep-dive-instructions.md +299 -0
  53. package/src/bmm-skills/1-analysis/scm-document-project/workflows/deep-dive-workflow.md +34 -0
  54. package/src/bmm-skills/1-analysis/scm-document-project/workflows/full-scan-instructions.md +1107 -0
  55. package/src/bmm-skills/1-analysis/scm-document-project/workflows/full-scan-workflow.md +34 -0
  56. package/src/bmm-skills/1-analysis/scm-prfaq/SKILL.md +96 -0
  57. package/src/bmm-skills/1-analysis/scm-prfaq/agents/artifact-analyzer.md +60 -0
  58. package/src/bmm-skills/1-analysis/scm-prfaq/agents/web-researcher.md +49 -0
  59. package/src/bmm-skills/1-analysis/scm-prfaq/assets/prfaq-template.md +62 -0
  60. package/src/bmm-skills/1-analysis/scm-prfaq/references/customer-faq.md +55 -0
  61. package/src/bmm-skills/1-analysis/scm-prfaq/references/internal-faq.md +51 -0
  62. package/src/bmm-skills/1-analysis/scm-prfaq/references/press-release.md +60 -0
  63. package/src/bmm-skills/1-analysis/scm-prfaq/references/verdict.md +79 -0
  64. package/src/bmm-skills/1-analysis/scm-prfaq/scm-manifest.json +16 -0
  65. package/src/bmm-skills/1-analysis/scm-product-brief/SKILL.md +82 -0
  66. package/src/bmm-skills/1-analysis/scm-product-brief/agents/artifact-analyzer.md +60 -0
  67. package/src/bmm-skills/1-analysis/scm-product-brief/agents/opportunity-reviewer.md +44 -0
  68. package/src/bmm-skills/1-analysis/scm-product-brief/agents/skeptic-reviewer.md +44 -0
  69. package/src/bmm-skills/1-analysis/scm-product-brief/agents/web-researcher.md +49 -0
  70. package/src/bmm-skills/1-analysis/scm-product-brief/prompts/contextual-discovery.md +57 -0
  71. package/src/bmm-skills/1-analysis/scm-product-brief/prompts/draft-and-review.md +86 -0
  72. package/src/bmm-skills/1-analysis/scm-product-brief/prompts/finalize.md +75 -0
  73. package/src/bmm-skills/1-analysis/scm-product-brief/prompts/guided-elicitation.md +70 -0
  74. package/src/bmm-skills/1-analysis/scm-product-brief/resources/brief-template.md +60 -0
  75. package/src/bmm-skills/1-analysis/scm-product-brief/scm-manifest.json +17 -0
  76. package/src/bmm-skills/2-plan-workflows/scm-agent-pm/SKILL.md +59 -0
  77. package/src/bmm-skills/2-plan-workflows/scm-agent-pm/scm-skill-manifest.yaml +11 -0
  78. package/src/bmm-skills/2-plan-workflows/scm-agent-ux-designer/SKILL.md +55 -0
  79. package/src/bmm-skills/2-plan-workflows/scm-agent-ux-designer/scm-skill-manifest.yaml +11 -0
  80. package/src/bmm-skills/2-plan-workflows/scm-create-prd/SKILL.md +6 -0
  81. package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/domain-complexity.csv +15 -0
  82. package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/prd-purpose.md +197 -0
  83. package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/project-types.csv +11 -0
  84. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-01-init.md +178 -0
  85. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-01b-continue.md +161 -0
  86. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02-discovery.md +208 -0
  87. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02b-vision.md +142 -0
  88. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02c-executive-summary.md +158 -0
  89. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-03-success.md +214 -0
  90. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-04-journeys.md +201 -0
  91. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-05-domain.md +194 -0
  92. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-06-innovation.md +211 -0
  93. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-07-project-type.md +222 -0
  94. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-08-scoping.md +216 -0
  95. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-09-functional.md +219 -0
  96. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-10-nonfunctional.md +230 -0
  97. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-11-polish.md +221 -0
  98. package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-12-complete.md +115 -0
  99. package/src/bmm-skills/2-plan-workflows/scm-create-prd/templates/prd-template.md +10 -0
  100. package/src/bmm-skills/2-plan-workflows/scm-create-prd/workflow.md +61 -0
  101. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/SKILL.md +6 -0
  102. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-01-init.md +135 -0
  103. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-01b-continue.md +127 -0
  104. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-02-discovery.md +190 -0
  105. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-03-core-experience.md +217 -0
  106. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-04-emotional-response.md +220 -0
  107. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-05-inspiration.md +235 -0
  108. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-06-design-system.md +253 -0
  109. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-07-defining-experience.md +255 -0
  110. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-08-visual-foundation.md +225 -0
  111. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-09-design-directions.md +225 -0
  112. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-10-user-journeys.md +242 -0
  113. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-11-component-strategy.md +249 -0
  114. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-12-ux-patterns.md +238 -0
  115. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-13-responsive-accessibility.md +265 -0
  116. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-14-complete.md +171 -0
  117. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/ux-design-template.md +13 -0
  118. package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/workflow.md +35 -0
  119. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/SKILL.md +6 -0
  120. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-01-discovery.md +242 -0
  121. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-01b-legacy-conversion.md +204 -0
  122. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-02-review.md +245 -0
  123. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-03-edit.md +250 -0
  124. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-04-complete.md +165 -0
  125. package/src/bmm-skills/2-plan-workflows/scm-edit-prd/workflow.md +62 -0
  126. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/SKILL.md +6 -0
  127. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/domain-complexity.csv +15 -0
  128. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/prd-purpose.md +197 -0
  129. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/project-types.csv +11 -0
  130. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-01-discovery.md +221 -0
  131. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-02-format-detection.md +188 -0
  132. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-02b-parity-check.md +206 -0
  133. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-03-density-validation.md +171 -0
  134. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-04-brief-coverage-validation.md +211 -0
  135. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-05-measurability-validation.md +225 -0
  136. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-06-traceability-validation.md +214 -0
  137. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-07-implementation-leakage-validation.md +202 -0
  138. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-08-domain-compliance-validation.md +240 -0
  139. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-09-project-type-validation.md +260 -0
  140. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-10-smart-validation.md +206 -0
  141. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-11-holistic-quality-validation.md +261 -0
  142. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-12-completeness-validation.md +239 -0
  143. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-13-report-complete.md +229 -0
  144. package/src/bmm-skills/2-plan-workflows/scm-validate-prd/workflow.md +61 -0
  145. package/src/bmm-skills/3-solutioning/scm-agent-architect/SKILL.md +54 -0
  146. package/src/bmm-skills/3-solutioning/scm-agent-architect/scm-skill-manifest.yaml +11 -0
  147. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/SKILL.md +6 -0
  148. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-01-document-discovery.md +179 -0
  149. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-02-prd-analysis.md +168 -0
  150. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +169 -0
  151. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-04-ux-alignment.md +129 -0
  152. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-05-epic-quality-review.md +241 -0
  153. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-06-final-assessment.md +126 -0
  154. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/templates/readiness-report-template.md +4 -0
  155. package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/workflow.md +47 -0
  156. package/src/bmm-skills/3-solutioning/scm-create-architecture/SKILL.md +6 -0
  157. package/src/bmm-skills/3-solutioning/scm-create-architecture/architecture-decision-template.md +12 -0
  158. package/src/bmm-skills/3-solutioning/scm-create-architecture/data/domain-complexity.csv +13 -0
  159. package/src/bmm-skills/3-solutioning/scm-create-architecture/data/project-types.csv +7 -0
  160. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-01-init.md +153 -0
  161. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-01b-continue.md +173 -0
  162. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-02-context.md +224 -0
  163. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-03-starter.md +329 -0
  164. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-04-decisions.md +318 -0
  165. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-05-patterns.md +359 -0
  166. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-06-structure.md +379 -0
  167. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-07-validation.md +359 -0
  168. package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-08-complete.md +76 -0
  169. package/src/bmm-skills/3-solutioning/scm-create-architecture/workflow.md +32 -0
  170. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/SKILL.md +6 -0
  171. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-01-validate-prerequisites.md +255 -0
  172. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-02-design-epics.md +212 -0
  173. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
  174. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-04-final-validation.md +131 -0
  175. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/templates/epics-template.md +61 -0
  176. package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/workflow.md +51 -0
  177. package/src/bmm-skills/3-solutioning/scm-generate-project-context/SKILL.md +6 -0
  178. package/src/bmm-skills/3-solutioning/scm-generate-project-context/project-context-template.md +21 -0
  179. package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-01-discover.md +186 -0
  180. package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-02-generate.md +321 -0
  181. package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-03-complete.md +278 -0
  182. package/src/bmm-skills/3-solutioning/scm-generate-project-context/workflow.md +39 -0
  183. package/src/bmm-skills/4-implementation/scm-agent-dev/SKILL.md +64 -0
  184. package/src/bmm-skills/4-implementation/scm-agent-dev/scm-skill-manifest.yaml +11 -0
  185. package/src/bmm-skills/4-implementation/scm-agent-qa/SKILL.md +61 -0
  186. package/src/bmm-skills/4-implementation/scm-agent-qa/scm-skill-manifest.yaml +11 -0
  187. package/src/bmm-skills/4-implementation/scm-agent-quick-flow-solo-dev/SKILL.md +53 -0
  188. package/src/bmm-skills/4-implementation/scm-agent-quick-flow-solo-dev/scm-skill-manifest.yaml +11 -0
  189. package/src/bmm-skills/4-implementation/scm-agent-sm/SKILL.md +55 -0
  190. package/src/bmm-skills/4-implementation/scm-agent-sm/scm-skill-manifest.yaml +11 -0
  191. package/src/bmm-skills/4-implementation/scm-code-review/SKILL.md +6 -0
  192. package/src/bmm-skills/4-implementation/scm-code-review/steps/step-01-gather-context.md +62 -0
  193. package/src/bmm-skills/4-implementation/scm-code-review/steps/step-02-review.md +34 -0
  194. package/src/bmm-skills/4-implementation/scm-code-review/steps/step-03-triage.md +49 -0
  195. package/src/bmm-skills/4-implementation/scm-code-review/steps/step-04-present.md +129 -0
  196. package/src/bmm-skills/4-implementation/scm-code-review/workflow.md +55 -0
  197. package/src/bmm-skills/4-implementation/scm-correct-course/SKILL.md +6 -0
  198. package/src/bmm-skills/4-implementation/scm-correct-course/checklist.md +288 -0
  199. package/src/bmm-skills/4-implementation/scm-correct-course/workflow.md +267 -0
  200. package/src/bmm-skills/4-implementation/scm-create-story/SKILL.md +6 -0
  201. package/src/bmm-skills/4-implementation/scm-create-story/checklist.md +357 -0
  202. package/src/bmm-skills/4-implementation/scm-create-story/discover-inputs.md +88 -0
  203. package/src/bmm-skills/4-implementation/scm-create-story/template.md +49 -0
  204. package/src/bmm-skills/4-implementation/scm-create-story/workflow.md +380 -0
  205. package/src/bmm-skills/4-implementation/scm-dev-story/SKILL.md +6 -0
  206. package/src/bmm-skills/4-implementation/scm-dev-story/checklist.md +80 -0
  207. package/src/bmm-skills/4-implementation/scm-dev-story/workflow.md +450 -0
  208. package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/SKILL.md +6 -0
  209. package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/checklist.md +33 -0
  210. package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/workflow.md +136 -0
  211. package/src/bmm-skills/4-implementation/scm-quick-dev/SKILL.md +6 -0
  212. package/src/bmm-skills/4-implementation/scm-quick-dev/spec-template.md +88 -0
  213. package/src/bmm-skills/4-implementation/scm-quick-dev/step-01-clarify-and-route.md +66 -0
  214. package/src/bmm-skills/4-implementation/scm-quick-dev/step-02-plan.md +35 -0
  215. package/src/bmm-skills/4-implementation/scm-quick-dev/step-03-implement.md +37 -0
  216. package/src/bmm-skills/4-implementation/scm-quick-dev/step-04-review.md +49 -0
  217. package/src/bmm-skills/4-implementation/scm-quick-dev/step-05-present.md +63 -0
  218. package/src/bmm-skills/4-implementation/scm-quick-dev/step-oneshot.md +62 -0
  219. package/src/bmm-skills/4-implementation/scm-quick-dev/workflow.md +79 -0
  220. package/src/bmm-skills/4-implementation/scm-retrospective/SKILL.md +6 -0
  221. package/src/bmm-skills/4-implementation/scm-retrospective/workflow.md +1479 -0
  222. package/src/bmm-skills/4-implementation/scm-sprint-planning/SKILL.md +6 -0
  223. package/src/bmm-skills/4-implementation/scm-sprint-planning/checklist.md +33 -0
  224. package/src/bmm-skills/4-implementation/scm-sprint-planning/sprint-status-template.yaml +56 -0
  225. package/src/bmm-skills/4-implementation/scm-sprint-planning/workflow.md +263 -0
  226. package/src/bmm-skills/4-implementation/scm-sprint-status/SKILL.md +6 -0
  227. package/src/bmm-skills/4-implementation/scm-sprint-status/workflow.md +261 -0
  228. package/src/bmm-skills/module-help.csv +31 -0
  229. package/src/bmm-skills/module.yaml +50 -0
  230. package/src/core-skills/module-help.csv +11 -0
  231. package/src/core-skills/module.yaml +25 -0
  232. package/src/core-skills/scm-advanced-elicitation/SKILL.md +136 -0
  233. package/src/core-skills/scm-advanced-elicitation/methods.csv +51 -0
  234. package/src/core-skills/scm-brainstorming/SKILL.md +6 -0
  235. package/src/core-skills/scm-brainstorming/brain-methods.csv +62 -0
  236. package/src/core-skills/scm-brainstorming/steps/step-01-session-setup.md +214 -0
  237. package/src/core-skills/scm-brainstorming/steps/step-01b-continue.md +124 -0
  238. package/src/core-skills/scm-brainstorming/steps/step-02a-user-selected.md +229 -0
  239. package/src/core-skills/scm-brainstorming/steps/step-02b-ai-recommended.md +239 -0
  240. package/src/core-skills/scm-brainstorming/steps/step-02c-random-selection.md +211 -0
  241. package/src/core-skills/scm-brainstorming/steps/step-02d-progressive-flow.md +266 -0
  242. package/src/core-skills/scm-brainstorming/steps/step-03-technique-execution.md +401 -0
  243. package/src/core-skills/scm-brainstorming/steps/step-04-idea-organization.md +305 -0
  244. package/src/core-skills/scm-brainstorming/template.md +15 -0
  245. package/src/core-skills/scm-brainstorming/workflow.md +53 -0
  246. package/src/core-skills/scm-distillator/SKILL.md +177 -0
  247. package/src/core-skills/scm-distillator/agents/distillate-compressor.md +116 -0
  248. package/src/core-skills/scm-distillator/agents/round-trip-reconstructor.md +68 -0
  249. package/src/core-skills/scm-distillator/resources/compression-rules.md +51 -0
  250. package/src/core-skills/scm-distillator/resources/distillate-format-reference.md +227 -0
  251. package/src/core-skills/scm-distillator/resources/splitting-strategy.md +78 -0
  252. package/src/core-skills/scm-distillator/scripts/analyze_sources.py +300 -0
  253. package/src/core-skills/scm-distillator/scripts/tests/test_analyze_sources.py +204 -0
  254. package/src/core-skills/scm-editorial-review-prose/SKILL.md +86 -0
  255. package/src/core-skills/scm-editorial-review-structure/SKILL.md +179 -0
  256. package/src/core-skills/scm-help/SKILL.md +73 -0
  257. package/src/core-skills/scm-index-docs/SKILL.md +66 -0
  258. package/src/core-skills/scm-party-mode/SKILL.md +125 -0
  259. package/src/core-skills/scm-review-adversarial-general/SKILL.md +37 -0
  260. package/src/core-skills/scm-review-edge-case-hunter/SKILL.md +67 -0
  261. package/src/core-skills/scm-shard-doc/SKILL.md +105 -0
  262. package/tools/format-workflow-md.js +263 -0
  263. package/tools/installer/README.md +60 -0
  264. package/tools/installer/cli-utils.js +181 -0
  265. package/tools/installer/commands/install.js +80 -0
  266. package/tools/installer/commands/status.js +65 -0
  267. package/tools/installer/commands/uninstall.js +167 -0
  268. package/tools/installer/core/config.js +52 -0
  269. package/tools/installer/core/custom-module-cache.js +260 -0
  270. package/tools/installer/core/existing-install.js +127 -0
  271. package/tools/installer/core/install-paths.js +129 -0
  272. package/tools/installer/core/installer.js +1790 -0
  273. package/tools/installer/core/manifest-generator.js +701 -0
  274. package/tools/installer/core/manifest.js +1040 -0
  275. package/tools/installer/custom-handler.js +112 -0
  276. package/tools/installer/external-official-modules.yaml +63 -0
  277. package/tools/installer/file-ops.js +204 -0
  278. package/tools/installer/ide/_config-driven.js +536 -0
  279. package/tools/installer/ide/manager.js +247 -0
  280. package/tools/installer/ide/platform-codes.js +37 -0
  281. package/tools/installer/ide/platform-codes.yaml +192 -0
  282. package/tools/installer/ide/shared/agent-command-generator.js +180 -0
  283. package/tools/installer/ide/shared/module-injections.js +136 -0
  284. package/tools/installer/ide/shared/path-utils.js +364 -0
  285. package/tools/installer/ide/shared/scm-artifacts.js +208 -0
  286. package/tools/installer/ide/shared/skill-manifest.js +72 -0
  287. package/tools/installer/ide/templates/agent-command-template.md +14 -0
  288. package/tools/installer/ide/templates/combined/antigravity.md +8 -0
  289. package/tools/installer/ide/templates/combined/default-agent.md +15 -0
  290. package/tools/installer/ide/templates/combined/default-task.md +10 -0
  291. package/tools/installer/ide/templates/combined/default-tool.md +10 -0
  292. package/tools/installer/ide/templates/combined/default-workflow.md +6 -0
  293. package/tools/installer/ide/templates/combined/gemini-agent.toml +14 -0
  294. package/tools/installer/ide/templates/combined/gemini-task.toml +11 -0
  295. package/tools/installer/ide/templates/combined/gemini-tool.toml +11 -0
  296. package/tools/installer/ide/templates/combined/gemini-workflow-yaml.toml +16 -0
  297. package/tools/installer/ide/templates/combined/gemini-workflow.toml +14 -0
  298. package/tools/installer/ide/templates/combined/kiro-agent.md +16 -0
  299. package/tools/installer/ide/templates/combined/kiro-task.md +9 -0
  300. package/tools/installer/ide/templates/combined/kiro-tool.md +9 -0
  301. package/tools/installer/ide/templates/combined/kiro-workflow.md +7 -0
  302. package/tools/installer/ide/templates/combined/opencode-agent.md +15 -0
  303. package/tools/installer/ide/templates/combined/opencode-task.md +13 -0
  304. package/tools/installer/ide/templates/combined/opencode-tool.md +13 -0
  305. package/tools/installer/ide/templates/combined/opencode-workflow-yaml.md +16 -0
  306. package/tools/installer/ide/templates/combined/opencode-workflow.md +16 -0
  307. package/tools/installer/ide/templates/combined/rovodev.md +9 -0
  308. package/tools/installer/ide/templates/combined/trae.md +9 -0
  309. package/tools/installer/ide/templates/combined/windsurf-workflow.md +10 -0
  310. package/tools/installer/ide/templates/split/.gitkeep +0 -0
  311. package/tools/installer/install-messages.yaml +35 -0
  312. package/tools/installer/message-loader.js +83 -0
  313. package/tools/installer/modules/custom-modules.js +197 -0
  314. package/tools/installer/modules/external-manager.js +354 -0
  315. package/tools/installer/modules/official-modules.js +2043 -0
  316. package/tools/installer/project-root.js +77 -0
  317. package/tools/installer/prompts.js +809 -0
  318. package/tools/installer/scm-cli.js +108 -0
  319. package/tools/installer/ui.js +1683 -0
  320. package/tools/installer/yaml-format.js +245 -0
  321. package/tools/javascript-conventions.md +5 -0
  322. package/tools/migrate-custom-module-paths.js +124 -0
  323. package/tools/platform-codes.yaml +169 -0
  324. package/tools/validate-skills.js +736 -0
@@ -0,0 +1,167 @@
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const prompts = require('../prompts');
4
+ const { Installer } = require('../core/installer');
5
+
6
+ const installer = new Installer();
7
+
8
+ module.exports = {
9
+ command: 'uninstall',
10
+ description: 'Remove SCM installation from the current project',
11
+ options: [
12
+ ['-y, --yes', 'Remove all SCM components without prompting (preserves user artifacts)'],
13
+ ['--directory <path>', 'Project directory (default: current directory)'],
14
+ ],
15
+ action: async (options) => {
16
+ try {
17
+ let projectDir;
18
+
19
+ if (options.directory) {
20
+ // Explicit --directory flag takes precedence
21
+ projectDir = path.resolve(options.directory);
22
+ } else if (options.yes) {
23
+ // Non-interactive mode: use current directory
24
+ projectDir = process.cwd();
25
+ } else {
26
+ // Interactive: ask user which directory to uninstall from
27
+ // select() handles cancellation internally (exits process)
28
+ const dirChoice = await prompts.select({
29
+ message: 'Where do you want to uninstall SCM from?',
30
+ choices: [
31
+ { value: 'cwd', name: `Current directory (${process.cwd()})` },
32
+ { value: 'other', name: 'Another directory...' },
33
+ ],
34
+ });
35
+
36
+ if (dirChoice === 'other') {
37
+ // text() handles cancellation internally (exits process)
38
+ const customDir = await prompts.text({
39
+ message: 'Enter the project directory path:',
40
+ placeholder: process.cwd(),
41
+ validate: (value) => {
42
+ if (!value || value.trim().length === 0) return 'Directory path is required';
43
+ },
44
+ });
45
+
46
+ projectDir = path.resolve(customDir.trim());
47
+ } else {
48
+ projectDir = process.cwd();
49
+ }
50
+ }
51
+
52
+ if (!(await fs.pathExists(projectDir))) {
53
+ await prompts.log.error(`Directory does not exist: ${projectDir}`);
54
+ process.exit(1);
55
+ }
56
+
57
+ const { scmDir } = await installer.findBmadDir(projectDir);
58
+
59
+ if (!(await fs.pathExists(scmDir))) {
60
+ await prompts.log.warn('No SCM installation found.');
61
+ process.exit(0);
62
+ }
63
+
64
+ const existingInstall = await installer.getStatus(projectDir);
65
+ const version = existingInstall.installed ? existingInstall.version : 'unknown';
66
+ const modules = existingInstall.moduleIds.join(', ');
67
+ const ides = existingInstall.ides.join(', ');
68
+
69
+ const outputFolder = await installer.getOutputFolder(projectDir);
70
+
71
+ await prompts.intro('SCM Uninstall');
72
+ await prompts.note(`Version: ${version}\nModules: ${modules}\nIDE integrations: ${ides}`, 'Current Installation');
73
+
74
+ let removeModules = true;
75
+ let removeIdeConfigs = true;
76
+ let removeOutputFolder = false;
77
+
78
+ if (!options.yes) {
79
+ // multiselect() handles cancellation internally (exits process)
80
+ const selected = await prompts.multiselect({
81
+ message: 'Select components to remove:',
82
+ options: [
83
+ {
84
+ value: 'modules',
85
+ label: `SCM Modules & data (${installer.scmFolderName}/)`,
86
+ hint: 'Core installation, agents, workflows, config',
87
+ },
88
+ { value: 'ide', label: 'IDE integrations', hint: ides || 'No IDEs configured' },
89
+ { value: 'output', label: `User artifacts (${outputFolder}/)`, hint: 'WARNING: Contains your work products' },
90
+ ],
91
+ initialValues: ['modules', 'ide'],
92
+ required: true,
93
+ });
94
+
95
+ removeModules = selected.includes('modules');
96
+ removeIdeConfigs = selected.includes('ide');
97
+ removeOutputFolder = selected.includes('output');
98
+
99
+ const red = (s) => `\u001B[31m${s}\u001B[0m`;
100
+ await prompts.note(
101
+ red('💀 This action is IRREVERSIBLE! Removed files cannot be recovered!') +
102
+ '\n' +
103
+ red('💀 IDE configurations and modules will need to be reinstalled.') +
104
+ '\n' +
105
+ red('💀 User artifacts are preserved unless explicitly selected.'),
106
+ '!! DESTRUCTIVE ACTION !!',
107
+ );
108
+
109
+ const confirmed = await prompts.confirm({
110
+ message: 'Proceed with uninstall?',
111
+ default: false,
112
+ });
113
+
114
+ if (!confirmed) {
115
+ await prompts.outro('Uninstall cancelled.');
116
+ process.exit(0);
117
+ }
118
+ }
119
+
120
+ // Phase 1: IDE integrations
121
+ if (removeIdeConfigs) {
122
+ const s = await prompts.spinner();
123
+ s.start('Removing IDE integrations...');
124
+ await installer.uninstallIdeConfigs(projectDir, existingInstall, { silent: true });
125
+ s.stop(`Removed IDE integrations (${ides || 'none'})`);
126
+ }
127
+
128
+ // Phase 2: User artifacts
129
+ if (removeOutputFolder) {
130
+ const s = await prompts.spinner();
131
+ s.start(`Removing user artifacts (${outputFolder}/)...`);
132
+ await installer.uninstallOutputFolder(projectDir, outputFolder);
133
+ s.stop('User artifacts removed');
134
+ }
135
+
136
+ // Phase 3: SCM modules & data (last — other phases may need _scm/)
137
+ if (removeModules) {
138
+ const s = await prompts.spinner();
139
+ s.start(`Removing SCM modules & data (${installer.scmFolderName}/)...`);
140
+ await installer.uninstallModules(projectDir);
141
+ s.stop('Modules & data removed');
142
+ }
143
+
144
+ const summary = [];
145
+ if (removeIdeConfigs) summary.push('IDE integrations cleaned');
146
+ if (removeModules) summary.push('Modules & data removed');
147
+ if (removeOutputFolder) summary.push('User artifacts removed');
148
+ if (!removeOutputFolder) summary.push(`User artifacts preserved in ${outputFolder}/`);
149
+
150
+ await prompts.note(summary.join('\n'), 'Summary');
151
+ await prompts.outro('To reinstall, run: npx SCM-method install');
152
+
153
+ process.exit(0);
154
+ } catch (error) {
155
+ try {
156
+ const errorMessage = error instanceof Error ? error.message : String(error);
157
+ await prompts.log.error(`Uninstall failed: ${errorMessage}`);
158
+ if (error instanceof Error && error.stack) {
159
+ await prompts.log.message(error.stack);
160
+ }
161
+ } catch {
162
+ console.error(error instanceof Error ? error.message : error);
163
+ }
164
+ process.exit(1);
165
+ }
166
+ },
167
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Clean install configuration built from user input.
3
+ * User input comes from either UI answers or headless CLI flags.
4
+ */
5
+ class Config {
6
+ constructor({ directory, modules, ides, skipPrompts, verbose, actionType, coreConfig, moduleConfigs, quickUpdate }) {
7
+ this.directory = directory;
8
+ this.modules = Object.freeze([...modules]);
9
+ this.ides = Object.freeze([...ides]);
10
+ this.skipPrompts = skipPrompts;
11
+ this.verbose = verbose;
12
+ this.actionType = actionType;
13
+ this.coreConfig = coreConfig;
14
+ this.moduleConfigs = moduleConfigs;
15
+ this._quickUpdate = quickUpdate;
16
+ Object.freeze(this);
17
+ }
18
+
19
+ /**
20
+ * Build a clean install config from raw user input.
21
+ * @param {Object} userInput - UI answers or CLI flags
22
+ * @returns {Config}
23
+ */
24
+ static build(userInput) {
25
+ const modules = [...(userInput.modules || [])];
26
+ if (userInput.installCore && !modules.includes('core')) {
27
+ modules.unshift('core');
28
+ }
29
+
30
+ return new Config({
31
+ directory: userInput.directory,
32
+ modules,
33
+ ides: userInput.skipIde ? [] : [...(userInput.ides || [])],
34
+ skipPrompts: userInput.skipPrompts || false,
35
+ verbose: userInput.verbose || false,
36
+ actionType: userInput.actionType,
37
+ coreConfig: userInput.coreConfig || {},
38
+ moduleConfigs: userInput.moduleConfigs || null,
39
+ quickUpdate: userInput._quickUpdate || false,
40
+ });
41
+ }
42
+
43
+ hasCoreConfig() {
44
+ return this.coreConfig && Object.keys(this.coreConfig).length > 0;
45
+ }
46
+
47
+ isQuickUpdate() {
48
+ return this._quickUpdate;
49
+ }
50
+ }
51
+
52
+ module.exports = { Config };
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Custom Module Source Cache
3
+ * Caches custom module sources under _config/custom/ to ensure they're never lost
4
+ * and can be checked into source control
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('node:path');
9
+ const crypto = require('node:crypto');
10
+ const prompts = require('../prompts');
11
+
12
+ class CustomModuleCache {
13
+ constructor(scmDir) {
14
+ this.scmDir = scmDir;
15
+ this.customCacheDir = path.join(scmDir, '_config', 'custom');
16
+ this.manifestPath = path.join(this.customCacheDir, 'cache-manifest.yaml');
17
+ }
18
+
19
+ /**
20
+ * Ensure the custom cache directory exists
21
+ */
22
+ async ensureCacheDir() {
23
+ await fs.ensureDir(this.customCacheDir);
24
+ }
25
+
26
+ /**
27
+ * Get cache manifest
28
+ */
29
+ async getCacheManifest() {
30
+ if (!(await fs.pathExists(this.manifestPath))) {
31
+ return {};
32
+ }
33
+
34
+ const content = await fs.readFile(this.manifestPath, 'utf8');
35
+ const yaml = require('yaml');
36
+ return yaml.parse(content) || {};
37
+ }
38
+
39
+ /**
40
+ * Update cache manifest
41
+ */
42
+ async updateCacheManifest(manifest) {
43
+ const yaml = require('yaml');
44
+ // Clean the manifest to remove any non-serializable values
45
+ const cleanManifest = structuredClone(manifest);
46
+
47
+ const content = yaml.stringify(cleanManifest, {
48
+ indent: 2,
49
+ lineWidth: 0,
50
+ sortKeys: false,
51
+ });
52
+
53
+ await fs.writeFile(this.manifestPath, content);
54
+ }
55
+
56
+ /**
57
+ * Stream a file into the hash to avoid loading entire file into memory
58
+ */
59
+ async hashFileStream(filePath, hash) {
60
+ return new Promise((resolve, reject) => {
61
+ const stream = require('node:fs').createReadStream(filePath);
62
+ stream.on('data', (chunk) => hash.update(chunk));
63
+ stream.on('end', resolve);
64
+ stream.on('error', reject);
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Calculate hash of a file or directory using streaming to minimize memory usage
70
+ */
71
+ async calculateHash(sourcePath) {
72
+ const hash = crypto.createHash('sha256');
73
+
74
+ const isDir = (await fs.stat(sourcePath)).isDirectory();
75
+
76
+ if (isDir) {
77
+ // For directories, hash all files
78
+ const files = [];
79
+ async function collectFiles(dir) {
80
+ const entries = await fs.readdir(dir, { withFileTypes: true });
81
+ for (const entry of entries) {
82
+ if (entry.isFile()) {
83
+ files.push(path.join(dir, entry.name));
84
+ } else if (entry.isDirectory() && !entry.name.startsWith('.')) {
85
+ await collectFiles(path.join(dir, entry.name));
86
+ }
87
+ }
88
+ }
89
+
90
+ await collectFiles(sourcePath);
91
+ files.sort(); // Ensure consistent order
92
+
93
+ for (const file of files) {
94
+ const relativePath = path.relative(sourcePath, file);
95
+ // Hash the path first, then stream file contents
96
+ hash.update(relativePath + '|');
97
+ await this.hashFileStream(file, hash);
98
+ }
99
+ } else {
100
+ // For single files, stream directly into hash
101
+ await this.hashFileStream(sourcePath, hash);
102
+ }
103
+
104
+ return hash.digest('hex');
105
+ }
106
+
107
+ /**
108
+ * Cache a custom module source
109
+ * @param {string} moduleId - Module ID
110
+ * @param {string} sourcePath - Original source path
111
+ * @param {Object} metadata - Additional metadata to store
112
+ * @returns {Object} Cached module info
113
+ */
114
+ async cacheModule(moduleId, sourcePath, metadata = {}) {
115
+ await this.ensureCacheDir();
116
+
117
+ const cacheDir = path.join(this.customCacheDir, moduleId);
118
+ const cacheManifest = await this.getCacheManifest();
119
+
120
+ // Check if already cached and unchanged
121
+ if (cacheManifest[moduleId]) {
122
+ const cached = cacheManifest[moduleId];
123
+ if (cached.originalHash && cached.originalHash === (await this.calculateHash(sourcePath))) {
124
+ // Source unchanged, return existing cache info
125
+ return {
126
+ moduleId,
127
+ cachePath: cacheDir,
128
+ ...cached,
129
+ };
130
+ }
131
+ }
132
+
133
+ // Remove existing cache if it exists
134
+ if (await fs.pathExists(cacheDir)) {
135
+ await fs.remove(cacheDir);
136
+ }
137
+
138
+ // Copy module to cache
139
+ await fs.copy(sourcePath, cacheDir, {
140
+ filter: (src) => {
141
+ const relative = path.relative(sourcePath, src);
142
+ // Skip node_modules, .git, and other common ignore patterns
143
+ return !relative.includes('node_modules') && !relative.startsWith('.git') && !relative.startsWith('.DS_Store');
144
+ },
145
+ });
146
+
147
+ // Calculate hash of the source
148
+ const sourceHash = await this.calculateHash(sourcePath);
149
+ const cacheHash = await this.calculateHash(cacheDir);
150
+
151
+ // Update manifest - don't store absolute paths for portability
152
+ // Clean metadata to remove absolute paths
153
+ const cleanMetadata = { ...metadata };
154
+ if (cleanMetadata.sourcePath) {
155
+ delete cleanMetadata.sourcePath;
156
+ }
157
+
158
+ cacheManifest[moduleId] = {
159
+ originalHash: sourceHash,
160
+ cacheHash: cacheHash,
161
+ cachedAt: new Date().toISOString(),
162
+ ...cleanMetadata,
163
+ };
164
+
165
+ await this.updateCacheManifest(cacheManifest);
166
+
167
+ return {
168
+ moduleId,
169
+ cachePath: cacheDir,
170
+ ...cacheManifest[moduleId],
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Get cached module info
176
+ * @param {string} moduleId - Module ID
177
+ * @returns {Object|null} Cached module info or null
178
+ */
179
+ async getCachedModule(moduleId) {
180
+ const cacheManifest = await this.getCacheManifest();
181
+ const cached = cacheManifest[moduleId];
182
+
183
+ if (!cached) {
184
+ return null;
185
+ }
186
+
187
+ const cacheDir = path.join(this.customCacheDir, moduleId);
188
+
189
+ if (!(await fs.pathExists(cacheDir))) {
190
+ // Cache dir missing, remove from manifest
191
+ delete cacheManifest[moduleId];
192
+ await this.updateCacheManifest(cacheManifest);
193
+ return null;
194
+ }
195
+
196
+ // Verify cache integrity
197
+ const currentCacheHash = await this.calculateHash(cacheDir);
198
+ if (currentCacheHash !== cached.cacheHash) {
199
+ await prompts.log.warn(`Cache integrity check failed for ${moduleId}`);
200
+ }
201
+
202
+ return {
203
+ moduleId,
204
+ cachePath: cacheDir,
205
+ ...cached,
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Get all cached modules
211
+ * @returns {Array} Array of cached module info
212
+ */
213
+ async getAllCachedModules() {
214
+ const cacheManifest = await this.getCacheManifest();
215
+ const cached = [];
216
+
217
+ for (const [moduleId, info] of Object.entries(cacheManifest)) {
218
+ const cachedModule = await this.getCachedModule(moduleId);
219
+ if (cachedModule) {
220
+ cached.push(cachedModule);
221
+ }
222
+ }
223
+
224
+ return cached;
225
+ }
226
+
227
+ /**
228
+ * Remove a cached module
229
+ * @param {string} moduleId - Module ID to remove
230
+ */
231
+ async removeCachedModule(moduleId) {
232
+ const cacheManifest = await this.getCacheManifest();
233
+ const cacheDir = path.join(this.customCacheDir, moduleId);
234
+
235
+ // Remove cache directory
236
+ if (await fs.pathExists(cacheDir)) {
237
+ await fs.remove(cacheDir);
238
+ }
239
+
240
+ // Remove from manifest
241
+ delete cacheManifest[moduleId];
242
+ await this.updateCacheManifest(cacheManifest);
243
+ }
244
+
245
+ /**
246
+ * Sync cached modules with a list of module IDs
247
+ * @param {Array<string>} moduleIds - Module IDs to keep
248
+ */
249
+ async syncCache(moduleIds) {
250
+ const cached = await this.getAllCachedModules();
251
+
252
+ for (const cachedModule of cached) {
253
+ if (!moduleIds.includes(cachedModule.moduleId)) {
254
+ await this.removeCachedModule(cachedModule.moduleId);
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ module.exports = { CustomModuleCache };
@@ -0,0 +1,127 @@
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const yaml = require('yaml');
4
+ const { Manifest } = require('./manifest');
5
+
6
+ /**
7
+ * Immutable snapshot of an existing SCM installation.
8
+ * Pure query object — no filesystem operations after construction.
9
+ */
10
+ class ExistingInstall {
11
+ #version;
12
+
13
+ constructor({ installed, version, hasCore, modules, ides, customModules }) {
14
+ this.installed = installed;
15
+ this.#version = version;
16
+ this.hasCore = hasCore;
17
+ this.modules = Object.freeze(modules.map((m) => Object.freeze({ ...m })));
18
+ this.moduleIds = Object.freeze(this.modules.map((m) => m.id));
19
+ this.ides = Object.freeze([...ides]);
20
+ this.customModules = Object.freeze([...customModules]);
21
+ Object.freeze(this);
22
+ }
23
+
24
+ get version() {
25
+ if (!this.installed) {
26
+ throw new Error('version is not available when nothing is installed');
27
+ }
28
+ return this.#version;
29
+ }
30
+
31
+ static empty() {
32
+ return new ExistingInstall({
33
+ installed: false,
34
+ version: null,
35
+ hasCore: false,
36
+ modules: [],
37
+ ides: [],
38
+ customModules: [],
39
+ });
40
+ }
41
+
42
+ /**
43
+ * Scan a scm directory and return an immutable snapshot of what's installed.
44
+ * @param {string} scmDir - Path to scm directory
45
+ * @returns {Promise<ExistingInstall>}
46
+ */
47
+ static async detect(scmDir) {
48
+ if (!(await fs.pathExists(scmDir))) {
49
+ return ExistingInstall.empty();
50
+ }
51
+
52
+ let version = null;
53
+ let hasCore = false;
54
+ const modules = [];
55
+ let ides = [];
56
+ let customModules = [];
57
+
58
+ const manifest = new Manifest();
59
+ const manifestData = await manifest.read(scmDir);
60
+ if (manifestData) {
61
+ version = manifestData.version;
62
+ if (manifestData.customModules) {
63
+ customModules = manifestData.customModules;
64
+ }
65
+ if (manifestData.ides) {
66
+ ides = manifestData.ides.filter((ide) => ide && typeof ide === 'string');
67
+ }
68
+ }
69
+
70
+ const corePath = path.join(scmDir, 'core');
71
+ if (await fs.pathExists(corePath)) {
72
+ hasCore = true;
73
+
74
+ if (!version) {
75
+ const coreConfigPath = path.join(corePath, 'config.yaml');
76
+ if (await fs.pathExists(coreConfigPath)) {
77
+ try {
78
+ const configContent = await fs.readFile(coreConfigPath, 'utf8');
79
+ const config = yaml.parse(configContent);
80
+ if (config.version) {
81
+ version = config.version;
82
+ }
83
+ } catch {
84
+ // Ignore config read errors
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ if (manifestData && manifestData.modules && manifestData.modules.length > 0) {
91
+ for (const moduleId of manifestData.modules) {
92
+ const modulePath = path.join(scmDir, moduleId);
93
+ const moduleConfigPath = path.join(modulePath, 'config.yaml');
94
+
95
+ const moduleInfo = {
96
+ id: moduleId,
97
+ path: modulePath,
98
+ version: 'unknown',
99
+ };
100
+
101
+ if (await fs.pathExists(moduleConfigPath)) {
102
+ try {
103
+ const configContent = await fs.readFile(moduleConfigPath, 'utf8');
104
+ const config = yaml.parse(configContent);
105
+ moduleInfo.version = config.version || 'unknown';
106
+ moduleInfo.name = config.name || moduleId;
107
+ moduleInfo.description = config.description;
108
+ } catch {
109
+ // Ignore config read errors
110
+ }
111
+ }
112
+
113
+ modules.push(moduleInfo);
114
+ }
115
+ }
116
+
117
+ const installed = hasCore || modules.length > 0 || !!manifestData;
118
+
119
+ if (!installed) {
120
+ return ExistingInstall.empty();
121
+ }
122
+
123
+ return new ExistingInstall({ installed, version, hasCore, modules, ides, customModules });
124
+ }
125
+ }
126
+
127
+ module.exports = { ExistingInstall };