agentic-qe 3.3.0 → 3.3.2

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 (416) hide show
  1. package/README.md +6 -2
  2. package/package.json +6 -1
  3. package/v3/CHANGELOG.md +134 -0
  4. package/v3/dist/cli/bundle.js +29332 -22739
  5. package/v3/dist/cli/command-registry.d.ts +55 -0
  6. package/v3/dist/cli/command-registry.d.ts.map +1 -0
  7. package/v3/dist/cli/command-registry.js +103 -0
  8. package/v3/dist/cli/command-registry.js.map +1 -0
  9. package/v3/dist/cli/commands/code.d.ts +9 -0
  10. package/v3/dist/cli/commands/code.d.ts.map +1 -0
  11. package/v3/dist/cli/commands/code.js +254 -0
  12. package/v3/dist/cli/commands/code.js.map +1 -0
  13. package/v3/dist/cli/commands/completions.d.ts +8 -0
  14. package/v3/dist/cli/commands/completions.d.ts.map +1 -0
  15. package/v3/dist/cli/commands/completions.js +99 -0
  16. package/v3/dist/cli/commands/completions.js.map +1 -0
  17. package/v3/dist/cli/commands/coverage.d.ts +9 -0
  18. package/v3/dist/cli/commands/coverage.d.ts.map +1 -0
  19. package/v3/dist/cli/commands/coverage.js +208 -0
  20. package/v3/dist/cli/commands/coverage.js.map +1 -0
  21. package/v3/dist/cli/commands/fleet.d.ts +11 -0
  22. package/v3/dist/cli/commands/fleet.d.ts.map +1 -0
  23. package/v3/dist/cli/commands/fleet.js +338 -0
  24. package/v3/dist/cli/commands/fleet.js.map +1 -0
  25. package/v3/dist/cli/commands/migrate.d.ts +9 -0
  26. package/v3/dist/cli/commands/migrate.d.ts.map +1 -0
  27. package/v3/dist/cli/commands/migrate.js +566 -0
  28. package/v3/dist/cli/commands/migrate.js.map +1 -0
  29. package/v3/dist/cli/commands/quality.d.ts +9 -0
  30. package/v3/dist/cli/commands/quality.d.ts.map +1 -0
  31. package/v3/dist/cli/commands/quality.js +40 -0
  32. package/v3/dist/cli/commands/quality.js.map +1 -0
  33. package/v3/dist/cli/commands/security.d.ts +9 -0
  34. package/v3/dist/cli/commands/security.d.ts.map +1 -0
  35. package/v3/dist/cli/commands/security.js +124 -0
  36. package/v3/dist/cli/commands/security.js.map +1 -0
  37. package/v3/dist/cli/commands/sync.d.ts +19 -0
  38. package/v3/dist/cli/commands/sync.d.ts.map +1 -0
  39. package/v3/dist/cli/commands/sync.js +283 -0
  40. package/v3/dist/cli/commands/sync.js.map +1 -0
  41. package/v3/dist/cli/commands/test.d.ts +9 -0
  42. package/v3/dist/cli/commands/test.d.ts.map +1 -0
  43. package/v3/dist/cli/commands/test.js +166 -0
  44. package/v3/dist/cli/commands/test.js.map +1 -0
  45. package/v3/dist/cli/handlers/agent-handler.d.ts +20 -0
  46. package/v3/dist/cli/handlers/agent-handler.d.ts.map +1 -0
  47. package/v3/dist/cli/handlers/agent-handler.js +158 -0
  48. package/v3/dist/cli/handlers/agent-handler.js.map +1 -0
  49. package/v3/dist/cli/handlers/domain-handler.d.ts +20 -0
  50. package/v3/dist/cli/handlers/domain-handler.d.ts.map +1 -0
  51. package/v3/dist/cli/handlers/domain-handler.js +115 -0
  52. package/v3/dist/cli/handlers/domain-handler.js.map +1 -0
  53. package/v3/dist/cli/handlers/index.d.ts +13 -0
  54. package/v3/dist/cli/handlers/index.d.ts.map +1 -0
  55. package/v3/dist/cli/handlers/index.js +15 -0
  56. package/v3/dist/cli/handlers/index.js.map +1 -0
  57. package/v3/dist/cli/handlers/init-handler.d.ts +38 -0
  58. package/v3/dist/cli/handlers/init-handler.d.ts.map +1 -0
  59. package/v3/dist/cli/handlers/init-handler.js +288 -0
  60. package/v3/dist/cli/handlers/init-handler.js.map +1 -0
  61. package/v3/dist/cli/handlers/interfaces.d.ts +104 -0
  62. package/v3/dist/cli/handlers/interfaces.d.ts.map +1 -0
  63. package/v3/dist/cli/handlers/interfaces.js +109 -0
  64. package/v3/dist/cli/handlers/interfaces.js.map +1 -0
  65. package/v3/dist/cli/handlers/protocol-handler.d.ts +19 -0
  66. package/v3/dist/cli/handlers/protocol-handler.d.ts.map +1 -0
  67. package/v3/dist/cli/handlers/protocol-handler.js +79 -0
  68. package/v3/dist/cli/handlers/protocol-handler.js.map +1 -0
  69. package/v3/dist/cli/handlers/status-handler.d.ts +30 -0
  70. package/v3/dist/cli/handlers/status-handler.d.ts.map +1 -0
  71. package/v3/dist/cli/handlers/status-handler.js +218 -0
  72. package/v3/dist/cli/handlers/status-handler.js.map +1 -0
  73. package/v3/dist/cli/handlers/task-handler.d.ts +22 -0
  74. package/v3/dist/cli/handlers/task-handler.d.ts.map +1 -0
  75. package/v3/dist/cli/handlers/task-handler.js +271 -0
  76. package/v3/dist/cli/handlers/task-handler.js.map +1 -0
  77. package/v3/dist/cli/index.d.ts +4 -0
  78. package/v3/dist/cli/index.d.ts.map +1 -1
  79. package/v3/dist/cli/index.js +48 -2677
  80. package/v3/dist/cli/index.js.map +1 -1
  81. package/v3/dist/cli/wizards/core/index.d.ts +11 -0
  82. package/v3/dist/cli/wizards/core/index.d.ts.map +1 -0
  83. package/v3/dist/cli/wizards/core/index.js +15 -0
  84. package/v3/dist/cli/wizards/core/index.js.map +1 -0
  85. package/v3/dist/cli/wizards/core/wizard-base.d.ts +87 -0
  86. package/v3/dist/cli/wizards/core/wizard-base.d.ts.map +1 -0
  87. package/v3/dist/cli/wizards/core/wizard-base.js +120 -0
  88. package/v3/dist/cli/wizards/core/wizard-base.js.map +1 -0
  89. package/v3/dist/cli/wizards/core/wizard-command.d.ts +182 -0
  90. package/v3/dist/cli/wizards/core/wizard-command.d.ts.map +1 -0
  91. package/v3/dist/cli/wizards/core/wizard-command.js +45 -0
  92. package/v3/dist/cli/wizards/core/wizard-command.js.map +1 -0
  93. package/v3/dist/cli/wizards/core/wizard-step.d.ts +109 -0
  94. package/v3/dist/cli/wizards/core/wizard-step.d.ts.map +1 -0
  95. package/v3/dist/cli/wizards/core/wizard-step.js +384 -0
  96. package/v3/dist/cli/wizards/core/wizard-step.js.map +1 -0
  97. package/v3/dist/cli/wizards/core/wizard-utils.d.ts +117 -0
  98. package/v3/dist/cli/wizards/core/wizard-utils.d.ts.map +1 -0
  99. package/v3/dist/cli/wizards/core/wizard-utils.js +291 -0
  100. package/v3/dist/cli/wizards/core/wizard-utils.js.map +1 -0
  101. package/v3/dist/cli/wizards/coverage-wizard.d.ts +13 -68
  102. package/v3/dist/cli/wizards/coverage-wizard.d.ts.map +1 -1
  103. package/v3/dist/cli/wizards/coverage-wizard.js +127 -391
  104. package/v3/dist/cli/wizards/coverage-wizard.js.map +1 -1
  105. package/v3/dist/cli/wizards/fleet-wizard.d.ts +13 -64
  106. package/v3/dist/cli/wizards/fleet-wizard.d.ts.map +1 -1
  107. package/v3/dist/cli/wizards/fleet-wizard.js +150 -363
  108. package/v3/dist/cli/wizards/fleet-wizard.js.map +1 -1
  109. package/v3/dist/cli/wizards/index.d.ts +2 -0
  110. package/v3/dist/cli/wizards/index.d.ts.map +1 -1
  111. package/v3/dist/cli/wizards/index.js +3 -0
  112. package/v3/dist/cli/wizards/index.js.map +1 -1
  113. package/v3/dist/cli/wizards/security-wizard.d.ts +13 -64
  114. package/v3/dist/cli/wizards/security-wizard.d.ts.map +1 -1
  115. package/v3/dist/cli/wizards/security-wizard.js +152 -395
  116. package/v3/dist/cli/wizards/security-wizard.js.map +1 -1
  117. package/v3/dist/cli/wizards/test-wizard.d.ts +13 -77
  118. package/v3/dist/cli/wizards/test-wizard.d.ts.map +1 -1
  119. package/v3/dist/cli/wizards/test-wizard.js +196 -328
  120. package/v3/dist/cli/wizards/test-wizard.js.map +1 -1
  121. package/v3/dist/coordination/mincut/mincut-health-monitor.d.ts +3 -0
  122. package/v3/dist/coordination/mincut/mincut-health-monitor.d.ts.map +1 -1
  123. package/v3/dist/coordination/mincut/mincut-health-monitor.js +6 -2
  124. package/v3/dist/coordination/mincut/mincut-health-monitor.js.map +1 -1
  125. package/v3/dist/coordination/mincut/queen-integration.d.ts +3 -0
  126. package/v3/dist/coordination/mincut/queen-integration.d.ts.map +1 -1
  127. package/v3/dist/coordination/mincut/queen-integration.js +6 -1
  128. package/v3/dist/coordination/mincut/queen-integration.js.map +1 -1
  129. package/v3/dist/coordination/queen-coordinator.d.ts +13 -1
  130. package/v3/dist/coordination/queen-coordinator.d.ts.map +1 -1
  131. package/v3/dist/coordination/queen-coordinator.js +91 -3
  132. package/v3/dist/coordination/queen-coordinator.js.map +1 -1
  133. package/v3/dist/coordination/task-executor.js +2 -2
  134. package/v3/dist/coordination/task-executor.js.map +1 -1
  135. package/v3/dist/domains/chaos-resilience/plugin.js +2 -2
  136. package/v3/dist/domains/chaos-resilience/plugin.js.map +1 -1
  137. package/v3/dist/domains/code-intelligence/plugin.js +2 -2
  138. package/v3/dist/domains/code-intelligence/plugin.js.map +1 -1
  139. package/v3/dist/domains/contract-testing/plugin.js +2 -2
  140. package/v3/dist/domains/contract-testing/plugin.js.map +1 -1
  141. package/v3/dist/domains/coverage-analysis/plugin.d.ts +6 -1
  142. package/v3/dist/domains/coverage-analysis/plugin.d.ts.map +1 -1
  143. package/v3/dist/domains/coverage-analysis/plugin.js +75 -1
  144. package/v3/dist/domains/coverage-analysis/plugin.js.map +1 -1
  145. package/v3/dist/domains/defect-intelligence/plugin.js +2 -2
  146. package/v3/dist/domains/defect-intelligence/plugin.js.map +1 -1
  147. package/v3/dist/domains/domain-interface.d.ts +39 -2
  148. package/v3/dist/domains/domain-interface.d.ts.map +1 -1
  149. package/v3/dist/domains/domain-interface.js +102 -1
  150. package/v3/dist/domains/domain-interface.js.map +1 -1
  151. package/v3/dist/domains/learning-optimization/coordinator.d.ts +83 -0
  152. package/v3/dist/domains/learning-optimization/coordinator.d.ts.map +1 -1
  153. package/v3/dist/domains/learning-optimization/coordinator.js +174 -0
  154. package/v3/dist/domains/learning-optimization/coordinator.js.map +1 -1
  155. package/v3/dist/domains/learning-optimization/interfaces.d.ts +14 -0
  156. package/v3/dist/domains/learning-optimization/interfaces.d.ts.map +1 -1
  157. package/v3/dist/domains/learning-optimization/plugin.js +2 -2
  158. package/v3/dist/domains/learning-optimization/plugin.js.map +1 -1
  159. package/v3/dist/domains/quality-assessment/coordinator.d.ts +23 -0
  160. package/v3/dist/domains/quality-assessment/coordinator.d.ts.map +1 -1
  161. package/v3/dist/domains/quality-assessment/coordinator.js +139 -1
  162. package/v3/dist/domains/quality-assessment/coordinator.js.map +1 -1
  163. package/v3/dist/domains/quality-assessment/plugin.d.ts +6 -1
  164. package/v3/dist/domains/quality-assessment/plugin.d.ts.map +1 -1
  165. package/v3/dist/domains/quality-assessment/plugin.js +69 -2
  166. package/v3/dist/domains/quality-assessment/plugin.js.map +1 -1
  167. package/v3/dist/domains/requirements-validation/plugin.js +2 -2
  168. package/v3/dist/domains/requirements-validation/plugin.js.map +1 -1
  169. package/v3/dist/domains/security-compliance/plugin.js +2 -2
  170. package/v3/dist/domains/security-compliance/plugin.js.map +1 -1
  171. package/v3/dist/domains/test-execution/index.d.ts +2 -1
  172. package/v3/dist/domains/test-execution/index.d.ts.map +1 -1
  173. package/v3/dist/domains/test-execution/index.js +0 -2
  174. package/v3/dist/domains/test-execution/index.js.map +1 -1
  175. package/v3/dist/domains/test-execution/interfaces.d.ts +222 -25
  176. package/v3/dist/domains/test-execution/interfaces.d.ts.map +1 -1
  177. package/v3/dist/domains/test-execution/interfaces.js +130 -3
  178. package/v3/dist/domains/test-execution/interfaces.js.map +1 -1
  179. package/v3/dist/domains/test-execution/plugin.d.ts +6 -1
  180. package/v3/dist/domains/test-execution/plugin.d.ts.map +1 -1
  181. package/v3/dist/domains/test-execution/plugin.js +79 -1
  182. package/v3/dist/domains/test-execution/plugin.js.map +1 -1
  183. package/v3/dist/domains/test-execution/test-prioritization-types.d.ts +5 -172
  184. package/v3/dist/domains/test-execution/test-prioritization-types.d.ts.map +1 -1
  185. package/v3/dist/domains/test-execution/test-prioritization-types.js +6 -129
  186. package/v3/dist/domains/test-execution/test-prioritization-types.js.map +1 -1
  187. package/v3/dist/domains/test-execution/types/index.d.ts +7 -3
  188. package/v3/dist/domains/test-execution/types/index.d.ts.map +1 -1
  189. package/v3/dist/domains/test-execution/types/index.js +7 -17
  190. package/v3/dist/domains/test-execution/types/index.js.map +1 -1
  191. package/v3/dist/domains/test-generation/coordinator.d.ts +41 -1
  192. package/v3/dist/domains/test-generation/coordinator.d.ts.map +1 -1
  193. package/v3/dist/domains/test-generation/coordinator.js +187 -4
  194. package/v3/dist/domains/test-generation/coordinator.js.map +1 -1
  195. package/v3/dist/domains/test-generation/factories/index.d.ts +8 -0
  196. package/v3/dist/domains/test-generation/factories/index.d.ts.map +1 -0
  197. package/v3/dist/domains/test-generation/factories/index.js +8 -0
  198. package/v3/dist/domains/test-generation/factories/index.js.map +1 -0
  199. package/v3/dist/domains/test-generation/factories/test-generator-factory.d.ts +108 -0
  200. package/v3/dist/domains/test-generation/factories/test-generator-factory.d.ts.map +1 -0
  201. package/v3/dist/domains/test-generation/factories/test-generator-factory.js +158 -0
  202. package/v3/dist/domains/test-generation/factories/test-generator-factory.js.map +1 -0
  203. package/v3/dist/domains/test-generation/generators/base-test-generator.d.ts +79 -0
  204. package/v3/dist/domains/test-generation/generators/base-test-generator.d.ts.map +1 -0
  205. package/v3/dist/domains/test-generation/generators/base-test-generator.js +252 -0
  206. package/v3/dist/domains/test-generation/generators/base-test-generator.js.map +1 -0
  207. package/v3/dist/domains/test-generation/generators/index.d.ts +11 -0
  208. package/v3/dist/domains/test-generation/generators/index.d.ts.map +1 -0
  209. package/v3/dist/domains/test-generation/generators/index.js +13 -0
  210. package/v3/dist/domains/test-generation/generators/index.js.map +1 -0
  211. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.d.ts +77 -0
  212. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.d.ts.map +1 -0
  213. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.js +365 -0
  214. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.js.map +1 -0
  215. package/v3/dist/domains/test-generation/generators/mocha-generator.d.ts +56 -0
  216. package/v3/dist/domains/test-generation/generators/mocha-generator.d.ts.map +1 -0
  217. package/v3/dist/domains/test-generation/generators/mocha-generator.js +197 -0
  218. package/v3/dist/domains/test-generation/generators/mocha-generator.js.map +1 -0
  219. package/v3/dist/domains/test-generation/generators/pytest-generator.d.ts +66 -0
  220. package/v3/dist/domains/test-generation/generators/pytest-generator.d.ts.map +1 -0
  221. package/v3/dist/domains/test-generation/generators/pytest-generator.js +240 -0
  222. package/v3/dist/domains/test-generation/generators/pytest-generator.js.map +1 -0
  223. package/v3/dist/domains/test-generation/index.d.ts +2 -2
  224. package/v3/dist/domains/test-generation/index.d.ts.map +1 -1
  225. package/v3/dist/domains/test-generation/index.js +3 -3
  226. package/v3/dist/domains/test-generation/index.js.map +1 -1
  227. package/v3/dist/domains/test-generation/interfaces/index.d.ts +9 -0
  228. package/v3/dist/domains/test-generation/interfaces/index.d.ts.map +1 -0
  229. package/v3/dist/domains/test-generation/interfaces/index.js +9 -0
  230. package/v3/dist/domains/test-generation/interfaces/index.js.map +1 -0
  231. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.d.ts +166 -0
  232. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.d.ts.map +1 -0
  233. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.js +8 -0
  234. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.js.map +1 -0
  235. package/v3/dist/domains/test-generation/interfaces.d.ts +163 -24
  236. package/v3/dist/domains/test-generation/interfaces.d.ts.map +1 -1
  237. package/v3/dist/domains/test-generation/interfaces.js +2 -2
  238. package/v3/dist/domains/test-generation/plugin.d.ts +6 -1
  239. package/v3/dist/domains/test-generation/plugin.d.ts.map +1 -1
  240. package/v3/dist/domains/test-generation/plugin.js +90 -5
  241. package/v3/dist/domains/test-generation/plugin.js.map +1 -1
  242. package/v3/dist/domains/test-generation/{coherence-gate.d.ts → services/coherence-gate-service.d.ts} +4 -4
  243. package/v3/dist/domains/test-generation/services/coherence-gate-service.d.ts.map +1 -0
  244. package/v3/dist/domains/test-generation/{coherence-gate.js → services/coherence-gate-service.js} +2 -2
  245. package/v3/dist/domains/test-generation/services/coherence-gate-service.js.map +1 -0
  246. package/v3/dist/domains/test-generation/services/index.d.ts +8 -2
  247. package/v3/dist/domains/test-generation/services/index.d.ts.map +1 -1
  248. package/v3/dist/domains/test-generation/services/index.js +10 -3
  249. package/v3/dist/domains/test-generation/services/index.js.map +1 -1
  250. package/v3/dist/domains/test-generation/services/property-test-generator.d.ts +34 -0
  251. package/v3/dist/domains/test-generation/services/property-test-generator.d.ts.map +1 -0
  252. package/v3/dist/domains/test-generation/services/property-test-generator.js +306 -0
  253. package/v3/dist/domains/test-generation/services/property-test-generator.js.map +1 -0
  254. package/v3/dist/domains/test-generation/services/tdd-generator.d.ts +33 -0
  255. package/v3/dist/domains/test-generation/services/tdd-generator.d.ts.map +1 -0
  256. package/v3/dist/domains/test-generation/services/tdd-generator.js +342 -0
  257. package/v3/dist/domains/test-generation/services/tdd-generator.js.map +1 -0
  258. package/v3/dist/domains/test-generation/services/test-data-generator.d.ts +34 -0
  259. package/v3/dist/domains/test-generation/services/test-data-generator.d.ts.map +1 -0
  260. package/v3/dist/domains/test-generation/services/test-data-generator.js +245 -0
  261. package/v3/dist/domains/test-generation/services/test-data-generator.js.map +1 -0
  262. package/v3/dist/domains/test-generation/services/test-generator.d.ts +51 -160
  263. package/v3/dist/domains/test-generation/services/test-generator.d.ts.map +1 -1
  264. package/v3/dist/domains/test-generation/services/test-generator.js +101 -1858
  265. package/v3/dist/domains/test-generation/services/test-generator.js.map +1 -1
  266. package/v3/dist/domains/visual-accessibility/plugin.js +2 -2
  267. package/v3/dist/domains/visual-accessibility/plugin.js.map +1 -1
  268. package/v3/dist/init/phases/12-verification.d.ts +23 -0
  269. package/v3/dist/init/phases/12-verification.d.ts.map +1 -1
  270. package/v3/dist/init/phases/12-verification.js +185 -2
  271. package/v3/dist/init/phases/12-verification.js.map +1 -1
  272. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.d.ts +24 -62
  273. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.d.ts.map +1 -1
  274. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.js +45 -497
  275. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.js.map +1 -1
  276. package/v3/dist/integrations/agentic-flow/model-router/router.js +2 -2
  277. package/v3/dist/integrations/agentic-flow/model-router/router.js.map +1 -1
  278. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.d.ts +98 -0
  279. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.d.ts.map +1 -0
  280. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js +197 -0
  281. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js.map +1 -0
  282. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts +102 -0
  283. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts.map +1 -0
  284. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js +372 -0
  285. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js.map +1 -0
  286. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.d.ts +64 -0
  287. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.d.ts.map +1 -0
  288. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.js +120 -0
  289. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.js.map +1 -0
  290. package/v3/dist/integrations/coherence/coherence-service.d.ts.map +1 -1
  291. package/v3/dist/integrations/coherence/coherence-service.js +87 -30
  292. package/v3/dist/integrations/coherence/coherence-service.js.map +1 -1
  293. package/v3/dist/integrations/coherence/engines/spectral-adapter.d.ts.map +1 -1
  294. package/v3/dist/integrations/coherence/engines/spectral-adapter.js +124 -35
  295. package/v3/dist/integrations/coherence/engines/spectral-adapter.js.map +1 -1
  296. package/v3/dist/kernel/interfaces.d.ts +54 -1
  297. package/v3/dist/kernel/interfaces.d.ts.map +1 -1
  298. package/v3/dist/learning/dream/dream-scheduler.d.ts +302 -0
  299. package/v3/dist/learning/dream/dream-scheduler.d.ts.map +1 -0
  300. package/v3/dist/learning/dream/dream-scheduler.js +551 -0
  301. package/v3/dist/learning/dream/dream-scheduler.js.map +1 -0
  302. package/v3/dist/learning/dream/index.d.ts +1 -0
  303. package/v3/dist/learning/dream/index.d.ts.map +1 -1
  304. package/v3/dist/learning/dream/index.js +4 -0
  305. package/v3/dist/learning/dream/index.js.map +1 -1
  306. package/v3/dist/learning/memory-auditor.d.ts.map +1 -1
  307. package/v3/dist/learning/memory-auditor.js +3 -1
  308. package/v3/dist/learning/memory-auditor.js.map +1 -1
  309. package/v3/dist/mcp/bundle.js +30870 -23598
  310. package/v3/dist/mcp/handlers/core-handlers.d.ts.map +1 -1
  311. package/v3/dist/mcp/handlers/core-handlers.js +16 -2
  312. package/v3/dist/mcp/handlers/core-handlers.js.map +1 -1
  313. package/v3/dist/mcp/handlers/task-handlers.d.ts +1 -0
  314. package/v3/dist/mcp/handlers/task-handlers.d.ts.map +1 -1
  315. package/v3/dist/mcp/handlers/task-handlers.js +46 -12
  316. package/v3/dist/mcp/handlers/task-handlers.js.map +1 -1
  317. package/v3/dist/mcp/security/cve-prevention.d.ts +31 -134
  318. package/v3/dist/mcp/security/cve-prevention.d.ts.map +1 -1
  319. package/v3/dist/mcp/security/cve-prevention.js +37 -562
  320. package/v3/dist/mcp/security/cve-prevention.js.map +1 -1
  321. package/v3/dist/mcp/security/index.d.ts +5 -1
  322. package/v3/dist/mcp/security/index.d.ts.map +1 -1
  323. package/v3/dist/mcp/security/validators/command-validator.d.ts +41 -0
  324. package/v3/dist/mcp/security/validators/command-validator.d.ts.map +1 -0
  325. package/v3/dist/mcp/security/validators/command-validator.js +123 -0
  326. package/v3/dist/mcp/security/validators/command-validator.js.map +1 -0
  327. package/v3/dist/mcp/security/validators/crypto-validator.d.ts +40 -0
  328. package/v3/dist/mcp/security/validators/crypto-validator.d.ts.map +1 -0
  329. package/v3/dist/mcp/security/validators/crypto-validator.js +72 -0
  330. package/v3/dist/mcp/security/validators/crypto-validator.js.map +1 -0
  331. package/v3/dist/mcp/security/validators/index.d.ts +12 -0
  332. package/v3/dist/mcp/security/validators/index.d.ts.map +1 -0
  333. package/v3/dist/mcp/security/validators/index.js +22 -0
  334. package/v3/dist/mcp/security/validators/index.js.map +1 -0
  335. package/v3/dist/mcp/security/validators/input-sanitizer.d.ts +56 -0
  336. package/v3/dist/mcp/security/validators/input-sanitizer.d.ts.map +1 -0
  337. package/v3/dist/mcp/security/validators/input-sanitizer.js +157 -0
  338. package/v3/dist/mcp/security/validators/input-sanitizer.js.map +1 -0
  339. package/v3/dist/mcp/security/validators/interfaces.d.ts +164 -0
  340. package/v3/dist/mcp/security/validators/interfaces.d.ts.map +1 -0
  341. package/v3/dist/mcp/security/validators/interfaces.js +6 -0
  342. package/v3/dist/mcp/security/validators/interfaces.js.map +1 -0
  343. package/v3/dist/mcp/security/validators/path-traversal-validator.d.ts +50 -0
  344. package/v3/dist/mcp/security/validators/path-traversal-validator.d.ts.map +1 -0
  345. package/v3/dist/mcp/security/validators/path-traversal-validator.js +242 -0
  346. package/v3/dist/mcp/security/validators/path-traversal-validator.js.map +1 -0
  347. package/v3/dist/mcp/security/validators/regex-safety-validator.d.ts +50 -0
  348. package/v3/dist/mcp/security/validators/regex-safety-validator.d.ts.map +1 -0
  349. package/v3/dist/mcp/security/validators/regex-safety-validator.js +183 -0
  350. package/v3/dist/mcp/security/validators/regex-safety-validator.js.map +1 -0
  351. package/v3/dist/mcp/security/validators/validation-orchestrator.d.ts +66 -0
  352. package/v3/dist/mcp/security/validators/validation-orchestrator.d.ts.map +1 -0
  353. package/v3/dist/mcp/security/validators/validation-orchestrator.js +146 -0
  354. package/v3/dist/mcp/security/validators/validation-orchestrator.js.map +1 -0
  355. package/v3/dist/mcp/server.d.ts.map +1 -1
  356. package/v3/dist/mcp/server.js +1 -0
  357. package/v3/dist/mcp/server.js.map +1 -1
  358. package/v3/dist/mcp/services/reasoning-bank-service.d.ts +87 -13
  359. package/v3/dist/mcp/services/reasoning-bank-service.d.ts.map +1 -1
  360. package/v3/dist/mcp/services/reasoning-bank-service.js +291 -31
  361. package/v3/dist/mcp/services/reasoning-bank-service.js.map +1 -1
  362. package/v3/dist/mcp/tool-registry.d.ts +3 -1
  363. package/v3/dist/mcp/tool-registry.d.ts.map +1 -1
  364. package/v3/dist/mcp/tool-registry.js +155 -2
  365. package/v3/dist/mcp/tool-registry.js.map +1 -1
  366. package/v3/dist/mcp/tools/test-generation/generate.d.ts +1 -0
  367. package/v3/dist/mcp/tools/test-generation/generate.d.ts.map +1 -1
  368. package/v3/dist/mcp/tools/test-generation/generate.js +3 -2
  369. package/v3/dist/mcp/tools/test-generation/generate.js.map +1 -1
  370. package/v3/dist/routing/qe-agent-registry.d.ts +27 -0
  371. package/v3/dist/routing/qe-agent-registry.d.ts.map +1 -1
  372. package/v3/dist/routing/qe-agent-registry.js +96 -0
  373. package/v3/dist/routing/qe-agent-registry.js.map +1 -1
  374. package/v3/dist/shared/events/domain-events.d.ts +27 -0
  375. package/v3/dist/shared/events/domain-events.d.ts.map +1 -1
  376. package/v3/dist/shared/events/domain-events.js +1 -0
  377. package/v3/dist/shared/events/domain-events.js.map +1 -1
  378. package/v3/dist/sync/cloud/index.d.ts +8 -0
  379. package/v3/dist/sync/cloud/index.d.ts.map +1 -0
  380. package/v3/dist/sync/cloud/index.js +8 -0
  381. package/v3/dist/sync/cloud/index.js.map +1 -0
  382. package/v3/dist/sync/cloud/postgres-writer.d.ts +88 -0
  383. package/v3/dist/sync/cloud/postgres-writer.d.ts.map +1 -0
  384. package/v3/dist/sync/cloud/postgres-writer.js +319 -0
  385. package/v3/dist/sync/cloud/postgres-writer.js.map +1 -0
  386. package/v3/dist/sync/cloud/tunnel-manager.d.ts +75 -0
  387. package/v3/dist/sync/cloud/tunnel-manager.d.ts.map +1 -0
  388. package/v3/dist/sync/cloud/tunnel-manager.js +221 -0
  389. package/v3/dist/sync/cloud/tunnel-manager.js.map +1 -0
  390. package/v3/dist/sync/index.d.ts +35 -0
  391. package/v3/dist/sync/index.d.ts.map +1 -0
  392. package/v3/dist/sync/index.js +35 -0
  393. package/v3/dist/sync/index.js.map +1 -0
  394. package/v3/dist/sync/interfaces.d.ts +245 -0
  395. package/v3/dist/sync/interfaces.d.ts.map +1 -0
  396. package/v3/dist/sync/interfaces.js +160 -0
  397. package/v3/dist/sync/interfaces.js.map +1 -0
  398. package/v3/dist/sync/readers/index.d.ts +8 -0
  399. package/v3/dist/sync/readers/index.d.ts.map +1 -0
  400. package/v3/dist/sync/readers/index.js +8 -0
  401. package/v3/dist/sync/readers/index.js.map +1 -0
  402. package/v3/dist/sync/readers/json-reader.d.ts +95 -0
  403. package/v3/dist/sync/readers/json-reader.d.ts.map +1 -0
  404. package/v3/dist/sync/readers/json-reader.js +306 -0
  405. package/v3/dist/sync/readers/json-reader.js.map +1 -0
  406. package/v3/dist/sync/readers/sqlite-reader.d.ts +88 -0
  407. package/v3/dist/sync/readers/sqlite-reader.d.ts.map +1 -0
  408. package/v3/dist/sync/readers/sqlite-reader.js +255 -0
  409. package/v3/dist/sync/readers/sqlite-reader.js.map +1 -0
  410. package/v3/dist/sync/sync-agent.d.ts +116 -0
  411. package/v3/dist/sync/sync-agent.d.ts.map +1 -0
  412. package/v3/dist/sync/sync-agent.js +416 -0
  413. package/v3/dist/sync/sync-agent.js.map +1 -0
  414. package/v3/package.json +13 -2
  415. package/v3/dist/domains/test-generation/coherence-gate.d.ts.map +0 -1
  416. package/v3/dist/domains/test-generation/coherence-gate.js.map +0 -1
@@ -4,6 +4,10 @@
4
4
  *
5
5
  * Provides CLI access to the v3 DDD architecture through the Queen Coordinator.
6
6
  * All commands delegate to domain services via the coordination layer.
7
+ *
8
+ * Refactored to use CommandRegistry and handlers for better maintainability.
9
+ * See: cli/handlers/ for command implementations
10
+ * See: cli/commands/ for additional command modules
7
11
  */
8
12
  import { Command } from 'commander';
9
13
  import chalk from 'chalk';
@@ -14,19 +18,16 @@ import { CrossDomainEventRouter } from '../coordination/cross-domain-router';
14
18
  import { DefaultProtocolExecutor } from '../coordination/protocol-executor';
15
19
  import { WorkflowOrchestrator } from '../coordination/workflow-orchestrator';
16
20
  import { ALL_DOMAINS } from '../shared/types';
17
- import { InitOrchestrator } from '../init/init-wizard';
18
- import { createModularInitOrchestrator, } from '../init/orchestrator.js';
19
- import { integrateCodeIntelligence } from '../init/fleet-integration';
20
- import { setupClaudeFlowIntegration } from './commands/claude-flow-setup.js';
21
- import { generateCompletion, detectShell, getInstallInstructions, DOMAINS as COMPLETION_DOMAINS, QE_AGENTS, OTHER_AGENTS, } from './completions/index.js';
22
- import { FleetProgressManager, createTimedSpinner, } from './utils/progress';
23
21
  import { bootstrapTokenTracking, shutdownTokenTracking } from '../init/token-bootstrap.js';
24
22
  import { parsePipelineFile, validatePipeline, describeCronSchedule, } from './utils/workflow-parser.js';
25
- import { runCoverageAnalysisWizard, } from './wizards/coverage-wizard.js';
26
- import { parseJsonOption, parseJsonFile } from './helpers/safe-json.js';
27
- import { runFleetInitWizard, } from './wizards/fleet-wizard.js';
23
+ import { parseJsonOption } from './helpers/safe-json.js';
28
24
  import { createPersistentScheduler, createScheduleEntry, } from './scheduler/index.js';
29
- import { v2AgentMapping, resolveAgentName, isDeprecatedAgent, v3Agents, } from '../migration/agent-compat.js';
25
+ // Import handlers and registry
26
+ import { createCommandRegistry } from './command-registry.js';
27
+ import { formatDuration } from './handlers/interfaces.js';
28
+ // ============================================================================
29
+ // CLI State
30
+ // ============================================================================
30
31
  const context = {
31
32
  kernel: null,
32
33
  queen: null,
@@ -38,85 +39,40 @@ const context = {
38
39
  };
39
40
  /**
40
41
  * Register domain workflow actions with the WorkflowOrchestrator (Issue #206)
41
- * This enables domain-specific actions to be used in pipeline YAML workflows.
42
42
  */
43
43
  function registerDomainWorkflowActions(kernel, orchestrator) {
44
- // Register visual-accessibility domain actions
45
44
  const visualAccessibilityAPI = kernel.getDomainAPI('visual-accessibility');
46
45
  if (visualAccessibilityAPI?.registerWorkflowActions) {
47
46
  try {
48
47
  visualAccessibilityAPI.registerWorkflowActions(orchestrator);
49
48
  }
50
49
  catch (error) {
51
- // Log but don't fail - domain may not be enabled
52
- console.error(chalk.yellow(` ⚠ Could not register visual-accessibility workflow actions: ${error instanceof Error ? error.message : String(error)}`));
50
+ console.error(chalk.yellow(` Warning: Could not register visual-accessibility workflow actions: ${error instanceof Error ? error.message : String(error)}`));
53
51
  }
54
52
  }
55
- // Additional domain action registrations can be added here as needed
56
- // Example: registerTestGenerationWorkflowActions(kernel, orchestrator);
57
53
  }
58
54
  // ============================================================================
59
55
  // Helper Functions
60
56
  // ============================================================================
61
- function getStatusColor(status) {
62
- switch (status) {
63
- case 'healthy':
64
- case 'completed':
65
- return chalk.green(status);
66
- case 'idle':
67
- // Issue #205 fix: 'idle' is normal - show in cyan (neutral/ready)
68
- return chalk.cyan(status);
69
- case 'degraded':
70
- case 'running':
71
- return chalk.yellow(status);
72
- case 'unhealthy':
73
- case 'failed':
74
- return chalk.red(status);
75
- default:
76
- return chalk.gray(status);
77
- }
78
- }
79
- function formatDuration(ms) {
80
- if (ms < 1000)
81
- return `${ms}ms`;
82
- if (ms < 60000)
83
- return `${(ms / 1000).toFixed(1)}s`;
84
- if (ms < 3600000)
85
- return `${(ms / 60000).toFixed(1)}m`;
86
- return `${(ms / 3600000).toFixed(1)}h`;
87
- }
88
- function formatUptime(ms) {
89
- const hours = Math.floor(ms / 3600000);
90
- const minutes = Math.floor((ms % 3600000) / 60000);
91
- const seconds = Math.floor((ms % 60000) / 1000);
92
- return `${hours}h ${minutes}m ${seconds}s`;
93
- }
94
57
  async function autoInitialize() {
95
- // Create kernel with defaults
96
58
  context.kernel = new QEKernelImpl({
97
59
  maxConcurrentAgents: 15,
98
60
  memoryBackend: 'sqlite',
99
61
  hnswEnabled: true,
100
- lazyLoading: true, // ADR-046: Enable lazy loading to reduce memory footprint (was causing OOM)
62
+ lazyLoading: true,
101
63
  enabledDomains: [...ALL_DOMAINS],
102
64
  });
103
65
  await context.kernel.initialize();
104
- // Create cross-domain router
105
66
  context.router = new CrossDomainEventRouter(context.kernel.eventBus);
106
67
  await context.router.initialize();
107
- // Create protocol executor
108
68
  const getDomainAPI = (domain) => {
109
69
  return context.kernel.getDomainAPI(domain);
110
70
  };
111
71
  const protocolExecutor = new DefaultProtocolExecutor(context.kernel.eventBus, context.kernel.memory, getDomainAPI);
112
- // Create workflow orchestrator
113
72
  context.workflowOrchestrator = new WorkflowOrchestrator(context.kernel.eventBus, context.kernel.memory, context.kernel.coordinator);
114
73
  await context.workflowOrchestrator.initialize();
115
- // Register domain workflow actions (Issue #206)
116
74
  registerDomainWorkflowActions(context.kernel, context.workflowOrchestrator);
117
- // Create persistent scheduler for workflow scheduling (ADR-041)
118
75
  context.persistentScheduler = createPersistentScheduler();
119
- // Create Queen Coordinator
120
76
  context.queen = createQueenCoordinator(context.kernel, context.router, protocolExecutor, undefined);
121
77
  await context.queen.initialize();
122
78
  context.initialized = true;
@@ -125,18 +81,14 @@ async function ensureInitialized() {
125
81
  if (context.initialized && context.kernel && context.queen) {
126
82
  return true;
127
83
  }
128
- // Auto-initialize with defaults and timeout
129
84
  console.log(chalk.gray('Auto-initializing v3 system...'));
130
- const timeout = 30000; // 30 seconds
85
+ const timeout = 30000;
131
86
  const timeoutPromise = new Promise((_, reject) => {
132
87
  setTimeout(() => reject(new Error('Initialization timeout after 30 seconds')), timeout);
133
88
  });
134
89
  try {
135
- await Promise.race([
136
- autoInitialize(),
137
- timeoutPromise
138
- ]);
139
- console.log(chalk.green('✓ System ready\n'));
90
+ await Promise.race([autoInitialize(), timeoutPromise]);
91
+ console.log(chalk.green('System ready\n'));
140
92
  return true;
141
93
  }
142
94
  catch (err) {
@@ -157,7 +109,6 @@ async function ensureInitialized() {
157
109
  */
158
110
  async function cleanupAndExit(code = 0) {
159
111
  try {
160
- // ADR-042: Save token metrics before shutdown
161
112
  await shutdownTokenTracking();
162
113
  if (context.workflowOrchestrator) {
163
114
  await context.workflowOrchestrator.dispose();
@@ -171,8 +122,6 @@ async function cleanupAndExit(code = 0) {
171
122
  if (context.kernel) {
172
123
  await context.kernel.dispose();
173
124
  }
174
- // Close the UnifiedMemoryManager singleton to release database connection
175
- // This is critical for CLI commands to exit properly
176
125
  UnifiedMemoryManager.resetInstance();
177
126
  }
178
127
  catch {
@@ -184,735 +133,16 @@ async function cleanupAndExit(code = 0) {
184
133
  // CLI Program
185
134
  // ============================================================================
186
135
  const program = new Command();
187
- // Version injected at build time from root package.json
188
136
  const VERSION = typeof __CLI_VERSION__ !== 'undefined' ? __CLI_VERSION__ : '0.0.0-dev';
189
137
  program
190
138
  .name('aqe')
191
139
  .description('Agentic QE - Domain-Driven Quality Engineering')
192
140
  .version(VERSION);
193
141
  // ============================================================================
194
- // Init Command
195
- // ============================================================================
196
- program
197
- .command('init')
198
- .description('Initialize the AQE v3 system')
199
- .option('-d, --domains <domains>', 'Comma-separated list of domains to enable', 'all')
200
- .option('-m, --max-agents <number>', 'Maximum concurrent agents', '15')
201
- .option('--memory <backend>', 'Memory backend (sqlite|agentdb|hybrid)', 'hybrid')
202
- .option('--lazy', 'Enable lazy loading of domains')
203
- .option('--wizard', 'Run interactive setup wizard')
204
- .option('--auto', 'Auto-configure based on project analysis')
205
- .option('--minimal', 'Minimal configuration (skip optional features)')
206
- .option('--skip-patterns', 'Skip loading pre-trained patterns')
207
- .option('--with-n8n', 'Install n8n workflow testing agents and skills')
208
- .option('--auto-migrate', 'Automatically migrate from v2 if detected')
209
- .option('--with-claude-flow', 'Force Claude Flow integration setup')
210
- .option('--skip-claude-flow', 'Skip Claude Flow integration')
211
- .option('--modular', 'Use new modular init system (default for --auto)')
212
- .action(async (options) => {
213
- try {
214
- // --auto-migrate implies --auto (must use orchestrator for migration)
215
- if (options.autoMigrate && !options.auto && !options.wizard) {
216
- options.auto = true;
217
- }
218
- // Check if wizard mode requested
219
- if (options.wizard || options.auto) {
220
- console.log(chalk.blue('\n🚀 Agentic QE v3 Initialization\n'));
221
- // Use modular orchestrator for --auto or --modular
222
- if (options.auto || options.modular) {
223
- const orchestrator = createModularInitOrchestrator({
224
- projectRoot: process.cwd(),
225
- autoMode: options.auto,
226
- minimal: options.minimal,
227
- skipPatterns: options.skipPatterns,
228
- withN8n: options.withN8n,
229
- autoMigrate: options.autoMigrate,
230
- });
231
- console.log(chalk.white('🔍 Analyzing project...\n'));
232
- const result = await orchestrator.initialize();
233
- // Display step results
234
- for (const step of result.steps) {
235
- const statusIcon = step.status === 'success' ? '✓' : step.status === 'error' ? '✗' : '⚠';
236
- const statusColor = step.status === 'success' ? chalk.green : step.status === 'error' ? chalk.red : chalk.yellow;
237
- console.log(statusColor(` ${statusIcon} ${step.step} (${step.durationMs}ms)`));
238
- }
239
- console.log('');
240
- // Claude Flow integration (after base init)
241
- let cfResult;
242
- if (!options.skipClaudeFlow && (options.withClaudeFlow || result.success)) {
243
- try {
244
- cfResult = await setupClaudeFlowIntegration({
245
- projectRoot: process.cwd(),
246
- force: options.withClaudeFlow,
247
- });
248
- if (cfResult.available) {
249
- console.log(chalk.green('✓ Claude Flow integration enabled'));
250
- if (cfResult.features.trajectories) {
251
- console.log(chalk.gray(' • SONA trajectory tracking'));
252
- }
253
- if (cfResult.features.modelRouting) {
254
- console.log(chalk.gray(' • 3-tier model routing (haiku/sonnet/opus)'));
255
- }
256
- if (cfResult.features.pretrain) {
257
- console.log(chalk.gray(' • Codebase pretrain analysis'));
258
- }
259
- console.log('');
260
- }
261
- }
262
- catch {
263
- // Claude Flow not available - continue without it
264
- }
265
- }
266
- if (result.success) {
267
- console.log(chalk.green('✅ AQE v3 initialized successfully!\n'));
268
- // Show summary
269
- console.log(chalk.blue('📊 Summary:'));
270
- console.log(chalk.gray(` • Patterns loaded: ${result.summary.patternsLoaded}`));
271
- console.log(chalk.gray(` • Skills installed: ${result.summary.skillsInstalled}`));
272
- console.log(chalk.gray(` • Agents installed: ${result.summary.agentsInstalled}`));
273
- console.log(chalk.gray(` • Hooks configured: ${result.summary.hooksConfigured ? 'Yes' : 'No'}`));
274
- console.log(chalk.gray(` • Workers started: ${result.summary.workersStarted}`));
275
- console.log(chalk.gray(` • Claude Flow: ${cfResult?.available ? 'Enabled' : 'Standalone mode'}`));
276
- console.log(chalk.gray(` • Total time: ${result.totalDurationMs}ms\n`));
277
- console.log(chalk.white('Next steps:'));
278
- console.log(chalk.gray(' 1. Add MCP: claude mcp add aqe -- aqe-mcp'));
279
- console.log(chalk.gray(' 2. Run tests: aqe test <path>'));
280
- console.log(chalk.gray(' 3. Check status: aqe status\n'));
281
- }
282
- else {
283
- console.log(chalk.red('❌ Initialization failed. Check errors above.\n'));
284
- await cleanupAndExit(1);
285
- }
286
- await cleanupAndExit(0);
287
- }
288
- // Legacy wizard mode using InitOrchestrator
289
- const orchestratorOptions = {
290
- projectRoot: process.cwd(),
291
- autoMode: options.auto,
292
- minimal: options.minimal,
293
- skipPatterns: options.skipPatterns,
294
- withN8n: options.withN8n,
295
- autoMigrate: options.autoMigrate,
296
- };
297
- const orchestrator = new InitOrchestrator(orchestratorOptions);
298
- if (options.wizard) {
299
- // Show wizard steps
300
- console.log(chalk.white('📋 Setup Wizard Steps:\n'));
301
- const steps = orchestrator.getWizardSteps();
302
- for (let i = 0; i < steps.length; i++) {
303
- console.log(chalk.gray(` ${i + 1}. ${steps[i].title}`));
304
- console.log(chalk.gray(` ${steps[i].description}\n`));
305
- }
306
- }
307
- console.log(chalk.white('🔍 Analyzing project...\n'));
308
- const result = await orchestrator.initialize();
309
- // Display step results
310
- for (const step of result.steps) {
311
- const statusIcon = step.status === 'success' ? '✓' : step.status === 'error' ? '✗' : '⚠';
312
- const statusColor = step.status === 'success' ? chalk.green : step.status === 'error' ? chalk.red : chalk.yellow;
313
- console.log(statusColor(` ${statusIcon} ${step.step} (${step.durationMs}ms)`));
314
- }
315
- console.log('');
316
- if (result.success) {
317
- console.log(chalk.green('✅ AQE v3 initialized successfully!\n'));
318
- // Show summary
319
- console.log(chalk.blue('📊 Summary:'));
320
- console.log(chalk.gray(` • Patterns loaded: ${result.summary.patternsLoaded}`));
321
- console.log(chalk.gray(` • Hooks configured: ${result.summary.hooksConfigured ? 'Yes' : 'No'}`));
322
- console.log(chalk.gray(` • Workers started: ${result.summary.workersStarted}`));
323
- if (result.summary.n8nInstalled) {
324
- console.log(chalk.gray(` • N8n agents: ${result.summary.n8nInstalled.agents}`));
325
- console.log(chalk.gray(` • N8n skills: ${result.summary.n8nInstalled.skills}`));
326
- }
327
- console.log(chalk.gray(` • Total time: ${result.totalDurationMs}ms\n`));
328
- console.log(chalk.white('Next steps:'));
329
- console.log(chalk.gray(' 1. Add MCP: claude mcp add aqe -- aqe-mcp'));
330
- console.log(chalk.gray(' 2. Run tests: aqe test <path>'));
331
- console.log(chalk.gray(' 3. Check status: aqe status\n'));
332
- }
333
- else {
334
- console.log(chalk.red('❌ Initialization failed. Check errors above.\n'));
335
- await cleanupAndExit(1);
336
- }
337
- await cleanupAndExit(0);
338
- }
339
- // Standard init without wizard
340
- console.log(chalk.blue('\n🚀 Initializing Agentic QE v3...\n'));
341
- // Determine enabled domains
342
- const enabledDomains = options.domains === 'all'
343
- ? [...ALL_DOMAINS]
344
- : options.domains.split(',').filter((d) => ALL_DOMAINS.includes(d));
345
- console.log(chalk.gray(` Domains: ${enabledDomains.length}`));
346
- console.log(chalk.gray(` Max Agents: ${options.maxAgents}`));
347
- console.log(chalk.gray(` Memory: ${options.memory}`));
348
- console.log(chalk.gray(` Lazy Loading: ${options.lazy ? 'enabled' : 'disabled'}\n`));
349
- // Create kernel
350
- context.kernel = new QEKernelImpl({
351
- maxConcurrentAgents: parseInt(options.maxAgents, 10),
352
- memoryBackend: options.memory,
353
- hnswEnabled: true,
354
- lazyLoading: options.lazy || false,
355
- enabledDomains,
356
- });
357
- await context.kernel.initialize();
358
- console.log(chalk.green(' ✓ Kernel initialized'));
359
- // Create cross-domain router
360
- context.router = new CrossDomainEventRouter(context.kernel.eventBus);
361
- await context.router.initialize();
362
- console.log(chalk.green(' ✓ Cross-domain router initialized'));
363
- // Create protocol executor
364
- const getDomainAPI = (domain) => {
365
- return context.kernel.getDomainAPI(domain);
366
- };
367
- const protocolExecutor = new DefaultProtocolExecutor(context.kernel.eventBus, context.kernel.memory, getDomainAPI);
368
- console.log(chalk.green(' ✓ Protocol executor initialized'));
369
- // Create workflow orchestrator
370
- context.workflowOrchestrator = new WorkflowOrchestrator(context.kernel.eventBus, context.kernel.memory, context.kernel.coordinator);
371
- await context.workflowOrchestrator.initialize();
372
- // Register domain workflow actions (Issue #206)
373
- registerDomainWorkflowActions(context.kernel, context.workflowOrchestrator);
374
- console.log(chalk.green(' ✓ Workflow orchestrator initialized'));
375
- // Create Queen Coordinator
376
- // Note: workflowExecutor is omitted as WorkflowOrchestrator uses different interface
377
- context.queen = createQueenCoordinator(context.kernel, context.router, protocolExecutor, undefined // WorkflowExecutor - optional, can be added later
378
- );
379
- await context.queen.initialize();
380
- console.log(chalk.green(' ✓ Queen Coordinator initialized'));
381
- context.initialized = true;
382
- console.log(chalk.green('\n✅ AQE v3 initialized successfully!\n'));
383
- // Show enabled domains
384
- console.log(chalk.blue('📦 Enabled Domains:'));
385
- for (const domain of enabledDomains) {
386
- console.log(chalk.gray(` • ${domain}`));
387
- }
388
- console.log('');
389
- await cleanupAndExit(0);
390
- }
391
- catch (error) {
392
- console.error(chalk.red('\n❌ Failed to initialize:'), error);
393
- await cleanupAndExit(1);
394
- }
395
- });
396
- // ============================================================================
397
- // Status Command
398
- // ============================================================================
399
- program
400
- .command('status')
401
- .description('Show system status')
402
- .option('-v, --verbose', 'Show detailed status')
403
- .action(async (options) => {
404
- if (!await ensureInitialized())
405
- return;
406
- try {
407
- const health = context.queen.getHealth();
408
- const metrics = context.queen.getMetrics();
409
- console.log(chalk.blue('\n📊 AQE v3 Status\n'));
410
- // Overall health
411
- console.log(` Status: ${getStatusColor(health.status)}`);
412
- console.log(` Uptime: ${chalk.cyan(formatUptime(metrics.uptime))}`);
413
- console.log(` Work Stealing: ${health.workStealingActive ? chalk.green('active') : chalk.gray('inactive')}`);
414
- // Agents
415
- console.log(chalk.blue('\n👥 Agents:'));
416
- console.log(` Total: ${chalk.cyan(health.totalAgents)}`);
417
- console.log(` Active: ${chalk.yellow(health.activeAgents)}`);
418
- console.log(` Utilization: ${chalk.cyan((metrics.agentUtilization * 100).toFixed(1))}%`);
419
- // Tasks
420
- console.log(chalk.blue('\n📋 Tasks:'));
421
- console.log(` Received: ${chalk.cyan(metrics.tasksReceived)}`);
422
- console.log(` Completed: ${chalk.green(metrics.tasksCompleted)}`);
423
- console.log(` Failed: ${chalk.red(metrics.tasksFailed)}`);
424
- console.log(` Pending: ${chalk.yellow(health.pendingTasks)}`);
425
- console.log(` Running: ${chalk.yellow(health.runningTasks)}`);
426
- if (metrics.tasksStolen > 0) {
427
- console.log(` Stolen (work stealing): ${chalk.cyan(metrics.tasksStolen)}`);
428
- }
429
- // Protocols & Workflows
430
- if (metrics.protocolsExecuted > 0 || metrics.workflowsExecuted > 0) {
431
- console.log(chalk.blue('\n🔄 Coordination:'));
432
- console.log(` Protocols Executed: ${chalk.cyan(metrics.protocolsExecuted)}`);
433
- console.log(` Workflows Executed: ${chalk.cyan(metrics.workflowsExecuted)}`);
434
- }
435
- // Verbose domain status
436
- if (options.verbose) {
437
- console.log(chalk.blue('\n📦 Domain Status:'));
438
- for (const [domain, domainHealth] of health.domainHealth) {
439
- console.log(` ${domain}: ${getStatusColor(domainHealth.status)}`);
440
- console.log(chalk.gray(` Agents: ${domainHealth.agents.active}/${domainHealth.agents.total} active`));
441
- if (domainHealth.errors.length > 0) {
442
- console.log(chalk.red(` Errors: ${domainHealth.errors.length}`));
443
- }
444
- }
445
- // Domain utilization
446
- console.log(chalk.blue('\n📈 Domain Load:'));
447
- for (const [domain, load] of metrics.domainUtilization) {
448
- const bar = '█'.repeat(Math.min(load, 20)) + '░'.repeat(Math.max(0, 20 - load));
449
- console.log(` ${domain.padEnd(25)} ${bar} ${load}`);
450
- }
451
- }
452
- // Health issues
453
- if (health.issues.length > 0) {
454
- console.log(chalk.red('\n⚠️ Issues:'));
455
- for (const issue of health.issues) {
456
- const color = issue.severity === 'high' ? chalk.red :
457
- issue.severity === 'medium' ? chalk.yellow : chalk.gray;
458
- console.log(` ${color(`[${issue.severity}]`)} ${issue.message}`);
459
- }
460
- }
461
- console.log('');
462
- await cleanupAndExit(0);
463
- }
464
- catch (error) {
465
- console.error(chalk.red('\n❌ Failed to get status:'), error);
466
- await cleanupAndExit(1);
467
- }
468
- });
469
- // ============================================================================
470
- // Health Command
471
- // ============================================================================
472
- program
473
- .command('health')
474
- .description('Check system health')
475
- .option('-d, --domain <domain>', 'Check specific domain health')
476
- .action(async (options) => {
477
- if (!await ensureInitialized())
478
- return;
479
- try {
480
- if (options.domain) {
481
- const domain = options.domain;
482
- const health = context.queen.getDomainHealth(domain);
483
- if (!health) {
484
- console.log(chalk.red(`\n❌ Domain not found: ${domain}\n`));
485
- return;
486
- }
487
- console.log(chalk.blue(`\n🏥 Health: ${domain}\n`));
488
- console.log(` Status: ${getStatusColor(health.status)}`);
489
- console.log(` Agents: ${health.agents.active}/${health.agents.total} active`);
490
- console.log(` Idle: ${health.agents.idle}`);
491
- console.log(` Failed: ${health.agents.failed}`);
492
- if (health.lastActivity) {
493
- console.log(` Last Activity: ${health.lastActivity.toISOString()}`);
494
- }
495
- if (health.errors.length > 0) {
496
- console.log(chalk.red(`\n Errors:`));
497
- health.errors.forEach(err => console.log(chalk.red(` • ${err}`)));
498
- }
499
- }
500
- else {
501
- const health = context.queen.getHealth();
502
- console.log(chalk.blue('\n🏥 System Health\n'));
503
- console.log(` Overall: ${getStatusColor(health.status)}`);
504
- console.log(` Last Check: ${health.lastHealthCheck.toISOString()}`);
505
- // Issue #205 fix: Summary by status including 'idle'
506
- let healthy = 0, idle = 0, degraded = 0, unhealthy = 0;
507
- for (const [, domainHealth] of health.domainHealth) {
508
- if (domainHealth.status === 'healthy')
509
- healthy++;
510
- else if (domainHealth.status === 'idle')
511
- idle++;
512
- else if (domainHealth.status === 'degraded')
513
- degraded++;
514
- else
515
- unhealthy++;
516
- }
517
- console.log(chalk.blue('\n📦 Domains:'));
518
- console.log(` ${chalk.green('●')} Healthy: ${healthy}`);
519
- console.log(` ${chalk.cyan('●')} Idle (ready): ${idle}`);
520
- console.log(` ${chalk.yellow('●')} Degraded: ${degraded}`);
521
- console.log(` ${chalk.red('●')} Unhealthy: ${unhealthy}`);
522
- // Issue #205 fix: Add helpful tip for fresh installs
523
- if (idle > 0 && healthy === 0 && degraded === 0 && unhealthy === 0) {
524
- console.log(chalk.gray('\n 💡 Tip: Domains are idle (ready). Run a task to spawn agents.'));
525
- }
526
- }
527
- console.log('');
528
- await cleanupAndExit(0);
529
- }
530
- catch (error) {
531
- console.error(chalk.red('\n❌ Health check failed:'), error);
532
- await cleanupAndExit(1);
533
- }
534
- });
535
- // ============================================================================
536
- // Task Command Group
537
- // ============================================================================
538
- const taskCmd = program
539
- .command('task')
540
- .description('Manage QE tasks');
541
- taskCmd
542
- .command('submit <type>')
543
- .description('Submit a task to the Queen Coordinator')
544
- .option('-p, --priority <priority>', 'Task priority (p0|p1|p2|p3)', 'p1')
545
- .option('-d, --domain <domain>', 'Target domain')
546
- .option('-t, --timeout <ms>', 'Task timeout in ms', '300000')
547
- .option('--payload <json>', 'Task payload as JSON', '{}')
548
- .option('--wait', 'Wait for task completion with progress')
549
- .option('--no-progress', 'Disable progress indicator')
550
- .action(async (type, options) => {
551
- if (!await ensureInitialized())
552
- return;
553
- try {
554
- const taskType = type;
555
- const payload = parseJsonOption(options.payload, 'payload');
556
- const targetDomains = options.domain ? [options.domain] : [];
557
- console.log(chalk.blue(`\n Submitting task: ${taskType}\n`));
558
- // Use spinner for submit operation
559
- const spinner = options.progress !== false
560
- ? createTimedSpinner(`Submitting ${taskType} task`)
561
- : null;
562
- const result = await context.queen.submitTask({
563
- type: taskType,
564
- priority: options.priority,
565
- targetDomains,
566
- payload,
567
- timeout: parseInt(options.timeout, 10),
568
- });
569
- if (spinner) {
570
- if (result.success) {
571
- spinner.succeed(`Task submitted successfully`);
572
- }
573
- else {
574
- spinner.fail(`Failed to submit task`);
575
- }
576
- }
577
- if (result.success) {
578
- console.log(chalk.cyan(` ID: ${result.value}`));
579
- console.log(chalk.gray(` Type: ${taskType}`));
580
- console.log(chalk.gray(` Priority: ${options.priority}`));
581
- // If --wait flag is provided, poll for task completion with progress
582
- if (options.wait) {
583
- console.log('');
584
- const taskId = result.value;
585
- const waitSpinner = createTimedSpinner('Waiting for task completion');
586
- const timeout = parseInt(options.timeout, 10);
587
- const startTime = Date.now();
588
- let completed = false;
589
- while (!completed && (Date.now() - startTime) < timeout) {
590
- const taskStatus = context.queen.getTaskStatus(taskId);
591
- if (taskStatus) {
592
- if (taskStatus.status === 'completed') {
593
- waitSpinner.succeed('Task completed successfully');
594
- completed = true;
595
- }
596
- else if (taskStatus.status === 'failed') {
597
- waitSpinner.fail(`Task failed: ${taskStatus.error || 'Unknown error'}`);
598
- completed = true;
599
- }
600
- else {
601
- // Update spinner with progress info
602
- waitSpinner.spinner.text = `Task ${taskStatus.status}... (${Math.round((Date.now() - startTime) / 1000)}s)`;
603
- }
604
- }
605
- if (!completed) {
606
- await new Promise(resolve => setTimeout(resolve, 500));
607
- }
608
- }
609
- if (!completed) {
610
- waitSpinner.fail('Task timed out');
611
- }
612
- }
613
- }
614
- else {
615
- console.log(chalk.red(` Error: ${result.error.message}`));
616
- }
617
- console.log('');
618
- }
619
- catch (error) {
620
- console.error(chalk.red('\n Failed to submit task:'), error);
621
- await cleanupAndExit(1);
622
- }
623
- });
624
- taskCmd
625
- .command('list')
626
- .description('List all tasks')
627
- .option('-s, --status <status>', 'Filter by status')
628
- .option('-p, --priority <priority>', 'Filter by priority')
629
- .option('-d, --domain <domain>', 'Filter by domain')
630
- .action(async (options) => {
631
- if (!await ensureInitialized())
632
- return;
633
- try {
634
- const tasks = context.queen.listTasks({
635
- status: options.status,
636
- priority: options.priority,
637
- domain: options.domain,
638
- });
639
- console.log(chalk.blue(`\n📋 Tasks (${tasks.length})\n`));
640
- if (tasks.length === 0) {
641
- console.log(chalk.gray(' No tasks found'));
642
- }
643
- else {
644
- for (const task of tasks) {
645
- console.log(` ${chalk.cyan(task.taskId)}`);
646
- console.log(` Type: ${task.task.type}`);
647
- console.log(` Status: ${getStatusColor(task.status)}`);
648
- console.log(` Priority: ${task.task.priority}`);
649
- if (task.assignedDomain) {
650
- console.log(` Domain: ${task.assignedDomain}`);
651
- }
652
- if (task.startedAt) {
653
- console.log(chalk.gray(` Started: ${task.startedAt.toISOString()}`));
654
- }
655
- console.log('');
656
- }
657
- }
658
- }
659
- catch (error) {
660
- console.error(chalk.red('\n❌ Failed to list tasks:'), error);
661
- await cleanupAndExit(1);
662
- }
663
- });
664
- taskCmd
665
- .command('cancel <taskId>')
666
- .description('Cancel a task')
667
- .action(async (taskId) => {
668
- if (!await ensureInitialized())
669
- return;
670
- try {
671
- const result = await context.queen.cancelTask(taskId);
672
- if (result.success) {
673
- console.log(chalk.green(`\n✅ Task cancelled: ${taskId}\n`));
674
- }
675
- else {
676
- console.log(chalk.red(`\n❌ Failed to cancel task: ${result.error.message}\n`));
677
- }
678
- }
679
- catch (error) {
680
- console.error(chalk.red('\n❌ Failed to cancel task:'), error);
681
- await cleanupAndExit(1);
682
- }
683
- });
684
- taskCmd
685
- .command('status <taskId>')
686
- .description('Get task status')
687
- .action(async (taskId) => {
688
- if (!await ensureInitialized())
689
- return;
690
- try {
691
- const task = context.queen.getTaskStatus(taskId);
692
- if (!task) {
693
- console.log(chalk.red(`\n❌ Task not found: ${taskId}\n`));
694
- return;
695
- }
696
- console.log(chalk.blue(`\n📋 Task: ${taskId}\n`));
697
- console.log(` Type: ${task.task.type}`);
698
- console.log(` Status: ${getStatusColor(task.status)}`);
699
- console.log(` Priority: ${task.task.priority}`);
700
- if (task.assignedDomain) {
701
- console.log(` Domain: ${task.assignedDomain}`);
702
- }
703
- if (task.assignedAgents.length > 0) {
704
- console.log(` Agents: ${task.assignedAgents.join(', ')}`);
705
- }
706
- console.log(` Created: ${task.task.createdAt.toISOString()}`);
707
- if (task.startedAt) {
708
- console.log(` Started: ${task.startedAt.toISOString()}`);
709
- }
710
- if (task.completedAt) {
711
- console.log(` Completed: ${task.completedAt.toISOString()}`);
712
- const duration = task.completedAt.getTime() - task.startedAt.getTime();
713
- console.log(` Duration: ${formatDuration(duration)}`);
714
- }
715
- if (task.error) {
716
- console.log(chalk.red(` Error: ${task.error}`));
717
- }
718
- if (task.retryCount > 0) {
719
- console.log(chalk.yellow(` Retries: ${task.retryCount}`));
720
- }
721
- console.log('');
722
- }
723
- catch (error) {
724
- console.error(chalk.red('\n❌ Failed to get task status:'), error);
725
- await cleanupAndExit(1);
726
- }
727
- });
728
- // ============================================================================
729
- // Agent Command Group
730
- // ============================================================================
731
- const agentCmd = program
732
- .command('agent')
733
- .description('Manage QE agents');
734
- agentCmd
735
- .command('list')
736
- .description('List all agents')
737
- .option('-d, --domain <domain>', 'Filter by domain')
738
- .option('-s, --status <status>', 'Filter by status')
739
- .action(async (options) => {
740
- if (!await ensureInitialized())
741
- return;
742
- try {
743
- let agents = options.domain
744
- ? context.queen.getAgentsByDomain(options.domain)
745
- : context.queen.listAllAgents();
746
- if (options.status) {
747
- agents = agents.filter(a => a.status === options.status);
748
- }
749
- console.log(chalk.blue(`\n👥 Agents (${agents.length})\n`));
750
- if (agents.length === 0) {
751
- console.log(chalk.gray(' No agents found'));
752
- }
753
- else {
754
- // Group by domain
755
- const byDomain = new Map();
756
- for (const agent of agents) {
757
- if (!byDomain.has(agent.domain)) {
758
- byDomain.set(agent.domain, []);
759
- }
760
- byDomain.get(agent.domain).push(agent);
761
- }
762
- for (const [domain, domainAgents] of byDomain) {
763
- console.log(chalk.cyan(` ${domain}:`));
764
- for (const agent of domainAgents) {
765
- console.log(` ${agent.id}`);
766
- console.log(` Type: ${agent.type}`);
767
- console.log(` Status: ${getStatusColor(agent.status)}`);
768
- if (agent.startedAt) {
769
- console.log(chalk.gray(` Started: ${agent.startedAt.toISOString()}`));
770
- }
771
- }
772
- console.log('');
773
- }
774
- }
775
- }
776
- catch (error) {
777
- console.error(chalk.red('\n❌ Failed to list agents:'), error);
778
- await cleanupAndExit(1);
779
- }
780
- });
781
- agentCmd
782
- .command('spawn <domain>')
783
- .description('Spawn an agent in a domain')
784
- .option('-t, --type <type>', 'Agent type', 'worker')
785
- .option('-c, --capabilities <caps>', 'Comma-separated capabilities', 'general')
786
- .option('--no-progress', 'Disable progress indicator')
787
- .action(async (domain, options) => {
788
- if (!await ensureInitialized())
789
- return;
790
- try {
791
- const capabilities = options.capabilities.split(',');
792
- console.log(chalk.blue(`\n Spawning agent in ${domain}...\n`));
793
- // Use spinner for spawn operation
794
- const spinner = options.progress !== false
795
- ? createTimedSpinner(`Spawning ${options.type} agent`)
796
- : null;
797
- const result = await context.queen.requestAgentSpawn(domain, options.type, capabilities);
798
- if (spinner) {
799
- if (result.success) {
800
- spinner.succeed(`Agent spawned successfully`);
801
- }
802
- else {
803
- spinner.fail(`Failed to spawn agent`);
804
- }
805
- }
806
- if (result.success) {
807
- console.log(chalk.cyan(` ID: ${result.value}`));
808
- console.log(chalk.gray(` Domain: ${domain}`));
809
- console.log(chalk.gray(` Type: ${options.type}`));
810
- console.log(chalk.gray(` Capabilities: ${capabilities.join(', ')}`));
811
- }
812
- else {
813
- console.log(chalk.red(` Error: ${result.error.message}`));
814
- }
815
- console.log('');
816
- }
817
- catch (error) {
818
- console.error(chalk.red('\n Failed to spawn agent:'), error);
819
- await cleanupAndExit(1);
820
- }
821
- });
822
- // ============================================================================
823
- // Domain Command Group
824
- // ============================================================================
825
- const domainCmd = program
826
- .command('domain')
827
- .description('Domain operations');
828
- domainCmd
829
- .command('list')
830
- .description('List all domains')
831
- .action(async () => {
832
- if (!await ensureInitialized())
833
- return;
834
- try {
835
- console.log(chalk.blue('\n📦 Domains\n'));
836
- for (const domain of ALL_DOMAINS) {
837
- const health = context.queen.getDomainHealth(domain);
838
- const load = context.queen.getDomainLoad(domain);
839
- console.log(` ${chalk.cyan(domain)}`);
840
- console.log(` Status: ${getStatusColor(health?.status || 'unknown')}`);
841
- console.log(` Load: ${load} tasks`);
842
- if (health) {
843
- console.log(` Agents: ${health.agents.active}/${health.agents.total}`);
844
- }
845
- console.log('');
846
- }
847
- }
848
- catch (error) {
849
- console.error(chalk.red('\n❌ Failed to list domains:'), error);
850
- await cleanupAndExit(1);
851
- }
852
- });
853
- domainCmd
854
- .command('health <domain>')
855
- .description('Get domain health')
856
- .action(async (domain) => {
857
- if (!await ensureInitialized())
858
- return;
859
- try {
860
- const health = context.queen.getDomainHealth(domain);
861
- if (!health) {
862
- console.log(chalk.red(`\n❌ Domain not found: ${domain}\n`));
863
- return;
864
- }
865
- console.log(chalk.blue(`\n🏥 ${domain} Health\n`));
866
- console.log(` Status: ${getStatusColor(health.status)}`);
867
- console.log(` Agents Total: ${health.agents.total}`);
868
- console.log(` Agents Active: ${chalk.green(health.agents.active)}`);
869
- console.log(` Agents Idle: ${chalk.yellow(health.agents.idle)}`);
870
- console.log(` Agents Failed: ${chalk.red(health.agents.failed)}`);
871
- if (health.lastActivity) {
872
- console.log(` Last Activity: ${health.lastActivity.toISOString()}`);
873
- }
874
- if (health.errors.length > 0) {
875
- console.log(chalk.red('\n Errors:'));
876
- health.errors.forEach(err => console.log(chalk.red(` • ${err}`)));
877
- }
878
- console.log('');
879
- }
880
- catch (error) {
881
- console.error(chalk.red('\n❌ Failed to get domain health:'), error);
882
- await cleanupAndExit(1);
883
- }
884
- });
885
- // ============================================================================
886
- // Protocol Command Group
142
+ // Register Handlers via CommandRegistry
887
143
  // ============================================================================
888
- const protocolCmd = program
889
- .command('protocol')
890
- .description('Execute coordination protocols');
891
- protocolCmd
892
- .command('run <protocolId>')
893
- .description('Execute a protocol')
894
- .option('--params <json>', 'Protocol parameters as JSON', '{}')
895
- .action(async (protocolId, options) => {
896
- if (!await ensureInitialized())
897
- return;
898
- try {
899
- const params = parseJsonOption(options.params, 'params');
900
- console.log(chalk.blue(`\n🔄 Executing protocol: ${protocolId}\n`));
901
- const result = await context.queen.executeProtocol(protocolId, params);
902
- if (result.success) {
903
- console.log(chalk.green(`✅ Protocol execution started`));
904
- console.log(chalk.cyan(` Execution ID: ${result.value}`));
905
- }
906
- else {
907
- console.log(chalk.red(`❌ Failed to execute protocol: ${result.error.message}`));
908
- }
909
- console.log('');
910
- }
911
- catch (error) {
912
- console.error(chalk.red('\n❌ Failed to execute protocol:'), error);
913
- await cleanupAndExit(1);
914
- }
915
- });
144
+ const registry = createCommandRegistry(context, cleanupAndExit, ensureInitialized);
145
+ registry.registerAll(program);
916
146
  // ============================================================================
917
147
  // Workflow Command Group (ADR-041)
918
148
  // ============================================================================
@@ -933,7 +163,6 @@ workflowCmd
933
163
  const filePath = pathModule.resolve(file);
934
164
  try {
935
165
  console.log(chalk.blue(`\n Running workflow from: ${file}\n`));
936
- // Parse the pipeline file
937
166
  const parseResult = parsePipelineFile(filePath);
938
167
  if (!parseResult.success || !parseResult.workflow) {
939
168
  console.log(chalk.red('Failed to parse pipeline:'));
@@ -942,11 +171,8 @@ workflowCmd
942
171
  }
943
172
  await cleanupAndExit(1);
944
173
  }
945
- // Additional params (SEC-001: safe parsing prevents prototype pollution)
946
174
  const additionalParams = parseJsonOption(options.params, 'params');
947
- // Build input from pipeline params and additional params
948
175
  const input = { ...additionalParams };
949
- // Add stage params to input context
950
176
  if (parseResult.pipeline) {
951
177
  for (const stage of parseResult.pipeline.stages) {
952
178
  if (stage.params) {
@@ -956,7 +182,6 @@ workflowCmd
956
182
  }
957
183
  }
958
184
  }
959
- // Register the workflow if not already registered
960
185
  const existingWorkflow = context.workflowOrchestrator.getWorkflow(parseResult.workflow.id);
961
186
  if (!existingWorkflow) {
962
187
  const registerResult = context.workflowOrchestrator.registerWorkflow(parseResult.workflow);
@@ -965,19 +190,17 @@ workflowCmd
965
190
  await cleanupAndExit(1);
966
191
  }
967
192
  }
968
- // Execute the workflow
969
193
  const execResult = await context.workflowOrchestrator.executeWorkflow(parseResult.workflow.id, input);
970
194
  if (!execResult.success) {
971
195
  console.log(chalk.red(`Failed to start workflow: ${execResult.error.message}`));
972
196
  await cleanupAndExit(1);
973
- return; // TypeScript flow analysis
197
+ return;
974
198
  }
975
199
  const executionId = execResult.value;
976
200
  console.log(chalk.cyan(` Execution ID: ${executionId}`));
977
201
  console.log(chalk.gray(` Workflow: ${parseResult.workflow.name}`));
978
202
  console.log(chalk.gray(` Stages: ${parseResult.workflow.steps.length}`));
979
203
  console.log('');
980
- // Watch progress if requested
981
204
  if (options.watch) {
982
205
  console.log(chalk.blue('Workflow Progress:\n'));
983
206
  let lastStatus;
@@ -986,12 +209,10 @@ workflowCmd
986
209
  const status = context.workflowOrchestrator.getWorkflowStatus(executionId);
987
210
  if (!status)
988
211
  break;
989
- // Update display if status changed
990
212
  if (!lastStatus ||
991
213
  lastStatus.progress !== status.progress ||
992
214
  lastStatus.status !== status.status ||
993
215
  JSON.stringify(lastStatus.currentSteps) !== JSON.stringify(status.currentSteps)) {
994
- // Clear line and show progress
995
216
  process.stdout.write('\r\x1b[K');
996
217
  const progressBar = String.fromCharCode(0x2588).repeat(Math.floor(status.progress / 5)) +
997
218
  String.fromCharCode(0x2591).repeat(20 - Math.floor(status.progress / 5));
@@ -1004,14 +225,11 @@ workflowCmd
1004
225
  }
1005
226
  lastStatus = status;
1006
227
  }
1007
- // Check if completed
1008
228
  if (status.status === 'completed' || status.status === 'failed' || status.status === 'cancelled') {
1009
229
  break;
1010
230
  }
1011
- // Wait before next check
1012
231
  await new Promise(resolve => setTimeout(resolve, 500));
1013
232
  }
1014
- // Show final status
1015
233
  const finalStatus = context.workflowOrchestrator.getWorkflowStatus(executionId);
1016
234
  if (finalStatus) {
1017
235
  console.log('');
@@ -1054,12 +272,10 @@ workflowCmd
1054
272
  .action(async (file, options) => {
1055
273
  if (!await ensureInitialized())
1056
274
  return;
1057
- const fs = await import('fs');
1058
275
  const pathModule = await import('path');
1059
276
  const filePath = pathModule.resolve(file);
1060
277
  try {
1061
278
  console.log(chalk.blue(`\nScheduling workflow from: ${file}\n`));
1062
- // Parse the pipeline file
1063
279
  const parseResult = parsePipelineFile(filePath);
1064
280
  if (!parseResult.success || !parseResult.pipeline || !parseResult.workflow) {
1065
281
  console.log(chalk.red('Failed to parse pipeline:'));
@@ -1068,14 +284,12 @@ workflowCmd
1068
284
  }
1069
285
  await cleanupAndExit(1);
1070
286
  }
1071
- // Get schedule from option or file
1072
287
  const schedule = options.cron || parseResult.pipeline.schedule;
1073
288
  if (!schedule) {
1074
289
  console.log(chalk.red('No schedule specified'));
1075
290
  console.log(chalk.gray(' Add "schedule" field to YAML or use --cron option'));
1076
291
  await cleanupAndExit(1);
1077
292
  }
1078
- // Register the workflow
1079
293
  const existingWorkflow = context.workflowOrchestrator.getWorkflow(parseResult.workflow.id);
1080
294
  if (!existingWorkflow) {
1081
295
  const registerResult = context.workflowOrchestrator.registerWorkflow(parseResult.workflow);
@@ -1084,7 +298,6 @@ workflowCmd
1084
298
  await cleanupAndExit(1);
1085
299
  }
1086
300
  }
1087
- // Create scheduled workflow entry using persistent scheduler (ADR-041)
1088
301
  const persistedSchedule = createScheduleEntry({
1089
302
  workflowId: parseResult.workflow.id,
1090
303
  pipelinePath: filePath,
@@ -1092,9 +305,7 @@ workflowCmd
1092
305
  scheduleDescription: describeCronSchedule(schedule),
1093
306
  enabled: options.enable !== false,
1094
307
  });
1095
- // Persist to disk using PersistentScheduler
1096
308
  await context.persistentScheduler.saveSchedule(persistedSchedule);
1097
- // Also keep in memory for backward compatibility
1098
309
  const scheduledWorkflow = {
1099
310
  id: persistedSchedule.id,
1100
311
  workflowId: persistedSchedule.workflowId,
@@ -1135,17 +346,15 @@ workflowCmd
1135
346
  return;
1136
347
  try {
1137
348
  console.log(chalk.blue('\nWorkflows\n'));
1138
- // Show scheduled workflows (from PersistentScheduler)
1139
349
  if (options.scheduled || options.all) {
1140
350
  console.log(chalk.cyan('Scheduled Workflows:'));
1141
- // Load schedules from persistent storage (ADR-041)
1142
351
  const scheduled = await context.persistentScheduler.getSchedules();
1143
352
  if (scheduled.length === 0) {
1144
353
  console.log(chalk.gray(' No scheduled workflows\n'));
1145
354
  }
1146
355
  else {
1147
356
  for (const sched of scheduled) {
1148
- const statusIcon = sched.enabled ? chalk.green('') : chalk.gray('');
357
+ const statusIcon = sched.enabled ? chalk.green('*') : chalk.gray('o');
1149
358
  console.log(` ${statusIcon} ${chalk.white(sched.workflowId)}`);
1150
359
  console.log(chalk.gray(` ID: ${sched.id}`));
1151
360
  console.log(chalk.gray(` Schedule: ${sched.schedule} (${sched.scheduleDescription})`));
@@ -1159,7 +368,6 @@ workflowCmd
1159
368
  }
1160
369
  }
1161
370
  }
1162
- // Show active executions
1163
371
  if (options.active || options.all) {
1164
372
  console.log(chalk.cyan('Active Executions:'));
1165
373
  const activeExecutions = context.workflowOrchestrator.getActiveExecutions();
@@ -1180,7 +388,6 @@ workflowCmd
1180
388
  }
1181
389
  }
1182
390
  }
1183
- // Show registered workflows (default behavior)
1184
391
  if (!options.scheduled && !options.active || options.all) {
1185
392
  console.log(chalk.cyan('Registered Workflows:'));
1186
393
  const workflows = context.workflowOrchestrator.listWorkflows();
@@ -1222,12 +429,10 @@ workflowCmd
1222
429
  const filePath = pathModule.resolve(file);
1223
430
  try {
1224
431
  console.log(chalk.blue(`\nValidating pipeline: ${file}\n`));
1225
- // Check file exists
1226
432
  if (!fs.existsSync(filePath)) {
1227
433
  console.log(chalk.red(`File not found: ${filePath}`));
1228
434
  await cleanupAndExit(1);
1229
435
  }
1230
- // Parse the pipeline file
1231
436
  const parseResult = parsePipelineFile(filePath);
1232
437
  if (!parseResult.success) {
1233
438
  console.log(chalk.red('Parse errors:'));
@@ -1236,9 +441,7 @@ workflowCmd
1236
441
  }
1237
442
  await cleanupAndExit(1);
1238
443
  }
1239
- // Validate the pipeline structure
1240
444
  const validationResult = validatePipeline(parseResult.pipeline);
1241
- // Show results
1242
445
  if (validationResult.valid) {
1243
446
  console.log(chalk.green('Pipeline is valid\n'));
1244
447
  }
@@ -1249,7 +452,6 @@ workflowCmd
1249
452
  }
1250
453
  console.log('');
1251
454
  }
1252
- // Show warnings
1253
455
  if (validationResult.warnings.length > 0) {
1254
456
  console.log(chalk.yellow('Warnings:'));
1255
457
  for (const warning of validationResult.warnings) {
@@ -1257,7 +459,6 @@ workflowCmd
1257
459
  }
1258
460
  console.log('');
1259
461
  }
1260
- // Show pipeline details if verbose
1261
462
  if (options.verbose && parseResult.pipeline) {
1262
463
  const pipeline = parseResult.pipeline;
1263
464
  console.log(chalk.cyan('Pipeline Details:\n'));
@@ -1297,7 +498,6 @@ workflowCmd
1297
498
  }
1298
499
  }
1299
500
  }
1300
- // Show converted workflow definition if verbose
1301
501
  if (options.verbose && parseResult.workflow) {
1302
502
  console.log(chalk.cyan('\n Converted Workflow ID: ') + chalk.white(parseResult.workflow.id));
1303
503
  console.log(chalk.gray(` Steps: ${parseResult.workflow.steps.length}`));
@@ -1325,7 +525,7 @@ workflowCmd
1325
525
  if (!status) {
1326
526
  console.log(chalk.red(`\nExecution not found: ${executionId}\n`));
1327
527
  await cleanupAndExit(1);
1328
- return; // TypeScript flow analysis
528
+ return;
1329
529
  }
1330
530
  console.log(chalk.blue(`\nWorkflow Execution Status\n`));
1331
531
  const statusColor = status.status === 'completed' ? chalk.green :
@@ -1352,7 +552,6 @@ workflowCmd
1352
552
  if (status.error) {
1353
553
  console.log(chalk.red(`\n Error: ${status.error}`));
1354
554
  }
1355
- // Show detailed step results if verbose
1356
555
  if (options.verbose && status.stepResults.size > 0) {
1357
556
  console.log(chalk.cyan('\n Step Results:'));
1358
557
  for (const [stepId, result] of status.stepResults) {
@@ -1401,1863 +600,36 @@ workflowCmd
1401
600
  }
1402
601
  });
1403
602
  // ============================================================================
1404
- // Shortcut Commands
603
+ // Shortcut Commands (test, coverage, quality, security, code)
1405
604
  // ============================================================================
1406
- // aqe test generate <source>
1407
- program
1408
- .command('test')
1409
- .description('Test generation shortcut')
1410
- .argument('<action>', 'Action (generate|execute)')
1411
- .argument('[target]', 'Target file or directory')
1412
- .option('-f, --framework <framework>', 'Test framework', 'vitest')
1413
- .option('-t, --type <type>', 'Test type (unit|integration|e2e)', 'unit')
1414
- .action(async (action, target, options) => {
1415
- if (!await ensureInitialized())
1416
- return;
1417
- try {
1418
- if (action === 'generate') {
1419
- console.log(chalk.blue(`\n🧪 Generating tests for ${target || 'current directory'}...\n`));
1420
- // Get test generation domain API directly (with lazy loading support)
1421
- const testGenAPI = await context.kernel.getDomainAPIAsync('test-generation');
1422
- if (!testGenAPI) {
1423
- console.log(chalk.red('❌ Test generation domain not available'));
1424
- return;
1425
- }
1426
- // Collect source files
1427
- const fs = await import('fs');
1428
- const path = await import('path');
1429
- const targetPath = path.resolve(target || '.');
1430
- let sourceFiles = [];
1431
- if (fs.existsSync(targetPath)) {
1432
- if (fs.statSync(targetPath).isDirectory()) {
1433
- const walkDir = (dir, depth = 0) => {
1434
- if (depth > 4)
1435
- return [];
1436
- const result = [];
1437
- const items = fs.readdirSync(dir);
1438
- for (const item of items) {
1439
- if (item === 'node_modules' || item === 'dist' || item === 'tests' || item.includes('.test.') || item.includes('.spec.'))
1440
- continue;
1441
- const fullPath = path.join(dir, item);
1442
- const stat = fs.statSync(fullPath);
1443
- if (stat.isDirectory()) {
1444
- result.push(...walkDir(fullPath, depth + 1));
1445
- }
1446
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
1447
- result.push(fullPath);
1448
- }
1449
- }
1450
- return result;
1451
- };
1452
- sourceFiles = walkDir(targetPath);
1453
- }
1454
- else {
1455
- sourceFiles = [targetPath];
1456
- }
1457
- }
1458
- if (sourceFiles.length === 0) {
1459
- console.log(chalk.yellow('No source files found'));
1460
- return;
1461
- }
1462
- console.log(chalk.gray(` Found ${sourceFiles.length} source files\n`));
1463
- // Generate tests
1464
- const result = await testGenAPI.generateTests({
1465
- sourceFiles,
1466
- testType: options.type,
1467
- framework: options.framework,
1468
- coverageTarget: 80,
1469
- });
1470
- if (result.success && result.value) {
1471
- const generated = result.value;
1472
- console.log(chalk.green(`✅ Generated ${generated.tests.length} tests\n`));
1473
- console.log(chalk.cyan(' Tests:'));
1474
- for (const test of generated.tests.slice(0, 10)) {
1475
- console.log(` ${chalk.white(test.name)}`);
1476
- console.log(chalk.gray(` Source: ${path.basename(test.sourceFile)}`));
1477
- console.log(chalk.gray(` Assertions: ${test.assertions}`));
1478
- }
1479
- if (generated.tests.length > 10) {
1480
- console.log(chalk.gray(` ... and ${generated.tests.length - 10} more`));
1481
- }
1482
- console.log(`\n Coverage Estimate: ${chalk.yellow(generated.coverageEstimate + '%')}`);
1483
- if (generated.patternsUsed.length > 0) {
1484
- console.log(` Patterns Used: ${chalk.cyan(generated.patternsUsed.join(', '))}`);
1485
- }
1486
- }
1487
- else {
1488
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
1489
- }
1490
- }
1491
- else if (action === 'execute') {
1492
- console.log(chalk.blue(`\n🧪 Executing tests in ${target || 'current directory'}...\n`));
1493
- // Get test execution domain API (with lazy loading support)
1494
- const testExecAPI = await context.kernel.getDomainAPIAsync('test-execution');
1495
- if (!testExecAPI) {
1496
- console.log(chalk.red('❌ Test execution domain not available'));
1497
- return;
1498
- }
1499
- // Collect test files
1500
- const fs = await import('fs');
1501
- const path = await import('path');
1502
- const targetPath = path.resolve(target || '.');
1503
- let testFiles = [];
1504
- if (fs.existsSync(targetPath)) {
1505
- if (fs.statSync(targetPath).isDirectory()) {
1506
- const walkDir = (dir, depth = 0) => {
1507
- if (depth > 4)
1508
- return [];
1509
- const result = [];
1510
- const items = fs.readdirSync(dir);
1511
- for (const item of items) {
1512
- if (item === 'node_modules' || item === 'dist')
1513
- continue;
1514
- const fullPath = path.join(dir, item);
1515
- const stat = fs.statSync(fullPath);
1516
- if (stat.isDirectory()) {
1517
- result.push(...walkDir(fullPath, depth + 1));
1518
- }
1519
- else if ((item.includes('.test.') || item.includes('.spec.')) && item.endsWith('.ts')) {
1520
- result.push(fullPath);
1521
- }
1522
- }
1523
- return result;
1524
- };
1525
- testFiles = walkDir(targetPath);
1526
- }
1527
- else {
1528
- testFiles = [targetPath];
1529
- }
1530
- }
1531
- if (testFiles.length === 0) {
1532
- console.log(chalk.yellow('No test files found'));
1533
- return;
1534
- }
1535
- console.log(chalk.gray(` Found ${testFiles.length} test files\n`));
1536
- const result = await testExecAPI.runTests({
1537
- testFiles,
1538
- parallel: true,
1539
- retryCount: 2,
1540
- });
1541
- if (result.success && result.value) {
1542
- const run = result.value;
1543
- const total = run.passed + run.failed + run.skipped;
1544
- console.log(chalk.green(`✅ Test run complete`));
1545
- console.log(`\n Results:`);
1546
- console.log(` Total: ${chalk.white(total)}`);
1547
- console.log(` Passed: ${chalk.green(run.passed)}`);
1548
- console.log(` Failed: ${chalk.red(run.failed)}`);
1549
- console.log(` Skipped: ${chalk.yellow(run.skipped)}`);
1550
- console.log(` Duration: ${chalk.cyan(run.duration + 'ms')}`);
1551
- }
1552
- else {
1553
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
1554
- }
1555
- }
1556
- else {
1557
- console.log(chalk.red(`\n❌ Unknown action: ${action}\n`));
1558
- await cleanupAndExit(1);
1559
- }
1560
- console.log('');
1561
- await cleanupAndExit(0);
1562
- }
1563
- catch (error) {
1564
- console.error(chalk.red('\n❌ Failed:'), error);
1565
- await cleanupAndExit(1);
1566
- }
1567
- });
1568
- // aqe coverage <target>
1569
- program
1570
- .command('coverage')
1571
- .description('Coverage analysis shortcut')
1572
- .argument('[target]', 'Target file or directory', '.')
1573
- .option('--risk', 'Include risk scoring')
1574
- .option('--gaps', 'Detect coverage gaps')
1575
- .option('--threshold <percent>', 'Coverage threshold percentage', '80')
1576
- .option('--sensitivity <level>', 'Gap detection sensitivity (low|medium|high)', 'medium')
1577
- .option('--wizard', 'Run interactive coverage analysis wizard')
1578
- .action(async (target, options) => {
1579
- let analyzeTarget = target;
1580
- let includeRisk = options.risk;
1581
- let detectGaps = options.gaps;
1582
- let threshold = parseInt(options.threshold, 10);
1583
- // Run wizard if requested
1584
- if (options.wizard) {
1585
- try {
1586
- const wizardResult = await runCoverageAnalysisWizard({
1587
- defaultTarget: target !== '.' ? target : undefined,
1588
- defaultThreshold: options.threshold !== '80' ? parseInt(options.threshold, 10) : undefined,
1589
- defaultRiskScoring: options.risk,
1590
- defaultSensitivity: options.sensitivity !== 'medium' ? options.sensitivity : undefined,
1591
- });
1592
- if (wizardResult.cancelled) {
1593
- console.log(chalk.yellow('\n Coverage analysis cancelled.\n'));
1594
- await cleanupAndExit(0);
1595
- }
1596
- // Use wizard results
1597
- analyzeTarget = wizardResult.target;
1598
- includeRisk = wizardResult.riskScoring;
1599
- detectGaps = true; // Wizard always enables gap detection
1600
- threshold = wizardResult.threshold;
1601
- console.log(chalk.green('\n Starting coverage analysis...\n'));
1602
- }
1603
- catch (err) {
1604
- console.error(chalk.red('\n Wizard error:'), err);
1605
- await cleanupAndExit(1);
1606
- }
1607
- }
1608
- if (!await ensureInitialized())
1609
- return;
1610
- try {
1611
- console.log(chalk.blue(`\n Analyzing coverage for ${analyzeTarget}...\n`));
1612
- // Get coverage analysis domain API directly (with lazy loading support)
1613
- const coverageAPI = await context.kernel.getDomainAPIAsync('coverage-analysis');
1614
- if (!coverageAPI) {
1615
- console.log(chalk.red('❌ Coverage analysis domain not available'));
1616
- return;
1617
- }
1618
- // Collect source files and generate synthetic coverage data for analysis
1619
- const fs = await import('fs');
1620
- const path = await import('path');
1621
- const targetPath = path.resolve(analyzeTarget);
1622
- let sourceFiles = [];
1623
- if (fs.existsSync(targetPath)) {
1624
- if (fs.statSync(targetPath).isDirectory()) {
1625
- const walkDir = (dir, depth = 0) => {
1626
- if (depth > 4)
1627
- return [];
1628
- const result = [];
1629
- const items = fs.readdirSync(dir);
1630
- for (const item of items) {
1631
- if (item === 'node_modules' || item === 'dist')
1632
- continue;
1633
- const fullPath = path.join(dir, item);
1634
- const stat = fs.statSync(fullPath);
1635
- if (stat.isDirectory()) {
1636
- result.push(...walkDir(fullPath, depth + 1));
1637
- }
1638
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
1639
- result.push(fullPath);
1640
- }
1641
- }
1642
- return result;
1643
- };
1644
- sourceFiles = walkDir(targetPath);
1645
- }
1646
- else {
1647
- sourceFiles = [targetPath];
1648
- }
1649
- }
1650
- if (sourceFiles.length === 0) {
1651
- console.log(chalk.yellow('No source files found'));
1652
- return;
1653
- }
1654
- console.log(chalk.gray(` Analyzing ${sourceFiles.length} files...\n`));
1655
- // Build coverage data from file analysis
1656
- const files = sourceFiles.map(filePath => {
1657
- const content = fs.readFileSync(filePath, 'utf-8');
1658
- const lines = content.split('\n');
1659
- const totalLines = lines.length;
1660
- // Estimate coverage based on presence of corresponding test file
1661
- const testFile = filePath.replace('.ts', '.test.ts').replace('/src/', '/tests/');
1662
- const hasTest = fs.existsSync(testFile);
1663
- const coverageRate = hasTest ? 0.75 + Math.random() * 0.2 : 0.2 + Math.random() * 0.3;
1664
- const coveredLines = Math.floor(totalLines * coverageRate);
1665
- const uncoveredLines = Array.from({ length: totalLines - coveredLines }, (_, i) => i + coveredLines + 1);
1666
- return {
1667
- path: filePath,
1668
- lines: { covered: coveredLines, total: totalLines },
1669
- branches: { covered: Math.floor(coveredLines * 0.8), total: totalLines },
1670
- functions: { covered: Math.floor(coveredLines * 0.9), total: Math.ceil(totalLines / 20) },
1671
- statements: { covered: coveredLines, total: totalLines },
1672
- uncoveredLines,
1673
- uncoveredBranches: uncoveredLines.slice(0, Math.floor(uncoveredLines.length / 2)),
1674
- };
1675
- });
1676
- const totalLines = files.reduce((sum, f) => sum + f.lines.total, 0);
1677
- const coveredLines = files.reduce((sum, f) => sum + f.lines.covered, 0);
1678
- const totalBranches = files.reduce((sum, f) => sum + f.branches.total, 0);
1679
- const coveredBranches = files.reduce((sum, f) => sum + f.branches.covered, 0);
1680
- const totalFunctions = files.reduce((sum, f) => sum + f.functions.total, 0);
1681
- const coveredFunctions = files.reduce((sum, f) => sum + f.functions.covered, 0);
1682
- const coverageData = {
1683
- files,
1684
- summary: {
1685
- line: Math.round((coveredLines / totalLines) * 100),
1686
- branch: Math.round((coveredBranches / totalBranches) * 100),
1687
- function: Math.round((coveredFunctions / totalFunctions) * 100),
1688
- statement: Math.round((coveredLines / totalLines) * 100),
1689
- files: files.length,
1690
- },
1691
- };
1692
- // Run coverage analysis
1693
- const result = await coverageAPI.analyze({
1694
- coverageData,
1695
- threshold,
1696
- includeFileDetails: true,
1697
- });
1698
- if (result.success && result.value) {
1699
- const report = result.value;
1700
- console.log(chalk.cyan(' Coverage Summary:'));
1701
- console.log(` Lines: ${getColorForPercent(report.summary.line)(report.summary.line + '%')}`);
1702
- console.log(` Branches: ${getColorForPercent(report.summary.branch)(report.summary.branch + '%')}`);
1703
- console.log(` Functions: ${getColorForPercent(report.summary.function)(report.summary.function + '%')}`);
1704
- console.log(` Statements: ${getColorForPercent(report.summary.statement)(report.summary.statement + '%')}`);
1705
- console.log(`\n Threshold: ${report.meetsThreshold ? chalk.green(`Met (${threshold}%)`) : chalk.red(`Not met (${threshold}%)`)}`);
1706
- if (report.recommendations.length > 0) {
1707
- console.log(chalk.cyan('\n Recommendations:'));
1708
- for (const rec of report.recommendations) {
1709
- console.log(chalk.gray(` - ${rec}`));
1710
- }
1711
- }
1712
- }
1713
- // Detect gaps if requested
1714
- if (detectGaps) {
1715
- console.log(chalk.cyan('\n Coverage Gaps:'));
1716
- const gapResult = await coverageAPI.detectGaps({
1717
- coverageData,
1718
- minCoverage: threshold,
1719
- prioritize: includeRisk ? 'risk' : 'size',
1720
- });
1721
- if (gapResult.success && gapResult.value) {
1722
- const gaps = gapResult.value;
1723
- console.log(chalk.gray(` Total uncovered lines: ${gaps.totalUncoveredLines}`));
1724
- console.log(chalk.gray(` Estimated effort: ${gaps.estimatedEffort} hours\n`));
1725
- for (const gap of gaps.gaps.slice(0, 8)) {
1726
- const severityColor = gap.severity === 'high' ? chalk.red : gap.severity === 'medium' ? chalk.yellow : chalk.gray;
1727
- const filePath = gap.file.replace(process.cwd() + '/', '');
1728
- console.log(` ${severityColor(`[${gap.severity}]`)} ${chalk.white(filePath)}`);
1729
- console.log(chalk.gray(` ${gap.lines.length} uncovered lines, Risk: ${(gap.riskScore * 100).toFixed(0)}%`));
1730
- }
1731
- if (gaps.gaps.length > 8) {
1732
- console.log(chalk.gray(` ... and ${gaps.gaps.length - 8} more gaps`));
1733
- }
1734
- }
1735
- }
1736
- // Calculate risk if requested
1737
- if (includeRisk) {
1738
- console.log(chalk.cyan('\n⚠️ Risk Analysis:'));
1739
- // Calculate risk for top 5 files with lowest coverage
1740
- const lowCoverageFiles = [...files]
1741
- .sort((a, b) => (a.lines.covered / a.lines.total) - (b.lines.covered / b.lines.total))
1742
- .slice(0, 5);
1743
- for (const file of lowCoverageFiles) {
1744
- const riskResult = await coverageAPI.calculateRisk({
1745
- file: file.path,
1746
- uncoveredLines: file.uncoveredLines,
1747
- });
1748
- if (riskResult.success && riskResult.value) {
1749
- const risk = riskResult.value;
1750
- const riskColor = risk.riskLevel === 'high' ? chalk.red : risk.riskLevel === 'medium' ? chalk.yellow : chalk.green;
1751
- const filePath = file.path.replace(process.cwd() + '/', '');
1752
- console.log(` ${riskColor(`[${risk.riskLevel}]`)} ${chalk.white(filePath)}`);
1753
- console.log(chalk.gray(` Risk: ${(risk.overallRisk * 100).toFixed(0)}%, Coverage: ${Math.round((file.lines.covered / file.lines.total) * 100)}%`));
1754
- }
1755
- }
1756
- }
1757
- console.log(chalk.green('\n✅ Coverage analysis complete\n'));
1758
- await cleanupAndExit(0);
1759
- }
1760
- catch (error) {
1761
- console.error(chalk.red('\n❌ Failed:'), error);
1762
- await cleanupAndExit(1);
1763
- }
1764
- });
1765
- function getColorForPercent(percent) {
1766
- if (percent >= 80)
1767
- return chalk.green;
1768
- if (percent >= 50)
1769
- return chalk.yellow;
1770
- return chalk.red;
1771
- }
1772
- // aqe token-usage (ADR-042)
1773
- import { createTokenUsageCommand } from './commands/token-usage.js';
1774
- program.addCommand(createTokenUsageCommand());
1775
- // aqe llm (ADR-043)
1776
- import { createLLMRouterCommand } from './commands/llm-router.js';
1777
- program.addCommand(createLLMRouterCommand());
1778
- // aqe quality
1779
- program
1780
- .command('quality')
1781
- .description('Quality assessment shortcut')
1782
- .option('--gate', 'Run quality gate evaluation')
1783
- .action(async (options) => {
1784
- if (!await ensureInitialized())
1785
- return;
1786
- try {
1787
- console.log(chalk.blue(`\n🎯 Running quality assessment...\n`));
1788
- const result = await context.queen.submitTask({
1789
- type: 'assess-quality',
1790
- priority: 'p0',
1791
- targetDomains: ['quality-assessment'],
1792
- payload: { runGate: options.gate },
1793
- timeout: 300000,
1794
- });
1795
- if (result.success) {
1796
- console.log(chalk.green(`✅ Task submitted: ${result.value}`));
1797
- console.log(chalk.gray(` Use 'aqe task status ${result.value}' to check progress`));
1798
- }
1799
- else {
1800
- console.log(chalk.red(`❌ Failed: ${result.error.message}`));
1801
- }
1802
- console.log('');
1803
- }
1804
- catch (error) {
1805
- console.error(chalk.red('\n❌ Failed:'), error);
1806
- await cleanupAndExit(1);
1807
- }
1808
- });
1809
- // aqe security
1810
- program
1811
- .command('security')
1812
- .description('Security scanning shortcut')
1813
- .option('--sast', 'Run SAST scan')
1814
- .option('--dast', 'Run DAST scan')
1815
- .option('--compliance <frameworks>', 'Check compliance (gdpr,hipaa,soc2)', '')
1816
- .option('-t, --target <path>', 'Target directory to scan', '.')
1817
- .action(async (options) => {
1818
- if (!await ensureInitialized())
1819
- return;
1820
- try {
1821
- console.log(chalk.blue(`\n🔒 Running security scan on ${options.target}...\n`));
1822
- // Get security domain API directly (with lazy loading support)
1823
- const securityAPI = await context.kernel.getDomainAPIAsync('security-compliance');
1824
- if (!securityAPI) {
1825
- console.log(chalk.red('❌ Security domain not available'));
1826
- return;
1827
- }
1828
- // Collect files from target
1829
- const fs = await import('fs');
1830
- const path = await import('path');
1831
- const targetPath = path.resolve(options.target);
1832
- let files = [];
1833
- if (fs.existsSync(targetPath)) {
1834
- if (fs.statSync(targetPath).isDirectory()) {
1835
- // Get TypeScript files recursively using fs
1836
- const walkDir = (dir, depth = 0) => {
1837
- if (depth > 4)
1838
- return []; // Max depth limit
1839
- const result = [];
1840
- const items = fs.readdirSync(dir);
1841
- for (const item of items) {
1842
- if (item === 'node_modules' || item === 'dist')
1843
- continue;
1844
- const fullPath = path.join(dir, item);
1845
- const stat = fs.statSync(fullPath);
1846
- if (stat.isDirectory()) {
1847
- result.push(...walkDir(fullPath, depth + 1));
1848
- }
1849
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
1850
- result.push(fullPath);
1851
- }
1852
- }
1853
- return result;
1854
- };
1855
- files = walkDir(targetPath);
1856
- }
1857
- else {
1858
- files = [targetPath];
1859
- }
1860
- }
1861
- if (files.length === 0) {
1862
- console.log(chalk.yellow('No files found to scan'));
1863
- return;
1864
- }
1865
- console.log(chalk.gray(` Scanning ${files.length} files...\n`));
1866
- // Run SAST if requested
1867
- if (options.sast) {
1868
- console.log(chalk.blue('📋 SAST Scan:'));
1869
- const sastResult = await securityAPI.runSASTScan(files);
1870
- if (sastResult.success && sastResult.value) {
1871
- const result = sastResult.value;
1872
- const vulns = result.vulnerabilities || [];
1873
- if (vulns.length === 0) {
1874
- console.log(chalk.green(' ✓ No vulnerabilities found'));
1875
- }
1876
- else {
1877
- console.log(chalk.yellow(` ⚠ Found ${vulns.length} potential issues:`));
1878
- for (const v of vulns.slice(0, 10)) {
1879
- const color = v.severity === 'high' ? chalk.red : v.severity === 'medium' ? chalk.yellow : chalk.gray;
1880
- console.log(color(` [${v.severity}] ${v.type}: ${v.file}:${v.line}`));
1881
- console.log(chalk.gray(` ${v.message}`));
1882
- }
1883
- if (vulns.length > 10) {
1884
- console.log(chalk.gray(` ... and ${vulns.length - 10} more`));
1885
- }
1886
- }
1887
- }
1888
- else {
1889
- console.log(chalk.red(` ✗ SAST failed: ${sastResult.error?.message || 'Unknown error'}`));
1890
- }
1891
- console.log('');
1892
- }
1893
- // Run compliance check if requested
1894
- if (options.compliance) {
1895
- const frameworks = options.compliance.split(',');
1896
- console.log(chalk.blue(`📜 Compliance Check (${frameworks.join(', ')}):`));
1897
- const compResult = await securityAPI.checkCompliance(frameworks);
1898
- if (compResult.success && compResult.value) {
1899
- const result = compResult.value;
1900
- if (result.compliant) {
1901
- console.log(chalk.green(' ✓ Compliant with all frameworks'));
1902
- }
1903
- else {
1904
- console.log(chalk.yellow(' ⚠ Compliance issues found:'));
1905
- for (const issue of (result.issues || []).slice(0, 5)) {
1906
- console.log(chalk.yellow(` [${issue.framework}] ${issue.issue}`));
1907
- }
1908
- }
1909
- }
1910
- else {
1911
- console.log(chalk.red(` ✗ Compliance check failed: ${compResult.error?.message || 'Unknown error'}`));
1912
- }
1913
- console.log('');
1914
- }
1915
- // DAST note
1916
- if (options.dast) {
1917
- console.log(chalk.gray('Note: DAST requires running application URLs. Use --target with URLs for DAST scanning.'));
1918
- }
1919
- console.log(chalk.green('✅ Security scan complete\n'));
1920
- await cleanupAndExit(0);
1921
- }
1922
- catch (err) {
1923
- console.error(chalk.red('\n❌ Failed:'), err);
1924
- await cleanupAndExit(1);
1925
- }
1926
- });
1927
- // aqe code (code intelligence)
1928
- program
1929
- .command('code')
1930
- .description('Code intelligence analysis')
1931
- .argument('<action>', 'Action (index|search|impact|deps)')
1932
- .argument('[target]', 'Target path or query')
1933
- .option('--depth <depth>', 'Analysis depth', '3')
1934
- .option('--include-tests', 'Include test files')
1935
- .action(async (action, target, options) => {
1936
- if (!await ensureInitialized())
1937
- return;
1938
- try {
1939
- // Get code intelligence domain API directly (with lazy loading support)
1940
- const codeAPI = await context.kernel.getDomainAPIAsync('code-intelligence');
1941
- if (!codeAPI) {
1942
- console.log(chalk.red('❌ Code intelligence domain not available'));
1943
- return;
1944
- }
1945
- const fs = await import('fs');
1946
- const path = await import('path');
1947
- if (action === 'index') {
1948
- console.log(chalk.blue(`\n🗂️ Indexing codebase at ${target || '.'}...\n`));
1949
- const targetPath = path.resolve(target || '.');
1950
- let paths = [];
1951
- if (fs.existsSync(targetPath)) {
1952
- if (fs.statSync(targetPath).isDirectory()) {
1953
- const walkDir = (dir, depth = 0) => {
1954
- if (depth > 4)
1955
- return [];
1956
- const result = [];
1957
- const items = fs.readdirSync(dir);
1958
- for (const item of items) {
1959
- if (item === 'node_modules' || item === 'dist')
1960
- continue;
1961
- const fullPath = path.join(dir, item);
1962
- const stat = fs.statSync(fullPath);
1963
- if (stat.isDirectory()) {
1964
- result.push(...walkDir(fullPath, depth + 1));
1965
- }
1966
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
1967
- result.push(fullPath);
1968
- }
1969
- }
1970
- return result;
1971
- };
1972
- paths = walkDir(targetPath);
1973
- }
1974
- else {
1975
- paths = [targetPath];
1976
- }
1977
- }
1978
- console.log(chalk.gray(` Found ${paths.length} files to index...\n`));
1979
- const result = await codeAPI.index({
1980
- paths,
1981
- incremental: false,
1982
- includeTests: options.includeTests || false,
1983
- });
1984
- if (result.success && result.value) {
1985
- const idx = result.value;
1986
- console.log(chalk.green(`✅ Indexing complete\n`));
1987
- console.log(chalk.cyan(' Results:'));
1988
- console.log(` Files indexed: ${chalk.white(idx.filesIndexed)}`);
1989
- console.log(` Nodes created: ${chalk.white(idx.nodesCreated)}`);
1990
- console.log(` Edges created: ${chalk.white(idx.edgesCreated)}`);
1991
- console.log(` Duration: ${chalk.yellow(idx.duration + 'ms')}`);
1992
- if (idx.errors.length > 0) {
1993
- console.log(chalk.red(`\n Errors (${idx.errors.length}):`));
1994
- for (const err of idx.errors.slice(0, 5)) {
1995
- console.log(chalk.red(` ${err.file}: ${err.error}`));
1996
- }
1997
- }
1998
- }
1999
- else {
2000
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
2001
- }
2002
- }
2003
- else if (action === 'search') {
2004
- if (!target) {
2005
- console.log(chalk.red('❌ Search query required'));
2006
- return;
2007
- }
2008
- console.log(chalk.blue(`\n🔎 Searching for: "${target}"...\n`));
2009
- const result = await codeAPI.search({
2010
- query: target,
2011
- type: 'semantic',
2012
- limit: 10,
2013
- });
2014
- if (result.success && result.value) {
2015
- const search = result.value;
2016
- console.log(chalk.green(`✅ Found ${search.total} results (${search.searchTime}ms)\n`));
2017
- for (const r of search.results) {
2018
- const filePath = r.file.replace(process.cwd() + '/', '');
2019
- console.log(` ${chalk.cyan(filePath)}${r.line ? ':' + r.line : ''}`);
2020
- console.log(chalk.gray(` ${r.snippet.slice(0, 100)}...`));
2021
- console.log(chalk.gray(` Score: ${(r.score * 100).toFixed(0)}%\n`));
2022
- }
2023
- }
2024
- else {
2025
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
2026
- }
2027
- }
2028
- else if (action === 'impact') {
2029
- console.log(chalk.blue(`\n📊 Analyzing impact for ${target || 'recent changes'}...\n`));
2030
- const targetPath = path.resolve(target || '.');
2031
- let changedFiles = [];
2032
- if (fs.existsSync(targetPath)) {
2033
- if (fs.statSync(targetPath).isFile()) {
2034
- changedFiles = [targetPath];
2035
- }
2036
- else {
2037
- // Get recently modified files (simulated)
2038
- const walkDir = (dir, depth = 0) => {
2039
- if (depth > 2)
2040
- return [];
2041
- const result = [];
2042
- const items = fs.readdirSync(dir);
2043
- for (const item of items) {
2044
- if (item === 'node_modules' || item === 'dist')
2045
- continue;
2046
- const fullPath = path.join(dir, item);
2047
- const stat = fs.statSync(fullPath);
2048
- if (stat.isDirectory()) {
2049
- result.push(...walkDir(fullPath, depth + 1));
2050
- }
2051
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
2052
- result.push(fullPath);
2053
- }
2054
- }
2055
- return result;
2056
- };
2057
- changedFiles = walkDir(targetPath).slice(0, 10);
2058
- }
2059
- }
2060
- const result = await codeAPI.analyzeImpact({
2061
- changedFiles,
2062
- depth: parseInt(options.depth),
2063
- includeTests: options.includeTests || false,
2064
- });
2065
- if (result.success && result.value) {
2066
- const impact = result.value;
2067
- const riskColor = impact.riskLevel === 'high' ? chalk.red : impact.riskLevel === 'medium' ? chalk.yellow : chalk.green;
2068
- console.log(` Risk Level: ${riskColor(impact.riskLevel)}\n`);
2069
- console.log(chalk.cyan(` Direct Impact (${impact.directImpact.length} files):`));
2070
- for (const file of impact.directImpact.slice(0, 5)) {
2071
- const filePath = file.file.replace(process.cwd() + '/', '');
2072
- console.log(` ${chalk.white(filePath)}`);
2073
- console.log(chalk.gray(` Reason: ${file.reason}, Risk: ${(file.riskScore * 100).toFixed(0)}%`));
2074
- }
2075
- if (impact.transitiveImpact.length > 0) {
2076
- console.log(chalk.cyan(`\n Transitive Impact (${impact.transitiveImpact.length} files):`));
2077
- for (const file of impact.transitiveImpact.slice(0, 5)) {
2078
- const filePath = file.file.replace(process.cwd() + '/', '');
2079
- console.log(` ${chalk.white(filePath)} (distance: ${file.distance})`);
2080
- }
2081
- }
2082
- if (impact.impactedTests.length > 0) {
2083
- console.log(chalk.cyan(`\n Impacted Tests (${impact.impactedTests.length}):`));
2084
- for (const test of impact.impactedTests.slice(0, 5)) {
2085
- console.log(` ${chalk.gray(test)}`);
2086
- }
2087
- }
2088
- if (impact.recommendations.length > 0) {
2089
- console.log(chalk.cyan('\n Recommendations:'));
2090
- for (const rec of impact.recommendations) {
2091
- console.log(chalk.gray(` • ${rec}`));
2092
- }
2093
- }
2094
- }
2095
- else {
2096
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
2097
- }
2098
- }
2099
- else if (action === 'deps') {
2100
- console.log(chalk.blue(`\n🔗 Mapping dependencies for ${target || '.'}...\n`));
2101
- const targetPath = path.resolve(target || '.');
2102
- let files = [];
2103
- if (fs.existsSync(targetPath)) {
2104
- if (fs.statSync(targetPath).isFile()) {
2105
- files = [targetPath];
2106
- }
2107
- else {
2108
- const walkDir = (dir, depth = 0) => {
2109
- if (depth > 2)
2110
- return [];
2111
- const result = [];
2112
- const items = fs.readdirSync(dir);
2113
- for (const item of items) {
2114
- if (item === 'node_modules' || item === 'dist')
2115
- continue;
2116
- const fullPath = path.join(dir, item);
2117
- const stat = fs.statSync(fullPath);
2118
- if (stat.isDirectory()) {
2119
- result.push(...walkDir(fullPath, depth + 1));
2120
- }
2121
- else if (item.endsWith('.ts') && !item.endsWith('.d.ts')) {
2122
- result.push(fullPath);
2123
- }
2124
- }
2125
- return result;
2126
- };
2127
- files = walkDir(targetPath).slice(0, 50);
2128
- }
2129
- }
2130
- const result = await codeAPI.mapDependencies({
2131
- files,
2132
- direction: 'both',
2133
- depth: parseInt(options.depth),
2134
- });
2135
- if (result.success && result.value) {
2136
- const deps = result.value;
2137
- console.log(chalk.cyan(' Dependency Metrics:'));
2138
- console.log(` Nodes: ${chalk.white(deps.metrics.totalNodes)}`);
2139
- console.log(` Edges: ${chalk.white(deps.metrics.totalEdges)}`);
2140
- console.log(` Avg Degree: ${chalk.yellow(deps.metrics.avgDegree.toFixed(2))}`);
2141
- console.log(` Max Depth: ${chalk.yellow(deps.metrics.maxDepth)}`);
2142
- console.log(` Cyclomatic Complexity: ${chalk.yellow(deps.metrics.cyclomaticComplexity)}`);
2143
- if (deps.cycles.length > 0) {
2144
- console.log(chalk.red(`\n ⚠️ Circular Dependencies (${deps.cycles.length}):`));
2145
- for (const cycle of deps.cycles.slice(0, 3)) {
2146
- console.log(chalk.red(` ${cycle.join(' → ')}`));
2147
- }
2148
- }
2149
- console.log(chalk.cyan(`\n Top Dependencies (by connections):`));
2150
- const sortedNodes = [...deps.nodes].sort((a, b) => (b.inDegree + b.outDegree) - (a.inDegree + a.outDegree));
2151
- for (const node of sortedNodes.slice(0, 8)) {
2152
- const filePath = node.path.replace(process.cwd() + '/', '');
2153
- console.log(` ${chalk.white(filePath)}`);
2154
- console.log(chalk.gray(` In: ${node.inDegree}, Out: ${node.outDegree}, Type: ${node.type}`));
2155
- }
2156
- }
2157
- else {
2158
- console.log(chalk.red(`❌ Failed: ${result.error?.message || 'Unknown error'}`));
2159
- }
2160
- }
2161
- else {
2162
- console.log(chalk.red(`\n❌ Unknown action: ${action}`));
2163
- console.log(chalk.gray(' Available: index, search, impact, deps\n'));
2164
- await cleanupAndExit(1);
2165
- }
2166
- console.log('');
2167
- await cleanupAndExit(0);
2168
- }
2169
- catch (error) {
2170
- console.error(chalk.red('\n❌ Failed:'), error);
2171
- await cleanupAndExit(1);
2172
- }
2173
- });
605
+ import { createTestCommand } from './commands/test.js';
606
+ import { createCoverageCommand } from './commands/coverage.js';
607
+ import { createQualityCommand } from './commands/quality.js';
608
+ import { createSecurityCommand } from './commands/security.js';
609
+ import { createCodeCommand } from './commands/code.js';
610
+ import { createMigrateCommand } from './commands/migrate.js';
611
+ import { createCompletionsCommand } from './commands/completions.js';
612
+ import { createFleetCommand } from './commands/fleet.js';
613
+ // Register shortcut commands
614
+ program.addCommand(createTestCommand(context, cleanupAndExit, ensureInitialized));
615
+ program.addCommand(createCoverageCommand(context, cleanupAndExit, ensureInitialized));
616
+ program.addCommand(createQualityCommand(context, cleanupAndExit, ensureInitialized));
617
+ program.addCommand(createSecurityCommand(context, cleanupAndExit, ensureInitialized));
618
+ program.addCommand(createCodeCommand(context, cleanupAndExit, ensureInitialized));
619
+ program.addCommand(createMigrateCommand(context, cleanupAndExit, ensureInitialized));
620
+ program.addCommand(createCompletionsCommand(cleanupAndExit));
621
+ program.addCommand(createFleetCommand(context, cleanupAndExit, ensureInitialized, registerDomainWorkflowActions));
2174
622
  // ============================================================================
2175
- // Migrate Command - V2 to V3 Migration (ADR-048)
2176
- // ============================================================================
2177
- const migrateCmd = program
2178
- .command('migrate')
2179
- .description('V2-to-V3 migration tools with agent compatibility (ADR-048)');
2180
- // Helper to check path existence
2181
- const pathExists = (p) => {
2182
- try {
2183
- require('fs').accessSync(p);
2184
- return true;
2185
- }
2186
- catch {
2187
- return false;
2188
- }
2189
- };
2190
- // migrate run - Main migration command (default behavior)
2191
- migrateCmd
2192
- .command('run')
2193
- .description('Run full migration from v2 to v3')
2194
- .option('--dry-run', 'Preview migration without making changes')
2195
- .option('--backup', 'Create backup before migration (recommended)', true)
2196
- .option('--skip-memory', 'Skip memory database migration')
2197
- .option('--skip-patterns', 'Skip pattern migration')
2198
- .option('--skip-config', 'Skip configuration migration')
2199
- .option('--skip-agents', 'Skip agent name migration')
2200
- .option('--target <component>', 'Migrate specific component (agents, skills, config, memory)')
2201
- .option('--force', 'Force migration even if v3 already exists')
2202
- .action(async (options) => {
2203
- const fs = await import('fs');
2204
- const path = await import('path');
2205
- console.log(chalk.blue('\n🔄 Agentic QE v2 to v3 Migration (ADR-048)\n'));
2206
- const cwd = process.cwd();
2207
- const v2Dir = path.join(cwd, '.agentic-qe');
2208
- const v3Dir = path.join(cwd, '.aqe');
2209
- const claudeAgentDir = path.join(cwd, '.claude', 'agents');
2210
- // Step 1: Detect v2 installation
2211
- console.log(chalk.white('1. Detecting v2 installation...'));
2212
- const hasV2Dir = fs.existsSync(v2Dir);
2213
- const hasClaudeAgents = fs.existsSync(claudeAgentDir);
2214
- if (!hasV2Dir && !hasClaudeAgents) {
2215
- console.log(chalk.yellow(' ⚠ No v2 installation found'));
2216
- console.log(chalk.gray(' This might be a fresh project. Use `aqe init` instead.'));
2217
- await cleanupAndExit(0);
2218
- }
2219
- const v2Files = {
2220
- memoryDb: path.join(v2Dir, 'memory.db'),
2221
- config: path.join(v2Dir, 'config.json'),
2222
- patterns: path.join(v2Dir, 'patterns'),
2223
- };
2224
- const hasMemory = hasV2Dir && fs.existsSync(v2Files.memoryDb);
2225
- const hasConfig = hasV2Dir && fs.existsSync(v2Files.config);
2226
- const hasPatterns = hasV2Dir && fs.existsSync(v2Files.patterns);
2227
- // Detect v2 agents needing migration
2228
- const agentsToMigrate = [];
2229
- if (hasClaudeAgents) {
2230
- const files = fs.readdirSync(claudeAgentDir);
2231
- for (const file of files) {
2232
- if (file.endsWith('.md') && file.startsWith('qe-')) {
2233
- const agentName = file.replace('.md', '');
2234
- if (isDeprecatedAgent(agentName)) {
2235
- agentsToMigrate.push(agentName);
2236
- }
2237
- }
2238
- }
2239
- }
2240
- console.log(chalk.green(' ✓ Found v2 installation:'));
2241
- console.log(chalk.gray(` Memory DB: ${hasMemory ? '✓' : '✗'}`));
2242
- console.log(chalk.gray(` Config: ${hasConfig ? '✓' : '✗'}`));
2243
- console.log(chalk.gray(` Patterns: ${hasPatterns ? '✓' : '✗'}`));
2244
- console.log(chalk.gray(` Agents to migrate: ${agentsToMigrate.length}\n`));
2245
- // Step 2: Check v3 existence
2246
- console.log(chalk.white('2. Checking v3 status...'));
2247
- if (fs.existsSync(v3Dir) && !options.force) {
2248
- console.log(chalk.yellow(' ⚠ v3 directory already exists at .aqe/'));
2249
- console.log(chalk.gray(' Use --force to overwrite existing v3 installation.'));
2250
- await cleanupAndExit(1);
2251
- }
2252
- console.log(chalk.green(' ✓ Ready for migration\n'));
2253
- // Dry run mode
2254
- if (options.dryRun) {
2255
- console.log(chalk.blue('📋 Dry Run - Migration Plan:\n'));
2256
- if (!options.skipMemory && hasMemory) {
2257
- const stats = fs.statSync(v2Files.memoryDb);
2258
- console.log(chalk.gray(` • Migrate memory.db (${(stats.size / 1024).toFixed(1)} KB)`));
2259
- }
2260
- if (!options.skipConfig && hasConfig) {
2261
- console.log(chalk.gray(' • Convert config.json to v3 format'));
2262
- }
2263
- if (!options.skipPatterns && hasPatterns) {
2264
- const patternFiles = fs.readdirSync(v2Files.patterns);
2265
- console.log(chalk.gray(` • Migrate ${patternFiles.length} pattern files`));
2266
- }
2267
- if (!options.skipAgents && agentsToMigrate.length > 0) {
2268
- console.log(chalk.gray(` • Migrate ${agentsToMigrate.length} agent names:`));
2269
- for (const agent of agentsToMigrate) {
2270
- console.log(chalk.gray(` ${agent} → ${resolveAgentName(agent)}`));
2271
- }
2272
- }
2273
- console.log(chalk.yellow('\n⚠ This is a dry run. No changes were made.'));
2274
- console.log(chalk.gray('Run without --dry-run to execute migration.\n'));
2275
- await cleanupAndExit(0);
2276
- }
2277
- // Step 3: Create backup
2278
- if (options.backup) {
2279
- console.log(chalk.white('3. Creating backup...'));
2280
- const backupDir = path.join(cwd, '.aqe-backup', `backup-${Date.now()}`);
2281
- try {
2282
- fs.mkdirSync(backupDir, { recursive: true });
2283
- const copyDir = (src, dest) => {
2284
- if (!fs.existsSync(src))
2285
- return;
2286
- if (fs.statSync(src).isDirectory()) {
2287
- fs.mkdirSync(dest, { recursive: true });
2288
- for (const file of fs.readdirSync(src)) {
2289
- copyDir(path.join(src, file), path.join(dest, file));
2290
- }
2291
- }
2292
- else {
2293
- fs.copyFileSync(src, dest);
2294
- }
2295
- };
2296
- if (hasV2Dir)
2297
- copyDir(v2Dir, path.join(backupDir, '.agentic-qe'));
2298
- if (hasClaudeAgents)
2299
- copyDir(claudeAgentDir, path.join(backupDir, '.claude', 'agents'));
2300
- console.log(chalk.green(` ✓ Backup created at .aqe-backup/\n`));
2301
- }
2302
- catch (err) {
2303
- console.log(chalk.red(` ✗ Backup failed: ${err}`));
2304
- await cleanupAndExit(1);
2305
- }
2306
- }
2307
- else {
2308
- console.log(chalk.yellow('3. Backup skipped (--no-backup)\n'));
2309
- }
2310
- // Step 4: Create v3 directory structure
2311
- if (!options.target || options.target === 'config' || options.target === 'memory') {
2312
- console.log(chalk.white('4. Creating v3 directory structure...'));
2313
- try {
2314
- fs.mkdirSync(v3Dir, { recursive: true });
2315
- fs.mkdirSync(path.join(v3Dir, 'agentdb'), { recursive: true });
2316
- fs.mkdirSync(path.join(v3Dir, 'reasoning-bank'), { recursive: true });
2317
- fs.mkdirSync(path.join(v3Dir, 'cache'), { recursive: true });
2318
- fs.mkdirSync(path.join(v3Dir, 'logs'), { recursive: true });
2319
- console.log(chalk.green(' ✓ Directory structure created\n'));
2320
- }
2321
- catch (err) {
2322
- console.log(chalk.red(` ✗ Failed: ${err}\n`));
2323
- await cleanupAndExit(1);
2324
- }
2325
- }
2326
- // Step 5: Migrate memory database
2327
- if ((!options.target || options.target === 'memory') && !options.skipMemory && hasMemory) {
2328
- console.log(chalk.white('5. Migrating memory database...'));
2329
- try {
2330
- const destDb = path.join(v3Dir, 'agentdb', 'memory.db');
2331
- fs.copyFileSync(v2Files.memoryDb, destDb);
2332
- const indexFile = path.join(v3Dir, 'agentdb', 'index.json');
2333
- fs.writeFileSync(indexFile, JSON.stringify({
2334
- version: '3.0.0',
2335
- migratedFrom: 'v2',
2336
- migratedAt: new Date().toISOString(),
2337
- hnswEnabled: true,
2338
- vectorDimensions: 128,
2339
- }, null, 2));
2340
- const stats = fs.statSync(v2Files.memoryDb);
2341
- console.log(chalk.green(` ✓ Memory database migrated (${(stats.size / 1024).toFixed(1)} KB)\n`));
2342
- }
2343
- catch (err) {
2344
- console.log(chalk.red(` ✗ Migration failed: ${err}\n`));
2345
- }
2346
- }
2347
- else if (options.target && options.target !== 'memory') {
2348
- console.log(chalk.gray('5. Memory migration skipped (--target)\n'));
2349
- }
2350
- else if (options.skipMemory) {
2351
- console.log(chalk.yellow('5. Memory migration skipped\n'));
2352
- }
2353
- else {
2354
- console.log(chalk.gray('5. No memory database to migrate\n'));
2355
- }
2356
- // Step 6: Migrate configuration
2357
- if ((!options.target || options.target === 'config') && !options.skipConfig && hasConfig) {
2358
- console.log(chalk.white('6. Migrating configuration...'));
2359
- try {
2360
- const v2ConfigRaw = fs.readFileSync(v2Files.config, 'utf-8');
2361
- const v2Config = parseJsonFile(v2ConfigRaw, v2Files.config);
2362
- const v3Config = {
2363
- version: '3.0.0',
2364
- migratedFrom: v2Config.version || '2.x',
2365
- migratedAt: new Date().toISOString(),
2366
- kernel: { eventBus: 'in-memory', coordinator: 'queen' },
2367
- domains: {
2368
- 'test-generation': { enabled: true },
2369
- 'test-execution': { enabled: true },
2370
- 'coverage-analysis': { enabled: true, algorithm: 'hnsw', dimensions: 128 },
2371
- 'quality-assessment': { enabled: true },
2372
- 'defect-intelligence': { enabled: true },
2373
- 'requirements-validation': { enabled: true },
2374
- 'code-intelligence': { enabled: true },
2375
- 'security-compliance': { enabled: true },
2376
- 'contract-testing': { enabled: true },
2377
- 'visual-accessibility': { enabled: false },
2378
- 'chaos-resilience': { enabled: true },
2379
- 'learning-optimization': { enabled: true },
2380
- },
2381
- memory: {
2382
- backend: 'hybrid',
2383
- path: '.aqe/agentdb/',
2384
- hnsw: { M: 16, efConstruction: 200 },
2385
- },
2386
- learning: {
2387
- reasoningBank: true,
2388
- sona: true,
2389
- patternRetention: v2Config.learning?.patternRetention || 180,
2390
- },
2391
- v2Migration: {
2392
- originalConfig: v2Config,
2393
- migrationDate: new Date().toISOString(),
2394
- },
2395
- };
2396
- const destConfig = path.join(v3Dir, 'config.json');
2397
- fs.writeFileSync(destConfig, JSON.stringify(v3Config, null, 2));
2398
- console.log(chalk.green(' ✓ Configuration migrated\n'));
2399
- }
2400
- catch (err) {
2401
- console.log(chalk.red(` ✗ Config migration failed: ${err}\n`));
2402
- }
2403
- }
2404
- else if (options.target && options.target !== 'config') {
2405
- console.log(chalk.gray('6. Config migration skipped (--target)\n'));
2406
- }
2407
- else if (options.skipConfig) {
2408
- console.log(chalk.yellow('6. Configuration migration skipped\n'));
2409
- }
2410
- else {
2411
- console.log(chalk.gray('6. No configuration to migrate\n'));
2412
- }
2413
- // Step 7: Migrate patterns
2414
- if ((!options.target || options.target === 'memory') && !options.skipPatterns && hasPatterns) {
2415
- console.log(chalk.white('7. Migrating patterns to ReasoningBank...'));
2416
- try {
2417
- const patternFiles = fs.readdirSync(v2Files.patterns);
2418
- let migratedCount = 0;
2419
- for (const file of patternFiles) {
2420
- const srcPath = path.join(v2Files.patterns, file);
2421
- const destPath = path.join(v3Dir, 'reasoning-bank', file);
2422
- if (fs.statSync(srcPath).isFile()) {
2423
- fs.copyFileSync(srcPath, destPath);
2424
- migratedCount++;
2425
- }
2426
- }
2427
- const indexPath = path.join(v3Dir, 'reasoning-bank', 'index.json');
2428
- fs.writeFileSync(indexPath, JSON.stringify({
2429
- version: '3.0.0',
2430
- migratedFrom: 'v2',
2431
- migratedAt: new Date().toISOString(),
2432
- patternCount: migratedCount,
2433
- hnswIndexed: false,
2434
- }, null, 2));
2435
- console.log(chalk.green(` ✓ ${migratedCount} patterns migrated\n`));
2436
- }
2437
- catch (err) {
2438
- console.log(chalk.red(` ✗ Pattern migration failed: ${err}\n`));
2439
- }
2440
- }
2441
- else if (options.skipPatterns) {
2442
- console.log(chalk.yellow('7. Pattern migration skipped\n'));
2443
- }
2444
- else {
2445
- console.log(chalk.gray('7. No patterns to migrate\n'));
2446
- }
2447
- // Step 8: Migrate agent names (ADR-048)
2448
- if ((!options.target || options.target === 'agents') && !options.skipAgents && agentsToMigrate.length > 0) {
2449
- console.log(chalk.white('8. Migrating agent names (ADR-048)...'));
2450
- let migratedAgents = 0;
2451
- const deprecatedDir = path.join(claudeAgentDir, 'deprecated');
2452
- // Create deprecated directory for old agents
2453
- if (!fs.existsSync(deprecatedDir)) {
2454
- fs.mkdirSync(deprecatedDir, { recursive: true });
2455
- }
2456
- for (const v2Name of agentsToMigrate) {
2457
- const v3Name = resolveAgentName(v2Name);
2458
- const v2FilePath = path.join(claudeAgentDir, `${v2Name}.md`);
2459
- const v3FilePath = path.join(claudeAgentDir, `${v3Name}.md`);
2460
- const deprecatedPath = path.join(deprecatedDir, `${v2Name}.md.v2`);
2461
- try {
2462
- // Read the original file
2463
- const content = fs.readFileSync(v2FilePath, 'utf-8');
2464
- // Parse frontmatter (between first two ---)
2465
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
2466
- if (!frontmatterMatch) {
2467
- console.log(chalk.yellow(` ⚠ ${v2Name}: No frontmatter found, skipping`));
2468
- continue;
2469
- }
2470
- const frontmatter = frontmatterMatch[1];
2471
- const bodyStart = content.indexOf('---', 4) + 4; // After second ---
2472
- let body = content.slice(bodyStart);
2473
- // Update frontmatter: change name and add v2_compat
2474
- let newFrontmatter = frontmatter.replace(/^name:\s*.+$/m, `name: ${v3Name}`);
2475
- // Add v2_compat field if not present
2476
- if (!newFrontmatter.includes('v2_compat:')) {
2477
- newFrontmatter += `\nv2_compat:\n name: ${v2Name}\n deprecated_in: "3.0.0"\n removed_in: "4.0.0"`;
2478
- }
2479
- // Update body content: replace old agent name references
2480
- // Convert kebab-case to Title Case for display names
2481
- const toTitleCase = (s) => s.replace('qe-', '').split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
2482
- const v2DisplayName = toTitleCase(v2Name);
2483
- const v3DisplayName = toTitleCase(v3Name);
2484
- // Replace display names in body (e.g., "Test Generator" → "Test Architect")
2485
- body = body.replace(new RegExp(v2DisplayName, 'g'), v3DisplayName);
2486
- // Replace kebab-case references (e.g., "qe-test-generator" → "qe-test-architect")
2487
- body = body.replace(new RegExp(v2Name, 'g'), v3Name);
2488
- // Create new content
2489
- const newContent = `---\n${newFrontmatter}\n---${body}`;
2490
- // Write new v3 agent file
2491
- fs.writeFileSync(v3FilePath, newContent, 'utf-8');
2492
- // Move old file to deprecated folder
2493
- fs.renameSync(v2FilePath, deprecatedPath);
2494
- console.log(chalk.gray(` ${v2Name} → ${v3Name}`));
2495
- migratedAgents++;
2496
- }
2497
- catch (err) {
2498
- console.log(chalk.red(` ✗ ${v2Name}: ${err}`));
2499
- }
2500
- }
2501
- if (migratedAgents > 0) {
2502
- console.log(chalk.green(` ✓ ${migratedAgents} agents migrated`));
2503
- console.log(chalk.gray(` Old files archived to: ${deprecatedDir}\n`));
2504
- }
2505
- else {
2506
- console.log(chalk.yellow(' ⚠ No agents were migrated\n'));
2507
- }
2508
- }
2509
- else if (options.skipAgents) {
2510
- console.log(chalk.yellow('8. Agent migration skipped\n'));
2511
- }
2512
- else {
2513
- console.log(chalk.gray('8. No agents need migration\n'));
2514
- }
2515
- // Step 9: Validation
2516
- console.log(chalk.white('9. Validating migration...'));
2517
- const validationResults = {
2518
- v3DirExists: fs.existsSync(v3Dir),
2519
- configExists: fs.existsSync(path.join(v3Dir, 'config.json')),
2520
- agentdbExists: fs.existsSync(path.join(v3Dir, 'agentdb')),
2521
- reasoningBankExists: fs.existsSync(path.join(v3Dir, 'reasoning-bank')),
2522
- };
2523
- const allValid = Object.values(validationResults).every(v => v);
2524
- if (allValid) {
2525
- console.log(chalk.green(' ✓ Migration validated successfully\n'));
2526
- }
2527
- else {
2528
- console.log(chalk.yellow(' ⚠ Some validations failed:'));
2529
- for (const [key, value] of Object.entries(validationResults)) {
2530
- console.log(chalk.gray(` ${key}: ${value ? '✓' : '✗'}`));
2531
- }
2532
- }
2533
- // Summary
2534
- console.log(chalk.blue('═══════════════════════════════════════════════'));
2535
- console.log(chalk.green.bold('✅ Migration Complete!\n'));
2536
- console.log(chalk.white('Next steps:'));
2537
- console.log(chalk.gray(' 1. Run `aqe migrate verify` to validate'));
2538
- console.log(chalk.gray(' 2. Run `aqe migrate status` to check'));
2539
- console.log(chalk.gray(' 3. Use `aqe migrate rollback` if needed\n'));
2540
- await cleanupAndExit(0);
2541
- });
2542
- // migrate status - Check migration status
2543
- migrateCmd
2544
- .command('status')
2545
- .description('Check migration status of current project')
2546
- .option('--json', 'Output as JSON')
2547
- .action(async (options) => {
2548
- const fs = await import('fs');
2549
- const path = await import('path');
2550
- const cwd = process.cwd();
2551
- const v2Dir = path.join(cwd, '.agentic-qe');
2552
- const v3Dir = path.join(cwd, '.aqe');
2553
- const claudeAgentDir = path.join(cwd, '.claude', 'agents');
2554
- const isV2Project = fs.existsSync(v2Dir);
2555
- const isV3Project = fs.existsSync(v3Dir);
2556
- // Find agents needing migration
2557
- const agentsToMigrate = [];
2558
- const agentsMigrated = [];
2559
- if (fs.existsSync(claudeAgentDir)) {
2560
- const files = fs.readdirSync(claudeAgentDir);
2561
- for (const file of files) {
2562
- if (file.endsWith('.md') && file.startsWith('qe-')) {
2563
- const agentName = file.replace('.md', '');
2564
- if (isDeprecatedAgent(agentName)) {
2565
- agentsToMigrate.push(agentName);
2566
- }
2567
- else if (v3Agents.includes(agentName)) {
2568
- agentsMigrated.push(agentName);
2569
- }
2570
- }
2571
- }
2572
- }
2573
- const needsMigration = isV2Project && !isV3Project || agentsToMigrate.length > 0;
2574
- const status = {
2575
- version: '3.0.0',
2576
- isV2Project,
2577
- isV3Project,
2578
- needsMigration,
2579
- agentsToMigrate,
2580
- agentsMigrated,
2581
- components: [
2582
- { name: 'Data Directory', status: isV3Project ? 'migrated' : (isV2Project ? 'pending' : 'not-required') },
2583
- { name: 'Agent Names', status: agentsToMigrate.length === 0 ? 'migrated' : 'pending' },
2584
- ],
2585
- };
2586
- if (options.json) {
2587
- console.log(JSON.stringify(status, null, 2));
2588
- return;
2589
- }
2590
- console.log(chalk.bold('\n📊 Migration Status\n'));
2591
- console.log(`Version: ${chalk.cyan(status.version)}`);
2592
- console.log(`V2 Project: ${status.isV2Project ? chalk.yellow('Yes') : chalk.dim('No')}`);
2593
- console.log(`V3 Project: ${status.isV3Project ? chalk.green('Yes') : chalk.dim('No')}`);
2594
- console.log(`Needs Migration: ${status.needsMigration ? chalk.yellow('Yes') : chalk.green('No')}`);
2595
- console.log(chalk.bold('\n📦 Components\n'));
2596
- for (const comp of status.components) {
2597
- const color = comp.status === 'migrated' ? chalk.green : comp.status === 'pending' ? chalk.yellow : chalk.dim;
2598
- console.log(` ${comp.name}: ${color(comp.status)}`);
2599
- }
2600
- if (agentsToMigrate.length > 0) {
2601
- console.log(chalk.bold('\n⚠️ Agents Needing Migration\n'));
2602
- for (const agent of agentsToMigrate) {
2603
- console.log(` ${chalk.yellow(agent)} → ${chalk.green(resolveAgentName(agent))}`);
2604
- }
2605
- }
2606
- console.log();
2607
- await cleanupAndExit(0);
2608
- });
2609
- // migrate verify - Verify migration
2610
- migrateCmd
2611
- .command('verify')
2612
- .description('Verify migration integrity')
2613
- .option('--fix', 'Attempt to fix issues automatically')
2614
- .action(async (options) => {
2615
- const fs = await import('fs');
2616
- const path = await import('path');
2617
- console.log(chalk.bold('\n🔍 Verifying Migration...\n'));
2618
- const cwd = process.cwd();
2619
- const v3Dir = path.join(cwd, '.aqe');
2620
- const claudeAgentDir = path.join(cwd, '.claude', 'agents');
2621
- // Find deprecated agents still in use
2622
- const deprecatedInUse = [];
2623
- if (fs.existsSync(claudeAgentDir)) {
2624
- const files = fs.readdirSync(claudeAgentDir);
2625
- for (const file of files) {
2626
- if (file.endsWith('.md') && file.startsWith('qe-')) {
2627
- const agentName = file.replace('.md', '');
2628
- if (isDeprecatedAgent(agentName)) {
2629
- deprecatedInUse.push(agentName);
2630
- }
2631
- }
2632
- }
2633
- }
2634
- const checks = [
2635
- {
2636
- name: 'V3 Directory',
2637
- passed: fs.existsSync(v3Dir),
2638
- message: fs.existsSync(v3Dir) ? 'Exists' : 'Missing .aqe/',
2639
- },
2640
- {
2641
- name: 'Agent Compatibility',
2642
- passed: deprecatedInUse.length === 0,
2643
- message: deprecatedInUse.length === 0 ? 'All agents use v3 names' : `${deprecatedInUse.length} deprecated agents`,
2644
- },
2645
- {
2646
- name: 'Config Format',
2647
- passed: fs.existsSync(path.join(v3Dir, 'config.json')),
2648
- message: 'Valid v3 config',
2649
- },
2650
- ];
2651
- let allPassed = true;
2652
- for (const check of checks) {
2653
- const icon = check.passed ? chalk.green('✓') : chalk.red('✗');
2654
- const color = check.passed ? chalk.green : chalk.red;
2655
- console.log(` ${icon} ${check.name}: ${color(check.message)}`);
2656
- if (!check.passed)
2657
- allPassed = false;
2658
- }
2659
- console.log();
2660
- if (allPassed) {
2661
- console.log(chalk.green('✅ All verification checks passed!\n'));
2662
- }
2663
- else {
2664
- console.log(chalk.yellow('⚠️ Some checks failed.'));
2665
- if (options.fix) {
2666
- console.log(chalk.dim(' Attempting automatic fixes...\n'));
2667
- let fixedCount = 0;
2668
- // Fix 1: Create v3 directory if missing
2669
- if (!fs.existsSync(v3Dir)) {
2670
- fs.mkdirSync(v3Dir, { recursive: true });
2671
- fs.mkdirSync(path.join(v3Dir, 'agentdb'), { recursive: true });
2672
- fs.mkdirSync(path.join(v3Dir, 'reasoning-bank'), { recursive: true });
2673
- fs.writeFileSync(path.join(v3Dir, 'config.json'), JSON.stringify({
2674
- version: '3.0.0',
2675
- createdAt: new Date().toISOString(),
2676
- autoCreated: true,
2677
- }, null, 2));
2678
- console.log(chalk.green(' ✓ Created .aqe/ directory structure'));
2679
- fixedCount++;
2680
- }
2681
- // Fix 2: Migrate deprecated agents
2682
- if (deprecatedInUse.length > 0) {
2683
- const deprecatedDir = path.join(claudeAgentDir, 'deprecated');
2684
- if (!fs.existsSync(deprecatedDir)) {
2685
- fs.mkdirSync(deprecatedDir, { recursive: true });
2686
- }
2687
- for (const v2Name of deprecatedInUse) {
2688
- const v3Name = resolveAgentName(v2Name);
2689
- const v2FilePath = path.join(claudeAgentDir, `${v2Name}.md`);
2690
- const v3FilePath = path.join(claudeAgentDir, `${v3Name}.md`);
2691
- const deprecatedPath = path.join(deprecatedDir, `${v2Name}.md.v2`);
2692
- try {
2693
- const content = fs.readFileSync(v2FilePath, 'utf-8');
2694
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
2695
- if (frontmatterMatch) {
2696
- const frontmatter = frontmatterMatch[1];
2697
- const bodyStart = content.indexOf('---', 4) + 4;
2698
- let body = content.slice(bodyStart);
2699
- let newFrontmatter = frontmatter.replace(/^name:\s*.+$/m, `name: ${v3Name}`);
2700
- if (!newFrontmatter.includes('v2_compat:')) {
2701
- newFrontmatter += `\nv2_compat:\n name: ${v2Name}\n deprecated_in: "3.0.0"\n removed_in: "4.0.0"`;
2702
- }
2703
- // Update body content: replace old agent name references
2704
- const toTitleCase = (s) => s.replace('qe-', '').split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
2705
- body = body.replace(new RegExp(toTitleCase(v2Name), 'g'), toTitleCase(v3Name));
2706
- body = body.replace(new RegExp(v2Name, 'g'), v3Name);
2707
- const newContent = `---\n${newFrontmatter}\n---${body}`;
2708
- fs.writeFileSync(v3FilePath, newContent, 'utf-8');
2709
- fs.renameSync(v2FilePath, deprecatedPath);
2710
- console.log(chalk.green(` ✓ Migrated ${v2Name} → ${v3Name}`));
2711
- fixedCount++;
2712
- }
2713
- }
2714
- catch (err) {
2715
- console.log(chalk.red(` ✗ Failed to migrate ${v2Name}: ${err}`));
2716
- }
2717
- }
2718
- }
2719
- if (fixedCount > 0) {
2720
- console.log(chalk.green(`\n✅ Applied ${fixedCount} fixes. Re-run 'aqe migrate verify' to confirm.\n`));
2721
- }
2722
- else {
2723
- console.log(chalk.yellow('\n⚠️ No automatic fixes available for remaining issues.\n'));
2724
- }
2725
- }
2726
- else {
2727
- console.log(chalk.dim(' Run with --fix to attempt fixes.\n'));
2728
- }
2729
- }
2730
- await cleanupAndExit(0);
2731
- });
2732
- // migrate rollback - Rollback migration
2733
- migrateCmd
2734
- .command('rollback')
2735
- .description('Rollback to previous version from backup')
2736
- .option('--backup-id <id>', 'Specific backup to restore')
2737
- .option('--force', 'Skip confirmation')
2738
- .action(async (options) => {
2739
- const fs = await import('fs');
2740
- const path = await import('path');
2741
- const cwd = process.cwd();
2742
- const backupRoot = path.join(cwd, '.aqe-backup');
2743
- if (!fs.existsSync(backupRoot)) {
2744
- console.log(chalk.yellow('\n⚠️ No backups found.\n'));
2745
- return;
2746
- }
2747
- const backups = fs.readdirSync(backupRoot)
2748
- .filter(f => f.startsWith('backup-'))
2749
- .sort()
2750
- .reverse();
2751
- if (backups.length === 0) {
2752
- console.log(chalk.yellow('\n⚠️ No backups found.\n'));
2753
- return;
2754
- }
2755
- console.log(chalk.bold('\n📦 Available Backups\n'));
2756
- for (const backup of backups.slice(0, 5)) {
2757
- const timestamp = backup.replace('backup-', '');
2758
- const date = new Date(parseInt(timestamp));
2759
- console.log(` ${chalk.cyan(backup)} - ${date.toLocaleString()}`);
2760
- }
2761
- const targetBackup = options.backupId || backups[0];
2762
- const backupPath = path.join(backupRoot, targetBackup);
2763
- if (!fs.existsSync(backupPath)) {
2764
- console.log(chalk.red(`\n❌ Backup not found: ${targetBackup}\n`));
2765
- await cleanupAndExit(1);
2766
- }
2767
- if (!options.force) {
2768
- console.log(chalk.yellow(`\n⚠️ This will restore from: ${targetBackup}`));
2769
- console.log(chalk.dim(' Run with --force to confirm.\n'));
2770
- return;
2771
- }
2772
- console.log(chalk.bold(`\n🔄 Rolling back to ${targetBackup}...\n`));
2773
- // Restore backup
2774
- const v2Backup = path.join(backupPath, '.agentic-qe');
2775
- const agentsBackup = path.join(backupPath, '.claude', 'agents');
2776
- if (fs.existsSync(v2Backup)) {
2777
- const v2Dir = path.join(cwd, '.agentic-qe');
2778
- fs.cpSync(v2Backup, v2Dir, { recursive: true });
2779
- console.log(chalk.dim(' Restored .agentic-qe/'));
2780
- }
2781
- if (fs.existsSync(agentsBackup)) {
2782
- const agentsDir = path.join(cwd, '.claude', 'agents');
2783
- fs.cpSync(agentsBackup, agentsDir, { recursive: true });
2784
- console.log(chalk.dim(' Restored .claude/agents/'));
2785
- }
2786
- // Remove v3 directory
2787
- const v3Dir = path.join(cwd, '.aqe');
2788
- if (fs.existsSync(v3Dir)) {
2789
- fs.rmSync(v3Dir, { recursive: true, force: true });
2790
- console.log(chalk.dim(' Removed .aqe/'));
2791
- }
2792
- console.log(chalk.green('\n✅ Rollback complete!\n'));
2793
- await cleanupAndExit(0);
2794
- });
2795
- // migrate mapping - Show agent name mappings
2796
- migrateCmd
2797
- .command('mapping')
2798
- .description('Show v2 to v3 agent name mappings (ADR-048)')
2799
- .option('--json', 'Output as JSON')
2800
- .action(async (options) => {
2801
- if (options.json) {
2802
- console.log(JSON.stringify(v2AgentMapping, null, 2));
2803
- return;
2804
- }
2805
- console.log(chalk.bold('\n🔄 Agent Name Mappings (V2 → V3)\n'));
2806
- const entries = Object.entries(v2AgentMapping);
2807
- for (const [v2Name, v3Name] of entries) {
2808
- console.log(` ${chalk.yellow(v2Name)} → ${chalk.green(v3Name)}`);
2809
- }
2810
- console.log(chalk.dim(`\n Total: ${entries.length} mappings\n`));
2811
- console.log(chalk.gray(' See ADR-048 for full migration strategy.\n'));
2812
- await cleanupAndExit(0);
2813
- });
2814
- // ============================================================================
2815
- // Completions Command
2816
- // ============================================================================
2817
- const completionsCmd = program
2818
- .command('completions')
2819
- .description('Generate shell completions for aqe');
2820
- completionsCmd
2821
- .command('bash')
2822
- .description('Generate Bash completion script')
2823
- .action(() => {
2824
- console.log(generateCompletion('bash'));
2825
- });
2826
- completionsCmd
2827
- .command('zsh')
2828
- .description('Generate Zsh completion script')
2829
- .action(() => {
2830
- console.log(generateCompletion('zsh'));
2831
- });
2832
- completionsCmd
2833
- .command('fish')
2834
- .description('Generate Fish completion script')
2835
- .action(() => {
2836
- console.log(generateCompletion('fish'));
2837
- });
2838
- completionsCmd
2839
- .command('powershell')
2840
- .description('Generate PowerShell completion script')
2841
- .action(() => {
2842
- console.log(generateCompletion('powershell'));
2843
- });
2844
- completionsCmd
2845
- .command('install')
2846
- .description('Auto-install completions for current shell')
2847
- .option('-s, --shell <shell>', 'Target shell (bash|zsh|fish|powershell)')
2848
- .action(async (options) => {
2849
- const fs = await import('fs');
2850
- const path = await import('path');
2851
- const shellInfo = options.shell
2852
- ? { name: options.shell, configFile: null, detected: false }
2853
- : detectShell();
2854
- if (shellInfo.name === 'unknown') {
2855
- console.log(chalk.red('Could not detect shell. Please specify with --shell option.\n'));
2856
- console.log(getInstallInstructions('unknown'));
2857
- await cleanupAndExit(1);
2858
- return; // TypeScript flow control hint - cleanupAndExit exits but TS doesn't know
2859
- }
2860
- console.log(chalk.blue(`\nInstalling completions for ${shellInfo.name}...\n`));
2861
- const script = generateCompletion(shellInfo.name);
2862
- // For Fish, write directly to completions directory
2863
- if (shellInfo.name === 'fish') {
2864
- const fishCompletionsDir = `${process.env.HOME}/.config/fish/completions`;
2865
- try {
2866
- fs.mkdirSync(fishCompletionsDir, { recursive: true });
2867
- const completionFile = path.join(fishCompletionsDir, 'aqe.fish');
2868
- fs.writeFileSync(completionFile, script);
2869
- console.log(chalk.green(`Completions installed to: ${completionFile}`));
2870
- console.log(chalk.gray('\nRestart your shell or run: source ~/.config/fish/completions/aqe.fish\n'));
2871
- }
2872
- catch (err) {
2873
- console.log(chalk.red(`Failed to install: ${err}`));
2874
- console.log(chalk.yellow('\nManual installation:'));
2875
- console.log(getInstallInstructions('fish'));
2876
- }
2877
- }
2878
- else {
2879
- // For other shells, show instructions
2880
- console.log(chalk.yellow('To install completions, follow these instructions:\n'));
2881
- console.log(getInstallInstructions(shellInfo.name));
2882
- console.log(chalk.gray('\n---\nCompletion script:\n'));
2883
- console.log(script);
2884
- }
2885
- });
2886
- completionsCmd
2887
- .command('list')
2888
- .description('List all completion values (domains, agents, etc.)')
2889
- .option('-t, --type <type>', 'Type to list (domains|agents|v3-qe-agents)', 'all')
2890
- .action((options) => {
2891
- if (options.type === 'domains' || options.type === 'all') {
2892
- console.log(chalk.blue('\n12 DDD Domains:'));
2893
- COMPLETION_DOMAINS.forEach(d => console.log(chalk.gray(` ${d}`)));
2894
- }
2895
- if (options.type === 'v3-qe-agents' || options.type === 'all') {
2896
- console.log(chalk.blue('\nQE Agents (' + QE_AGENTS.length + '):'));
2897
- QE_AGENTS.forEach(a => console.log(chalk.gray(` ${a}`)));
2898
- }
2899
- if (options.type === 'agents' || options.type === 'all') {
2900
- console.log(chalk.blue('\nOther Agents (' + OTHER_AGENTS.length + '):'));
2901
- OTHER_AGENTS.forEach(a => console.log(chalk.gray(` ${a}`)));
2902
- }
2903
- console.log('');
2904
- });
2905
- // ============================================================================
2906
- // Fleet Command Group - Multi-agent operations with progress
2907
- // ============================================================================
2908
- const fleetCmd = program
2909
- .command('fleet')
2910
- .description('Fleet operations with multi-agent progress tracking');
2911
- // Fleet init with wizard (ADR-041)
2912
- fleetCmd
2913
- .command('init')
2914
- .description('Initialize fleet with interactive wizard')
2915
- .option('--wizard', 'Run interactive fleet initialization wizard')
2916
- .option('-t, --topology <type>', 'Fleet topology (hierarchical|mesh|ring|adaptive|hierarchical-mesh)', 'hierarchical-mesh')
2917
- .option('-m, --max-agents <count>', 'Maximum agent count (5-50)', '15')
2918
- .option('-d, --domains <domains>', 'Domains to enable (comma-separated or "all")', 'all')
2919
- .option('--memory <backend>', 'Memory backend (sqlite|agentdb|hybrid)', 'hybrid')
2920
- .option('--lazy', 'Enable lazy loading', true)
2921
- .option('--skip-patterns', 'Skip loading pre-trained patterns')
2922
- .option('--skip-code-scan', 'Skip code intelligence index check')
2923
- .action(async (options) => {
2924
- try {
2925
- let topology = options.topology;
2926
- let maxAgents = parseInt(options.maxAgents, 10);
2927
- let domains = options.domains;
2928
- let memoryBackend = options.memory;
2929
- let lazyLoading = options.lazy;
2930
- let loadPatterns = !options.skipPatterns;
2931
- // CI-005: Check code intelligence index before fleet initialization
2932
- console.log(chalk.blue('\n 🧠 Code Intelligence Check\n'));
2933
- const ciResult = await integrateCodeIntelligence(process.cwd(), {
2934
- skipCodeScan: options.skipCodeScan,
2935
- nonInteractive: !options.wizard, // Only prompt in wizard mode
2936
- });
2937
- // If user requested scan, exit and let them run it
2938
- if (!ciResult.shouldProceed) {
2939
- console.log(chalk.blue('\n Please run the code intelligence scan first:'));
2940
- console.log(chalk.cyan(' aqe code-intelligence index\n'));
2941
- console.log(chalk.gray(' Then re-run fleet init when ready.\n'));
2942
- await cleanupAndExit(0);
2943
- return;
2944
- }
2945
- // Run wizard if requested (ADR-041)
2946
- if (options.wizard) {
2947
- console.log(chalk.blue('\n🚀 Fleet Initialization Wizard\n'));
2948
- const wizardResult = await runFleetInitWizard({
2949
- defaultTopology: options.topology !== 'hierarchical-mesh' ? options.topology : undefined,
2950
- defaultMaxAgents: options.maxAgents !== '15' ? parseInt(options.maxAgents, 10) : undefined,
2951
- defaultDomains: options.domains !== 'all' ? options.domains.split(',') : undefined,
2952
- defaultMemoryBackend: options.memory !== 'hybrid' ? options.memory : undefined,
2953
- });
2954
- if (wizardResult.cancelled) {
2955
- console.log(chalk.yellow('\n Fleet initialization cancelled.\n'));
2956
- await cleanupAndExit(0);
2957
- }
2958
- // Use wizard results
2959
- topology = wizardResult.topology;
2960
- maxAgents = wizardResult.maxAgents;
2961
- domains = wizardResult.domains.join(',');
2962
- memoryBackend = wizardResult.memoryBackend;
2963
- lazyLoading = wizardResult.lazyLoading;
2964
- loadPatterns = wizardResult.loadPatterns;
2965
- console.log(chalk.green('\n Starting fleet initialization...\n'));
2966
- }
2967
- // Parse domains
2968
- const enabledDomains = domains === 'all'
2969
- ? [...ALL_DOMAINS]
2970
- : domains.split(',').filter((d) => ALL_DOMAINS.includes(d));
2971
- console.log(chalk.blue('\n Fleet Configuration\n'));
2972
- console.log(chalk.gray(` Topology: ${topology}`));
2973
- console.log(chalk.gray(` Max Agents: ${maxAgents}`));
2974
- console.log(chalk.gray(` Domains: ${enabledDomains.length}`));
2975
- console.log(chalk.gray(` Memory: ${memoryBackend}`));
2976
- console.log(chalk.gray(` Lazy Loading: ${lazyLoading ? 'enabled' : 'disabled'}`));
2977
- console.log(chalk.gray(` Pre-trained Patterns: ${loadPatterns ? 'load' : 'skip'}\n`));
2978
- // Initialize if not already done
2979
- if (!context.initialized) {
2980
- context.kernel = new QEKernelImpl({
2981
- maxConcurrentAgents: maxAgents,
2982
- memoryBackend,
2983
- hnswEnabled: true,
2984
- lazyLoading,
2985
- enabledDomains,
2986
- });
2987
- await context.kernel.initialize();
2988
- console.log(chalk.green(' ✓ Kernel initialized'));
2989
- context.router = new CrossDomainEventRouter(context.kernel.eventBus);
2990
- await context.router.initialize();
2991
- console.log(chalk.green(' ✓ Cross-domain router initialized'));
2992
- context.workflowOrchestrator = new WorkflowOrchestrator(context.kernel.eventBus, context.kernel.memory, context.kernel.coordinator);
2993
- await context.workflowOrchestrator.initialize();
2994
- // Register domain workflow actions (Issue #206)
2995
- registerDomainWorkflowActions(context.kernel, context.workflowOrchestrator);
2996
- console.log(chalk.green(' ✓ Workflow orchestrator initialized'));
2997
- context.persistentScheduler = createPersistentScheduler();
2998
- console.log(chalk.green(' ✓ Persistent scheduler initialized'));
2999
- const getDomainAPI = (domain) => {
3000
- return context.kernel.getDomainAPI(domain);
3001
- };
3002
- const protocolExecutor = new DefaultProtocolExecutor(context.kernel.eventBus, context.kernel.memory, getDomainAPI);
3003
- context.queen = createQueenCoordinator(context.kernel, context.router, protocolExecutor, undefined);
3004
- await context.queen.initialize();
3005
- console.log(chalk.green(' ✓ Queen coordinator initialized'));
3006
- context.initialized = true;
3007
- }
3008
- console.log(chalk.green('\n✅ Fleet initialized successfully!\n'));
3009
- console.log(chalk.white('Next steps:'));
3010
- console.log(chalk.gray(' 1. Spawn agents: aqe fleet spawn --domains test-generation'));
3011
- console.log(chalk.gray(' 2. Run operation: aqe fleet run test --target ./src'));
3012
- console.log(chalk.gray(' 3. Check status: aqe fleet status\n'));
3013
- await cleanupAndExit(0);
3014
- }
3015
- catch (error) {
3016
- console.error(chalk.red('\n Fleet initialization failed:'), error);
3017
- await cleanupAndExit(1);
3018
- }
3019
- });
3020
- fleetCmd
3021
- .command('spawn')
3022
- .description('Spawn multiple agents with progress tracking')
3023
- .option('-d, --domains <domains>', 'Comma-separated domains', 'test-generation,coverage-analysis')
3024
- .option('-t, --type <type>', 'Agent type for all', 'worker')
3025
- .option('-c, --count <count>', 'Number of agents per domain', '1')
3026
- .action(async (options) => {
3027
- if (!await ensureInitialized())
3028
- return;
3029
- try {
3030
- const domains = options.domains.split(',');
3031
- const countPerDomain = parseInt(options.count, 10);
3032
- console.log(chalk.blue('\n Fleet Spawn Operation\n'));
3033
- // Create fleet progress manager
3034
- const progress = new FleetProgressManager({
3035
- title: 'Agent Spawn Progress',
3036
- showEta: true,
3037
- });
3038
- const totalAgents = domains.length * countPerDomain;
3039
- progress.start(totalAgents);
3040
- // Track spawned agents
3041
- const spawnedAgents = [];
3042
- let agentIndex = 0;
3043
- // Spawn agents across domains
3044
- for (const domain of domains) {
3045
- for (let i = 0; i < countPerDomain; i++) {
3046
- const agentName = `${domain}-${options.type}-${i + 1}`;
3047
- const agentId = `agent-${agentIndex++}`;
3048
- // Add agent to progress tracker
3049
- progress.addAgent({
3050
- id: agentId,
3051
- name: agentName,
3052
- status: 'pending',
3053
- progress: 0,
3054
- });
3055
- // Update to running
3056
- progress.updateAgent(agentId, 10, { status: 'running' });
3057
- try {
3058
- // Spawn the agent
3059
- progress.updateAgent(agentId, 30, { message: 'Initializing...' });
3060
- const result = await context.queen.requestAgentSpawn(domain, options.type, ['general']);
3061
- progress.updateAgent(agentId, 80, { message: 'Configuring...' });
3062
- if (result.success) {
3063
- progress.completeAgent(agentId, true);
3064
- spawnedAgents.push({ id: result.value, domain, success: true });
3065
- }
3066
- else {
3067
- progress.completeAgent(agentId, false);
3068
- spawnedAgents.push({ id: agentId, domain, success: false });
3069
- }
3070
- }
3071
- catch {
3072
- progress.completeAgent(agentId, false);
3073
- spawnedAgents.push({ id: agentId, domain, success: false });
3074
- }
3075
- }
3076
- }
3077
- progress.stop();
3078
- // Summary
3079
- const successful = spawnedAgents.filter(a => a.success).length;
3080
- const failed = spawnedAgents.filter(a => !a.success).length;
3081
- console.log(chalk.blue('\n Fleet Summary:'));
3082
- console.log(chalk.gray(` Domains: ${domains.join(', ')}`));
3083
- console.log(chalk.green(` Successful: ${successful}`));
3084
- if (failed > 0) {
3085
- console.log(chalk.red(` Failed: ${failed}`));
3086
- }
3087
- console.log('');
3088
- await cleanupAndExit(failed > 0 ? 1 : 0);
3089
- }
3090
- catch (error) {
3091
- console.error(chalk.red('\n Fleet spawn failed:'), error);
3092
- await cleanupAndExit(1);
3093
- }
3094
- });
3095
- fleetCmd
3096
- .command('run')
3097
- .description('Run a coordinated fleet operation')
3098
- .argument('<operation>', 'Operation type (test|analyze|scan)')
3099
- .option('-t, --target <path>', 'Target path', '.')
3100
- .option('--parallel <count>', 'Number of parallel agents', '4')
3101
- .action(async (operation, options) => {
3102
- if (!await ensureInitialized())
3103
- return;
3104
- try {
3105
- const parallelCount = parseInt(options.parallel, 10);
3106
- console.log(chalk.blue(`\n Fleet Operation: ${operation}\n`));
3107
- // Create fleet progress manager
3108
- const progress = new FleetProgressManager({
3109
- title: `${operation.charAt(0).toUpperCase() + operation.slice(1)} Progress`,
3110
- showEta: true,
3111
- });
3112
- progress.start(parallelCount);
3113
- // Define agent operations based on operation type
3114
- const domainMap = {
3115
- test: 'test-generation',
3116
- analyze: 'coverage-analysis',
3117
- scan: 'security-compliance',
3118
- };
3119
- const domain = domainMap[operation] || 'test-generation';
3120
- // Create parallel agent operations
3121
- const agentOperations = Array.from({ length: parallelCount }, (_, i) => {
3122
- const agentId = `${operation}-agent-${i + 1}`;
3123
- return {
3124
- id: agentId,
3125
- name: `${operation}-worker-${i + 1}`,
3126
- domain,
3127
- };
3128
- });
3129
- // Add all agents to progress
3130
- for (const op of agentOperations) {
3131
- progress.addAgent({
3132
- id: op.id,
3133
- name: op.name,
3134
- status: 'pending',
3135
- progress: 0,
3136
- });
3137
- }
3138
- // Execute operations in parallel with progress updates
3139
- const results = await Promise.all(agentOperations.map(async (op, index) => {
3140
- // Simulate staggered start
3141
- await new Promise(resolve => setTimeout(resolve, index * 200));
3142
- progress.updateAgent(op.id, 0, { status: 'running' });
3143
- try {
3144
- // Simulate operation phases with progress updates
3145
- for (let p = 10; p <= 90; p += 20) {
3146
- await new Promise(resolve => setTimeout(resolve, 300 + Math.random() * 200));
3147
- progress.updateAgent(op.id, p, {
3148
- eta: Math.round((100 - p) * 50),
3149
- });
3150
- }
3151
- // Submit actual task
3152
- const taskResult = await context.queen.submitTask({
3153
- type: operation === 'test' ? 'generate-tests' :
3154
- operation === 'analyze' ? 'analyze-coverage' :
3155
- 'scan-security',
3156
- priority: 'p1',
3157
- targetDomains: [domain],
3158
- payload: { target: options.target, workerId: op.id },
3159
- timeout: 60000,
3160
- });
3161
- progress.completeAgent(op.id, taskResult.success);
3162
- return { id: op.id, success: taskResult.success };
3163
- }
3164
- catch {
3165
- progress.completeAgent(op.id, false);
3166
- return { id: op.id, success: false };
3167
- }
3168
- }));
3169
- progress.stop();
3170
- // Summary
3171
- const successful = results.filter(r => r.success).length;
3172
- const failed = results.filter(r => !r.success).length;
3173
- console.log(chalk.blue('\n Operation Summary:'));
3174
- console.log(chalk.gray(` Operation: ${operation}`));
3175
- console.log(chalk.gray(` Target: ${options.target}`));
3176
- console.log(chalk.green(` Successful: ${successful}`));
3177
- if (failed > 0) {
3178
- console.log(chalk.red(` Failed: ${failed}`));
3179
- }
3180
- console.log('');
3181
- await cleanupAndExit(failed > 0 ? 1 : 0);
3182
- }
3183
- catch (error) {
3184
- console.error(chalk.red('\n Fleet operation failed:'), error);
3185
- await cleanupAndExit(1);
3186
- }
3187
- });
3188
- fleetCmd
3189
- .command('status')
3190
- .description('Show fleet status with agent progress')
3191
- .option('-w, --watch', 'Watch mode with live updates')
3192
- .action(async (options) => {
3193
- if (!await ensureInitialized())
3194
- return;
3195
- try {
3196
- const showStatus = async () => {
3197
- const health = context.queen.getHealth();
3198
- const metrics = context.queen.getMetrics();
3199
- console.log(chalk.blue('\n Fleet Status\n'));
3200
- // Overall fleet bar
3201
- const utilizationBar = '\u2588'.repeat(Math.min(Math.round(metrics.agentUtilization * 20), 20)) +
3202
- '\u2591'.repeat(Math.max(20 - Math.round(metrics.agentUtilization * 20), 0));
3203
- console.log(chalk.white(`Fleet Utilization ${chalk.cyan(utilizationBar)} ${(metrics.agentUtilization * 100).toFixed(0)}%`));
3204
- console.log('');
3205
- // Agent status by domain
3206
- console.log(chalk.white('Agent Progress:'));
3207
- for (const [domain, domainHealth] of health.domainHealth) {
3208
- const active = domainHealth.agents.active;
3209
- const total = domainHealth.agents.total;
3210
- const progressPercent = total > 0 ? Math.round((active / total) * 100) : 0;
3211
- const statusIcon = domainHealth.status === 'healthy' ? chalk.green('\u2713') :
3212
- domainHealth.status === 'degraded' ? chalk.yellow('\u25B6') :
3213
- chalk.red('\u2717');
3214
- const bar = '\u2588'.repeat(Math.round(progressPercent / 5)) +
3215
- '\u2591'.repeat(20 - Math.round(progressPercent / 5));
3216
- console.log(` ${domain.padEnd(28)} ${chalk.cyan(bar)} ${progressPercent.toString().padStart(3)}% ${statusIcon}`);
3217
- }
3218
- console.log('');
3219
- console.log(chalk.gray(` Active: ${health.activeAgents}/${health.totalAgents} agents`));
3220
- console.log(chalk.gray(` Tasks: ${health.runningTasks} running, ${health.pendingTasks} pending`));
3221
- console.log('');
3222
- };
3223
- if (options.watch) {
3224
- const spinner = createTimedSpinner('Watching fleet status (Ctrl+C to exit)');
3225
- // Initial display
3226
- spinner.spinner.stop();
3227
- await showStatus();
3228
- // Watch mode - update every 2 seconds
3229
- const interval = setInterval(async () => {
3230
- console.clear();
3231
- await showStatus();
3232
- }, 2000);
3233
- // Handle Ctrl+C - use once to avoid conflict with global handler
3234
- process.once('SIGINT', async () => {
3235
- clearInterval(interval);
3236
- console.log(chalk.yellow('\nStopped watching.'));
3237
- await cleanupAndExit(0);
3238
- });
3239
- }
3240
- else {
3241
- await showStatus();
3242
- await cleanupAndExit(0);
3243
- }
3244
- }
3245
- catch (error) {
3246
- console.error(chalk.red('\n Failed to get fleet status:'), error);
3247
- await cleanupAndExit(1);
3248
- }
3249
- });
3250
- // ============================================================================
3251
- // Hooks Command (AQE v3 Independent Hooks - using QEHookRegistry)
623
+ // External Command Modules
3252
624
  // ============================================================================
625
+ import { createTokenUsageCommand } from './commands/token-usage.js';
626
+ import { createLLMRouterCommand } from './commands/llm-router.js';
627
+ import { createSyncCommands } from './commands/sync.js';
3253
628
  import { createHooksCommand } from './commands/hooks.js';
3254
- // Register the hooks command from the proper module (uses QEHookRegistry)
3255
- const hooksCmd = createHooksCommand();
3256
- program.addCommand(hooksCmd);
3257
- // Note: All hooks functionality is now in ./commands/hooks.ts which uses:
3258
- // - QEHookRegistry for event handling
3259
- // - QEReasoningBank for pattern learning
3260
- // - setupQEHooks() for proper initialization
629
+ program.addCommand(createTokenUsageCommand());
630
+ program.addCommand(createLLMRouterCommand());
631
+ program.addCommand(createSyncCommands());
632
+ program.addCommand(createHooksCommand());
3261
633
  // ============================================================================
3262
634
  // Shutdown Handlers
3263
635
  // ============================================================================
@@ -3274,7 +646,6 @@ process.on('SIGTERM', async () => {
3274
646
  // Main
3275
647
  // ============================================================================
3276
648
  async function main() {
3277
- // ADR-042: Initialize token tracking and optimization
3278
649
  await bootstrapTokenTracking({
3279
650
  enableOptimization: true,
3280
651
  enablePersistence: true,