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,1040 @@
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const crypto = require('node:crypto');
4
+ const { getProjectRoot } = require('../project-root');
5
+ const prompts = require('../prompts');
6
+
7
+ class Manifest {
8
+ /**
9
+ * Create a new manifest
10
+ * @param {string} scmDir - Path to scm directory
11
+ * @param {Object} data - Manifest data
12
+ * @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv)
13
+ */
14
+ async create(scmDir, data, installedFiles = []) {
15
+ const manifestPath = path.join(scmDir, '_config', 'manifest.yaml');
16
+ const yaml = require('yaml');
17
+
18
+ // Ensure _config directory exists
19
+ await fs.ensureDir(path.dirname(manifestPath));
20
+
21
+ // Get the SCM version from package.json
22
+ const scmVersion = data.version || require(path.join(process.cwd(), 'package.json')).version;
23
+
24
+ // Convert module list to new detailed format
25
+ const moduleDetails = [];
26
+ if (data.modules && Array.isArray(data.modules)) {
27
+ for (const moduleName of data.modules) {
28
+ // Core and BMM modules use the SCM version
29
+ const moduleVersion = moduleName === 'core' || moduleName === 'bmm' ? scmVersion : null;
30
+ const now = data.installDate || new Date().toISOString();
31
+
32
+ moduleDetails.push({
33
+ name: moduleName,
34
+ version: moduleVersion,
35
+ installDate: now,
36
+ lastUpdated: now,
37
+ source: moduleName === 'core' || moduleName === 'bmm' ? 'built-in' : 'unknown',
38
+ });
39
+ }
40
+ }
41
+
42
+ // Structure the manifest data
43
+ const manifestData = {
44
+ installation: {
45
+ version: scmVersion,
46
+ installDate: data.installDate || new Date().toISOString(),
47
+ lastUpdated: data.lastUpdated || new Date().toISOString(),
48
+ },
49
+ modules: moduleDetails,
50
+ ides: data.ides || [],
51
+ };
52
+
53
+ // Write YAML manifest
54
+ // Clean the manifest data to remove any non-serializable values
55
+ const cleanManifestData = structuredClone(manifestData);
56
+
57
+ const yamlContent = yaml.stringify(cleanManifestData, {
58
+ indent: 2,
59
+ lineWidth: 0,
60
+ sortKeys: false,
61
+ });
62
+
63
+ // Ensure POSIX-compliant final newline
64
+ const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
65
+ await fs.writeFile(manifestPath, content, 'utf8');
66
+ return { success: true, path: manifestPath, filesTracked: 0 };
67
+ }
68
+
69
+ /**
70
+ * Read existing manifest
71
+ * @param {string} scmDir - Path to scm directory
72
+ * @returns {Object|null} Manifest data or null if not found
73
+ */
74
+ async read(scmDir) {
75
+ const yamlPath = path.join(scmDir, '_config', 'manifest.yaml');
76
+ const yaml = require('yaml');
77
+
78
+ if (await fs.pathExists(yamlPath)) {
79
+ try {
80
+ const content = await fs.readFile(yamlPath, 'utf8');
81
+ const manifestData = yaml.parse(content);
82
+
83
+ // Handle new detailed module format
84
+ const modules = manifestData.modules || [];
85
+
86
+ // For backward compatibility: if modules is an array of strings (old format),
87
+ // the calling code may need the array of names
88
+ const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
89
+
90
+ // Check if we have the new detailed format
91
+ const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
92
+
93
+ // Flatten the structure for compatibility with existing code
94
+ return {
95
+ version: manifestData.installation?.version,
96
+ installDate: manifestData.installation?.installDate,
97
+ lastUpdated: manifestData.installation?.lastUpdated,
98
+ modules: moduleNames, // Simple array of module names for backward compatibility
99
+ modulesDetailed: hasDetailedModules ? modules : null, // New detailed format
100
+ customModules: manifestData.customModules || [], // Keep for backward compatibility
101
+ ides: manifestData.ides || [],
102
+ };
103
+ } catch (error) {
104
+ await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
105
+ }
106
+ }
107
+
108
+ return null;
109
+ }
110
+
111
+ /**
112
+ * Update existing manifest
113
+ * @param {string} scmDir - Path to scm directory
114
+ * @param {Object} updates - Fields to update
115
+ * @param {Array} installedFiles - Updated list of installed files
116
+ */
117
+ async update(scmDir, updates, installedFiles = null) {
118
+ const yaml = require('yaml');
119
+ const manifest = (await this._readRaw(scmDir)) || {
120
+ installation: {},
121
+ modules: [],
122
+ ides: [],
123
+ };
124
+
125
+ // Handle module updates
126
+ if (updates.modules) {
127
+ // If modules is being updated, we need to preserve detailed module info
128
+ const existingDetailed = manifest.modules || [];
129
+ const incomingNames = updates.modules;
130
+
131
+ // Build updated modules array
132
+ const updatedModules = [];
133
+ for (const name of incomingNames) {
134
+ const existing = existingDetailed.find((m) => m.name === name);
135
+ if (existing) {
136
+ // Preserve existing details, update lastUpdated if this module is being updated
137
+ updatedModules.push({
138
+ ...existing,
139
+ lastUpdated: new Date().toISOString(),
140
+ });
141
+ } else {
142
+ // New module - add with minimal details
143
+ updatedModules.push({
144
+ name,
145
+ version: null,
146
+ installDate: new Date().toISOString(),
147
+ lastUpdated: new Date().toISOString(),
148
+ source: 'unknown',
149
+ });
150
+ }
151
+ }
152
+
153
+ manifest.modules = updatedModules;
154
+ }
155
+
156
+ // Merge other updates
157
+ if (updates.version) {
158
+ manifest.installation.version = updates.version;
159
+ }
160
+ if (updates.installDate) {
161
+ manifest.installation.installDate = updates.installDate;
162
+ }
163
+ manifest.installation.lastUpdated = new Date().toISOString();
164
+
165
+ if (updates.ides) {
166
+ manifest.ides = updates.ides;
167
+ }
168
+
169
+ // Handle per-module version updates
170
+ if (updates.moduleVersions) {
171
+ for (const [moduleName, versionInfo] of Object.entries(updates.moduleVersions)) {
172
+ const moduleIndex = manifest.modules.findIndex((m) => m.name === moduleName);
173
+ if (moduleIndex !== -1) {
174
+ manifest.modules[moduleIndex] = {
175
+ ...manifest.modules[moduleIndex],
176
+ ...versionInfo,
177
+ lastUpdated: new Date().toISOString(),
178
+ };
179
+ }
180
+ }
181
+ }
182
+
183
+ // Handle adding a new module with version info
184
+ if (updates.addModule) {
185
+ const { name, version, source, npmPackage, repoUrl } = updates.addModule;
186
+ const existing = manifest.modules.find((m) => m.name === name);
187
+ if (!existing) {
188
+ manifest.modules.push({
189
+ name,
190
+ version: version || null,
191
+ installDate: new Date().toISOString(),
192
+ lastUpdated: new Date().toISOString(),
193
+ source: source || 'external',
194
+ npmPackage: npmPackage || null,
195
+ repoUrl: repoUrl || null,
196
+ });
197
+ }
198
+ }
199
+
200
+ const manifestPath = path.join(scmDir, '_config', 'manifest.yaml');
201
+ await fs.ensureDir(path.dirname(manifestPath));
202
+
203
+ // Clean the manifest data to remove any non-serializable values
204
+ const cleanManifestData = structuredClone(manifest);
205
+
206
+ const yamlContent = yaml.stringify(cleanManifestData, {
207
+ indent: 2,
208
+ lineWidth: 0,
209
+ sortKeys: false,
210
+ });
211
+
212
+ // Ensure POSIX-compliant final newline
213
+ const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
214
+ await fs.writeFile(manifestPath, content, 'utf8');
215
+
216
+ // Return the flattened format for compatibility
217
+ return this._flattenManifest(manifest);
218
+ }
219
+
220
+ /**
221
+ * Read raw manifest data without flattening
222
+ * @param {string} scmDir - Path to scm directory
223
+ * @returns {Object|null} Raw manifest data or null if not found
224
+ */
225
+ async _readRaw(scmDir) {
226
+ const yamlPath = path.join(scmDir, '_config', 'manifest.yaml');
227
+ const yaml = require('yaml');
228
+
229
+ if (await fs.pathExists(yamlPath)) {
230
+ try {
231
+ const content = await fs.readFile(yamlPath, 'utf8');
232
+ return yaml.parse(content);
233
+ } catch (error) {
234
+ await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
235
+ }
236
+ }
237
+
238
+ return null;
239
+ }
240
+
241
+ /**
242
+ * Flatten manifest for backward compatibility
243
+ * @param {Object} manifest - Raw manifest data
244
+ * @returns {Object} Flattened manifest
245
+ */
246
+ _flattenManifest(manifest) {
247
+ const modules = manifest.modules || [];
248
+ const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
249
+ const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
250
+
251
+ return {
252
+ version: manifest.installation?.version,
253
+ installDate: manifest.installation?.installDate,
254
+ lastUpdated: manifest.installation?.lastUpdated,
255
+ modules: moduleNames,
256
+ modulesDetailed: hasDetailedModules ? modules : null,
257
+ customModules: manifest.customModules || [],
258
+ ides: manifest.ides || [],
259
+ };
260
+ }
261
+
262
+ /**
263
+ * Add a module to the manifest with optional version info
264
+ * If module already exists, update its version info
265
+ * @param {string} scmDir - Path to scm directory
266
+ * @param {string} moduleName - Module name to add
267
+ * @param {Object} options - Optional version info
268
+ */
269
+ async addModule(scmDir, moduleName, options = {}) {
270
+ let manifest = await this._readRaw(scmDir);
271
+ if (!manifest) {
272
+ // Bootstrap a minimal manifest if it doesn't exist yet
273
+ // (e.g., skill-only modules with no agents to compile)
274
+ manifest = { modules: [] };
275
+ }
276
+
277
+ if (!manifest.modules) {
278
+ manifest.modules = [];
279
+ }
280
+
281
+ const existingIndex = manifest.modules.findIndex((m) => m.name === moduleName);
282
+
283
+ if (existingIndex === -1) {
284
+ // Module doesn't exist, add it
285
+ manifest.modules.push({
286
+ name: moduleName,
287
+ version: options.version || null,
288
+ installDate: new Date().toISOString(),
289
+ lastUpdated: new Date().toISOString(),
290
+ source: options.source || 'unknown',
291
+ npmPackage: options.npmPackage || null,
292
+ repoUrl: options.repoUrl || null,
293
+ });
294
+ } else {
295
+ // Module exists, update its version info
296
+ const existing = manifest.modules[existingIndex];
297
+ manifest.modules[existingIndex] = {
298
+ ...existing,
299
+ version: options.version === undefined ? existing.version : options.version,
300
+ source: options.source || existing.source,
301
+ npmPackage: options.npmPackage === undefined ? existing.npmPackage : options.npmPackage,
302
+ repoUrl: options.repoUrl === undefined ? existing.repoUrl : options.repoUrl,
303
+ lastUpdated: new Date().toISOString(),
304
+ };
305
+ }
306
+
307
+ await this._writeRaw(scmDir, manifest);
308
+ }
309
+
310
+ /**
311
+ * Remove a module from the manifest
312
+ * @param {string} scmDir - Path to scm directory
313
+ * @param {string} moduleName - Module name to remove
314
+ */
315
+ async removeModule(scmDir, moduleName) {
316
+ const manifest = await this._readRaw(scmDir);
317
+ if (!manifest || !manifest.modules) {
318
+ return;
319
+ }
320
+
321
+ const index = manifest.modules.findIndex((m) => m.name === moduleName);
322
+ if (index !== -1) {
323
+ manifest.modules.splice(index, 1);
324
+ await this._writeRaw(scmDir, manifest);
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Update a single module's version info
330
+ * @param {string} scmDir - Path to scm directory
331
+ * @param {string} moduleName - Module name
332
+ * @param {Object} versionInfo - Version info to update
333
+ */
334
+ async updateModuleVersion(scmDir, moduleName, versionInfo) {
335
+ const manifest = await this._readRaw(scmDir);
336
+ if (!manifest || !manifest.modules) {
337
+ return;
338
+ }
339
+
340
+ const index = manifest.modules.findIndex((m) => m.name === moduleName);
341
+ if (index !== -1) {
342
+ manifest.modules[index] = {
343
+ ...manifest.modules[index],
344
+ ...versionInfo,
345
+ lastUpdated: new Date().toISOString(),
346
+ };
347
+ await this._writeRaw(scmDir, manifest);
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Get version info for a specific module
353
+ * @param {string} scmDir - Path to scm directory
354
+ * @param {string} moduleName - Module name
355
+ * @returns {Object|null} Module version info or null
356
+ */
357
+ async getModuleVersion(scmDir, moduleName) {
358
+ const manifest = await this._readRaw(scmDir);
359
+ if (!manifest || !manifest.modules) {
360
+ return null;
361
+ }
362
+
363
+ return manifest.modules.find((m) => m.name === moduleName) || null;
364
+ }
365
+
366
+ /**
367
+ * Get all modules with their version info
368
+ * @param {string} scmDir - Path to scm directory
369
+ * @returns {Array} Array of module info objects
370
+ */
371
+ async getAllModuleVersions(scmDir) {
372
+ const manifest = await this._readRaw(scmDir);
373
+ if (!manifest || !manifest.modules) {
374
+ return [];
375
+ }
376
+
377
+ return manifest.modules;
378
+ }
379
+
380
+ /**
381
+ * Write raw manifest data to file
382
+ * @param {string} scmDir - Path to scm directory
383
+ * @param {Object} manifestData - Raw manifest data to write
384
+ */
385
+ async _writeRaw(scmDir, manifestData) {
386
+ const yaml = require('yaml');
387
+ const manifestPath = path.join(scmDir, '_config', 'manifest.yaml');
388
+
389
+ await fs.ensureDir(path.dirname(manifestPath));
390
+
391
+ const cleanManifestData = structuredClone(manifestData);
392
+
393
+ const yamlContent = yaml.stringify(cleanManifestData, {
394
+ indent: 2,
395
+ lineWidth: 0,
396
+ sortKeys: false,
397
+ });
398
+
399
+ const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
400
+ await fs.writeFile(manifestPath, content, 'utf8');
401
+ }
402
+
403
+ /**
404
+ * Add an IDE configuration to the manifest
405
+ * @param {string} scmDir - Path to scm directory
406
+ * @param {string} ideName - IDE name to add
407
+ */
408
+ async addIde(scmDir, ideName) {
409
+ const manifest = await this.read(scmDir);
410
+ if (!manifest) {
411
+ throw new Error('No manifest found');
412
+ }
413
+
414
+ if (!manifest.ides) {
415
+ manifest.ides = [];
416
+ }
417
+
418
+ if (!manifest.ides.includes(ideName)) {
419
+ manifest.ides.push(ideName);
420
+ await this.update(scmDir, { ides: manifest.ides });
421
+ }
422
+ }
423
+
424
+ /**
425
+ * Calculate SHA256 hash of a file
426
+ * @param {string} filePath - Path to file
427
+ * @returns {string} SHA256 hash
428
+ */
429
+ async calculateFileHash(filePath) {
430
+ try {
431
+ const content = await fs.readFile(filePath);
432
+ return crypto.createHash('sha256').update(content).digest('hex');
433
+ } catch {
434
+ return null;
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Parse installed files to extract metadata
440
+ * @param {Array} installedFiles - List of installed file paths
441
+ * @param {string} scmDir - Path to scm directory for relative paths
442
+ * @returns {Array} Array of file metadata objects
443
+ */
444
+ async parseInstalledFiles(installedFiles, scmDir) {
445
+ const fileMetadata = [];
446
+
447
+ for (const filePath of installedFiles) {
448
+ const fileExt = path.extname(filePath).toLowerCase();
449
+ // Make path relative to parent of scm directory, starting with 'scm/'
450
+ const relativePath = 'scm' + filePath.replace(scmDir, '').replaceAll('\\', '/');
451
+
452
+ // Calculate file hash
453
+ const hash = await this.calculateFileHash(filePath);
454
+
455
+ // Handle markdown files - extract XML metadata if present
456
+ if (fileExt === '.md') {
457
+ try {
458
+ if (await fs.pathExists(filePath)) {
459
+ const content = await fs.readFile(filePath, 'utf8');
460
+ const metadata = this.extractXmlNodeAttributes(content, filePath, relativePath);
461
+
462
+ if (metadata) {
463
+ // Has XML metadata
464
+ metadata.hash = hash;
465
+ fileMetadata.push(metadata);
466
+ } else {
467
+ // No XML metadata - still track the file
468
+ fileMetadata.push({
469
+ file: relativePath,
470
+ type: 'md',
471
+ name: path.basename(filePath, fileExt),
472
+ title: null,
473
+ hash: hash,
474
+ });
475
+ }
476
+ }
477
+ } catch (error) {
478
+ await prompts.log.warn(`Could not parse ${filePath}: ${error.message}`);
479
+ }
480
+ }
481
+ // Handle other file types (CSV, JSON, YAML, etc.)
482
+ else {
483
+ fileMetadata.push({
484
+ file: relativePath,
485
+ type: fileExt.slice(1), // Remove the dot
486
+ name: path.basename(filePath, fileExt),
487
+ title: null,
488
+ hash: hash,
489
+ });
490
+ }
491
+ }
492
+
493
+ return fileMetadata;
494
+ }
495
+
496
+ /**
497
+ * Extract XML node attributes from MD file content
498
+ * @param {string} content - File content
499
+ * @param {string} filePath - File path for context
500
+ * @param {string} relativePath - Relative path starting with 'scm/'
501
+ * @returns {Object|null} Extracted metadata or null
502
+ */
503
+ extractXmlNodeAttributes(content, filePath, relativePath) {
504
+ // Look for XML blocks in code fences
505
+ const xmlBlockMatch = content.match(/```xml\s*([\s\S]*?)```/);
506
+ if (!xmlBlockMatch) {
507
+ return null;
508
+ }
509
+
510
+ const xmlContent = xmlBlockMatch[1];
511
+
512
+ // Extract root XML node (agent, task, template, etc.)
513
+ const rootNodeMatch = xmlContent.match(/<(\w+)([^>]*)>/);
514
+ if (!rootNodeMatch) {
515
+ return null;
516
+ }
517
+
518
+ const nodeType = rootNodeMatch[1];
519
+ const attributes = rootNodeMatch[2];
520
+
521
+ // Extract name and title attributes (id not needed since we have path)
522
+ const nameMatch = attributes.match(/name="([^"]*)"/);
523
+ const titleMatch = attributes.match(/title="([^"]*)"/);
524
+
525
+ return {
526
+ file: relativePath,
527
+ type: nodeType,
528
+ name: nameMatch ? nameMatch[1] : null,
529
+ title: titleMatch ? titleMatch[1] : null,
530
+ };
531
+ }
532
+
533
+ /**
534
+ * Generate CSV manifest content
535
+ * @param {Object} data - Manifest data
536
+ * @param {Array} fileMetadata - File metadata array
537
+ * @param {Object} moduleConfigs - Module configuration data
538
+ * @returns {string} CSV content
539
+ */
540
+ generateManifestCsv(data, fileMetadata, moduleConfigs = {}) {
541
+ const timestamp = new Date().toISOString();
542
+ let csv = [];
543
+
544
+ // Header section
545
+ csv.push(
546
+ '# SCM Manifest',
547
+ `# Generated: ${timestamp}`,
548
+ '',
549
+ '## Installation Info',
550
+ 'Property,Value',
551
+ `Version,${data.version}`,
552
+ `InstallDate,${data.installDate || timestamp}`,
553
+ `LastUpdated,${data.lastUpdated || timestamp}`,
554
+ );
555
+ if (data.language) {
556
+ csv.push(`Language,${data.language}`);
557
+ }
558
+ csv.push('');
559
+
560
+ // Modules section
561
+ if (data.modules && data.modules.length > 0) {
562
+ csv.push('## Modules', 'Name,Version,ShortTitle');
563
+ for (const moduleName of data.modules) {
564
+ const config = moduleConfigs[moduleName] || {};
565
+ csv.push([moduleName, config.version || '', config['short-title'] || ''].map((v) => this.escapeCsv(v)).join(','));
566
+ }
567
+ csv.push('');
568
+ }
569
+
570
+ // IDEs section
571
+ if (data.ides && data.ides.length > 0) {
572
+ csv.push('## IDEs', 'IDE');
573
+ for (const ide of data.ides) {
574
+ csv.push(this.escapeCsv(ide));
575
+ }
576
+ csv.push('');
577
+ }
578
+
579
+ // Files section - NO LONGER USED
580
+ // Files are now tracked in files-manifest.csv by ManifestGenerator
581
+
582
+ return csv.join('\n');
583
+ }
584
+
585
+ /**
586
+ * Parse CSV manifest content back to object
587
+ * @param {string} csvContent - CSV content to parse
588
+ * @returns {Object} Parsed manifest data
589
+ */
590
+ parseManifestCsv(csvContent) {
591
+ const result = {
592
+ modules: [],
593
+ ides: [],
594
+ files: [],
595
+ };
596
+
597
+ const lines = csvContent.split('\n');
598
+ let section = '';
599
+
600
+ for (const line_ of lines) {
601
+ const line = line_.trim();
602
+
603
+ // Skip empty lines and comments
604
+ if (!line || line.startsWith('#')) {
605
+ // Check for section headers
606
+ if (line.startsWith('## ')) {
607
+ section = line.slice(3).toLowerCase();
608
+ }
609
+ continue;
610
+ }
611
+
612
+ // Parse based on current section
613
+ switch (section) {
614
+ case 'installation info': {
615
+ // Skip header row
616
+ if (line === 'Property,Value') continue;
617
+
618
+ const [property, ...valueParts] = line.split(',');
619
+ const value = this.unescapeCsv(valueParts.join(','));
620
+
621
+ switch (property) {
622
+ // Path no longer stored in manifest
623
+ case 'Version': {
624
+ result.version = value;
625
+ break;
626
+ }
627
+ case 'InstallDate': {
628
+ result.installDate = value;
629
+ break;
630
+ }
631
+ case 'LastUpdated': {
632
+ result.lastUpdated = value;
633
+ break;
634
+ }
635
+ case 'Language': {
636
+ result.language = value;
637
+ break;
638
+ }
639
+ }
640
+
641
+ break;
642
+ }
643
+ case 'modules': {
644
+ // Skip header row
645
+ if (line === 'Name,Version,ShortTitle') continue;
646
+
647
+ const parts = this.parseCsvLine(line);
648
+ if (parts[0]) {
649
+ result.modules.push(parts[0]);
650
+ }
651
+
652
+ break;
653
+ }
654
+ case 'ides': {
655
+ // Skip header row
656
+ if (line === 'IDE') continue;
657
+
658
+ result.ides.push(this.unescapeCsv(line));
659
+
660
+ break;
661
+ }
662
+ case 'files': {
663
+ // Skip header rows (support both old and new format)
664
+ if (line === 'Type,Path,Name,Title' || line === 'Type,Path,Name,Title,Hash') continue;
665
+
666
+ const parts = this.parseCsvLine(line);
667
+ if (parts.length >= 2) {
668
+ result.files.push({
669
+ type: parts[0] || '',
670
+ file: parts[1] || '',
671
+ name: parts[2] || null,
672
+ title: parts[3] || null,
673
+ hash: parts[4] || null, // Hash column (may not exist in old manifests)
674
+ });
675
+ }
676
+
677
+ break;
678
+ }
679
+ // No default
680
+ }
681
+ }
682
+
683
+ return result;
684
+ }
685
+
686
+ /**
687
+ * Parse a CSV line handling quotes and commas
688
+ * @param {string} line - CSV line to parse
689
+ * @returns {Array} Array of values
690
+ */
691
+ parseCsvLine(line) {
692
+ const result = [];
693
+ let current = '';
694
+ let inQuotes = false;
695
+
696
+ for (let i = 0; i < line.length; i++) {
697
+ const char = line[i];
698
+
699
+ if (char === '"') {
700
+ if (inQuotes && line[i + 1] === '"') {
701
+ // Escaped quote
702
+ current += '"';
703
+ i++;
704
+ } else {
705
+ // Toggle quote state
706
+ inQuotes = !inQuotes;
707
+ }
708
+ } else if (char === ',' && !inQuotes) {
709
+ // Field separator
710
+ result.push(this.unescapeCsv(current));
711
+ current = '';
712
+ } else {
713
+ current += char;
714
+ }
715
+ }
716
+
717
+ // Add the last field
718
+ result.push(this.unescapeCsv(current));
719
+
720
+ return result;
721
+ }
722
+
723
+ /**
724
+ * Escape CSV special characters
725
+ * @param {string} text - Text to escape
726
+ * @returns {string} Escaped text
727
+ */
728
+ escapeCsv(text) {
729
+ if (!text) return '';
730
+ const str = String(text);
731
+
732
+ // If contains comma, newline, or quote, wrap in quotes and escape quotes
733
+ if (str.includes(',') || str.includes('\n') || str.includes('"')) {
734
+ return '"' + str.replaceAll('"', '""') + '"';
735
+ }
736
+
737
+ return str;
738
+ }
739
+
740
+ /**
741
+ * Unescape CSV field
742
+ * @param {string} text - Text to unescape
743
+ * @returns {string} Unescaped text
744
+ */
745
+ unescapeCsv(text) {
746
+ if (!text) return '';
747
+
748
+ // Remove surrounding quotes if present
749
+ if (text.startsWith('"') && text.endsWith('"')) {
750
+ text = text.slice(1, -1);
751
+ // Unescape doubled quotes
752
+ text = text.replaceAll('""', '"');
753
+ }
754
+
755
+ return text;
756
+ }
757
+
758
+ /**
759
+ * Load module configuration files
760
+ * @param {Array} modules - List of module names
761
+ * @returns {Object} Module configurations indexed by name
762
+ */
763
+ async loadModuleConfigs(modules) {
764
+ const configs = {};
765
+
766
+ for (const moduleName of modules) {
767
+ // Handle core module differently - it's in src/core-skills not src/modules/core
768
+ const configPath =
769
+ moduleName === 'core'
770
+ ? path.join(process.cwd(), 'src', 'core-skills', 'config.yaml')
771
+ : path.join(process.cwd(), 'src', 'modules', moduleName, 'config.yaml');
772
+
773
+ try {
774
+ if (await fs.pathExists(configPath)) {
775
+ const yaml = require('yaml');
776
+ const content = await fs.readFile(configPath, 'utf8');
777
+ configs[moduleName] = yaml.parse(content);
778
+ }
779
+ } catch (error) {
780
+ await prompts.log.warn(`Could not load config for module ${moduleName}: ${error.message}`);
781
+ }
782
+ }
783
+
784
+ return configs;
785
+ }
786
+ /**
787
+ * Add a custom module to the manifest with its source path
788
+ * @param {string} scmDir - Path to scm directory
789
+ * @param {Object} customModule - Custom module info
790
+ */
791
+ async addCustomModule(scmDir, customModule) {
792
+ const manifest = await this.read(scmDir);
793
+ if (!manifest) {
794
+ throw new Error('No manifest found');
795
+ }
796
+
797
+ if (!manifest.customModules) {
798
+ manifest.customModules = [];
799
+ }
800
+
801
+ // Check if custom module already exists
802
+ const existingIndex = manifest.customModules.findIndex((m) => m.id === customModule.id);
803
+ if (existingIndex === -1) {
804
+ // Add new entry
805
+ manifest.customModules.push(customModule);
806
+ } else {
807
+ // Update existing entry
808
+ manifest.customModules[existingIndex] = customModule;
809
+ }
810
+
811
+ await this.update(scmDir, { customModules: manifest.customModules });
812
+ }
813
+
814
+ /**
815
+ * Remove a custom module from the manifest
816
+ * @param {string} scmDir - Path to scm directory
817
+ * @param {string} moduleId - Module ID to remove
818
+ */
819
+ async removeCustomModule(scmDir, moduleId) {
820
+ const manifest = await this.read(scmDir);
821
+ if (!manifest || !manifest.customModules) {
822
+ return;
823
+ }
824
+
825
+ const index = manifest.customModules.findIndex((m) => m.id === moduleId);
826
+ if (index !== -1) {
827
+ manifest.customModules.splice(index, 1);
828
+ await this.update(scmDir, { customModules: manifest.customModules });
829
+ }
830
+ }
831
+
832
+ /**
833
+ * Get module version info from source
834
+ * @param {string} moduleName - Module name/code
835
+ * @param {string} scmDir - Path to scm directory
836
+ * @param {string} moduleSourcePath - Optional source path for custom modules
837
+ * @returns {Object} Version info object with version, source, npmPackage, repoUrl
838
+ */
839
+ async getModuleVersionInfo(moduleName, scmDir, moduleSourcePath = null) {
840
+ const os = require('node:os');
841
+ const yaml = require('yaml');
842
+
843
+ // Built-in modules use SCM version (only core and bmm are in SCM-METHOD repo)
844
+ if (['core', 'bmm'].includes(moduleName)) {
845
+ const scmVersion = require(path.join(getProjectRoot(), 'package.json')).version;
846
+ return {
847
+ version: scmVersion,
848
+ source: 'built-in',
849
+ npmPackage: null,
850
+ repoUrl: null,
851
+ };
852
+ }
853
+
854
+ // Check if this is an external official module
855
+ const { ExternalModuleManager } = require('../modules/external-manager');
856
+ const extMgr = new ExternalModuleManager();
857
+ const moduleInfo = await extMgr.getModuleByCode(moduleName);
858
+
859
+ if (moduleInfo) {
860
+ // External module - try to get version from npm registry first, then fall back to cache
861
+ let version = null;
862
+
863
+ if (moduleInfo.npmPackage) {
864
+ // Fetch version from npm registry
865
+ try {
866
+ version = await this.fetchNpmVersion(moduleInfo.npmPackage);
867
+ } catch {
868
+ // npm fetch failed, try cache as fallback
869
+ }
870
+ }
871
+
872
+ // If npm didn't work, try reading from cached repo's package.json
873
+ if (!version) {
874
+ const cacheDir = path.join(os.homedir(), '.scm', 'cache', 'external-modules', moduleName);
875
+ const packageJsonPath = path.join(cacheDir, 'package.json');
876
+
877
+ if (await fs.pathExists(packageJsonPath)) {
878
+ try {
879
+ const pkg = require(packageJsonPath);
880
+ version = pkg.version;
881
+ } catch (error) {
882
+ await prompts.log.warn(`Failed to read package.json for ${moduleName}: ${error.message}`);
883
+ }
884
+ }
885
+ }
886
+
887
+ return {
888
+ version: version,
889
+ source: 'external',
890
+ npmPackage: moduleInfo.npmPackage || null,
891
+ repoUrl: moduleInfo.url || null,
892
+ };
893
+ }
894
+
895
+ // Custom module - check cache directory
896
+ const cacheDir = path.join(scmDir, '_config', 'custom', moduleName);
897
+ const moduleYamlPath = path.join(cacheDir, 'module.yaml');
898
+
899
+ if (await fs.pathExists(moduleYamlPath)) {
900
+ try {
901
+ const yamlContent = await fs.readFile(moduleYamlPath, 'utf8');
902
+ const moduleConfig = yaml.parse(yamlContent);
903
+ return {
904
+ version: moduleConfig.version || null,
905
+ source: 'custom',
906
+ npmPackage: moduleConfig.npmPackage || null,
907
+ repoUrl: moduleConfig.repoUrl || null,
908
+ };
909
+ } catch (error) {
910
+ await prompts.log.warn(`Failed to read module.yaml for ${moduleName}: ${error.message}`);
911
+ }
912
+ }
913
+
914
+ // Unknown module
915
+ return {
916
+ version: null,
917
+ source: 'unknown',
918
+ npmPackage: null,
919
+ repoUrl: null,
920
+ };
921
+ }
922
+
923
+ /**
924
+ * Fetch latest version from npm for a package
925
+ * @param {string} packageName - npm package name
926
+ * @returns {string|null} Latest version or null
927
+ */
928
+ async fetchNpmVersion(packageName) {
929
+ try {
930
+ const https = require('node:https');
931
+ const { execSync } = require('node:child_process');
932
+
933
+ // Try using npm view first (more reliable)
934
+ try {
935
+ const result = execSync(`npm view ${packageName} version`, {
936
+ encoding: 'utf8',
937
+ stdio: 'pipe',
938
+ timeout: 10_000,
939
+ });
940
+ return result.trim();
941
+ } catch {
942
+ // Fallback to npm registry API
943
+ return new Promise((resolve, reject) => {
944
+ https
945
+ .get(`https://registry.npmjs.org/${packageName}`, (res) => {
946
+ let data = '';
947
+ res.on('data', (chunk) => (data += chunk));
948
+ res.on('end', () => {
949
+ try {
950
+ const pkg = JSON.parse(data);
951
+ resolve(pkg['dist-tags']?.latest || pkg.version || null);
952
+ } catch {
953
+ resolve(null);
954
+ }
955
+ });
956
+ })
957
+ .on('error', () => resolve(null));
958
+ });
959
+ }
960
+ } catch {
961
+ return null;
962
+ }
963
+ }
964
+
965
+ /**
966
+ * Check for available updates for installed modules
967
+ * @param {string} scmDir - Path to scm directory
968
+ * @returns {Array} Array of update info objects
969
+ */
970
+ async checkForUpdates(scmDir) {
971
+ const modules = await this.getAllModuleVersions(scmDir);
972
+ const updates = [];
973
+
974
+ for (const module of modules) {
975
+ if (!module.npmPackage) {
976
+ continue; // Skip modules without npm package (built-in)
977
+ }
978
+
979
+ const latestVersion = await this.fetchNpmVersion(module.npmPackage);
980
+ if (!latestVersion) {
981
+ continue;
982
+ }
983
+
984
+ if (module.version !== latestVersion) {
985
+ updates.push({
986
+ name: module.name,
987
+ installedVersion: module.version,
988
+ latestVersion: latestVersion,
989
+ npmPackage: module.npmPackage,
990
+ updateAvailable: true,
991
+ });
992
+ }
993
+ }
994
+
995
+ return updates;
996
+ }
997
+
998
+ /**
999
+ * Compare two semantic versions
1000
+ * @param {string} v1 - First version
1001
+ * @param {string} v2 - Second version
1002
+ * @returns {number} -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
1003
+ */
1004
+ compareVersions(v1, v2) {
1005
+ if (!v1 || !v2) return 0;
1006
+
1007
+ const normalize = (v) => {
1008
+ // Remove leading 'v' if present
1009
+ v = v.replace(/^v/, '');
1010
+ // Handle prerelease tags
1011
+ const parts = v.split('-');
1012
+ const main = parts[0].split('.');
1013
+ const prerelease = parts[1];
1014
+ return { main, prerelease };
1015
+ };
1016
+
1017
+ const n1 = normalize(v1);
1018
+ const n2 = normalize(v2);
1019
+
1020
+ // Compare main version parts
1021
+ for (let i = 0; i < 3; i++) {
1022
+ const num1 = parseInt(n1.main[i] || '0', 10);
1023
+ const num2 = parseInt(n2.main[i] || '0', 10);
1024
+ if (num1 !== num2) {
1025
+ return num1 < num2 ? -1 : 1;
1026
+ }
1027
+ }
1028
+
1029
+ // If main versions are equal, compare prerelease
1030
+ if (n1.prerelease && n2.prerelease) {
1031
+ return n1.prerelease < n2.prerelease ? -1 : n1.prerelease > n2.prerelease ? 1 : 0;
1032
+ }
1033
+ if (n1.prerelease) return -1; // Prerelease is older than stable
1034
+ if (n2.prerelease) return 1; // Stable is newer than prerelease
1035
+
1036
+ return 0;
1037
+ }
1038
+ }
1039
+
1040
+ module.exports = { Manifest };