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.
- package/.claude-plugin/marketplace.json +77 -0
- package/AGENTS.md +12 -0
- package/LICENSE +30 -0
- package/README.md +109 -0
- package/README_CN.md +108 -0
- package/package.json +110 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/SKILL.md +6 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-01-init.md +137 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-02-domain-analysis.md +229 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-03-competitive-landscape.md +238 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-04-regulatory-focus.md +206 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-05-technical-trends.md +234 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/domain-steps/step-06-research-synthesis.md +444 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/research.template.md +29 -0
- package/src/bmm-skills/1-analysis/research/scm-domain-research/workflow.md +51 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/SKILL.md +6 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/research.template.md +29 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-01-init.md +184 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-02-customer-behavior.md +239 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-03-customer-pain-points.md +251 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-04-customer-decisions.md +261 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-05-competitive-analysis.md +173 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/steps/step-06-research-completion.md +478 -0
- package/src/bmm-skills/1-analysis/research/scm-market-research/workflow.md +51 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/SKILL.md +6 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/research.template.md +29 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-01-init.md +137 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-02-technical-overview.md +239 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-03-integration-patterns.md +248 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-04-architectural-patterns.md +202 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-05-implementation-research.md +233 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/technical-steps/step-06-research-synthesis.md +487 -0
- package/src/bmm-skills/1-analysis/research/scm-technical-research/workflow.md +52 -0
- package/src/bmm-skills/1-analysis/scm-agent-analyst/SKILL.md +59 -0
- package/src/bmm-skills/1-analysis/scm-agent-analyst/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/SKILL.md +57 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/explain-concept.md +20 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/mermaid-gen.md +20 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/validate-doc.md +19 -0
- package/src/bmm-skills/1-analysis/scm-agent-tech-writer/write-document.md +20 -0
- package/src/bmm-skills/1-analysis/scm-document-project/SKILL.md +6 -0
- package/src/bmm-skills/1-analysis/scm-document-project/checklist.md +245 -0
- package/src/bmm-skills/1-analysis/scm-document-project/documentation-requirements.csv +12 -0
- package/src/bmm-skills/1-analysis/scm-document-project/instructions.md +128 -0
- package/src/bmm-skills/1-analysis/scm-document-project/templates/deep-dive-template.md +345 -0
- package/src/bmm-skills/1-analysis/scm-document-project/templates/index-template.md +169 -0
- package/src/bmm-skills/1-analysis/scm-document-project/templates/project-overview-template.md +103 -0
- package/src/bmm-skills/1-analysis/scm-document-project/templates/project-scan-report-schema.json +160 -0
- package/src/bmm-skills/1-analysis/scm-document-project/templates/source-tree-template.md +135 -0
- package/src/bmm-skills/1-analysis/scm-document-project/workflow.md +25 -0
- package/src/bmm-skills/1-analysis/scm-document-project/workflows/deep-dive-instructions.md +299 -0
- package/src/bmm-skills/1-analysis/scm-document-project/workflows/deep-dive-workflow.md +34 -0
- package/src/bmm-skills/1-analysis/scm-document-project/workflows/full-scan-instructions.md +1107 -0
- package/src/bmm-skills/1-analysis/scm-document-project/workflows/full-scan-workflow.md +34 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/SKILL.md +96 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/agents/artifact-analyzer.md +60 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/agents/web-researcher.md +49 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/assets/prfaq-template.md +62 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/references/customer-faq.md +55 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/references/internal-faq.md +51 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/references/press-release.md +60 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/references/verdict.md +79 -0
- package/src/bmm-skills/1-analysis/scm-prfaq/scm-manifest.json +16 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/SKILL.md +82 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/agents/artifact-analyzer.md +60 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/agents/opportunity-reviewer.md +44 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/agents/skeptic-reviewer.md +44 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/agents/web-researcher.md +49 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/prompts/contextual-discovery.md +57 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/prompts/draft-and-review.md +86 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/prompts/finalize.md +75 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/prompts/guided-elicitation.md +70 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/resources/brief-template.md +60 -0
- package/src/bmm-skills/1-analysis/scm-product-brief/scm-manifest.json +17 -0
- package/src/bmm-skills/2-plan-workflows/scm-agent-pm/SKILL.md +59 -0
- package/src/bmm-skills/2-plan-workflows/scm-agent-pm/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/2-plan-workflows/scm-agent-ux-designer/SKILL.md +55 -0
- package/src/bmm-skills/2-plan-workflows/scm-agent-ux-designer/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/SKILL.md +6 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/domain-complexity.csv +15 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/prd-purpose.md +197 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/data/project-types.csv +11 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-01-init.md +178 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-01b-continue.md +161 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02-discovery.md +208 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02b-vision.md +142 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-02c-executive-summary.md +158 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-03-success.md +214 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-04-journeys.md +201 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-05-domain.md +194 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-06-innovation.md +211 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-07-project-type.md +222 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-08-scoping.md +216 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-09-functional.md +219 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-10-nonfunctional.md +230 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-11-polish.md +221 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/steps-c/step-12-complete.md +115 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/templates/prd-template.md +10 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-prd/workflow.md +61 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/SKILL.md +6 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-01-init.md +135 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-01b-continue.md +127 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-02-discovery.md +190 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-03-core-experience.md +217 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-04-emotional-response.md +220 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-05-inspiration.md +235 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-06-design-system.md +253 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-07-defining-experience.md +255 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-08-visual-foundation.md +225 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-09-design-directions.md +225 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-10-user-journeys.md +242 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-11-component-strategy.md +249 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-12-ux-patterns.md +238 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-13-responsive-accessibility.md +265 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/steps/step-14-complete.md +171 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/ux-design-template.md +13 -0
- package/src/bmm-skills/2-plan-workflows/scm-create-ux-design/workflow.md +35 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/SKILL.md +6 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-01-discovery.md +242 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-01b-legacy-conversion.md +204 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-02-review.md +245 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-03-edit.md +250 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/steps-e/step-e-04-complete.md +165 -0
- package/src/bmm-skills/2-plan-workflows/scm-edit-prd/workflow.md +62 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/SKILL.md +6 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/domain-complexity.csv +15 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/prd-purpose.md +197 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/data/project-types.csv +11 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-01-discovery.md +221 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-02-format-detection.md +188 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-02b-parity-check.md +206 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-03-density-validation.md +171 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-04-brief-coverage-validation.md +211 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-05-measurability-validation.md +225 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-06-traceability-validation.md +214 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-07-implementation-leakage-validation.md +202 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-08-domain-compliance-validation.md +240 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-09-project-type-validation.md +260 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-10-smart-validation.md +206 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-11-holistic-quality-validation.md +261 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-12-completeness-validation.md +239 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/steps-v/step-v-13-report-complete.md +229 -0
- package/src/bmm-skills/2-plan-workflows/scm-validate-prd/workflow.md +61 -0
- package/src/bmm-skills/3-solutioning/scm-agent-architect/SKILL.md +54 -0
- package/src/bmm-skills/3-solutioning/scm-agent-architect/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/SKILL.md +6 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-01-document-discovery.md +179 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-02-prd-analysis.md +168 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +169 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-04-ux-alignment.md +129 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-05-epic-quality-review.md +241 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/steps/step-06-final-assessment.md +126 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/src/bmm-skills/3-solutioning/scm-check-implementation-readiness/workflow.md +47 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/SKILL.md +6 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/architecture-decision-template.md +12 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/data/domain-complexity.csv +13 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/data/project-types.csv +7 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-01-init.md +153 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-01b-continue.md +173 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-02-context.md +224 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-03-starter.md +329 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-04-decisions.md +318 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-05-patterns.md +359 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-06-structure.md +379 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-07-validation.md +359 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/steps/step-08-complete.md +76 -0
- package/src/bmm-skills/3-solutioning/scm-create-architecture/workflow.md +32 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/SKILL.md +6 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-01-validate-prerequisites.md +255 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-02-design-epics.md +212 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/steps/step-04-final-validation.md +131 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/templates/epics-template.md +61 -0
- package/src/bmm-skills/3-solutioning/scm-create-epics-and-stories/workflow.md +51 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/SKILL.md +6 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/project-context-template.md +21 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-01-discover.md +186 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-02-generate.md +321 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/steps/step-03-complete.md +278 -0
- package/src/bmm-skills/3-solutioning/scm-generate-project-context/workflow.md +39 -0
- package/src/bmm-skills/4-implementation/scm-agent-dev/SKILL.md +64 -0
- package/src/bmm-skills/4-implementation/scm-agent-dev/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/4-implementation/scm-agent-qa/SKILL.md +61 -0
- package/src/bmm-skills/4-implementation/scm-agent-qa/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/4-implementation/scm-agent-quick-flow-solo-dev/SKILL.md +53 -0
- package/src/bmm-skills/4-implementation/scm-agent-quick-flow-solo-dev/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/4-implementation/scm-agent-sm/SKILL.md +55 -0
- package/src/bmm-skills/4-implementation/scm-agent-sm/scm-skill-manifest.yaml +11 -0
- package/src/bmm-skills/4-implementation/scm-code-review/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-code-review/steps/step-01-gather-context.md +62 -0
- package/src/bmm-skills/4-implementation/scm-code-review/steps/step-02-review.md +34 -0
- package/src/bmm-skills/4-implementation/scm-code-review/steps/step-03-triage.md +49 -0
- package/src/bmm-skills/4-implementation/scm-code-review/steps/step-04-present.md +129 -0
- package/src/bmm-skills/4-implementation/scm-code-review/workflow.md +55 -0
- package/src/bmm-skills/4-implementation/scm-correct-course/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-correct-course/checklist.md +288 -0
- package/src/bmm-skills/4-implementation/scm-correct-course/workflow.md +267 -0
- package/src/bmm-skills/4-implementation/scm-create-story/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-create-story/checklist.md +357 -0
- package/src/bmm-skills/4-implementation/scm-create-story/discover-inputs.md +88 -0
- package/src/bmm-skills/4-implementation/scm-create-story/template.md +49 -0
- package/src/bmm-skills/4-implementation/scm-create-story/workflow.md +380 -0
- package/src/bmm-skills/4-implementation/scm-dev-story/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-dev-story/checklist.md +80 -0
- package/src/bmm-skills/4-implementation/scm-dev-story/workflow.md +450 -0
- package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/checklist.md +33 -0
- package/src/bmm-skills/4-implementation/scm-qa-generate-e2e-tests/workflow.md +136 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/spec-template.md +88 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-01-clarify-and-route.md +66 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-02-plan.md +35 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-03-implement.md +37 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-04-review.md +49 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-05-present.md +63 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/step-oneshot.md +62 -0
- package/src/bmm-skills/4-implementation/scm-quick-dev/workflow.md +79 -0
- package/src/bmm-skills/4-implementation/scm-retrospective/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-retrospective/workflow.md +1479 -0
- package/src/bmm-skills/4-implementation/scm-sprint-planning/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-sprint-planning/checklist.md +33 -0
- package/src/bmm-skills/4-implementation/scm-sprint-planning/sprint-status-template.yaml +56 -0
- package/src/bmm-skills/4-implementation/scm-sprint-planning/workflow.md +263 -0
- package/src/bmm-skills/4-implementation/scm-sprint-status/SKILL.md +6 -0
- package/src/bmm-skills/4-implementation/scm-sprint-status/workflow.md +261 -0
- package/src/bmm-skills/module-help.csv +31 -0
- package/src/bmm-skills/module.yaml +50 -0
- package/src/core-skills/module-help.csv +11 -0
- package/src/core-skills/module.yaml +25 -0
- package/src/core-skills/scm-advanced-elicitation/SKILL.md +136 -0
- package/src/core-skills/scm-advanced-elicitation/methods.csv +51 -0
- package/src/core-skills/scm-brainstorming/SKILL.md +6 -0
- package/src/core-skills/scm-brainstorming/brain-methods.csv +62 -0
- package/src/core-skills/scm-brainstorming/steps/step-01-session-setup.md +214 -0
- package/src/core-skills/scm-brainstorming/steps/step-01b-continue.md +124 -0
- package/src/core-skills/scm-brainstorming/steps/step-02a-user-selected.md +229 -0
- package/src/core-skills/scm-brainstorming/steps/step-02b-ai-recommended.md +239 -0
- package/src/core-skills/scm-brainstorming/steps/step-02c-random-selection.md +211 -0
- package/src/core-skills/scm-brainstorming/steps/step-02d-progressive-flow.md +266 -0
- package/src/core-skills/scm-brainstorming/steps/step-03-technique-execution.md +401 -0
- package/src/core-skills/scm-brainstorming/steps/step-04-idea-organization.md +305 -0
- package/src/core-skills/scm-brainstorming/template.md +15 -0
- package/src/core-skills/scm-brainstorming/workflow.md +53 -0
- package/src/core-skills/scm-distillator/SKILL.md +177 -0
- package/src/core-skills/scm-distillator/agents/distillate-compressor.md +116 -0
- package/src/core-skills/scm-distillator/agents/round-trip-reconstructor.md +68 -0
- package/src/core-skills/scm-distillator/resources/compression-rules.md +51 -0
- package/src/core-skills/scm-distillator/resources/distillate-format-reference.md +227 -0
- package/src/core-skills/scm-distillator/resources/splitting-strategy.md +78 -0
- package/src/core-skills/scm-distillator/scripts/analyze_sources.py +300 -0
- package/src/core-skills/scm-distillator/scripts/tests/test_analyze_sources.py +204 -0
- package/src/core-skills/scm-editorial-review-prose/SKILL.md +86 -0
- package/src/core-skills/scm-editorial-review-structure/SKILL.md +179 -0
- package/src/core-skills/scm-help/SKILL.md +73 -0
- package/src/core-skills/scm-index-docs/SKILL.md +66 -0
- package/src/core-skills/scm-party-mode/SKILL.md +125 -0
- package/src/core-skills/scm-review-adversarial-general/SKILL.md +37 -0
- package/src/core-skills/scm-review-edge-case-hunter/SKILL.md +67 -0
- package/src/core-skills/scm-shard-doc/SKILL.md +105 -0
- package/tools/format-workflow-md.js +263 -0
- package/tools/installer/README.md +60 -0
- package/tools/installer/cli-utils.js +181 -0
- package/tools/installer/commands/install.js +80 -0
- package/tools/installer/commands/status.js +65 -0
- package/tools/installer/commands/uninstall.js +167 -0
- package/tools/installer/core/config.js +52 -0
- package/tools/installer/core/custom-module-cache.js +260 -0
- package/tools/installer/core/existing-install.js +127 -0
- package/tools/installer/core/install-paths.js +129 -0
- package/tools/installer/core/installer.js +1790 -0
- package/tools/installer/core/manifest-generator.js +701 -0
- package/tools/installer/core/manifest.js +1040 -0
- package/tools/installer/custom-handler.js +112 -0
- package/tools/installer/external-official-modules.yaml +63 -0
- package/tools/installer/file-ops.js +204 -0
- package/tools/installer/ide/_config-driven.js +536 -0
- package/tools/installer/ide/manager.js +247 -0
- package/tools/installer/ide/platform-codes.js +37 -0
- package/tools/installer/ide/platform-codes.yaml +192 -0
- package/tools/installer/ide/shared/agent-command-generator.js +180 -0
- package/tools/installer/ide/shared/module-injections.js +136 -0
- package/tools/installer/ide/shared/path-utils.js +364 -0
- package/tools/installer/ide/shared/scm-artifacts.js +208 -0
- package/tools/installer/ide/shared/skill-manifest.js +72 -0
- package/tools/installer/ide/templates/agent-command-template.md +14 -0
- package/tools/installer/ide/templates/combined/antigravity.md +8 -0
- package/tools/installer/ide/templates/combined/default-agent.md +15 -0
- package/tools/installer/ide/templates/combined/default-task.md +10 -0
- package/tools/installer/ide/templates/combined/default-tool.md +10 -0
- package/tools/installer/ide/templates/combined/default-workflow.md +6 -0
- package/tools/installer/ide/templates/combined/gemini-agent.toml +14 -0
- package/tools/installer/ide/templates/combined/gemini-task.toml +11 -0
- package/tools/installer/ide/templates/combined/gemini-tool.toml +11 -0
- package/tools/installer/ide/templates/combined/gemini-workflow-yaml.toml +16 -0
- package/tools/installer/ide/templates/combined/gemini-workflow.toml +14 -0
- package/tools/installer/ide/templates/combined/kiro-agent.md +16 -0
- package/tools/installer/ide/templates/combined/kiro-task.md +9 -0
- package/tools/installer/ide/templates/combined/kiro-tool.md +9 -0
- package/tools/installer/ide/templates/combined/kiro-workflow.md +7 -0
- package/tools/installer/ide/templates/combined/opencode-agent.md +15 -0
- package/tools/installer/ide/templates/combined/opencode-task.md +13 -0
- package/tools/installer/ide/templates/combined/opencode-tool.md +13 -0
- package/tools/installer/ide/templates/combined/opencode-workflow-yaml.md +16 -0
- package/tools/installer/ide/templates/combined/opencode-workflow.md +16 -0
- package/tools/installer/ide/templates/combined/rovodev.md +9 -0
- package/tools/installer/ide/templates/combined/trae.md +9 -0
- package/tools/installer/ide/templates/combined/windsurf-workflow.md +10 -0
- package/tools/installer/ide/templates/split/.gitkeep +0 -0
- package/tools/installer/install-messages.yaml +35 -0
- package/tools/installer/message-loader.js +83 -0
- package/tools/installer/modules/custom-modules.js +197 -0
- package/tools/installer/modules/external-manager.js +354 -0
- package/tools/installer/modules/official-modules.js +2043 -0
- package/tools/installer/project-root.js +77 -0
- package/tools/installer/prompts.js +809 -0
- package/tools/installer/scm-cli.js +108 -0
- package/tools/installer/ui.js +1683 -0
- package/tools/installer/yaml-format.js +245 -0
- package/tools/javascript-conventions.md +5 -0
- package/tools/migrate-custom-module-paths.js +124 -0
- package/tools/platform-codes.yaml +169 -0
- package/tools/validate-skills.js +736 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
const os = require('node:os');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const yaml = require('yaml');
|
|
5
|
+
const prompts = require('../prompts');
|
|
6
|
+
const csv = require('csv-parse/sync');
|
|
7
|
+
const { SCM_FOLDER_NAME } = require('./shared/path-utils');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Config-driven IDE setup handler
|
|
11
|
+
*
|
|
12
|
+
* This class provides a standardized way to install SCM artifacts to IDEs
|
|
13
|
+
* based on configuration in platform-codes.yaml. It eliminates the need for
|
|
14
|
+
* individual installer files for each IDE.
|
|
15
|
+
*
|
|
16
|
+
* Features:
|
|
17
|
+
* - Config-driven from platform-codes.yaml
|
|
18
|
+
* - Verbatim skill installation from skill-manifest.csv
|
|
19
|
+
* - Legacy directory cleanup and IDE-specific marker removal
|
|
20
|
+
*/
|
|
21
|
+
class ConfigDrivenIdeSetup {
|
|
22
|
+
constructor(platformCode, platformConfig) {
|
|
23
|
+
this.name = platformCode;
|
|
24
|
+
this.displayName = platformConfig.name || platformCode;
|
|
25
|
+
this.preferred = platformConfig.preferred || false;
|
|
26
|
+
this.platformConfig = platformConfig;
|
|
27
|
+
this.installerConfig = platformConfig.installer || null;
|
|
28
|
+
this.scmFolderName = SCM_FOLDER_NAME;
|
|
29
|
+
|
|
30
|
+
// Set configDir from target_dir so detect() works
|
|
31
|
+
this.configDir = this.installerConfig?.target_dir || null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setBmadFolderName(scmFolderName) {
|
|
35
|
+
this.scmFolderName = scmFolderName;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Detect whether this IDE already has configuration in the project.
|
|
40
|
+
* Checks for scm-prefixed entries in target_dir.
|
|
41
|
+
* @param {string} projectDir - Project directory
|
|
42
|
+
* @returns {Promise<boolean>}
|
|
43
|
+
*/
|
|
44
|
+
async detect(projectDir) {
|
|
45
|
+
if (!this.configDir) return false;
|
|
46
|
+
|
|
47
|
+
const dir = path.join(projectDir || process.cwd(), this.configDir);
|
|
48
|
+
if (await fs.pathExists(dir)) {
|
|
49
|
+
try {
|
|
50
|
+
const entries = await fs.readdir(dir);
|
|
51
|
+
return entries.some((e) => typeof e === 'string' && e.startsWith('scm'));
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Main setup method - called by IdeManager
|
|
61
|
+
* @param {string} projectDir - Project directory
|
|
62
|
+
* @param {string} scmDir - SCM installation directory
|
|
63
|
+
* @param {Object} options - Setup options
|
|
64
|
+
* @returns {Promise<Object>} Setup result
|
|
65
|
+
*/
|
|
66
|
+
async setup(projectDir, scmDir, options = {}) {
|
|
67
|
+
// Check for SCM files in ancestor directories that would cause duplicates
|
|
68
|
+
if (this.installerConfig?.ancestor_conflict_check) {
|
|
69
|
+
const conflict = await this.findAncestorConflict(projectDir);
|
|
70
|
+
if (conflict) {
|
|
71
|
+
await prompts.log.error(
|
|
72
|
+
`Found existing SCM skills in ancestor installation: ${conflict}\n` +
|
|
73
|
+
` ${this.name} inherits skills from parent directories, so this would cause duplicates.\n` +
|
|
74
|
+
` Please remove the SCM files from that directory first:\n` +
|
|
75
|
+
` rm -rf "${conflict}"/scm*`,
|
|
76
|
+
);
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
reason: 'ancestor-conflict',
|
|
80
|
+
error: `Ancestor conflict: ${conflict}`,
|
|
81
|
+
conflictDir: conflict,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
|
|
87
|
+
|
|
88
|
+
// Clean up any old SCM installation first
|
|
89
|
+
await this.cleanup(projectDir, options);
|
|
90
|
+
|
|
91
|
+
if (!this.installerConfig) {
|
|
92
|
+
return { success: false, reason: 'no-config' };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (this.installerConfig.target_dir) {
|
|
96
|
+
return this.installToTarget(projectDir, scmDir, this.installerConfig, options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { success: false, reason: 'invalid-config' };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Install to a single target directory
|
|
104
|
+
* @param {string} projectDir - Project directory
|
|
105
|
+
* @param {string} scmDir - SCM installation directory
|
|
106
|
+
* @param {Object} config - Installation configuration
|
|
107
|
+
* @param {Object} options - Setup options
|
|
108
|
+
* @returns {Promise<Object>} Installation result
|
|
109
|
+
*/
|
|
110
|
+
async installToTarget(projectDir, scmDir, config, options) {
|
|
111
|
+
const { target_dir } = config;
|
|
112
|
+
const targetPath = path.join(projectDir, target_dir);
|
|
113
|
+
await fs.ensureDir(targetPath);
|
|
114
|
+
|
|
115
|
+
this.skillWriteTracker = new Set();
|
|
116
|
+
const results = { skills: 0 };
|
|
117
|
+
|
|
118
|
+
results.skills = await this.installVerbatimSkills(projectDir, scmDir, targetPath, config);
|
|
119
|
+
results.skillDirectories = this.skillWriteTracker.size;
|
|
120
|
+
|
|
121
|
+
await this.printSummary(results, target_dir, options);
|
|
122
|
+
this.skillWriteTracker = null;
|
|
123
|
+
return { success: true, results };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Install verbatim native SKILL.md directories from skill-manifest.csv.
|
|
128
|
+
* Copies the entire source directory as-is into the IDE skill directory.
|
|
129
|
+
* The source SKILL.md is used directly — no frontmatter transformation or file generation.
|
|
130
|
+
* @param {string} projectDir - Project directory
|
|
131
|
+
* @param {string} scmDir - SCM installation directory
|
|
132
|
+
* @param {string} targetPath - Target skills directory
|
|
133
|
+
* @param {Object} config - Installation configuration
|
|
134
|
+
* @returns {Promise<number>} Count of skills installed
|
|
135
|
+
*/
|
|
136
|
+
async installVerbatimSkills(projectDir, scmDir, targetPath, config) {
|
|
137
|
+
const scmFolderName = path.basename(scmDir);
|
|
138
|
+
const scmPrefix = scmFolderName + '/';
|
|
139
|
+
const csvPath = path.join(scmDir, '_config', 'skill-manifest.csv');
|
|
140
|
+
|
|
141
|
+
if (!(await fs.pathExists(csvPath))) return 0;
|
|
142
|
+
|
|
143
|
+
const csvContent = await fs.readFile(csvPath, 'utf8');
|
|
144
|
+
const records = csv.parse(csvContent, {
|
|
145
|
+
columns: true,
|
|
146
|
+
skip_empty_lines: true,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
let count = 0;
|
|
150
|
+
|
|
151
|
+
for (const record of records) {
|
|
152
|
+
const canonicalId = record.canonicalId;
|
|
153
|
+
if (!canonicalId) continue;
|
|
154
|
+
|
|
155
|
+
// Derive source directory from path column
|
|
156
|
+
// path is like "_scm/bmm/workflows/scm-quick-flow/scm-quick-dev-new-preview/SKILL.md"
|
|
157
|
+
// Strip scmFolderName prefix and join with scmDir, then get dirname
|
|
158
|
+
const relativePath = record.path.startsWith(scmPrefix) ? record.path.slice(scmPrefix.length) : record.path;
|
|
159
|
+
const sourceFile = path.join(scmDir, relativePath);
|
|
160
|
+
const sourceDir = path.dirname(sourceFile);
|
|
161
|
+
|
|
162
|
+
if (!(await fs.pathExists(sourceDir))) continue;
|
|
163
|
+
|
|
164
|
+
// Clean target before copy to prevent stale files
|
|
165
|
+
const skillDir = path.join(targetPath, canonicalId);
|
|
166
|
+
await fs.remove(skillDir);
|
|
167
|
+
await fs.ensureDir(skillDir);
|
|
168
|
+
this.skillWriteTracker?.add(canonicalId);
|
|
169
|
+
|
|
170
|
+
// Copy all skill files, filtering OS/editor artifacts recursively
|
|
171
|
+
const skipPatterns = new Set(['.DS_Store', 'Thumbs.db', 'desktop.ini']);
|
|
172
|
+
const skipSuffixes = ['~', '.swp', '.swo', '.bak'];
|
|
173
|
+
const filter = (src) => {
|
|
174
|
+
const name = path.basename(src);
|
|
175
|
+
if (src === sourceDir) return true;
|
|
176
|
+
if (skipPatterns.has(name)) return false;
|
|
177
|
+
if (name.startsWith('.') && name !== '.gitkeep') return false;
|
|
178
|
+
if (skipSuffixes.some((s) => name.endsWith(s))) return false;
|
|
179
|
+
return true;
|
|
180
|
+
};
|
|
181
|
+
await fs.copy(sourceDir, skillDir, { filter });
|
|
182
|
+
|
|
183
|
+
count++;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Post-install cleanup: remove _scm/ directories for skills with install_to_scm === "false"
|
|
187
|
+
for (const record of records) {
|
|
188
|
+
if (record.install_to_scm === 'false') {
|
|
189
|
+
const relativePath = record.path.startsWith(scmPrefix) ? record.path.slice(scmPrefix.length) : record.path;
|
|
190
|
+
const sourceFile = path.join(scmDir, relativePath);
|
|
191
|
+
const sourceDir = path.dirname(sourceFile);
|
|
192
|
+
if (await fs.pathExists(sourceDir)) {
|
|
193
|
+
await fs.remove(sourceDir);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return count;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Print installation summary
|
|
203
|
+
* @param {Object} results - Installation results
|
|
204
|
+
* @param {string} targetDir - Target directory (relative)
|
|
205
|
+
*/
|
|
206
|
+
async printSummary(results, targetDir, options = {}) {
|
|
207
|
+
if (options.silent) return;
|
|
208
|
+
const count = results.skillDirectories || results.skills || 0;
|
|
209
|
+
if (count > 0) {
|
|
210
|
+
await prompts.log.success(`${this.name} configured: ${count} skills → ${targetDir}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Cleanup IDE configuration
|
|
216
|
+
* @param {string} projectDir - Project directory
|
|
217
|
+
*/
|
|
218
|
+
async cleanup(projectDir, options = {}) {
|
|
219
|
+
// Migrate legacy target directories (e.g. .opencode/agent → .opencode/agents)
|
|
220
|
+
if (this.installerConfig?.legacy_targets) {
|
|
221
|
+
if (!options.silent) await prompts.log.message(' Migrating legacy directories...');
|
|
222
|
+
for (const legacyDir of this.installerConfig.legacy_targets) {
|
|
223
|
+
if (this.isGlobalPath(legacyDir)) {
|
|
224
|
+
await this.warnGlobalLegacy(legacyDir, options);
|
|
225
|
+
} else {
|
|
226
|
+
await this.cleanupTarget(projectDir, legacyDir, options);
|
|
227
|
+
await this.removeEmptyParents(projectDir, legacyDir);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Strip SCM markers from copilot-instructions.md if present
|
|
233
|
+
if (this.name === 'github-copilot') {
|
|
234
|
+
await this.cleanupCopilotInstructions(projectDir, options);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Strip SCM modes from .kilocodemodes if present
|
|
238
|
+
if (this.name === 'kilo') {
|
|
239
|
+
await this.cleanupKiloModes(projectDir, options);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Strip SCM entries from .rovodev/prompts.yml if present
|
|
243
|
+
if (this.name === 'rovo-dev') {
|
|
244
|
+
await this.cleanupRovoDevPrompts(projectDir, options);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Clean target directory
|
|
248
|
+
if (this.installerConfig?.target_dir) {
|
|
249
|
+
await this.cleanupTarget(projectDir, this.installerConfig.target_dir, options);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Check if a path is global (starts with ~ or is absolute)
|
|
255
|
+
* @param {string} p - Path to check
|
|
256
|
+
* @returns {boolean}
|
|
257
|
+
*/
|
|
258
|
+
isGlobalPath(p) {
|
|
259
|
+
return p.startsWith('~') || path.isAbsolute(p);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Warn about stale SCM files in a global legacy directory (never auto-deletes)
|
|
264
|
+
* @param {string} legacyDir - Legacy directory path (may start with ~)
|
|
265
|
+
* @param {Object} options - Options (silent, etc.)
|
|
266
|
+
*/
|
|
267
|
+
async warnGlobalLegacy(legacyDir, options = {}) {
|
|
268
|
+
try {
|
|
269
|
+
const expanded = legacyDir.startsWith('~/')
|
|
270
|
+
? path.join(os.homedir(), legacyDir.slice(2))
|
|
271
|
+
: legacyDir === '~'
|
|
272
|
+
? os.homedir()
|
|
273
|
+
: legacyDir;
|
|
274
|
+
|
|
275
|
+
if (!(await fs.pathExists(expanded))) return;
|
|
276
|
+
|
|
277
|
+
const entries = await fs.readdir(expanded);
|
|
278
|
+
const scmFiles = entries.filter((e) => typeof e === 'string' && e.startsWith('scm'));
|
|
279
|
+
|
|
280
|
+
if (scmFiles.length > 0 && !options.silent) {
|
|
281
|
+
await prompts.log.warn(`Found ${scmFiles.length} stale SCM file(s) in ${expanded}. Remove manually: rm ${expanded}/scm-*`);
|
|
282
|
+
}
|
|
283
|
+
} catch {
|
|
284
|
+
// Errors reading global paths are silently ignored
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Cleanup a specific target directory
|
|
290
|
+
* @param {string} projectDir - Project directory
|
|
291
|
+
* @param {string} targetDir - Target directory to clean
|
|
292
|
+
*/
|
|
293
|
+
async cleanupTarget(projectDir, targetDir, options = {}) {
|
|
294
|
+
const targetPath = path.join(projectDir, targetDir);
|
|
295
|
+
|
|
296
|
+
if (!(await fs.pathExists(targetPath))) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Remove all scm* files
|
|
301
|
+
let entries;
|
|
302
|
+
try {
|
|
303
|
+
entries = await fs.readdir(targetPath);
|
|
304
|
+
} catch {
|
|
305
|
+
// Directory exists but can't be read - skip cleanup
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (!entries || !Array.isArray(entries)) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let removedCount = 0;
|
|
314
|
+
|
|
315
|
+
for (const entry of entries) {
|
|
316
|
+
if (!entry || typeof entry !== 'string') {
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (entry.startsWith('scm') && !entry.startsWith('scm-os-')) {
|
|
320
|
+
const entryPath = path.join(targetPath, entry);
|
|
321
|
+
try {
|
|
322
|
+
await fs.remove(entryPath);
|
|
323
|
+
removedCount++;
|
|
324
|
+
} catch {
|
|
325
|
+
// Skip entries that can't be removed (broken symlinks, permission errors)
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (removedCount > 0 && !options.silent) {
|
|
331
|
+
await prompts.log.message(` Cleaned ${removedCount} SCM files from ${targetDir}`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Remove empty directory after cleanup
|
|
335
|
+
if (removedCount > 0) {
|
|
336
|
+
try {
|
|
337
|
+
const remaining = await fs.readdir(targetPath);
|
|
338
|
+
if (remaining.length === 0) {
|
|
339
|
+
await fs.remove(targetPath);
|
|
340
|
+
}
|
|
341
|
+
} catch {
|
|
342
|
+
// Directory may already be gone or in use — skip
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Strip SCM-owned content from .github/copilot-instructions.md.
|
|
349
|
+
* The old custom installer injected content between <!-- SCM:START --> and <!-- SCM:END --> markers.
|
|
350
|
+
* Deletes the file if nothing remains. Restores .bak backup if one exists.
|
|
351
|
+
*/
|
|
352
|
+
async cleanupCopilotInstructions(projectDir, options = {}) {
|
|
353
|
+
const filePath = path.join(projectDir, '.github', 'copilot-instructions.md');
|
|
354
|
+
|
|
355
|
+
if (!(await fs.pathExists(filePath))) return;
|
|
356
|
+
|
|
357
|
+
try {
|
|
358
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
359
|
+
const startIdx = content.indexOf('<!-- SCM:START -->');
|
|
360
|
+
const endIdx = content.indexOf('<!-- SCM:END -->');
|
|
361
|
+
|
|
362
|
+
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return;
|
|
363
|
+
|
|
364
|
+
const cleaned = content.slice(0, startIdx) + content.slice(endIdx + '<!-- SCM:END -->'.length);
|
|
365
|
+
|
|
366
|
+
if (cleaned.trim().length === 0) {
|
|
367
|
+
await fs.remove(filePath);
|
|
368
|
+
const backupPath = `${filePath}.bak`;
|
|
369
|
+
if (await fs.pathExists(backupPath)) {
|
|
370
|
+
await fs.rename(backupPath, filePath);
|
|
371
|
+
if (!options.silent) await prompts.log.message(' Restored copilot-instructions.md from backup');
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
await fs.writeFile(filePath, cleaned, 'utf8');
|
|
375
|
+
const backupPath = `${filePath}.bak`;
|
|
376
|
+
if (await fs.pathExists(backupPath)) await fs.remove(backupPath);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (!options.silent) await prompts.log.message(' Cleaned SCM markers from copilot-instructions.md');
|
|
380
|
+
} catch {
|
|
381
|
+
if (!options.silent) await prompts.log.warn(' Warning: Could not clean SCM markers from copilot-instructions.md');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Strip SCM-owned modes from .kilocodemodes.
|
|
387
|
+
* The old custom kilo.js installer added modes with slug starting with 'scm-'.
|
|
388
|
+
* Parses YAML, filters out SCM modes, rewrites. Leaves file as-is on parse failure.
|
|
389
|
+
*/
|
|
390
|
+
async cleanupKiloModes(projectDir, options = {}) {
|
|
391
|
+
const kiloModesPath = path.join(projectDir, '.kilocodemodes');
|
|
392
|
+
|
|
393
|
+
if (!(await fs.pathExists(kiloModesPath))) return;
|
|
394
|
+
|
|
395
|
+
const content = await fs.readFile(kiloModesPath, 'utf8');
|
|
396
|
+
|
|
397
|
+
let config;
|
|
398
|
+
try {
|
|
399
|
+
config = yaml.parse(content) || {};
|
|
400
|
+
} catch {
|
|
401
|
+
if (!options.silent) await prompts.log.warn(' Warning: Could not parse .kilocodemodes for cleanup');
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (!Array.isArray(config.customModes)) return;
|
|
406
|
+
|
|
407
|
+
const originalCount = config.customModes.length;
|
|
408
|
+
config.customModes = config.customModes.filter((mode) => mode && (!mode.slug || !mode.slug.startsWith('scm-')));
|
|
409
|
+
const removedCount = originalCount - config.customModes.length;
|
|
410
|
+
|
|
411
|
+
if (removedCount > 0) {
|
|
412
|
+
try {
|
|
413
|
+
await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 }));
|
|
414
|
+
if (!options.silent) await prompts.log.message(` Removed ${removedCount} SCM modes from .kilocodemodes`);
|
|
415
|
+
} catch {
|
|
416
|
+
if (!options.silent) await prompts.log.warn(' Warning: Could not write .kilocodemodes during cleanup');
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Strip SCM-owned entries from .rovodev/prompts.yml.
|
|
423
|
+
* The old custom rovodev.js installer registered workflows in prompts.yml.
|
|
424
|
+
* Parses YAML, filters out entries with name starting with 'scm-', rewrites.
|
|
425
|
+
* Removes the file if no entries remain.
|
|
426
|
+
*/
|
|
427
|
+
async cleanupRovoDevPrompts(projectDir, options = {}) {
|
|
428
|
+
const promptsPath = path.join(projectDir, '.rovodev', 'prompts.yml');
|
|
429
|
+
|
|
430
|
+
if (!(await fs.pathExists(promptsPath))) return;
|
|
431
|
+
|
|
432
|
+
const content = await fs.readFile(promptsPath, 'utf8');
|
|
433
|
+
|
|
434
|
+
let config;
|
|
435
|
+
try {
|
|
436
|
+
config = yaml.parse(content) || {};
|
|
437
|
+
} catch {
|
|
438
|
+
if (!options.silent) await prompts.log.warn(' Warning: Could not parse prompts.yml for cleanup');
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (!Array.isArray(config.prompts)) return;
|
|
443
|
+
|
|
444
|
+
const originalCount = config.prompts.length;
|
|
445
|
+
config.prompts = config.prompts.filter((entry) => entry && (!entry.name || !entry.name.startsWith('scm-')));
|
|
446
|
+
const removedCount = originalCount - config.prompts.length;
|
|
447
|
+
|
|
448
|
+
if (removedCount > 0) {
|
|
449
|
+
try {
|
|
450
|
+
if (config.prompts.length === 0) {
|
|
451
|
+
await fs.remove(promptsPath);
|
|
452
|
+
} else {
|
|
453
|
+
await fs.writeFile(promptsPath, yaml.stringify(config, { lineWidth: 0 }));
|
|
454
|
+
}
|
|
455
|
+
if (!options.silent) await prompts.log.message(` Removed ${removedCount} SCM entries from prompts.yml`);
|
|
456
|
+
} catch {
|
|
457
|
+
if (!options.silent) await prompts.log.warn(' Warning: Could not write prompts.yml during cleanup');
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Check ancestor directories for existing SCM files in the same target_dir.
|
|
464
|
+
* IDEs like Claude Code inherit commands from parent directories, so an existing
|
|
465
|
+
* installation in an ancestor would cause duplicate commands.
|
|
466
|
+
* @param {string} projectDir - Project directory being installed to
|
|
467
|
+
* @returns {Promise<string|null>} Path to conflicting directory, or null if clean
|
|
468
|
+
*/
|
|
469
|
+
async findAncestorConflict(projectDir) {
|
|
470
|
+
const targetDir = this.installerConfig?.target_dir;
|
|
471
|
+
if (!targetDir) return null;
|
|
472
|
+
|
|
473
|
+
const resolvedProject = await fs.realpath(path.resolve(projectDir));
|
|
474
|
+
let current = path.dirname(resolvedProject);
|
|
475
|
+
const root = path.parse(current).root;
|
|
476
|
+
|
|
477
|
+
while (current !== root && current.length > root.length) {
|
|
478
|
+
const candidatePath = path.join(current, targetDir);
|
|
479
|
+
try {
|
|
480
|
+
if (await fs.pathExists(candidatePath)) {
|
|
481
|
+
const entries = await fs.readdir(candidatePath);
|
|
482
|
+
const hasBmad = entries.some(
|
|
483
|
+
(e) => typeof e === 'string' && e.toLowerCase().startsWith('scm') && !e.toLowerCase().startsWith('scm-os-'),
|
|
484
|
+
);
|
|
485
|
+
if (hasBmad) {
|
|
486
|
+
return candidatePath;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
} catch {
|
|
490
|
+
// Can't read directory — skip
|
|
491
|
+
}
|
|
492
|
+
current = path.dirname(current);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Walk up ancestor directories from relativeDir toward projectDir, removing each if empty
|
|
500
|
+
* Stops at projectDir boundary — never removes projectDir itself
|
|
501
|
+
* @param {string} projectDir - Project root (boundary)
|
|
502
|
+
* @param {string} relativeDir - Relative directory to start from
|
|
503
|
+
*/
|
|
504
|
+
async removeEmptyParents(projectDir, relativeDir) {
|
|
505
|
+
const resolvedProject = path.resolve(projectDir);
|
|
506
|
+
let current = relativeDir;
|
|
507
|
+
let last = null;
|
|
508
|
+
while (current && current !== '.' && current !== last) {
|
|
509
|
+
last = current;
|
|
510
|
+
const fullPath = path.resolve(projectDir, current);
|
|
511
|
+
// Boundary guard: never traverse outside projectDir
|
|
512
|
+
if (!fullPath.startsWith(resolvedProject + path.sep) && fullPath !== resolvedProject) break;
|
|
513
|
+
try {
|
|
514
|
+
if (!(await fs.pathExists(fullPath))) {
|
|
515
|
+
// Dir already gone — advance current; last is reset at top of next iteration
|
|
516
|
+
current = path.dirname(current);
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
const remaining = await fs.readdir(fullPath);
|
|
520
|
+
if (remaining.length > 0) break;
|
|
521
|
+
await fs.rmdir(fullPath);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
// ENOTEMPTY: TOCTOU race (file added between readdir and rmdir) — skip level, continue upward
|
|
524
|
+
// ENOENT: dir removed by another process between pathExists and rmdir — skip level, continue upward
|
|
525
|
+
if (error.code === 'ENOTEMPTY' || error.code === 'ENOENT') {
|
|
526
|
+
current = path.dirname(current);
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
break; // fatal error (e.g. EACCES) — stop upward walk
|
|
530
|
+
}
|
|
531
|
+
current = path.dirname(current);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
module.exports = { ConfigDrivenIdeSetup };
|