@monoes/monomindcli 1.14.7 → 1.15.1

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 (329) hide show
  1. package/.claude/agents/reengineer-squad/boss.md +113 -0
  2. package/.claude/agents/reengineer-squad/critic-architect.md +132 -0
  3. package/.claude/agents/reengineer-squad/git-manager.md +145 -0
  4. package/.claude/agents/reengineer-squad/idea-generator.md +95 -0
  5. package/.claude/agents/reengineer-squad/implementer.md +112 -0
  6. package/.claude/agents/reengineer-squad/integration-planner.md +112 -0
  7. package/.claude/agents/reengineer-squad/source-analyst.md +103 -0
  8. package/.claude/agents/reengineer-squad/target-analyst.md +118 -0
  9. package/.claude/agents/reengineer-squad/tester.md +105 -0
  10. package/.claude/commands/mastermind/master.md +35 -14
  11. package/.claude/helpers/handlers/capture-handler.cjs +155 -18
  12. package/.claude/helpers/monolean-activate.cjs +20 -0
  13. package/.claude/helpers/monolean-config.cjs +76 -0
  14. package/.claude/helpers/monolean-instructions.cjs +109 -0
  15. package/.claude/helpers/monolean-propagate.cjs +9 -0
  16. package/.claude/helpers/monolean-tracker.cjs +18 -0
  17. package/.claude/helpers/skill-registry.json +2 -2
  18. package/.claude/skills/agent-browser-testing/SKILL.md +301 -18
  19. package/.claude/skills/mastermind/runorg.md +69 -23
  20. package/.claude/skills/monodesign/SKILL.md +32 -1
  21. package/.claude/skills/monodesign/adapt.md +53 -0
  22. package/.claude/skills/monodesign/agents/monodesign-asset-producer.md +100 -0
  23. package/.claude/skills/monodesign/animate.md +65 -0
  24. package/.claude/skills/monodesign/audit.md +89 -0
  25. package/.claude/skills/monodesign/bolder.md +50 -0
  26. package/.claude/skills/monodesign/clarify.md +64 -0
  27. package/.claude/skills/monodesign/colorize.md +68 -0
  28. package/.claude/skills/monodesign/craft.md +51 -0
  29. package/.claude/skills/monodesign/critique.md +66 -0
  30. package/.claude/skills/monodesign/delight.md +47 -0
  31. package/.claude/skills/monodesign/distill.md +56 -0
  32. package/.claude/skills/monodesign/document.md +80 -0
  33. package/.claude/skills/monodesign/extract.md +74 -0
  34. package/.claude/skills/monodesign/harden.md +65 -0
  35. package/.claude/skills/monodesign/live.md +59 -0
  36. package/.claude/skills/monodesign/onboard.md +50 -0
  37. package/.claude/skills/monodesign/optimize.md +64 -0
  38. package/.claude/skills/monodesign/overdrive.md +56 -0
  39. package/.claude/skills/monodesign/polish.md +68 -0
  40. package/.claude/skills/monodesign/quieter.md +57 -0
  41. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +248 -76
  42. package/.claude/skills/monodesign/reference/codex.md +107 -0
  43. package/.claude/skills/monodesign/reference/craft.md +3 -0
  44. package/.claude/skills/monodesign/reference/hooks.md +99 -0
  45. package/.claude/skills/monodesign/reference/image-prompts.md +12 -0
  46. package/.claude/skills/monodesign/shape.md +71 -0
  47. package/.claude/skills/monodesign/teach.md +69 -0
  48. package/.claude/skills/monodesign/typeset.md +59 -0
  49. package/.claude/skills/monolean/SKILL.md +118 -0
  50. package/.claude/skills/monolean-audit/SKILL.md +41 -0
  51. package/.claude/skills/monolean-debt/SKILL.md +46 -0
  52. package/.claude/skills/monolean-help/SKILL.md +60 -0
  53. package/.claude/skills/monolean-review/SKILL.md +57 -0
  54. package/bin/cli.js +3 -1
  55. package/dist/dashboard/server.js +137 -0
  56. package/dist/src/__tests__/browse-adapters.test.d.ts +2 -0
  57. package/dist/src/__tests__/browse-adapters.test.d.ts.map +1 -0
  58. package/dist/src/__tests__/browse-adapters.test.js +51 -0
  59. package/dist/src/__tests__/browse-adapters.test.js.map +1 -0
  60. package/dist/src/__tests__/browse-analyzer.test.d.ts +2 -0
  61. package/dist/src/__tests__/browse-analyzer.test.d.ts.map +1 -0
  62. package/dist/src/__tests__/browse-analyzer.test.js +68 -0
  63. package/dist/src/__tests__/browse-analyzer.test.js.map +1 -0
  64. package/dist/src/__tests__/browse-builtin-handlers.test.d.ts +2 -0
  65. package/dist/src/__tests__/browse-builtin-handlers.test.d.ts.map +1 -0
  66. package/dist/src/__tests__/browse-builtin-handlers.test.js +139 -0
  67. package/dist/src/__tests__/browse-builtin-handlers.test.js.map +1 -0
  68. package/dist/src/__tests__/browse-cdp.test.d.ts +2 -0
  69. package/dist/src/__tests__/browse-cdp.test.d.ts.map +1 -0
  70. package/dist/src/__tests__/browse-cdp.test.js +169 -0
  71. package/dist/src/__tests__/browse-cdp.test.js.map +1 -0
  72. package/dist/src/__tests__/browse-dashboard.test.d.ts +2 -0
  73. package/dist/src/__tests__/browse-dashboard.test.d.ts.map +1 -0
  74. package/dist/src/__tests__/browse-dashboard.test.js +179 -0
  75. package/dist/src/__tests__/browse-dashboard.test.js.map +1 -0
  76. package/dist/src/__tests__/browse-engine.test.d.ts +2 -0
  77. package/dist/src/__tests__/browse-engine.test.d.ts.map +1 -0
  78. package/dist/src/__tests__/browse-engine.test.js +122 -0
  79. package/dist/src/__tests__/browse-engine.test.js.map +1 -0
  80. package/dist/src/__tests__/browse-expression.test.d.ts +2 -0
  81. package/dist/src/__tests__/browse-expression.test.d.ts.map +1 -0
  82. package/dist/src/__tests__/browse-expression.test.js +54 -0
  83. package/dist/src/__tests__/browse-expression.test.js.map +1 -0
  84. package/dist/src/__tests__/browse-store.test.d.ts +2 -0
  85. package/dist/src/__tests__/browse-store.test.d.ts.map +1 -0
  86. package/dist/src/__tests__/browse-store.test.js +99 -0
  87. package/dist/src/__tests__/browse-store.test.js.map +1 -0
  88. package/dist/src/__tests__/browse-workflow-types.test.d.ts +2 -0
  89. package/dist/src/__tests__/browse-workflow-types.test.d.ts.map +1 -0
  90. package/dist/src/__tests__/browse-workflow-types.test.js +33 -0
  91. package/dist/src/__tests__/browse-workflow-types.test.js.map +1 -0
  92. package/dist/src/browser/action-builder/analyzer.d.ts +11 -0
  93. package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -0
  94. package/dist/src/browser/action-builder/analyzer.js +71 -0
  95. package/dist/src/browser/action-builder/analyzer.js.map +1 -0
  96. package/dist/src/browser/action-builder/types.d.ts +47 -0
  97. package/dist/src/browser/action-builder/types.d.ts.map +1 -0
  98. package/dist/src/browser/action-builder/types.js +2 -0
  99. package/dist/src/browser/action-builder/types.js.map +1 -0
  100. package/dist/src/browser/adapters/gemini.d.ts +3 -0
  101. package/dist/src/browser/adapters/gemini.d.ts.map +1 -0
  102. package/dist/src/browser/adapters/gemini.js +16 -0
  103. package/dist/src/browser/adapters/gemini.js.map +1 -0
  104. package/dist/src/browser/adapters/google.d.ts +3 -0
  105. package/dist/src/browser/adapters/google.d.ts.map +1 -0
  106. package/dist/src/browser/adapters/google.js +17 -0
  107. package/dist/src/browser/adapters/google.js.map +1 -0
  108. package/dist/src/browser/adapters/index.d.ts +19 -0
  109. package/dist/src/browser/adapters/index.d.ts.map +1 -0
  110. package/dist/src/browser/adapters/index.js +23 -0
  111. package/dist/src/browser/adapters/index.js.map +1 -0
  112. package/dist/src/browser/adapters/instagram.d.ts +3 -0
  113. package/dist/src/browser/adapters/instagram.d.ts.map +1 -0
  114. package/dist/src/browser/adapters/instagram.js +17 -0
  115. package/dist/src/browser/adapters/instagram.js.map +1 -0
  116. package/dist/src/browser/adapters/linkedin.d.ts +3 -0
  117. package/dist/src/browser/adapters/linkedin.d.ts.map +1 -0
  118. package/dist/src/browser/adapters/linkedin.js +19 -0
  119. package/dist/src/browser/adapters/linkedin.js.map +1 -0
  120. package/dist/src/browser/adapters/microsoft.d.ts +3 -0
  121. package/dist/src/browser/adapters/microsoft.d.ts.map +1 -0
  122. package/dist/src/browser/adapters/microsoft.js +16 -0
  123. package/dist/src/browser/adapters/microsoft.js.map +1 -0
  124. package/dist/src/browser/adapters/x.d.ts +3 -0
  125. package/dist/src/browser/adapters/x.d.ts.map +1 -0
  126. package/dist/src/browser/adapters/x.js +19 -0
  127. package/dist/src/browser/adapters/x.js.map +1 -0
  128. package/dist/src/browser/dashboard/api-types.d.ts +50 -0
  129. package/dist/src/browser/dashboard/api-types.d.ts.map +1 -0
  130. package/dist/src/browser/dashboard/api-types.js +14 -0
  131. package/dist/src/browser/dashboard/api-types.js.map +1 -0
  132. package/dist/src/browser/dashboard/server.d.ts +9 -0
  133. package/dist/src/browser/dashboard/server.d.ts.map +1 -0
  134. package/dist/src/browser/dashboard/server.js +62 -0
  135. package/dist/src/browser/dashboard/server.js.map +1 -0
  136. package/dist/src/browser/dashboard/ui.html +1811 -0
  137. package/dist/src/browser/workflow/builtin-handlers.d.ts +3 -0
  138. package/dist/src/browser/workflow/builtin-handlers.d.ts.map +1 -0
  139. package/dist/src/browser/workflow/builtin-handlers.js +343 -0
  140. package/dist/src/browser/workflow/builtin-handlers.js.map +1 -0
  141. package/dist/src/browser/workflow/engine.d.ts +15 -0
  142. package/dist/src/browser/workflow/engine.d.ts.map +1 -0
  143. package/dist/src/browser/workflow/engine.js +127 -0
  144. package/dist/src/browser/workflow/engine.js.map +1 -0
  145. package/dist/src/browser/workflow/expression.d.ts +4 -0
  146. package/dist/src/browser/workflow/expression.d.ts.map +1 -0
  147. package/dist/src/browser/workflow/expression.js +64 -0
  148. package/dist/src/browser/workflow/expression.js.map +1 -0
  149. package/dist/src/browser/workflow/store.d.ts +24 -0
  150. package/dist/src/browser/workflow/store.d.ts.map +1 -0
  151. package/dist/src/browser/workflow/store.js +145 -0
  152. package/dist/src/browser/workflow/store.js.map +1 -0
  153. package/dist/src/browser/workflow/types.d.ts +48 -0
  154. package/dist/src/browser/workflow/types.d.ts.map +1 -0
  155. package/dist/src/browser/workflow/types.js +2 -0
  156. package/dist/src/browser/workflow/types.js.map +1 -0
  157. package/dist/src/commands/browse-action.d.ts +4 -0
  158. package/dist/src/commands/browse-action.d.ts.map +1 -0
  159. package/dist/src/commands/browse-action.js +151 -0
  160. package/dist/src/commands/browse-action.js.map +1 -0
  161. package/dist/src/commands/browse-platform.d.ts +4 -0
  162. package/dist/src/commands/browse-platform.d.ts.map +1 -0
  163. package/dist/src/commands/browse-platform.js +117 -0
  164. package/dist/src/commands/browse-platform.js.map +1 -0
  165. package/dist/src/commands/browse-workflow.d.ts +4 -0
  166. package/dist/src/commands/browse-workflow.d.ts.map +1 -0
  167. package/dist/src/commands/browse-workflow.js +153 -0
  168. package/dist/src/commands/browse-workflow.js.map +1 -0
  169. package/dist/src/commands/browse.d.ts +10 -6
  170. package/dist/src/commands/browse.d.ts.map +1 -1
  171. package/dist/src/commands/browse.js +11 -2154
  172. package/dist/src/commands/browse.js.map +1 -1
  173. package/dist/src/commands/design-detect.d.ts +21 -0
  174. package/dist/src/commands/design-detect.d.ts.map +1 -0
  175. package/dist/src/commands/design-detect.js +127 -0
  176. package/dist/src/commands/design-detect.js.map +1 -0
  177. package/dist/src/commands/design-palette.d.ts +22 -0
  178. package/dist/src/commands/design-palette.d.ts.map +1 -0
  179. package/dist/src/commands/design-palette.js +539 -0
  180. package/dist/src/commands/design-palette.js.map +1 -0
  181. package/dist/src/commands/hooks-core-commands.d.ts +10 -0
  182. package/dist/src/commands/hooks-core-commands.d.ts.map +1 -0
  183. package/dist/src/commands/hooks-core-commands.js +377 -0
  184. package/dist/src/commands/hooks-core-commands.js.map +1 -0
  185. package/dist/src/commands/hooks-coverage-commands.d.ts +12 -0
  186. package/dist/src/commands/hooks-coverage-commands.d.ts.map +1 -0
  187. package/dist/src/commands/hooks-coverage-commands.js +1217 -0
  188. package/dist/src/commands/hooks-coverage-commands.js.map +1 -0
  189. package/dist/src/commands/hooks-coverage-utils.d.ts +42 -0
  190. package/dist/src/commands/hooks-coverage-utils.d.ts.map +1 -0
  191. package/dist/src/commands/hooks-coverage-utils.js +220 -0
  192. package/dist/src/commands/hooks-coverage-utils.js.map +1 -0
  193. package/dist/src/commands/hooks-extended-commands.d.ts +14 -0
  194. package/dist/src/commands/hooks-extended-commands.d.ts.map +1 -0
  195. package/dist/src/commands/hooks-extended-commands.js +579 -0
  196. package/dist/src/commands/hooks-extended-commands.js.map +1 -0
  197. package/dist/src/commands/hooks-formatting.d.ts +13 -0
  198. package/dist/src/commands/hooks-formatting.d.ts.map +1 -0
  199. package/dist/src/commands/hooks-formatting.js +42 -0
  200. package/dist/src/commands/hooks-formatting.js.map +1 -0
  201. package/dist/src/commands/hooks-routing-commands.d.ts +15 -0
  202. package/dist/src/commands/hooks-routing-commands.d.ts.map +1 -0
  203. package/dist/src/commands/hooks-routing-commands.js +723 -0
  204. package/dist/src/commands/hooks-routing-commands.js.map +1 -0
  205. package/dist/src/commands/hooks-workers.d.ts +9 -0
  206. package/dist/src/commands/hooks-workers.d.ts.map +1 -0
  207. package/dist/src/commands/hooks-workers.js +782 -0
  208. package/dist/src/commands/hooks-workers.js.map +1 -0
  209. package/dist/src/commands/hooks.d.ts +8 -0
  210. package/dist/src/commands/hooks.d.ts.map +1 -1
  211. package/dist/src/commands/hooks.js +179 -4103
  212. package/dist/src/commands/hooks.js.map +1 -1
  213. package/dist/src/commands/index.d.ts +1 -0
  214. package/dist/src/commands/index.d.ts.map +1 -1
  215. package/dist/src/commands/index.js +6 -0
  216. package/dist/src/commands/index.js.map +1 -1
  217. package/dist/src/commands/org.d.ts.map +1 -1
  218. package/dist/src/commands/org.js +14 -15
  219. package/dist/src/commands/org.js.map +1 -1
  220. package/dist/src/commands/tokens.d.ts.map +1 -1
  221. package/dist/src/commands/tokens.js +77 -1
  222. package/dist/src/commands/tokens.js.map +1 -1
  223. package/dist/src/init/executor.d.ts.map +1 -1
  224. package/dist/src/init/executor.js +18 -8
  225. package/dist/src/init/executor.js.map +1 -1
  226. package/dist/src/init/settings-generator.d.ts.map +1 -1
  227. package/dist/src/init/settings-generator.js +39 -5
  228. package/dist/src/init/settings-generator.js.map +1 -1
  229. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  230. package/dist/src/init/statusline-generator.js +25 -5
  231. package/dist/src/init/statusline-generator.js.map +1 -1
  232. package/dist/src/mcp-tools/browser-tools.d.ts +3 -5
  233. package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
  234. package/dist/src/mcp-tools/browser-tools.js +619 -326
  235. package/dist/src/mcp-tools/browser-tools.js.map +1 -1
  236. package/dist/src/mcp-tools/hooks-embedding.d.ts +161 -0
  237. package/dist/src/mcp-tools/hooks-embedding.d.ts.map +1 -0
  238. package/dist/src/mcp-tools/hooks-embedding.js +506 -0
  239. package/dist/src/mcp-tools/hooks-embedding.js.map +1 -0
  240. package/dist/src/mcp-tools/hooks-intelligence.d.ts +26 -0
  241. package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -0
  242. package/dist/src/mcp-tools/hooks-intelligence.js +1328 -0
  243. package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -0
  244. package/dist/src/mcp-tools/hooks-routing.d.ts +27 -0
  245. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -0
  246. package/dist/src/mcp-tools/hooks-routing.js +1591 -0
  247. package/dist/src/mcp-tools/hooks-routing.js.map +1 -0
  248. package/dist/src/mcp-tools/hooks-tools.d.ts +3 -38
  249. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  250. package/dist/src/mcp-tools/hooks-tools.js +5 -3393
  251. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  252. package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
  253. package/dist/src/mcp-tools/monograph-tools.js +24 -14
  254. package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
  255. package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
  256. package/dist/src/mcp-tools/workflow-tools.js +54 -1
  257. package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
  258. package/dist/src/memory/embedding-operations.d.ts +58 -0
  259. package/dist/src/memory/embedding-operations.d.ts.map +1 -0
  260. package/dist/src/memory/embedding-operations.js +299 -0
  261. package/dist/src/memory/embedding-operations.js.map +1 -0
  262. package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
  263. package/dist/src/memory/ewc-consolidation.js +37 -3
  264. package/dist/src/memory/ewc-consolidation.js.map +1 -1
  265. package/dist/src/memory/hnsw-operations.d.ts +130 -0
  266. package/dist/src/memory/hnsw-operations.d.ts.map +1 -0
  267. package/dist/src/memory/hnsw-operations.js +400 -0
  268. package/dist/src/memory/hnsw-operations.js.map +1 -0
  269. package/dist/src/memory/intelligence.d.ts.map +1 -1
  270. package/dist/src/memory/intelligence.js +42 -23
  271. package/dist/src/memory/intelligence.js.map +1 -1
  272. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  273. package/dist/src/memory/memory-bridge.js +52 -8
  274. package/dist/src/memory/memory-bridge.js.map +1 -1
  275. package/dist/src/memory/memory-crud.d.ts +67 -0
  276. package/dist/src/memory/memory-crud.d.ts.map +1 -0
  277. package/dist/src/memory/memory-crud.js +415 -0
  278. package/dist/src/memory/memory-crud.js.map +1 -0
  279. package/dist/src/memory/memory-initializer.d.ts +9 -322
  280. package/dist/src/memory/memory-initializer.d.ts.map +1 -1
  281. package/dist/src/memory/memory-initializer.js +17 -1794
  282. package/dist/src/memory/memory-initializer.js.map +1 -1
  283. package/dist/src/memory/memory-migrations.d.ts +30 -0
  284. package/dist/src/memory/memory-migrations.d.ts.map +1 -0
  285. package/dist/src/memory/memory-migrations.js +134 -0
  286. package/dist/src/memory/memory-migrations.js.map +1 -0
  287. package/dist/src/memory/memory-read.d.ts +78 -0
  288. package/dist/src/memory/memory-read.d.ts.map +1 -0
  289. package/dist/src/memory/memory-read.js +331 -0
  290. package/dist/src/memory/memory-read.js.map +1 -0
  291. package/dist/src/memory/memory-schema.d.ts +13 -0
  292. package/dist/src/memory/memory-schema.d.ts.map +1 -0
  293. package/dist/src/memory/memory-schema.js +167 -0
  294. package/dist/src/memory/memory-schema.js.map +1 -0
  295. package/dist/src/memory/sona-optimizer.d.ts.map +1 -1
  296. package/dist/src/memory/sona-optimizer.js +37 -4
  297. package/dist/src/memory/sona-optimizer.js.map +1 -1
  298. package/dist/src/monovector/route-outcomes.d.ts.map +1 -1
  299. package/dist/src/monovector/route-outcomes.js +16 -6
  300. package/dist/src/monovector/route-outcomes.js.map +1 -1
  301. package/dist/src/pricing/model-pricing.d.ts +41 -0
  302. package/dist/src/pricing/model-pricing.d.ts.map +1 -0
  303. package/dist/src/pricing/model-pricing.js +61 -0
  304. package/dist/src/pricing/model-pricing.js.map +1 -0
  305. package/dist/src/ui/.monomind/capture/active-run.json +1 -0
  306. package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.convs.jsonl +3 -0
  307. package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.jsonl +11 -0
  308. package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/rigid-qa-restart-1782288201.jsonl +540 -0
  309. package/dist/src/ui/.monomind/orgs/system-trial-qa-threads.jsonl +3 -0
  310. package/dist/src/ui/.monomind/orgs/test-event-fix/runs/rigid-qa-restart-1782288201.jsonl +2 -0
  311. package/dist/src/ui/MODULARIZATION_PLAN.md +79 -0
  312. package/dist/src/ui/collector.mjs +23 -13
  313. package/dist/src/ui/dashboard.html +1653 -14
  314. package/dist/src/ui/data/known-projects.json +1 -0
  315. package/dist/src/ui/data/mastermind-events.jsonl +553 -0
  316. package/dist/src/ui/data/sessions/_index.json +1 -0
  317. package/dist/src/ui/data/sessions/final-sess-001.jsonl +542 -0
  318. package/dist/src/ui/data/unknown-events.jsonl +1 -0
  319. package/dist/src/ui/orgs.html +154 -10
  320. package/dist/src/ui/server.mjs +1162 -168
  321. package/dist/src/ui/sse-manager.mjs +119 -0
  322. package/dist/src/update/checker.js +1 -1
  323. package/dist/src/update/checker.js.map +1 -1
  324. package/dist/tsconfig.tsbuildinfo +1 -1
  325. package/dist/workflow/builtin-handlers.js +321 -0
  326. package/dist/workflow/engine.js +253 -0
  327. package/dist/workflow/expression.js +98 -0
  328. package/dist/workflow/types.js +2 -0
  329. package/package.json +8 -6
@@ -0,0 +1,1217 @@
1
+ /**
2
+ * Hooks Coverage Commands
3
+ * Coverage-aware routing, progress tracking, and statusline generation.
4
+ * Extracted from hooks.ts to reduce file size.
5
+ */
6
+ import { output } from '../output.js';
7
+ import { callMCPTool, MCPClientError } from '../mcp-client.js';
8
+ import { readCoverageFromDisk, classifyCoverageGap, suggestAgentsForFile, } from './hooks-coverage-utils.js';
9
+ // ============================================================================
10
+ // Coverage-Aware Routing Commands
11
+ // ============================================================================
12
+ // Coverage route subcommand
13
+ export const coverageRouteCommand = {
14
+ name: 'coverage-route',
15
+ description: 'Route task to agents based on test coverage gaps (monovector integration)',
16
+ options: [
17
+ {
18
+ name: 'task',
19
+ short: 't',
20
+ description: 'Task description to route',
21
+ type: 'string',
22
+ required: true
23
+ },
24
+ {
25
+ name: 'threshold',
26
+ description: 'Coverage threshold percentage (default: 80)',
27
+ type: 'number',
28
+ default: 80
29
+ },
30
+ {
31
+ name: 'no-monovector',
32
+ description: 'Disable monovector integration',
33
+ type: 'boolean',
34
+ default: false
35
+ }
36
+ ],
37
+ examples: [
38
+ { command: 'monomind hooks coverage-route -t "fix bug in auth"', description: 'Route with coverage awareness' },
39
+ { command: 'monomind hooks coverage-route -t "add tests" --threshold 90', description: 'Route with custom threshold' }
40
+ ],
41
+ action: async (ctx) => {
42
+ const task = ctx.args[0] || ctx.flags.task;
43
+ const threshold = ctx.flags.threshold || 80;
44
+ const useMonovector = !ctx.flags['no-monovector'];
45
+ if (!task) {
46
+ output.printError('Task description is required. Use --task or -t flag.');
47
+ return { success: false, exitCode: 1 };
48
+ }
49
+ const spinner = output.createSpinner({ text: 'Analyzing coverage and routing task...' });
50
+ spinner.start();
51
+ // Try reading coverage from disk first
52
+ const diskCoverage = readCoverageFromDisk();
53
+ if (diskCoverage.found) {
54
+ spinner.succeed(`Coverage data loaded from ${diskCoverage.source}`);
55
+ // Find files with lowest coverage that may relate to the task
56
+ const taskLower = task.toLowerCase();
57
+ const taskWords = taskLower.split(/\s+/).filter(w => w.length > 2);
58
+ // Score each file by relevance to the task and how low its coverage is
59
+ const scoredFiles = diskCoverage.entries
60
+ .filter(e => e.lines < threshold)
61
+ .map(e => {
62
+ const fileNameLower = e.filePath.toLowerCase();
63
+ let relevance = 0;
64
+ for (const word of taskWords) {
65
+ if (fileNameLower.includes(word))
66
+ relevance += 2;
67
+ }
68
+ // Penalize high coverage (we care about low coverage)
69
+ const coveragePenalty = e.lines / 100;
70
+ return { ...e, relevance, score: relevance + (1 - coveragePenalty) };
71
+ })
72
+ .sort((a, b) => b.score - a.score);
73
+ const gaps = scoredFiles.slice(0, 8).map(e => {
74
+ const { gapType, priority } = classifyCoverageGap(e.lines, threshold);
75
+ return {
76
+ filePath: e.filePath,
77
+ coveragePercent: e.lines,
78
+ gapType,
79
+ priority,
80
+ suggestedAgents: suggestAgentsForFile(e.filePath),
81
+ reason: `${e.lines.toFixed(1)}% coverage, below ${threshold}%`,
82
+ };
83
+ });
84
+ const criticalGaps = gaps.filter(g => g.gapType === 'critical').length;
85
+ const primaryAgent = taskLower.includes('test') ? 'tester' :
86
+ taskLower.includes('security') || taskLower.includes('auth') ? 'security-auditor' :
87
+ taskLower.includes('fix') || taskLower.includes('bug') ? 'coder' : 'tester';
88
+ const suggestions = [];
89
+ if (criticalGaps > 0)
90
+ suggestions.push(`${criticalGaps} critical coverage gaps need immediate attention`);
91
+ if (diskCoverage.summary.overallLineCoverage < threshold) {
92
+ suggestions.push(`Overall line coverage (${diskCoverage.summary.overallLineCoverage.toFixed(1)}%) is below ${threshold}% threshold`);
93
+ }
94
+ if (scoredFiles.length > 8)
95
+ suggestions.push(`${scoredFiles.length - 8} additional files with low coverage`);
96
+ const result = {
97
+ success: true,
98
+ task,
99
+ coverageAware: true,
100
+ gaps,
101
+ routing: {
102
+ primaryAgent,
103
+ confidence: gaps.length > 0 ? 0.85 : 0.6,
104
+ reason: gaps.length > 0
105
+ ? `Routing to ${primaryAgent} based on ${gaps.length} coverage gaps related to task`
106
+ : `No coverage gaps found related to task, routing to ${primaryAgent}`,
107
+ coverageImpact: gaps.length > 0 ? 'high' : 'low',
108
+ },
109
+ suggestions,
110
+ metrics: {
111
+ filesAnalyzed: diskCoverage.summary.totalFiles,
112
+ totalGaps: scoredFiles.length,
113
+ criticalGaps,
114
+ avgCoverage: diskCoverage.summary.overallLineCoverage,
115
+ },
116
+ source: diskCoverage.source,
117
+ };
118
+ if (ctx.flags.format === 'json') {
119
+ output.printJson(result);
120
+ return { success: true, data: result };
121
+ }
122
+ output.writeln();
123
+ output.printBox([
124
+ `Agent: ${output.highlight(result.routing.primaryAgent)}`,
125
+ `Confidence: ${(result.routing.confidence * 100).toFixed(1)}%`,
126
+ `Coverage-Aware: ${output.success('Yes')} (from ${diskCoverage.source})`,
127
+ `Reason: ${result.routing.reason}`
128
+ ].join('\n'), 'Coverage-Aware Routing');
129
+ if (gaps.length > 0) {
130
+ output.writeln();
131
+ output.writeln(output.bold('Priority Coverage Gaps'));
132
+ output.printTable({
133
+ columns: [
134
+ { key: 'filePath', header: 'File', width: 35, format: (v) => {
135
+ const s = String(v);
136
+ return s.length > 32 ? '...' + s.slice(-32) : s;
137
+ } },
138
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
139
+ { key: 'gapType', header: 'Type', width: 10 },
140
+ { key: 'suggestedAgents', header: 'Agent', width: 15, format: (v) => Array.isArray(v) ? v[0] || '' : String(v) }
141
+ ],
142
+ data: gaps.slice(0, 8)
143
+ });
144
+ }
145
+ if (result.metrics.filesAnalyzed > 0) {
146
+ output.writeln();
147
+ output.writeln(output.bold('Coverage Metrics'));
148
+ output.printList([
149
+ `Files Analyzed: ${result.metrics.filesAnalyzed}`,
150
+ `Total Gaps: ${result.metrics.totalGaps}`,
151
+ `Critical Gaps: ${result.metrics.criticalGaps}`,
152
+ `Average Coverage: ${result.metrics.avgCoverage.toFixed(1)}%`
153
+ ]);
154
+ }
155
+ if (suggestions.length > 0) {
156
+ output.writeln();
157
+ output.writeln(output.bold('Suggestions'));
158
+ output.printList(suggestions.map(s => output.dim(s)));
159
+ }
160
+ return { success: true, data: result };
161
+ }
162
+ // No disk coverage - fall back to MCP tool
163
+ try {
164
+ const result = await callMCPTool('hooks_coverage-route', {
165
+ task,
166
+ threshold,
167
+ useMonovector,
168
+ });
169
+ spinner.stop();
170
+ if (ctx.flags.format === 'json') {
171
+ output.printJson(result);
172
+ return { success: true, data: result };
173
+ }
174
+ output.writeln();
175
+ output.printBox([
176
+ `Agent: ${output.highlight(result.routing.primaryAgent)}`,
177
+ `Confidence: ${(result.routing.confidence * 100).toFixed(1)}%`,
178
+ `Coverage-Aware: ${result.coverageAware ? output.success('Yes') : output.dim('No coverage data')}`,
179
+ `Reason: ${result.routing.reason}`
180
+ ].join('\n'), 'Coverage-Aware Routing');
181
+ if (result.gaps.length > 0) {
182
+ output.writeln();
183
+ output.writeln(output.bold('Priority Coverage Gaps'));
184
+ output.printTable({
185
+ columns: [
186
+ { key: 'filePath', header: 'File', width: 35, format: (v) => {
187
+ const s = String(v);
188
+ return s.length > 32 ? '...' + s.slice(-32) : s;
189
+ } },
190
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
191
+ { key: 'gapType', header: 'Type', width: 10 },
192
+ { key: 'suggestedAgents', header: 'Agent', width: 15, format: (v) => Array.isArray(v) ? v[0] || '' : String(v) }
193
+ ],
194
+ data: result.gaps.slice(0, 8)
195
+ });
196
+ }
197
+ if (result.metrics.filesAnalyzed > 0) {
198
+ output.writeln();
199
+ output.writeln(output.bold('Coverage Metrics'));
200
+ output.printList([
201
+ `Files Analyzed: ${result.metrics.filesAnalyzed}`,
202
+ `Total Gaps: ${result.metrics.totalGaps}`,
203
+ `Critical Gaps: ${result.metrics.criticalGaps}`,
204
+ `Average Coverage: ${result.metrics.avgCoverage.toFixed(1)}%`
205
+ ]);
206
+ }
207
+ if (result.suggestions.length > 0) {
208
+ output.writeln();
209
+ output.writeln(output.bold('Suggestions'));
210
+ output.printList(result.suggestions.map(s => output.dim(s)));
211
+ }
212
+ return { success: true, data: result };
213
+ }
214
+ catch (error) {
215
+ spinner.fail('No coverage data found');
216
+ output.writeln();
217
+ output.printWarning('No coverage data found. Run your test suite with coverage first.');
218
+ output.writeln();
219
+ output.printList([
220
+ 'Jest: npx jest --coverage',
221
+ 'Vitest: npx vitest --coverage',
222
+ 'nyc: npx nyc npm test',
223
+ 'c8: npx c8 npm test',
224
+ ]);
225
+ output.writeln();
226
+ output.writeln(output.dim('Expected files: coverage/coverage-summary.json, coverage/lcov.info, or .nyc_output/out.json'));
227
+ return { success: false, exitCode: 1 };
228
+ }
229
+ }
230
+ };
231
+ // Coverage suggest subcommand
232
+ export const coverageSuggestCommand = {
233
+ name: 'coverage-suggest',
234
+ description: 'Suggest coverage improvements for a path (monovector integration)',
235
+ options: [
236
+ {
237
+ name: 'path',
238
+ short: 'p',
239
+ description: 'Path to analyze for coverage suggestions',
240
+ type: 'string',
241
+ required: true
242
+ },
243
+ {
244
+ name: 'threshold',
245
+ description: 'Coverage threshold percentage (default: 80)',
246
+ type: 'number',
247
+ default: 80
248
+ },
249
+ {
250
+ name: 'limit',
251
+ short: 'l',
252
+ description: 'Maximum number of suggestions (default: 20)',
253
+ type: 'number',
254
+ default: 20
255
+ }
256
+ ],
257
+ examples: [
258
+ { command: 'monomind hooks coverage-suggest -p src/', description: 'Suggest improvements for src/' },
259
+ { command: 'monomind hooks coverage-suggest -p src/services --threshold 90', description: 'Stricter threshold' }
260
+ ],
261
+ action: async (ctx) => {
262
+ const targetPath = ctx.args[0] || ctx.flags.path;
263
+ const threshold = ctx.flags.threshold || 80;
264
+ const limit = ctx.flags.limit || 20;
265
+ if (!targetPath) {
266
+ output.printError('Path is required. Use --path or -p flag.');
267
+ return { success: false, exitCode: 1 };
268
+ }
269
+ const spinner = output.createSpinner({ text: `Analyzing coverage for ${targetPath}...` });
270
+ spinner.start();
271
+ // Try reading coverage from disk first
272
+ const diskCoverage = readCoverageFromDisk();
273
+ if (diskCoverage.found) {
274
+ spinner.succeed(`Coverage data loaded from ${diskCoverage.source}`);
275
+ // Filter entries to those matching the target path
276
+ const pathLower = targetPath.toLowerCase().replace(/\\/g, '/');
277
+ const matchingEntries = diskCoverage.entries.filter(e => {
278
+ const fileLower = e.filePath.toLowerCase().replace(/\\/g, '/');
279
+ return fileLower.includes(pathLower);
280
+ });
281
+ const belowThreshold = matchingEntries.filter(e => e.lines < threshold);
282
+ const suggestions = belowThreshold.slice(0, limit).map(e => {
283
+ const { gapType, priority } = classifyCoverageGap(e.lines, threshold);
284
+ return {
285
+ filePath: e.filePath,
286
+ coveragePercent: e.lines,
287
+ gapType,
288
+ priority,
289
+ suggestedAgents: suggestAgentsForFile(e.filePath),
290
+ reason: e.lines === 0 ? 'No coverage at all' :
291
+ e.lines < 20 ? 'Very low coverage, needs tests' :
292
+ e.lines < 50 ? 'Below 50%, add more tests' :
293
+ `Below ${threshold}% threshold`,
294
+ };
295
+ });
296
+ const totalLinesCov = matchingEntries.length > 0
297
+ ? matchingEntries.reduce((acc, e) => acc + e.lines, 0) / matchingEntries.length
298
+ : 0;
299
+ const totalBranchesCov = matchingEntries.length > 0
300
+ ? matchingEntries.reduce((acc, e) => acc + e.branches, 0) / matchingEntries.length
301
+ : 0;
302
+ const prioritizedFiles = belowThreshold.slice(0, 5).map(e => e.filePath);
303
+ const result = {
304
+ success: true,
305
+ path: targetPath,
306
+ suggestions,
307
+ summary: {
308
+ totalFiles: matchingEntries.length,
309
+ overallLineCoverage: totalLinesCov,
310
+ overallBranchCoverage: totalBranchesCov,
311
+ filesBelowThreshold: belowThreshold.length,
312
+ },
313
+ prioritizedFiles,
314
+ monovectorAvailable: false,
315
+ source: diskCoverage.source,
316
+ };
317
+ if (ctx.flags.format === 'json') {
318
+ output.printJson(result);
319
+ return { success: true, data: result };
320
+ }
321
+ output.writeln();
322
+ output.printBox([
323
+ `Path: ${output.highlight(targetPath)}`,
324
+ `Files Analyzed: ${result.summary.totalFiles}`,
325
+ `Line Coverage: ${result.summary.overallLineCoverage.toFixed(1)}%`,
326
+ `Branch Coverage: ${result.summary.overallBranchCoverage.toFixed(1)}%`,
327
+ `Below Threshold: ${result.summary.filesBelowThreshold} files`,
328
+ `Source: ${output.highlight(diskCoverage.source)}`
329
+ ].join('\n'), 'Coverage Summary');
330
+ if (suggestions.length > 0) {
331
+ output.writeln();
332
+ output.writeln(output.bold('Coverage Improvement Suggestions'));
333
+ output.printTable({
334
+ columns: [
335
+ { key: 'filePath', header: 'File', width: 40, format: (v) => {
336
+ const s = String(v);
337
+ return s.length > 37 ? '...' + s.slice(-37) : s;
338
+ } },
339
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
340
+ { key: 'gapType', header: 'Priority', width: 10 },
341
+ { key: 'reason', header: 'Reason', width: 25 }
342
+ ],
343
+ data: suggestions.slice(0, 15)
344
+ });
345
+ }
346
+ else {
347
+ output.writeln();
348
+ output.printSuccess('All files meet coverage threshold!');
349
+ }
350
+ if (prioritizedFiles.length > 0) {
351
+ output.writeln();
352
+ output.writeln(output.bold('Priority Files (Top 5)'));
353
+ output.printList(prioritizedFiles.slice(0, 5).map(f => output.highlight(f)));
354
+ }
355
+ return { success: true, data: result };
356
+ }
357
+ // No disk coverage - fall back to MCP tool
358
+ try {
359
+ const result = await callMCPTool('hooks_coverage-suggest', {
360
+ path: targetPath,
361
+ threshold,
362
+ limit,
363
+ });
364
+ spinner.stop();
365
+ if (ctx.flags.format === 'json') {
366
+ output.printJson(result);
367
+ return { success: true, data: result };
368
+ }
369
+ output.writeln();
370
+ output.printBox([
371
+ `Path: ${output.highlight(result.path)}`,
372
+ `Files Analyzed: ${result.summary.totalFiles}`,
373
+ `Line Coverage: ${result.summary.overallLineCoverage.toFixed(1)}%`,
374
+ `Branch Coverage: ${result.summary.overallBranchCoverage.toFixed(1)}%`,
375
+ `Below Threshold: ${result.summary.filesBelowThreshold} files`,
376
+ `Keyword routing: ${result.monovectorAvailable ? output.success('Available') : output.dim('Unavailable')}`
377
+ ].join('\n'), 'Coverage Summary');
378
+ if (result.suggestions.length > 0) {
379
+ output.writeln();
380
+ output.writeln(output.bold('Coverage Improvement Suggestions'));
381
+ output.printTable({
382
+ columns: [
383
+ { key: 'filePath', header: 'File', width: 40, format: (v) => {
384
+ const s = String(v);
385
+ return s.length > 37 ? '...' + s.slice(-37) : s;
386
+ } },
387
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
388
+ { key: 'gapType', header: 'Priority', width: 10 },
389
+ { key: 'reason', header: 'Reason', width: 25 }
390
+ ],
391
+ data: result.suggestions.slice(0, 15)
392
+ });
393
+ }
394
+ else {
395
+ output.writeln();
396
+ output.printSuccess('All files meet coverage threshold!');
397
+ }
398
+ if (result.prioritizedFiles.length > 0) {
399
+ output.writeln();
400
+ output.writeln(output.bold('Priority Files (Top 5)'));
401
+ output.printList(result.prioritizedFiles.slice(0, 5).map(f => output.highlight(f)));
402
+ }
403
+ return { success: true, data: result };
404
+ }
405
+ catch (error) {
406
+ spinner.fail('No coverage data found');
407
+ output.writeln();
408
+ output.printWarning('No coverage data found. Run your test suite with coverage first.');
409
+ output.writeln();
410
+ output.printList([
411
+ 'Jest: npx jest --coverage',
412
+ 'Vitest: npx vitest --coverage',
413
+ 'nyc: npx nyc npm test',
414
+ 'c8: npx c8 npm test',
415
+ ]);
416
+ output.writeln();
417
+ output.writeln(output.dim('Expected files: coverage/coverage-summary.json, coverage/lcov.info, or .nyc_output/out.json'));
418
+ return { success: false, exitCode: 1 };
419
+ }
420
+ }
421
+ };
422
+ // Coverage gaps subcommand
423
+ export const coverageGapsCommand = {
424
+ name: 'coverage-gaps',
425
+ description: 'List all coverage gaps with priority scoring and agent assignments',
426
+ options: [
427
+ {
428
+ name: 'threshold',
429
+ description: 'Coverage threshold percentage (default: 80)',
430
+ type: 'number',
431
+ default: 80
432
+ },
433
+ {
434
+ name: 'group-by-agent',
435
+ description: 'Group gaps by suggested agent (default: true)',
436
+ type: 'boolean',
437
+ default: true
438
+ },
439
+ {
440
+ name: 'critical-only',
441
+ description: 'Show only critical gaps',
442
+ type: 'boolean',
443
+ default: false
444
+ }
445
+ ],
446
+ examples: [
447
+ { command: 'monomind hooks coverage-gaps', description: 'List all coverage gaps' },
448
+ { command: 'monomind hooks coverage-gaps --critical-only', description: 'Only critical gaps' },
449
+ { command: 'monomind hooks coverage-gaps --threshold 90', description: 'Stricter threshold' }
450
+ ],
451
+ action: async (ctx) => {
452
+ const threshold = ctx.flags.threshold || 80;
453
+ const groupByAgent = ctx.flags['group-by-agent'] !== false;
454
+ const criticalOnly = ctx.flags['critical-only'] || false;
455
+ const spinner = output.createSpinner({ text: 'Analyzing project coverage gaps...' });
456
+ spinner.start();
457
+ // Try reading coverage from disk first
458
+ const diskCoverage = readCoverageFromDisk();
459
+ if (diskCoverage.found) {
460
+ spinner.succeed(`Coverage data loaded from ${diskCoverage.source}`);
461
+ // Build gaps from disk data
462
+ const allGaps = diskCoverage.entries
463
+ .filter(e => e.lines < threshold)
464
+ .map(e => {
465
+ const { gapType, priority } = classifyCoverageGap(e.lines, threshold);
466
+ return {
467
+ filePath: e.filePath,
468
+ coveragePercent: e.lines,
469
+ gapType,
470
+ complexity: Math.round((100 - e.lines) / 10),
471
+ priority,
472
+ suggestedAgents: suggestAgentsForFile(e.filePath),
473
+ reason: `Line coverage ${e.lines.toFixed(1)}% below ${threshold}% threshold`,
474
+ };
475
+ });
476
+ const gaps = criticalOnly
477
+ ? allGaps.filter(g => g.gapType === 'critical')
478
+ : allGaps;
479
+ // Build agent assignments
480
+ const agentAssignments = {};
481
+ if (groupByAgent) {
482
+ for (const gap of gaps) {
483
+ const agent = gap.suggestedAgents[0] || 'tester';
484
+ if (!agentAssignments[agent])
485
+ agentAssignments[agent] = [];
486
+ agentAssignments[agent].push(gap.filePath);
487
+ }
488
+ }
489
+ const result = {
490
+ success: true,
491
+ gaps,
492
+ summary: {
493
+ totalFiles: diskCoverage.summary.totalFiles,
494
+ overallLineCoverage: diskCoverage.summary.overallLineCoverage,
495
+ overallBranchCoverage: diskCoverage.summary.overallBranchCoverage,
496
+ filesBelowThreshold: gaps.length,
497
+ coverageThreshold: threshold,
498
+ },
499
+ agentAssignments,
500
+ monovectorAvailable: false,
501
+ source: diskCoverage.source,
502
+ };
503
+ if (ctx.flags.format === 'json') {
504
+ output.printJson(result);
505
+ return { success: true, data: result };
506
+ }
507
+ output.writeln();
508
+ output.printBox([
509
+ `Total Files: ${result.summary.totalFiles}`,
510
+ `Line Coverage: ${result.summary.overallLineCoverage.toFixed(1)}%`,
511
+ `Branch Coverage: ${result.summary.overallBranchCoverage.toFixed(1)}%`,
512
+ `Below ${threshold}%: ${result.summary.filesBelowThreshold} files`,
513
+ `Source: ${output.highlight(diskCoverage.source)}`
514
+ ].join('\n'), 'Coverage Gap Analysis');
515
+ if (gaps.length > 0) {
516
+ output.writeln();
517
+ output.writeln(output.bold(`Coverage Gaps (${gaps.length} files)`));
518
+ output.printTable({
519
+ columns: [
520
+ { key: 'filePath', header: 'File', width: 35, format: (v) => {
521
+ const s = String(v);
522
+ return s.length > 32 ? '...' + s.slice(-32) : s;
523
+ } },
524
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
525
+ { key: 'gapType', header: 'Type', width: 10, format: (v) => {
526
+ const t = String(v);
527
+ if (t === 'critical')
528
+ return output.error(t);
529
+ if (t === 'high')
530
+ return output.warning(t);
531
+ return t;
532
+ } },
533
+ { key: 'priority', header: 'Priority', width: 8, align: 'right' },
534
+ { key: 'suggestedAgents', header: 'Agent', width: 12, format: (v) => Array.isArray(v) ? v[0] || '' : String(v) }
535
+ ],
536
+ data: gaps.slice(0, 20)
537
+ });
538
+ }
539
+ else {
540
+ output.writeln();
541
+ output.printSuccess('No coverage gaps found! All files meet threshold.');
542
+ }
543
+ if (groupByAgent && Object.keys(agentAssignments).length > 0) {
544
+ output.writeln();
545
+ output.writeln(output.bold('Agent Assignments'));
546
+ for (const [agent, files] of Object.entries(agentAssignments)) {
547
+ output.writeln();
548
+ output.writeln(` ${output.highlight(agent)} (${files.length} files)`);
549
+ files.slice(0, 3).forEach(f => {
550
+ output.writeln(` - ${output.dim(f)}`);
551
+ });
552
+ if (files.length > 3) {
553
+ output.writeln(` ... and ${files.length - 3} more`);
554
+ }
555
+ }
556
+ }
557
+ return { success: true, data: result };
558
+ }
559
+ // No coverage files on disk - try MCP tool as fallback
560
+ try {
561
+ const result = await callMCPTool('hooks_coverage-gaps', {
562
+ threshold,
563
+ groupByAgent,
564
+ });
565
+ spinner.stop();
566
+ const gaps = criticalOnly
567
+ ? result.gaps.filter(g => g.gapType === 'critical')
568
+ : result.gaps;
569
+ if (ctx.flags.format === 'json') {
570
+ output.printJson({ ...result, gaps });
571
+ return { success: true, data: result };
572
+ }
573
+ output.writeln();
574
+ output.printBox([
575
+ `Total Files: ${result.summary.totalFiles}`,
576
+ `Line Coverage: ${result.summary.overallLineCoverage.toFixed(1)}%`,
577
+ `Branch Coverage: ${result.summary.overallBranchCoverage.toFixed(1)}%`,
578
+ `Below ${result.summary.coverageThreshold}%: ${result.summary.filesBelowThreshold} files`,
579
+ `Keyword routing: ${result.monovectorAvailable ? output.success('Available') : output.dim('Unavailable')}`
580
+ ].join('\n'), 'Coverage Gap Analysis');
581
+ if (gaps.length > 0) {
582
+ output.writeln();
583
+ output.writeln(output.bold(`Coverage Gaps (${gaps.length} files)`));
584
+ output.printTable({
585
+ columns: [
586
+ { key: 'filePath', header: 'File', width: 35, format: (v) => {
587
+ const s = String(v);
588
+ return s.length > 32 ? '...' + s.slice(-32) : s;
589
+ } },
590
+ { key: 'coveragePercent', header: 'Coverage', width: 10, align: 'right', format: (v) => `${Number(v).toFixed(1)}%` },
591
+ { key: 'gapType', header: 'Type', width: 10, format: (v) => {
592
+ const t = String(v);
593
+ if (t === 'critical')
594
+ return output.error(t);
595
+ if (t === 'high')
596
+ return output.warning(t);
597
+ return t;
598
+ } },
599
+ { key: 'priority', header: 'Priority', width: 8, align: 'right' },
600
+ { key: 'suggestedAgents', header: 'Agent', width: 12, format: (v) => Array.isArray(v) ? v[0] || '' : String(v) }
601
+ ],
602
+ data: gaps.slice(0, 20)
603
+ });
604
+ }
605
+ else {
606
+ output.writeln();
607
+ output.printSuccess('No coverage gaps found! All files meet threshold.');
608
+ }
609
+ if (groupByAgent && Object.keys(result.agentAssignments).length > 0) {
610
+ output.writeln();
611
+ output.writeln(output.bold('Agent Assignments'));
612
+ for (const [agent, files] of Object.entries(result.agentAssignments)) {
613
+ output.writeln();
614
+ output.writeln(` ${output.highlight(agent)} (${files.length} files)`);
615
+ files.slice(0, 3).forEach(f => {
616
+ output.writeln(` - ${output.dim(f)}`);
617
+ });
618
+ if (files.length > 3) {
619
+ output.writeln(` ... and ${files.length - 3} more`);
620
+ }
621
+ }
622
+ }
623
+ return { success: true, data: result };
624
+ }
625
+ catch (error) {
626
+ spinner.fail('No coverage data found');
627
+ output.writeln();
628
+ output.printWarning('No coverage data found. Run your test suite with coverage first.');
629
+ output.writeln();
630
+ output.printList([
631
+ 'Jest: npx jest --coverage',
632
+ 'Vitest: npx vitest --coverage',
633
+ 'nyc: npx nyc npm test',
634
+ 'c8: npx c8 npm test',
635
+ ]);
636
+ output.writeln();
637
+ output.writeln(output.dim('Expected files: coverage/coverage-summary.json, coverage/lcov.info, or .nyc_output/out.json'));
638
+ return { success: false, exitCode: 1 };
639
+ }
640
+ }
641
+ };
642
+ // Progress hook command
643
+ export const progressHookCommand = {
644
+ name: 'progress',
645
+ description: 'Check implementation progress via hooks',
646
+ options: [
647
+ {
648
+ name: 'detailed',
649
+ short: 'd',
650
+ description: 'Show detailed breakdown by category',
651
+ type: 'boolean',
652
+ default: false
653
+ },
654
+ {
655
+ name: 'sync',
656
+ short: 's',
657
+ description: 'Sync and persist progress to file',
658
+ type: 'boolean',
659
+ default: false
660
+ },
661
+ {
662
+ name: 'summary',
663
+ description: 'Show human-readable summary',
664
+ type: 'boolean',
665
+ default: false
666
+ }
667
+ ],
668
+ examples: [
669
+ { command: 'monomind hooks progress', description: 'Check current progress' },
670
+ { command: 'monomind hooks progress -d', description: 'Detailed breakdown' },
671
+ { command: 'monomind hooks progress --sync', description: 'Sync progress to file' },
672
+ { command: 'monomind hooks progress --summary', description: 'Human-readable summary' }
673
+ ],
674
+ action: async (ctx) => {
675
+ const detailed = ctx.flags.detailed;
676
+ const sync = ctx.flags.sync;
677
+ const summary = ctx.flags.summary;
678
+ try {
679
+ if (summary) {
680
+ const spinner = output.createSpinner({ text: 'Getting progress summary...' });
681
+ spinner.start();
682
+ const result = await callMCPTool('progress_summary', {});
683
+ spinner.stop();
684
+ if (ctx.flags.format === 'json') {
685
+ output.printJson(result);
686
+ return { success: true, data: result };
687
+ }
688
+ output.writeln();
689
+ output.writeln(result.summary);
690
+ return { success: true, data: result };
691
+ }
692
+ if (sync) {
693
+ const spinner = output.createSpinner({ text: 'Syncing progress...' });
694
+ spinner.start();
695
+ const result = await callMCPTool('progress_sync', {});
696
+ spinner.stop();
697
+ if (ctx.flags.format === 'json') {
698
+ output.printJson(result);
699
+ return { success: true, data: result };
700
+ }
701
+ output.writeln();
702
+ output.printSuccess(`Progress synced: ${result.progress}%`);
703
+ output.writeln(output.dim(` Persisted to .monomind/metrics/v1-progress.json`));
704
+ output.writeln(output.dim(` Last updated: ${result.lastUpdated}`));
705
+ return { success: true, data: result };
706
+ }
707
+ // Default: check progress
708
+ const spinner = output.createSpinner({ text: 'Checking v1 progress...' });
709
+ spinner.start();
710
+ const result = await callMCPTool('progress_check', { detailed });
711
+ spinner.stop();
712
+ if (ctx.flags.format === 'json') {
713
+ output.printJson(result);
714
+ return { success: true, data: result };
715
+ }
716
+ output.writeln();
717
+ const progressValue = result.overall ?? result.progress ?? 0;
718
+ // Create progress bar
719
+ const barWidth = 30;
720
+ const filled = Math.round((progressValue / 100) * barWidth);
721
+ const empty = barWidth - filled;
722
+ const bar = output.success('█'.repeat(filled)) + output.dim('░'.repeat(empty));
723
+ output.writeln(output.bold('v1 Implementation Progress'));
724
+ output.writeln();
725
+ output.writeln(`[${bar}] ${progressValue}%`);
726
+ output.writeln();
727
+ if (detailed && result.cli) {
728
+ output.writeln(output.highlight('CLI Commands:') + ` ${result.cli.progress}% (${result.cli.commands}/${result.cli.target})`);
729
+ output.writeln(output.highlight('MCP Tools:') + ` ${result.mcp?.progress ?? 0}% (${result.mcp?.tools ?? 0}/${result.mcp?.target ?? 0})`);
730
+ output.writeln(output.highlight('Hooks:') + ` ${result.hooks?.progress ?? 0}% (${result.hooks?.subcommands ?? 0}/${result.hooks?.target ?? 0})`);
731
+ output.writeln(output.highlight('Packages:') + ` ${result.packages?.progress ?? 0}% (${result.packages?.total ?? 0}/${result.packages?.target ?? 0})`);
732
+ output.writeln(output.highlight('DDD Structure:') + ` ${result.ddd?.progress ?? 0}% (${result.packages?.withDDD ?? 0}/${result.packages?.total ?? 0})`);
733
+ output.writeln();
734
+ if (result.codebase) {
735
+ output.writeln(output.dim(`Codebase: ${result.codebase.totalFiles} files, ${result.codebase.totalLines.toLocaleString()} lines`));
736
+ }
737
+ }
738
+ else if (result.breakdown) {
739
+ output.writeln('Breakdown:');
740
+ for (const [category, value] of Object.entries(result.breakdown)) {
741
+ output.writeln(` ${output.highlight(category)}: ${value}`);
742
+ }
743
+ }
744
+ if (result.lastUpdated) {
745
+ output.writeln(output.dim(`Last updated: ${result.lastUpdated}`));
746
+ }
747
+ return { success: true, data: result };
748
+ }
749
+ catch (error) {
750
+ if (error instanceof MCPClientError) {
751
+ output.printError(`Progress check failed: ${error.message}`);
752
+ }
753
+ else {
754
+ output.printError(`Progress check failed: ${String(error)}`);
755
+ }
756
+ return { success: false, exitCode: 1 };
757
+ }
758
+ }
759
+ };
760
+ // Statusline subcommand - generates dynamic status display
761
+ export const statuslineCommand = {
762
+ name: 'statusline',
763
+ description: 'Generate dynamic statusline with v1 progress and system status',
764
+ options: [
765
+ {
766
+ name: 'json',
767
+ description: 'Output as JSON',
768
+ type: 'boolean',
769
+ default: false
770
+ },
771
+ {
772
+ name: 'compact',
773
+ description: 'Compact single-line output',
774
+ type: 'boolean',
775
+ default: false
776
+ },
777
+ {
778
+ name: 'no-color',
779
+ description: 'Disable ANSI colors',
780
+ type: 'boolean',
781
+ default: false
782
+ }
783
+ ],
784
+ examples: [
785
+ { command: 'monomind hooks statusline', description: 'Display full statusline' },
786
+ { command: 'monomind hooks statusline --json', description: 'JSON output for hooks' },
787
+ { command: 'monomind hooks statusline --compact', description: 'Single-line status' }
788
+ ],
789
+ action: async (ctx) => {
790
+ const fs = await import('fs');
791
+ const path = await import('path');
792
+ const { execSync } = await import('child_process');
793
+ // Get learning stats from memory database
794
+ function getLearningStats() {
795
+ const memoryPaths = [
796
+ path.join(process.cwd(), '.swarm', 'memory.db'),
797
+ path.join(process.cwd(), '.claude', 'memory.db'),
798
+ ];
799
+ let patterns = 0;
800
+ let sessions = 0;
801
+ let trajectories = 0;
802
+ for (const dbPath of memoryPaths) {
803
+ if (fs.existsSync(dbPath)) {
804
+ try {
805
+ const stats = fs.statSync(dbPath);
806
+ const sizeKB = stats.size / 1024;
807
+ patterns = Math.floor(sizeKB / 2);
808
+ sessions = Math.max(1, Math.floor(patterns / 10));
809
+ trajectories = Math.floor(patterns / 5);
810
+ break;
811
+ }
812
+ catch {
813
+ // Ignore
814
+ }
815
+ }
816
+ }
817
+ const sessionsPath = path.join(process.cwd(), '.claude', 'sessions');
818
+ if (fs.existsSync(sessionsPath)) {
819
+ try {
820
+ const sessionFiles = fs.readdirSync(sessionsPath).filter((f) => f.endsWith('.json'));
821
+ sessions = Math.max(sessions, sessionFiles.length);
822
+ }
823
+ catch {
824
+ // Ignore
825
+ }
826
+ }
827
+ return { patterns, sessions, trajectories };
828
+ }
829
+ // Get v1 progress
830
+ function getv1Progress() {
831
+ const learning = getLearningStats();
832
+ let domainsCompleted = 0;
833
+ if (learning.patterns >= 500)
834
+ domainsCompleted = 5;
835
+ else if (learning.patterns >= 200)
836
+ domainsCompleted = 4;
837
+ else if (learning.patterns >= 100)
838
+ domainsCompleted = 3;
839
+ else if (learning.patterns >= 50)
840
+ domainsCompleted = 2;
841
+ else if (learning.patterns >= 10)
842
+ domainsCompleted = 1;
843
+ const totalDomains = 5;
844
+ const dddProgress = Math.min(100, Math.floor((domainsCompleted / totalDomains) * 100));
845
+ return { domainsCompleted, totalDomains, dddProgress, patternsLearned: learning.patterns, sessionsCompleted: learning.sessions };
846
+ }
847
+ // Get security status
848
+ function getSecurityStatus() {
849
+ const scanResultsPath = path.join(process.cwd(), '.claude', 'security-scans');
850
+ let cvesFixed = 0;
851
+ const totalCves = 3;
852
+ if (fs.existsSync(scanResultsPath)) {
853
+ try {
854
+ const scans = fs.readdirSync(scanResultsPath).filter((f) => f.endsWith('.json'));
855
+ cvesFixed = Math.min(totalCves, scans.length);
856
+ }
857
+ catch {
858
+ // Ignore
859
+ }
860
+ }
861
+ const auditPath = path.join(process.cwd(), '.swarm', 'security');
862
+ if (fs.existsSync(auditPath)) {
863
+ try {
864
+ const audits = fs.readdirSync(auditPath).filter((f) => f.includes('audit'));
865
+ cvesFixed = Math.min(totalCves, Math.max(cvesFixed, audits.length));
866
+ }
867
+ catch {
868
+ // Ignore
869
+ }
870
+ }
871
+ const status = cvesFixed >= totalCves ? 'CLEAN' : cvesFixed > 0 ? 'IN_PROGRESS' : 'PENDING';
872
+ return { status, cvesFixed, totalCves };
873
+ }
874
+ // Get swarm status
875
+ function getSwarmStatus() {
876
+ let activeAgents = 0;
877
+ let coordinationActive = false;
878
+ const maxAgents = 15;
879
+ const isWindows = process.platform === 'win32';
880
+ try {
881
+ const psCmd = isWindows
882
+ ? 'tasklist /FI "IMAGENAME eq node.exe" 2>NUL | findstr /I /C:"node" >NUL && echo 1 || echo 0'
883
+ : 'ps aux 2>/dev/null | grep -c agentic-flow || echo "0"';
884
+ const ps = execSync(psCmd, { encoding: 'utf-8' });
885
+ const raw = parseInt(ps.trim());
886
+ activeAgents = Math.max(0, isWindows ? raw : raw - 1);
887
+ coordinationActive = activeAgents > 0;
888
+ }
889
+ catch {
890
+ // Ignore
891
+ }
892
+ return { activeAgents, maxAgents, coordinationActive };
893
+ }
894
+ // Get system metrics
895
+ function getSystemMetrics() {
896
+ let memoryMB = 0;
897
+ let subAgents = 0;
898
+ const learning = getLearningStats();
899
+ try {
900
+ memoryMB = Math.floor(process.memoryUsage().heapUsed / 1024 / 1024);
901
+ }
902
+ catch {
903
+ // Ignore
904
+ }
905
+ // Calculate intelligence from multiple sources (matching statusline-generator.ts)
906
+ let intelligencePct = 0;
907
+ // 1. Check learning.json for REAL intelligence metrics first
908
+ const learningJsonPaths = [
909
+ path.join(process.cwd(), '.monomind', 'learning.json'),
910
+ path.join(process.cwd(), '.claude', '.monomind', 'learning.json'),
911
+ path.join(process.cwd(), '.swarm', 'learning.json'),
912
+ ];
913
+ for (const lPath of learningJsonPaths) {
914
+ if (fs.existsSync(lPath)) {
915
+ try {
916
+ if (fs.statSync(lPath).size <= 524_288) {
917
+ const data = JSON.parse(fs.readFileSync(lPath, 'utf-8'));
918
+ if (data.intelligence?.score !== undefined) {
919
+ intelligencePct = Math.min(100, Math.floor(data.intelligence.score));
920
+ break;
921
+ }
922
+ }
923
+ }
924
+ catch { /* ignore */ }
925
+ }
926
+ }
927
+ // 2. Fallback: calculate from patterns and vectors
928
+ if (intelligencePct === 0) {
929
+ const fromPatterns = learning.patterns > 0 ? Math.min(100, Math.floor(learning.patterns / 10)) : 0;
930
+ // Will be updated later with vector count
931
+ intelligencePct = fromPatterns;
932
+ }
933
+ // 3. Fallback: calculate maturity score from project indicators
934
+ if (intelligencePct === 0) {
935
+ let maturityScore = 0;
936
+ // Check for key project files/dirs
937
+ if (fs.existsSync(path.join(process.cwd(), '.claude')))
938
+ maturityScore += 15;
939
+ if (fs.existsSync(path.join(process.cwd(), '.monomind')))
940
+ maturityScore += 15;
941
+ if (fs.existsSync(path.join(process.cwd(), 'CLAUDE.md')))
942
+ maturityScore += 10;
943
+ if (fs.existsSync(path.join(process.cwd(), 'monomind.config.json')))
944
+ maturityScore += 10;
945
+ if (fs.existsSync(path.join(process.cwd(), '.swarm')))
946
+ maturityScore += 10;
947
+ // Check for test files
948
+ const testDirs = ['tests', '__tests__', 'test', 'v1/__tests__'];
949
+ for (const dir of testDirs) {
950
+ if (fs.existsSync(path.join(process.cwd(), dir))) {
951
+ maturityScore += 10;
952
+ break;
953
+ }
954
+ }
955
+ // Check for hooks config
956
+ if (fs.existsSync(path.join(process.cwd(), '.claude', 'settings.json')))
957
+ maturityScore += 10;
958
+ intelligencePct = Math.min(100, maturityScore);
959
+ }
960
+ const contextPct = Math.min(100, Math.floor(learning.sessions * 5));
961
+ return { memoryMB, contextPct, intelligencePct, subAgents };
962
+ }
963
+ // Get user info
964
+ function getUserInfo() {
965
+ let name = 'user';
966
+ let gitBranch = '';
967
+ const modelName = 'Opus 4.6 (1M context)';
968
+ const isWindows = process.platform === 'win32';
969
+ try {
970
+ const nameCmd = isWindows
971
+ ? 'git config user.name 2>NUL || echo user'
972
+ : 'git config user.name 2>/dev/null || echo "user"';
973
+ const branchCmd = isWindows
974
+ ? 'git branch --show-current 2>NUL || echo.'
975
+ : 'git branch --show-current 2>/dev/null || echo ""';
976
+ name = execSync(nameCmd, { encoding: 'utf-8' }).trim();
977
+ gitBranch = execSync(branchCmd, { encoding: 'utf-8' }).trim();
978
+ if (gitBranch === '.')
979
+ gitBranch = '';
980
+ }
981
+ catch {
982
+ // Ignore
983
+ }
984
+ return { name, gitBranch, modelName };
985
+ }
986
+ // Collect all status
987
+ const progress = getv1Progress();
988
+ const security = getSecurityStatus();
989
+ const swarm = getSwarmStatus();
990
+ const system = getSystemMetrics();
991
+ const user = getUserInfo();
992
+ const statusData = {
993
+ user,
994
+ v1Progress: progress,
995
+ security,
996
+ swarm,
997
+ system,
998
+ timestamp: new Date().toISOString()
999
+ };
1000
+ // JSON output
1001
+ if (ctx.flags.json || ctx.flags.format === 'json') {
1002
+ output.printJson(statusData);
1003
+ return { success: true, data: statusData };
1004
+ }
1005
+ // Compact output
1006
+ if (ctx.flags.compact) {
1007
+ const line = `DDD:${progress.domainsCompleted}/${progress.totalDomains} CVE:${security.cvesFixed}/${security.totalCves} Swarm:${swarm.activeAgents}/${swarm.maxAgents} Ctx:${system.contextPct}% Int:${system.intelligencePct}%`;
1008
+ output.writeln(line);
1009
+ return { success: true, data: statusData };
1010
+ }
1011
+ // Full colored output
1012
+ const noColor = ctx.flags['no-color'] || ctx.flags.noColor;
1013
+ const c = noColor ? {
1014
+ reset: '', bold: '', dim: '', red: '', green: '', yellow: '', blue: '',
1015
+ purple: '', cyan: '', brightRed: '', brightGreen: '', brightYellow: '',
1016
+ brightBlue: '', brightPurple: '', brightCyan: '', brightWhite: ''
1017
+ } : {
1018
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[0;31m',
1019
+ green: '\x1b[0;32m', yellow: '\x1b[0;33m', blue: '\x1b[0;34m',
1020
+ purple: '\x1b[0;35m', cyan: '\x1b[0;36m', brightRed: '\x1b[1;31m',
1021
+ brightGreen: '\x1b[1;32m', brightYellow: '\x1b[1;33m', brightBlue: '\x1b[1;34m',
1022
+ brightPurple: '\x1b[1;35m', brightCyan: '\x1b[1;36m', brightWhite: '\x1b[1;37m'
1023
+ };
1024
+ // Progress bar helper
1025
+ const progressBar = (current, total) => {
1026
+ const filled = Math.round((current / total) * 5);
1027
+ const empty = 5 - filled;
1028
+ return '[' + '●'.repeat(filled) + '○'.repeat(empty) + ']';
1029
+ };
1030
+ // Generate lines
1031
+ let header = `${c.bold}${c.brightPurple}▊ Monomind ${c.reset}`;
1032
+ header += `${swarm.coordinationActive ? c.brightCyan : c.dim}● ${c.brightCyan}${user.name}${c.reset}`;
1033
+ if (user.gitBranch) {
1034
+ header += ` ${c.dim}│${c.reset} ${c.brightBlue}⎇ ${user.gitBranch}${c.reset}`;
1035
+ }
1036
+ header += ` ${c.dim}│${c.reset} ${c.purple}${user.modelName}${c.reset}`;
1037
+ const separator = `${c.dim}─────────────────────────────────────────────────────${c.reset}`;
1038
+ // Get hooks stats
1039
+ const hooksStats = { enabled: 0, total: 17 };
1040
+ const settingsPath = path.join(process.cwd(), '.claude', 'settings.json');
1041
+ if (fs.existsSync(settingsPath)) {
1042
+ try {
1043
+ if (fs.statSync(settingsPath).size <= 524_288) {
1044
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
1045
+ if (settings.hooks) {
1046
+ hooksStats.enabled = Object.values(settings.hooks).filter((h) => h && typeof h === 'object').length;
1047
+ }
1048
+ }
1049
+ }
1050
+ catch { /* ignore */ }
1051
+ }
1052
+ // Get AgentDB stats (matching statusline-generator.ts paths)
1053
+ const agentdbStats = { vectorCount: 0, dbSizeKB: 0, hasHnsw: false };
1054
+ // Check for direct database files first
1055
+ const dbPaths = [
1056
+ path.join(process.cwd(), '.swarm', 'memory.db'),
1057
+ path.join(process.cwd(), '.monomind', 'memory.db'),
1058
+ path.join(process.cwd(), '.claude', 'memory.db'),
1059
+ path.join(process.cwd(), 'data', 'memory.db'),
1060
+ path.join(process.cwd(), 'memory.db'),
1061
+ path.join(process.cwd(), '.agentdb', 'memory.db'),
1062
+ path.join(process.cwd(), '.monomind', 'memory', 'agentdb.db'),
1063
+ ];
1064
+ for (const dbPath of dbPaths) {
1065
+ if (fs.existsSync(dbPath)) {
1066
+ try {
1067
+ const stats = fs.statSync(dbPath);
1068
+ agentdbStats.dbSizeKB = Math.round(stats.size / 1024);
1069
+ agentdbStats.vectorCount = Math.floor(agentdbStats.dbSizeKB / 2);
1070
+ agentdbStats.hasHnsw = agentdbStats.vectorCount > 100;
1071
+ break;
1072
+ }
1073
+ catch { /* ignore */ }
1074
+ }
1075
+ }
1076
+ // Check for AgentDB directories if no direct db found
1077
+ if (agentdbStats.vectorCount === 0) {
1078
+ const agentdbDirs = [
1079
+ path.join(process.cwd(), '.monomind', 'agentdb'),
1080
+ path.join(process.cwd(), '.swarm', 'agentdb'),
1081
+ path.join(process.cwd(), 'data', 'agentdb'),
1082
+ path.join(process.cwd(), '.agentdb'),
1083
+ ];
1084
+ for (const dir of agentdbDirs) {
1085
+ if (fs.existsSync(dir)) {
1086
+ try {
1087
+ const files = fs.readdirSync(dir);
1088
+ for (const f of files) {
1089
+ if (f.endsWith('.db') || f.endsWith('.sqlite')) {
1090
+ const filePath = path.join(dir, f);
1091
+ const fileStat = fs.statSync(filePath);
1092
+ agentdbStats.dbSizeKB += Math.round(fileStat.size / 1024);
1093
+ }
1094
+ }
1095
+ agentdbStats.vectorCount = Math.floor(agentdbStats.dbSizeKB / 2);
1096
+ agentdbStats.hasHnsw = agentdbStats.vectorCount > 100;
1097
+ if (agentdbStats.vectorCount > 0)
1098
+ break;
1099
+ }
1100
+ catch { /* ignore */ }
1101
+ }
1102
+ }
1103
+ }
1104
+ // Check for HNSW index files
1105
+ const hnswPaths = [
1106
+ path.join(process.cwd(), '.monomind', 'hnsw'),
1107
+ path.join(process.cwd(), '.swarm', 'hnsw'),
1108
+ path.join(process.cwd(), 'data', 'hnsw'),
1109
+ ];
1110
+ for (const hnswPath of hnswPaths) {
1111
+ if (fs.existsSync(hnswPath)) {
1112
+ agentdbStats.hasHnsw = true;
1113
+ try {
1114
+ const hnswFiles = fs.readdirSync(hnswPath);
1115
+ const indexFile = hnswFiles.find(f => f.endsWith('.index'));
1116
+ if (indexFile) {
1117
+ const indexStat = fs.statSync(path.join(hnswPath, indexFile));
1118
+ const hnswVectors = Math.floor(indexStat.size / 512);
1119
+ agentdbStats.vectorCount = Math.max(agentdbStats.vectorCount, hnswVectors);
1120
+ }
1121
+ }
1122
+ catch { /* ignore */ }
1123
+ break;
1124
+ }
1125
+ }
1126
+ // Check for vectors.json file
1127
+ const vectorsPath = path.join(process.cwd(), '.monomind', 'vectors.json');
1128
+ if (fs.existsSync(vectorsPath) && agentdbStats.vectorCount === 0) {
1129
+ try {
1130
+ if (fs.statSync(vectorsPath).size <= 8_388_608) {
1131
+ const data = JSON.parse(fs.readFileSync(vectorsPath, 'utf-8'));
1132
+ if (Array.isArray(data)) {
1133
+ agentdbStats.vectorCount = data.length;
1134
+ }
1135
+ else if (data.vectors) {
1136
+ agentdbStats.vectorCount = Object.keys(data.vectors).length;
1137
+ }
1138
+ }
1139
+ }
1140
+ catch { /* ignore */ }
1141
+ }
1142
+ // Get test stats
1143
+ const testStats = { testFiles: 0, testCases: 0 };
1144
+ const testPaths = ['tests', '__tests__', 'test', 'spec'];
1145
+ for (const testPath of testPaths) {
1146
+ const fullPath = path.join(process.cwd(), testPath);
1147
+ if (fs.existsSync(fullPath)) {
1148
+ try {
1149
+ const files = fs.readdirSync(fullPath, { recursive: true });
1150
+ testStats.testFiles = files.filter((f) => /\.(test|spec)\.(ts|js|tsx|jsx)$/.test(f)).length;
1151
+ testStats.testCases = testStats.testFiles * 28; // Estimate
1152
+ }
1153
+ catch { /* ignore */ }
1154
+ }
1155
+ }
1156
+ // Get MCP stats
1157
+ const mcpStats = { enabled: 0, total: 0 };
1158
+ const mcpPath = path.join(process.cwd(), '.mcp.json');
1159
+ if (fs.existsSync(mcpPath)) {
1160
+ try {
1161
+ const mcp = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
1162
+ if (mcp.mcpServers) {
1163
+ mcpStats.total = Object.keys(mcp.mcpServers).length;
1164
+ mcpStats.enabled = mcpStats.total;
1165
+ }
1166
+ }
1167
+ catch { /* ignore */ }
1168
+ }
1169
+ const domainsColor = progress.domainsCompleted >= 3 ? c.brightGreen : progress.domainsCompleted > 0 ? c.yellow : c.red;
1170
+ // Dynamic perf indicator based on patterns/HNSW
1171
+ let perfIndicator = `${c.dim}⚡ HNSW: idle${c.reset}`;
1172
+ if (agentdbStats.hasHnsw && agentdbStats.vectorCount > 0) {
1173
+ perfIndicator = `${c.brightGreen}⚡ HNSW ${agentdbStats.vectorCount.toLocaleString()} vec${c.reset}`;
1174
+ }
1175
+ else if (progress.patternsLearned > 0) {
1176
+ const patternsK = progress.patternsLearned >= 1000 ? `${(progress.patternsLearned / 1000).toFixed(1)}k` : String(progress.patternsLearned);
1177
+ perfIndicator = `${c.brightYellow}📚 ${patternsK} patterns${c.reset}`;
1178
+ }
1179
+ const line1 = `${c.brightCyan}🏗️ DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
1180
+ `${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ` +
1181
+ perfIndicator;
1182
+ const swarmIndicator = swarm.coordinationActive ? `${c.brightGreen}◉${c.reset}` : `${c.dim}○${c.reset}`;
1183
+ const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
1184
+ const securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
1185
+ const securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
1186
+ const hooksColor = hooksStats.enabled > 0 ? c.brightGreen : c.dim;
1187
+ const line2 = `${c.brightYellow}🤖 Swarm${c.reset} ${swarmIndicator} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
1188
+ `${c.brightPurple}👥 ${system.subAgents}${c.reset} ` +
1189
+ `${c.brightBlue}🪝 ${hooksColor}${hooksStats.enabled}${c.reset}/${c.brightWhite}${hooksStats.total}${c.reset} ` +
1190
+ `${securityIcon} ${securityColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
1191
+ `${c.brightCyan}💾 ${system.memoryMB}MB${c.reset} ` +
1192
+ `${c.brightPurple}🧠 ${String(system.intelligencePct).padStart(3)}%${c.reset}`;
1193
+ const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
1194
+ const line3 = `${c.brightPurple}🔧 Architecture${c.reset} ` +
1195
+ `${c.cyan}ADRs${c.reset} ${c.dim}●0/0${c.reset} ${c.dim}│${c.reset} ` +
1196
+ `${c.cyan}DDD${c.reset} ${dddColor}●${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}│${c.reset} ` +
1197
+ `${c.cyan}Security${c.reset} ${securityColor}●${security.status}${c.reset}`;
1198
+ const vectorColor = agentdbStats.vectorCount > 0 ? c.brightGreen : c.dim;
1199
+ const testColor = testStats.testFiles > 0 ? c.brightGreen : c.dim;
1200
+ const mcpColor = mcpStats.enabled > 0 ? c.brightGreen : c.dim;
1201
+ const sizeDisplay = agentdbStats.dbSizeKB >= 1024 ? `${(agentdbStats.dbSizeKB / 1024).toFixed(1)}MB` : `${agentdbStats.dbSizeKB}KB`;
1202
+ const hnswIndicator = agentdbStats.hasHnsw ? `${c.brightGreen}⚡${c.reset}` : '';
1203
+ const line4 = `${c.brightCyan}📊 AgentDB${c.reset} ` +
1204
+ `${c.cyan}Vectors${c.reset} ${vectorColor}●${agentdbStats.vectorCount}${hnswIndicator}${c.reset} ${c.dim}│${c.reset} ` +
1205
+ `${c.cyan}Size${c.reset} ${c.brightWhite}${sizeDisplay}${c.reset} ${c.dim}│${c.reset} ` +
1206
+ `${c.cyan}Tests${c.reset} ${testColor}●${testStats.testFiles}${c.reset} ${c.dim}(${testStats.testCases} cases)${c.reset} ${c.dim}│${c.reset} ` +
1207
+ `${c.cyan}MCP${c.reset} ${mcpColor}●${mcpStats.enabled}/${mcpStats.total}${c.reset}`;
1208
+ output.writeln(header);
1209
+ output.writeln(separator);
1210
+ output.writeln(line1);
1211
+ output.writeln(line2);
1212
+ output.writeln(line3);
1213
+ output.writeln(line4);
1214
+ return { success: true, data: statusData };
1215
+ }
1216
+ };
1217
+ //# sourceMappingURL=hooks-coverage-commands.js.map