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,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-reboot session registry for `agileflow launch`.
|
|
3
|
+
*
|
|
4
|
+
* Lives at `~/.agileflow/launch-sessions.json`. Tracks every tmux
|
|
5
|
+
* session we create so we can resurrect them after the tmux server
|
|
6
|
+
* dies (machine reboot, manual `tmux kill-server`, etc.). For each
|
|
7
|
+
* session we keep:
|
|
8
|
+
* - name — the tmux session name (claude-myproject, ...)
|
|
9
|
+
* - cli — the AI CLI it wraps (claude, codex, ...)
|
|
10
|
+
* - cwd — directory the session was created in (or the
|
|
11
|
+
* worktree path for Alt+n sessions)
|
|
12
|
+
* - uuid — last-known conversation UUID for resume (captured
|
|
13
|
+
* from claude's `~/.claude/projects/<dir>/*.jsonl`
|
|
14
|
+
* or codex's session index)
|
|
15
|
+
* - lastSeen — ISO timestamp of the last __exec invocation
|
|
16
|
+
* - worktree — optional `{path, branch, base}` from createWorktree
|
|
17
|
+
*
|
|
18
|
+
* Atomic writes via tmp+rename — same pattern the prefs file uses.
|
|
19
|
+
*/
|
|
20
|
+
const fs = require("fs");
|
|
21
|
+
const os = require("os");
|
|
22
|
+
const path = require("path");
|
|
23
|
+
|
|
24
|
+
const FILENAME = "launch-sessions.json";
|
|
25
|
+
const LOCK_SUFFIX = ".lock";
|
|
26
|
+
const LOCK_STALE_MS = 5000;
|
|
27
|
+
const LOCK_MAX_ATTEMPTS = 100;
|
|
28
|
+
const LOCK_RETRY_MS = 10;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Busy-wait sleep for `ms` milliseconds. Used inside the lock-acquire
|
|
32
|
+
* retry loop to back off briefly between attempts without bringing in
|
|
33
|
+
* any async / Atomics machinery (the rest of the registry API is sync,
|
|
34
|
+
* so async sleep would force every caller through Promise plumbing).
|
|
35
|
+
*
|
|
36
|
+
* @param {number} ms
|
|
37
|
+
*/
|
|
38
|
+
function busyWait(ms) {
|
|
39
|
+
const target = Date.now() + ms;
|
|
40
|
+
while (Date.now() < target) {
|
|
41
|
+
/* spin */
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Acquire an exclusive write lock on the registry via an O_EXCL lock
|
|
47
|
+
* file, run `fn`, then release. Used by recordSession / updateSession /
|
|
48
|
+
* forgetSession so two concurrent `__exec` processes finishing claude
|
|
49
|
+
* at the same time don't lose each other's UUID updates (read-modify-
|
|
50
|
+
* write race).
|
|
51
|
+
*
|
|
52
|
+
* @template T
|
|
53
|
+
* @param {string | undefined} home
|
|
54
|
+
* @param {() => T} fn
|
|
55
|
+
* @returns {T}
|
|
56
|
+
*/
|
|
57
|
+
function withRegistryLock(home, fn) {
|
|
58
|
+
const lockFile = registryPath(home) + LOCK_SUFFIX;
|
|
59
|
+
fs.mkdirSync(path.dirname(lockFile), { recursive: true });
|
|
60
|
+
|
|
61
|
+
/** @type {number | null} */
|
|
62
|
+
let lockFd = null;
|
|
63
|
+
for (let attempt = 0; attempt < LOCK_MAX_ATTEMPTS; attempt++) {
|
|
64
|
+
try {
|
|
65
|
+
// `wx` is the Node.js shorthand for O_CREAT | O_EXCL — fails with
|
|
66
|
+
// EEXIST when someone else already holds the lock.
|
|
67
|
+
lockFd = fs.openSync(lockFile, "wx");
|
|
68
|
+
break;
|
|
69
|
+
} catch (err) {
|
|
70
|
+
if (!err || err.code !== "EEXIST") throw err;
|
|
71
|
+
// Stale-lock detection: if the lockfile's mtime is older than
|
|
72
|
+
// LOCK_STALE_MS the holder probably crashed without unlinking.
|
|
73
|
+
// Best-effort takeover. The race here is benign: even if two
|
|
74
|
+
// processes both decide it's stale, only one O_EXCL open will
|
|
75
|
+
// succeed and the other loops again.
|
|
76
|
+
try {
|
|
77
|
+
const stat = fs.statSync(lockFile);
|
|
78
|
+
if (Date.now() - (stat.mtimeMs || 0) > LOCK_STALE_MS) {
|
|
79
|
+
try {
|
|
80
|
+
fs.unlinkSync(lockFile);
|
|
81
|
+
} catch {
|
|
82
|
+
/* swallow */
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
/* lockfile vanished between EEXIST and stat — loop and retry */
|
|
88
|
+
}
|
|
89
|
+
busyWait(LOCK_RETRY_MS);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (lockFd === null) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`could not acquire launch-sessions registry lock after ${LOCK_MAX_ATTEMPTS} attempts`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
return fn();
|
|
100
|
+
} finally {
|
|
101
|
+
try {
|
|
102
|
+
fs.closeSync(lockFd);
|
|
103
|
+
} catch {
|
|
104
|
+
/* swallow */
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
fs.unlinkSync(lockFile);
|
|
108
|
+
} catch {
|
|
109
|
+
/* swallow */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @typedef {Object} WorktreeMeta
|
|
116
|
+
* @property {string} path
|
|
117
|
+
* @property {string} branch
|
|
118
|
+
* @property {string} base
|
|
119
|
+
*
|
|
120
|
+
* @typedef {Object} SessionEntry
|
|
121
|
+
* @property {string} name
|
|
122
|
+
* @property {string} cli
|
|
123
|
+
* @property {string} cwd
|
|
124
|
+
* @property {string | null} uuid - null until the first __exec capture
|
|
125
|
+
* @property {string} lastSeen - ISO timestamp
|
|
126
|
+
* @property {boolean} [pinned] - user-marked as "always keep";
|
|
127
|
+
* pinned entries skip prune and
|
|
128
|
+
* are pre-selected in the auto-
|
|
129
|
+
* restore picker
|
|
130
|
+
* @property {WorktreeMeta} [worktree]
|
|
131
|
+
*
|
|
132
|
+
* @typedef {Object} RegistryShape
|
|
133
|
+
* @property {1} version
|
|
134
|
+
* @property {SessionEntry[]} sessions
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {string} [home]
|
|
139
|
+
* @returns {string}
|
|
140
|
+
*/
|
|
141
|
+
function registryPath(home) {
|
|
142
|
+
return path.join(home || os.homedir(), ".agileflow", FILENAME);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** @returns {RegistryShape} */
|
|
146
|
+
function emptyRegistry() {
|
|
147
|
+
return { version: 1, sessions: [] };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Read the registry from disk; returns an empty registry if the file
|
|
152
|
+
* is missing or malformed (corrupted files shouldn't break `launch`).
|
|
153
|
+
* Unknown extras are dropped. Invalid entries (missing required keys)
|
|
154
|
+
* are filtered out.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} [home]
|
|
157
|
+
* @returns {RegistryShape}
|
|
158
|
+
*/
|
|
159
|
+
function loadRegistry(home) {
|
|
160
|
+
const file = registryPath(home);
|
|
161
|
+
let raw;
|
|
162
|
+
try {
|
|
163
|
+
raw = fs.readFileSync(file, "utf8");
|
|
164
|
+
} catch (err) {
|
|
165
|
+
if (err && err.code === "ENOENT") return emptyRegistry();
|
|
166
|
+
// Permission / I/O errors should NOT silently become an empty
|
|
167
|
+
// registry — that would tell a subsequent write to wipe out the
|
|
168
|
+
// user's whole session list. Surface a warning on stderr (so it
|
|
169
|
+
// shows up next to other launch chatter) and still return empty so
|
|
170
|
+
// the rest of the launch flow keeps working.
|
|
171
|
+
// eslint-disable-next-line no-console
|
|
172
|
+
console.error(
|
|
173
|
+
`agileflow launch: could not read ${file} (${err && err.code ? err.code : err && err.message ? err.message : "I/O error"}). ` +
|
|
174
|
+
"Saved sessions may not appear in `agileflow launch restore` until the file is readable.",
|
|
175
|
+
);
|
|
176
|
+
return emptyRegistry();
|
|
177
|
+
}
|
|
178
|
+
let parsed;
|
|
179
|
+
try {
|
|
180
|
+
parsed = JSON.parse(raw);
|
|
181
|
+
} catch {
|
|
182
|
+
return emptyRegistry();
|
|
183
|
+
}
|
|
184
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
185
|
+
return emptyRegistry();
|
|
186
|
+
}
|
|
187
|
+
const sessions = Array.isArray(parsed.sessions) ? parsed.sessions : [];
|
|
188
|
+
/** @type {SessionEntry[]} */
|
|
189
|
+
const sane = [];
|
|
190
|
+
for (const s of sessions) {
|
|
191
|
+
if (!s || typeof s !== "object") continue;
|
|
192
|
+
if (typeof s.name !== "string" || !s.name) continue;
|
|
193
|
+
if (typeof s.cli !== "string" || !s.cli) continue;
|
|
194
|
+
if (typeof s.cwd !== "string" || !s.cwd) continue;
|
|
195
|
+
sane.push({
|
|
196
|
+
name: s.name,
|
|
197
|
+
cli: s.cli,
|
|
198
|
+
cwd: s.cwd,
|
|
199
|
+
uuid: typeof s.uuid === "string" ? s.uuid : null,
|
|
200
|
+
lastSeen: typeof s.lastSeen === "string" ? s.lastSeen : "",
|
|
201
|
+
pinned: s.pinned === true,
|
|
202
|
+
worktree:
|
|
203
|
+
s.worktree && typeof s.worktree === "object"
|
|
204
|
+
? {
|
|
205
|
+
path: String(s.worktree.path || ""),
|
|
206
|
+
branch: String(s.worktree.branch || ""),
|
|
207
|
+
base: String(s.worktree.base || ""),
|
|
208
|
+
}
|
|
209
|
+
: undefined,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return { version: 1, sessions: sane };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Atomically write the registry to disk. Ensures `~/.agileflow/` exists.
|
|
217
|
+
*
|
|
218
|
+
* @param {RegistryShape} reg
|
|
219
|
+
* @param {string} [home]
|
|
220
|
+
* @returns {string}
|
|
221
|
+
*/
|
|
222
|
+
function writeRegistry(reg, home) {
|
|
223
|
+
const file = registryPath(home);
|
|
224
|
+
const dir = path.dirname(file);
|
|
225
|
+
const tmp = path.join(dir, `.${FILENAME}.tmp-${process.pid}`);
|
|
226
|
+
const payload = {
|
|
227
|
+
version: 1,
|
|
228
|
+
sessions: reg.sessions,
|
|
229
|
+
};
|
|
230
|
+
const content = JSON.stringify(payload, null, 2) + "\n";
|
|
231
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
232
|
+
try {
|
|
233
|
+
fs.writeFileSync(tmp, content, "utf8");
|
|
234
|
+
fs.renameSync(tmp, file);
|
|
235
|
+
} catch (err) {
|
|
236
|
+
try {
|
|
237
|
+
fs.unlinkSync(tmp);
|
|
238
|
+
} catch {
|
|
239
|
+
/* swallow */
|
|
240
|
+
}
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
return file;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Record a newly-created session. If an entry with the same name
|
|
248
|
+
* exists, it's replaced — same name = same logical session being
|
|
249
|
+
* re-created, which is what the restore flow does.
|
|
250
|
+
*
|
|
251
|
+
* @param {Omit<SessionEntry, "lastSeen"> & { lastSeen?: string }} entry
|
|
252
|
+
* @param {string} [home]
|
|
253
|
+
*/
|
|
254
|
+
/**
|
|
255
|
+
* Reject entries that loadRegistry would silently drop on the next
|
|
256
|
+
* read. Validates the same required-string fields the load-side filter
|
|
257
|
+
* checks, so writes and reads agree.
|
|
258
|
+
*
|
|
259
|
+
* @param {Partial<SessionEntry>} entry
|
|
260
|
+
*/
|
|
261
|
+
function validateEntry(entry) {
|
|
262
|
+
if (!entry || typeof entry !== "object") {
|
|
263
|
+
throw new TypeError("recordSession: entry must be an object");
|
|
264
|
+
}
|
|
265
|
+
if (typeof entry.name !== "string" || !entry.name) {
|
|
266
|
+
throw new TypeError("recordSession: entry.name must be a non-empty string");
|
|
267
|
+
}
|
|
268
|
+
if (typeof entry.cli !== "string" || !entry.cli) {
|
|
269
|
+
throw new TypeError("recordSession: entry.cli must be a non-empty string");
|
|
270
|
+
}
|
|
271
|
+
if (typeof entry.cwd !== "string" || !entry.cwd) {
|
|
272
|
+
throw new TypeError("recordSession: entry.cwd must be a non-empty string");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function recordSession(entry, home) {
|
|
277
|
+
validateEntry(entry);
|
|
278
|
+
withRegistryLock(home, () => {
|
|
279
|
+
const reg = loadRegistry(home);
|
|
280
|
+
const filtered = reg.sessions.filter((s) => s.name !== entry.name);
|
|
281
|
+
// Preserve `pinned` across re-records (the restore flow re-records
|
|
282
|
+
// every session it brings back from disk; without this carry-over a
|
|
283
|
+
// restored pinned session would silently un-pin itself).
|
|
284
|
+
const previous = reg.sessions.find((s) => s.name === entry.name);
|
|
285
|
+
const pinned =
|
|
286
|
+
typeof entry.pinned === "boolean"
|
|
287
|
+
? entry.pinned
|
|
288
|
+
: previous
|
|
289
|
+
? previous.pinned === true
|
|
290
|
+
: false;
|
|
291
|
+
filtered.push({
|
|
292
|
+
name: entry.name,
|
|
293
|
+
cli: entry.cli,
|
|
294
|
+
cwd: entry.cwd,
|
|
295
|
+
uuid: entry.uuid || null,
|
|
296
|
+
lastSeen: entry.lastSeen || new Date().toISOString(),
|
|
297
|
+
pinned,
|
|
298
|
+
worktree: entry.worktree,
|
|
299
|
+
});
|
|
300
|
+
writeRegistry({ version: 1, sessions: filtered }, home);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Patch an existing entry by name. Used by the __exec wrapper after
|
|
306
|
+
* the CLI exits to refresh the UUID + lastSeen. No-op if the entry
|
|
307
|
+
* doesn't exist.
|
|
308
|
+
*
|
|
309
|
+
* @param {string} name
|
|
310
|
+
* @param {Partial<SessionEntry>} patch
|
|
311
|
+
* @param {string} [home]
|
|
312
|
+
* @returns {boolean} - true if a row was updated
|
|
313
|
+
*/
|
|
314
|
+
function updateSession(name, patch, home) {
|
|
315
|
+
return withRegistryLock(home, () => {
|
|
316
|
+
// Re-read under the lock so concurrent __exec processes finishing
|
|
317
|
+
// claude at the same time don't lose each other's UUID updates.
|
|
318
|
+
// Without the lock: A loads, B loads, A writes, B writes → A's
|
|
319
|
+
// change clobbered.
|
|
320
|
+
const reg = loadRegistry(home);
|
|
321
|
+
let updated = false;
|
|
322
|
+
for (const s of reg.sessions) {
|
|
323
|
+
if (s.name === name) {
|
|
324
|
+
if (patch.uuid !== undefined) {
|
|
325
|
+
// Accept string-or-null only; coerce anything else to null
|
|
326
|
+
// to keep the on-disk shape consistent with what the load
|
|
327
|
+
// side validates.
|
|
328
|
+
s.uuid = typeof patch.uuid === "string" ? patch.uuid : null;
|
|
329
|
+
}
|
|
330
|
+
if (patch.lastSeen !== undefined) s.lastSeen = patch.lastSeen;
|
|
331
|
+
if (patch.cwd !== undefined) s.cwd = patch.cwd;
|
|
332
|
+
if (patch.worktree !== undefined) s.worktree = patch.worktree;
|
|
333
|
+
if (patch.pinned !== undefined) s.pinned = patch.pinned === true;
|
|
334
|
+
updated = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (updated) writeRegistry(reg, home);
|
|
338
|
+
return updated;
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Look up a single entry by name.
|
|
344
|
+
*
|
|
345
|
+
* @param {string} name
|
|
346
|
+
* @param {string} [home]
|
|
347
|
+
* @returns {SessionEntry | null}
|
|
348
|
+
*/
|
|
349
|
+
function findSession(name, home) {
|
|
350
|
+
const reg = loadRegistry(home);
|
|
351
|
+
return reg.sessions.find((s) => s.name === name) || null;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Set the pinned flag on a session. Convenience wrapper around
|
|
356
|
+
* updateSession that exists so callers don't have to remember the patch
|
|
357
|
+
* shape. Returns true when the entry was found and updated, false when
|
|
358
|
+
* the name isn't in the registry.
|
|
359
|
+
*
|
|
360
|
+
* @param {string} name
|
|
361
|
+
* @param {boolean} pinned
|
|
362
|
+
* @param {string} [home]
|
|
363
|
+
* @returns {boolean}
|
|
364
|
+
*/
|
|
365
|
+
function pinSession(name, pinned, home) {
|
|
366
|
+
return updateSession(name, { pinned: pinned === true }, home);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Drop an entry by name (e.g., user killed the worktree session and
|
|
371
|
+
* doesn't want it auto-restored next time).
|
|
372
|
+
*
|
|
373
|
+
* @param {string} name
|
|
374
|
+
* @param {string} [home]
|
|
375
|
+
* @returns {boolean}
|
|
376
|
+
*/
|
|
377
|
+
function forgetSession(name, home) {
|
|
378
|
+
return withRegistryLock(home, () => {
|
|
379
|
+
const reg = loadRegistry(home);
|
|
380
|
+
const before = reg.sessions.length;
|
|
381
|
+
reg.sessions = reg.sessions.filter((s) => s.name !== name);
|
|
382
|
+
if (reg.sessions.length !== before) {
|
|
383
|
+
writeRegistry(reg, home);
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
module.exports = {
|
|
391
|
+
FILENAME,
|
|
392
|
+
registryPath,
|
|
393
|
+
emptyRegistry,
|
|
394
|
+
loadRegistry,
|
|
395
|
+
writeRegistry,
|
|
396
|
+
recordSession,
|
|
397
|
+
updateSession,
|
|
398
|
+
findSession,
|
|
399
|
+
forgetSession,
|
|
400
|
+
pinSession,
|
|
401
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spawn an AI CLI as a foreground child process.
|
|
3
|
+
*
|
|
4
|
+
* stdio is inherited so the child takes over the terminal — same UX as
|
|
5
|
+
* if the user had typed the CLI's name directly. We resolve to an
|
|
6
|
+
* `{ exitCode, signal }` shape after the child closes so the caller can
|
|
7
|
+
* mirror the child's exit status with `process.exit(exitCode)`.
|
|
8
|
+
*
|
|
9
|
+
* `spawnImpl` is injectable so tests don't actually fork a process.
|
|
10
|
+
*/
|
|
11
|
+
const child_process = require("child_process");
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} SpawnResult
|
|
15
|
+
* @property {number} exitCode - 0..255 on normal exit; 128+signo on signal exits
|
|
16
|
+
* @property {NodeJS.Signals | null} signal
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Map a signal name to the conventional `128 + signo` exit code so
|
|
21
|
+
* callers can `process.exit(result.exitCode)` and propagate the
|
|
22
|
+
* termination cause to the parent shell. Falls back to 1 when the
|
|
23
|
+
* signal isn't in the well-known set.
|
|
24
|
+
*
|
|
25
|
+
* @param {NodeJS.Signals | null} signal
|
|
26
|
+
* @returns {number}
|
|
27
|
+
*/
|
|
28
|
+
function signalToExitCode(signal) {
|
|
29
|
+
if (!signal) return 1;
|
|
30
|
+
const table = {
|
|
31
|
+
SIGHUP: 129,
|
|
32
|
+
SIGINT: 130,
|
|
33
|
+
SIGQUIT: 131,
|
|
34
|
+
SIGILL: 132,
|
|
35
|
+
SIGTRAP: 133,
|
|
36
|
+
SIGABRT: 134,
|
|
37
|
+
SIGBUS: 135,
|
|
38
|
+
SIGFPE: 136,
|
|
39
|
+
SIGKILL: 137,
|
|
40
|
+
SIGUSR1: 138,
|
|
41
|
+
SIGSEGV: 139,
|
|
42
|
+
SIGUSR2: 140,
|
|
43
|
+
SIGPIPE: 141,
|
|
44
|
+
SIGALRM: 142,
|
|
45
|
+
SIGTERM: 143,
|
|
46
|
+
};
|
|
47
|
+
return table[signal] || 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Spawn `bin` with `args` and wait for it to close. Returns the
|
|
52
|
+
* exit code the parent should propagate.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} bin
|
|
55
|
+
* @param {string[]} [args]
|
|
56
|
+
* @param {{ spawn?: typeof child_process.spawn, cwd?: string, env?: NodeJS.ProcessEnv }} [options]
|
|
57
|
+
* @returns {Promise<SpawnResult>}
|
|
58
|
+
*/
|
|
59
|
+
function runCli(bin, args = [], options = {}) {
|
|
60
|
+
const spawn = options.spawn || child_process.spawn;
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
// Node's child_process fires `error` then `close` on a failed spawn.
|
|
63
|
+
// Promises absorb the second settlement, but relying on that is
|
|
64
|
+
// implicit — an explicit guard keeps behavior obvious in tests and
|
|
65
|
+
// future Node versions.
|
|
66
|
+
let settled = false;
|
|
67
|
+
const finish = (fn, value) => {
|
|
68
|
+
if (settled) return;
|
|
69
|
+
settled = true;
|
|
70
|
+
fn(value);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
let child;
|
|
74
|
+
try {
|
|
75
|
+
child = spawn(bin, args, {
|
|
76
|
+
stdio: "inherit",
|
|
77
|
+
cwd: options.cwd,
|
|
78
|
+
// `??` (not `||`) is the precise guard for "was env provided" —
|
|
79
|
+
// future callers passing a falsy-but-meaningful value (e.g., `0`
|
|
80
|
+
// or an empty string from a misconfigured wrapper) won't be
|
|
81
|
+
// silently coerced to process.env. Node treats `null` and
|
|
82
|
+
// `undefined` identically here, so both still default to
|
|
83
|
+
// process.env via spawn's own handling.
|
|
84
|
+
env: options.env ?? process.env,
|
|
85
|
+
});
|
|
86
|
+
} catch (err) {
|
|
87
|
+
finish(reject, err);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
child.on("error", (err) => {
|
|
92
|
+
finish(reject, err);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
child.on("close", (code, signal) => {
|
|
96
|
+
const exitCode =
|
|
97
|
+
typeof code === "number" ? code : signalToExitCode(signal);
|
|
98
|
+
finish(resolve, { exitCode, signal });
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = { runCli, signalToExitCode };
|