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.
Files changed (372) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/content/plugins/accessibility/plugin.yaml +14 -0
  3. package/content/plugins/accessibility/skills/agileflow-accessibility/SKILL.md +392 -0
  4. package/content/plugins/accessibility/skills/agileflow-accessibility/references/aria-patterns.md +528 -0
  5. package/content/plugins/accessibility/skills/agileflow-accessibility/references/testing-checklist.md +457 -0
  6. package/content/plugins/accessibility/skills/agileflow-accessibility/references/wcag-guide.md +683 -0
  7. package/content/plugins/accessibility/skills/agileflow-accessibility/workflows/audit-page.md +310 -0
  8. package/content/plugins/accessibility/skills/agileflow-accessibility/workflows/implement-accessible-component.md +479 -0
  9. package/content/plugins/ads/agents/ads-audit-budget.md +185 -0
  10. package/content/plugins/ads/agents/ads-audit-compliance.md +171 -0
  11. package/content/plugins/ads/agents/ads-audit-creative.md +168 -0
  12. package/content/plugins/ads/agents/ads-audit-google.md +227 -0
  13. package/content/plugins/ads/agents/ads-audit-meta.md +184 -0
  14. package/content/plugins/ads/agents/ads-audit-tracking.md +205 -0
  15. package/content/plugins/ads/agents/ads-consensus.md +410 -0
  16. package/content/plugins/ads/agents/ads-generate.md +152 -0
  17. package/content/plugins/ads/agents/ads-performance-tracker.md +212 -0
  18. package/content/plugins/ads/plugin.yaml +23 -4
  19. package/content/plugins/ads/skills/agileflow-ads/SKILL.md +218 -0
  20. package/content/plugins/ads/skills/agileflow-ads/references/ad-copy-formula-guide.md +131 -0
  21. package/content/plugins/ads/skills/agileflow-ads/references/audience-targeting-guide.md +137 -0
  22. package/content/plugins/ads/skills/agileflow-ads/references/bid-strategy-guide.md +115 -0
  23. package/content/plugins/ads/skills/agileflow-ads/references/platform-benchmarks.md +100 -0
  24. package/content/plugins/ads/skills/agileflow-ads/workflows/audit.md +118 -0
  25. package/content/plugins/ads/skills/agileflow-ads/workflows/generate.md +84 -0
  26. package/content/plugins/audit/agents/a11y-analyzer-aria.md +173 -0
  27. package/content/plugins/audit/agents/a11y-analyzer-forms.md +173 -0
  28. package/content/plugins/audit/agents/a11y-analyzer-keyboard.md +183 -0
  29. package/content/plugins/audit/agents/a11y-analyzer-semantic.md +169 -0
  30. package/content/plugins/audit/agents/a11y-analyzer-visual.md +172 -0
  31. package/content/plugins/audit/agents/a11y-consensus.md +249 -0
  32. package/content/plugins/audit/agents/accessibility.md +558 -0
  33. package/content/plugins/audit/agents/api-quality-analyzer-conventions.md +156 -0
  34. package/content/plugins/audit/agents/api-quality-analyzer-docs.md +184 -0
  35. package/content/plugins/audit/agents/api-quality-analyzer-errors.md +191 -0
  36. package/content/plugins/audit/agents/api-quality-analyzer-pagination.md +179 -0
  37. package/content/plugins/audit/agents/api-quality-analyzer-versioning.md +150 -0
  38. package/content/plugins/audit/agents/api-quality-consensus.md +217 -0
  39. package/content/plugins/audit/agents/api-validator.md +191 -0
  40. package/content/plugins/audit/agents/arch-analyzer-circular.md +156 -0
  41. package/content/plugins/audit/agents/arch-analyzer-complexity.md +193 -0
  42. package/content/plugins/audit/agents/arch-analyzer-coupling.md +152 -0
  43. package/content/plugins/audit/agents/arch-analyzer-layering.md +160 -0
  44. package/content/plugins/audit/agents/arch-analyzer-patterns.md +210 -0
  45. package/content/plugins/audit/agents/arch-consensus.md +228 -0
  46. package/content/plugins/audit/agents/browser-qa.md +342 -0
  47. package/content/plugins/audit/agents/code-reviewer.md +298 -0
  48. package/content/plugins/audit/agents/completeness-analyzer-api.md +199 -0
  49. package/content/plugins/audit/agents/completeness-analyzer-conditional.md +211 -0
  50. package/content/plugins/audit/agents/completeness-analyzer-handlers.md +166 -0
  51. package/content/plugins/audit/agents/completeness-analyzer-imports.md +165 -0
  52. package/content/plugins/audit/agents/completeness-analyzer-routes.md +190 -0
  53. package/content/plugins/audit/agents/completeness-analyzer-state.md +196 -0
  54. package/content/plugins/audit/agents/completeness-analyzer-stubs.md +206 -0
  55. package/content/plugins/audit/agents/completeness-consensus.md +295 -0
  56. package/content/plugins/audit/agents/error-analyzer.md +213 -0
  57. package/content/plugins/audit/agents/flow-analyzer-authorization.md +182 -0
  58. package/content/plugins/audit/agents/flow-analyzer-discovery.md +174 -0
  59. package/content/plugins/audit/agents/flow-analyzer-errors.md +186 -0
  60. package/content/plugins/audit/agents/flow-analyzer-feedback.md +185 -0
  61. package/content/plugins/audit/agents/flow-analyzer-navigation.md +177 -0
  62. package/content/plugins/audit/agents/flow-analyzer-persistence.md +193 -0
  63. package/content/plugins/audit/agents/flow-analyzer-wiring.md +169 -0
  64. package/content/plugins/audit/agents/flow-consensus.md +237 -0
  65. package/content/plugins/audit/agents/legal-analyzer-a11y.md +114 -0
  66. package/content/plugins/audit/agents/legal-analyzer-ai.md +121 -0
  67. package/content/plugins/audit/agents/legal-analyzer-consumer.md +114 -0
  68. package/content/plugins/audit/agents/legal-analyzer-content.md +117 -0
  69. package/content/plugins/audit/agents/legal-analyzer-international.md +119 -0
  70. package/content/plugins/audit/agents/legal-analyzer-licensing.md +119 -0
  71. package/content/plugins/audit/agents/legal-analyzer-privacy.md +112 -0
  72. package/content/plugins/audit/agents/legal-analyzer-security.md +116 -0
  73. package/content/plugins/audit/agents/legal-analyzer-terms.md +115 -0
  74. package/content/plugins/audit/agents/legal-consensus.md +250 -0
  75. package/content/plugins/audit/agents/logic-analyzer-edge.md +179 -0
  76. package/content/plugins/audit/agents/logic-analyzer-flow.md +264 -0
  77. package/content/plugins/audit/agents/logic-analyzer-invariant.md +215 -0
  78. package/content/plugins/audit/agents/logic-analyzer-race.md +280 -0
  79. package/content/plugins/audit/agents/logic-analyzer-type.md +227 -0
  80. package/content/plugins/audit/agents/logic-consensus.md +259 -0
  81. package/content/plugins/audit/agents/perf-analyzer-assets.md +182 -0
  82. package/content/plugins/audit/agents/perf-analyzer-bundle.md +173 -0
  83. package/content/plugins/audit/agents/perf-analyzer-caching.md +170 -0
  84. package/content/plugins/audit/agents/perf-analyzer-compute.md +173 -0
  85. package/content/plugins/audit/agents/perf-analyzer-memory.md +193 -0
  86. package/content/plugins/audit/agents/perf-analyzer-network.md +165 -0
  87. package/content/plugins/audit/agents/perf-analyzer-queries.md +162 -0
  88. package/content/plugins/audit/agents/perf-analyzer-rendering.md +168 -0
  89. package/content/plugins/audit/agents/perf-consensus.md +287 -0
  90. package/content/plugins/audit/agents/qa.md +820 -0
  91. package/content/plugins/audit/agents/quality-analyzer-comments.md +159 -0
  92. package/content/plugins/audit/agents/quality-analyzer-duplication.md +184 -0
  93. package/content/plugins/audit/agents/quality-analyzer-naming.md +160 -0
  94. package/content/plugins/audit/agents/quality-consensus.md +241 -0
  95. package/content/plugins/audit/agents/schema-validator.md +473 -0
  96. package/content/plugins/audit/agents/security-analyzer-api.md +210 -0
  97. package/content/plugins/audit/agents/security-analyzer-auth.md +169 -0
  98. package/content/plugins/audit/agents/security-analyzer-authz.md +180 -0
  99. package/content/plugins/audit/agents/security-analyzer-deps.md +153 -0
  100. package/content/plugins/audit/agents/security-analyzer-infra.md +184 -0
  101. package/content/plugins/audit/agents/security-analyzer-injection.md +155 -0
  102. package/content/plugins/audit/agents/security-analyzer-input.md +201 -0
  103. package/content/plugins/audit/agents/security-analyzer-secrets.md +183 -0
  104. package/content/plugins/audit/agents/security-consensus.md +283 -0
  105. package/content/plugins/audit/agents/test-analyzer-assertions.md +188 -0
  106. package/content/plugins/audit/agents/test-analyzer-coverage.md +189 -0
  107. package/content/plugins/audit/agents/test-analyzer-fragility.md +193 -0
  108. package/content/plugins/audit/agents/test-analyzer-integration.md +161 -0
  109. package/content/plugins/audit/agents/test-analyzer-maintenance.md +180 -0
  110. package/content/plugins/audit/agents/test-analyzer-mocking.md +188 -0
  111. package/content/plugins/audit/agents/test-analyzer-patterns.md +196 -0
  112. package/content/plugins/audit/agents/test-analyzer-structure.md +184 -0
  113. package/content/plugins/audit/agents/test-consensus.md +301 -0
  114. package/content/plugins/audit/agents/testing.md +561 -0
  115. package/content/plugins/audit/agents/ui-validator.md +344 -0
  116. package/content/plugins/audit/plugin.yaml +186 -5
  117. package/content/plugins/audit/skills/agileflow-audit/SKILL.md +113 -0
  118. package/content/plugins/audit/skills/agileflow-audit/references/audit-depth-guide.md +151 -0
  119. package/content/plugins/audit/skills/agileflow-audit/references/dependency-risk-guide.md +139 -0
  120. package/content/plugins/audit/skills/agileflow-audit/references/owasp-top10.md +120 -0
  121. package/content/plugins/audit/skills/agileflow-audit/references/performance-budget-guide.md +143 -0
  122. package/content/plugins/audit/skills/agileflow-audit/references/wcag-criteria.md +117 -0
  123. package/content/plugins/audit/skills/agileflow-audit/workflows/run-audit.md +52 -0
  124. package/content/plugins/audit/skills/agileflow-audit/workflows/tdd.md +66 -0
  125. package/content/plugins/core/agents/adr-writer.md +521 -0
  126. package/content/plugins/core/agents/epic-planner.md +520 -0
  127. package/content/plugins/core/agents/mentor.md +709 -0
  128. package/content/plugins/core/agents/orchestrator.md +776 -0
  129. package/content/plugins/core/agents/team-coordinator.md +334 -0
  130. package/content/plugins/core/agents/team-lead.md +181 -0
  131. package/content/plugins/core/agents/workspace-orchestrator.md +146 -0
  132. package/content/plugins/core/hooks/context-loader.js +31 -4
  133. package/content/plugins/core/hooks/damage-control-bash.js +10 -2
  134. package/content/plugins/core/hooks/damage-control-edit.js +4 -1
  135. package/content/plugins/core/hooks/damage-control-patterns.yaml +1 -1
  136. package/content/plugins/core/hooks/damage-control-write.js +4 -1
  137. package/content/plugins/core/hooks/{pre-compact-state.js → post-compact-state.js} +25 -8
  138. package/content/plugins/core/hooks/preferences-injector.js +352 -0
  139. package/content/plugins/core/plugin.yaml +24 -28
  140. package/content/plugins/core/skills/agileflow-adr/SKILL.md +34 -8
  141. package/content/plugins/core/skills/agileflow-adr/references/madr-format-guide.md +86 -0
  142. package/content/plugins/core/skills/agileflow-adr/workflows/write-adr.md +57 -0
  143. package/content/plugins/core/skills/agileflow-babysit-mentor/SKILL.md +94 -27
  144. package/content/plugins/core/skills/agileflow-babysit-mentor/references/mentor-decision-guide.md +81 -0
  145. package/content/plugins/core/skills/agileflow-babysit-mentor/workflows/mentor-session.md +79 -0
  146. package/content/plugins/core/skills/agileflow-epic-planner/SKILL.md +37 -7
  147. package/content/plugins/core/skills/agileflow-epic-planner/references/epic-sizing-guide.md +81 -0
  148. package/content/plugins/core/skills/agileflow-epic-planner/workflows/plan-epic.md +55 -0
  149. package/content/plugins/core/skills/agileflow-status-updater/SKILL.md +36 -20
  150. package/content/plugins/core/skills/agileflow-status-updater/references/status-transitions.md +89 -0
  151. package/content/plugins/core/skills/agileflow-status-updater/workflows/update-status.md +56 -0
  152. package/content/plugins/core/skills/agileflow-story-writer/SKILL.md +39 -114
  153. package/content/plugins/core/skills/agileflow-story-writer/references/estimation-reference.md +36 -0
  154. package/content/plugins/core/skills/agileflow-story-writer/references/story-template.md +92 -0
  155. package/content/plugins/core/skills/agileflow-story-writer/workflows/write-story.md +138 -0
  156. package/content/plugins/council/agents/council-advocate.md +223 -0
  157. package/content/plugins/council/agents/council-analyst.md +278 -0
  158. package/content/plugins/council/agents/council-compounder.md +204 -0
  159. package/content/plugins/council/agents/council-contrarian.md +217 -0
  160. package/content/plugins/council/agents/council-moonshot.md +217 -0
  161. package/content/plugins/council/agents/council-optimist.md +185 -0
  162. package/content/plugins/council/agents/council-revenue.md +200 -0
  163. package/content/plugins/council/agents/council-technical.md +218 -0
  164. package/content/plugins/council/agents/multi-expert.md +334 -0
  165. package/content/plugins/council/plugin.yaml +23 -4
  166. package/content/plugins/council/skills/agileflow-council/SKILL.md +102 -0
  167. package/content/plugins/council/skills/agileflow-council/references/decision-log-template.md +109 -0
  168. package/content/plugins/council/skills/agileflow-council/references/perspective-guide.md +104 -0
  169. package/content/plugins/council/skills/agileflow-council/references/when-to-convene-guide.md +112 -0
  170. package/content/plugins/council/skills/agileflow-council/workflows/convene.md +73 -0
  171. package/content/plugins/council/skills/agileflow-council/workflows/multi-expert.md +75 -0
  172. package/content/plugins/database/plugin.yaml +14 -0
  173. package/content/plugins/database/skills/agileflow-database/SKILL.md +284 -0
  174. package/content/plugins/database/skills/agileflow-database/references/indexing-guide.md +313 -0
  175. package/content/plugins/database/skills/agileflow-database/references/migration-guide.md +328 -0
  176. package/content/plugins/database/skills/agileflow-database/references/schema-design-guide.md +467 -0
  177. package/content/plugins/database/skills/agileflow-database/workflows/design-schema.md +213 -0
  178. package/content/plugins/database/skills/agileflow-database/workflows/optimize-query.md +253 -0
  179. package/content/plugins/debugging/plugin.yaml +14 -0
  180. package/content/plugins/debugging/skills/agileflow-debug/SKILL.md +236 -0
  181. package/content/plugins/debugging/skills/agileflow-debug/references/common-patterns.md +350 -0
  182. package/content/plugins/debugging/skills/agileflow-debug/references/debugging-strategies.md +328 -0
  183. package/content/plugins/debugging/skills/agileflow-debug/workflows/debug-issue.md +187 -0
  184. package/content/plugins/debugging/skills/agileflow-debug/workflows/reproduce-bug.md +194 -0
  185. package/content/plugins/delivery/agents/ci.md +547 -0
  186. package/content/plugins/delivery/agents/devops.md +789 -0
  187. package/content/plugins/delivery/plugin.yaml +19 -0
  188. package/content/plugins/delivery/skills/agileflow-delivery/SKILL.md +111 -0
  189. package/content/plugins/delivery/skills/agileflow-delivery/references/changelog-format-guide.md +133 -0
  190. package/content/plugins/delivery/skills/agileflow-delivery/references/ci-pipeline-guide.md +158 -0
  191. package/content/plugins/delivery/skills/agileflow-delivery/references/pr-checklist-guide.md +133 -0
  192. package/content/plugins/delivery/skills/agileflow-delivery/references/release-checklist.md +142 -0
  193. package/content/plugins/delivery/skills/agileflow-delivery/workflows/changelog.md +72 -0
  194. package/content/plugins/delivery/skills/agileflow-delivery/workflows/deploy.md +74 -0
  195. package/content/plugins/delivery/skills/agileflow-delivery/workflows/pr.md +75 -0
  196. package/content/plugins/docs/agents/documentation.md +544 -0
  197. package/content/plugins/docs/agents/readme-updater.md +640 -0
  198. package/content/plugins/docs/plugin.yaml +19 -0
  199. package/content/plugins/docs/skills/agileflow-docs/SKILL.md +106 -0
  200. package/content/plugins/docs/skills/agileflow-docs/references/api-doc-template.md +167 -0
  201. package/content/plugins/docs/skills/agileflow-docs/references/doc-types-guide.md +141 -0
  202. package/content/plugins/docs/skills/agileflow-docs/references/readme-template.md +156 -0
  203. package/content/plugins/docs/skills/agileflow-docs/workflows/readme-sync.md +57 -0
  204. package/content/plugins/docs/skills/agileflow-docs/workflows/sync.md +64 -0
  205. package/content/plugins/engineering/agents/api.md +718 -0
  206. package/content/plugins/engineering/agents/codebase-query.md +285 -0
  207. package/content/plugins/engineering/agents/compliance.md +559 -0
  208. package/content/plugins/engineering/agents/database.md +644 -0
  209. package/content/plugins/engineering/agents/integrations.md +644 -0
  210. package/content/plugins/engineering/agents/mobile.md +552 -0
  211. package/content/plugins/engineering/agents/monitoring.md +585 -0
  212. package/content/plugins/engineering/agents/performance.md +529 -0
  213. package/content/plugins/engineering/agents/refactor.md +592 -0
  214. package/content/plugins/engineering/agents/security.md +524 -0
  215. package/content/plugins/engineering/agents/ui.md +1336 -0
  216. package/content/plugins/engineering/plugin.yaml +37 -0
  217. package/content/plugins/engineering/skills/agileflow-engineering/SKILL.md +127 -0
  218. package/content/plugins/engineering/skills/agileflow-engineering/references/code-review-guide.md +126 -0
  219. package/content/plugins/engineering/skills/agileflow-engineering/references/domain-routing-guide.md +89 -0
  220. package/content/plugins/engineering/skills/agileflow-engineering/references/refactoring-guide.md +136 -0
  221. package/content/plugins/engineering/skills/agileflow-engineering/workflows/diagnose.md +63 -0
  222. package/content/plugins/engineering/skills/agileflow-engineering/workflows/impact.md +60 -0
  223. package/content/plugins/ideation/agents/brainstorm-analyzer-features.md +179 -0
  224. package/content/plugins/ideation/agents/brainstorm-analyzer-growth.md +169 -0
  225. package/content/plugins/ideation/agents/brainstorm-analyzer-integration.md +181 -0
  226. package/content/plugins/ideation/agents/brainstorm-analyzer-market.md +150 -0
  227. package/content/plugins/ideation/agents/brainstorm-analyzer-ux.md +180 -0
  228. package/content/plugins/ideation/agents/brainstorm-consensus.md +245 -0
  229. package/content/plugins/ideation/agents/design.md +568 -0
  230. package/content/plugins/ideation/agents/product.md +582 -0
  231. package/content/plugins/ideation/plugin.yaml +31 -0
  232. package/content/plugins/ideation/skills/agileflow-ideation/SKILL.md +109 -0
  233. package/content/plugins/ideation/skills/agileflow-ideation/references/brainstorm-techniques.md +138 -0
  234. package/content/plugins/ideation/skills/agileflow-ideation/references/competitive-analysis-template.md +148 -0
  235. package/content/plugins/ideation/skills/agileflow-ideation/references/feature-prioritization-guide.md +147 -0
  236. package/content/plugins/ideation/skills/agileflow-ideation/references/user-story-patterns.md +152 -0
  237. package/content/plugins/ideation/skills/agileflow-ideation/workflows/features.md +65 -0
  238. package/content/plugins/ideation/skills/agileflow-ideation/workflows/ideate.md +54 -0
  239. package/content/plugins/migration/agents/datamigration.md +757 -0
  240. package/content/plugins/migration/plugin.yaml +17 -0
  241. package/content/plugins/migration/skills/agileflow-migration/SKILL.md +106 -0
  242. package/content/plugins/migration/skills/agileflow-migration/references/data-validation-checklist.md +154 -0
  243. package/content/plugins/migration/skills/agileflow-migration/references/migration-patterns.md +209 -0
  244. package/content/plugins/migration/skills/agileflow-migration/references/rollback-playbook.md +171 -0
  245. package/content/plugins/migration/skills/agileflow-migration/references/version-compatibility-matrix.md +155 -0
  246. package/content/plugins/migration/skills/agileflow-migration/workflows/plan.md +73 -0
  247. package/content/plugins/migration/skills/agileflow-migration/workflows/validate.md +71 -0
  248. package/content/plugins/performance/plugin.yaml +14 -0
  249. package/content/plugins/performance/skills/agileflow-performance/SKILL.md +224 -0
  250. package/content/plugins/performance/skills/agileflow-performance/references/optimization-patterns.md +554 -0
  251. package/content/plugins/performance/skills/agileflow-performance/references/profiling-guide.md +383 -0
  252. package/content/plugins/performance/skills/agileflow-performance/references/web-vitals-guide.md +360 -0
  253. package/content/plugins/performance/skills/agileflow-performance/workflows/improve-web-vitals.md +344 -0
  254. package/content/plugins/performance/skills/agileflow-performance/workflows/profile-and-fix.md +254 -0
  255. package/content/plugins/planning/agents/analytics.md +670 -0
  256. package/content/plugins/planning/agents/rlm-subcore.md +215 -0
  257. package/content/plugins/planning/plugin.yaml +19 -0
  258. package/content/plugins/planning/skills/agileflow-planning/SKILL.md +111 -0
  259. package/content/plugins/planning/skills/agileflow-planning/references/estimation-guide.md +114 -0
  260. package/content/plugins/planning/skills/agileflow-planning/references/rpi-workflow.md +119 -0
  261. package/content/plugins/planning/skills/agileflow-planning/references/sprint-planning-guide.md +145 -0
  262. package/content/plugins/planning/skills/agileflow-planning/workflows/impact.md +63 -0
  263. package/content/plugins/planning/skills/agileflow-planning/workflows/rpi.md +104 -0
  264. package/content/plugins/psychology/plugin.yaml +14 -0
  265. package/content/plugins/psychology/skills/agileflow-retention/SKILL.md +252 -0
  266. package/content/plugins/psychology/skills/agileflow-retention/references/competitor-analysis.md +240 -0
  267. package/content/plugins/psychology/skills/agileflow-retention/references/psychology-models.md +349 -0
  268. package/content/plugins/psychology/skills/agileflow-retention/references/retention-patterns.md +279 -0
  269. package/content/plugins/psychology/skills/agileflow-retention/workflows/design-retention-feature.md +287 -0
  270. package/content/plugins/psychology/skills/agileflow-retention/workflows/retention-audit.md +259 -0
  271. package/content/plugins/refactoring/plugin.yaml +14 -0
  272. package/content/plugins/refactoring/skills/agileflow-refactor/SKILL.md +235 -0
  273. package/content/plugins/refactoring/skills/agileflow-refactor/references/refactoring-patterns.md +405 -0
  274. package/content/plugins/refactoring/skills/agileflow-refactor/references/safety-checks.md +177 -0
  275. package/content/plugins/refactoring/skills/agileflow-refactor/workflows/extract-module.md +226 -0
  276. package/content/plugins/refactoring/skills/agileflow-refactor/workflows/safe-refactor.md +169 -0
  277. package/content/plugins/research/agents/research.md +503 -0
  278. package/content/plugins/research/plugin.yaml +17 -0
  279. package/content/plugins/research/skills/agileflow-research/SKILL.md +110 -0
  280. package/content/plugins/research/skills/agileflow-research/references/knowledge-decay-guide.md +121 -0
  281. package/content/plugins/research/skills/agileflow-research/references/research-prompt-guide.md +141 -0
  282. package/content/plugins/research/skills/agileflow-research/references/synthesis-template.md +154 -0
  283. package/content/plugins/research/skills/agileflow-research/workflows/analyze.md +60 -0
  284. package/content/plugins/research/skills/agileflow-research/workflows/ask.md +64 -0
  285. package/content/plugins/research/skills/agileflow-research/workflows/import.md +66 -0
  286. package/content/plugins/research/skills/agileflow-research/workflows/synthesize.md +66 -0
  287. package/content/plugins/reviews/plugin.yaml +14 -0
  288. package/content/plugins/reviews/skills/agileflow-pr-reviewer/SKILL.md +241 -0
  289. package/content/plugins/reviews/skills/agileflow-pr-reviewer/references/review-checklist.md +200 -0
  290. package/content/plugins/reviews/skills/agileflow-pr-reviewer/references/security-patterns.md +328 -0
  291. package/content/plugins/reviews/skills/agileflow-pr-reviewer/workflows/review-pr.md +153 -0
  292. package/content/plugins/reviews/skills/agileflow-pr-reviewer/workflows/security-review.md +177 -0
  293. package/content/plugins/seo/agents/seo-analyzer-content.md +169 -0
  294. package/content/plugins/seo/agents/seo-analyzer-images.md +198 -0
  295. package/content/plugins/seo/agents/seo-analyzer-performance.md +217 -0
  296. package/content/plugins/seo/agents/seo-analyzer-schema.md +184 -0
  297. package/content/plugins/seo/agents/seo-analyzer-sitemap.md +177 -0
  298. package/content/plugins/seo/agents/seo-analyzer-technical.md +151 -0
  299. package/content/plugins/seo/agents/seo-consensus.md +304 -0
  300. package/content/plugins/seo/plugin.yaml +19 -4
  301. package/content/plugins/seo/skills/agileflow-seo/SKILL.md +188 -0
  302. package/content/plugins/seo/skills/agileflow-seo/references/cwv-thresholds.md +110 -0
  303. package/content/plugins/seo/skills/agileflow-seo/references/eeat-framework.md +144 -0
  304. package/content/plugins/seo/skills/agileflow-seo/references/keyword-research-guide.md +125 -0
  305. package/content/plugins/seo/skills/agileflow-seo/references/schema-types.md +139 -0
  306. package/content/plugins/seo/skills/agileflow-seo/references/technical-seo-checklist.md +139 -0
  307. package/content/plugins/seo/skills/agileflow-seo/workflows/audit.md +98 -0
  308. package/content/plugins/seo/skills/agileflow-seo/workflows/page.md +118 -0
  309. package/content/plugins/testing/plugin.yaml +16 -0
  310. package/content/plugins/testing/skills/agileflow-test-writer/SKILL.md +260 -0
  311. package/content/plugins/testing/skills/agileflow-test-writer/references/coverage-targets.md +239 -0
  312. package/content/plugins/testing/skills/agileflow-test-writer/references/test-patterns.md +420 -0
  313. package/content/plugins/testing/skills/agileflow-test-writer/workflows/add-coverage.md +154 -0
  314. package/content/plugins/testing/skills/agileflow-test-writer/workflows/write-tests-from-ac.md +225 -0
  315. package/package.json +2 -2
  316. package/src/cli/commands/doctor.js +818 -30
  317. package/src/cli/commands/hook.js +17 -14
  318. package/src/cli/commands/launch.js +1454 -0
  319. package/src/cli/commands/learn.js +149 -0
  320. package/src/cli/commands/plugins.js +113 -0
  321. package/src/cli/commands/setup.js +455 -110
  322. package/src/cli/commands/skills.js +324 -0
  323. package/src/cli/commands/status.js +8 -10
  324. package/src/cli/commands/update.js +76 -15
  325. package/src/cli/index.js +90 -26
  326. package/src/cli/wizard/babysit-mode-picker.js +192 -0
  327. package/src/cli/wizard/behaviors-picker.js +208 -54
  328. package/src/cli/wizard/ide-picker.js +40 -28
  329. package/src/cli/wizard/install-scope-picker.js +57 -0
  330. package/src/cli/wizard/launch-alias-picker.js +50 -0
  331. package/src/cli/wizard/launch-cli-picker.js +129 -0
  332. package/src/cli/wizard/launch-tmux-picker.js +133 -0
  333. package/src/cli/wizard/learnings-picker.js +40 -0
  334. package/src/cli/wizard/plugin-picker.js +47 -16
  335. package/src/lib/brand.js +116 -0
  336. package/src/lib/errors.js +120 -0
  337. package/src/lib/path-check.js +39 -0
  338. package/src/runtime/config/defaults.js +22 -17
  339. package/src/runtime/config/loader.js +77 -8
  340. package/src/runtime/config/schema.json +43 -16
  341. package/src/runtime/config/writer.js +3 -1
  342. package/src/runtime/ide/babysit-skill.js +202 -0
  343. package/src/runtime/ide/capabilities.js +84 -29
  344. package/src/runtime/ide/claude-code-content.js +177 -0
  345. package/src/runtime/ide/claude-code-settings.js +67 -29
  346. package/src/runtime/ide/claude-code-skills.js +47 -32
  347. package/src/runtime/ide/codex-config.js +295 -0
  348. package/src/runtime/installer/install.js +252 -24
  349. package/src/runtime/launch/alias-installer.js +191 -0
  350. package/src/runtime/launch/cli-resume.js +244 -0
  351. package/src/runtime/launch/closed-windows.js +338 -0
  352. package/src/runtime/launch/defaults.js +66 -0
  353. package/src/runtime/launch/detect-clis.js +69 -0
  354. package/src/runtime/launch/doctor.js +464 -0
  355. package/src/runtime/launch/exec-wrapper.js +114 -0
  356. package/src/runtime/launch/parallel-session.js +247 -0
  357. package/src/runtime/launch/prefs.js +211 -0
  358. package/src/runtime/launch/project-prefs.js +234 -0
  359. package/src/runtime/launch/resolve-cli.js +56 -0
  360. package/src/runtime/launch/restore.js +152 -0
  361. package/src/runtime/launch/schema.json +75 -0
  362. package/src/runtime/launch/session-lifecycle.js +313 -0
  363. package/src/runtime/launch/session-registry.js +401 -0
  364. package/src/runtime/launch/spawn.js +103 -0
  365. package/src/runtime/launch/tabs.js +350 -0
  366. package/src/runtime/launch/tmux.js +764 -0
  367. package/src/runtime/launch/worktree.js +260 -0
  368. package/src/runtime/plugins/registry.js +16 -11
  369. package/src/runtime/plugins/validator.js +57 -43
  370. package/src/runtime/skills/learnings.js +308 -0
  371. package/content/plugins/core/hooks/babysit-mentor-injector.js +0 -55
  372. package/src/cli/wizard/personalization.js +0 -64
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Resolve the AI CLI to launch given a prefs object.
3
+ *
4
+ * Walks `[cli.preferred, ...cli.fallbackOrder]` (deduped, preferred first),
5
+ * looks up each id's descriptor in the known-CLI registry, and returns
6
+ * the first one whose binary actually resolves on PATH. Returns null if
7
+ * none of the user's configured CLIs are installed — the caller surfaces
8
+ * the actionable error.
9
+ *
10
+ * `exists` is injectable so tests don't shell out.
11
+ */
12
+ const { commandExists: realCommandExists } = require("../../lib/path-check.js");
13
+ const { findCli } = require("./detect-clis.js");
14
+
15
+ /**
16
+ * Build the dedup'd lookup order: preferred first, then any fallback ids
17
+ * that weren't the preferred. Skips ids the user has explicitly removed
18
+ * from fallback (i.e., empty fallbackOrder means "only try preferred").
19
+ *
20
+ * @param {{ preferred: string, fallbackOrder: string[] }} cli
21
+ * @returns {string[]}
22
+ */
23
+ function buildLookupOrder(cli) {
24
+ const seen = new Set();
25
+ const order = [];
26
+ const push = (id) => {
27
+ if (typeof id !== "string" || !id) return;
28
+ if (seen.has(id)) return;
29
+ seen.add(id);
30
+ order.push(id);
31
+ };
32
+ push(cli.preferred);
33
+ for (const id of cli.fallbackOrder || []) push(id);
34
+ return order;
35
+ }
36
+
37
+ /**
38
+ * @param {{ cli: { preferred: string, fallbackOrder: string[] } }} prefs
39
+ * @param {(name: string) => boolean} [exists]
40
+ * @returns {{
41
+ * resolved: import('./detect-clis.js').CliDescriptor | null,
42
+ * tried: string[],
43
+ * }}
44
+ */
45
+ function resolveCli(prefs, exists = realCommandExists) {
46
+ const tried = buildLookupOrder(prefs.cli);
47
+ for (const id of tried) {
48
+ const desc = findCli(id);
49
+ if (desc && exists(desc.bin)) {
50
+ return { resolved: desc, tried };
51
+ }
52
+ }
53
+ return { resolved: null, tried };
54
+ }
55
+
56
+ module.exports = { resolveCli, buildLookupOrder };
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Bulk-restore tmux sessions from the registry after the tmux server
3
+ * died (typical cause: PC reboot). Walks every entry and re-creates
4
+ * the corresponding tmux session in the original cwd, wired to invoke
5
+ * `agileflow launch __exec <name>` so the per-CLI resume strategy
6
+ * fires automatically.
7
+ *
8
+ * Sessions that already exist on the running tmux server are skipped —
9
+ * restore is idempotent. Sessions whose original cwd no longer exists
10
+ * are skipped with a warning (e.g., user deleted the project dir).
11
+ *
12
+ * Returns counts so the caller can show a "restored N of M" summary.
13
+ */
14
+ const fs = require("fs");
15
+ const path = require("path");
16
+
17
+ const {
18
+ defaultRunner,
19
+ sessionExists,
20
+ createSession,
21
+ applyKeybindPreset,
22
+ applyTabFormat,
23
+ detectTmuxVersion,
24
+ } = require("./tmux.js");
25
+ const { loadRegistry } = require("./session-registry.js");
26
+ const { resolveAgileflowBin } = require("./alias-installer.js");
27
+
28
+ /**
29
+ * @typedef {Object} RestoreResult
30
+ * @property {number} restored
31
+ * @property {number} alreadyAlive
32
+ * @property {number} skipped - cwd missing or other unrecoverable state
33
+ * @property {number} failed
34
+ * @property {Array<{ name: string, reason: string }>} notes
35
+ */
36
+
37
+ /**
38
+ * @param {{
39
+ * prefs: import("./defaults.js").LaunchPrefs,
40
+ * runner?: ReturnType<typeof defaultRunner>,
41
+ * home?: string,
42
+ * agileflowBin?: string,
43
+ * existsSync?: (p: string) => boolean,
44
+ * log?: (msg: string) => void,
45
+ * onlyName?: string,
46
+ * onlyNames?: string[],
47
+ * }} opts
48
+ * @returns {RestoreResult}
49
+ */
50
+ function runRestore(opts) {
51
+ const runner = opts.runner || defaultRunner();
52
+ const existsSync = opts.existsSync || ((p) => fs.existsSync(p));
53
+ const log =
54
+ typeof opts.log === "function"
55
+ ? opts.log
56
+ : (msg) => {
57
+ // eslint-disable-next-line no-console
58
+ console.error(msg);
59
+ };
60
+ const agileflowBin = opts.agileflowBin || resolveAgileflowBin();
61
+
62
+ const reg = loadRegistry(opts.home);
63
+ /** @type {RestoreResult} */
64
+ const result = {
65
+ restored: 0,
66
+ alreadyAlive: 0,
67
+ skipped: 0,
68
+ failed: 0,
69
+ notes: [],
70
+ };
71
+
72
+ /** @type {import("./session-registry.js").SessionEntry[]} */
73
+ let entries;
74
+ if (opts.onlyName) {
75
+ entries = reg.sessions.filter((s) => s.name === opts.onlyName);
76
+ } else if (Array.isArray(opts.onlyNames)) {
77
+ // Use a Set for O(1) lookup so a 100-entry registry restoring a
78
+ // 20-entry subset stays linear, not quadratic.
79
+ const wanted = new Set(opts.onlyNames);
80
+ entries = reg.sessions.filter((s) => wanted.has(s.name));
81
+ } else {
82
+ entries = reg.sessions.slice();
83
+ }
84
+
85
+ for (const entry of entries) {
86
+ if (sessionExists(entry.name, runner)) {
87
+ result.alreadyAlive++;
88
+ continue;
89
+ }
90
+ if (!existsSync(entry.cwd)) {
91
+ result.skipped++;
92
+ result.notes.push({
93
+ name: entry.name,
94
+ reason: `cwd no longer exists: ${entry.cwd}`,
95
+ });
96
+ log(
97
+ `agileflow launch: skipping ${entry.name} — cwd missing (${entry.cwd})`,
98
+ );
99
+ continue;
100
+ }
101
+
102
+ // Tmux session command: invoke our own wrapper. tmux passes argv
103
+ // as separate words via the new-session args we hand it.
104
+ const wrapperArgs = [agileflowBin, "launch", "__exec", entry.name];
105
+ const create = createSession(
106
+ {
107
+ name: entry.name,
108
+ bin: wrapperArgs[0],
109
+ args: wrapperArgs.slice(1),
110
+ cwd: entry.cwd,
111
+ statusPosition: opts.prefs.tmux.statusPosition,
112
+ },
113
+ runner,
114
+ );
115
+ if (create.status !== 0) {
116
+ result.failed++;
117
+ const stderr = (create.stderr || "").trim() || "tmux new-session failed";
118
+ result.notes.push({ name: entry.name, reason: stderr });
119
+ log(`agileflow launch: failed to restore ${entry.name} — ${stderr}`);
120
+ continue;
121
+ }
122
+ // Apply the same per-session styling launchInTmux does for fresh
123
+ // sessions so the tab strip looks consistent on restore. Without
124
+ // this, restored sessions show tmux's default green status bar
125
+ // instead of the AgileFlow dark strip.
126
+ runner.runSync(["set-option", "-t", entry.name, "status", "1"]);
127
+ applyTabFormat(entry.name, runner, {
128
+ tmuxVersion: detectTmuxVersion(runner),
129
+ });
130
+ result.restored++;
131
+ log(`agileflow launch: restored session ${entry.name} (${entry.cwd})`);
132
+ }
133
+
134
+ // Apply keybinds once after the bulk restore so the user's preset is
135
+ // active across all the new sessions (tmux bind-key is server-wide).
136
+ if (
137
+ result.restored > 0 &&
138
+ opts.prefs.keybinds &&
139
+ opts.prefs.keybinds.preset
140
+ ) {
141
+ const kr = applyKeybindPreset(opts.prefs.keybinds.preset, runner, {
142
+ agileflowBin,
143
+ });
144
+ for (const f of kr.failures) {
145
+ log(`agileflow launch: keybind skipped during restore — ${f.hint}`);
146
+ }
147
+ }
148
+
149
+ return result;
150
+ }
151
+
152
+ module.exports = { runRestore };
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://agileflow.dev/schemas/launch-prefs.v1.json",
4
+ "title": "AgileFlow launch preferences",
5
+ "description": "User-level preferences for `agileflow launch` (multi-CLI tmux wrapper). Lives at ~/.agileflow/launch-prefs.json.",
6
+ "type": "object",
7
+ "required": ["version", "cli", "tmux", "keybinds", "aliases", "pinned"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "$schema": { "type": "string" },
11
+ "version": { "const": 1 },
12
+ "cli": {
13
+ "type": "object",
14
+ "required": ["preferred", "fallbackOrder"],
15
+ "additionalProperties": false,
16
+ "properties": {
17
+ "preferred": {
18
+ "type": "string",
19
+ "enum": ["claude", "codex", "cursor-agent", "aider"]
20
+ },
21
+ "fallbackOrder": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "string",
25
+ "enum": ["claude", "codex", "cursor-agent", "aider"]
26
+ },
27
+ "uniqueItems": true
28
+ }
29
+ }
30
+ },
31
+ "tmux": {
32
+ "type": "object",
33
+ "required": ["enabled", "statusPosition"],
34
+ "additionalProperties": false,
35
+ "properties": {
36
+ "enabled": { "type": "boolean" },
37
+ "statusPosition": { "type": "string", "enum": ["top", "bottom"] }
38
+ }
39
+ },
40
+ "keybinds": {
41
+ "type": "object",
42
+ "required": ["preset"],
43
+ "additionalProperties": false,
44
+ "properties": {
45
+ "preset": {
46
+ "type": "string",
47
+ "enum": ["default", "minimal", "none"]
48
+ }
49
+ }
50
+ },
51
+ "aliases": {
52
+ "type": "object",
53
+ "required": ["af"],
54
+ "additionalProperties": false,
55
+ "properties": {
56
+ "af": {
57
+ "type": "object",
58
+ "required": ["enabled"],
59
+ "additionalProperties": false,
60
+ "properties": {
61
+ "enabled": { "type": "boolean" }
62
+ }
63
+ }
64
+ }
65
+ },
66
+ "pinned": {
67
+ "type": "array",
68
+ "items": { "type": "string" }
69
+ },
70
+ "lastUpdated": {
71
+ "type": "string",
72
+ "format": "date-time"
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Pure helpers behind `agileflow launch ls / kill / attach / prune`.
3
+ *
4
+ * Composes already-built primitives:
5
+ * - registry: load / find / forget
6
+ * - tmux: sessionExists / killSession / attachSession
7
+ * - restore: runRestore({ onlyName }) for lazy re-creation
8
+ * - worktree: removeWorktree for paired cleanup
9
+ *
10
+ * Every helper accepts a `deps` bag with injectable callables so the unit
11
+ * tests don't have to spawn tmux or touch a real registry. The CLI
12
+ * wrappers in `commands/launch.js` are the only place that wires in the
13
+ * real implementations.
14
+ */
15
+ const fs = require("fs");
16
+
17
+ const {
18
+ loadRegistry,
19
+ findSession,
20
+ forgetSession,
21
+ } = require("./session-registry.js");
22
+ const {
23
+ defaultRunner,
24
+ sessionExists: tmuxSessionExists,
25
+ killSession: tmuxKillSession,
26
+ attachSession: tmuxAttachSession,
27
+ } = require("./tmux.js");
28
+ const { removeWorktree } = require("./worktree.js");
29
+ const { runRestore } = require("./restore.js");
30
+
31
+ /**
32
+ * @typedef {import("./session-registry.js").SessionEntry & {
33
+ * state: 'alive' | 'dormant' | 'missing-cwd',
34
+ * }} ClassifiedSession
35
+ */
36
+
37
+ /**
38
+ * Return every registered session, each tagged with its current state:
39
+ * - alive → tmux has the session
40
+ * - dormant → registry has it, cwd still exists, tmux doesn't
41
+ * - missing-cwd → registry has it but the cwd has been deleted
42
+ *
43
+ * Read-only — never mutates the registry. Worktree-only orphan detection
44
+ * lives in doctor.js; this helper just exposes raw state.
45
+ *
46
+ * @param {{
47
+ * home?: string,
48
+ * runner?: import("./tmux.js").TmuxRunner,
49
+ * sessionExistsFn?: typeof tmuxSessionExists,
50
+ * existsSync?: (p: string) => boolean,
51
+ * }} [deps]
52
+ * @returns {ClassifiedSession[]}
53
+ */
54
+ function listSessions(deps = {}) {
55
+ const runner = deps.runner || defaultRunner();
56
+ const sessionExistsFn = deps.sessionExistsFn || tmuxSessionExists;
57
+ const existsSync = deps.existsSync || ((p) => fs.existsSync(p));
58
+ const reg = loadRegistry(deps.home);
59
+ return reg.sessions.map((entry) => {
60
+ const alive = sessionExistsFn(entry.name, runner);
61
+ const cwdExists = existsSync(entry.cwd);
62
+ /** @type {'alive' | 'dormant' | 'missing-cwd'} */
63
+ const state = alive ? "alive" : cwdExists ? "dormant" : "missing-cwd";
64
+ return { ...entry, state };
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Kill a tmux session (if alive) and forget the registry entry. When
70
+ * `removeWorktree` is true and the entry has worktree metadata pointing
71
+ * at a directory that still exists, also remove the worktree + branch.
72
+ *
73
+ * The worktree removal is gated on caller intent rather than auto-applied
74
+ * so the CLI wrapper can prompt the user before destructive cleanup.
75
+ *
76
+ * Return shape lets the wrapper render a precise outcome without
77
+ * re-querying state:
78
+ * - ok: false + reason="not in registry" → unknown name
79
+ * - ok: true + wasAlive: boolean → kill attempted
80
+ * - ok: true + worktree: { removed, branchRemoved, stderr }
81
+ * → worktree cleanup attempted
82
+ *
83
+ * @param {{
84
+ * name: string,
85
+ * removeWorktree?: boolean,
86
+ * home?: string,
87
+ * runner?: import("./tmux.js").TmuxRunner,
88
+ * sessionExistsFn?: typeof tmuxSessionExists,
89
+ * killSessionFn?: typeof tmuxKillSession,
90
+ * removeWorktreeFn?: typeof removeWorktree,
91
+ * existsSync?: (p: string) => boolean,
92
+ * }} deps
93
+ * @returns {{
94
+ * ok: boolean,
95
+ * reason?: string,
96
+ * wasAlive?: boolean,
97
+ * worktree?: ReturnType<typeof removeWorktree> | null,
98
+ * }}
99
+ */
100
+ function killBySessionName(deps) {
101
+ const runner = deps.runner || defaultRunner();
102
+ const sessionExistsFn = deps.sessionExistsFn || tmuxSessionExists;
103
+ const killFn = deps.killSessionFn || tmuxKillSession;
104
+ const removeWtFn = deps.removeWorktreeFn || removeWorktree;
105
+ const existsSync = deps.existsSync || ((p) => fs.existsSync(p));
106
+
107
+ const entry = findSession(deps.name, deps.home);
108
+ if (!entry) return { ok: false, reason: "not in registry" };
109
+
110
+ // Best-effort kill: ignore the return value because we proceed with
111
+ // forget regardless. A failed kill on an alive session leaves a tmux
112
+ // orphan, but the registry stays consistent.
113
+ const wasAlive = sessionExistsFn(entry.name, runner);
114
+ if (wasAlive) killFn(entry.name, runner);
115
+
116
+ // forgetSession can throw if the lockfile can't be acquired (registry
117
+ // contention from concurrent __exec processes). Surface that as a
118
+ // structured failure instead of letting the exception escape — callers
119
+ // expect this helper to honor the { ok, reason, ... } contract.
120
+ try {
121
+ forgetSession(deps.name, deps.home);
122
+ } catch (err) {
123
+ return {
124
+ ok: false,
125
+ reason: `could not update registry: ${err && err.message ? err.message : String(err)}`,
126
+ wasAlive,
127
+ };
128
+ }
129
+
130
+ /** @type {ReturnType<typeof removeWorktree> | null} */
131
+ let wt = null;
132
+ if (
133
+ deps.removeWorktree &&
134
+ entry.worktree &&
135
+ entry.worktree.path &&
136
+ existsSync(entry.worktree.path)
137
+ ) {
138
+ wt = removeWtFn({
139
+ path: entry.worktree.path,
140
+ branch: entry.worktree.branch || undefined,
141
+ });
142
+ }
143
+ return { ok: true, wasAlive, worktree: wt };
144
+ }
145
+
146
+ /**
147
+ * Attach to a registered session, lazily restoring it from the registry
148
+ * if the tmux server doesn't currently have it. The lazy-restore step is
149
+ * what makes this useful after a reboot — `agileflow launch attach foo`
150
+ * Just Works whether or not foo is currently on the server.
151
+ *
152
+ * Failure cases (return { ok: false, reason }):
153
+ * - "not in registry" → unknown name
154
+ * - "cwd missing" → original directory deleted; can't restore
155
+ * - "could not restore" → tmux refused new-session (notes carries why)
156
+ *
157
+ * @param {{
158
+ * name: string,
159
+ * home?: string,
160
+ * prefs: import("./defaults.js").LaunchPrefs,
161
+ * agileflowBin?: string,
162
+ * runner?: import("./tmux.js").TmuxRunner,
163
+ * sessionExistsFn?: typeof tmuxSessionExists,
164
+ * attachSessionFn?: typeof tmuxAttachSession,
165
+ * runRestoreImpl?: typeof runRestore,
166
+ * existsSync?: (p: string) => boolean,
167
+ * }} deps
168
+ * @returns {Promise<{
169
+ * ok: boolean,
170
+ * reason?: string,
171
+ * restored?: boolean,
172
+ * attach?: Awaited<ReturnType<typeof tmuxAttachSession>>,
173
+ * notes?: Array<{ name: string, reason: string }>,
174
+ * }>}
175
+ */
176
+ async function attachByName(deps) {
177
+ const runner = deps.runner || defaultRunner();
178
+ const sessionExistsFn = deps.sessionExistsFn || tmuxSessionExists;
179
+ const attachFn = deps.attachSessionFn || tmuxAttachSession;
180
+ const restoreFn = deps.runRestoreImpl || runRestore;
181
+ const existsSync = deps.existsSync || ((p) => fs.existsSync(p));
182
+
183
+ const entry = findSession(deps.name, deps.home);
184
+ if (!entry) return { ok: false, reason: "not in registry" };
185
+ if (!existsSync(entry.cwd)) return { ok: false, reason: "cwd missing" };
186
+
187
+ let restored = false;
188
+ if (!sessionExistsFn(entry.name, runner)) {
189
+ const r = restoreFn({
190
+ prefs: deps.prefs,
191
+ runner,
192
+ home: deps.home,
193
+ agileflowBin: deps.agileflowBin,
194
+ onlyName: deps.name,
195
+ });
196
+ if (r.restored === 0) {
197
+ return { ok: false, reason: "could not restore", notes: r.notes };
198
+ }
199
+ restored = true;
200
+ }
201
+ const attach = await attachFn(entry.name, runner);
202
+ return { ok: true, restored, attach };
203
+ }
204
+
205
+ /**
206
+ * Return the registry entries that are safe to forget in bulk:
207
+ * - dormant + cwd missing (project deleted)
208
+ * - dormant + worktree dir missing (someone `git worktree remove`'d it)
209
+ *
210
+ * Alive sessions are NEVER candidates. Dormant entries with a live cwd
211
+ * stay too — the user likely just shut tmux down and intends to restore.
212
+ *
213
+ * Each candidate is annotated with `reason` so the CLI wrapper can show
214
+ * the user why it's offering the cleanup.
215
+ *
216
+ * @param {{
217
+ * home?: string,
218
+ * runner?: import("./tmux.js").TmuxRunner,
219
+ * sessionExistsFn?: typeof tmuxSessionExists,
220
+ * existsSync?: (p: string) => boolean,
221
+ * }} [deps]
222
+ * @returns {Array<ClassifiedSession & { reason: string }>}
223
+ */
224
+ function pruneCandidates(deps = {}) {
225
+ const existsSync = deps.existsSync || ((p) => fs.existsSync(p));
226
+ const classified = listSessions(deps);
227
+ /** @type {Array<ClassifiedSession & { reason: string }>} */
228
+ const out = [];
229
+ for (const c of classified) {
230
+ if (c.state === "alive") continue;
231
+ // Pinned entries are explicit "always keep" — never surface them as
232
+ // prune candidates, even if their cwd disappeared. The user has to
233
+ // unpin first if they really want to forget.
234
+ if (c.pinned) continue;
235
+ if (c.state === "missing-cwd") {
236
+ out.push({ ...c, reason: `cwd missing: ${c.cwd}` });
237
+ continue;
238
+ }
239
+ if (c.worktree && c.worktree.path && !existsSync(c.worktree.path)) {
240
+ out.push({
241
+ ...c,
242
+ reason: `worktree dir missing: ${c.worktree.path}`,
243
+ });
244
+ }
245
+ }
246
+ return out;
247
+ }
248
+
249
+ /**
250
+ * Apply a prune selection: forget each named entry, optionally remove
251
+ * its worktree (only when the path still exists — pruneCandidates
252
+ * surfaces missing-dir cases, but we don't want to issue `git worktree
253
+ * remove` on something the user already cleaned up manually).
254
+ *
255
+ * Returns counts so the CLI wrapper can print a one-line summary.
256
+ *
257
+ * @param {{
258
+ * selections: Array<{ name: string }>,
259
+ * removeWorktrees?: boolean,
260
+ * home?: string,
261
+ * removeWorktreeFn?: typeof removeWorktree,
262
+ * existsSync?: (p: string) => boolean,
263
+ * }} deps
264
+ * @returns {{ forgotten: number, worktreesRemoved: number, errors: Array<{ name: string, error: string }> }}
265
+ */
266
+ function applyPrune(deps) {
267
+ const removeWtFn = deps.removeWorktreeFn || removeWorktree;
268
+ const existsSync = deps.existsSync || ((p) => fs.existsSync(p));
269
+ let forgotten = 0;
270
+ let worktreesRemoved = 0;
271
+ /** @type {Array<{ name: string, error: string }>} */
272
+ const errors = [];
273
+
274
+ for (const sel of deps.selections || []) {
275
+ const entry = findSession(sel.name, deps.home);
276
+ if (!entry) {
277
+ // Concurrent prune from another process? Skip; nothing to do.
278
+ continue;
279
+ }
280
+ if (
281
+ deps.removeWorktrees &&
282
+ entry.worktree &&
283
+ entry.worktree.path &&
284
+ existsSync(entry.worktree.path)
285
+ ) {
286
+ try {
287
+ const r = removeWtFn({
288
+ path: entry.worktree.path,
289
+ branch: entry.worktree.branch || undefined,
290
+ });
291
+ if (r.removed) worktreesRemoved++;
292
+ if (r.stderr) errors.push({ name: sel.name, error: r.stderr });
293
+ } catch (err) {
294
+ errors.push({ name: sel.name, error: err.message || String(err) });
295
+ }
296
+ }
297
+ try {
298
+ forgetSession(sel.name, deps.home);
299
+ forgotten++;
300
+ } catch (err) {
301
+ errors.push({ name: sel.name, error: err.message || String(err) });
302
+ }
303
+ }
304
+ return { forgotten, worktreesRemoved, errors };
305
+ }
306
+
307
+ module.exports = {
308
+ listSessions,
309
+ killBySessionName,
310
+ attachByName,
311
+ pruneCandidates,
312
+ applyPrune,
313
+ };