@cleocode/cleo 2026.4.59 → 2026.4.62

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 (773) hide show
  1. package/dist/cli/index.js +1917 -314
  2. package/dist/cli/index.js.map +4 -4
  3. package/package.json +8 -8
  4. package/dist/cli/commander-shim.d.ts +0 -112
  5. package/dist/cli/commander-shim.d.ts.map +0 -1
  6. package/dist/cli/commander-shim.js +0 -233
  7. package/dist/cli/commander-shim.js.map +0 -1
  8. package/dist/cli/commands/adapter.d.ts +0 -21
  9. package/dist/cli/commands/adapter.d.ts.map +0 -1
  10. package/dist/cli/commands/adapter.js +0 -73
  11. package/dist/cli/commands/adapter.js.map +0 -1
  12. package/dist/cli/commands/add-batch.d.ts +0 -16
  13. package/dist/cli/commands/add-batch.d.ts.map +0 -1
  14. package/dist/cli/commands/add-batch.js +0 -133
  15. package/dist/cli/commands/add-batch.js.map +0 -1
  16. package/dist/cli/commands/add.d.ts +0 -12
  17. package/dist/cli/commands/add.d.ts.map +0 -1
  18. package/dist/cli/commands/add.js +0 -238
  19. package/dist/cli/commands/add.js.map +0 -1
  20. package/dist/cli/commands/admin.d.ts +0 -15
  21. package/dist/cli/commands/admin.d.ts.map +0 -1
  22. package/dist/cli/commands/admin.js +0 -143
  23. package/dist/cli/commands/admin.js.map +0 -1
  24. package/dist/cli/commands/adr.d.ts +0 -27
  25. package/dist/cli/commands/adr.d.ts.map +0 -1
  26. package/dist/cli/commands/adr.js +0 -79
  27. package/dist/cli/commands/adr.js.map +0 -1
  28. package/dist/cli/commands/agent-profile-status.d.ts +0 -98
  29. package/dist/cli/commands/agent-profile-status.d.ts.map +0 -1
  30. package/dist/cli/commands/agent-profile-status.js +0 -71
  31. package/dist/cli/commands/agent-profile-status.js.map +0 -1
  32. package/dist/cli/commands/agent.d.ts +0 -41
  33. package/dist/cli/commands/agent.d.ts.map +0 -1
  34. package/dist/cli/commands/agent.js +0 -2270
  35. package/dist/cli/commands/agent.js.map +0 -1
  36. package/dist/cli/commands/agents.d.ts +0 -17
  37. package/dist/cli/commands/agents.d.ts.map +0 -1
  38. package/dist/cli/commands/agents.js +0 -20
  39. package/dist/cli/commands/agents.js.map +0 -1
  40. package/dist/cli/commands/analyze.d.ts +0 -12
  41. package/dist/cli/commands/analyze.d.ts.map +0 -1
  42. package/dist/cli/commands/analyze.js +0 -20
  43. package/dist/cli/commands/analyze.js.map +0 -1
  44. package/dist/cli/commands/archive-stats.d.ts +0 -18
  45. package/dist/cli/commands/archive-stats.d.ts.map +0 -1
  46. package/dist/cli/commands/archive-stats.js +0 -49
  47. package/dist/cli/commands/archive-stats.js.map +0 -1
  48. package/dist/cli/commands/archive.d.ts +0 -12
  49. package/dist/cli/commands/archive.d.ts.map +0 -1
  50. package/dist/cli/commands/archive.js +0 -32
  51. package/dist/cli/commands/archive.js.map +0 -1
  52. package/dist/cli/commands/backfill.d.ts +0 -38
  53. package/dist/cli/commands/backfill.d.ts.map +0 -1
  54. package/dist/cli/commands/backfill.js +0 -144
  55. package/dist/cli/commands/backfill.js.map +0 -1
  56. package/dist/cli/commands/backup-inspect.d.ts +0 -24
  57. package/dist/cli/commands/backup-inspect.d.ts.map +0 -1
  58. package/dist/cli/commands/backup-inspect.js +0 -417
  59. package/dist/cli/commands/backup-inspect.js.map +0 -1
  60. package/dist/cli/commands/backup.d.ts +0 -13
  61. package/dist/cli/commands/backup.d.ts.map +0 -1
  62. package/dist/cli/commands/backup.js +0 -479
  63. package/dist/cli/commands/backup.js.map +0 -1
  64. package/dist/cli/commands/blockers.d.ts +0 -7
  65. package/dist/cli/commands/blockers.d.ts.map +0 -1
  66. package/dist/cli/commands/blockers.js +0 -16
  67. package/dist/cli/commands/blockers.js.map +0 -1
  68. package/dist/cli/commands/brain.d.ts +0 -29
  69. package/dist/cli/commands/brain.d.ts.map +0 -1
  70. package/dist/cli/commands/brain.js +0 -358
  71. package/dist/cli/commands/brain.js.map +0 -1
  72. package/dist/cli/commands/briefing.d.ts +0 -22
  73. package/dist/cli/commands/briefing.d.ts.map +0 -1
  74. package/dist/cli/commands/briefing.js +0 -45
  75. package/dist/cli/commands/briefing.js.map +0 -1
  76. package/dist/cli/commands/bug.d.ts +0 -12
  77. package/dist/cli/commands/bug.d.ts.map +0 -1
  78. package/dist/cli/commands/bug.js +0 -81
  79. package/dist/cli/commands/bug.js.map +0 -1
  80. package/dist/cli/commands/cancel.d.ts +0 -17
  81. package/dist/cli/commands/cancel.d.ts.map +0 -1
  82. package/dist/cli/commands/cancel.js +0 -28
  83. package/dist/cli/commands/cancel.js.map +0 -1
  84. package/dist/cli/commands/cant.d.ts +0 -32
  85. package/dist/cli/commands/cant.d.ts.map +0 -1
  86. package/dist/cli/commands/cant.js +0 -264
  87. package/dist/cli/commands/cant.js.map +0 -1
  88. package/dist/cli/commands/chain.d.ts +0 -16
  89. package/dist/cli/commands/chain.d.ts.map +0 -1
  90. package/dist/cli/commands/chain.js +0 -52
  91. package/dist/cli/commands/chain.js.map +0 -1
  92. package/dist/cli/commands/check.d.ts +0 -25
  93. package/dist/cli/commands/check.d.ts.map +0 -1
  94. package/dist/cli/commands/check.js +0 -193
  95. package/dist/cli/commands/check.js.map +0 -1
  96. package/dist/cli/commands/checkpoint.d.ts +0 -15
  97. package/dist/cli/commands/checkpoint.d.ts.map +0 -1
  98. package/dist/cli/commands/checkpoint.js +0 -91
  99. package/dist/cli/commands/checkpoint.js.map +0 -1
  100. package/dist/cli/commands/claim.d.ts +0 -27
  101. package/dist/cli/commands/claim.d.ts.map +0 -1
  102. package/dist/cli/commands/claim.js +0 -45
  103. package/dist/cli/commands/claim.js.map +0 -1
  104. package/dist/cli/commands/code.d.ts +0 -11
  105. package/dist/cli/commands/code.d.ts.map +0 -1
  106. package/dist/cli/commands/code.js +0 -114
  107. package/dist/cli/commands/code.js.map +0 -1
  108. package/dist/cli/commands/commands.d.ts +0 -13
  109. package/dist/cli/commands/commands.d.ts.map +0 -1
  110. package/dist/cli/commands/commands.js +0 -29
  111. package/dist/cli/commands/commands.js.map +0 -1
  112. package/dist/cli/commands/complete.d.ts +0 -12
  113. package/dist/cli/commands/complete.d.ts.map +0 -1
  114. package/dist/cli/commands/complete.js +0 -92
  115. package/dist/cli/commands/complete.js.map +0 -1
  116. package/dist/cli/commands/complexity.d.ts +0 -17
  117. package/dist/cli/commands/complexity.d.ts.map +0 -1
  118. package/dist/cli/commands/complexity.js +0 -25
  119. package/dist/cli/commands/complexity.js.map +0 -1
  120. package/dist/cli/commands/compliance.d.ts +0 -9
  121. package/dist/cli/commands/compliance.d.ts.map +0 -1
  122. package/dist/cli/commands/compliance.js +0 -110
  123. package/dist/cli/commands/compliance.js.map +0 -1
  124. package/dist/cli/commands/config.d.ts +0 -10
  125. package/dist/cli/commands/config.d.ts.map +0 -1
  126. package/dist/cli/commands/config.js +0 -69
  127. package/dist/cli/commands/config.js.map +0 -1
  128. package/dist/cli/commands/consensus.d.ts +0 -13
  129. package/dist/cli/commands/consensus.d.ts.map +0 -1
  130. package/dist/cli/commands/consensus.js +0 -45
  131. package/dist/cli/commands/consensus.js.map +0 -1
  132. package/dist/cli/commands/context.d.ts +0 -15
  133. package/dist/cli/commands/context.d.ts.map +0 -1
  134. package/dist/cli/commands/context.js +0 -76
  135. package/dist/cli/commands/context.js.map +0 -1
  136. package/dist/cli/commands/contribution.d.ts +0 -13
  137. package/dist/cli/commands/contribution.d.ts.map +0 -1
  138. package/dist/cli/commands/contribution.js +0 -41
  139. package/dist/cli/commands/contribution.js.map +0 -1
  140. package/dist/cli/commands/current.d.ts +0 -13
  141. package/dist/cli/commands/current.d.ts.map +0 -1
  142. package/dist/cli/commands/current.js +0 -20
  143. package/dist/cli/commands/current.js.map +0 -1
  144. package/dist/cli/commands/dash.d.ts +0 -12
  145. package/dist/cli/commands/dash.d.ts.map +0 -1
  146. package/dist/cli/commands/dash.js +0 -20
  147. package/dist/cli/commands/dash.js.map +0 -1
  148. package/dist/cli/commands/decomposition.d.ts +0 -13
  149. package/dist/cli/commands/decomposition.d.ts.map +0 -1
  150. package/dist/cli/commands/decomposition.js +0 -45
  151. package/dist/cli/commands/decomposition.js.map +0 -1
  152. package/dist/cli/commands/delete.d.ts +0 -12
  153. package/dist/cli/commands/delete.d.ts.map +0 -1
  154. package/dist/cli/commands/delete.js +0 -37
  155. package/dist/cli/commands/delete.js.map +0 -1
  156. package/dist/cli/commands/deps.d.ts +0 -24
  157. package/dist/cli/commands/deps.d.ts.map +0 -1
  158. package/dist/cli/commands/deps.js +0 -98
  159. package/dist/cli/commands/deps.js.map +0 -1
  160. package/dist/cli/commands/detect-drift.d.ts +0 -15
  161. package/dist/cli/commands/detect-drift.d.ts.map +0 -1
  162. package/dist/cli/commands/detect-drift.js +0 -428
  163. package/dist/cli/commands/detect-drift.js.map +0 -1
  164. package/dist/cli/commands/detect.d.ts +0 -13
  165. package/dist/cli/commands/detect.d.ts.map +0 -1
  166. package/dist/cli/commands/detect.js +0 -20
  167. package/dist/cli/commands/detect.js.map +0 -1
  168. package/dist/cli/commands/diagnostics.d.ts +0 -16
  169. package/dist/cli/commands/diagnostics.d.ts.map +0 -1
  170. package/dist/cli/commands/diagnostics.js +0 -58
  171. package/dist/cli/commands/diagnostics.js.map +0 -1
  172. package/dist/cli/commands/docs.d.ts +0 -13
  173. package/dist/cli/commands/docs.d.ts.map +0 -1
  174. package/dist/cli/commands/docs.js +0 -169
  175. package/dist/cli/commands/docs.js.map +0 -1
  176. package/dist/cli/commands/doctor.d.ts +0 -15
  177. package/dist/cli/commands/doctor.d.ts.map +0 -1
  178. package/dist/cli/commands/doctor.js +0 -133
  179. package/dist/cli/commands/doctor.js.map +0 -1
  180. package/dist/cli/commands/dynamic.d.ts +0 -24
  181. package/dist/cli/commands/dynamic.d.ts.map +0 -1
  182. package/dist/cli/commands/dynamic.js +0 -27
  183. package/dist/cli/commands/dynamic.js.map +0 -1
  184. package/dist/cli/commands/env.d.ts +0 -12
  185. package/dist/cli/commands/env.d.ts.map +0 -1
  186. package/dist/cli/commands/env.js +0 -44
  187. package/dist/cli/commands/env.js.map +0 -1
  188. package/dist/cli/commands/exists.d.ts +0 -24
  189. package/dist/cli/commands/exists.d.ts.map +0 -1
  190. package/dist/cli/commands/exists.js +0 -53
  191. package/dist/cli/commands/exists.js.map +0 -1
  192. package/dist/cli/commands/export-tasks.d.ts +0 -10
  193. package/dist/cli/commands/export-tasks.d.ts.map +0 -1
  194. package/dist/cli/commands/export-tasks.js +0 -47
  195. package/dist/cli/commands/export-tasks.js.map +0 -1
  196. package/dist/cli/commands/export.d.ts +0 -9
  197. package/dist/cli/commands/export.d.ts.map +0 -1
  198. package/dist/cli/commands/export.js +0 -46
  199. package/dist/cli/commands/export.js.map +0 -1
  200. package/dist/cli/commands/find.d.ts +0 -14
  201. package/dist/cli/commands/find.d.ts.map +0 -1
  202. package/dist/cli/commands/find.js +0 -152
  203. package/dist/cli/commands/find.js.map +0 -1
  204. package/dist/cli/commands/generate-changelog.d.ts +0 -14
  205. package/dist/cli/commands/generate-changelog.d.ts.map +0 -1
  206. package/dist/cli/commands/generate-changelog.js +0 -252
  207. package/dist/cli/commands/generate-changelog.js.map +0 -1
  208. package/dist/cli/commands/grade.d.ts +0 -13
  209. package/dist/cli/commands/grade.d.ts.map +0 -1
  210. package/dist/cli/commands/grade.js +0 -26
  211. package/dist/cli/commands/grade.js.map +0 -1
  212. package/dist/cli/commands/history.d.ts +0 -9
  213. package/dist/cli/commands/history.d.ts.map +0 -1
  214. package/dist/cli/commands/history.js +0 -33
  215. package/dist/cli/commands/history.js.map +0 -1
  216. package/dist/cli/commands/implementation.d.ts +0 -13
  217. package/dist/cli/commands/implementation.d.ts.map +0 -1
  218. package/dist/cli/commands/implementation.js +0 -41
  219. package/dist/cli/commands/implementation.js.map +0 -1
  220. package/dist/cli/commands/import-tasks.d.ts +0 -10
  221. package/dist/cli/commands/import-tasks.d.ts.map +0 -1
  222. package/dist/cli/commands/import-tasks.js +0 -38
  223. package/dist/cli/commands/import-tasks.js.map +0 -1
  224. package/dist/cli/commands/import.d.ts +0 -9
  225. package/dist/cli/commands/import.d.ts.map +0 -1
  226. package/dist/cli/commands/import.js +0 -28
  227. package/dist/cli/commands/import.js.map +0 -1
  228. package/dist/cli/commands/init.d.ts +0 -34
  229. package/dist/cli/commands/init.d.ts.map +0 -1
  230. package/dist/cli/commands/init.js +0 -96
  231. package/dist/cli/commands/init.js.map +0 -1
  232. package/dist/cli/commands/inject.d.ts +0 -8
  233. package/dist/cli/commands/inject.d.ts.map +0 -1
  234. package/dist/cli/commands/inject.js +0 -28
  235. package/dist/cli/commands/inject.js.map +0 -1
  236. package/dist/cli/commands/intelligence.d.ts +0 -22
  237. package/dist/cli/commands/intelligence.d.ts.map +0 -1
  238. package/dist/cli/commands/intelligence.js +0 -72
  239. package/dist/cli/commands/intelligence.js.map +0 -1
  240. package/dist/cli/commands/issue.d.ts +0 -17
  241. package/dist/cli/commands/issue.d.ts.map +0 -1
  242. package/dist/cli/commands/issue.js +0 -107
  243. package/dist/cli/commands/issue.js.map +0 -1
  244. package/dist/cli/commands/labels.d.ts +0 -17
  245. package/dist/cli/commands/labels.d.ts.map +0 -1
  246. package/dist/cli/commands/labels.js +0 -48
  247. package/dist/cli/commands/labels.js.map +0 -1
  248. package/dist/cli/commands/lifecycle.d.ts +0 -8
  249. package/dist/cli/commands/lifecycle.d.ts.map +0 -1
  250. package/dist/cli/commands/lifecycle.js +0 -128
  251. package/dist/cli/commands/lifecycle.js.map +0 -1
  252. package/dist/cli/commands/list.d.ts +0 -14
  253. package/dist/cli/commands/list.d.ts.map +0 -1
  254. package/dist/cli/commands/list.js +0 -143
  255. package/dist/cli/commands/list.js.map +0 -1
  256. package/dist/cli/commands/log.d.ts +0 -12
  257. package/dist/cli/commands/log.d.ts.map +0 -1
  258. package/dist/cli/commands/log.js +0 -30
  259. package/dist/cli/commands/log.js.map +0 -1
  260. package/dist/cli/commands/map.d.ts +0 -10
  261. package/dist/cli/commands/map.d.ts.map +0 -1
  262. package/dist/cli/commands/map.js +0 -23
  263. package/dist/cli/commands/map.js.map +0 -1
  264. package/dist/cli/commands/memory-brain.d.ts +0 -15
  265. package/dist/cli/commands/memory-brain.d.ts.map +0 -1
  266. package/dist/cli/commands/memory-brain.js +0 -436
  267. package/dist/cli/commands/memory-brain.js.map +0 -1
  268. package/dist/cli/commands/migrate-claude-mem.d.ts +0 -23
  269. package/dist/cli/commands/migrate-claude-mem.d.ts.map +0 -1
  270. package/dist/cli/commands/migrate-claude-mem.js +0 -79
  271. package/dist/cli/commands/migrate-claude-mem.js.map +0 -1
  272. package/dist/cli/commands/next.d.ts +0 -9
  273. package/dist/cli/commands/next.d.ts.map +0 -1
  274. package/dist/cli/commands/next.js +0 -20
  275. package/dist/cli/commands/next.js.map +0 -1
  276. package/dist/cli/commands/nexus.d.ts +0 -20
  277. package/dist/cli/commands/nexus.d.ts.map +0 -1
  278. package/dist/cli/commands/nexus.js +0 -2290
  279. package/dist/cli/commands/nexus.js.map +0 -1
  280. package/dist/cli/commands/observe.d.ts +0 -13
  281. package/dist/cli/commands/observe.d.ts.map +0 -1
  282. package/dist/cli/commands/observe.js +0 -30
  283. package/dist/cli/commands/observe.js.map +0 -1
  284. package/dist/cli/commands/ops.d.ts +0 -10
  285. package/dist/cli/commands/ops.d.ts.map +0 -1
  286. package/dist/cli/commands/ops.js +0 -19
  287. package/dist/cli/commands/ops.js.map +0 -1
  288. package/dist/cli/commands/orchestrate.d.ts +0 -24
  289. package/dist/cli/commands/orchestrate.d.ts.map +0 -1
  290. package/dist/cli/commands/orchestrate.js +0 -254
  291. package/dist/cli/commands/orchestrate.js.map +0 -1
  292. package/dist/cli/commands/otel.d.ts +0 -12
  293. package/dist/cli/commands/otel.d.ts.map +0 -1
  294. package/dist/cli/commands/otel.js +0 -128
  295. package/dist/cli/commands/otel.js.map +0 -1
  296. package/dist/cli/commands/phase.d.ts +0 -12
  297. package/dist/cli/commands/phase.d.ts.map +0 -1
  298. package/dist/cli/commands/phase.js +0 -91
  299. package/dist/cli/commands/phase.js.map +0 -1
  300. package/dist/cli/commands/phases.d.ts +0 -14
  301. package/dist/cli/commands/phases.d.ts.map +0 -1
  302. package/dist/cli/commands/phases.js +0 -42
  303. package/dist/cli/commands/phases.js.map +0 -1
  304. package/dist/cli/commands/plan.d.ts +0 -8
  305. package/dist/cli/commands/plan.d.ts.map +0 -1
  306. package/dist/cli/commands/plan.js +0 -15
  307. package/dist/cli/commands/plan.js.map +0 -1
  308. package/dist/cli/commands/promote.d.ts +0 -11
  309. package/dist/cli/commands/promote.d.ts.map +0 -1
  310. package/dist/cli/commands/promote.js +0 -18
  311. package/dist/cli/commands/promote.js.map +0 -1
  312. package/dist/cli/commands/provider.d.ts +0 -21
  313. package/dist/cli/commands/provider.d.ts.map +0 -1
  314. package/dist/cli/commands/provider.js +0 -88
  315. package/dist/cli/commands/provider.js.map +0 -1
  316. package/dist/cli/commands/reason.d.ts +0 -36
  317. package/dist/cli/commands/reason.d.ts.map +0 -1
  318. package/dist/cli/commands/reason.js +0 -85
  319. package/dist/cli/commands/reason.js.map +0 -1
  320. package/dist/cli/commands/refresh-memory.d.ts +0 -9
  321. package/dist/cli/commands/refresh-memory.d.ts.map +0 -1
  322. package/dist/cli/commands/refresh-memory.js +0 -24
  323. package/dist/cli/commands/refresh-memory.js.map +0 -1
  324. package/dist/cli/commands/relates.d.ts +0 -12
  325. package/dist/cli/commands/relates.d.ts.map +0 -1
  326. package/dist/cli/commands/relates.js +0 -53
  327. package/dist/cli/commands/relates.js.map +0 -1
  328. package/dist/cli/commands/release.d.ts +0 -8
  329. package/dist/cli/commands/release.d.ts.map +0 -1
  330. package/dist/cli/commands/release.js +0 -82
  331. package/dist/cli/commands/release.js.map +0 -1
  332. package/dist/cli/commands/remote.d.ts +0 -12
  333. package/dist/cli/commands/remote.d.ts.map +0 -1
  334. package/dist/cli/commands/remote.js +0 -207
  335. package/dist/cli/commands/remote.js.map +0 -1
  336. package/dist/cli/commands/reorder.d.ts +0 -17
  337. package/dist/cli/commands/reorder.d.ts.map +0 -1
  338. package/dist/cli/commands/reorder.js +0 -41
  339. package/dist/cli/commands/reorder.js.map +0 -1
  340. package/dist/cli/commands/reparent.d.ts +0 -10
  341. package/dist/cli/commands/reparent.d.ts.map +0 -1
  342. package/dist/cli/commands/reparent.js +0 -19
  343. package/dist/cli/commands/reparent.js.map +0 -1
  344. package/dist/cli/commands/research.d.ts +0 -8
  345. package/dist/cli/commands/research.d.ts.map +0 -1
  346. package/dist/cli/commands/research.js +0 -164
  347. package/dist/cli/commands/research.js.map +0 -1
  348. package/dist/cli/commands/restore.d.ts +0 -54
  349. package/dist/cli/commands/restore.d.ts.map +0 -1
  350. package/dist/cli/commands/restore.js +0 -470
  351. package/dist/cli/commands/restore.js.map +0 -1
  352. package/dist/cli/commands/roadmap.d.ts +0 -14
  353. package/dist/cli/commands/roadmap.d.ts.map +0 -1
  354. package/dist/cli/commands/roadmap.js +0 -26
  355. package/dist/cli/commands/roadmap.js.map +0 -1
  356. package/dist/cli/commands/safestop.d.ts +0 -14
  357. package/dist/cli/commands/safestop.d.ts.map +0 -1
  358. package/dist/cli/commands/safestop.js +0 -32
  359. package/dist/cli/commands/safestop.js.map +0 -1
  360. package/dist/cli/commands/schema.d.ts +0 -27
  361. package/dist/cli/commands/schema.d.ts.map +0 -1
  362. package/dist/cli/commands/schema.js +0 -160
  363. package/dist/cli/commands/schema.js.map +0 -1
  364. package/dist/cli/commands/self-update.d.ts +0 -15
  365. package/dist/cli/commands/self-update.d.ts.map +0 -1
  366. package/dist/cli/commands/self-update.js +0 -363
  367. package/dist/cli/commands/self-update.js.map +0 -1
  368. package/dist/cli/commands/sequence.d.ts +0 -11
  369. package/dist/cli/commands/sequence.d.ts.map +0 -1
  370. package/dist/cli/commands/sequence.js +0 -40
  371. package/dist/cli/commands/sequence.js.map +0 -1
  372. package/dist/cli/commands/session.d.ts +0 -12
  373. package/dist/cli/commands/session.d.ts.map +0 -1
  374. package/dist/cli/commands/session.js +0 -219
  375. package/dist/cli/commands/session.js.map +0 -1
  376. package/dist/cli/commands/show.d.ts +0 -13
  377. package/dist/cli/commands/show.d.ts.map +0 -1
  378. package/dist/cli/commands/show.js +0 -40
  379. package/dist/cli/commands/show.js.map +0 -1
  380. package/dist/cli/commands/skills.d.ts +0 -13
  381. package/dist/cli/commands/skills.d.ts.map +0 -1
  382. package/dist/cli/commands/skills.js +0 -161
  383. package/dist/cli/commands/skills.js.map +0 -1
  384. package/dist/cli/commands/snapshot.d.ts +0 -9
  385. package/dist/cli/commands/snapshot.d.ts.map +0 -1
  386. package/dist/cli/commands/snapshot.js +0 -50
  387. package/dist/cli/commands/snapshot.js.map +0 -1
  388. package/dist/cli/commands/specification.d.ts +0 -13
  389. package/dist/cli/commands/specification.d.ts.map +0 -1
  390. package/dist/cli/commands/specification.js +0 -45
  391. package/dist/cli/commands/specification.js.map +0 -1
  392. package/dist/cli/commands/start.d.ts +0 -13
  393. package/dist/cli/commands/start.d.ts.map +0 -1
  394. package/dist/cli/commands/start.js +0 -20
  395. package/dist/cli/commands/start.js.map +0 -1
  396. package/dist/cli/commands/stats.d.ts +0 -12
  397. package/dist/cli/commands/stats.d.ts.map +0 -1
  398. package/dist/cli/commands/stats.js +0 -35
  399. package/dist/cli/commands/stats.js.map +0 -1
  400. package/dist/cli/commands/sticky.d.ts +0 -16
  401. package/dist/cli/commands/sticky.d.ts.map +0 -1
  402. package/dist/cli/commands/sticky.js +0 -218
  403. package/dist/cli/commands/sticky.js.map +0 -1
  404. package/dist/cli/commands/stop.d.ts +0 -13
  405. package/dist/cli/commands/stop.d.ts.map +0 -1
  406. package/dist/cli/commands/stop.js +0 -20
  407. package/dist/cli/commands/stop.js.map +0 -1
  408. package/dist/cli/commands/sync.d.ts +0 -26
  409. package/dist/cli/commands/sync.d.ts.map +0 -1
  410. package/dist/cli/commands/sync.js +0 -82
  411. package/dist/cli/commands/sync.js.map +0 -1
  412. package/dist/cli/commands/testing.d.ts +0 -13
  413. package/dist/cli/commands/testing.d.ts.map +0 -1
  414. package/dist/cli/commands/testing.js +0 -65
  415. package/dist/cli/commands/testing.js.map +0 -1
  416. package/dist/cli/commands/token.d.ts +0 -10
  417. package/dist/cli/commands/token.d.ts.map +0 -1
  418. package/dist/cli/commands/token.js +0 -135
  419. package/dist/cli/commands/token.js.map +0 -1
  420. package/dist/cli/commands/update.d.ts +0 -12
  421. package/dist/cli/commands/update.d.ts.map +0 -1
  422. package/dist/cli/commands/update.js +0 -83
  423. package/dist/cli/commands/update.js.map +0 -1
  424. package/dist/cli/commands/upgrade.d.ts +0 -18
  425. package/dist/cli/commands/upgrade.d.ts.map +0 -1
  426. package/dist/cli/commands/upgrade.js +0 -103
  427. package/dist/cli/commands/upgrade.js.map +0 -1
  428. package/dist/cli/commands/validate.d.ts +0 -12
  429. package/dist/cli/commands/validate.d.ts.map +0 -1
  430. package/dist/cli/commands/validate.js +0 -24
  431. package/dist/cli/commands/validate.js.map +0 -1
  432. package/dist/cli/commands/verify.d.ts +0 -8
  433. package/dist/cli/commands/verify.d.ts.map +0 -1
  434. package/dist/cli/commands/verify.js +0 -28
  435. package/dist/cli/commands/verify.js.map +0 -1
  436. package/dist/cli/commands/web.d.ts +0 -19
  437. package/dist/cli/commands/web.d.ts.map +0 -1
  438. package/dist/cli/commands/web.js +0 -371
  439. package/dist/cli/commands/web.js.map +0 -1
  440. package/dist/cli/field-context.d.ts +0 -32
  441. package/dist/cli/field-context.d.ts.map +0 -1
  442. package/dist/cli/field-context.js +0 -47
  443. package/dist/cli/field-context.js.map +0 -1
  444. package/dist/cli/format-context.d.ts +0 -32
  445. package/dist/cli/format-context.d.ts.map +0 -1
  446. package/dist/cli/format-context.js +0 -50
  447. package/dist/cli/format-context.js.map +0 -1
  448. package/dist/cli/help-generator.d.ts +0 -74
  449. package/dist/cli/help-generator.d.ts.map +0 -1
  450. package/dist/cli/help-generator.js +0 -229
  451. package/dist/cli/help-generator.js.map +0 -1
  452. package/dist/cli/help-renderer.d.ts +0 -28
  453. package/dist/cli/help-renderer.d.ts.map +0 -1
  454. package/dist/cli/help-renderer.js +0 -301
  455. package/dist/cli/help-renderer.js.map +0 -1
  456. package/dist/cli/index.d.ts +0 -9
  457. package/dist/cli/index.d.ts.map +0 -1
  458. package/dist/cli/logger-bootstrap.d.ts +0 -6
  459. package/dist/cli/logger-bootstrap.d.ts.map +0 -1
  460. package/dist/cli/logger-bootstrap.js +0 -10
  461. package/dist/cli/logger-bootstrap.js.map +0 -1
  462. package/dist/cli/middleware/output-format.d.ts +0 -30
  463. package/dist/cli/middleware/output-format.d.ts.map +0 -1
  464. package/dist/cli/middleware/output-format.js +0 -35
  465. package/dist/cli/middleware/output-format.js.map +0 -1
  466. package/dist/cli/progress.d.ts +0 -84
  467. package/dist/cli/progress.d.ts.map +0 -1
  468. package/dist/cli/progress.js +0 -169
  469. package/dist/cli/progress.js.map +0 -1
  470. package/dist/cli/renderers/colors.d.ts +0 -32
  471. package/dist/cli/renderers/colors.d.ts.map +0 -1
  472. package/dist/cli/renderers/colors.js +0 -141
  473. package/dist/cli/renderers/colors.js.map +0 -1
  474. package/dist/cli/renderers/error.d.ts +0 -13
  475. package/dist/cli/renderers/error.d.ts.map +0 -1
  476. package/dist/cli/renderers/error.js +0 -42
  477. package/dist/cli/renderers/error.js.map +0 -1
  478. package/dist/cli/renderers/index.d.ts +0 -87
  479. package/dist/cli/renderers/index.d.ts.map +0 -1
  480. package/dist/cli/renderers/index.js +0 -262
  481. package/dist/cli/renderers/index.js.map +0 -1
  482. package/dist/cli/renderers/lafs-validator.d.ts +0 -91
  483. package/dist/cli/renderers/lafs-validator.d.ts.map +0 -1
  484. package/dist/cli/renderers/lafs-validator.js +0 -176
  485. package/dist/cli/renderers/lafs-validator.js.map +0 -1
  486. package/dist/cli/renderers/normalizer.d.ts +0 -21
  487. package/dist/cli/renderers/normalizer.d.ts.map +0 -1
  488. package/dist/cli/renderers/normalizer.js +0 -106
  489. package/dist/cli/renderers/normalizer.js.map +0 -1
  490. package/dist/cli/renderers/system.d.ts +0 -25
  491. package/dist/cli/renderers/system.d.ts.map +0 -1
  492. package/dist/cli/renderers/system.js +0 -416
  493. package/dist/cli/renderers/system.js.map +0 -1
  494. package/dist/cli/renderers/tasks.d.ts +0 -28
  495. package/dist/cli/renderers/tasks.d.ts.map +0 -1
  496. package/dist/cli/renderers/tasks.js +0 -306
  497. package/dist/cli/renderers/tasks.js.map +0 -1
  498. package/dist/dispatch/adapters/cli.d.ts +0 -67
  499. package/dist/dispatch/adapters/cli.d.ts.map +0 -1
  500. package/dist/dispatch/adapters/cli.js +0 -331
  501. package/dist/dispatch/adapters/cli.js.map +0 -1
  502. package/dist/dispatch/context/session-context.d.ts +0 -54
  503. package/dist/dispatch/context/session-context.d.ts.map +0 -1
  504. package/dist/dispatch/context/session-context.js +0 -61
  505. package/dist/dispatch/context/session-context.js.map +0 -1
  506. package/dist/dispatch/dispatcher.d.ts +0 -23
  507. package/dist/dispatch/dispatcher.d.ts.map +0 -1
  508. package/dist/dispatch/dispatcher.js +0 -84
  509. package/dist/dispatch/dispatcher.js.map +0 -1
  510. package/dist/dispatch/domains/_base.d.ts +0 -59
  511. package/dist/dispatch/domains/_base.d.ts.map +0 -1
  512. package/dist/dispatch/domains/_base.js +0 -77
  513. package/dist/dispatch/domains/_base.js.map +0 -1
  514. package/dist/dispatch/domains/_meta.d.ts +0 -23
  515. package/dist/dispatch/domains/_meta.d.ts.map +0 -1
  516. package/dist/dispatch/domains/_meta.js +0 -25
  517. package/dist/dispatch/domains/_meta.js.map +0 -1
  518. package/dist/dispatch/domains/_routing.d.ts +0 -8
  519. package/dist/dispatch/domains/_routing.d.ts.map +0 -1
  520. package/dist/dispatch/domains/_routing.js +0 -20
  521. package/dist/dispatch/domains/_routing.js.map +0 -1
  522. package/dist/dispatch/domains/admin.d.ts +0 -25
  523. package/dist/dispatch/domains/admin.d.ts.map +0 -1
  524. package/dist/dispatch/domains/admin.js +0 -791
  525. package/dist/dispatch/domains/admin.js.map +0 -1
  526. package/dist/dispatch/domains/check.d.ts +0 -22
  527. package/dist/dispatch/domains/check.d.ts.map +0 -1
  528. package/dist/dispatch/domains/check.js +0 -381
  529. package/dist/dispatch/domains/check.js.map +0 -1
  530. package/dist/dispatch/domains/conduit.d.ts +0 -38
  531. package/dist/dispatch/domains/conduit.d.ts.map +0 -1
  532. package/dist/dispatch/domains/conduit.js +0 -360
  533. package/dist/dispatch/domains/conduit.js.map +0 -1
  534. package/dist/dispatch/domains/diagnostics.d.ts +0 -20
  535. package/dist/dispatch/domains/diagnostics.d.ts.map +0 -1
  536. package/dist/dispatch/domains/diagnostics.js +0 -77
  537. package/dist/dispatch/domains/diagnostics.js.map +0 -1
  538. package/dist/dispatch/domains/index.d.ts +0 -29
  539. package/dist/dispatch/domains/index.d.ts.map +0 -1
  540. package/dist/dispatch/domains/index.js +0 -45
  541. package/dist/dispatch/domains/index.js.map +0 -1
  542. package/dist/dispatch/domains/intelligence.d.ts +0 -26
  543. package/dist/dispatch/domains/intelligence.d.ts.map +0 -1
  544. package/dist/dispatch/domains/intelligence.js +0 -154
  545. package/dist/dispatch/domains/intelligence.js.map +0 -1
  546. package/dist/dispatch/domains/memory.d.ts +0 -22
  547. package/dist/dispatch/domains/memory.d.ts.map +0 -1
  548. package/dist/dispatch/domains/memory.js +0 -387
  549. package/dist/dispatch/domains/memory.js.map +0 -1
  550. package/dist/dispatch/domains/nexus.d.ts +0 -22
  551. package/dist/dispatch/domains/nexus.d.ts.map +0 -1
  552. package/dist/dispatch/domains/nexus.js +0 -286
  553. package/dist/dispatch/domains/nexus.js.map +0 -1
  554. package/dist/dispatch/domains/orchestrate.d.ts +0 -26
  555. package/dist/dispatch/domains/orchestrate.d.ts.map +0 -1
  556. package/dist/dispatch/domains/orchestrate.js +0 -691
  557. package/dist/dispatch/domains/orchestrate.js.map +0 -1
  558. package/dist/dispatch/domains/pipeline.d.ts +0 -35
  559. package/dist/dispatch/domains/pipeline.d.ts.map +0 -1
  560. package/dist/dispatch/domains/pipeline.js +0 -593
  561. package/dist/dispatch/domains/pipeline.js.map +0 -1
  562. package/dist/dispatch/domains/session.d.ts +0 -22
  563. package/dist/dispatch/domains/session.d.ts.map +0 -1
  564. package/dist/dispatch/domains/session.js +0 -267
  565. package/dist/dispatch/domains/session.js.map +0 -1
  566. package/dist/dispatch/domains/sticky.d.ts +0 -20
  567. package/dist/dispatch/domains/sticky.d.ts.map +0 -1
  568. package/dist/dispatch/domains/sticky.js +0 -167
  569. package/dist/dispatch/domains/sticky.js.map +0 -1
  570. package/dist/dispatch/domains/tasks.d.ts +0 -25
  571. package/dist/dispatch/domains/tasks.d.ts.map +0 -1
  572. package/dist/dispatch/domains/tasks.js +0 -368
  573. package/dist/dispatch/domains/tasks.js.map +0 -1
  574. package/dist/dispatch/domains/tools.d.ts +0 -37
  575. package/dist/dispatch/domains/tools.d.ts.map +0 -1
  576. package/dist/dispatch/domains/tools.js +0 -481
  577. package/dist/dispatch/domains/tools.js.map +0 -1
  578. package/dist/dispatch/engines/_error.d.ts +0 -119
  579. package/dist/dispatch/engines/_error.d.ts.map +0 -1
  580. package/dist/dispatch/engines/_error.js +0 -298
  581. package/dist/dispatch/engines/_error.js.map +0 -1
  582. package/dist/dispatch/engines/code-engine.d.ts +0 -18
  583. package/dist/dispatch/engines/code-engine.d.ts.map +0 -1
  584. package/dist/dispatch/engines/code-engine.js +0 -71
  585. package/dist/dispatch/engines/code-engine.js.map +0 -1
  586. package/dist/dispatch/engines/codebase-map-engine.d.ts +0 -31
  587. package/dist/dispatch/engines/codebase-map-engine.d.ts.map +0 -1
  588. package/dist/dispatch/engines/codebase-map-engine.js +0 -43
  589. package/dist/dispatch/engines/codebase-map-engine.js.map +0 -1
  590. package/dist/dispatch/engines/config-engine.d.ts +0 -32
  591. package/dist/dispatch/engines/config-engine.d.ts.map +0 -1
  592. package/dist/dispatch/engines/config-engine.js +0 -70
  593. package/dist/dispatch/engines/config-engine.js.map +0 -1
  594. package/dist/dispatch/engines/diagnostics-engine.d.ts +0 -57
  595. package/dist/dispatch/engines/diagnostics-engine.d.ts.map +0 -1
  596. package/dist/dispatch/engines/diagnostics-engine.js +0 -163
  597. package/dist/dispatch/engines/diagnostics-engine.js.map +0 -1
  598. package/dist/dispatch/engines/hooks-engine.d.ts +0 -96
  599. package/dist/dispatch/engines/hooks-engine.d.ts.map +0 -1
  600. package/dist/dispatch/engines/hooks-engine.js +0 -144
  601. package/dist/dispatch/engines/hooks-engine.js.map +0 -1
  602. package/dist/dispatch/engines/init-engine.d.ts +0 -56
  603. package/dist/dispatch/engines/init-engine.d.ts.map +0 -1
  604. package/dist/dispatch/engines/init-engine.js +0 -78
  605. package/dist/dispatch/engines/init-engine.js.map +0 -1
  606. package/dist/dispatch/engines/lifecycle-engine.d.ts +0 -66
  607. package/dist/dispatch/engines/lifecycle-engine.d.ts.map +0 -1
  608. package/dist/dispatch/engines/lifecycle-engine.js +0 -224
  609. package/dist/dispatch/engines/lifecycle-engine.js.map +0 -1
  610. package/dist/dispatch/engines/memory-engine.d.ts +0 -10
  611. package/dist/dispatch/engines/memory-engine.d.ts.map +0 -1
  612. package/dist/dispatch/engines/memory-engine.js +0 -10
  613. package/dist/dispatch/engines/memory-engine.js.map +0 -1
  614. package/dist/dispatch/engines/nexus-engine.d.ts +0 -167
  615. package/dist/dispatch/engines/nexus-engine.d.ts.map +0 -1
  616. package/dist/dispatch/engines/nexus-engine.js +0 -356
  617. package/dist/dispatch/engines/nexus-engine.js.map +0 -1
  618. package/dist/dispatch/engines/orchestrate-engine.d.ts +0 -141
  619. package/dist/dispatch/engines/orchestrate-engine.d.ts.map +0 -1
  620. package/dist/dispatch/engines/orchestrate-engine.js +0 -892
  621. package/dist/dispatch/engines/orchestrate-engine.js.map +0 -1
  622. package/dist/dispatch/engines/pipeline-engine.d.ts +0 -51
  623. package/dist/dispatch/engines/pipeline-engine.d.ts.map +0 -1
  624. package/dist/dispatch/engines/pipeline-engine.js +0 -191
  625. package/dist/dispatch/engines/pipeline-engine.js.map +0 -1
  626. package/dist/dispatch/engines/release-engine.d.ts +0 -94
  627. package/dist/dispatch/engines/release-engine.d.ts.map +0 -1
  628. package/dist/dispatch/engines/release-engine.js +0 -763
  629. package/dist/dispatch/engines/release-engine.js.map +0 -1
  630. package/dist/dispatch/engines/session-engine.d.ts +0 -387
  631. package/dist/dispatch/engines/session-engine.d.ts.map +0 -1
  632. package/dist/dispatch/engines/session-engine.js +0 -924
  633. package/dist/dispatch/engines/session-engine.js.map +0 -1
  634. package/dist/dispatch/engines/sticky-engine.d.ts +0 -100
  635. package/dist/dispatch/engines/sticky-engine.d.ts.map +0 -1
  636. package/dist/dispatch/engines/sticky-engine.js +0 -181
  637. package/dist/dispatch/engines/sticky-engine.js.map +0 -1
  638. package/dist/dispatch/engines/system-engine.d.ts +0 -543
  639. package/dist/dispatch/engines/system-engine.d.ts.map +0 -1
  640. package/dist/dispatch/engines/system-engine.js +0 -1273
  641. package/dist/dispatch/engines/system-engine.js.map +0 -1
  642. package/dist/dispatch/engines/task-engine.d.ts +0 -971
  643. package/dist/dispatch/engines/task-engine.d.ts.map +0 -1
  644. package/dist/dispatch/engines/task-engine.js +0 -1255
  645. package/dist/dispatch/engines/task-engine.js.map +0 -1
  646. package/dist/dispatch/engines/template-parser.d.ts +0 -85
  647. package/dist/dispatch/engines/template-parser.d.ts.map +0 -1
  648. package/dist/dispatch/engines/template-parser.js +0 -108
  649. package/dist/dispatch/engines/template-parser.js.map +0 -1
  650. package/dist/dispatch/engines/tools-engine.d.ts +0 -270
  651. package/dist/dispatch/engines/tools-engine.d.ts.map +0 -1
  652. package/dist/dispatch/engines/tools-engine.js +0 -663
  653. package/dist/dispatch/engines/tools-engine.js.map +0 -1
  654. package/dist/dispatch/engines/validate-engine.d.ts +0 -218
  655. package/dist/dispatch/engines/validate-engine.d.ts.map +0 -1
  656. package/dist/dispatch/engines/validate-engine.js +0 -737
  657. package/dist/dispatch/engines/validate-engine.js.map +0 -1
  658. package/dist/dispatch/index.d.ts +0 -20
  659. package/dist/dispatch/index.d.ts.map +0 -1
  660. package/dist/dispatch/index.js +0 -19
  661. package/dist/dispatch/index.js.map +0 -1
  662. package/dist/dispatch/lib/background-jobs.d.ts +0 -86
  663. package/dist/dispatch/lib/background-jobs.d.ts.map +0 -1
  664. package/dist/dispatch/lib/background-jobs.js +0 -183
  665. package/dist/dispatch/lib/background-jobs.js.map +0 -1
  666. package/dist/dispatch/lib/budget.d.ts +0 -36
  667. package/dist/dispatch/lib/budget.d.ts.map +0 -1
  668. package/dist/dispatch/lib/budget.js +0 -109
  669. package/dist/dispatch/lib/budget.js.map +0 -1
  670. package/dist/dispatch/lib/capability-matrix.d.ts +0 -11
  671. package/dist/dispatch/lib/capability-matrix.d.ts.map +0 -1
  672. package/dist/dispatch/lib/capability-matrix.js +0 -10
  673. package/dist/dispatch/lib/capability-matrix.js.map +0 -1
  674. package/dist/dispatch/lib/config-loader.d.ts +0 -42
  675. package/dist/dispatch/lib/config-loader.d.ts.map +0 -1
  676. package/dist/dispatch/lib/config-loader.js +0 -217
  677. package/dist/dispatch/lib/config-loader.js.map +0 -1
  678. package/dist/dispatch/lib/config.d.ts +0 -11
  679. package/dist/dispatch/lib/config.d.ts.map +0 -1
  680. package/dist/dispatch/lib/config.js +0 -10
  681. package/dist/dispatch/lib/config.js.map +0 -1
  682. package/dist/dispatch/lib/defaults.d.ts +0 -115
  683. package/dist/dispatch/lib/defaults.d.ts.map +0 -1
  684. package/dist/dispatch/lib/defaults.js +0 -61
  685. package/dist/dispatch/lib/defaults.js.map +0 -1
  686. package/dist/dispatch/lib/engine.d.ts +0 -26
  687. package/dist/dispatch/lib/engine.d.ts.map +0 -1
  688. package/dist/dispatch/lib/engine.js +0 -46
  689. package/dist/dispatch/lib/engine.js.map +0 -1
  690. package/dist/dispatch/lib/exit-codes.d.ts +0 -35
  691. package/dist/dispatch/lib/exit-codes.d.ts.map +0 -1
  692. package/dist/dispatch/lib/exit-codes.js +0 -60
  693. package/dist/dispatch/lib/exit-codes.js.map +0 -1
  694. package/dist/dispatch/lib/gateway-meta.d.ts +0 -37
  695. package/dist/dispatch/lib/gateway-meta.d.ts.map +0 -1
  696. package/dist/dispatch/lib/gateway-meta.js +0 -50
  697. package/dist/dispatch/lib/gateway-meta.js.map +0 -1
  698. package/dist/dispatch/lib/job-manager-accessor.d.ts +0 -9
  699. package/dist/dispatch/lib/job-manager-accessor.d.ts.map +0 -1
  700. package/dist/dispatch/lib/job-manager-accessor.js +0 -13
  701. package/dist/dispatch/lib/job-manager-accessor.js.map +0 -1
  702. package/dist/dispatch/lib/meta.d.ts +0 -26
  703. package/dist/dispatch/lib/meta.d.ts.map +0 -1
  704. package/dist/dispatch/lib/meta.js +0 -37
  705. package/dist/dispatch/lib/meta.js.map +0 -1
  706. package/dist/dispatch/lib/param-utils.d.ts +0 -11
  707. package/dist/dispatch/lib/param-utils.d.ts.map +0 -1
  708. package/dist/dispatch/lib/param-utils.js +0 -10
  709. package/dist/dispatch/lib/param-utils.js.map +0 -1
  710. package/dist/dispatch/lib/projections.d.ts +0 -56
  711. package/dist/dispatch/lib/projections.d.ts.map +0 -1
  712. package/dist/dispatch/lib/projections.js +0 -65
  713. package/dist/dispatch/lib/projections.js.map +0 -1
  714. package/dist/dispatch/lib/proto-envelope.d.ts +0 -56
  715. package/dist/dispatch/lib/proto-envelope.d.ts.map +0 -1
  716. package/dist/dispatch/lib/proto-envelope.js +0 -17
  717. package/dist/dispatch/lib/proto-envelope.js.map +0 -1
  718. package/dist/dispatch/lib/schema-utils.d.ts +0 -39
  719. package/dist/dispatch/lib/schema-utils.d.ts.map +0 -1
  720. package/dist/dispatch/lib/schema-utils.js +0 -88
  721. package/dist/dispatch/lib/schema-utils.js.map +0 -1
  722. package/dist/dispatch/lib/security.d.ts +0 -11
  723. package/dist/dispatch/lib/security.d.ts.map +0 -1
  724. package/dist/dispatch/lib/security.js +0 -10
  725. package/dist/dispatch/lib/security.js.map +0 -1
  726. package/dist/dispatch/middleware/audit.d.ts +0 -23
  727. package/dist/dispatch/middleware/audit.d.ts.map +0 -1
  728. package/dist/dispatch/middleware/audit.js +0 -169
  729. package/dist/dispatch/middleware/audit.js.map +0 -1
  730. package/dist/dispatch/middleware/field-filter.d.ts +0 -25
  731. package/dist/dispatch/middleware/field-filter.d.ts.map +0 -1
  732. package/dist/dispatch/middleware/field-filter.js +0 -70
  733. package/dist/dispatch/middleware/field-filter.js.map +0 -1
  734. package/dist/dispatch/middleware/pipeline.d.ts +0 -33
  735. package/dist/dispatch/middleware/pipeline.d.ts.map +0 -1
  736. package/dist/dispatch/middleware/pipeline.js +0 -60
  737. package/dist/dispatch/middleware/pipeline.js.map +0 -1
  738. package/dist/dispatch/middleware/projection.d.ts +0 -35
  739. package/dist/dispatch/middleware/projection.d.ts.map +0 -1
  740. package/dist/dispatch/middleware/projection.js +0 -146
  741. package/dist/dispatch/middleware/projection.js.map +0 -1
  742. package/dist/dispatch/middleware/protocol-enforcement.d.ts +0 -30
  743. package/dist/dispatch/middleware/protocol-enforcement.d.ts.map +0 -1
  744. package/dist/dispatch/middleware/protocol-enforcement.js +0 -56
  745. package/dist/dispatch/middleware/protocol-enforcement.js.map +0 -1
  746. package/dist/dispatch/middleware/rate-limiter.d.ts +0 -72
  747. package/dist/dispatch/middleware/rate-limiter.d.ts.map +0 -1
  748. package/dist/dispatch/middleware/rate-limiter.js +0 -127
  749. package/dist/dispatch/middleware/rate-limiter.js.map +0 -1
  750. package/dist/dispatch/middleware/sanitizer.d.ts +0 -24
  751. package/dist/dispatch/middleware/sanitizer.d.ts.map +0 -1
  752. package/dist/dispatch/middleware/sanitizer.js +0 -56
  753. package/dist/dispatch/middleware/sanitizer.js.map +0 -1
  754. package/dist/dispatch/middleware/session-resolver.d.ts +0 -26
  755. package/dist/dispatch/middleware/session-resolver.d.ts.map +0 -1
  756. package/dist/dispatch/middleware/session-resolver.js +0 -65
  757. package/dist/dispatch/middleware/session-resolver.js.map +0 -1
  758. package/dist/dispatch/middleware/telemetry.d.ts +0 -21
  759. package/dist/dispatch/middleware/telemetry.d.ts.map +0 -1
  760. package/dist/dispatch/middleware/telemetry.js +0 -50
  761. package/dist/dispatch/middleware/telemetry.js.map +0 -1
  762. package/dist/dispatch/middleware/verification-gates.d.ts +0 -22
  763. package/dist/dispatch/middleware/verification-gates.d.ts.map +0 -1
  764. package/dist/dispatch/middleware/verification-gates.js +0 -59
  765. package/dist/dispatch/middleware/verification-gates.js.map +0 -1
  766. package/dist/dispatch/registry.d.ts +0 -91
  767. package/dist/dispatch/registry.d.ts.map +0 -1
  768. package/dist/dispatch/registry.js +0 -3535
  769. package/dist/dispatch/registry.js.map +0 -1
  770. package/dist/dispatch/types.d.ts +0 -206
  771. package/dist/dispatch/types.d.ts.map +0 -1
  772. package/dist/dispatch/types.js +0 -27
  773. package/dist/dispatch/types.js.map +0 -1
@@ -1,2290 +0,0 @@
1
- /**
2
- * CLI nexus command group - Cross-project NEXUS operations.
3
- *
4
- * Thin CLI wrappers routing through the dispatch layer.
5
- * All business logic lives in src/dispatch/domains/nexus.ts.
6
- *
7
- * `nexus analyze` is implemented directly here because it requires
8
- * `@cleocode/nexus` pipeline access and `@cleocode/core` DB access together,
9
- * and routing through the dispatch layer would create awkward coupling.
10
- *
11
- * @task T4554, T5323, T5330, T481, T534
12
- * @epic T4545
13
- */
14
- import path from 'node:path';
15
- import { dispatchFromCli } from '../../dispatch/adapters/cli.js';
16
- /**
17
- * Priority score for nexus node kinds when ranking symbol search results.
18
- *
19
- * Callable symbols (function, method) rank highest so that `nexus context`
20
- * and `nexus impact` return meaningful callers/callees instead of
21
- * file/folder structural nodes which have zero `calls` relations.
22
- *
23
- * Lower score = higher priority (sort ascending).
24
- */
25
- const NODE_KIND_PRIORITY = {
26
- function: 0,
27
- method: 1,
28
- constructor: 2,
29
- class: 3,
30
- interface: 4,
31
- type_alias: 5,
32
- enum: 6,
33
- constant: 7,
34
- property: 8,
35
- variable: 9,
36
- static: 10,
37
- struct: 11,
38
- trait: 12,
39
- impl: 13,
40
- macro: 14,
41
- // Structural/module nodes come last — they have no `calls` relations
42
- module: 20,
43
- namespace: 21,
44
- record: 22,
45
- delegate: 23,
46
- union: 24,
47
- typedef: 25,
48
- annotation: 26,
49
- template: 27,
50
- route: 28,
51
- tool: 29,
52
- section: 30,
53
- import: 31,
54
- export: 32,
55
- type: 33,
56
- file: 40,
57
- folder: 41,
58
- };
59
- /**
60
- * Generate GEXF (Gephi Graph Exchange XML Format) from nodes and relations.
61
- *
62
- * GEXF is a standard format for graph visualization. Supports node attributes,
63
- * edge weights (confidence), and color coding by node kind.
64
- *
65
- * @param nodes - Array of nexus nodes
66
- * @param relations - Array of nexus relations
67
- * @returns GEXF XML string
68
- */
69
- function generateGexf(nodes, relations) {
70
- // Build node by ID map for edge resolution
71
- const nodeById = new Map();
72
- for (const n of nodes) {
73
- nodeById.set(String(n['id']), n);
74
- }
75
- // Color map for node kinds (hex colors for visualization)
76
- const kindColors = {
77
- function: '#3498db', // blue
78
- method: '#2980b9', // darker blue
79
- class: '#e74c3c', // red
80
- interface: '#e67e22', // orange
81
- file: '#95a5a6', // gray
82
- folder: '#34495e', // dark gray
83
- community: '#9b59b6', // purple
84
- process: '#1abc9c', // teal
85
- import: '#f39c12', // amber
86
- default: '#7f8c8d', // medium gray
87
- };
88
- const getNodeColor = (kind) => {
89
- return kindColors[kind] ?? kindColors['default'];
90
- };
91
- // GEXF XML header
92
- let gexf = '<?xml version="1.0" encoding="UTF-8"?>\n';
93
- gexf +=
94
- '<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:viz="http://www.gexf.net/1.2draft/viz" version="1.2">\n';
95
- gexf += ' <meta lastmodifieddate="' + new Date().toISOString().split('T')[0] + '">\n';
96
- gexf += ' <creator>CLEO nexus export</creator>\n';
97
- gexf += ' <description>Code intelligence graph from CLEO nexus</description>\n';
98
- gexf += ' </meta>\n';
99
- gexf += ' <graph mode="static" defaultedgetype="directed">\n';
100
- // Attributes
101
- gexf += ' <attributes class="node">\n';
102
- gexf += ' <attribute id="kind" title="Node Kind" type="string" />\n';
103
- gexf += ' <attribute id="filePath" title="File Path" type="string" />\n';
104
- gexf += ' <attribute id="language" title="Language" type="string" />\n';
105
- gexf += ' <attribute id="startLine" title="Start Line" type="integer" />\n';
106
- gexf += ' <attribute id="endLine" title="End Line" type="integer" />\n';
107
- gexf += ' <attribute id="isExported" title="Is Exported" type="boolean" />\n';
108
- gexf += ' <attribute id="projectId" title="Project ID" type="string" />\n';
109
- gexf += ' </attributes>\n';
110
- gexf += ' <attributes class="edge">\n';
111
- gexf += ' <attribute id="relationType" title="Relation Type" type="string" />\n';
112
- gexf += ' <attribute id="confidence" title="Confidence" type="double" />\n';
113
- gexf += ' <attribute id="reason" title="Reason" type="string" />\n';
114
- gexf += ' </attributes>\n';
115
- // Nodes
116
- gexf += ' <nodes>\n';
117
- for (const node of nodes) {
118
- const nodeId = String(node['id']).replace(/[<>"'&]/g, (c) => {
119
- const map = {
120
- '<': '&lt;',
121
- '>': '&gt;',
122
- '"': '&quot;',
123
- "'": '&apos;',
124
- '&': '&amp;',
125
- };
126
- return map[c];
127
- });
128
- const label = String(node['label'] ?? node['id']);
129
- const kind = String(node['kind'] ?? 'unknown');
130
- const color = getNodeColor(kind);
131
- gexf += ` <node id="${nodeId}" label="${escapeXml(label)}">\n`;
132
- gexf += ` <viz:color r="${hexToRgb(color).r}" g="${hexToRgb(color).g}" b="${hexToRgb(color).b}" />\n`;
133
- gexf += ' <attvalues>\n';
134
- gexf += ` <attvalue id="kind" value="${escapeXml(kind)}" />\n`;
135
- if (node['filePath']) {
136
- gexf += ` <attvalue id="filePath" value="${escapeXml(String(node['filePath']))}" />\n`;
137
- }
138
- if (node['language']) {
139
- gexf += ` <attvalue id="language" value="${escapeXml(String(node['language']))}" />\n`;
140
- }
141
- if (node['startLine'] != null) {
142
- gexf += ` <attvalue id="startLine" value="${node['startLine']}" />\n`;
143
- }
144
- if (node['endLine'] != null) {
145
- gexf += ` <attvalue id="endLine" value="${node['endLine']}" />\n`;
146
- }
147
- if (node['isExported'] != null) {
148
- gexf += ` <attvalue id="isExported" value="${node['isExported'] ? 'true' : 'false'}" />\n`;
149
- }
150
- if (node['projectId']) {
151
- gexf += ` <attvalue id="projectId" value="${escapeXml(String(node['projectId']))}" />\n`;
152
- }
153
- gexf += ' </attvalues>\n';
154
- gexf += ' </node>\n';
155
- }
156
- gexf += ' </nodes>\n';
157
- // Edges
158
- gexf += ' <edges>\n';
159
- for (let i = 0; i < relations.length; i++) {
160
- const rel = relations[i];
161
- const sourceId = String(rel['sourceId']).replace(/[<>"'&]/g, (c) => {
162
- const map = {
163
- '<': '&lt;',
164
- '>': '&gt;',
165
- '"': '&quot;',
166
- "'": '&apos;',
167
- '&': '&amp;',
168
- };
169
- return map[c];
170
- });
171
- const targetId = String(rel['targetId']).replace(/[<>"'&]/g, (c) => {
172
- const map = {
173
- '<': '&lt;',
174
- '>': '&gt;',
175
- '"': '&quot;',
176
- "'": '&apos;',
177
- '&': '&amp;',
178
- };
179
- return map[c];
180
- });
181
- // Skip edges where source or target don't exist in our node set
182
- // (external references or unresolved imports)
183
- if (!nodeById.has(String(rel['sourceId'])) || !nodeById.has(String(rel['targetId']))) {
184
- continue;
185
- }
186
- const confidence = typeof rel['confidence'] === 'number' ? rel['confidence'] : 1.0;
187
- const relationType = String(rel['type'] ?? 'unknown');
188
- const reason = rel['reason'] ? String(rel['reason']) : '';
189
- gexf += ` <edge id="e${i}" source="${sourceId}" target="${targetId}" weight="${confidence}">\n`;
190
- gexf += ' <attvalues>\n';
191
- gexf += ` <attvalue id="relationType" value="${escapeXml(relationType)}" />\n`;
192
- gexf += ` <attvalue id="confidence" value="${confidence}" />\n`;
193
- if (reason) {
194
- gexf += ` <attvalue id="reason" value="${escapeXml(reason)}" />\n`;
195
- }
196
- gexf += ' </attvalues>\n';
197
- gexf += ' </edge>\n';
198
- }
199
- gexf += ' </edges>\n';
200
- gexf += ' </graph>\n';
201
- gexf += '</gexf>\n';
202
- return gexf;
203
- }
204
- /**
205
- * Escape XML special characters.
206
- */
207
- function escapeXml(str) {
208
- return String(str).replace(/[<>"'&]/g, (c) => {
209
- const map = {
210
- '<': '&lt;',
211
- '>': '&gt;',
212
- '"': '&quot;',
213
- "'": '&apos;',
214
- '&': '&amp;',
215
- };
216
- return map[c];
217
- });
218
- }
219
- /**
220
- * Convert hex color to RGB object.
221
- */
222
- function hexToRgb(hex) {
223
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
224
- return result
225
- ? {
226
- r: parseInt(result[1], 16),
227
- g: parseInt(result[2], 16),
228
- b: parseInt(result[3], 16),
229
- }
230
- : { r: 127, g: 140, b: 141 };
231
- }
232
- /**
233
- * Sort symbol search results so that callable nodes (function, method, class)
234
- * appear before structural nodes (file, folder). Within the same kind, prefer
235
- * exact name matches over partial matches.
236
- */
237
- function sortMatchingNodes(nodes, symbolName) {
238
- const lowerSymbol = symbolName.toLowerCase();
239
- return [...nodes].sort((a, b) => {
240
- const kindA = String(a['kind'] ?? '');
241
- const kindB = String(b['kind'] ?? '');
242
- const prioA = NODE_KIND_PRIORITY[kindA] ?? 15;
243
- const prioB = NODE_KIND_PRIORITY[kindB] ?? 15;
244
- if (prioA !== prioB)
245
- return prioA - prioB;
246
- // Within same kind: exact name matches before partial matches
247
- const nameA = String(a['name'] ?? '').toLowerCase();
248
- const nameB = String(b['name'] ?? '').toLowerCase();
249
- const exactA = nameA === lowerSymbol ? 0 : 1;
250
- const exactB = nameB === lowerSymbol ? 0 : 1;
251
- return exactA - exactB;
252
- });
253
- }
254
- /**
255
- * Register the nexus command group.
256
- * @task T4554
257
- */
258
- export function registerNexusCommand(program) {
259
- const nexus = program.command('nexus').description('Cross-project NEXUS operations');
260
- // ── nexus init ──────────────────────────────────────────────────────
261
- nexus
262
- .command('init')
263
- .description('Initialize NEXUS directory structure and registry')
264
- .action(async () => {
265
- await dispatchFromCli('mutate', 'nexus', 'init', {}, { command: 'nexus' });
266
- });
267
- // ── nexus register ──────────────────────────────────────────────────
268
- nexus
269
- .command('register <path>')
270
- .description('Register a project in the global registry')
271
- .option('--name <name>', 'Custom project name (default: directory name)')
272
- .option('--permissions <perms>', 'Permissions: read|write|execute', 'read')
273
- .action(async (projectPath, opts) => {
274
- await dispatchFromCli('mutate', 'nexus', 'register', {
275
- path: projectPath,
276
- name: opts['name'],
277
- permission: opts['permissions'],
278
- }, { command: 'nexus' });
279
- });
280
- // ── nexus unregister ────────────────────────────────────────────────
281
- nexus
282
- .command('unregister <nameOrHash>')
283
- .description('Remove a project from the registry')
284
- .action(async (nameOrHash) => {
285
- await dispatchFromCli('mutate', 'nexus', 'unregister', {
286
- name: nameOrHash,
287
- }, { command: 'nexus' });
288
- });
289
- // ── nexus list ──────────────────────────────────────────────────────
290
- nexus
291
- .command('list')
292
- .description('List all registered projects')
293
- .action(async () => {
294
- await dispatchFromCli('query', 'nexus', 'list', {}, { command: 'nexus' });
295
- });
296
- // ── nexus status ────────────────────────────────────────────────────
297
- // Shows both NEXUS registry status AND code intelligence index freshness.
298
- // When invoked with a path, shows index freshness for that project.
299
- nexus
300
- .command('status [path]')
301
- .description('Show code intelligence index freshness: file count, node/relation counts, last indexed time, stale files. Falls back to NEXUS registry status if code-intelligence index is unavailable.')
302
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from path)')
303
- .option('--json', 'Output as JSON (LAFS envelope format)')
304
- .action(async (targetPath, opts) => {
305
- const jsonOutput = !!opts['json'];
306
- const projectIdOverride = opts['projectId'];
307
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
308
- const startTime = Date.now();
309
- try {
310
- const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
311
- import('@cleocode/core/store/nexus-sqlite'),
312
- import('@cleocode/nexus/pipeline'),
313
- ]);
314
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
315
- const db = await getNexusDb();
316
- const tables = {
317
- nexusNodes: nexusSchema.nexusNodes,
318
- nexusRelations: nexusSchema.nexusRelations,
319
- };
320
- const stats = await getIndexStats(projectId, repoPath, db, tables);
321
- const durationMs = Date.now() - startTime;
322
- if (jsonOutput) {
323
- const envelope = {
324
- success: true,
325
- data: { projectId, repoPath, ...stats },
326
- meta: {
327
- operation: 'nexus.status',
328
- duration_ms: durationMs,
329
- timestamp: new Date().toISOString(),
330
- },
331
- };
332
- process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
333
- }
334
- else if (!stats.indexed) {
335
- process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
336
- ` Status: NOT INDEXED\n` +
337
- ` Run 'cleo nexus analyze' to build the index.\n`);
338
- }
339
- else {
340
- const staleLabel = stats.staleFileCount < 0
341
- ? 'unknown'
342
- : stats.staleFileCount === 0
343
- ? 'up to date'
344
- : `${stats.staleFileCount} stale`;
345
- process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
346
- ` Project ID: ${projectId}\n` +
347
- ` Nodes: ${stats.nodeCount}\n` +
348
- ` Relations: ${stats.relationCount}\n` +
349
- ` Files: ${stats.fileCount}\n` +
350
- ` Last indexed: ${stats.lastIndexedAt ?? 'never'}\n` +
351
- ` Staleness: ${staleLabel}\n`);
352
- }
353
- }
354
- catch (err) {
355
- // Fall back to NEXUS registry status on error
356
- const msg = err instanceof Error ? err.message : String(err);
357
- if (jsonOutput) {
358
- process.stdout.write(JSON.stringify({
359
- success: false,
360
- error: { code: 'E_STATUS_FAILED', message: msg },
361
- meta: {
362
- operation: 'nexus.status',
363
- duration_ms: Date.now() - startTime,
364
- timestamp: new Date().toISOString(),
365
- },
366
- }, null, 2) + '\n');
367
- }
368
- else {
369
- process.stderr.write(`[nexus] Error: ${msg}\n`);
370
- await dispatchFromCli('query', 'nexus', 'status', {}, { command: 'nexus' });
371
- }
372
- process.exitCode = 1;
373
- }
374
- });
375
- // ── nexus show ─────────────────────────────────────────────────────
376
- nexus
377
- .command('show <name>')
378
- .description('Show details for a registered project by name')
379
- .action(async (name) => {
380
- await dispatchFromCli('query', 'nexus', 'show', {
381
- name,
382
- }, { command: 'nexus' });
383
- });
384
- // ── nexus resolve ───────────────────────────────────────────────────
385
- nexus
386
- .command('resolve <taskRef>')
387
- .alias('query')
388
- .description('Resolve a task reference across projects (project:T### or T###)')
389
- .action(async (taskRef) => {
390
- await dispatchFromCli('query', 'nexus', 'resolve', {
391
- query: taskRef,
392
- }, { command: 'nexus' });
393
- });
394
- // ── nexus discover ──────────────────────────────────────────────────
395
- nexus
396
- .command('discover <taskQuery>')
397
- .description('Find related tasks across projects')
398
- .option('--method <method>', 'Discovery method: labels|description|files|auto', 'auto')
399
- .option('--limit <n>', 'Max results', parseInt, 10)
400
- .action(async (taskQuery, opts) => {
401
- await dispatchFromCli('query', 'nexus', 'discover', {
402
- query: taskQuery,
403
- method: opts['method'],
404
- limit: opts['limit'],
405
- }, { command: 'nexus' });
406
- });
407
- // ── nexus search ────────────────────────────────────────────────────
408
- nexus
409
- .command('search <pattern>')
410
- .description('Search tasks across projects by pattern')
411
- .option('--project <name>', 'Limit search to specific project')
412
- .option('--limit <n>', 'Max results', parseInt, 20)
413
- .action(async (pattern, opts) => {
414
- await dispatchFromCli('query', 'nexus', 'search', {
415
- pattern,
416
- project: opts['project'],
417
- limit: opts['limit'],
418
- }, { command: 'nexus' });
419
- });
420
- // ── nexus deps ──────────────────────────────────────────────────────
421
- nexus
422
- .command('deps <taskQuery>')
423
- .description('Show cross-project dependencies')
424
- .option('--reverse', 'Show reverse dependencies (what depends on this)')
425
- .action(async (taskQuery, opts) => {
426
- await dispatchFromCli('query', 'nexus', 'deps', {
427
- query: taskQuery,
428
- direction: opts['reverse'] ? 'reverse' : 'forward',
429
- }, { command: 'nexus' });
430
- });
431
- // ── nexus critical-path ───────────────────────────────────────────
432
- nexus
433
- .command('critical-path')
434
- .description('Show global critical path across all registered projects')
435
- .action(async () => {
436
- await dispatchFromCli('query', 'nexus', 'path.show', {}, { command: 'nexus' });
437
- });
438
- // ── nexus blocking ────────────────────────────────────────────────
439
- nexus
440
- .command('blocking <taskQuery>')
441
- .description('Show blocking impact analysis for a task')
442
- .action(async (taskQuery) => {
443
- await dispatchFromCli('query', 'nexus', 'blockers.show', {
444
- query: taskQuery,
445
- }, { command: 'nexus' });
446
- });
447
- // ── nexus orphans ─────────────────────────────────────────────────
448
- nexus
449
- .command('orphans')
450
- .description('Detect broken cross-project dependency references')
451
- .action(async () => {
452
- await dispatchFromCli('query', 'nexus', 'orphans.list', {}, { command: 'nexus' });
453
- });
454
- // ── nexus sync ──────────────────────────────────────────────────────
455
- nexus
456
- .command('sync [project]')
457
- .description('Sync project metadata (task count, labels)')
458
- .action(async (project) => {
459
- if (project) {
460
- await dispatchFromCli('mutate', 'nexus', 'sync', {
461
- name: project,
462
- }, { command: 'nexus' });
463
- }
464
- else {
465
- await dispatchFromCli('mutate', 'nexus', 'sync', {}, { command: 'nexus' });
466
- }
467
- });
468
- // ── nexus reconcile ──────────────────────────────────────────────────
469
- nexus
470
- .command('reconcile')
471
- .description('Reconcile current project with NEXUS registry (auto-register if new, update path if moved)')
472
- .option('--path <path>', 'Project path (default: current directory)')
473
- .action(async (opts) => {
474
- await dispatchFromCli('mutate', 'nexus', 'reconcile', {
475
- projectRoot: opts['path'],
476
- }, { command: 'nexus' });
477
- });
478
- // ── nexus graph ───────────────────────────────────────────────────
479
- nexus
480
- .command('graph')
481
- .description('Show full dependency graph across all registered projects')
482
- .action(async () => {
483
- await dispatchFromCli('query', 'nexus', 'graph', {}, { command: 'nexus' });
484
- });
485
- // ── nexus share-status ────────────────────────────────────────────
486
- nexus
487
- .command('share-status')
488
- .description('Show multi-contributor sharing status for the current project')
489
- .action(async () => {
490
- await dispatchFromCli('query', 'nexus', 'share.status', {}, { command: 'nexus' });
491
- });
492
- // ── nexus transfer-preview ────────────────────────────────────────
493
- nexus
494
- .command('transfer-preview <taskIds...>')
495
- .description('Preview a task transfer between projects (dry-run, no changes made)')
496
- .requiredOption('--from <project>', 'Source project name')
497
- .requiredOption('--to <project>', 'Target project name')
498
- .option('--mode <mode>', 'Transfer mode: copy|move', 'copy')
499
- .option('--scope <scope>', 'Transfer scope: single|subtree', 'subtree')
500
- .action(async (taskIds, opts) => {
501
- await dispatchFromCli('query', 'nexus', 'transfer.preview', {
502
- taskIds,
503
- sourceProject: opts['from'],
504
- targetProject: opts['to'],
505
- mode: opts['mode'],
506
- scope: opts['scope'],
507
- }, { command: 'nexus' });
508
- });
509
- // ── nexus transfer ────────────────────────────────────────────────
510
- nexus
511
- .command('transfer <taskIds...>')
512
- .description('Transfer tasks from one project to another')
513
- .requiredOption('--from <project>', 'Source project name')
514
- .requiredOption('--to <project>', 'Target project name')
515
- .option('--mode <mode>', 'Transfer mode: copy|move', 'copy')
516
- .option('--scope <scope>', 'Transfer scope: single|subtree', 'subtree')
517
- .option('--on-conflict <strategy>', 'Conflict strategy: rename|skip|duplicate|fail', 'rename')
518
- .option('--transfer-brain', 'Also transfer associated brain memory entries', false)
519
- .action(async (taskIds, opts) => {
520
- await dispatchFromCli('mutate', 'nexus', 'transfer', {
521
- taskIds,
522
- sourceProject: opts['from'],
523
- targetProject: opts['to'],
524
- mode: opts['mode'],
525
- scope: opts['scope'],
526
- onConflict: opts['onConflict'],
527
- transferBrain: opts['transferBrain'],
528
- }, { command: 'nexus' });
529
- });
530
- // ── nexus permission ──────────────────────────────────────────────
531
- const permission = nexus
532
- .command('permission')
533
- .description('Manage permissions for registered projects');
534
- permission
535
- .command('set <name> <level>')
536
- .description('Set permission level for a registered project (read|write|execute)')
537
- .action(async (name, level) => {
538
- await dispatchFromCli('mutate', 'nexus', 'permission.set', {
539
- name,
540
- level,
541
- }, { command: 'nexus' });
542
- });
543
- // ── nexus share ───────────────────────────────────────────────────
544
- const share = nexus.command('share').description('Multi-contributor sharing operations');
545
- share
546
- .command('export')
547
- .description('Export a snapshot of current project state for sharing')
548
- .option('--output <path>', 'Output file path (default: auto-generated in current directory)')
549
- .action(async (opts) => {
550
- await dispatchFromCli('mutate', 'nexus', 'share.snapshot.export', {
551
- outputPath: opts['output'],
552
- }, { command: 'nexus' });
553
- });
554
- share
555
- .command('import <file>')
556
- .description('Import a shared project snapshot')
557
- .action(async (file) => {
558
- await dispatchFromCli('mutate', 'nexus', 'share.snapshot.import', {
559
- inputPath: file,
560
- }, { command: 'nexus' });
561
- });
562
- // ── nexus clusters ────────────────────────────────────────────────────────
563
- nexus
564
- .command('clusters [path]')
565
- .description('List all detected communities (Louvain clusters) from the last analysis')
566
- .option('--json', 'Output result as JSON (LAFS envelope format)')
567
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from path)')
568
- .action(async (targetPath, opts) => {
569
- const startTime = Date.now();
570
- const jsonOutput = !!opts['json'];
571
- const projectIdOverride = opts['projectId'];
572
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
573
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
574
- try {
575
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
576
- const db = await getNexusDb();
577
- // Query all nodes for this project, filter to community kind in-memory
578
- // (avoids complex Drizzle where clause on an enum column).
579
- // NodeSQLiteDatabase uses sync Drizzle — .all() returns a plain array,
580
- // not a Promise, so wrap in try-catch rather than using .catch().
581
- let rows = [];
582
- try {
583
- rows = db.select().from(nexusSchema.nexusNodes).all();
584
- }
585
- catch {
586
- rows = [];
587
- }
588
- const communities = rows.filter((r) => r['kind'] === 'community' && r['projectId'] === projectId);
589
- const durationMs = Date.now() - startTime;
590
- if (jsonOutput) {
591
- process.stdout.write(JSON.stringify({
592
- success: true,
593
- data: {
594
- projectId,
595
- repoPath,
596
- count: communities.length,
597
- communities: communities.map((c) => {
598
- const meta = typeof c['metaJson'] === 'string'
599
- ? JSON.parse(c['metaJson'])
600
- : {};
601
- return {
602
- id: c['id'],
603
- label: c['label'],
604
- symbolCount: meta['symbolCount'] ?? 0,
605
- cohesion: meta['cohesion'] ?? 0,
606
- };
607
- }),
608
- },
609
- meta: {
610
- operation: 'nexus.clusters',
611
- duration_ms: durationMs,
612
- timestamp: new Date().toISOString(),
613
- },
614
- }, null, 2) + '\n');
615
- }
616
- else {
617
- if (communities.length === 0) {
618
- process.stdout.write(`[nexus] No communities found for project ${projectId}.\n` +
619
- ` Run 'cleo nexus analyze' first.\n`);
620
- }
621
- else {
622
- process.stdout.write(`[nexus] Communities for project ${projectId} (${communities.length} total):\n`);
623
- for (const c of communities) {
624
- const meta = typeof c['metaJson'] === 'string'
625
- ? JSON.parse(c['metaJson'])
626
- : {};
627
- const symbolCount = meta['symbolCount'] ?? 0;
628
- const cohesion = typeof meta['cohesion'] === 'number'
629
- ? meta['cohesion'].toFixed(3)
630
- : '0.000';
631
- process.stdout.write(` ${String(c['id']).padEnd(16)} label=${String(c['label']).padEnd(24)} symbols=${String(symbolCount).padStart(5)} cohesion=${cohesion}\n`);
632
- }
633
- }
634
- }
635
- }
636
- catch (err) {
637
- const msg = err instanceof Error ? err.message : String(err);
638
- if (jsonOutput) {
639
- process.stdout.write(JSON.stringify({
640
- success: false,
641
- error: { code: 'E_CLUSTERS_FAILED', message: msg },
642
- meta: {
643
- operation: 'nexus.clusters',
644
- duration_ms: Date.now() - startTime,
645
- timestamp: new Date().toISOString(),
646
- },
647
- }, null, 2) + '\n');
648
- }
649
- else {
650
- process.stderr.write(`[nexus] Error: ${msg}\n`);
651
- }
652
- process.exitCode = 1;
653
- }
654
- });
655
- // ── nexus flows ───────────────────────────────────────────────────────────
656
- nexus
657
- .command('flows [path]')
658
- .description('List all detected execution flows (processes) from the last analysis')
659
- .option('--json', 'Output result as JSON (LAFS envelope format)')
660
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from path)')
661
- .action(async (targetPath, opts) => {
662
- const startTime = Date.now();
663
- const jsonOutput = !!opts['json'];
664
- const projectIdOverride = opts['projectId'];
665
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
666
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
667
- try {
668
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
669
- const db = await getNexusDb();
670
- // NodeSQLiteDatabase uses sync Drizzle — .all() returns a plain array,
671
- // not a Promise, so wrap in try-catch rather than using .catch().
672
- let rows = [];
673
- try {
674
- rows = db.select().from(nexusSchema.nexusNodes).all();
675
- }
676
- catch {
677
- rows = [];
678
- }
679
- const processes = rows.filter((r) => r['kind'] === 'process' && r['projectId'] === projectId);
680
- const durationMs = Date.now() - startTime;
681
- if (jsonOutput) {
682
- process.stdout.write(JSON.stringify({
683
- success: true,
684
- data: {
685
- projectId,
686
- repoPath,
687
- count: processes.length,
688
- flows: processes.map((p) => {
689
- const meta = typeof p['metaJson'] === 'string'
690
- ? JSON.parse(p['metaJson'])
691
- : {};
692
- return {
693
- id: p['id'],
694
- label: p['label'],
695
- stepCount: meta['stepCount'] ?? 0,
696
- processType: meta['processType'] ?? 'intra_community',
697
- entryPointId: meta['entryPointId'] ?? null,
698
- };
699
- }),
700
- },
701
- meta: {
702
- operation: 'nexus.flows',
703
- duration_ms: durationMs,
704
- timestamp: new Date().toISOString(),
705
- },
706
- }, null, 2) + '\n');
707
- }
708
- else {
709
- if (processes.length === 0) {
710
- process.stdout.write(`[nexus] No execution flows found for project ${projectId}.\n` +
711
- ` Run 'cleo nexus analyze' first.\n`);
712
- }
713
- else {
714
- process.stdout.write(`[nexus] Execution flows for project ${projectId} (${processes.length} total):\n`);
715
- for (const p of processes) {
716
- const meta = typeof p['metaJson'] === 'string'
717
- ? JSON.parse(p['metaJson'])
718
- : {};
719
- const stepCount = meta['stepCount'] ?? 0;
720
- const processType = String(meta['processType'] ?? 'intra').replace('_community', '');
721
- process.stdout.write(` ${String(p['id']).padEnd(30)} steps=${String(stepCount).padStart(3)} type=${processType.padEnd(12)} ${String(p['label'])}\n`);
722
- }
723
- }
724
- }
725
- }
726
- catch (err) {
727
- const msg = err instanceof Error ? err.message : String(err);
728
- if (jsonOutput) {
729
- process.stdout.write(JSON.stringify({
730
- success: false,
731
- error: { code: 'E_FLOWS_FAILED', message: msg },
732
- meta: {
733
- operation: 'nexus.flows',
734
- duration_ms: Date.now() - startTime,
735
- timestamp: new Date().toISOString(),
736
- },
737
- }, null, 2) + '\n');
738
- }
739
- else {
740
- process.stderr.write(`[nexus] Error: ${msg}\n`);
741
- }
742
- process.exitCode = 1;
743
- }
744
- });
745
- // ── nexus context ─────────────────────────────────────────────────────────
746
- nexus
747
- .command('context <symbol>')
748
- .description('Show callers, callees, community membership, and process participation for a code symbol')
749
- .option('--json', 'Output result as JSON (LAFS envelope format)')
750
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from cwd)')
751
- .option('--limit <n>', 'Max callers/callees to show per side', parseInt, 20)
752
- .action(async (symbolName, opts) => {
753
- const startTime = Date.now();
754
- const jsonOutput = !!opts['json'];
755
- const projectIdOverride = opts['projectId'];
756
- const repoPath = process.cwd();
757
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
758
- const limit = opts['limit'] ?? 20;
759
- try {
760
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
761
- const db = await getNexusDb();
762
- // Find nodes matching the symbol name (case-insensitive partial match).
763
- // NodeSQLiteDatabase uses sync Drizzle — .all() returns a plain array.
764
- let allNodes = [];
765
- try {
766
- allNodes = db.select().from(nexusSchema.nexusNodes).all();
767
- }
768
- catch {
769
- allNodes = [];
770
- }
771
- const lowerSymbol = symbolName.toLowerCase();
772
- const rawMatchingNodes = allNodes.filter((n) => n['projectId'] === projectId &&
773
- n['name'] != null &&
774
- String(n['name']).toLowerCase().includes(lowerSymbol) &&
775
- // Exclude synthetic graph-level nodes from symbol search
776
- n['kind'] !== 'community' &&
777
- n['kind'] !== 'process');
778
- // Sort so callable symbols (function, method, class) rank before
779
- // structural nodes (file, folder) — structural nodes have no `calls`
780
- // relations and would produce empty callers/callees lists.
781
- const matchingNodes = sortMatchingNodes(rawMatchingNodes, symbolName);
782
- if (matchingNodes.length === 0) {
783
- const durationMs = Date.now() - startTime;
784
- if (jsonOutput) {
785
- process.stdout.write(JSON.stringify({
786
- success: false,
787
- error: {
788
- code: 'E_NOT_FOUND',
789
- message: `No symbol found matching '${symbolName}' in project ${projectId}`,
790
- },
791
- meta: {
792
- operation: 'nexus.context',
793
- duration_ms: durationMs,
794
- timestamp: new Date().toISOString(),
795
- },
796
- }, null, 2) + '\n');
797
- }
798
- else {
799
- process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n` +
800
- ` Run 'cleo nexus analyze' first, or check the symbol name.\n`);
801
- }
802
- process.exitCode = 4;
803
- return;
804
- }
805
- // Load all relations once — cheaper than N queries per node.
806
- let allRelations = [];
807
- try {
808
- allRelations = db.select().from(nexusSchema.nexusRelations).all();
809
- }
810
- catch {
811
- allRelations = [];
812
- }
813
- // Build a node-by-id index for fast lookups.
814
- const nodeById = new Map();
815
- for (const n of allNodes) {
816
- nodeById.set(String(n['id']), n);
817
- }
818
- // Build context for each matching node.
819
- const results = matchingNodes.slice(0, 5).map((node) => {
820
- const nodeId = String(node['id']);
821
- // Incoming: who calls/imports/references THIS node (target = nodeId)
822
- const incoming = allRelations
823
- .filter((r) => r['targetId'] === nodeId &&
824
- r['projectId'] === projectId &&
825
- (r['type'] === 'calls' || r['type'] === 'imports' || r['type'] === 'accesses'))
826
- .slice(0, limit)
827
- .map((r) => {
828
- const src = nodeById.get(String(r['sourceId']));
829
- return {
830
- relationType: r['type'],
831
- nodeId: r['sourceId'],
832
- name: src?.['name'] ?? r['sourceId'],
833
- kind: src?.['kind'] ?? 'unknown',
834
- filePath: src?.['filePath'] ?? null,
835
- };
836
- });
837
- // Outgoing: what THIS node calls/imports/accesses (source = nodeId)
838
- const outgoing = allRelations
839
- .filter((r) => r['sourceId'] === nodeId &&
840
- r['projectId'] === projectId &&
841
- (r['type'] === 'calls' || r['type'] === 'imports' || r['type'] === 'accesses'))
842
- .slice(0, limit)
843
- .map((r) => {
844
- const tgt = nodeById.get(String(r['targetId']));
845
- return {
846
- relationType: r['type'],
847
- nodeId: r['targetId'],
848
- name: tgt?.['name'] ?? r['targetId'],
849
- kind: tgt?.['kind'] ?? 'unknown',
850
- filePath: tgt?.['filePath'] ?? null,
851
- };
852
- });
853
- // Community membership
854
- const communityId = node['communityId'];
855
- const community = communityId ? nodeById.get(communityId) : null;
856
- // Process participation (step_in_process or entry_point_of relations)
857
- const processRelations = allRelations.filter((r) => r['sourceId'] === nodeId &&
858
- r['projectId'] === projectId &&
859
- (r['type'] === 'step_in_process' || r['type'] === 'entry_point_of'));
860
- const processes = processRelations
861
- .map((r) => {
862
- const proc = nodeById.get(String(r['targetId']));
863
- return {
864
- processId: r['targetId'],
865
- label: proc?.['label'] ?? r['targetId'],
866
- role: r['type'] === 'entry_point_of' ? 'entry_point' : 'step',
867
- step: r['step'] ?? null,
868
- };
869
- })
870
- .filter((p) => p.label !== p.processId); // filter unresolved
871
- return {
872
- nodeId,
873
- name: node['name'],
874
- kind: node['kind'],
875
- filePath: node['filePath'],
876
- startLine: node['startLine'],
877
- endLine: node['endLine'],
878
- isExported: node['isExported'],
879
- docSummary: node['docSummary'],
880
- community: community
881
- ? { id: communityId, label: community['label'] }
882
- : communityId
883
- ? { id: communityId, label: null }
884
- : null,
885
- callers: incoming,
886
- callees: outgoing,
887
- processes,
888
- };
889
- });
890
- const durationMs = Date.now() - startTime;
891
- const primary = results[0];
892
- if (jsonOutput) {
893
- process.stdout.write(JSON.stringify({
894
- success: true,
895
- data: {
896
- query: symbolName,
897
- projectId,
898
- matchCount: matchingNodes.length,
899
- results,
900
- },
901
- meta: {
902
- operation: 'nexus.context',
903
- duration_ms: durationMs,
904
- timestamp: new Date().toISOString(),
905
- },
906
- }, null, 2) + '\n');
907
- }
908
- else {
909
- process.stdout.write(`[nexus] Context for symbol '${symbolName}' (${matchingNodes.length} match${matchingNodes.length !== 1 ? 'es' : ''}):\n`);
910
- for (const r of results) {
911
- process.stdout.write(`\n Symbol: ${String(r.name)} (${String(r.kind)})\n` +
912
- ` File: ${r.filePath ? String(r.filePath) : 'n/a'}` +
913
- (r.startLine ? `:${String(r.startLine)}` : '') +
914
- '\n' +
915
- (r.docSummary ? ` Doc: ${String(r.docSummary)}\n` : '') +
916
- (r.community
917
- ? ` Community: ${String(r.community.label ?? r.community.id)}\n`
918
- : '') +
919
- ` Callers (${r.callers.length}): ${r.callers.length === 0
920
- ? 'none'
921
- : r.callers.map((c) => `${String(c.name)}[${String(c.kind)}]`).join(', ')}\n` +
922
- ` Callees (${r.callees.length}): ${r.callees.length === 0
923
- ? 'none'
924
- : r.callees.map((c) => `${String(c.name)}[${String(c.kind)}]`).join(', ')}\n` +
925
- (r.processes.length > 0
926
- ? ` Processes: ${r.processes.map((p) => `${String(p.label)}(${String(p.role)})`).join(', ')}\n`
927
- : ''));
928
- }
929
- if (matchingNodes.length > 5) {
930
- process.stdout.write(`\n (Showing 5 of ${matchingNodes.length} matches — use --json for full list)\n`);
931
- }
932
- }
933
- void primary; // referenced to satisfy lint
934
- }
935
- catch (err) {
936
- const msg = err instanceof Error ? err.message : String(err);
937
- if (jsonOutput) {
938
- process.stdout.write(JSON.stringify({
939
- success: false,
940
- error: { code: 'E_CONTEXT_FAILED', message: msg },
941
- meta: {
942
- operation: 'nexus.context',
943
- duration_ms: Date.now() - startTime,
944
- timestamp: new Date().toISOString(),
945
- },
946
- }, null, 2) + '\n');
947
- }
948
- else {
949
- process.stderr.write(`[nexus] Error: ${msg}\n`);
950
- }
951
- process.exitCode = 1;
952
- }
953
- });
954
- // ── nexus impact ──────────────────────────────────────────────────────────
955
- nexus
956
- .command('impact <symbol>')
957
- .description('Show blast radius for a code symbol — direct callers (d=1), indirect callers (d=2), transitive (d=3)')
958
- .option('--json', 'Output result as JSON (LAFS envelope format)')
959
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from cwd)')
960
- .option('--depth <n>', 'Maximum traversal depth (default: 3)', parseInt, 3)
961
- .action(async (symbolName, opts) => {
962
- const startTime = Date.now();
963
- const jsonOutput = !!opts['json'];
964
- const projectIdOverride = opts['projectId'];
965
- const repoPath = process.cwd();
966
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
967
- const maxDepth = Math.min(opts['depth'] ?? 3, 5);
968
- try {
969
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
970
- const db = await getNexusDb();
971
- // Load all nodes and relations for this project once.
972
- let allNodes = [];
973
- try {
974
- allNodes = db.select().from(nexusSchema.nexusNodes).all();
975
- }
976
- catch {
977
- allNodes = [];
978
- }
979
- const lowerSymbol = symbolName.toLowerCase();
980
- const rawMatchingNodes = allNodes.filter((n) => n['projectId'] === projectId &&
981
- n['name'] != null &&
982
- String(n['name']).toLowerCase().includes(lowerSymbol) &&
983
- n['kind'] !== 'community' &&
984
- n['kind'] !== 'process');
985
- // Sort so callable symbols (function, method, class) rank before
986
- // structural nodes (file, folder) — structural nodes have no `calls`
987
- // relations and would produce zero impact.
988
- const matchingNodes = sortMatchingNodes(rawMatchingNodes, symbolName);
989
- if (matchingNodes.length === 0) {
990
- const durationMs = Date.now() - startTime;
991
- if (jsonOutput) {
992
- process.stdout.write(JSON.stringify({
993
- success: false,
994
- error: {
995
- code: 'E_NOT_FOUND',
996
- message: `No symbol found matching '${symbolName}' in project ${projectId}`,
997
- },
998
- meta: {
999
- operation: 'nexus.impact',
1000
- duration_ms: durationMs,
1001
- timestamp: new Date().toISOString(),
1002
- },
1003
- }, null, 2) + '\n');
1004
- }
1005
- else {
1006
- process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n` +
1007
- ` Run 'cleo nexus analyze' first, or check the symbol name.\n`);
1008
- }
1009
- process.exitCode = 4;
1010
- return;
1011
- }
1012
- let allRelations = [];
1013
- try {
1014
- allRelations = db.select().from(nexusSchema.nexusRelations).all();
1015
- }
1016
- catch {
1017
- allRelations = [];
1018
- }
1019
- // Build a node-by-id index for fast lookups.
1020
- const nodeById = new Map();
1021
- for (const n of allNodes) {
1022
- nodeById.set(String(n['id']), n);
1023
- }
1024
- // BFS upstream: find all nodes that (transitively) call/import the target.
1025
- const targetNode = matchingNodes[0];
1026
- const targetId = String(targetNode['id']);
1027
- // Build reverse adjacency: targetId → [sourceIds that call it]
1028
- const reverseAdj = new Map();
1029
- for (const r of allRelations) {
1030
- if (r['projectId'] === projectId &&
1031
- (r['type'] === 'calls' || r['type'] === 'imports' || r['type'] === 'accesses')) {
1032
- const tid = String(r['targetId']);
1033
- const sid = String(r['sourceId']);
1034
- if (!reverseAdj.has(tid))
1035
- reverseAdj.set(tid, []);
1036
- reverseAdj.get(tid).push(sid);
1037
- }
1038
- }
1039
- // BFS traversal up to maxDepth levels.
1040
- const visited = new Set([targetId]);
1041
- const depthMap = new Map(); // nodeId → depth
1042
- const queue = [{ id: targetId, depth: 0 }];
1043
- const impactByDepth = [];
1044
- while (queue.length > 0) {
1045
- const item = queue.shift();
1046
- if (item.depth >= maxDepth)
1047
- continue;
1048
- const callers = reverseAdj.get(item.id) ?? [];
1049
- for (const callerId of callers) {
1050
- if (visited.has(callerId))
1051
- continue;
1052
- visited.add(callerId);
1053
- const depth = item.depth + 1;
1054
- depthMap.set(callerId, depth);
1055
- const callerNode = nodeById.get(callerId);
1056
- if (!impactByDepth[depth - 1])
1057
- impactByDepth[depth - 1] = [];
1058
- impactByDepth[depth - 1].push({
1059
- nodeId: callerId,
1060
- name: String(callerNode?.['name'] ?? callerId),
1061
- kind: String(callerNode?.['kind'] ?? 'unknown'),
1062
- filePath: callerNode?.['filePath'] ? String(callerNode['filePath']) : null,
1063
- });
1064
- queue.push({ id: callerId, depth });
1065
- }
1066
- }
1067
- const totalImpact = visited.size - 1; // exclude the target itself
1068
- const riskLevel = totalImpact === 0
1069
- ? 'NONE'
1070
- : totalImpact <= 3
1071
- ? 'LOW'
1072
- : totalImpact <= 10
1073
- ? 'MEDIUM'
1074
- : totalImpact <= 25
1075
- ? 'HIGH'
1076
- : 'CRITICAL';
1077
- const durationMs = Date.now() - startTime;
1078
- if (jsonOutput) {
1079
- process.stdout.write(JSON.stringify({
1080
- success: true,
1081
- data: {
1082
- query: symbolName,
1083
- projectId,
1084
- targetNodeId: targetId,
1085
- targetName: targetNode['name'],
1086
- targetKind: targetNode['kind'],
1087
- targetFilePath: targetNode['filePath'],
1088
- riskLevel,
1089
- totalImpactedNodes: totalImpact,
1090
- maxDepth,
1091
- impactByDepth: impactByDepth.map((layer, i) => ({
1092
- depth: i + 1,
1093
- label: i === 0
1094
- ? 'WILL BREAK (direct callers)'
1095
- : i === 1
1096
- ? 'LIKELY AFFECTED'
1097
- : 'MAY NEED TESTING',
1098
- nodes: layer,
1099
- })),
1100
- },
1101
- meta: {
1102
- operation: 'nexus.impact',
1103
- duration_ms: durationMs,
1104
- timestamp: new Date().toISOString(),
1105
- },
1106
- }, null, 2) + '\n');
1107
- }
1108
- else {
1109
- process.stdout.write(`[nexus] Impact analysis for '${symbolName}'\n` +
1110
- ` Target: ${String(targetNode['name'])} (${String(targetNode['kind'])})\n` +
1111
- ` File: ${targetNode['filePath'] ? String(targetNode['filePath']) : 'n/a'}\n` +
1112
- ` Risk: ${riskLevel} (${totalImpact} impacted node${totalImpact !== 1 ? 's' : ''})\n`);
1113
- if (totalImpact === 0) {
1114
- process.stdout.write(' No callers found — safe to modify.\n');
1115
- }
1116
- else {
1117
- for (let i = 0; i < impactByDepth.length; i++) {
1118
- const layer = impactByDepth[i];
1119
- if (!layer || layer.length === 0)
1120
- continue;
1121
- const label = i === 0 ? 'WILL BREAK' : i === 1 ? 'LIKELY AFFECTED' : 'MAY NEED TESTING';
1122
- process.stdout.write(`\n d=${i + 1} ${label} (${layer.length}):\n`);
1123
- for (const node of layer.slice(0, 15)) {
1124
- process.stdout.write(` ${String(node.name).padEnd(36)} ${String(node.kind).padEnd(12)} ${node.filePath ?? ''}\n`);
1125
- }
1126
- if (layer.length > 15) {
1127
- process.stdout.write(` ... and ${layer.length - 15} more\n`);
1128
- }
1129
- }
1130
- }
1131
- if (matchingNodes.length > 1) {
1132
- process.stdout.write(`\n (Showing analysis for first match — ${matchingNodes.length} total matches for '${symbolName}')\n`);
1133
- }
1134
- }
1135
- }
1136
- catch (err) {
1137
- const msg = err instanceof Error ? err.message : String(err);
1138
- if (jsonOutput) {
1139
- process.stdout.write(JSON.stringify({
1140
- success: false,
1141
- error: { code: 'E_IMPACT_FAILED', message: msg },
1142
- meta: {
1143
- operation: 'nexus.impact',
1144
- duration_ms: Date.now() - startTime,
1145
- timestamp: new Date().toISOString(),
1146
- },
1147
- }, null, 2) + '\n');
1148
- }
1149
- else {
1150
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1151
- }
1152
- process.exitCode = 1;
1153
- }
1154
- });
1155
- // ── nexus analyze ─────────────────────────────────────────────────────────
1156
- nexus
1157
- .command('analyze [path]')
1158
- .description('Run code intelligence pipeline on a repository directory')
1159
- .option('--json', 'Output result as JSON (LAFS envelope format)')
1160
- .option('--project-id <id>', 'Override the project ID (default: auto-detected)')
1161
- .option('--incremental', 'Only re-index files that have changed since the last run (faster)')
1162
- .action(async (targetPath, opts) => {
1163
- const startTime = Date.now();
1164
- const jsonOutput = !!opts['json'];
1165
- const projectIdOverride = opts['projectId'];
1166
- const isIncremental = !!opts['incremental'];
1167
- // Resolve target path
1168
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
1169
- if (!jsonOutput) {
1170
- process.stderr.write(`[nexus] Analyzing: ${repoPath}${isIncremental ? ' (incremental)' : ''}\n`);
1171
- }
1172
- try {
1173
- // Lazy imports to avoid loading heavy dependencies until needed
1174
- const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot }, { eq }] = await Promise.all([
1175
- import('@cleocode/core/store/nexus-sqlite'),
1176
- import('@cleocode/nexus/pipeline'),
1177
- import('@cleocode/core/internal'),
1178
- import('drizzle-orm'),
1179
- ]);
1180
- // Determine project ID — use override or derive from path
1181
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
1182
- // Get DB and table references
1183
- const db = await getNexusDb();
1184
- const tables = {
1185
- nexusNodes: nexusSchema.nexusNodes,
1186
- nexusRelations: nexusSchema.nexusRelations,
1187
- };
1188
- // For full (non-incremental) runs: delete existing index first.
1189
- // NodeSQLiteDatabase uses sync Drizzle — no await, wrap in try-catch.
1190
- if (!isIncremental) {
1191
- if (!jsonOutput) {
1192
- process.stderr.write('[nexus] Clearing existing index for project...\n');
1193
- }
1194
- try {
1195
- db.delete(nexusSchema.nexusNodes)
1196
- .where(eq(nexusSchema.nexusNodes.projectId, projectId))
1197
- .run();
1198
- }
1199
- catch {
1200
- // Table may not have rows — ignore
1201
- }
1202
- try {
1203
- db.delete(nexusSchema.nexusRelations)
1204
- .where(eq(nexusSchema.nexusRelations.projectId, projectId))
1205
- .run();
1206
- }
1207
- catch {
1208
- // Table may not have rows — ignore
1209
- }
1210
- }
1211
- // Run the pipeline (full or incremental)
1212
- const result = await runPipeline(repoPath, projectId, db, tables, jsonOutput
1213
- ? undefined
1214
- : (current, total, filePath) => {
1215
- if (current % 50 === 0 || current === total) {
1216
- const pct = total > 0 ? Math.round((current / total) * 100) : 100;
1217
- process.stderr.write(`[nexus] Progress: ${current}/${total} files (${pct}%) — ${filePath}\n`);
1218
- }
1219
- }, { incremental: isIncremental });
1220
- const durationMs = Date.now() - startTime;
1221
- // Write nexus-bridge.md after a successful pipeline run (best-effort)
1222
- try {
1223
- const { refreshNexusBridge } = await import('@cleocode/core/internal');
1224
- await refreshNexusBridge(repoPath, projectId);
1225
- if (!jsonOutput) {
1226
- process.stderr.write(`[nexus] nexus-bridge.md refreshed at ${repoPath}/.cleo/nexus-bridge.md\n`);
1227
- }
1228
- }
1229
- catch {
1230
- // Non-fatal — bridge refresh failure should not fail the analyze command
1231
- }
1232
- // Auto-register project and update index stats in the multi-project registry (best-effort)
1233
- try {
1234
- const { nexusUpdateIndexStats } = await import('@cleocode/core/internal');
1235
- await nexusUpdateIndexStats(repoPath, {
1236
- nodeCount: result.nodeCount,
1237
- relationCount: result.relationCount,
1238
- fileCount: result.fileCount,
1239
- });
1240
- if (!jsonOutput) {
1241
- process.stderr.write('[nexus] Project registered/updated in multi-project registry.\n');
1242
- }
1243
- }
1244
- catch {
1245
- // Non-fatal — registry update must never fail the analyze command
1246
- }
1247
- if (jsonOutput) {
1248
- const envelope = {
1249
- success: true,
1250
- data: {
1251
- projectId,
1252
- repoPath,
1253
- incremental: isIncremental,
1254
- nodeCount: result.nodeCount,
1255
- relationCount: result.relationCount,
1256
- fileCount: result.fileCount,
1257
- durationMs,
1258
- },
1259
- meta: {
1260
- operation: 'nexus.analyze',
1261
- duration_ms: durationMs,
1262
- timestamp: new Date().toISOString(),
1263
- },
1264
- };
1265
- process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
1266
- }
1267
- else {
1268
- process.stdout.write(`[nexus] Analysis complete${isIncremental ? ' (incremental)' : ''}:\n` +
1269
- ` Project ID: ${projectId}\n` +
1270
- ` Files: ${result.fileCount}\n` +
1271
- ` Nodes: ${result.nodeCount}\n` +
1272
- ` Relations: ${result.relationCount}\n` +
1273
- ` Duration: ${durationMs}ms\n`);
1274
- }
1275
- void getProjectRoot; // referenced to satisfy import
1276
- }
1277
- catch (err) {
1278
- const msg = err instanceof Error ? err.message : String(err);
1279
- if (jsonOutput) {
1280
- const envelope = {
1281
- success: false,
1282
- error: { code: 'E_PIPELINE_FAILED', message: msg },
1283
- meta: {
1284
- operation: 'nexus.analyze',
1285
- duration_ms: Date.now() - startTime,
1286
- timestamp: new Date().toISOString(),
1287
- },
1288
- };
1289
- process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
1290
- }
1291
- else {
1292
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1293
- }
1294
- process.exitCode = 1;
1295
- }
1296
- });
1297
- // ── nexus projects ────────────────────────────────────────────────────────
1298
- // A focused subcommand group for the multi-project registry (T622).
1299
- // Maps to the existing nexus.list / nexus.register / nexus.unregister
1300
- // operations but adds richer output including db paths and index stats.
1301
- const projects = nexus.command('projects').description('Multi-project registry management');
1302
- projects
1303
- .command('list')
1304
- .description('List all projects registered in the global nexus registry')
1305
- .option('--json', 'Output as JSON (LAFS envelope format)')
1306
- .action(async (opts) => {
1307
- const startTime = Date.now();
1308
- const jsonOutput = !!opts['json'];
1309
- try {
1310
- const { nexusList } = await import('@cleocode/core/internal');
1311
- const list = (await nexusList());
1312
- const durationMs = Date.now() - startTime;
1313
- if (jsonOutput) {
1314
- process.stdout.write(JSON.stringify({
1315
- success: true,
1316
- data: { projects: list, count: list.length },
1317
- meta: {
1318
- operation: 'nexus.projects.list',
1319
- duration_ms: durationMs,
1320
- timestamp: new Date().toISOString(),
1321
- },
1322
- }, null, 2) + '\n');
1323
- }
1324
- else if (list.length === 0) {
1325
- process.stdout.write('[nexus] No projects registered. Run: cleo nexus projects register\n');
1326
- }
1327
- else {
1328
- process.stdout.write(`[nexus] Registered projects (${list.length}):\n\n`);
1329
- for (const p of list) {
1330
- const nodes = p.stats?.nodeCount ?? 0;
1331
- const rels = p.stats?.relationCount ?? 0;
1332
- const indexed = p.lastIndexed ? p.lastIndexed.slice(0, 10) : 'never';
1333
- process.stdout.write(` ${p.name.padEnd(28)} tasks=${String(p.taskCount).padStart(5)} nodes=${String(nodes).padStart(6)} relations=${String(rels).padStart(7)} indexed=${indexed}\n` +
1334
- ` ${''.padEnd(28)} path=${p.path}\n`);
1335
- }
1336
- }
1337
- }
1338
- catch (err) {
1339
- const msg = err instanceof Error ? err.message : String(err);
1340
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1341
- process.exitCode = 1;
1342
- }
1343
- });
1344
- projects
1345
- .command('register [path]')
1346
- .description('Register a project in the global nexus registry (default: current directory)')
1347
- .option('--name <name>', 'Custom project name (default: directory name)')
1348
- .option('--json', 'Output as JSON (LAFS envelope format)')
1349
- .action(async (targetPath, opts) => {
1350
- const startTime = Date.now();
1351
- const jsonOutput = !!opts['json'];
1352
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
1353
- const name = opts['name'];
1354
- try {
1355
- const { nexusRegister } = await import('@cleocode/core/internal');
1356
- const hash = await nexusRegister(repoPath, name);
1357
- const durationMs = Date.now() - startTime;
1358
- if (jsonOutput) {
1359
- process.stdout.write(JSON.stringify({
1360
- success: true,
1361
- data: { hash, path: repoPath },
1362
- meta: {
1363
- operation: 'nexus.projects.register',
1364
- duration_ms: durationMs,
1365
- timestamp: new Date().toISOString(),
1366
- },
1367
- }, null, 2) + '\n');
1368
- }
1369
- else {
1370
- process.stdout.write(`[nexus] Registered: ${repoPath} (hash: ${hash})\n`);
1371
- }
1372
- }
1373
- catch (err) {
1374
- const msg = err instanceof Error ? err.message : String(err);
1375
- if (jsonOutput) {
1376
- process.stdout.write(JSON.stringify({
1377
- success: false,
1378
- error: { code: 'E_REGISTER_FAILED', message: msg },
1379
- meta: {
1380
- operation: 'nexus.projects.register',
1381
- duration_ms: Date.now() - startTime,
1382
- timestamp: new Date().toISOString(),
1383
- },
1384
- }, null, 2) + '\n');
1385
- }
1386
- else {
1387
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1388
- }
1389
- process.exitCode = 1;
1390
- }
1391
- });
1392
- projects
1393
- .command('remove <nameOrHash>')
1394
- .alias('rm')
1395
- .description('Remove a project from the global nexus registry')
1396
- .option('--json', 'Output as JSON (LAFS envelope format)')
1397
- .action(async (nameOrHash, opts) => {
1398
- const startTime = Date.now();
1399
- const jsonOutput = !!opts['json'];
1400
- try {
1401
- const { nexusUnregister } = await import('@cleocode/core/internal');
1402
- await nexusUnregister(nameOrHash);
1403
- const durationMs = Date.now() - startTime;
1404
- if (jsonOutput) {
1405
- process.stdout.write(JSON.stringify({
1406
- success: true,
1407
- data: { removed: nameOrHash },
1408
- meta: {
1409
- operation: 'nexus.projects.remove',
1410
- duration_ms: durationMs,
1411
- timestamp: new Date().toISOString(),
1412
- },
1413
- }, null, 2) + '\n');
1414
- }
1415
- else {
1416
- process.stdout.write(`[nexus] Removed: ${nameOrHash}\n`);
1417
- }
1418
- }
1419
- catch (err) {
1420
- const msg = err instanceof Error ? err.message : String(err);
1421
- if (jsonOutput) {
1422
- process.stdout.write(JSON.stringify({
1423
- success: false,
1424
- error: { code: 'E_REMOVE_FAILED', message: msg },
1425
- meta: {
1426
- operation: 'nexus.projects.remove',
1427
- duration_ms: Date.now() - startTime,
1428
- timestamp: new Date().toISOString(),
1429
- },
1430
- }, null, 2) + '\n');
1431
- }
1432
- else {
1433
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1434
- }
1435
- process.exitCode = 1;
1436
- }
1437
- });
1438
- // ── nexus projects scan ───────────────────────────────────────────────────
1439
- // Walk filesystem roots to discover .cleo/ directories not in the registry.
1440
- projects
1441
- .command('scan')
1442
- .description('Walk filesystem roots to discover .cleo/ directories not registered in the global nexus registry')
1443
- .option('--roots <paths>', 'Comma-separated search roots (default: ~/code,~/projects,/mnt/projects)')
1444
- .option('--max-depth <n>', 'Maximum directory traversal depth (default: 4)', parseInt, 4)
1445
- .option('--auto-register', 'Register all discovered unregistered projects automatically')
1446
- .option('--include-existing', 'Also report projects that are already registered')
1447
- .option('--json', 'Output as JSON (LAFS envelope format)')
1448
- .action(async (opts) => {
1449
- const startTime = Date.now();
1450
- const jsonOutput = !!opts['json'];
1451
- const autoRegister = !!opts['autoRegister'];
1452
- const includeExisting = !!opts['includeExisting'];
1453
- const maxDepth = Math.max(1, Math.min(opts['maxDepth'] ?? 4, 20));
1454
- // Resolve search roots
1455
- const { homedir } = await import('node:os');
1456
- const home = homedir();
1457
- const defaultRoots = [path.join(home, 'code'), path.join(home, 'projects'), '/mnt/projects'];
1458
- const rawRoots = typeof opts['roots'] === 'string' && opts['roots'].trim().length > 0
1459
- ? opts['roots']
1460
- .split(',')
1461
- .map((r) => r.trim())
1462
- .filter((r) => r.length > 0)
1463
- .map((r) => r.startsWith('~') ? path.join(home, r.slice(1)) : path.resolve(r))
1464
- : defaultRoots;
1465
- // Filter to roots that actually exist
1466
- const { existsSync, readdirSync, statSync } = await import('node:fs');
1467
- const { Dirent } = await import('node:fs');
1468
- const roots = rawRoots.filter((r) => {
1469
- try {
1470
- return existsSync(r) && statSync(r).isDirectory();
1471
- }
1472
- catch {
1473
- return false;
1474
- }
1475
- });
1476
- if (!jsonOutput) {
1477
- process.stdout.write(`[nexus] Scanning ${roots.length} root(s) up to depth ${maxDepth}:\n` +
1478
- roots.map((r) => ` ${r}`).join('\n') +
1479
- '\n');
1480
- }
1481
- // ── Filesystem walker ──────────────────────────────────────────────
1482
- // Walk recursively up to maxDepth. Skip common build/cache directories.
1483
- // Does NOT follow symlinks. Does NOT cross mount points.
1484
- const SKIP_DIRS = new Set([
1485
- 'node_modules',
1486
- '.git',
1487
- 'target', // Rust build
1488
- 'dist',
1489
- 'build',
1490
- '.svelte-kit',
1491
- '.next',
1492
- '.cache',
1493
- 'coverage',
1494
- '.turbo',
1495
- '.nx',
1496
- '__pycache__',
1497
- '.venv',
1498
- 'venv',
1499
- '.tox',
1500
- 'vendor',
1501
- ]);
1502
- /**
1503
- * Return the device number for a path, or -1 on error.
1504
- * Used to detect filesystem boundary crossings.
1505
- */
1506
- function getDevice(p) {
1507
- try {
1508
- return statSync(p).dev;
1509
- }
1510
- catch {
1511
- return -1;
1512
- }
1513
- }
1514
- /**
1515
- * Walk a directory tree looking for directories named `.cleo/`.
1516
- * Candidates are returned as absolute parent directory paths (the project root).
1517
- *
1518
- * @param dir - Absolute directory path to walk.
1519
- * @param depth - Current recursion depth (0 = root).
1520
- * @param rootDev - Device number of the search root for boundary checks.
1521
- */
1522
- function walkForCleo(dir, depth, rootDev) {
1523
- if (depth > maxDepth)
1524
- return [];
1525
- let entries;
1526
- try {
1527
- // withFileTypes:true + default encoding returns Dirent<string>[]
1528
- entries = readdirSync(dir, { withFileTypes: true });
1529
- }
1530
- catch {
1531
- return [];
1532
- }
1533
- const found = [];
1534
- for (const entry of entries) {
1535
- // Only process directories; skip symlinks (security requirement).
1536
- if (!entry.isDirectory())
1537
- continue;
1538
- if (entry.isSymbolicLink())
1539
- continue;
1540
- const fullPath = path.join(dir, entry.name);
1541
- if (entry.name === '.cleo') {
1542
- // Parent dir is a CLEO project root
1543
- found.push(dir);
1544
- // Do not recurse into .cleo/ itself
1545
- continue;
1546
- }
1547
- if (SKIP_DIRS.has(entry.name))
1548
- continue;
1549
- // Filesystem boundary check — don't traverse into different mount points.
1550
- const childDev = getDevice(fullPath);
1551
- if (childDev !== rootDev && childDev !== -1)
1552
- continue;
1553
- const nested = walkForCleo(fullPath, depth + 1, rootDev);
1554
- for (const n of nested)
1555
- found.push(n);
1556
- }
1557
- return found;
1558
- }
1559
- // Collect all candidates
1560
- const allCandidates = [];
1561
- for (const root of roots) {
1562
- const rootDev = getDevice(root);
1563
- const found = walkForCleo(root, 0, rootDev);
1564
- for (const f of found)
1565
- allCandidates.push(f);
1566
- }
1567
- // Deduplicate (a root could itself be a .cleo parent)
1568
- const candidates = [...new Set(allCandidates)];
1569
- // ── Cross-reference with registry ─────────────────────────────────
1570
- let registeredPaths = new Set();
1571
- try {
1572
- const { nexusList: listProjects } = await import('@cleocode/core/internal');
1573
- const projects = await listProjects();
1574
- for (const p of projects) {
1575
- registeredPaths.add(path.resolve(p.path));
1576
- }
1577
- }
1578
- catch {
1579
- // Registry unavailable — treat all as unregistered
1580
- registeredPaths = new Set();
1581
- }
1582
- const unregistered = [];
1583
- const registered = [];
1584
- for (const candidate of candidates) {
1585
- const resolved = path.resolve(candidate);
1586
- if (registeredPaths.has(resolved)) {
1587
- registered.push(resolved);
1588
- }
1589
- else {
1590
- unregistered.push(resolved);
1591
- }
1592
- }
1593
- const tally = {
1594
- total: candidates.length,
1595
- unregistered: unregistered.length,
1596
- registered: registered.length,
1597
- };
1598
- // ── Auto-register ─────────────────────────────────────────────────
1599
- const autoRegistered = [];
1600
- const autoRegisterErrors = [];
1601
- if (autoRegister && unregistered.length > 0) {
1602
- const { nexusRegister: doRegister } = await import('@cleocode/core/internal');
1603
- for (const projectPath of unregistered) {
1604
- try {
1605
- await doRegister(projectPath);
1606
- autoRegistered.push(projectPath);
1607
- }
1608
- catch (err) {
1609
- autoRegisterErrors.push({
1610
- path: projectPath,
1611
- error: err instanceof Error ? err.message : String(err),
1612
- });
1613
- }
1614
- }
1615
- }
1616
- // ── Audit log ─────────────────────────────────────────────────────
1617
- // Best-effort: never let audit failure surface to the user.
1618
- try {
1619
- const { getNexusDb } = await import('@cleocode/core/store/nexus-sqlite');
1620
- const { nexusAuditLog: auditTable } = await import('@cleocode/core/store/nexus-schema');
1621
- const { randomUUID } = await import('node:crypto');
1622
- const db = await getNexusDb();
1623
- await db.insert(auditTable).values({
1624
- id: randomUUID(),
1625
- action: 'projects.scan',
1626
- domain: 'nexus',
1627
- operation: 'projects.scan',
1628
- success: 1,
1629
- detailsJson: JSON.stringify({
1630
- roots,
1631
- found: candidates.length,
1632
- unregistered: unregistered.length,
1633
- registered: registered.length,
1634
- autoRegistered: autoRegistered.length,
1635
- }),
1636
- });
1637
- }
1638
- catch {
1639
- // Audit failure is non-fatal
1640
- }
1641
- const durationMs = Date.now() - startTime;
1642
- // ── Output ────────────────────────────────────────────────────────
1643
- if (jsonOutput) {
1644
- const data = {
1645
- roots,
1646
- unregistered,
1647
- tally,
1648
- };
1649
- if (includeExisting)
1650
- data['registered'] = registered;
1651
- if (autoRegister) {
1652
- data['autoRegistered'] = autoRegistered;
1653
- data['autoRegisterErrors'] = autoRegisterErrors;
1654
- }
1655
- process.stdout.write(JSON.stringify({
1656
- success: true,
1657
- data,
1658
- meta: {
1659
- operation: 'nexus.projects.scan',
1660
- duration_ms: durationMs,
1661
- timestamp: new Date().toISOString(),
1662
- },
1663
- }, null, 2) + '\n');
1664
- }
1665
- else {
1666
- // Human-readable output
1667
- process.stdout.write(`\n[nexus] Scan complete — ${tally.total} project(s) found ` +
1668
- `(${tally.unregistered} unregistered, ${tally.registered} registered)\n`);
1669
- if (unregistered.length > 0) {
1670
- process.stdout.write('\n Unregistered:\n');
1671
- for (const p of unregistered) {
1672
- process.stdout.write(` ${p}\n`);
1673
- }
1674
- if (!autoRegister) {
1675
- process.stdout.write('\n Tip: run with --auto-register to register all of the above.\n');
1676
- }
1677
- }
1678
- if (includeExisting && registered.length > 0) {
1679
- process.stdout.write('\n Already registered:\n');
1680
- for (const p of registered) {
1681
- process.stdout.write(` ${p}\n`);
1682
- }
1683
- }
1684
- if (autoRegister) {
1685
- process.stdout.write(`\n Auto-registered: ${autoRegistered.length} project(s)` +
1686
- (autoRegisterErrors.length > 0 ? `, ${autoRegisterErrors.length} failed` : '') +
1687
- '\n');
1688
- for (const e of autoRegisterErrors) {
1689
- process.stdout.write(` FAILED ${e.path}: ${e.error}\n`);
1690
- }
1691
- }
1692
- }
1693
- });
1694
- // ── nexus projects clean ─────────────────────────────────────────────────
1695
- // Bulk purge project_registry rows matching path criteria.
1696
- // Provides safety rails: at least one criteria flag required, always shows
1697
- // a preview before deletion, runs deletion in a single transaction.
1698
- projects
1699
- .command('clean')
1700
- .description('Bulk purge project_registry rows matching path criteria (requires at least one filter flag)')
1701
- .option('--dry-run', 'List matching projects without deleting anything')
1702
- .option('--pattern <regex>', 'JS regex matched against project_path')
1703
- .option('--include-temp', 'Preset: match paths containing a .temp/ segment')
1704
- .option('--include-tests', 'Preset: match paths containing tmp/test/fixture/scratch/sandbox segments')
1705
- .option('--unhealthy', 'Also match rows where health_status is "unhealthy"')
1706
- .option('--never-indexed', 'Also match rows where last_indexed IS NULL')
1707
- .option('--yes', 'Skip confirmation prompt (still shows preview)')
1708
- .option('--json', 'Output as JSON (LAFS envelope format)')
1709
- .action(async (opts) => {
1710
- const startTime = Date.now();
1711
- const jsonOutput = !!opts['json'];
1712
- const dryRun = !!opts['dryRun'];
1713
- const skipPrompt = !!opts['yes'];
1714
- const patternRaw = opts['pattern'];
1715
- const includeTemp = !!opts['includeTemp'];
1716
- const includeTests = !!opts['includeTests'];
1717
- const matchUnhealthy = !!opts['unhealthy'];
1718
- const matchNeverIndexed = !!opts['neverIndexed'];
1719
- // Require at least one real criteria flag (not just --dry-run / --yes / --json)
1720
- const hasCriteria = patternRaw !== undefined ||
1721
- includeTemp ||
1722
- includeTests ||
1723
- matchUnhealthy ||
1724
- matchNeverIndexed;
1725
- if (!hasCriteria) {
1726
- const errMsg = 'No filter criteria provided. Refusing to purge all projects without explicit criteria.\n' +
1727
- 'Use at least one of: --pattern <regex>, --include-temp, --include-tests, --unhealthy, --never-indexed';
1728
- if (jsonOutput) {
1729
- process.stdout.write(JSON.stringify({
1730
- success: false,
1731
- error: { code: 'E_NO_CRITERIA', message: errMsg },
1732
- meta: {
1733
- operation: 'nexus.projects.clean',
1734
- duration_ms: Date.now() - startTime,
1735
- timestamp: new Date().toISOString(),
1736
- },
1737
- }, null, 2) + '\n');
1738
- }
1739
- else {
1740
- process.stderr.write(`[nexus] Error: ${errMsg}\n`);
1741
- }
1742
- process.exitCode = 6;
1743
- return;
1744
- }
1745
- // Compile user-supplied regex (if any)
1746
- let patternRegex = null;
1747
- if (patternRaw !== undefined) {
1748
- try {
1749
- patternRegex = new RegExp(patternRaw);
1750
- }
1751
- catch (err) {
1752
- const msg = `Invalid --pattern regex: ${err instanceof Error ? err.message : String(err)}`;
1753
- if (jsonOutput) {
1754
- process.stdout.write(JSON.stringify({
1755
- success: false,
1756
- error: { code: 'E_INVALID_PATTERN', message: msg },
1757
- meta: {
1758
- operation: 'nexus.projects.clean',
1759
- duration_ms: Date.now() - startTime,
1760
- timestamp: new Date().toISOString(),
1761
- },
1762
- }, null, 2) + '\n');
1763
- }
1764
- else {
1765
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1766
- }
1767
- process.exitCode = 6;
1768
- return;
1769
- }
1770
- }
1771
- // Preset regexes
1772
- const TEMP_RE = /(^|\/)\.temp(\/|$)/;
1773
- const TESTS_RE = /(^|\/)(tmp|test|fixture|scratch|sandbox)(\/|$)/;
1774
- /**
1775
- * Return true if a project_path matches any of the active criteria.
1776
- */
1777
- function matchesCriteria(projectPath, healthStatus, lastIndexed) {
1778
- if (patternRegex?.test(projectPath))
1779
- return true;
1780
- if (includeTemp && TEMP_RE.test(projectPath))
1781
- return true;
1782
- if (includeTests && TESTS_RE.test(projectPath))
1783
- return true;
1784
- if (matchUnhealthy && healthStatus === 'unhealthy')
1785
- return true;
1786
- if (matchNeverIndexed && lastIndexed === null)
1787
- return true;
1788
- return false;
1789
- }
1790
- try {
1791
- const { getNexusDb } = await import('@cleocode/core/store/nexus-sqlite');
1792
- const { projectRegistry: regTable, nexusAuditLog: auditTable } = await import('@cleocode/core/store/nexus-schema');
1793
- const { randomUUID } = await import('node:crypto');
1794
- const { inArray } = await import('drizzle-orm');
1795
- const db = await getNexusDb();
1796
- // Fetch all registry rows in one query — avoid N+1.
1797
- // Cast is required because dynamic imports with `as string` suppress
1798
- // the real module types; the actual schema column types match this shape.
1799
- const allRows = (await db
1800
- .select({
1801
- projectId: regTable.projectId,
1802
- projectPath: regTable.projectPath,
1803
- healthStatus: regTable.healthStatus,
1804
- lastIndexed: regTable.lastIndexed,
1805
- })
1806
- .from(regTable));
1807
- const matches = allRows.filter((row) => matchesCriteria(row.projectPath, row.healthStatus, row.lastIndexed));
1808
- const totalCount = allRows.length;
1809
- const matchCount = matches.length;
1810
- const samplePaths = matches.slice(0, 10).map((r) => r.projectPath);
1811
- // Always show preview
1812
- if (!jsonOutput) {
1813
- process.stdout.write(`[nexus] Clean preview — ${matchCount} project(s) of ${totalCount} total match criteria:\n`);
1814
- if (matchCount === 0) {
1815
- process.stdout.write(' (no matches)\n');
1816
- }
1817
- else {
1818
- for (const p of samplePaths) {
1819
- process.stdout.write(` ${p}\n`);
1820
- }
1821
- if (matchCount > 10) {
1822
- process.stdout.write(` ... and ${matchCount - 10} more\n`);
1823
- }
1824
- }
1825
- }
1826
- if (matchCount === 0) {
1827
- const durationMs = Date.now() - startTime;
1828
- if (jsonOutput) {
1829
- process.stdout.write(JSON.stringify({
1830
- success: true,
1831
- data: {
1832
- dryRun,
1833
- matched: 0,
1834
- purged: 0,
1835
- remaining: totalCount,
1836
- sample: [],
1837
- },
1838
- meta: {
1839
- operation: 'nexus.projects.clean',
1840
- duration_ms: durationMs,
1841
- timestamp: new Date().toISOString(),
1842
- },
1843
- }, null, 2) + '\n');
1844
- }
1845
- return;
1846
- }
1847
- // Dry-run: stop here
1848
- if (dryRun) {
1849
- const durationMs = Date.now() - startTime;
1850
- if (jsonOutput) {
1851
- process.stdout.write(JSON.stringify({
1852
- success: true,
1853
- data: {
1854
- dryRun: true,
1855
- matched: matchCount,
1856
- purged: 0,
1857
- remaining: totalCount,
1858
- sample: samplePaths,
1859
- },
1860
- meta: {
1861
- operation: 'nexus.projects.clean',
1862
- duration_ms: durationMs,
1863
- timestamp: new Date().toISOString(),
1864
- },
1865
- }, null, 2) + '\n');
1866
- }
1867
- else {
1868
- process.stdout.write(`[nexus] Dry-run — ${matchCount} project(s) would be purged. Rerun without --dry-run to delete.\n`);
1869
- }
1870
- return;
1871
- }
1872
- // Confirmation prompt (skip with --yes)
1873
- if (!skipPrompt) {
1874
- const { createInterface } = await import('node:readline');
1875
- const rl = createInterface({ input: process.stdin, output: process.stdout });
1876
- const confirmed = await new Promise((resolve) => {
1877
- rl.question(`\n[nexus] Delete ${matchCount} project(s) from the registry? [y/N] `, (answer) => {
1878
- rl.close();
1879
- resolve(answer.trim().toLowerCase() === 'y');
1880
- });
1881
- });
1882
- if (!confirmed) {
1883
- process.stdout.write('[nexus] Aborted — no projects deleted.\n');
1884
- return;
1885
- }
1886
- }
1887
- // Delete in a single transaction
1888
- const idsToDelete = matches.map((r) => r.projectId);
1889
- await db.delete(regTable).where(inArray(regTable.projectId, idsToDelete));
1890
- const remaining = totalCount - matchCount;
1891
- // Audit log (best-effort)
1892
- try {
1893
- await db.insert(auditTable).values({
1894
- id: randomUUID(),
1895
- action: 'projects.clean',
1896
- domain: 'nexus',
1897
- operation: 'projects.clean',
1898
- success: 1,
1899
- detailsJson: JSON.stringify({
1900
- pattern: patternRaw ?? null,
1901
- presets: {
1902
- includeTemp,
1903
- includeTests,
1904
- matchUnhealthy,
1905
- matchNeverIndexed,
1906
- },
1907
- count: matchCount,
1908
- sample: samplePaths,
1909
- }),
1910
- });
1911
- }
1912
- catch {
1913
- // Audit failure is non-fatal
1914
- }
1915
- const durationMs = Date.now() - startTime;
1916
- if (jsonOutput) {
1917
- process.stdout.write(JSON.stringify({
1918
- success: true,
1919
- data: {
1920
- dryRun: false,
1921
- matched: matchCount,
1922
- purged: matchCount,
1923
- remaining,
1924
- sample: samplePaths,
1925
- },
1926
- meta: {
1927
- operation: 'nexus.projects.clean',
1928
- duration_ms: durationMs,
1929
- timestamp: new Date().toISOString(),
1930
- },
1931
- }, null, 2) + '\n');
1932
- }
1933
- else {
1934
- process.stdout.write(`[nexus] Purged ${matchCount} project(s). ${remaining} project(s) remaining in registry.\n`);
1935
- }
1936
- }
1937
- catch (err) {
1938
- const msg = err instanceof Error ? err.message : String(err);
1939
- const durationMs = Date.now() - startTime;
1940
- if (jsonOutput) {
1941
- process.stdout.write(JSON.stringify({
1942
- success: false,
1943
- error: { code: 'E_CLEAN_FAILED', message: msg },
1944
- meta: {
1945
- operation: 'nexus.projects.clean',
1946
- duration_ms: durationMs,
1947
- timestamp: new Date().toISOString(),
1948
- },
1949
- }, null, 2) + '\n');
1950
- }
1951
- else {
1952
- process.stderr.write(`[nexus] Error: ${msg}\n`);
1953
- }
1954
- process.exitCode = 1;
1955
- }
1956
- });
1957
- // ── nexus refresh-bridge ──────────────────────────────────────────────────
1958
- nexus
1959
- .command('refresh-bridge [path]')
1960
- .description('Regenerate .cleo/nexus-bridge.md from the existing nexus.db index (does not re-index)')
1961
- .option('--json', 'Output result as JSON (LAFS envelope format)')
1962
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from path)')
1963
- .action(async (targetPath, opts) => {
1964
- const startTime = Date.now();
1965
- const jsonOutput = !!opts['json'];
1966
- const projectIdOverride = opts['projectId'];
1967
- const repoPath = targetPath ? path.resolve(targetPath) : process.cwd();
1968
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
1969
- try {
1970
- const { writeNexusBridge } = await import('@cleocode/core/internal');
1971
- const result = await writeNexusBridge(repoPath, projectId);
1972
- const durationMs = Date.now() - startTime;
1973
- if (jsonOutput) {
1974
- process.stdout.write(JSON.stringify({
1975
- success: true,
1976
- data: { path: result.path, written: result.written, projectId, repoPath },
1977
- meta: {
1978
- operation: 'nexus.refresh-bridge',
1979
- duration_ms: durationMs,
1980
- timestamp: new Date().toISOString(),
1981
- },
1982
- }, null, 2) + '\n');
1983
- }
1984
- else if (result.written) {
1985
- process.stdout.write(`[nexus] nexus-bridge.md refreshed at ${result.path}\n`);
1986
- }
1987
- else {
1988
- process.stdout.write(`[nexus] nexus-bridge.md unchanged at ${result.path}\n`);
1989
- }
1990
- }
1991
- catch (err) {
1992
- const msg = err instanceof Error ? err.message : String(err);
1993
- if (jsonOutput) {
1994
- process.stdout.write(JSON.stringify({
1995
- success: false,
1996
- error: { code: 'E_BRIDGE_FAILED', message: msg },
1997
- meta: {
1998
- operation: 'nexus.refresh-bridge',
1999
- duration_ms: Date.now() - startTime,
2000
- timestamp: new Date().toISOString(),
2001
- },
2002
- }, null, 2) + '\n');
2003
- }
2004
- else {
2005
- process.stderr.write(`[nexus] Error refreshing bridge: ${msg}\n`);
2006
- }
2007
- process.exitCode = 1;
2008
- }
2009
- });
2010
- // ── nexus export ──────────────────────────────────────────────────────────
2011
- /**
2012
- * Export nexus graph to GEXF (Gephi) or JSON format.
2013
- *
2014
- * Queries graph_nodes and graph_edges from nexus.db and emits GEXF format
2015
- * suitable for visualization in Gephi. Supports optional project filtering.
2016
- *
2017
- * @task T626-M7
2018
- */
2019
- nexus
2020
- .command('export')
2021
- .description('Export nexus graph to GEXF (Gephi) or JSON format')
2022
- .option('--format <format>', 'Output format: gexf, json', 'gexf')
2023
- .option('--output <file>', 'Output file path (stdout if omitted)')
2024
- .option('--project <id>', 'Filter by project ID (exports all projects if omitted)')
2025
- .action(async (opts) => {
2026
- const startTime = Date.now();
2027
- const format = opts['format'] ?? 'gexf';
2028
- const outputFile = opts['output'];
2029
- const projectFilter = opts['project'];
2030
- try {
2031
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
2032
- const db = await getNexusDb();
2033
- // Load all nodes and relations
2034
- let allNodes = [];
2035
- let allRelations = [];
2036
- try {
2037
- allNodes = db.select().from(nexusSchema.nexusNodes).all();
2038
- allRelations = db.select().from(nexusSchema.nexusRelations).all();
2039
- }
2040
- catch {
2041
- // DB may be empty
2042
- }
2043
- // Filter by project if specified
2044
- const nodes = projectFilter
2045
- ? allNodes.filter((n) => n['projectId'] === projectFilter)
2046
- : allNodes;
2047
- const relations = projectFilter
2048
- ? allRelations.filter((r) => r['projectId'] === projectFilter)
2049
- : allRelations;
2050
- let output = '';
2051
- if (format === 'json') {
2052
- output = JSON.stringify({
2053
- nodes: nodes.map((n) => ({
2054
- id: n['id'],
2055
- kind: n['kind'],
2056
- label: n['label'],
2057
- name: n['name'],
2058
- filePath: n['filePath'],
2059
- language: n['language'],
2060
- isExported: n['isExported'],
2061
- startLine: n['startLine'],
2062
- endLine: n['endLine'],
2063
- projectId: n['projectId'],
2064
- })),
2065
- edges: relations.map((r) => ({
2066
- id: r['id'],
2067
- source: r['sourceId'],
2068
- target: r['targetId'],
2069
- type: r['type'],
2070
- confidence: r['confidence'],
2071
- reason: r['reason'],
2072
- })),
2073
- }, null, 2);
2074
- }
2075
- else if (format === 'gexf') {
2076
- // GEXF format (Gephi standard)
2077
- output = generateGexf(nodes, relations);
2078
- }
2079
- else {
2080
- process.stderr.write(`[nexus] Error: Unknown format '${format}'. Supported: gexf, json\n`);
2081
- process.exitCode = 1;
2082
- return;
2083
- }
2084
- if (outputFile) {
2085
- const { writeFileSync } = await import('node:fs');
2086
- writeFileSync(outputFile, output, 'utf-8');
2087
- process.stdout.write(`[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)\n`);
2088
- }
2089
- else {
2090
- process.stdout.write(output);
2091
- if (!output.endsWith('\n'))
2092
- process.stdout.write('\n');
2093
- }
2094
- const durationMs = Date.now() - startTime;
2095
- if (outputFile) {
2096
- process.stderr.write(`[nexus] Export completed in ${durationMs}ms\n`);
2097
- }
2098
- }
2099
- catch (err) {
2100
- const msg = err instanceof Error ? err.message : String(err);
2101
- process.stderr.write(`[nexus] Error: ${msg}\n`);
2102
- process.exitCode = 1;
2103
- }
2104
- });
2105
- // ── nexus diff ────────────────────────────────────────────────────────────
2106
- /**
2107
- * Compare NEXUS index state between two git commits.
2108
- *
2109
- * Runs an incremental re-analysis against the current working tree state
2110
- * (representing the "after" snapshot) and compares relation/node counts
2111
- * against the pre-analysis snapshot. Reports new relations, removed
2112
- * relations, and any regressions detected.
2113
- *
2114
- * @task T625
2115
- */
2116
- nexus
2117
- .command('diff')
2118
- .description('Compare NEXUS index state between two git commits — shows new/removed relations and broken call chains')
2119
- .option('--before <sha>', 'Git SHA or ref for the "before" snapshot (default: HEAD~1)')
2120
- .option('--after <sha>', 'Git SHA or ref for the "after" snapshot (default: HEAD)', 'HEAD')
2121
- .option('--path <dir>', 'Repository directory to analyze (default: cwd)')
2122
- .option('--json', 'Output result as JSON (LAFS envelope format)')
2123
- .option('--project-id <id>', 'Override the project ID (default: auto-detected from path)')
2124
- .action(async (opts) => {
2125
- const startTime = Date.now();
2126
- const jsonOutput = !!opts['json'];
2127
- const repoPath = opts['path'] ? path.resolve(opts['path']) : process.cwd();
2128
- const projectIdOverride = opts['projectId'];
2129
- const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
2130
- const beforeRef = opts['before'] ?? 'HEAD~1';
2131
- const afterRef = opts['after'] ?? 'HEAD';
2132
- if (!jsonOutput) {
2133
- process.stderr.write(`[nexus] Diffing relations: ${beforeRef}..${afterRef} in ${repoPath}\n`);
2134
- }
2135
- try {
2136
- const { execFile: execFileNode } = await import('node:child_process');
2137
- const { promisify } = await import('node:util');
2138
- const execFileAsync = promisify(execFileNode);
2139
- /** Resolve a git ref to a short SHA. Falls back to the ref itself on failure. */
2140
- const resolveSha = async (ref) => {
2141
- try {
2142
- const { stdout } = await execFileAsync('git', ['rev-parse', '--short', ref], {
2143
- timeout: 5_000,
2144
- cwd: repoPath,
2145
- });
2146
- return stdout.trim();
2147
- }
2148
- catch {
2149
- return ref;
2150
- }
2151
- };
2152
- const [beforeSha, afterSha] = await Promise.all([
2153
- resolveSha(beforeRef),
2154
- resolveSha(afterRef),
2155
- ]);
2156
- // Get files changed between the two refs (TypeScript/JavaScript/Rust only)
2157
- let changedFiles = [];
2158
- try {
2159
- const { stdout: diffOutput } = await execFileAsync('git', ['diff', '--name-only', beforeSha, afterSha], { timeout: 10_000, cwd: repoPath });
2160
- changedFiles = diffOutput
2161
- .split('\n')
2162
- .map((f) => f.trim())
2163
- .filter((f) => f.length > 0 && (f.endsWith('.ts') || f.endsWith('.js') || f.endsWith('.rs')));
2164
- }
2165
- catch {
2166
- // git diff failed — proceed with full status comparison
2167
- }
2168
- // Load nexus DB and snapshot relation/node counts before incremental analysis
2169
- const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
2170
- const db = await getNexusDb();
2171
- let relationsBefore = 0;
2172
- let nodesBefore = 0;
2173
- try {
2174
- const allRelsBefore = db.select().from(nexusSchema.nexusRelations).all();
2175
- const allNodesBefore = db.select().from(nexusSchema.nexusNodes).all();
2176
- relationsBefore = allRelsBefore.filter((r) => r['projectId'] === projectId).length;
2177
- nodesBefore = allNodesBefore.filter((n) => n['projectId'] === projectId).length;
2178
- }
2179
- catch {
2180
- // DB not yet initialized — start from zero
2181
- }
2182
- // Run incremental pipeline to reflect the afterRef state
2183
- const { runPipeline } = await import('@cleocode/nexus/pipeline');
2184
- const pipelineResult = await runPipeline(repoPath, projectId, db, {
2185
- nexusNodes: nexusSchema.nexusNodes,
2186
- nexusRelations: nexusSchema.nexusRelations,
2187
- }, undefined, // no progress callback in diff mode
2188
- { incremental: true });
2189
- // Snapshot counts after incremental analysis
2190
- let relationsAfter = 0;
2191
- let nodesAfter = 0;
2192
- try {
2193
- const allRelsAfter = db.select().from(nexusSchema.nexusRelations).all();
2194
- const allNodesAfter = db.select().from(nexusSchema.nexusNodes).all();
2195
- relationsAfter = allRelsAfter.filter((r) => r['projectId'] === projectId).length;
2196
- nodesAfter = allNodesAfter.filter((n) => n['projectId'] === projectId).length;
2197
- }
2198
- catch {
2199
- // Fallback: use pipeline result counts directly
2200
- relationsAfter = pipelineResult.relationCount;
2201
- nodesAfter = pipelineResult.nodeCount;
2202
- }
2203
- const newRelations = Math.max(0, relationsAfter - relationsBefore);
2204
- const removedRelations = Math.max(0, relationsBefore - relationsAfter);
2205
- const newNodes = Math.max(0, nodesAfter - nodesBefore);
2206
- const removedNodes = Math.max(0, nodesBefore - nodesAfter);
2207
- const durationMs = Date.now() - startTime;
2208
- // Classify regressions: significant relation or node loss
2209
- const regressions = [];
2210
- if (removedRelations > 5) {
2211
- regressions.push(`${removedRelations} relations removed — verify no broken call chains`);
2212
- }
2213
- if (removedNodes > 0) {
2214
- regressions.push(`${removedNodes} symbols removed — callers may be broken`);
2215
- }
2216
- const diffHealthStatus = regressions.length > 0
2217
- ? 'REGRESSIONS_DETECTED'
2218
- : removedRelations > 0
2219
- ? 'RELATIONS_REDUCED'
2220
- : newRelations > 0
2221
- ? 'RELATIONS_ADDED'
2222
- : 'STABLE';
2223
- if (jsonOutput) {
2224
- process.stdout.write(JSON.stringify({
2225
- success: true,
2226
- data: {
2227
- beforeRef,
2228
- afterRef,
2229
- beforeSha,
2230
- afterSha,
2231
- projectId,
2232
- repoPath,
2233
- changedFiles,
2234
- nodesBefore,
2235
- nodesAfter,
2236
- newNodes,
2237
- removedNodes,
2238
- relationsBefore,
2239
- relationsAfter,
2240
- newRelations,
2241
- removedRelations,
2242
- healthStatus: diffHealthStatus,
2243
- regressions,
2244
- },
2245
- meta: {
2246
- operation: 'nexus.diff',
2247
- duration_ms: durationMs,
2248
- timestamp: new Date().toISOString(),
2249
- },
2250
- }, null, 2) + '\n');
2251
- }
2252
- else {
2253
- process.stdout.write(`[nexus] Diff: ${beforeSha}..${afterSha}\n` +
2254
- ` Changed files: ${changedFiles.length > 0 ? changedFiles.join(', ') : 'n/a'}\n` +
2255
- ` Nodes: before=${nodesBefore} after=${nodesAfter} new=+${newNodes} removed=-${removedNodes}\n` +
2256
- ` Relations: before=${relationsBefore} after=${relationsAfter} new=+${newRelations} removed=-${removedRelations}\n` +
2257
- ` Health: ${diffHealthStatus}\n`);
2258
- if (regressions.length > 0) {
2259
- process.stdout.write('\n REGRESSIONS:\n');
2260
- for (const reg of regressions) {
2261
- process.stdout.write(` - ${reg}\n`);
2262
- }
2263
- }
2264
- else {
2265
- process.stdout.write(' No regressions detected.\n');
2266
- }
2267
- }
2268
- }
2269
- catch (err) {
2270
- const msg = err instanceof Error ? err.message : String(err);
2271
- const durationMs = Date.now() - startTime;
2272
- if (jsonOutput) {
2273
- process.stdout.write(JSON.stringify({
2274
- success: false,
2275
- error: { code: 'E_DIFF_FAILED', message: msg },
2276
- meta: {
2277
- operation: 'nexus.diff',
2278
- duration_ms: durationMs,
2279
- timestamp: new Date().toISOString(),
2280
- },
2281
- }, null, 2) + '\n');
2282
- }
2283
- else {
2284
- process.stderr.write(`[nexus] Error running diff: ${msg}\n`);
2285
- }
2286
- process.exitCode = 1;
2287
- }
2288
- });
2289
- }
2290
- //# sourceMappingURL=nexus.js.map