agileflow 4.0.0-alpha.2 → 4.0.0-alpha.21
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/CHANGELOG.md +51 -0
- package/content/plugins/accessibility/plugin.yaml +14 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/SKILL.md +392 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/references/aria-patterns.md +528 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/references/testing-checklist.md +457 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/references/wcag-guide.md +683 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/workflows/audit-page.md +310 -0
- package/content/plugins/accessibility/skills/agileflow-accessibility/workflows/implement-accessible-component.md +479 -0
- package/content/plugins/ads/agents/ads-audit-budget.md +185 -0
- package/content/plugins/ads/agents/ads-audit-compliance.md +171 -0
- package/content/plugins/ads/agents/ads-audit-creative.md +168 -0
- package/content/plugins/ads/agents/ads-audit-google.md +227 -0
- package/content/plugins/ads/agents/ads-audit-meta.md +184 -0
- package/content/plugins/ads/agents/ads-audit-tracking.md +205 -0
- package/content/plugins/ads/agents/ads-consensus.md +410 -0
- package/content/plugins/ads/agents/ads-generate.md +152 -0
- package/content/plugins/ads/agents/ads-performance-tracker.md +212 -0
- package/content/plugins/ads/plugin.yaml +23 -4
- package/content/plugins/ads/skills/agileflow-ads/SKILL.md +218 -0
- package/content/plugins/ads/skills/agileflow-ads/references/ad-copy-formula-guide.md +131 -0
- package/content/plugins/ads/skills/agileflow-ads/references/audience-targeting-guide.md +137 -0
- package/content/plugins/ads/skills/agileflow-ads/references/bid-strategy-guide.md +115 -0
- package/content/plugins/ads/skills/agileflow-ads/references/platform-benchmarks.md +100 -0
- package/content/plugins/ads/skills/agileflow-ads/workflows/audit.md +118 -0
- package/content/plugins/ads/skills/agileflow-ads/workflows/generate.md +84 -0
- package/content/plugins/audit/agents/a11y-analyzer-aria.md +173 -0
- package/content/plugins/audit/agents/a11y-analyzer-forms.md +173 -0
- package/content/plugins/audit/agents/a11y-analyzer-keyboard.md +183 -0
- package/content/plugins/audit/agents/a11y-analyzer-semantic.md +169 -0
- package/content/plugins/audit/agents/a11y-analyzer-visual.md +172 -0
- package/content/plugins/audit/agents/a11y-consensus.md +249 -0
- package/content/plugins/audit/agents/accessibility.md +558 -0
- package/content/plugins/audit/agents/api-quality-analyzer-conventions.md +156 -0
- package/content/plugins/audit/agents/api-quality-analyzer-docs.md +184 -0
- package/content/plugins/audit/agents/api-quality-analyzer-errors.md +191 -0
- package/content/plugins/audit/agents/api-quality-analyzer-pagination.md +179 -0
- package/content/plugins/audit/agents/api-quality-analyzer-versioning.md +150 -0
- package/content/plugins/audit/agents/api-quality-consensus.md +217 -0
- package/content/plugins/audit/agents/api-validator.md +191 -0
- package/content/plugins/audit/agents/arch-analyzer-circular.md +156 -0
- package/content/plugins/audit/agents/arch-analyzer-complexity.md +193 -0
- package/content/plugins/audit/agents/arch-analyzer-coupling.md +152 -0
- package/content/plugins/audit/agents/arch-analyzer-layering.md +160 -0
- package/content/plugins/audit/agents/arch-analyzer-patterns.md +210 -0
- package/content/plugins/audit/agents/arch-consensus.md +228 -0
- package/content/plugins/audit/agents/browser-qa.md +342 -0
- package/content/plugins/audit/agents/code-reviewer.md +298 -0
- package/content/plugins/audit/agents/completeness-analyzer-api.md +199 -0
- package/content/plugins/audit/agents/completeness-analyzer-conditional.md +211 -0
- package/content/plugins/audit/agents/completeness-analyzer-handlers.md +166 -0
- package/content/plugins/audit/agents/completeness-analyzer-imports.md +165 -0
- package/content/plugins/audit/agents/completeness-analyzer-routes.md +190 -0
- package/content/plugins/audit/agents/completeness-analyzer-state.md +196 -0
- package/content/plugins/audit/agents/completeness-analyzer-stubs.md +206 -0
- package/content/plugins/audit/agents/completeness-consensus.md +295 -0
- package/content/plugins/audit/agents/error-analyzer.md +213 -0
- package/content/plugins/audit/agents/flow-analyzer-authorization.md +182 -0
- package/content/plugins/audit/agents/flow-analyzer-discovery.md +174 -0
- package/content/plugins/audit/agents/flow-analyzer-errors.md +186 -0
- package/content/plugins/audit/agents/flow-analyzer-feedback.md +185 -0
- package/content/plugins/audit/agents/flow-analyzer-navigation.md +177 -0
- package/content/plugins/audit/agents/flow-analyzer-persistence.md +193 -0
- package/content/plugins/audit/agents/flow-analyzer-wiring.md +169 -0
- package/content/plugins/audit/agents/flow-consensus.md +237 -0
- package/content/plugins/audit/agents/legal-analyzer-a11y.md +114 -0
- package/content/plugins/audit/agents/legal-analyzer-ai.md +121 -0
- package/content/plugins/audit/agents/legal-analyzer-consumer.md +114 -0
- package/content/plugins/audit/agents/legal-analyzer-content.md +117 -0
- package/content/plugins/audit/agents/legal-analyzer-international.md +119 -0
- package/content/plugins/audit/agents/legal-analyzer-licensing.md +119 -0
- package/content/plugins/audit/agents/legal-analyzer-privacy.md +112 -0
- package/content/plugins/audit/agents/legal-analyzer-security.md +116 -0
- package/content/plugins/audit/agents/legal-analyzer-terms.md +115 -0
- package/content/plugins/audit/agents/legal-consensus.md +250 -0
- package/content/plugins/audit/agents/logic-analyzer-edge.md +179 -0
- package/content/plugins/audit/agents/logic-analyzer-flow.md +264 -0
- package/content/plugins/audit/agents/logic-analyzer-invariant.md +215 -0
- package/content/plugins/audit/agents/logic-analyzer-race.md +280 -0
- package/content/plugins/audit/agents/logic-analyzer-type.md +227 -0
- package/content/plugins/audit/agents/logic-consensus.md +259 -0
- package/content/plugins/audit/agents/perf-analyzer-assets.md +182 -0
- package/content/plugins/audit/agents/perf-analyzer-bundle.md +173 -0
- package/content/plugins/audit/agents/perf-analyzer-caching.md +170 -0
- package/content/plugins/audit/agents/perf-analyzer-compute.md +173 -0
- package/content/plugins/audit/agents/perf-analyzer-memory.md +193 -0
- package/content/plugins/audit/agents/perf-analyzer-network.md +165 -0
- package/content/plugins/audit/agents/perf-analyzer-queries.md +162 -0
- package/content/plugins/audit/agents/perf-analyzer-rendering.md +168 -0
- package/content/plugins/audit/agents/perf-consensus.md +287 -0
- package/content/plugins/audit/agents/qa.md +820 -0
- package/content/plugins/audit/agents/quality-analyzer-comments.md +159 -0
- package/content/plugins/audit/agents/quality-analyzer-duplication.md +184 -0
- package/content/plugins/audit/agents/quality-analyzer-naming.md +160 -0
- package/content/plugins/audit/agents/quality-consensus.md +241 -0
- package/content/plugins/audit/agents/schema-validator.md +473 -0
- package/content/plugins/audit/agents/security-analyzer-api.md +210 -0
- package/content/plugins/audit/agents/security-analyzer-auth.md +169 -0
- package/content/plugins/audit/agents/security-analyzer-authz.md +180 -0
- package/content/plugins/audit/agents/security-analyzer-deps.md +153 -0
- package/content/plugins/audit/agents/security-analyzer-infra.md +184 -0
- package/content/plugins/audit/agents/security-analyzer-injection.md +155 -0
- package/content/plugins/audit/agents/security-analyzer-input.md +201 -0
- package/content/plugins/audit/agents/security-analyzer-secrets.md +183 -0
- package/content/plugins/audit/agents/security-consensus.md +283 -0
- package/content/plugins/audit/agents/test-analyzer-assertions.md +188 -0
- package/content/plugins/audit/agents/test-analyzer-coverage.md +189 -0
- package/content/plugins/audit/agents/test-analyzer-fragility.md +193 -0
- package/content/plugins/audit/agents/test-analyzer-integration.md +161 -0
- package/content/plugins/audit/agents/test-analyzer-maintenance.md +180 -0
- package/content/plugins/audit/agents/test-analyzer-mocking.md +188 -0
- package/content/plugins/audit/agents/test-analyzer-patterns.md +196 -0
- package/content/plugins/audit/agents/test-analyzer-structure.md +184 -0
- package/content/plugins/audit/agents/test-consensus.md +301 -0
- package/content/plugins/audit/agents/testing.md +561 -0
- package/content/plugins/audit/agents/ui-validator.md +344 -0
- package/content/plugins/audit/plugin.yaml +186 -5
- package/content/plugins/audit/skills/agileflow-audit/SKILL.md +113 -0
- package/content/plugins/audit/skills/agileflow-audit/references/audit-depth-guide.md +151 -0
- package/content/plugins/audit/skills/agileflow-audit/references/dependency-risk-guide.md +139 -0
- package/content/plugins/audit/skills/agileflow-audit/references/owasp-top10.md +120 -0
- package/content/plugins/audit/skills/agileflow-audit/references/performance-budget-guide.md +143 -0
- package/content/plugins/audit/skills/agileflow-audit/references/wcag-criteria.md +117 -0
- package/content/plugins/audit/skills/agileflow-audit/workflows/run-audit.md +52 -0
- package/content/plugins/audit/skills/agileflow-audit/workflows/tdd.md +66 -0
- package/content/plugins/core/agents/adr-writer.md +521 -0
- package/content/plugins/core/agents/epic-planner.md +520 -0
- package/content/plugins/core/agents/mentor.md +709 -0
- package/content/plugins/core/agents/orchestrator.md +776 -0
- package/content/plugins/core/agents/team-coordinator.md +334 -0
- package/content/plugins/core/agents/team-lead.md +181 -0
- package/content/plugins/core/agents/workspace-orchestrator.md +146 -0
- package/content/plugins/core/hooks/context-loader.js +31 -4
- package/content/plugins/core/hooks/damage-control-bash.js +10 -2
- package/content/plugins/core/hooks/damage-control-edit.js +4 -1
- package/content/plugins/core/hooks/damage-control-patterns.yaml +1 -1
- package/content/plugins/core/hooks/damage-control-write.js +4 -1
- package/content/plugins/core/hooks/{pre-compact-state.js → post-compact-state.js} +25 -8
- package/content/plugins/core/hooks/preferences-injector.js +352 -0
- package/content/plugins/core/plugin.yaml +24 -28
- package/content/plugins/core/skills/agileflow-adr/SKILL.md +34 -8
- package/content/plugins/core/skills/agileflow-adr/references/madr-format-guide.md +86 -0
- package/content/plugins/core/skills/agileflow-adr/workflows/write-adr.md +57 -0
- package/content/plugins/core/skills/agileflow-babysit-mentor/SKILL.md +94 -27
- package/content/plugins/core/skills/agileflow-babysit-mentor/references/mentor-decision-guide.md +81 -0
- package/content/plugins/core/skills/agileflow-babysit-mentor/workflows/mentor-session.md +79 -0
- package/content/plugins/core/skills/agileflow-epic-planner/SKILL.md +37 -7
- package/content/plugins/core/skills/agileflow-epic-planner/references/epic-sizing-guide.md +81 -0
- package/content/plugins/core/skills/agileflow-epic-planner/workflows/plan-epic.md +55 -0
- package/content/plugins/core/skills/agileflow-status-updater/SKILL.md +36 -20
- package/content/plugins/core/skills/agileflow-status-updater/references/status-transitions.md +89 -0
- package/content/plugins/core/skills/agileflow-status-updater/workflows/update-status.md +56 -0
- package/content/plugins/core/skills/agileflow-story-writer/SKILL.md +39 -114
- package/content/plugins/core/skills/agileflow-story-writer/references/estimation-reference.md +36 -0
- package/content/plugins/core/skills/agileflow-story-writer/references/story-template.md +92 -0
- package/content/plugins/core/skills/agileflow-story-writer/workflows/write-story.md +138 -0
- package/content/plugins/council/agents/council-advocate.md +223 -0
- package/content/plugins/council/agents/council-analyst.md +278 -0
- package/content/plugins/council/agents/council-compounder.md +204 -0
- package/content/plugins/council/agents/council-contrarian.md +217 -0
- package/content/plugins/council/agents/council-moonshot.md +217 -0
- package/content/plugins/council/agents/council-optimist.md +185 -0
- package/content/plugins/council/agents/council-revenue.md +200 -0
- package/content/plugins/council/agents/council-technical.md +218 -0
- package/content/plugins/council/agents/multi-expert.md +334 -0
- package/content/plugins/council/plugin.yaml +23 -4
- package/content/plugins/council/skills/agileflow-council/SKILL.md +102 -0
- package/content/plugins/council/skills/agileflow-council/references/decision-log-template.md +109 -0
- package/content/plugins/council/skills/agileflow-council/references/perspective-guide.md +104 -0
- package/content/plugins/council/skills/agileflow-council/references/when-to-convene-guide.md +112 -0
- package/content/plugins/council/skills/agileflow-council/workflows/convene.md +73 -0
- package/content/plugins/council/skills/agileflow-council/workflows/multi-expert.md +75 -0
- package/content/plugins/database/plugin.yaml +14 -0
- package/content/plugins/database/skills/agileflow-database/SKILL.md +284 -0
- package/content/plugins/database/skills/agileflow-database/references/indexing-guide.md +313 -0
- package/content/plugins/database/skills/agileflow-database/references/migration-guide.md +328 -0
- package/content/plugins/database/skills/agileflow-database/references/schema-design-guide.md +467 -0
- package/content/plugins/database/skills/agileflow-database/workflows/design-schema.md +213 -0
- package/content/plugins/database/skills/agileflow-database/workflows/optimize-query.md +253 -0
- package/content/plugins/debugging/plugin.yaml +14 -0
- package/content/plugins/debugging/skills/agileflow-debug/SKILL.md +236 -0
- package/content/plugins/debugging/skills/agileflow-debug/references/common-patterns.md +350 -0
- package/content/plugins/debugging/skills/agileflow-debug/references/debugging-strategies.md +328 -0
- package/content/plugins/debugging/skills/agileflow-debug/workflows/debug-issue.md +187 -0
- package/content/plugins/debugging/skills/agileflow-debug/workflows/reproduce-bug.md +194 -0
- package/content/plugins/delivery/agents/ci.md +547 -0
- package/content/plugins/delivery/agents/devops.md +789 -0
- package/content/plugins/delivery/plugin.yaml +19 -0
- package/content/plugins/delivery/skills/agileflow-delivery/SKILL.md +111 -0
- package/content/plugins/delivery/skills/agileflow-delivery/references/changelog-format-guide.md +133 -0
- package/content/plugins/delivery/skills/agileflow-delivery/references/ci-pipeline-guide.md +158 -0
- package/content/plugins/delivery/skills/agileflow-delivery/references/pr-checklist-guide.md +133 -0
- package/content/plugins/delivery/skills/agileflow-delivery/references/release-checklist.md +142 -0
- package/content/plugins/delivery/skills/agileflow-delivery/workflows/changelog.md +72 -0
- package/content/plugins/delivery/skills/agileflow-delivery/workflows/deploy.md +74 -0
- package/content/plugins/delivery/skills/agileflow-delivery/workflows/pr.md +75 -0
- package/content/plugins/docs/agents/documentation.md +544 -0
- package/content/plugins/docs/agents/readme-updater.md +640 -0
- package/content/plugins/docs/plugin.yaml +19 -0
- package/content/plugins/docs/skills/agileflow-docs/SKILL.md +106 -0
- package/content/plugins/docs/skills/agileflow-docs/references/api-doc-template.md +167 -0
- package/content/plugins/docs/skills/agileflow-docs/references/doc-types-guide.md +141 -0
- package/content/plugins/docs/skills/agileflow-docs/references/readme-template.md +156 -0
- package/content/plugins/docs/skills/agileflow-docs/workflows/readme-sync.md +57 -0
- package/content/plugins/docs/skills/agileflow-docs/workflows/sync.md +64 -0
- package/content/plugins/engineering/agents/api.md +718 -0
- package/content/plugins/engineering/agents/codebase-query.md +285 -0
- package/content/plugins/engineering/agents/compliance.md +559 -0
- package/content/plugins/engineering/agents/database.md +644 -0
- package/content/plugins/engineering/agents/integrations.md +644 -0
- package/content/plugins/engineering/agents/mobile.md +552 -0
- package/content/plugins/engineering/agents/monitoring.md +585 -0
- package/content/plugins/engineering/agents/performance.md +529 -0
- package/content/plugins/engineering/agents/refactor.md +592 -0
- package/content/plugins/engineering/agents/security.md +524 -0
- package/content/plugins/engineering/agents/ui.md +1336 -0
- package/content/plugins/engineering/plugin.yaml +37 -0
- package/content/plugins/engineering/skills/agileflow-engineering/SKILL.md +127 -0
- package/content/plugins/engineering/skills/agileflow-engineering/references/code-review-guide.md +126 -0
- package/content/plugins/engineering/skills/agileflow-engineering/references/domain-routing-guide.md +89 -0
- package/content/plugins/engineering/skills/agileflow-engineering/references/refactoring-guide.md +136 -0
- package/content/plugins/engineering/skills/agileflow-engineering/workflows/diagnose.md +63 -0
- package/content/plugins/engineering/skills/agileflow-engineering/workflows/impact.md +60 -0
- package/content/plugins/ideation/agents/brainstorm-analyzer-features.md +179 -0
- package/content/plugins/ideation/agents/brainstorm-analyzer-growth.md +169 -0
- package/content/plugins/ideation/agents/brainstorm-analyzer-integration.md +181 -0
- package/content/plugins/ideation/agents/brainstorm-analyzer-market.md +150 -0
- package/content/plugins/ideation/agents/brainstorm-analyzer-ux.md +180 -0
- package/content/plugins/ideation/agents/brainstorm-consensus.md +245 -0
- package/content/plugins/ideation/agents/design.md +568 -0
- package/content/plugins/ideation/agents/product.md +582 -0
- package/content/plugins/ideation/plugin.yaml +31 -0
- package/content/plugins/ideation/skills/agileflow-ideation/SKILL.md +109 -0
- package/content/plugins/ideation/skills/agileflow-ideation/references/brainstorm-techniques.md +138 -0
- package/content/plugins/ideation/skills/agileflow-ideation/references/competitive-analysis-template.md +148 -0
- package/content/plugins/ideation/skills/agileflow-ideation/references/feature-prioritization-guide.md +147 -0
- package/content/plugins/ideation/skills/agileflow-ideation/references/user-story-patterns.md +152 -0
- package/content/plugins/ideation/skills/agileflow-ideation/workflows/features.md +65 -0
- package/content/plugins/ideation/skills/agileflow-ideation/workflows/ideate.md +54 -0
- package/content/plugins/migration/agents/datamigration.md +757 -0
- package/content/plugins/migration/plugin.yaml +17 -0
- package/content/plugins/migration/skills/agileflow-migration/SKILL.md +106 -0
- package/content/plugins/migration/skills/agileflow-migration/references/data-validation-checklist.md +154 -0
- package/content/plugins/migration/skills/agileflow-migration/references/migration-patterns.md +209 -0
- package/content/plugins/migration/skills/agileflow-migration/references/rollback-playbook.md +171 -0
- package/content/plugins/migration/skills/agileflow-migration/references/version-compatibility-matrix.md +155 -0
- package/content/plugins/migration/skills/agileflow-migration/workflows/plan.md +73 -0
- package/content/plugins/migration/skills/agileflow-migration/workflows/validate.md +71 -0
- package/content/plugins/performance/plugin.yaml +14 -0
- package/content/plugins/performance/skills/agileflow-performance/SKILL.md +224 -0
- package/content/plugins/performance/skills/agileflow-performance/references/optimization-patterns.md +554 -0
- package/content/plugins/performance/skills/agileflow-performance/references/profiling-guide.md +383 -0
- package/content/plugins/performance/skills/agileflow-performance/references/web-vitals-guide.md +360 -0
- package/content/plugins/performance/skills/agileflow-performance/workflows/improve-web-vitals.md +344 -0
- package/content/plugins/performance/skills/agileflow-performance/workflows/profile-and-fix.md +254 -0
- package/content/plugins/planning/agents/analytics.md +670 -0
- package/content/plugins/planning/agents/rlm-subcore.md +215 -0
- package/content/plugins/planning/plugin.yaml +19 -0
- package/content/plugins/planning/skills/agileflow-planning/SKILL.md +111 -0
- package/content/plugins/planning/skills/agileflow-planning/references/estimation-guide.md +114 -0
- package/content/plugins/planning/skills/agileflow-planning/references/rpi-workflow.md +119 -0
- package/content/plugins/planning/skills/agileflow-planning/references/sprint-planning-guide.md +145 -0
- package/content/plugins/planning/skills/agileflow-planning/workflows/impact.md +63 -0
- package/content/plugins/planning/skills/agileflow-planning/workflows/rpi.md +104 -0
- package/content/plugins/psychology/plugin.yaml +14 -0
- package/content/plugins/psychology/skills/agileflow-retention/SKILL.md +252 -0
- package/content/plugins/psychology/skills/agileflow-retention/references/competitor-analysis.md +240 -0
- package/content/plugins/psychology/skills/agileflow-retention/references/psychology-models.md +349 -0
- package/content/plugins/psychology/skills/agileflow-retention/references/retention-patterns.md +279 -0
- package/content/plugins/psychology/skills/agileflow-retention/workflows/design-retention-feature.md +287 -0
- package/content/plugins/psychology/skills/agileflow-retention/workflows/retention-audit.md +259 -0
- package/content/plugins/refactoring/plugin.yaml +14 -0
- package/content/plugins/refactoring/skills/agileflow-refactor/SKILL.md +235 -0
- package/content/plugins/refactoring/skills/agileflow-refactor/references/refactoring-patterns.md +405 -0
- package/content/plugins/refactoring/skills/agileflow-refactor/references/safety-checks.md +177 -0
- package/content/plugins/refactoring/skills/agileflow-refactor/workflows/extract-module.md +226 -0
- package/content/plugins/refactoring/skills/agileflow-refactor/workflows/safe-refactor.md +169 -0
- package/content/plugins/research/agents/research.md +503 -0
- package/content/plugins/research/plugin.yaml +17 -0
- package/content/plugins/research/skills/agileflow-research/SKILL.md +110 -0
- package/content/plugins/research/skills/agileflow-research/references/knowledge-decay-guide.md +121 -0
- package/content/plugins/research/skills/agileflow-research/references/research-prompt-guide.md +141 -0
- package/content/plugins/research/skills/agileflow-research/references/synthesis-template.md +154 -0
- package/content/plugins/research/skills/agileflow-research/workflows/analyze.md +60 -0
- package/content/plugins/research/skills/agileflow-research/workflows/ask.md +64 -0
- package/content/plugins/research/skills/agileflow-research/workflows/import.md +66 -0
- package/content/plugins/research/skills/agileflow-research/workflows/synthesize.md +66 -0
- package/content/plugins/reviews/plugin.yaml +14 -0
- package/content/plugins/reviews/skills/agileflow-pr-reviewer/SKILL.md +241 -0
- package/content/plugins/reviews/skills/agileflow-pr-reviewer/references/review-checklist.md +200 -0
- package/content/plugins/reviews/skills/agileflow-pr-reviewer/references/security-patterns.md +328 -0
- package/content/plugins/reviews/skills/agileflow-pr-reviewer/workflows/review-pr.md +153 -0
- package/content/plugins/reviews/skills/agileflow-pr-reviewer/workflows/security-review.md +177 -0
- package/content/plugins/seo/agents/seo-analyzer-content.md +169 -0
- package/content/plugins/seo/agents/seo-analyzer-images.md +198 -0
- package/content/plugins/seo/agents/seo-analyzer-performance.md +217 -0
- package/content/plugins/seo/agents/seo-analyzer-schema.md +184 -0
- package/content/plugins/seo/agents/seo-analyzer-sitemap.md +177 -0
- package/content/plugins/seo/agents/seo-analyzer-technical.md +151 -0
- package/content/plugins/seo/agents/seo-consensus.md +304 -0
- package/content/plugins/seo/plugin.yaml +19 -4
- package/content/plugins/seo/skills/agileflow-seo/SKILL.md +188 -0
- package/content/plugins/seo/skills/agileflow-seo/references/cwv-thresholds.md +110 -0
- package/content/plugins/seo/skills/agileflow-seo/references/eeat-framework.md +144 -0
- package/content/plugins/seo/skills/agileflow-seo/references/keyword-research-guide.md +125 -0
- package/content/plugins/seo/skills/agileflow-seo/references/schema-types.md +139 -0
- package/content/plugins/seo/skills/agileflow-seo/references/technical-seo-checklist.md +139 -0
- package/content/plugins/seo/skills/agileflow-seo/workflows/audit.md +98 -0
- package/content/plugins/seo/skills/agileflow-seo/workflows/page.md +118 -0
- package/content/plugins/testing/plugin.yaml +16 -0
- package/content/plugins/testing/skills/agileflow-test-writer/SKILL.md +260 -0
- package/content/plugins/testing/skills/agileflow-test-writer/references/coverage-targets.md +239 -0
- package/content/plugins/testing/skills/agileflow-test-writer/references/test-patterns.md +420 -0
- package/content/plugins/testing/skills/agileflow-test-writer/workflows/add-coverage.md +154 -0
- package/content/plugins/testing/skills/agileflow-test-writer/workflows/write-tests-from-ac.md +225 -0
- package/package.json +2 -2
- package/src/cli/commands/doctor.js +818 -30
- package/src/cli/commands/hook.js +17 -14
- package/src/cli/commands/launch.js +1454 -0
- package/src/cli/commands/learn.js +149 -0
- package/src/cli/commands/plugins.js +113 -0
- package/src/cli/commands/setup.js +455 -110
- package/src/cli/commands/skills.js +324 -0
- package/src/cli/commands/status.js +8 -10
- package/src/cli/commands/update.js +76 -15
- package/src/cli/index.js +90 -26
- package/src/cli/wizard/babysit-mode-picker.js +192 -0
- package/src/cli/wizard/behaviors-picker.js +208 -54
- package/src/cli/wizard/ide-picker.js +40 -28
- package/src/cli/wizard/install-scope-picker.js +57 -0
- package/src/cli/wizard/launch-alias-picker.js +50 -0
- package/src/cli/wizard/launch-cli-picker.js +129 -0
- package/src/cli/wizard/launch-tmux-picker.js +133 -0
- package/src/cli/wizard/learnings-picker.js +40 -0
- package/src/cli/wizard/plugin-picker.js +47 -16
- package/src/lib/brand.js +116 -0
- package/src/lib/errors.js +120 -0
- package/src/lib/path-check.js +39 -0
- package/src/runtime/config/defaults.js +22 -17
- package/src/runtime/config/loader.js +77 -8
- package/src/runtime/config/schema.json +43 -16
- package/src/runtime/config/writer.js +3 -1
- package/src/runtime/ide/babysit-skill.js +202 -0
- package/src/runtime/ide/capabilities.js +84 -29
- package/src/runtime/ide/claude-code-content.js +177 -0
- package/src/runtime/ide/claude-code-settings.js +67 -29
- package/src/runtime/ide/claude-code-skills.js +47 -32
- package/src/runtime/ide/codex-config.js +295 -0
- package/src/runtime/installer/install.js +252 -24
- package/src/runtime/launch/alias-installer.js +191 -0
- package/src/runtime/launch/cli-resume.js +244 -0
- package/src/runtime/launch/closed-windows.js +338 -0
- package/src/runtime/launch/defaults.js +66 -0
- package/src/runtime/launch/detect-clis.js +69 -0
- package/src/runtime/launch/doctor.js +464 -0
- package/src/runtime/launch/exec-wrapper.js +114 -0
- package/src/runtime/launch/parallel-session.js +247 -0
- package/src/runtime/launch/prefs.js +211 -0
- package/src/runtime/launch/project-prefs.js +234 -0
- package/src/runtime/launch/resolve-cli.js +56 -0
- package/src/runtime/launch/restore.js +152 -0
- package/src/runtime/launch/schema.json +75 -0
- package/src/runtime/launch/session-lifecycle.js +313 -0
- package/src/runtime/launch/session-registry.js +401 -0
- package/src/runtime/launch/spawn.js +103 -0
- package/src/runtime/launch/tabs.js +350 -0
- package/src/runtime/launch/tmux.js +764 -0
- package/src/runtime/launch/worktree.js +260 -0
- package/src/runtime/plugins/registry.js +16 -11
- package/src/runtime/plugins/validator.js +57 -43
- package/src/runtime/skills/learnings.js +308 -0
- package/content/plugins/core/hooks/babysit-mentor-injector.js +0 -55
- package/src/cli/wizard/personalization.js +0 -64
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a git worktree for `agileflow launch new <name>`.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors v3 `worktree-create.sh` defaults: sibling dir at
|
|
5
|
+
* `../<repo>-<sanitized-name>`, new branch `<sanitized-name>` off the
|
|
6
|
+
* current HEAD (or a caller-supplied base branch). Fails cleanly on the
|
|
7
|
+
* common pre-conditions: not in a repo, target dir already exists,
|
|
8
|
+
* branch already exists.
|
|
9
|
+
*
|
|
10
|
+
* `exec` is injectable so tests don't shell out to git. The exec must
|
|
11
|
+
* return `{ status: number, stdout: string, stderr: string }` (the
|
|
12
|
+
* shape `child_process.spawnSync({ encoding: "utf8" })` produces).
|
|
13
|
+
*/
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
const path = require("path");
|
|
16
|
+
const { spawnSync } = require("child_process");
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {{
|
|
20
|
+
* status: number,
|
|
21
|
+
* stdout: string,
|
|
22
|
+
* stderr: string,
|
|
23
|
+
* }} GitExecResult
|
|
24
|
+
*
|
|
25
|
+
* @typedef {(args: string[]) => GitExecResult} GitExec
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const NAME_SANITIZE = /[^A-Za-z0-9._-]+/g;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build a typed error with a stable `code` so callers can branch on it.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} message
|
|
34
|
+
* @param {string} code
|
|
35
|
+
* @returns {Error}
|
|
36
|
+
*/
|
|
37
|
+
function makeWorktreeError(message, code) {
|
|
38
|
+
const err = new Error(message);
|
|
39
|
+
/** @type {any} */ (err).code = code;
|
|
40
|
+
return err;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Default exec implementation — actually spawns `git` synchronously.
|
|
45
|
+
*
|
|
46
|
+
* @type {GitExec}
|
|
47
|
+
*/
|
|
48
|
+
function defaultGitExec(args) {
|
|
49
|
+
const result = spawnSync("git", args, {
|
|
50
|
+
encoding: "utf8",
|
|
51
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
status: typeof result.status === "number" ? result.status : 1,
|
|
55
|
+
stdout: result.stdout || "",
|
|
56
|
+
stderr: result.stderr || "",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sanitize a user-supplied worktree name. Lets alphanumerics, dot,
|
|
62
|
+
* underscore, and hyphen pass; collapses other characters to `-`.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} name
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
function sanitizeName(name) {
|
|
68
|
+
if (typeof name !== "string") return "";
|
|
69
|
+
return name.replace(NAME_SANITIZE, "-").replace(/^-+|-+$/g, "");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create a new git worktree at `../<repo>-<name>` with branch `<name>`
|
|
74
|
+
* off the current HEAD (or `baseBranch` if supplied).
|
|
75
|
+
*
|
|
76
|
+
* @param {{
|
|
77
|
+
* name: string,
|
|
78
|
+
* baseBranch?: string,
|
|
79
|
+
* exec?: GitExec,
|
|
80
|
+
* fsExists?: (p: string) => boolean,
|
|
81
|
+
* }} opts
|
|
82
|
+
* @returns {{ path: string, branch: string, base: string }}
|
|
83
|
+
*/
|
|
84
|
+
function createWorktree(opts) {
|
|
85
|
+
const exec = opts.exec || defaultGitExec;
|
|
86
|
+
const exists = opts.fsExists || ((p) => fs.existsSync(p));
|
|
87
|
+
|
|
88
|
+
// 1. Must be inside a git work tree.
|
|
89
|
+
const top = exec(["rev-parse", "--show-toplevel"]);
|
|
90
|
+
if (top.status !== 0) {
|
|
91
|
+
throw makeWorktreeError(
|
|
92
|
+
`not in a git repository (${top.stderr.trim() || "rev-parse failed"})`,
|
|
93
|
+
"EWT_NOT_REPO",
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const repoRoot = top.stdout.trim();
|
|
97
|
+
if (!repoRoot) {
|
|
98
|
+
throw makeWorktreeError(
|
|
99
|
+
"git rev-parse --show-toplevel returned no output",
|
|
100
|
+
"EWT_NOT_REPO",
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const repoName = path.basename(repoRoot);
|
|
104
|
+
if (!repoName) {
|
|
105
|
+
// path.basename("/") is "" — degenerate setup (repo at filesystem
|
|
106
|
+
// root). Worktree path would resolve to "/-<name>" which is
|
|
107
|
+
// never what the user wants.
|
|
108
|
+
throw makeWorktreeError(
|
|
109
|
+
`repository root has no name (got "${repoRoot}") — cannot derive worktree path`,
|
|
110
|
+
"EWT_NOT_REPO",
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 2. Sanitize.
|
|
115
|
+
const safe = sanitizeName(opts.name || "");
|
|
116
|
+
if (!safe) {
|
|
117
|
+
throw makeWorktreeError(
|
|
118
|
+
"worktree name is empty after sanitizing",
|
|
119
|
+
"EWT_BAD_NAME",
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 3. Compute target dir; reject if it already exists.
|
|
124
|
+
const wtPath = path.resolve(repoRoot, "..", `${repoName}-${safe}`);
|
|
125
|
+
if (exists(wtPath)) {
|
|
126
|
+
throw makeWorktreeError(
|
|
127
|
+
`worktree directory already exists: ${wtPath}`,
|
|
128
|
+
"EWT_DIR_EXISTS",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 4. Determine base branch.
|
|
133
|
+
let base = opts.baseBranch;
|
|
134
|
+
if (!base) {
|
|
135
|
+
const head = exec(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
136
|
+
if (head.status !== 0) {
|
|
137
|
+
throw makeWorktreeError(
|
|
138
|
+
`could not determine current branch: ${head.stderr.trim()}`,
|
|
139
|
+
"EWT_NO_HEAD",
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
base = head.stdout.trim();
|
|
143
|
+
if (base === "HEAD") {
|
|
144
|
+
// `git rev-parse --abbrev-ref HEAD` returns the literal string
|
|
145
|
+
// "HEAD" when the working tree is in a detached-HEAD state.
|
|
146
|
+
// Passing that to `git worktree add -b` would fail with a less
|
|
147
|
+
// helpful "fatal: invalid reference: HEAD" — fail clearly here.
|
|
148
|
+
throw makeWorktreeError(
|
|
149
|
+
"cannot create worktree from a detached HEAD — check out a branch first",
|
|
150
|
+
"EWT_NO_HEAD",
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 5. New branch must not already exist (otherwise `git worktree add -b`
|
|
156
|
+
// would fail with a less actionable error).
|
|
157
|
+
const refCheck = exec([
|
|
158
|
+
"show-ref",
|
|
159
|
+
"--verify",
|
|
160
|
+
"--quiet",
|
|
161
|
+
`refs/heads/${safe}`,
|
|
162
|
+
]);
|
|
163
|
+
if (refCheck.status === 0) {
|
|
164
|
+
throw makeWorktreeError(
|
|
165
|
+
`branch '${safe}' already exists`,
|
|
166
|
+
"EWT_BRANCH_EXISTS",
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 6. Create it.
|
|
171
|
+
const wt = exec(["worktree", "add", "-b", safe, wtPath, base]);
|
|
172
|
+
if (wt.status !== 0) {
|
|
173
|
+
const stderr = wt.stderr.trim();
|
|
174
|
+
// Map git's "already exists" failures back to the typed codes our
|
|
175
|
+
// pre-check would have thrown — covers the TOCTOU window where
|
|
176
|
+
// another process created the dir or branch between our checks
|
|
177
|
+
// and `git worktree add`. The caller already has actionable hints
|
|
178
|
+
// wired up for EWT_DIR_EXISTS / EWT_BRANCH_EXISTS, but only the
|
|
179
|
+
// generic "re-run with DEBUG=1" for EWT_CREATE.
|
|
180
|
+
if (/refs\/heads\/.*already exists/i.test(stderr)) {
|
|
181
|
+
throw makeWorktreeError(
|
|
182
|
+
`branch '${safe}' already exists`,
|
|
183
|
+
"EWT_BRANCH_EXISTS",
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (/already exists/i.test(stderr)) {
|
|
187
|
+
throw makeWorktreeError(
|
|
188
|
+
`worktree directory already exists: ${wtPath}`,
|
|
189
|
+
"EWT_DIR_EXISTS",
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
throw makeWorktreeError(
|
|
193
|
+
`git worktree add failed: ${stderr || "unknown error"}`,
|
|
194
|
+
"EWT_CREATE",
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return { path: wtPath, branch: safe, base };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Roll back a worktree created by `createWorktree`. Removes both the
|
|
203
|
+
* worktree directory (via `git worktree remove`) and the branch (via
|
|
204
|
+
* `git branch -D`). Used by `parallel-session.js` to keep the repo
|
|
205
|
+
* clean when a tmux session creation fails after the worktree was
|
|
206
|
+
* already established.
|
|
207
|
+
*
|
|
208
|
+
* Best-effort: surfaces partial failures via `removed`/`branchRemoved`
|
|
209
|
+
* flags so the caller can warn the user about what's left behind.
|
|
210
|
+
* Doesn't throw on individual git failures — the goal is rollback,
|
|
211
|
+
* not perfect cleanup.
|
|
212
|
+
*
|
|
213
|
+
* @param {{
|
|
214
|
+
* path: string,
|
|
215
|
+
* branch?: string,
|
|
216
|
+
* exec?: GitExec,
|
|
217
|
+
* }} opts
|
|
218
|
+
* @returns {{
|
|
219
|
+
* removed: boolean,
|
|
220
|
+
* branchRemoved: boolean,
|
|
221
|
+
* stderr: string,
|
|
222
|
+
* }}
|
|
223
|
+
*/
|
|
224
|
+
function removeWorktree(opts) {
|
|
225
|
+
const exec = opts.exec || defaultGitExec;
|
|
226
|
+
let removed = false;
|
|
227
|
+
let branchRemoved = false;
|
|
228
|
+
const stderrParts = [];
|
|
229
|
+
|
|
230
|
+
// `git worktree remove -f` so locked / dirty worktrees still get
|
|
231
|
+
// cleaned up — rollback is a "we just created this, take it back"
|
|
232
|
+
// operation so force is appropriate.
|
|
233
|
+
const wt = exec(["worktree", "remove", "-f", opts.path]);
|
|
234
|
+
if (wt.status === 0) {
|
|
235
|
+
removed = true;
|
|
236
|
+
} else if (wt.stderr) {
|
|
237
|
+
stderrParts.push(`worktree remove: ${wt.stderr.trim()}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Branch removal: only attempted if a branch name was supplied.
|
|
241
|
+
// `git branch -D` force-deletes regardless of merge state.
|
|
242
|
+
if (opts.branch) {
|
|
243
|
+
const br = exec(["branch", "-D", opts.branch]);
|
|
244
|
+
if (br.status === 0) {
|
|
245
|
+
branchRemoved = true;
|
|
246
|
+
} else if (br.stderr) {
|
|
247
|
+
stderrParts.push(`branch -D: ${br.stderr.trim()}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return { removed, branchRemoved, stderr: stderrParts.join("; ") };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
module.exports = {
|
|
255
|
+
createWorktree,
|
|
256
|
+
removeWorktree,
|
|
257
|
+
sanitizeName,
|
|
258
|
+
defaultGitExec,
|
|
259
|
+
makeWorktreeError,
|
|
260
|
+
};
|
|
@@ -5,13 +5,20 @@
|
|
|
5
5
|
* (depends resolution, cycle detection, command/skill cross-refs) lands
|
|
6
6
|
* with the full validator in Phase 2b.
|
|
7
7
|
*/
|
|
8
|
-
const fs = require(
|
|
9
|
-
const path = require(
|
|
10
|
-
const yaml = require(
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const yaml = require("js-yaml");
|
|
11
11
|
|
|
12
|
-
const PLUGINS_DIR = path.join(
|
|
12
|
+
const PLUGINS_DIR = path.join(
|
|
13
|
+
__dirname,
|
|
14
|
+
"..",
|
|
15
|
+
"..",
|
|
16
|
+
"..",
|
|
17
|
+
"content",
|
|
18
|
+
"plugins",
|
|
19
|
+
);
|
|
13
20
|
|
|
14
|
-
const REQUIRED_FIELDS = [
|
|
21
|
+
const REQUIRED_FIELDS = ["id", "name", "description", "version"];
|
|
15
22
|
|
|
16
23
|
/**
|
|
17
24
|
* @typedef {Object} PluginManifest
|
|
@@ -23,7 +30,6 @@ const REQUIRED_FIELDS = ['id', 'name', 'description', 'version'];
|
|
|
23
30
|
* @property {boolean} [cannotDisable]
|
|
24
31
|
* @property {string[]} [depends]
|
|
25
32
|
* @property {{
|
|
26
|
-
* commands?: object[],
|
|
27
33
|
* skills?: object[],
|
|
28
34
|
* agents?: object[],
|
|
29
35
|
* hooks?: object[],
|
|
@@ -38,13 +44,13 @@ const REQUIRED_FIELDS = ['id', 'name', 'description', 'version'];
|
|
|
38
44
|
* @returns {PluginManifest}
|
|
39
45
|
*/
|
|
40
46
|
function loadPlugin(pluginDir) {
|
|
41
|
-
const manifestPath = path.join(pluginDir,
|
|
47
|
+
const manifestPath = path.join(pluginDir, "plugin.yaml");
|
|
42
48
|
if (!fs.existsSync(manifestPath)) {
|
|
43
49
|
throw new Error(`Missing plugin.yaml at ${pluginDir}`);
|
|
44
50
|
}
|
|
45
51
|
let raw;
|
|
46
52
|
try {
|
|
47
|
-
raw = fs.readFileSync(manifestPath,
|
|
53
|
+
raw = fs.readFileSync(manifestPath, "utf8");
|
|
48
54
|
} catch (err) {
|
|
49
55
|
throw new Error(`Cannot read ${manifestPath}: ${err.message}`);
|
|
50
56
|
}
|
|
@@ -54,13 +60,13 @@ function loadPlugin(pluginDir) {
|
|
|
54
60
|
} catch (err) {
|
|
55
61
|
throw new Error(`Invalid YAML in ${manifestPath}: ${err.message}`);
|
|
56
62
|
}
|
|
57
|
-
if (!parsed || typeof parsed !==
|
|
63
|
+
if (!parsed || typeof parsed !== "object") {
|
|
58
64
|
throw new Error(`Empty or non-object plugin.yaml at ${manifestPath}`);
|
|
59
65
|
}
|
|
60
66
|
const missing = REQUIRED_FIELDS.filter((k) => parsed[k] == null);
|
|
61
67
|
if (missing.length) {
|
|
62
68
|
throw new Error(
|
|
63
|
-
`Plugin ${path.basename(pluginDir)} missing required fields: ${missing.join(
|
|
69
|
+
`Plugin ${path.basename(pluginDir)} missing required fields: ${missing.join(", ")}`,
|
|
64
70
|
);
|
|
65
71
|
}
|
|
66
72
|
// `depends` is optional, but if present it MUST be an array — silently
|
|
@@ -83,7 +89,6 @@ function loadPlugin(pluginDir) {
|
|
|
83
89
|
cannotDisable: Boolean(parsed.cannotDisable),
|
|
84
90
|
depends,
|
|
85
91
|
provides: parsed.provides || {
|
|
86
|
-
commands: [],
|
|
87
92
|
skills: [],
|
|
88
93
|
agents: [],
|
|
89
94
|
hooks: [],
|
|
@@ -26,13 +26,7 @@ const SEMVER_PATTERN =
|
|
|
26
26
|
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
27
27
|
|
|
28
28
|
/** @type {ReadonlySet<string>} */
|
|
29
|
-
const VALID_PROVIDES_KEYS = new Set([
|
|
30
|
-
'commands',
|
|
31
|
-
'skills',
|
|
32
|
-
'agents',
|
|
33
|
-
'hooks',
|
|
34
|
-
'templates',
|
|
35
|
-
]);
|
|
29
|
+
const VALID_PROVIDES_KEYS = new Set(["skills", "agents", "hooks", "templates"]);
|
|
36
30
|
|
|
37
31
|
/**
|
|
38
32
|
* Validate a single plugin manifest. Pure: no I/O.
|
|
@@ -43,18 +37,26 @@ const VALID_PROVIDES_KEYS = new Set([
|
|
|
43
37
|
function validatePlugin(plugin) {
|
|
44
38
|
/** @type {Issue[]} */
|
|
45
39
|
const issues = [];
|
|
46
|
-
const id = plugin && typeof plugin.id ===
|
|
47
|
-
|
|
48
|
-
const error = (msg) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
const id = plugin && typeof plugin.id === "string" ? plugin.id : "<unknown>";
|
|
41
|
+
|
|
42
|
+
const error = (msg) =>
|
|
43
|
+
issues.push({ severity: "error", pluginId: id, message: msg });
|
|
44
|
+
const warn = (msg) =>
|
|
45
|
+
issues.push({ severity: "warning", pluginId: id, message: msg });
|
|
46
|
+
|
|
47
|
+
if (!plugin || typeof plugin !== "object") {
|
|
48
|
+
return [
|
|
49
|
+
{
|
|
50
|
+
severity: "error",
|
|
51
|
+
pluginId: id,
|
|
52
|
+
message: "Plugin manifest is not an object.",
|
|
53
|
+
},
|
|
54
|
+
];
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
// id format
|
|
56
|
-
if (typeof plugin.id !==
|
|
57
|
-
error(
|
|
58
|
+
if (typeof plugin.id !== "string") {
|
|
59
|
+
error("`id` must be a string.");
|
|
58
60
|
} else if (!ID_PATTERN.test(plugin.id)) {
|
|
59
61
|
error(
|
|
60
62
|
`\`id\` "${plugin.id}" must match /^[a-z0-9][a-z0-9-]{0,63}$/ (lowercase, kebab-case, max 64 chars).`,
|
|
@@ -62,52 +64,60 @@ function validatePlugin(plugin) {
|
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
// name
|
|
65
|
-
if (typeof plugin.name !==
|
|
66
|
-
error(
|
|
67
|
+
if (typeof plugin.name !== "string" || !plugin.name.trim()) {
|
|
68
|
+
error("`name` must be a non-empty string.");
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
// description
|
|
70
|
-
if (typeof plugin.description !==
|
|
71
|
-
error(
|
|
72
|
+
if (typeof plugin.description !== "string" || !plugin.description.trim()) {
|
|
73
|
+
error("`description` must be a non-empty string.");
|
|
72
74
|
} else if (plugin.description.length < 16) {
|
|
73
|
-
warn(
|
|
75
|
+
warn(
|
|
76
|
+
"`description` is very short — aim for at least one meaningful sentence.",
|
|
77
|
+
);
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
// version
|
|
77
|
-
if (typeof plugin.version !==
|
|
78
|
-
error(
|
|
81
|
+
if (typeof plugin.version !== "string") {
|
|
82
|
+
error("`version` must be a string (semver).");
|
|
79
83
|
} else if (!SEMVER_PATTERN.test(plugin.version)) {
|
|
80
|
-
error(
|
|
84
|
+
error(
|
|
85
|
+
`\`version\` "${plugin.version}" must be a valid semver (MAJOR.MINOR.PATCH).`,
|
|
86
|
+
);
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
// booleans
|
|
84
|
-
if (typeof plugin.enabledByDefault !==
|
|
85
|
-
error(
|
|
90
|
+
if (typeof plugin.enabledByDefault !== "boolean") {
|
|
91
|
+
error("`enabledByDefault` must be a boolean.");
|
|
86
92
|
}
|
|
87
|
-
if (typeof plugin.cannotDisable !==
|
|
88
|
-
error(
|
|
93
|
+
if (typeof plugin.cannotDisable !== "boolean") {
|
|
94
|
+
error("`cannotDisable` must be a boolean.");
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
// cannotDisable implies enabledByDefault
|
|
92
98
|
if (plugin.cannotDisable === true && plugin.enabledByDefault === false) {
|
|
93
|
-
error(
|
|
99
|
+
error(
|
|
100
|
+
"A plugin with `cannotDisable: true` must also have `enabledByDefault: true`.",
|
|
101
|
+
);
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
// depends
|
|
97
105
|
if (!Array.isArray(plugin.depends)) {
|
|
98
|
-
error(
|
|
106
|
+
error("`depends` must be an array of plugin ids.");
|
|
99
107
|
} else {
|
|
100
108
|
for (const dep of plugin.depends) {
|
|
101
|
-
if (typeof dep !==
|
|
102
|
-
error(
|
|
109
|
+
if (typeof dep !== "string" || !ID_PATTERN.test(dep)) {
|
|
110
|
+
error(
|
|
111
|
+
`\`depends\` entry ${JSON.stringify(dep)} must be a valid plugin id.`,
|
|
112
|
+
);
|
|
103
113
|
}
|
|
104
|
-
if (typeof dep ===
|
|
105
|
-
error(
|
|
114
|
+
if (typeof dep === "string" && dep === plugin.id) {
|
|
115
|
+
error("A plugin cannot depend on itself.");
|
|
106
116
|
}
|
|
107
117
|
}
|
|
108
118
|
const seen = new Set();
|
|
109
119
|
for (const dep of plugin.depends) {
|
|
110
|
-
if (typeof dep ===
|
|
120
|
+
if (typeof dep === "string") {
|
|
111
121
|
if (seen.has(dep)) {
|
|
112
122
|
warn(`Duplicate dependency "${dep}" in \`depends\` (deduplicate).`);
|
|
113
123
|
}
|
|
@@ -118,12 +128,16 @@ function validatePlugin(plugin) {
|
|
|
118
128
|
|
|
119
129
|
// provides — allowed shape
|
|
120
130
|
if (plugin.provides != null) {
|
|
121
|
-
if (typeof plugin.provides !==
|
|
122
|
-
error(
|
|
131
|
+
if (typeof plugin.provides !== "object" || Array.isArray(plugin.provides)) {
|
|
132
|
+
error(
|
|
133
|
+
"`provides` must be an object with arrays of skills/agents/hooks/templates.",
|
|
134
|
+
);
|
|
123
135
|
} else {
|
|
124
136
|
for (const key of Object.keys(plugin.provides)) {
|
|
125
137
|
if (!VALID_PROVIDES_KEYS.has(key)) {
|
|
126
|
-
warn(
|
|
138
|
+
warn(
|
|
139
|
+
`\`provides.${key}\` is not a recognized key — expected one of: ${[...VALID_PROVIDES_KEYS].join(", ")}.`,
|
|
140
|
+
);
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
143
|
for (const key of VALID_PROVIDES_KEYS) {
|
|
@@ -154,10 +168,10 @@ function validatePluginSet(plugins) {
|
|
|
154
168
|
}
|
|
155
169
|
const ids = new Set();
|
|
156
170
|
for (const p of plugins) {
|
|
157
|
-
if (typeof p.id ===
|
|
171
|
+
if (typeof p.id === "string") {
|
|
158
172
|
if (ids.has(p.id)) {
|
|
159
173
|
issues.push({
|
|
160
|
-
severity:
|
|
174
|
+
severity: "error",
|
|
161
175
|
pluginId: p.id,
|
|
162
176
|
message: `Duplicate plugin id "${p.id}".`,
|
|
163
177
|
});
|
|
@@ -167,9 +181,9 @@ function validatePluginSet(plugins) {
|
|
|
167
181
|
}
|
|
168
182
|
for (const p of plugins) {
|
|
169
183
|
for (const dep of p.depends || []) {
|
|
170
|
-
if (typeof dep ===
|
|
184
|
+
if (typeof dep === "string" && !ids.has(dep)) {
|
|
171
185
|
issues.push({
|
|
172
|
-
severity:
|
|
186
|
+
severity: "error",
|
|
173
187
|
pluginId: p.id,
|
|
174
188
|
message: `Depends on unknown plugin "${dep}".`,
|
|
175
189
|
});
|
|
@@ -184,7 +198,7 @@ function validatePluginSet(plugins) {
|
|
|
184
198
|
* @returns {boolean}
|
|
185
199
|
*/
|
|
186
200
|
function hasErrors(issues) {
|
|
187
|
-
return issues.some((i) => i.severity ===
|
|
201
|
+
return issues.some((i) => i.severity === "error");
|
|
188
202
|
}
|
|
189
203
|
|
|
190
204
|
module.exports = {
|