specweave 0.4.0 ā 0.6.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/README.md +325 -0
- package/.claude-plugin/marketplace.json +210 -0
- package/CLAUDE.md +1000 -252
- package/README.md +273 -180
- package/bin/install-agents.sh +1 -1
- package/bin/install-commands.sh +66 -14
- package/bin/install-hooks.sh +1 -1
- package/bin/install-skills.sh +1 -1
- package/bin/specweave.js +18 -0
- package/dist/adapters/adapter-base.d.ts +21 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -1
- package/dist/adapters/adapter-base.js +28 -0
- package/dist/adapters/adapter-base.js.map +1 -1
- package/dist/adapters/adapter-interface.d.ts +41 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.d.ts +85 -11
- package/dist/adapters/claude/adapter.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.js +305 -37
- package/dist/adapters/claude/adapter.js.map +1 -1
- package/dist/adapters/copilot/adapter.d.ts +45 -2
- package/dist/adapters/copilot/adapter.d.ts.map +1 -1
- package/dist/adapters/copilot/adapter.js +226 -4
- package/dist/adapters/copilot/adapter.js.map +1 -1
- package/dist/adapters/cursor/adapter.d.ts +54 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -1
- package/dist/adapters/cursor/adapter.js +192 -0
- package/dist/adapters/cursor/adapter.js.map +1 -1
- package/dist/adapters/generic/adapter.d.ts +43 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -1
- package/dist/adapters/generic/adapter.js +163 -0
- package/dist/adapters/generic/adapter.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +392 -123
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/install.d.ts +2 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +28 -25
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/list.js +26 -24
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/plugin.d.ts +43 -0
- package/dist/cli/commands/plugin.d.ts.map +1 -0
- package/dist/cli/commands/plugin.js +307 -0
- package/dist/cli/commands/plugin.js.map +1 -0
- package/dist/core/i18n/language-detector.d.ts +29 -0
- package/dist/core/i18n/language-detector.d.ts.map +1 -0
- package/dist/core/i18n/language-detector.js +143 -0
- package/dist/core/i18n/language-detector.js.map +1 -0
- package/dist/core/i18n/language-manager.d.ts +101 -0
- package/dist/core/i18n/language-manager.d.ts.map +1 -0
- package/dist/core/i18n/language-manager.js +232 -0
- package/dist/core/i18n/language-manager.js.map +1 -0
- package/dist/core/i18n/language-registry.d.ts +44 -0
- package/dist/core/i18n/language-registry.d.ts.map +1 -0
- package/dist/core/i18n/language-registry.js +234 -0
- package/dist/core/i18n/language-registry.js.map +1 -0
- package/dist/core/i18n/locale-manager.d.ts +62 -0
- package/dist/core/i18n/locale-manager.d.ts.map +1 -0
- package/dist/core/i18n/locale-manager.js +137 -0
- package/dist/core/i18n/locale-manager.js.map +1 -0
- package/dist/core/i18n/system-prompt-injector.d.ts +33 -0
- package/dist/core/i18n/system-prompt-injector.d.ts.map +1 -0
- package/dist/core/i18n/system-prompt-injector.js +131 -0
- package/dist/core/i18n/system-prompt-injector.js.map +1 -0
- package/dist/core/i18n/types.d.ts +151 -0
- package/dist/core/i18n/types.d.ts.map +1 -0
- package/dist/core/i18n/types.js +11 -0
- package/dist/core/i18n/types.js.map +1 -0
- package/dist/core/increment-status.d.ts +72 -0
- package/dist/core/increment-status.d.ts.map +1 -0
- package/dist/core/increment-status.js +227 -0
- package/dist/core/increment-status.js.map +1 -0
- package/dist/core/plugin-detector.d.ts +96 -0
- package/dist/core/plugin-detector.d.ts.map +1 -0
- package/dist/core/plugin-detector.js +349 -0
- package/dist/core/plugin-detector.js.map +1 -0
- package/dist/core/plugin-loader.d.ts +131 -0
- package/dist/core/plugin-loader.d.ts.map +1 -0
- package/dist/core/plugin-loader.js +421 -0
- package/dist/core/plugin-loader.js.map +1 -0
- package/dist/core/plugin-manager.d.ts +144 -0
- package/dist/core/plugin-manager.d.ts.map +1 -0
- package/dist/core/plugin-manager.js +393 -0
- package/dist/core/plugin-manager.js.map +1 -0
- package/dist/core/schemas/plugin-manifest.schema.json +253 -0
- package/dist/core/types/config.d.ts +51 -0
- package/dist/core/types/config.d.ts.map +1 -0
- package/dist/core/types/config.js +21 -0
- package/dist/core/types/config.js.map +1 -0
- package/dist/core/types/plugin.d.ts +283 -0
- package/dist/core/types/plugin.d.ts.map +1 -0
- package/dist/core/types/plugin.js +49 -0
- package/dist/core/types/plugin.js.map +1 -0
- package/dist/hooks/lib/sync-living-docs.d.ts +27 -0
- package/dist/hooks/lib/sync-living-docs.d.ts.map +1 -0
- package/dist/hooks/lib/sync-living-docs.js +116 -0
- package/dist/hooks/lib/sync-living-docs.js.map +1 -0
- package/dist/hooks/lib/translate-living-docs.d.ts +13 -0
- package/dist/hooks/lib/translate-living-docs.d.ts.map +1 -0
- package/dist/hooks/lib/translate-living-docs.js +166 -0
- package/dist/hooks/lib/translate-living-docs.js.map +1 -0
- package/dist/hooks/lib/update-tasks-md.d.ts +29 -0
- package/dist/hooks/lib/update-tasks-md.d.ts.map +1 -0
- package/dist/hooks/lib/update-tasks-md.js +203 -0
- package/dist/hooks/lib/update-tasks-md.js.map +1 -0
- package/dist/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/integrations/jira/jira-mapper.d.ts +2 -2
- package/dist/integrations/jira/jira-mapper.js +2 -2
- package/dist/integrations/jira/jira-mapper.js.map +1 -1
- package/dist/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +108 -0
- package/dist/locales/en/cli.json +269 -0
- package/dist/locales/en/errors.json +7 -0
- package/dist/locales/en/templates.json +6 -0
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +41 -0
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +108 -0
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +108 -0
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +108 -0
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +108 -0
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +269 -0
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +108 -0
- package/dist/plugins/specweave-github/lib/github-client.d.ts +86 -0
- package/dist/plugins/specweave-github/lib/github-client.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client.js +275 -0
- package/dist/plugins/specweave-github/lib/github-client.js.map +1 -0
- package/dist/plugins/specweave-github/lib/index.d.ts +10 -0
- package/dist/plugins/specweave-github/lib/index.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/index.js +10 -0
- package/dist/plugins/specweave-github/lib/index.js.map +1 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts +51 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.js +147 -0
- package/dist/plugins/specweave-github/lib/subtask-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/task-parser.d.ts +37 -0
- package/dist/plugins/specweave-github/lib/task-parser.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/task-parser.js +211 -0
- package/dist/plugins/specweave-github/lib/task-parser.js.map +1 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts +51 -0
- package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/task-sync.js +332 -0
- package/dist/plugins/specweave-github/lib/task-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/types.d.ts +80 -0
- package/dist/plugins/specweave-github/lib/types.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/types.js +5 -0
- package/dist/plugins/specweave-github/lib/types.js.map +1 -0
- package/dist/utils/agents-md-compiler.d.ts +68 -0
- package/dist/utils/agents-md-compiler.d.ts.map +1 -0
- package/dist/utils/agents-md-compiler.js +420 -0
- package/dist/utils/agents-md-compiler.js.map +1 -0
- package/dist/utils/generate-skills-index.js +4 -4
- package/dist/utils/generate-skills-index.js.map +1 -1
- package/package.json +24 -21
- package/plugins/specweave-ado/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/SKILL.md +626 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +1010 -0
- package/plugins/specweave-backend/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-core/.claude-plugin/plugin.json +25 -0
- package/{src ā plugins/specweave-core}/agents/pm/AGENT.md +80 -0
- package/plugins/specweave-core/agents/translator/AGENT.md +282 -0
- package/{src ā plugins/specweave-core}/commands/README.md +11 -11
- package/{src ā plugins/specweave-core}/commands/specweave.costs.md +7 -7
- package/{src ā plugins/specweave-core}/commands/specweave.do.md +34 -7
- package/{src ā plugins/specweave-core}/commands/specweave.increment.md +131 -22
- package/{src ā plugins/specweave-core}/commands/specweave.md +49 -17
- package/{src ā plugins/specweave-core}/commands/specweave.sync-docs.md +5 -5
- package/plugins/specweave-core/commands/specweave.translate.md +425 -0
- package/{src ā plugins/specweave-core}/commands/specweave.validate.md +1 -1
- package/plugins/specweave-core/hooks/hooks.json +13 -0
- package/plugins/specweave-core/hooks/post-increment-plugin-detect.sh +142 -0
- package/plugins/specweave-core/hooks/post-task-completion.sh +265 -0
- package/plugins/specweave-core/hooks/pre-task-plugin-detect.sh +96 -0
- package/plugins/specweave-core/skills/SKILLS-INDEX.md +229 -0
- package/{src ā plugins/specweave-core}/skills/brownfield-analyzer/SKILL.md +66 -24
- package/{src ā plugins/specweave-core}/skills/context-loader/SKILL.md +1 -1
- package/plugins/specweave-core/skills/context-optimizer/SKILL.md +588 -0
- package/plugins/specweave-core/skills/docs-updater/SKILL.md +0 -0
- package/{src ā plugins/specweave-core}/skills/increment-planner/SKILL.md +81 -4
- package/plugins/specweave-core/skills/plugin-detector/SKILL.md +211 -0
- package/{src ā plugins/specweave-core}/skills/project-kickstarter/SKILL.md +7 -7
- package/plugins/specweave-core/skills/rfc-generator/SKILL.md +369 -0
- package/{src ā plugins/specweave-core}/skills/specweave-detector/SKILL.md +2 -2
- package/plugins/specweave-core/skills/specweave-framework/SKILL.md +498 -0
- package/plugins/specweave-core/skills/specweave-framework/test-cases/test-1-increment-naming.yaml +11 -0
- package/plugins/specweave-core/skills/specweave-framework/test-cases/test-2-source-of-truth.yaml +11 -0
- package/plugins/specweave-core/skills/specweave-framework/test-cases/test-3-increment-discipline.yaml +12 -0
- package/plugins/specweave-core/skills/specweave-framework/test-cases/test-4-file-placement.yaml +11 -0
- package/{src ā plugins/specweave-core}/skills/tdd-workflow/SKILL.md +20 -20
- package/plugins/specweave-core/skills/translator/SKILL.md +172 -0
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-docs/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +526 -0
- package/plugins/specweave-figma/.claude-plugin/.mcp.json +12 -0
- package/plugins/specweave-figma/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-figma/ARCHITECTURE.md +453 -0
- package/plugins/specweave-figma/README.md +728 -0
- package/plugins/specweave-figma/skills/figma-to-code/SKILL.md +632 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-1-token-generation.yaml +29 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-2-component-generation.yaml +27 -0
- package/plugins/specweave-figma/skills/figma-to-code/test-3-typescript-generation.yaml +28 -0
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-github/agents/github-manager/AGENT.md +651 -0
- package/plugins/specweave-github/commands/github-close-issue.md +418 -0
- package/plugins/specweave-github/commands/github-create-issue.md +307 -0
- package/plugins/specweave-github/commands/github-status.md +533 -0
- package/plugins/specweave-github/commands/github-sync-tasks.md +530 -0
- package/plugins/specweave-github/commands/github-sync.md +443 -0
- package/plugins/specweave-github/lib/github-client.ts +330 -0
- package/plugins/specweave-github/lib/index.ts +10 -0
- package/plugins/specweave-github/lib/subtask-sync.ts +225 -0
- package/plugins/specweave-github/lib/task-parser.ts +246 -0
- package/plugins/specweave-github/lib/task-sync.ts +402 -0
- package/plugins/specweave-github/lib/types.ts +86 -0
- package/plugins/specweave-github/skills/github-issue-tracker/SKILL.md +497 -0
- package/plugins/specweave-github/skills/github-sync/SKILL.md +461 -0
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-jira/.claude-plugin/plugin.json +8 -0
- package/{src ā plugins/specweave-jira}/commands/specweave.sync-jira.md +18 -18
- package/plugins/specweave-kubernetes/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-ml/.claude-plugin/plugin.json +39 -0
- package/plugins/specweave-ml/README.md +885 -0
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +402 -0
- package/plugins/specweave-ml/commands/ml-deploy.md +116 -0
- package/plugins/specweave-ml/commands/ml-evaluate.md +87 -0
- package/plugins/specweave-ml/commands/ml-explain.md +83 -0
- package/plugins/specweave-ml/skills/anomaly-detector/SKILL.md +559 -0
- package/plugins/specweave-ml/skills/automl-optimizer/SKILL.md +485 -0
- package/plugins/specweave-ml/skills/cv-pipeline-builder/SKILL.md +157 -0
- package/plugins/specweave-ml/skills/data-visualizer/SKILL.md +521 -0
- package/plugins/specweave-ml/skills/experiment-tracker/SKILL.md +535 -0
- package/plugins/specweave-ml/skills/feature-engineer/SKILL.md +566 -0
- package/plugins/specweave-ml/skills/ml-deployment-helper/SKILL.md +345 -0
- package/plugins/specweave-ml/skills/ml-pipeline-orchestrator/SKILL.md +518 -0
- package/plugins/specweave-ml/skills/model-evaluator/SKILL.md +155 -0
- package/plugins/specweave-ml/skills/model-explainer/SKILL.md +227 -0
- package/plugins/specweave-ml/skills/model-registry/SKILL.md +541 -0
- package/plugins/specweave-ml/skills/nlp-pipeline-builder/SKILL.md +180 -0
- package/plugins/specweave-ml/skills/time-series-forecaster/SKILL.md +569 -0
- package/plugins/specweave-payments/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-testing/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +8 -0
- package/plugins/specweave-ui/.claude-plugin/plugin.json +106 -0
- package/plugins/specweave-ui/.mcp.json +14 -0
- package/plugins/specweave-ui/README.md +386 -0
- package/src/adapters/adapter-base.ts +33 -0
- package/src/adapters/adapter-interface.ts +46 -0
- package/src/adapters/claude/adapter.ts +350 -39
- package/src/adapters/copilot/adapter.ts +267 -4
- package/src/adapters/cursor/adapter.ts +229 -0
- package/src/adapters/generic/adapter.ts +196 -0
- package/src/templates/AGENTS.md.template +170 -1
- package/src/templates/CLAUDE.md.template +122 -24
- package/src/templates/tasks.md.template +261 -0
- package/src/agents/ml-engineer/AGENT.md +0 -150
- package/src/commands/specweave.sync-github.md +0 -269
- package/src/hooks/post-task-completion.sh +0 -79
- package/src/skills/SKILLS-INDEX.md +0 -444
- package/src/skills/github-sync/SKILL.md +0 -234
- /package/{src ā plugins/specweave-ado}/skills/ado-sync/README.md +0 -0
- /package/{src ā plugins/specweave-ado}/skills/ado-sync/SKILL.md +0 -0
- /package/{src ā plugins/specweave-ado}/skills/specweave-ado-mapper/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/agents/database-optimizer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/dotnet-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/nodejs-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-backend}/skills/python-backend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/code-reviewer.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/docs-writer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/performance/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/qa-lead/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/security/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/tdd-orchestrator/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/agents/tech-lead/AGENT.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.done.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.inc.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.list-increments.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.next.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.progress.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.tdd-cycle.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.tdd-green.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.tdd-red.md +0 -0
- /package/{src ā plugins/specweave-core}/commands/specweave.tdd-refactor.md +0 -0
- /package/{src ā plugins/specweave-core}/hooks/README.md +0 -0
- /package/{src ā plugins/specweave-core}/hooks/docs-changed.sh +0 -0
- /package/{src ā plugins/specweave-core}/hooks/human-input-required.sh +0 -0
- /package/{src ā plugins/specweave-core}/hooks/pre-implementation.sh +0 -0
- /package/{src ā plugins/specweave-core}/skills/brownfield-onboarder/SKILL.md +0 -0
- /package/{src ā plugins/specweave-core}/skills/docs-updater/README.md +0 -0
- /package/{src ā plugins/specweave-core}/skills/increment-planner/scripts/feature-utils.js +0 -0
- /package/{src ā plugins/specweave-core}/skills/increment-quality-judge/SKILL.md +0 -0
- /package/{src ā plugins/specweave-core}/skills/project-kickstarter/test-cases/test-1-high-confidence-full-product.yaml +0 -0
- /package/{src ā plugins/specweave-core}/skills/project-kickstarter/test-cases/test-2-medium-confidence-partial.yaml +0 -0
- /package/{src ā plugins/specweave-core}/skills/project-kickstarter/test-cases/test-3-low-confidence-technical-question.yaml +0 -0
- /package/{src ā plugins/specweave-core}/skills/project-kickstarter/test-cases/test-4-opt-out-explicit.yaml +0 -0
- /package/{src ā plugins/specweave-core}/skills/role-orchestrator/README.md +0 -0
- /package/{src ā plugins/specweave-core}/skills/role-orchestrator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-core}/skills/task-builder/README.md +0 -0
- /package/{src ā plugins/specweave-cost-optimizer}/skills/cost-optimizer/SKILL.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-component-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-container-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/c4-context-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/deployment-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/er-diagram-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/templates/sequence-template.mmd +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-1-c4-context.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-2-sequence.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/agents/diagrams-architect/test-cases/test-3-er-diagram.yaml +0 -0
- /package/{src ā plugins/specweave-diagrams}/skills/diagrams-architect/SKILL.md +0 -0
- /package/{src ā plugins/specweave-diagrams}/skills/diagrams-generator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-brainstorming/README.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-brainstorming/SKILL.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-debugging/README.md +0 -0
- /package/{src ā plugins/specweave-docs}/skills/spec-driven-debugging/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/design-system-architect/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/frontend/SKILL.md +0 -0
- /package/{src ā plugins/specweave-frontend}/skills/nextjs/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/devops/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/network-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/observability-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/performance-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/AGENT.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/backend-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/database-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/infrastructure.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/monitoring.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/security-incidents.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/modules/ui-diagnostics.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/01-high-cpu-usage.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/02-database-deadlock.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/03-memory-leak.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/04-slow-api-response.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/05-ddos-attack.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/06-disk-full.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/07-service-down.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/08-data-corruption.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/09-cascade-failure.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/playbooks/10-rate-limit-exceeded.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/health-check.sh +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/log-analyzer.py +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/metrics-collector.sh +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/scripts/trace-analyzer.js +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/incident-report.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/mitigation-plan.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/post-mortem.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/agents/sre/templates/runbook-template.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/commands/specweave.monitor-setup.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/commands/specweave.slo-implement.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/distributed-tracing/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/grafana-dashboards/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/hetzner-provisioner/README.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/hetzner-provisioner/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/prometheus-configuration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-infrastructure}/skills/slo-implementation/SKILL.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/jira-sync/README.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/jira-sync/SKILL.md +0 -0
- /package/{src ā plugins/specweave-jira}/skills/specweave-jira-mapper/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/agents/kubernetes-architect/AGENT.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/references/argocd-setup.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/gitops-workflow/references/sync-policies.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/assets/Chart.yaml.template +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/assets/values.yaml.template +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/references/chart-structure.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/helm-chart-scaffolding/scripts/validate-chart.sh +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/configmap-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/deployment-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/assets/service-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/references/deployment-spec.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-manifest-generator/references/service-spec.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/SKILL.md +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/assets/network-policy-template.yaml +0 -0
- /package/{src ā plugins/specweave-kubernetes}/skills/k8s-security-policies/references/rbac-patterns.md +0 -0
- /package/{src ā plugins/specweave-ml}/agents/data-scientist/AGENT.md +0 -0
- /package/{src ā plugins/specweave-ml}/agents/mlops-engineer/AGENT.md +0 -0
- /package/{src ā plugins/specweave-ml}/commands/specweave.ml-pipeline.md +0 -0
- /package/{src ā plugins/specweave-ml}/skills/ml-pipeline-workflow/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/agents/payment-integration/AGENT.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/billing-automation/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/paypal-integration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/pci-compliance/SKILL.md +0 -0
- /package/{src ā plugins/specweave-payments}/skills/stripe-integration/SKILL.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/README.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/SKILL.md +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/execute.js +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/lib/utils.js +0 -0
- /package/{src ā plugins/specweave-testing}/skills/e2e-playwright/package.json +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/LICENSE.txt +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/SKILL.md +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/init_skill.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/package_skill.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-creator/scripts/quick_validate.py +0 -0
- /package/{src ā plugins/specweave-tooling}/skills/skill-router/SKILL.md +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Increment Status Detection
|
|
3
|
+
*
|
|
4
|
+
* Utility to detect increment completion status and enforce increment discipline.
|
|
5
|
+
*
|
|
6
|
+
* **The Iron Rule**: Cannot start increment N+1 until increment N is DONE.
|
|
7
|
+
*
|
|
8
|
+
* DONE means one of:
|
|
9
|
+
* 1. All tasks in tasks.md marked [x] Completed
|
|
10
|
+
* 2. COMPLETION-SUMMARY.md exists with "COMPLETE" status
|
|
11
|
+
* 3. All tasks removed/moved with documentation
|
|
12
|
+
*/
|
|
13
|
+
import fs from 'fs-extra';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
export class IncrementStatusDetector {
|
|
16
|
+
constructor(projectPath = process.cwd()) {
|
|
17
|
+
this.incrementsPath = path.join(projectPath, '.specweave/increments');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get status for a specific increment
|
|
21
|
+
*/
|
|
22
|
+
async getStatus(incrementId) {
|
|
23
|
+
const incrementPath = path.join(this.incrementsPath, incrementId);
|
|
24
|
+
if (!await fs.pathExists(incrementPath)) {
|
|
25
|
+
return {
|
|
26
|
+
id: incrementId,
|
|
27
|
+
path: incrementPath,
|
|
28
|
+
exists: false,
|
|
29
|
+
isComplete: false,
|
|
30
|
+
totalTasks: 0,
|
|
31
|
+
completedTasks: 0,
|
|
32
|
+
percentComplete: 0,
|
|
33
|
+
pendingTasks: [],
|
|
34
|
+
completionReports: [],
|
|
35
|
+
hasCompletionMarker: false,
|
|
36
|
+
reason: 'Increment directory does not exist',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Check for completion markers
|
|
40
|
+
const completionReports = await this.findCompletionReports(incrementPath);
|
|
41
|
+
const hasCompletionMarker = completionReports.length > 0;
|
|
42
|
+
// Parse tasks.md
|
|
43
|
+
const tasksPath = path.join(incrementPath, 'tasks.md');
|
|
44
|
+
let totalTasks = 0;
|
|
45
|
+
let completedTasks = 0;
|
|
46
|
+
let pendingTasks = [];
|
|
47
|
+
if (await fs.pathExists(tasksPath)) {
|
|
48
|
+
const tasksContent = await fs.readFile(tasksPath, 'utf-8');
|
|
49
|
+
const taskStats = this.parseTasksFile(tasksContent);
|
|
50
|
+
totalTasks = taskStats.totalTasks;
|
|
51
|
+
completedTasks = taskStats.completedTasks;
|
|
52
|
+
pendingTasks = taskStats.pendingTasks;
|
|
53
|
+
}
|
|
54
|
+
const percentComplete = totalTasks > 0
|
|
55
|
+
? Math.round((completedTasks / totalTasks) * 100)
|
|
56
|
+
: (hasCompletionMarker ? 100 : 0);
|
|
57
|
+
const isComplete = hasCompletionMarker || (totalTasks > 0 && completedTasks === totalTasks);
|
|
58
|
+
let reason;
|
|
59
|
+
if (!isComplete) {
|
|
60
|
+
if (totalTasks === 0) {
|
|
61
|
+
reason = 'No tasks found (tasks.md missing or empty)';
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
reason = `${totalTasks - completedTasks} tasks incomplete (${percentComplete}% complete)`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
id: incrementId,
|
|
69
|
+
path: incrementPath,
|
|
70
|
+
exists: true,
|
|
71
|
+
isComplete,
|
|
72
|
+
totalTasks,
|
|
73
|
+
completedTasks,
|
|
74
|
+
percentComplete,
|
|
75
|
+
pendingTasks,
|
|
76
|
+
completionReports,
|
|
77
|
+
hasCompletionMarker,
|
|
78
|
+
reason,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get all incomplete increments
|
|
83
|
+
*/
|
|
84
|
+
async getAllIncomplete() {
|
|
85
|
+
if (!await fs.pathExists(this.incrementsPath)) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const entries = await fs.readdir(this.incrementsPath, { withFileTypes: true });
|
|
89
|
+
const incrementDirs = entries
|
|
90
|
+
.filter(entry => entry.isDirectory())
|
|
91
|
+
.filter(entry => /^\d{4}-/.test(entry.name)) // Only numbered increments
|
|
92
|
+
.map(entry => entry.name);
|
|
93
|
+
const statuses = await Promise.all(incrementDirs.map(id => this.getStatus(id)));
|
|
94
|
+
return statuses.filter(status => status.exists && !status.isComplete);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get latest increment ID
|
|
98
|
+
*/
|
|
99
|
+
async getLatest() {
|
|
100
|
+
if (!await fs.pathExists(this.incrementsPath)) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const entries = await fs.readdir(this.incrementsPath, { withFileTypes: true });
|
|
104
|
+
const incrementDirs = entries
|
|
105
|
+
.filter(entry => entry.isDirectory())
|
|
106
|
+
.filter(entry => /^\d{4}-/.test(entry.name))
|
|
107
|
+
.map(entry => entry.name)
|
|
108
|
+
.sort()
|
|
109
|
+
.reverse();
|
|
110
|
+
return incrementDirs[0] || null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if increment is complete
|
|
114
|
+
*/
|
|
115
|
+
async isComplete(incrementId) {
|
|
116
|
+
const status = await this.getStatus(incrementId);
|
|
117
|
+
return status.isComplete;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Find completion reports (COMPLETION-SUMMARY.md, etc.)
|
|
121
|
+
*/
|
|
122
|
+
async findCompletionReports(incrementPath) {
|
|
123
|
+
const reportPatterns = [
|
|
124
|
+
'COMPLETION-SUMMARY.md',
|
|
125
|
+
'COMPLETION-REPORT.md',
|
|
126
|
+
'FINAL-REPORT.md',
|
|
127
|
+
'DONE.md',
|
|
128
|
+
];
|
|
129
|
+
const reports = [];
|
|
130
|
+
for (const pattern of reportPatterns) {
|
|
131
|
+
const reportPath = path.join(incrementPath, pattern);
|
|
132
|
+
if (await fs.pathExists(reportPath)) {
|
|
133
|
+
// Check if report contains "COMPLETE" status
|
|
134
|
+
const content = await fs.readFile(reportPath, 'utf-8');
|
|
135
|
+
if (/Status.*:.*COMPLETE/i.test(content) || /ā
.*COMPLETE/i.test(content)) {
|
|
136
|
+
reports.push(pattern);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return reports;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Parse tasks.md to extract task statistics
|
|
144
|
+
*/
|
|
145
|
+
parseTasksFile(content) {
|
|
146
|
+
const lines = content.split('\n');
|
|
147
|
+
let totalTasks = 0;
|
|
148
|
+
let completedTasks = 0;
|
|
149
|
+
const pendingTasks = [];
|
|
150
|
+
let currentTaskId = null;
|
|
151
|
+
let currentTaskTitle = null;
|
|
152
|
+
let currentTaskPriority = null;
|
|
153
|
+
let currentTaskPhase = null;
|
|
154
|
+
for (const line of lines) {
|
|
155
|
+
// Match task header: ### T-001: Task Title OR ### T-001-DISCIPLINE: Task Title
|
|
156
|
+
const taskHeaderMatch = line.match(/^###\s+(T-\d+(?:-[A-Z]+)?):\s+(.+)/);
|
|
157
|
+
if (taskHeaderMatch) {
|
|
158
|
+
currentTaskId = taskHeaderMatch[1];
|
|
159
|
+
currentTaskTitle = taskHeaderMatch[2];
|
|
160
|
+
currentTaskPriority = null;
|
|
161
|
+
currentTaskPhase = null;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
// Match priority: **Priority**: P0
|
|
165
|
+
const priorityMatch = line.match(/\*\*Priority\*\*:\s+(\w+)/);
|
|
166
|
+
if (priorityMatch && currentTaskId) {
|
|
167
|
+
currentTaskPriority = priorityMatch[1];
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Match phase: **Phase**: Week 1
|
|
171
|
+
const phaseMatch = line.match(/\*\*Phase\*\*:\s+(.+)/);
|
|
172
|
+
if (phaseMatch && currentTaskId) {
|
|
173
|
+
currentTaskPhase = phaseMatch[1];
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
// Match status: **Status**: [x] Completed OR pending
|
|
177
|
+
const statusMatch = line.match(/\*\*Status\*\*:\s+\[([x ])\]\s+(\w+)/);
|
|
178
|
+
if (statusMatch && currentTaskId && currentTaskTitle) {
|
|
179
|
+
totalTasks++;
|
|
180
|
+
const isComplete = statusMatch[1] === 'x';
|
|
181
|
+
if (isComplete) {
|
|
182
|
+
completedTasks++;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
pendingTasks.push({
|
|
186
|
+
id: currentTaskId,
|
|
187
|
+
title: currentTaskTitle,
|
|
188
|
+
priority: currentTaskPriority || undefined,
|
|
189
|
+
phase: currentTaskPhase || undefined,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
// Reset for next task
|
|
193
|
+
currentTaskId = null;
|
|
194
|
+
currentTaskTitle = null;
|
|
195
|
+
currentTaskPriority = null;
|
|
196
|
+
currentTaskPhase = null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
totalTasks,
|
|
201
|
+
completedTasks,
|
|
202
|
+
pendingTasks,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Convenience function to check if an increment is complete
|
|
208
|
+
*/
|
|
209
|
+
export async function isIncrementComplete(incrementId, projectPath) {
|
|
210
|
+
const detector = new IncrementStatusDetector(projectPath);
|
|
211
|
+
return detector.isComplete(incrementId);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Convenience function to get all incomplete increments
|
|
215
|
+
*/
|
|
216
|
+
export async function getAllIncompleteIncrements(projectPath) {
|
|
217
|
+
const detector = new IncrementStatusDetector(projectPath);
|
|
218
|
+
return detector.getAllIncomplete();
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Convenience function to get latest increment
|
|
222
|
+
*/
|
|
223
|
+
export async function getLatestIncrement(projectPath) {
|
|
224
|
+
const detector = new IncrementStatusDetector(projectPath);
|
|
225
|
+
return detector.getLatest();
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=increment-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"increment-status.js","sourceRoot":"","sources":["../../src/core/increment-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Detector
|
|
3
|
+
*
|
|
4
|
+
* Automatically detects which plugins should be enabled based on:
|
|
5
|
+
* 1. Project structure (package.json, directories, env vars, git remote)
|
|
6
|
+
* 2. Spec content (keywords, domain analysis)
|
|
7
|
+
* 3. Task descriptions (pre-task hook)
|
|
8
|
+
* 4. Git changes (post-increment hook)
|
|
9
|
+
*
|
|
10
|
+
* @module core/plugin-detector
|
|
11
|
+
* @version 0.4.0
|
|
12
|
+
*/
|
|
13
|
+
import type { DetectionResult } from './types/plugin.js';
|
|
14
|
+
/**
|
|
15
|
+
* PluginDetector - Auto-detects relevant plugins for a project
|
|
16
|
+
*/
|
|
17
|
+
export declare class PluginDetector {
|
|
18
|
+
private loader;
|
|
19
|
+
private availablePlugins;
|
|
20
|
+
private pluginsDir;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new PluginDetector
|
|
23
|
+
*
|
|
24
|
+
* @param pluginsDir - Path to plugins directory (default: src/plugins)
|
|
25
|
+
*/
|
|
26
|
+
constructor(pluginsDir?: string);
|
|
27
|
+
/**
|
|
28
|
+
* Load available plugins for detection
|
|
29
|
+
*
|
|
30
|
+
* Scans plugins directory and loads all plugin manifests
|
|
31
|
+
*/
|
|
32
|
+
loadAvailablePlugins(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Phase 1: Init-time detection
|
|
35
|
+
*
|
|
36
|
+
* Detects plugins based on project structure during `specweave init`
|
|
37
|
+
*
|
|
38
|
+
* @param projectPath - Path to project root
|
|
39
|
+
* @returns Array of detection results with confidence scores
|
|
40
|
+
*/
|
|
41
|
+
detectFromProject(projectPath: string): Promise<DetectionResult[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Phase 2: Spec-based detection
|
|
44
|
+
*
|
|
45
|
+
* Detects plugins based on increment spec content during `/specweave.inc`
|
|
46
|
+
*
|
|
47
|
+
* @param specContent - Content of spec.md
|
|
48
|
+
* @returns Array of detection results
|
|
49
|
+
*/
|
|
50
|
+
detectFromSpec(specContent: string): Promise<DetectionResult[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Phase 3: Task-based detection
|
|
53
|
+
*
|
|
54
|
+
* Detects plugins based on task description (pre-task hook)
|
|
55
|
+
*
|
|
56
|
+
* @param taskContent - Content of task description
|
|
57
|
+
* @returns Array of detection results
|
|
58
|
+
*/
|
|
59
|
+
detectFromTask(taskContent: string): Promise<DetectionResult[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Phase 4: Git diff detection
|
|
62
|
+
*
|
|
63
|
+
* Detects plugins based on recent git changes (post-increment hook)
|
|
64
|
+
*
|
|
65
|
+
* @param diff - Git diff output
|
|
66
|
+
* @returns Array of detection results
|
|
67
|
+
*/
|
|
68
|
+
detectFromChanges(diff: string): Promise<DetectionResult[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Combine detection results from multiple sources
|
|
71
|
+
*
|
|
72
|
+
* Merges results and adjusts confidence scores
|
|
73
|
+
*
|
|
74
|
+
* @param results - Array of detection result arrays
|
|
75
|
+
* @returns Merged and deduplicated results
|
|
76
|
+
*/
|
|
77
|
+
combineResults(...results: DetectionResult[][]): DetectionResult[];
|
|
78
|
+
/**
|
|
79
|
+
* Get high-confidence suggestions
|
|
80
|
+
*
|
|
81
|
+
* Filters detection results by confidence threshold
|
|
82
|
+
*
|
|
83
|
+
* @param results - Detection results
|
|
84
|
+
* @param threshold - Minimum confidence (default: 0.6)
|
|
85
|
+
* @returns High-confidence plugin suggestions
|
|
86
|
+
*/
|
|
87
|
+
getHighConfidenceSuggestions(results: DetectionResult[], threshold?: number): string[];
|
|
88
|
+
/**
|
|
89
|
+
* Format detection results for display
|
|
90
|
+
*
|
|
91
|
+
* @param results - Detection results
|
|
92
|
+
* @returns Formatted string for CLI output
|
|
93
|
+
*/
|
|
94
|
+
formatResults(results: DetectionResult[]): string;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=plugin-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-detector.d.ts","sourceRoot":"","sources":["../../src/core/plugin-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGjE;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;OAIG;gBACS,UAAU,CAAC,EAAE,MAAM;IAK/B;;;;OAIG;IACG,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3C;;;;;;;OAOG;IACG,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAoFxE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA4CrE;;;;;;;OAOG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAyCrE;;;;;;;OAOG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAqEjE;;;;;;;OAOG;IACH,cAAc,CAAC,GAAG,OAAO,EAAE,eAAe,EAAE,EAAE,GAAG,eAAe,EAAE;IAwBlE;;;;;;;;OAQG;IACH,4BAA4B,CAC1B,OAAO,EAAE,eAAe,EAAE,EAC1B,SAAS,GAAE,MAAY,GACtB,MAAM,EAAE;IAMX;;;;;OAKG;IACH,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM;CAkBlD"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Detector
|
|
3
|
+
*
|
|
4
|
+
* Automatically detects which plugins should be enabled based on:
|
|
5
|
+
* 1. Project structure (package.json, directories, env vars, git remote)
|
|
6
|
+
* 2. Spec content (keywords, domain analysis)
|
|
7
|
+
* 3. Task descriptions (pre-task hook)
|
|
8
|
+
* 4. Git changes (post-increment hook)
|
|
9
|
+
*
|
|
10
|
+
* @module core/plugin-detector
|
|
11
|
+
* @version 0.4.0
|
|
12
|
+
*/
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import * as fs from 'fs-extra';
|
|
15
|
+
import { PluginLoader } from './plugin-loader.js';
|
|
16
|
+
/**
|
|
17
|
+
* PluginDetector - Auto-detects relevant plugins for a project
|
|
18
|
+
*/
|
|
19
|
+
export class PluginDetector {
|
|
20
|
+
/**
|
|
21
|
+
* Create a new PluginDetector
|
|
22
|
+
*
|
|
23
|
+
* @param pluginsDir - Path to plugins directory (default: src/plugins)
|
|
24
|
+
*/
|
|
25
|
+
constructor(pluginsDir) {
|
|
26
|
+
this.availablePlugins = [];
|
|
27
|
+
this.loader = new PluginLoader();
|
|
28
|
+
this.pluginsDir = pluginsDir || path.join(process.cwd(), 'src', 'plugins');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Load available plugins for detection
|
|
32
|
+
*
|
|
33
|
+
* Scans plugins directory and loads all plugin manifests
|
|
34
|
+
*/
|
|
35
|
+
async loadAvailablePlugins() {
|
|
36
|
+
this.availablePlugins = [];
|
|
37
|
+
if (!(await fs.pathExists(this.pluginsDir))) {
|
|
38
|
+
return; // No plugins available
|
|
39
|
+
}
|
|
40
|
+
const dirs = await fs.readdir(this.pluginsDir);
|
|
41
|
+
for (const dir of dirs) {
|
|
42
|
+
const pluginPath = path.join(this.pluginsDir, dir);
|
|
43
|
+
const stat = await fs.stat(pluginPath);
|
|
44
|
+
if (stat.isDirectory()) {
|
|
45
|
+
try {
|
|
46
|
+
const plugin = await this.loader.loadFromDirectory(pluginPath);
|
|
47
|
+
this.availablePlugins.push(plugin);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.warn(`ā ļø Failed to load plugin ${dir}: ${error.message}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Phase 1: Init-time detection
|
|
57
|
+
*
|
|
58
|
+
* Detects plugins based on project structure during `specweave init`
|
|
59
|
+
*
|
|
60
|
+
* @param projectPath - Path to project root
|
|
61
|
+
* @returns Array of detection results with confidence scores
|
|
62
|
+
*/
|
|
63
|
+
async detectFromProject(projectPath) {
|
|
64
|
+
const results = [];
|
|
65
|
+
// Ensure plugins are loaded
|
|
66
|
+
if (this.availablePlugins.length === 0) {
|
|
67
|
+
await this.loadAvailablePlugins();
|
|
68
|
+
}
|
|
69
|
+
// Check each plugin's auto_detect rules
|
|
70
|
+
for (const plugin of this.availablePlugins) {
|
|
71
|
+
const { auto_detect } = plugin.manifest;
|
|
72
|
+
if (!auto_detect)
|
|
73
|
+
continue;
|
|
74
|
+
let confidence = 0;
|
|
75
|
+
const reasons = [];
|
|
76
|
+
// Check files/directories
|
|
77
|
+
if (auto_detect.files) {
|
|
78
|
+
for (const pattern of auto_detect.files) {
|
|
79
|
+
const filePath = path.join(projectPath, pattern);
|
|
80
|
+
if (await fs.pathExists(filePath)) {
|
|
81
|
+
confidence += 0.3;
|
|
82
|
+
reasons.push(`Found ${pattern}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Check package.json dependencies
|
|
87
|
+
if (auto_detect.packages) {
|
|
88
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
89
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
90
|
+
const packageJson = await fs.readJSON(packageJsonPath);
|
|
91
|
+
const allDeps = {
|
|
92
|
+
...packageJson.dependencies,
|
|
93
|
+
...packageJson.devDependencies
|
|
94
|
+
};
|
|
95
|
+
for (const pkg of auto_detect.packages) {
|
|
96
|
+
if (allDeps[pkg]) {
|
|
97
|
+
confidence += 0.25;
|
|
98
|
+
reasons.push(`Uses ${pkg}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Check environment variables
|
|
104
|
+
if (auto_detect.env_vars) {
|
|
105
|
+
for (const envVar of auto_detect.env_vars) {
|
|
106
|
+
if (process.env[envVar]) {
|
|
107
|
+
confidence += 0.2;
|
|
108
|
+
reasons.push(`Env var ${envVar} set`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Check git remote pattern
|
|
113
|
+
if (auto_detect.git_remote_pattern) {
|
|
114
|
+
const gitConfigPath = path.join(projectPath, '.git', 'config');
|
|
115
|
+
if (await fs.pathExists(gitConfigPath)) {
|
|
116
|
+
const gitConfig = await fs.readFile(gitConfigPath, 'utf-8');
|
|
117
|
+
const regex = new RegExp(auto_detect.git_remote_pattern);
|
|
118
|
+
if (regex.test(gitConfig)) {
|
|
119
|
+
confidence += 0.25;
|
|
120
|
+
reasons.push(`Git remote matches ${auto_detect.git_remote_pattern}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Add to results if confidence > 0
|
|
125
|
+
if (confidence > 0) {
|
|
126
|
+
results.push({
|
|
127
|
+
pluginName: plugin.manifest.name,
|
|
128
|
+
confidence: Math.min(confidence, 1.0), // Cap at 1.0
|
|
129
|
+
reason: reasons.join(', '),
|
|
130
|
+
trigger: 'project-structure'
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Sort by confidence (highest first)
|
|
135
|
+
return results.sort((a, b) => b.confidence - a.confidence);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Phase 2: Spec-based detection
|
|
139
|
+
*
|
|
140
|
+
* Detects plugins based on increment spec content during `/specweave.inc`
|
|
141
|
+
*
|
|
142
|
+
* @param specContent - Content of spec.md
|
|
143
|
+
* @returns Array of detection results
|
|
144
|
+
*/
|
|
145
|
+
async detectFromSpec(specContent) {
|
|
146
|
+
const results = [];
|
|
147
|
+
// Ensure plugins are loaded
|
|
148
|
+
if (this.availablePlugins.length === 0) {
|
|
149
|
+
await this.loadAvailablePlugins();
|
|
150
|
+
}
|
|
151
|
+
const normalizedContent = specContent.toLowerCase();
|
|
152
|
+
// Check each plugin's trigger keywords
|
|
153
|
+
for (const plugin of this.availablePlugins) {
|
|
154
|
+
const { triggers } = plugin.manifest;
|
|
155
|
+
if (!triggers || triggers.length === 0)
|
|
156
|
+
continue;
|
|
157
|
+
let matchCount = 0;
|
|
158
|
+
const matchedTriggers = [];
|
|
159
|
+
for (const trigger of triggers) {
|
|
160
|
+
const regex = new RegExp(`\\b${trigger.toLowerCase()}\\b`, 'gi');
|
|
161
|
+
const matches = normalizedContent.match(regex);
|
|
162
|
+
if (matches) {
|
|
163
|
+
matchCount += matches.length;
|
|
164
|
+
matchedTriggers.push(trigger);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (matchCount > 0) {
|
|
168
|
+
// Confidence based on frequency (capped at 1.0)
|
|
169
|
+
const confidence = Math.min(matchCount * 0.1, 1.0);
|
|
170
|
+
results.push({
|
|
171
|
+
pluginName: plugin.manifest.name,
|
|
172
|
+
confidence,
|
|
173
|
+
reason: `Spec mentions: ${matchedTriggers.join(', ')}`,
|
|
174
|
+
trigger: 'spec-keywords'
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Sort by confidence
|
|
179
|
+
return results.sort((a, b) => b.confidence - a.confidence);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Phase 3: Task-based detection
|
|
183
|
+
*
|
|
184
|
+
* Detects plugins based on task description (pre-task hook)
|
|
185
|
+
*
|
|
186
|
+
* @param taskContent - Content of task description
|
|
187
|
+
* @returns Array of detection results
|
|
188
|
+
*/
|
|
189
|
+
async detectFromTask(taskContent) {
|
|
190
|
+
const results = [];
|
|
191
|
+
// Ensure plugins are loaded
|
|
192
|
+
if (this.availablePlugins.length === 0) {
|
|
193
|
+
await this.loadAvailablePlugins();
|
|
194
|
+
}
|
|
195
|
+
const normalizedContent = taskContent.toLowerCase();
|
|
196
|
+
// Check each plugin's trigger keywords
|
|
197
|
+
for (const plugin of this.availablePlugins) {
|
|
198
|
+
const { triggers } = plugin.manifest;
|
|
199
|
+
if (!triggers || triggers.length === 0)
|
|
200
|
+
continue;
|
|
201
|
+
const matchedTriggers = [];
|
|
202
|
+
for (const trigger of triggers) {
|
|
203
|
+
const regex = new RegExp(`\\b${trigger.toLowerCase()}\\b`, 'i');
|
|
204
|
+
if (regex.test(normalizedContent)) {
|
|
205
|
+
matchedTriggers.push(trigger);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (matchedTriggers.length > 0) {
|
|
209
|
+
// Task-based detection has moderate confidence
|
|
210
|
+
const confidence = 0.6;
|
|
211
|
+
results.push({
|
|
212
|
+
pluginName: plugin.manifest.name,
|
|
213
|
+
confidence,
|
|
214
|
+
reason: `Task mentions: ${matchedTriggers.join(', ')}`,
|
|
215
|
+
trigger: 'task-keywords'
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Sort by confidence
|
|
220
|
+
return results.sort((a, b) => b.confidence - a.confidence);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Phase 4: Git diff detection
|
|
224
|
+
*
|
|
225
|
+
* Detects plugins based on recent git changes (post-increment hook)
|
|
226
|
+
*
|
|
227
|
+
* @param diff - Git diff output
|
|
228
|
+
* @returns Array of detection results
|
|
229
|
+
*/
|
|
230
|
+
async detectFromChanges(diff) {
|
|
231
|
+
const results = [];
|
|
232
|
+
// Ensure plugins are loaded
|
|
233
|
+
if (this.availablePlugins.length === 0) {
|
|
234
|
+
await this.loadAvailablePlugins();
|
|
235
|
+
}
|
|
236
|
+
const normalizedDiff = diff.toLowerCase();
|
|
237
|
+
// Check for new file patterns
|
|
238
|
+
for (const plugin of this.availablePlugins) {
|
|
239
|
+
const { auto_detect } = plugin.manifest;
|
|
240
|
+
if (!auto_detect?.files)
|
|
241
|
+
continue;
|
|
242
|
+
const matchedFiles = [];
|
|
243
|
+
for (const pattern of auto_detect.files) {
|
|
244
|
+
// Check if diff contains new files matching pattern
|
|
245
|
+
const regex = new RegExp(`\\+\\+\\+.*${pattern}`, 'i');
|
|
246
|
+
if (regex.test(normalizedDiff)) {
|
|
247
|
+
matchedFiles.push(pattern);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (matchedFiles.length > 0) {
|
|
251
|
+
results.push({
|
|
252
|
+
pluginName: plugin.manifest.name,
|
|
253
|
+
confidence: 0.7,
|
|
254
|
+
reason: `Added files: ${matchedFiles.join(', ')}`,
|
|
255
|
+
trigger: 'git-changes'
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Check for new package.json dependencies
|
|
260
|
+
const packageJsonMatch = diff.match(/\+\+\+ b\/package\.json([\s\S]+?)(?=\+\+\+|$)/);
|
|
261
|
+
if (packageJsonMatch) {
|
|
262
|
+
const addedLines = packageJsonMatch[1]
|
|
263
|
+
.split('\n')
|
|
264
|
+
.filter(line => line.startsWith('+') && !line.startsWith('+++'));
|
|
265
|
+
for (const plugin of this.availablePlugins) {
|
|
266
|
+
const { auto_detect } = plugin.manifest;
|
|
267
|
+
if (!auto_detect?.packages)
|
|
268
|
+
continue;
|
|
269
|
+
const matchedPackages = [];
|
|
270
|
+
for (const pkg of auto_detect.packages) {
|
|
271
|
+
if (addedLines.some(line => line.includes(`"${pkg}"`))) {
|
|
272
|
+
matchedPackages.push(pkg);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (matchedPackages.length > 0) {
|
|
276
|
+
results.push({
|
|
277
|
+
pluginName: plugin.manifest.name,
|
|
278
|
+
confidence: 0.8,
|
|
279
|
+
reason: `Added dependencies: ${matchedPackages.join(', ')}`,
|
|
280
|
+
trigger: 'package-json-changes'
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Sort by confidence
|
|
286
|
+
return results.sort((a, b) => b.confidence - a.confidence);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Combine detection results from multiple sources
|
|
290
|
+
*
|
|
291
|
+
* Merges results and adjusts confidence scores
|
|
292
|
+
*
|
|
293
|
+
* @param results - Array of detection result arrays
|
|
294
|
+
* @returns Merged and deduplicated results
|
|
295
|
+
*/
|
|
296
|
+
combineResults(...results) {
|
|
297
|
+
const combined = new Map();
|
|
298
|
+
for (const resultArray of results) {
|
|
299
|
+
for (const result of resultArray) {
|
|
300
|
+
const existing = combined.get(result.pluginName);
|
|
301
|
+
if (existing) {
|
|
302
|
+
// Boost confidence if detected from multiple sources
|
|
303
|
+
existing.confidence = Math.min(existing.confidence + result.confidence * 0.3, 1.0);
|
|
304
|
+
existing.reason += `; ${result.reason}`;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
combined.set(result.pluginName, { ...result });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Convert to array and sort
|
|
312
|
+
return Array.from(combined.values()).sort((a, b) => b.confidence - a.confidence);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get high-confidence suggestions
|
|
316
|
+
*
|
|
317
|
+
* Filters detection results by confidence threshold
|
|
318
|
+
*
|
|
319
|
+
* @param results - Detection results
|
|
320
|
+
* @param threshold - Minimum confidence (default: 0.6)
|
|
321
|
+
* @returns High-confidence plugin suggestions
|
|
322
|
+
*/
|
|
323
|
+
getHighConfidenceSuggestions(results, threshold = 0.6) {
|
|
324
|
+
return results
|
|
325
|
+
.filter(r => r.confidence >= threshold)
|
|
326
|
+
.map(r => r.pluginName);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Format detection results for display
|
|
330
|
+
*
|
|
331
|
+
* @param results - Detection results
|
|
332
|
+
* @returns Formatted string for CLI output
|
|
333
|
+
*/
|
|
334
|
+
formatResults(results) {
|
|
335
|
+
if (results.length === 0) {
|
|
336
|
+
return 'No plugins detected for this project.';
|
|
337
|
+
}
|
|
338
|
+
let output = '\nš¦ Detected plugins:\n\n';
|
|
339
|
+
for (const result of results) {
|
|
340
|
+
const confidenceBar = 'ā'.repeat(Math.floor(result.confidence * 10));
|
|
341
|
+
const confidencePercent = Math.floor(result.confidence * 100);
|
|
342
|
+
output += ` ${result.pluginName}\n`;
|
|
343
|
+
output += ` Confidence: ${confidenceBar} ${confidencePercent}%\n`;
|
|
344
|
+
output += ` Reason: ${result.reason}\n\n`;
|
|
345
|
+
}
|
|
346
|
+
return output;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=plugin-detector.js.map
|