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,464 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health checks behind `agileflow launch doctor`.
|
|
3
|
+
*
|
|
4
|
+
* Read-only diagnostics. Every check returns a structured result so the
|
|
5
|
+
* CLI wrapper can render a consistent table AND a test can assert on each
|
|
6
|
+
* check in isolation. No auto-remediation here — surfacing fixes is a
|
|
7
|
+
* later slice.
|
|
8
|
+
*
|
|
9
|
+
* Result shape:
|
|
10
|
+
* { id, status: 'pass' | 'warn' | 'fail', message: string, fix?: string }
|
|
11
|
+
*
|
|
12
|
+
* - pass: everything is fine
|
|
13
|
+
* - warn: degraded but launch will still work (e.g., one fallback CLI
|
|
14
|
+
* missing from PATH)
|
|
15
|
+
* - fail: launch will fail or behave wrong (e.g., tmux not installed,
|
|
16
|
+
* preferred CLI not on PATH, orphan worktree references)
|
|
17
|
+
*
|
|
18
|
+
* The CLI exits non-zero iff ANY check returns 'fail'. Warnings don't
|
|
19
|
+
* fail the doctor — they're for the user to triage.
|
|
20
|
+
*/
|
|
21
|
+
const fs = require("fs");
|
|
22
|
+
|
|
23
|
+
const { commandExists: realCommandExists } = require("../../lib/path-check.js");
|
|
24
|
+
const { defaultRunner } = require("./tmux.js");
|
|
25
|
+
const { loadPrefs } = require("./prefs.js");
|
|
26
|
+
const { loadRegistry, registryPath } = require("./session-registry.js");
|
|
27
|
+
const { findCli } = require("./detect-clis.js");
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} DoctorCheck
|
|
31
|
+
* @property {string} id
|
|
32
|
+
* @property {'pass' | 'warn' | 'fail'} status
|
|
33
|
+
* @property {string} message
|
|
34
|
+
* @property {string} [fix]
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Minimum tmux version required by `status-position` (used by prefs). */
|
|
38
|
+
const MIN_TMUX_VERSION = { major: 2, minor: 1 };
|
|
39
|
+
/** Lockfile is considered stuck after this many ms (matches registry's LOCK_STALE_MS). */
|
|
40
|
+
const STALE_LOCK_MS = 5000;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Parse the output of `tmux -V` into { major, minor }. Returns null when
|
|
44
|
+
* the string doesn't match the expected `tmux <major>.<minor>...` shape.
|
|
45
|
+
*
|
|
46
|
+
* tmux versions look like: "tmux 3.3a", "tmux next-3.4", "tmux 2.1".
|
|
47
|
+
* We extract the first M.N pair and ignore any suffix.
|
|
48
|
+
*
|
|
49
|
+
* @param {string} raw
|
|
50
|
+
* @returns {{ major: number, minor: number } | null}
|
|
51
|
+
*/
|
|
52
|
+
function parseTmuxVersion(raw) {
|
|
53
|
+
if (typeof raw !== "string") return null;
|
|
54
|
+
const match = raw.match(/(\d+)\.(\d+)/);
|
|
55
|
+
if (!match) return null;
|
|
56
|
+
return { major: Number(match[1]), minor: Number(match[2]) };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {{ major: number, minor: number }} a
|
|
61
|
+
* @param {{ major: number, minor: number }} b
|
|
62
|
+
* @returns {number}
|
|
63
|
+
*/
|
|
64
|
+
function compareVersions(a, b) {
|
|
65
|
+
if (a.major !== b.major) return a.major - b.major;
|
|
66
|
+
return a.minor - b.minor;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check #1: tmux installed.
|
|
71
|
+
*
|
|
72
|
+
* @param {{ commandExists?: typeof realCommandExists }} [deps]
|
|
73
|
+
* @returns {DoctorCheck}
|
|
74
|
+
*/
|
|
75
|
+
function checkTmuxInstalled(deps = {}) {
|
|
76
|
+
const exists = deps.commandExists || realCommandExists;
|
|
77
|
+
if (exists("tmux")) {
|
|
78
|
+
return { id: "tmux-installed", status: "pass", message: "tmux is on PATH" };
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
id: "tmux-installed",
|
|
82
|
+
status: "fail",
|
|
83
|
+
message: "tmux is not on PATH",
|
|
84
|
+
fix: "install tmux (e.g., `brew install tmux` / `apt install tmux`) and re-run",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Check #2: tmux version supports the features prefs depend on
|
|
90
|
+
* (`status-position` landed in tmux 2.1).
|
|
91
|
+
*
|
|
92
|
+
* Skipped (returns 'warn') when tmux isn't installed — the install check
|
|
93
|
+
* already failed, so emitting a second fail here would be noise.
|
|
94
|
+
*
|
|
95
|
+
* @param {{
|
|
96
|
+
* commandExists?: typeof realCommandExists,
|
|
97
|
+
* runner?: import("./tmux.js").TmuxRunner,
|
|
98
|
+
* }} [deps]
|
|
99
|
+
* @returns {DoctorCheck}
|
|
100
|
+
*/
|
|
101
|
+
function checkTmuxVersion(deps = {}) {
|
|
102
|
+
const exists = deps.commandExists || realCommandExists;
|
|
103
|
+
if (!exists("tmux")) {
|
|
104
|
+
return {
|
|
105
|
+
id: "tmux-version",
|
|
106
|
+
status: "warn",
|
|
107
|
+
message: "tmux not installed — version check skipped",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const runner = deps.runner || defaultRunner();
|
|
111
|
+
const res = runner.runSync(["-V"]);
|
|
112
|
+
const parsed = parseTmuxVersion(res.stdout);
|
|
113
|
+
if (!parsed) {
|
|
114
|
+
return {
|
|
115
|
+
id: "tmux-version",
|
|
116
|
+
status: "warn",
|
|
117
|
+
message: `could not parse tmux version (output: ${(res.stdout || "").trim() || "<empty>"})`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (compareVersions(parsed, MIN_TMUX_VERSION) < 0) {
|
|
121
|
+
return {
|
|
122
|
+
id: "tmux-version",
|
|
123
|
+
status: "fail",
|
|
124
|
+
message: `tmux ${parsed.major}.${parsed.minor} is older than required ${MIN_TMUX_VERSION.major}.${MIN_TMUX_VERSION.minor}`,
|
|
125
|
+
fix: "upgrade tmux — status-position requires 2.1+",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
id: "tmux-version",
|
|
130
|
+
status: "pass",
|
|
131
|
+
message: `tmux ${parsed.major}.${parsed.minor} (>= ${MIN_TMUX_VERSION.major}.${MIN_TMUX_VERSION.minor})`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Check #3: prefs file loads cleanly (or is absent → warn, not fail —
|
|
137
|
+
* `agileflow launch` walks the user through setup on first run).
|
|
138
|
+
*
|
|
139
|
+
* @param {{ loadPrefsImpl?: typeof loadPrefs, home?: string }} [deps]
|
|
140
|
+
* @returns {Promise<DoctorCheck>}
|
|
141
|
+
*/
|
|
142
|
+
async function checkPrefsLoad(deps = {}) {
|
|
143
|
+
const impl = deps.loadPrefsImpl || loadPrefs;
|
|
144
|
+
try {
|
|
145
|
+
const { source, path: file } = await impl(deps.home);
|
|
146
|
+
if (source === "defaults") {
|
|
147
|
+
return {
|
|
148
|
+
id: "prefs-load",
|
|
149
|
+
status: "warn",
|
|
150
|
+
message: "no prefs file yet (running with defaults)",
|
|
151
|
+
fix: "run `agileflow launch setup` to lock in your preferences",
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
id: "prefs-load",
|
|
156
|
+
status: "pass",
|
|
157
|
+
message: `prefs load cleanly from ${file}`,
|
|
158
|
+
};
|
|
159
|
+
} catch (err) {
|
|
160
|
+
return {
|
|
161
|
+
id: "prefs-load",
|
|
162
|
+
status: "fail",
|
|
163
|
+
message: err && err.message ? err.message : String(err),
|
|
164
|
+
fix: "fix or delete the prefs file and re-run `agileflow launch setup`",
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Check #4: every CLI in prefs.cli.fallbackOrder is resolvable on PATH.
|
|
171
|
+
* 'warn' if some are missing but the preferred is present (launch still
|
|
172
|
+
* works). 'fail' if the preferred itself is missing — launch will error
|
|
173
|
+
* out.
|
|
174
|
+
*
|
|
175
|
+
* Returns 'warn' (skipped) if prefs aren't loadable, because the prefs
|
|
176
|
+
* check above will already have failed and we'd just be re-shouting.
|
|
177
|
+
*
|
|
178
|
+
* @param {{
|
|
179
|
+
* loadPrefsImpl?: typeof loadPrefs,
|
|
180
|
+
* commandExists?: typeof realCommandExists,
|
|
181
|
+
* home?: string,
|
|
182
|
+
* }} [deps]
|
|
183
|
+
* @returns {Promise<DoctorCheck>}
|
|
184
|
+
*/
|
|
185
|
+
async function checkFallbackClisOnPath(deps = {}) {
|
|
186
|
+
const impl = deps.loadPrefsImpl || loadPrefs;
|
|
187
|
+
const exists = deps.commandExists || realCommandExists;
|
|
188
|
+
let prefs;
|
|
189
|
+
try {
|
|
190
|
+
const loaded = await impl(deps.home);
|
|
191
|
+
prefs = loaded.prefs;
|
|
192
|
+
} catch {
|
|
193
|
+
return {
|
|
194
|
+
id: "cli-on-path",
|
|
195
|
+
status: "warn",
|
|
196
|
+
message: "prefs unreadable — cli check skipped",
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const order = prefs.cli.fallbackOrder || [];
|
|
200
|
+
const missing = [];
|
|
201
|
+
for (const id of order) {
|
|
202
|
+
const desc = findCli(id);
|
|
203
|
+
const bin = desc ? desc.bin : id;
|
|
204
|
+
if (!exists(bin)) missing.push(id);
|
|
205
|
+
}
|
|
206
|
+
if (missing.length === 0) {
|
|
207
|
+
return {
|
|
208
|
+
id: "cli-on-path",
|
|
209
|
+
status: "pass",
|
|
210
|
+
message: `all ${order.length} configured CLI(s) on PATH`,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const preferredMissing = missing.includes(prefs.cli.preferred);
|
|
214
|
+
if (preferredMissing) {
|
|
215
|
+
return {
|
|
216
|
+
id: "cli-on-path",
|
|
217
|
+
status: "fail",
|
|
218
|
+
message: `preferred CLI "${prefs.cli.preferred}" is not on PATH (also missing: ${missing.filter((m) => m !== prefs.cli.preferred).join(", ") || "none"})`,
|
|
219
|
+
fix: "install the CLI, or run `agileflow launch setup` to switch preferred",
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
id: "cli-on-path",
|
|
224
|
+
status: "warn",
|
|
225
|
+
message: `${missing.length} fallback CLI(s) not on PATH: ${missing.join(", ")}`,
|
|
226
|
+
fix: "install them or remove from fallbackOrder via `agileflow launch setup`",
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Check #5: registry file loads cleanly. `loadRegistry` is resilient
|
|
232
|
+
* (returns empty on malformed JSON instead of throwing) but it also
|
|
233
|
+
* emits a stderr warning on I/O errors — that warning is the signal
|
|
234
|
+
* we want to surface here. We re-read the file directly to distinguish
|
|
235
|
+
* "absent" (fine) from "present but unreadable" (fail).
|
|
236
|
+
*
|
|
237
|
+
* @param {{
|
|
238
|
+
* home?: string,
|
|
239
|
+
* readFileSync?: typeof fs.readFileSync,
|
|
240
|
+
* existsSync?: typeof fs.existsSync,
|
|
241
|
+
* loadRegistryImpl?: typeof loadRegistry,
|
|
242
|
+
* }} [deps]
|
|
243
|
+
* @returns {DoctorCheck}
|
|
244
|
+
*/
|
|
245
|
+
function checkRegistryLoads(deps = {}) {
|
|
246
|
+
const readFileSync = deps.readFileSync || fs.readFileSync;
|
|
247
|
+
const existsSync = deps.existsSync || fs.existsSync;
|
|
248
|
+
const loadImpl = deps.loadRegistryImpl || loadRegistry;
|
|
249
|
+
const file = registryPath(deps.home);
|
|
250
|
+
if (!existsSync(file)) {
|
|
251
|
+
return {
|
|
252
|
+
id: "registry-load",
|
|
253
|
+
status: "pass",
|
|
254
|
+
message: "no registry yet (0 sessions tracked)",
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
let raw;
|
|
258
|
+
try {
|
|
259
|
+
raw = readFileSync(file, "utf8");
|
|
260
|
+
} catch (err) {
|
|
261
|
+
return {
|
|
262
|
+
id: "registry-load",
|
|
263
|
+
status: "fail",
|
|
264
|
+
message: `cannot read ${file}: ${err && err.message ? err.message : err}`,
|
|
265
|
+
fix: "check file permissions, or delete the file to start fresh",
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/** @type {unknown} */
|
|
269
|
+
let parsed;
|
|
270
|
+
try {
|
|
271
|
+
parsed = JSON.parse(raw);
|
|
272
|
+
} catch {
|
|
273
|
+
return {
|
|
274
|
+
id: "registry-load",
|
|
275
|
+
status: "fail",
|
|
276
|
+
message: `${file} is not valid JSON`,
|
|
277
|
+
fix: "fix the JSON by hand, or delete the file (you'll lose saved sessions)",
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
// Count malformed entries within the SAME parsed snapshot so a
|
|
281
|
+
// concurrent write between reads can't produce a false positive.
|
|
282
|
+
// (We replicate loadRegistry's filter inline rather than re-reading.)
|
|
283
|
+
const rawSessions =
|
|
284
|
+
parsed && typeof parsed === "object" && Array.isArray(parsed.sessions)
|
|
285
|
+
? parsed.sessions
|
|
286
|
+
: [];
|
|
287
|
+
let saneCount = 0;
|
|
288
|
+
for (const s of rawSessions) {
|
|
289
|
+
if (!s || typeof s !== "object") continue;
|
|
290
|
+
if (typeof s.name !== "string" || !s.name) continue;
|
|
291
|
+
if (typeof s.cli !== "string" || !s.cli) continue;
|
|
292
|
+
if (typeof s.cwd !== "string" || !s.cwd) continue;
|
|
293
|
+
saneCount++;
|
|
294
|
+
}
|
|
295
|
+
const rejected = rawSessions.length - saneCount;
|
|
296
|
+
if (rejected > 0) {
|
|
297
|
+
return {
|
|
298
|
+
id: "registry-load",
|
|
299
|
+
status: "warn",
|
|
300
|
+
message: `${rejected} registry entry(ies) rejected as malformed (kept ${saneCount})`,
|
|
301
|
+
fix: "inspect the registry file; malformed entries are silently filtered on load",
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// loadRegistry-side sanity check: surface the count the rest of the
|
|
305
|
+
// launch flow will actually see. Reads the file again but only to
|
|
306
|
+
// produce the message — any race only affects the displayed count, not
|
|
307
|
+
// the pass/warn/fail verdict above.
|
|
308
|
+
const sane = loadImpl(deps.home).sessions;
|
|
309
|
+
return {
|
|
310
|
+
id: "registry-load",
|
|
311
|
+
status: "pass",
|
|
312
|
+
message: `registry loads cleanly (${sane.length} session(s))`,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Check #6: the registry lockfile isn't stuck. A lockfile older than
|
|
318
|
+
* STALE_LOCK_MS that hasn't been cleaned up suggests an `__exec` /
|
|
319
|
+
* `recordSession` process crashed mid-write. The lock helper takes
|
|
320
|
+
* over stale locks automatically, but reporting it here helps the user
|
|
321
|
+
* understand intermittent registry weirdness.
|
|
322
|
+
*
|
|
323
|
+
* @param {{
|
|
324
|
+
* home?: string,
|
|
325
|
+
* statSync?: typeof fs.statSync,
|
|
326
|
+
* existsSync?: typeof fs.existsSync,
|
|
327
|
+
* now?: () => number,
|
|
328
|
+
* }} [deps]
|
|
329
|
+
* @returns {DoctorCheck}
|
|
330
|
+
*/
|
|
331
|
+
function checkStaleLockfile(deps = {}) {
|
|
332
|
+
const statSync = deps.statSync || fs.statSync;
|
|
333
|
+
const existsSync = deps.existsSync || fs.existsSync;
|
|
334
|
+
const now = deps.now || (() => Date.now());
|
|
335
|
+
const lock = registryPath(deps.home) + ".lock";
|
|
336
|
+
if (!existsSync(lock)) {
|
|
337
|
+
return {
|
|
338
|
+
id: "stale-lockfile",
|
|
339
|
+
status: "pass",
|
|
340
|
+
message: "no registry lockfile present",
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
let stat;
|
|
344
|
+
try {
|
|
345
|
+
stat = statSync(lock);
|
|
346
|
+
} catch {
|
|
347
|
+
return {
|
|
348
|
+
id: "stale-lockfile",
|
|
349
|
+
status: "pass",
|
|
350
|
+
message: "lockfile vanished mid-check (benign)",
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const age = now() - (stat.mtimeMs || 0);
|
|
354
|
+
if (age > STALE_LOCK_MS) {
|
|
355
|
+
return {
|
|
356
|
+
id: "stale-lockfile",
|
|
357
|
+
status: "warn",
|
|
358
|
+
message: `registry lockfile is ${Math.round(age / 1000)}s old (stale; will be auto-recovered)`,
|
|
359
|
+
fix: `remove ${lock} if the warning persists`,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
id: "stale-lockfile",
|
|
364
|
+
status: "pass",
|
|
365
|
+
message: `lockfile fresh (${age}ms old)`,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Check #7: every registered worktree's path still exists on disk.
|
|
371
|
+
* Mismatches mean someone `git worktree remove`'d the dir behind our
|
|
372
|
+
* back, or the project itself was deleted. Surfacing them lets the user
|
|
373
|
+
* `agileflow launch kill <name>` or `agileflow launch prune` to tidy up.
|
|
374
|
+
*
|
|
375
|
+
* @param {{
|
|
376
|
+
* home?: string,
|
|
377
|
+
* existsSync?: typeof fs.existsSync,
|
|
378
|
+
* loadRegistryImpl?: typeof loadRegistry,
|
|
379
|
+
* }} [deps]
|
|
380
|
+
* @returns {DoctorCheck}
|
|
381
|
+
*/
|
|
382
|
+
function checkOrphanWorktrees(deps = {}) {
|
|
383
|
+
const existsSync = deps.existsSync || fs.existsSync;
|
|
384
|
+
const loadImpl = deps.loadRegistryImpl || loadRegistry;
|
|
385
|
+
const reg = loadImpl(deps.home);
|
|
386
|
+
/** @type {Array<{ name: string, path: string }>} */
|
|
387
|
+
const orphans = [];
|
|
388
|
+
for (const entry of reg.sessions) {
|
|
389
|
+
if (!entry.worktree || !entry.worktree.path) continue;
|
|
390
|
+
if (!existsSync(entry.worktree.path)) {
|
|
391
|
+
orphans.push({ name: entry.name, path: entry.worktree.path });
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (orphans.length === 0) {
|
|
395
|
+
return {
|
|
396
|
+
id: "orphan-worktrees",
|
|
397
|
+
status: "pass",
|
|
398
|
+
message: "no orphan worktrees",
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const list = orphans.map((o) => `${o.name} → ${o.path}`).join("; ");
|
|
402
|
+
return {
|
|
403
|
+
id: "orphan-worktrees",
|
|
404
|
+
status: "warn",
|
|
405
|
+
message: `${orphans.length} registered worktree path(s) missing: ${list}`,
|
|
406
|
+
fix: "run `agileflow launch prune` to forget orphan entries",
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Run every check and return a structured report. The CLI wrapper renders
|
|
412
|
+
* the result; this helper does no I/O of its own beyond the deps.
|
|
413
|
+
*
|
|
414
|
+
* @param {{
|
|
415
|
+
* home?: string,
|
|
416
|
+
* runner?: import("./tmux.js").TmuxRunner,
|
|
417
|
+
* commandExists?: typeof realCommandExists,
|
|
418
|
+
* loadPrefsImpl?: typeof loadPrefs,
|
|
419
|
+
* loadRegistryImpl?: typeof loadRegistry,
|
|
420
|
+
* existsSync?: typeof fs.existsSync,
|
|
421
|
+
* statSync?: typeof fs.statSync,
|
|
422
|
+
* readFileSync?: typeof fs.readFileSync,
|
|
423
|
+
* now?: () => number,
|
|
424
|
+
* }} [deps]
|
|
425
|
+
* @returns {Promise<{ checks: DoctorCheck[] }>}
|
|
426
|
+
*/
|
|
427
|
+
async function runDoctorChecks(deps = {}) {
|
|
428
|
+
const checks = [
|
|
429
|
+
checkTmuxInstalled(deps),
|
|
430
|
+
checkTmuxVersion(deps),
|
|
431
|
+
await checkPrefsLoad(deps),
|
|
432
|
+
await checkFallbackClisOnPath(deps),
|
|
433
|
+
checkRegistryLoads(deps),
|
|
434
|
+
checkStaleLockfile(deps),
|
|
435
|
+
checkOrphanWorktrees(deps),
|
|
436
|
+
];
|
|
437
|
+
return { checks };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Convenience for the CLI wrapper: any check with status === 'fail'?
|
|
442
|
+
*
|
|
443
|
+
* @param {{ checks: DoctorCheck[] }} report
|
|
444
|
+
* @returns {boolean}
|
|
445
|
+
*/
|
|
446
|
+
function anyFailed(report) {
|
|
447
|
+
return report.checks.some((c) => c.status === "fail");
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
module.exports = {
|
|
451
|
+
MIN_TMUX_VERSION,
|
|
452
|
+
STALE_LOCK_MS,
|
|
453
|
+
parseTmuxVersion,
|
|
454
|
+
compareVersions,
|
|
455
|
+
checkTmuxInstalled,
|
|
456
|
+
checkTmuxVersion,
|
|
457
|
+
checkPrefsLoad,
|
|
458
|
+
checkFallbackClisOnPath,
|
|
459
|
+
checkRegistryLoads,
|
|
460
|
+
checkStaleLockfile,
|
|
461
|
+
checkOrphanWorktrees,
|
|
462
|
+
runDoctorChecks,
|
|
463
|
+
anyFailed,
|
|
464
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The body of `agileflow launch __exec <session-name>` — a hidden
|
|
3
|
+
* subcommand that tmux sessions invoke instead of the raw CLI. It:
|
|
4
|
+
*
|
|
5
|
+
* 1. Loads the session's entry from the registry to learn which CLI
|
|
6
|
+
* to spawn and the last-known conversation UUID.
|
|
7
|
+
* 2. Spawns the CLI with the CLI-specific resume flags (so claude
|
|
8
|
+
* gets `--resume <uuid>` etc.).
|
|
9
|
+
* 3. After the CLI exits, asks the resume strategy to capture a fresh
|
|
10
|
+
* UUID from disk (claude writes a new jsonl per conversation) and
|
|
11
|
+
* writes it back to the registry. This makes the NEXT __exec /
|
|
12
|
+
* restore pick up the newest conversation.
|
|
13
|
+
*
|
|
14
|
+
* Wired up by `tmux new-session -d -s <name> -c <cwd> <agileflow-bin>
|
|
15
|
+
* launch __exec <name>`. tmux is responsible for the cwd and the
|
|
16
|
+
* pane; we just route the CLI invocation through here so the resume
|
|
17
|
+
* dance happens transparently.
|
|
18
|
+
*/
|
|
19
|
+
const { runCli } = require("./spawn.js");
|
|
20
|
+
const { findSession, updateSession } = require("./session-registry.js");
|
|
21
|
+
const { findCli } = require("./detect-clis.js");
|
|
22
|
+
const { getResumeStrategy } = require("./cli-resume.js");
|
|
23
|
+
const { OperationFailedError, fail } = require("../../lib/errors.js");
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} sessionName
|
|
27
|
+
* @returns {Promise<never>}
|
|
28
|
+
*/
|
|
29
|
+
async function runExec(sessionName) {
|
|
30
|
+
const entry = findSession(sessionName);
|
|
31
|
+
if (!entry) {
|
|
32
|
+
fail(
|
|
33
|
+
new OperationFailedError(
|
|
34
|
+
`agileflow launch __exec: no registry entry for session "${sessionName}"`,
|
|
35
|
+
{
|
|
36
|
+
suggestion:
|
|
37
|
+
"this command is meant to be invoked by tmux on session create — " +
|
|
38
|
+
"run `agileflow launch` from the original directory to spawn a session normally",
|
|
39
|
+
},
|
|
40
|
+
),
|
|
41
|
+
{ command: "launch" },
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const cliDesc = findCli(entry.cli);
|
|
46
|
+
if (!cliDesc) {
|
|
47
|
+
fail(
|
|
48
|
+
new OperationFailedError(
|
|
49
|
+
`unknown CLI "${entry.cli}" in registry entry for "${sessionName}"`,
|
|
50
|
+
{
|
|
51
|
+
suggestion:
|
|
52
|
+
"the registry references a CLI agileflow doesn't know about; " +
|
|
53
|
+
"edit ~/.agileflow/launch-sessions.json or re-run `agileflow launch setup`",
|
|
54
|
+
},
|
|
55
|
+
),
|
|
56
|
+
{ command: "launch" },
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const strategy = getResumeStrategy(entry.cli);
|
|
61
|
+
const args = strategy.resumeArgs(entry.uuid);
|
|
62
|
+
|
|
63
|
+
/** @type {{ exitCode: number, signal: NodeJS.Signals | null }} */
|
|
64
|
+
let result;
|
|
65
|
+
try {
|
|
66
|
+
result = await runCli(cliDesc.bin, args);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
// Spawn failure — most often the binary disappeared since the
|
|
69
|
+
// session was created. Tell the user what happened and bail with
|
|
70
|
+
// a non-zero exit so the tmux pane closes.
|
|
71
|
+
fail(
|
|
72
|
+
new OperationFailedError(
|
|
73
|
+
`agileflow launch __exec: ${err && err.message ? err.message : String(err)}`,
|
|
74
|
+
{
|
|
75
|
+
suggestion: `verify "${cliDesc.bin}" is on PATH; install it or run \`agileflow launch setup\` to pick a different CLI`,
|
|
76
|
+
cause: err,
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
{ command: "launch" },
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Best-effort UUID capture. Failures here are NEVER fatal — the user
|
|
84
|
+
// ran their CLI fine; we just don't get to update the registry. Worst
|
|
85
|
+
// case: next __exec resumes the same UUID we had before.
|
|
86
|
+
//
|
|
87
|
+
// CRITICAL: only persist a new UUID when the CLI exited cleanly. If
|
|
88
|
+
// claude crashed mid-conversation the newest .jsonl is an incomplete
|
|
89
|
+
// snapshot, and resuming into it later would land the user in a
|
|
90
|
+
// corrupted state. On non-zero exit we still bump lastSeen so the
|
|
91
|
+
// registry shows the session was alive recently, but the UUID
|
|
92
|
+
// pointer stays at whatever the last successful capture wrote.
|
|
93
|
+
try {
|
|
94
|
+
if (result.exitCode === 0) {
|
|
95
|
+
const newUuid = strategy.captureUuid(entry.cwd);
|
|
96
|
+
if (newUuid) {
|
|
97
|
+
updateSession(sessionName, {
|
|
98
|
+
uuid: newUuid,
|
|
99
|
+
lastSeen: new Date().toISOString(),
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
updateSession(sessionName, { lastSeen: new Date().toISOString() });
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
updateSession(sessionName, { lastSeen: new Date().toISOString() });
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
/* swallow */
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
process.exit(result.exitCode);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = { runExec };
|