@cleocode/cleo 2026.4.161 → 2026.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (857) hide show
  1. package/dist/backfill/audit-columns.d.ts +105 -0
  2. package/dist/backfill/audit-columns.d.ts.map +1 -0
  3. package/dist/backfill/audit-columns.js +258 -0
  4. package/dist/backfill/audit-columns.js.map +1 -0
  5. package/dist/cli/commands/adapter.d.ts +28 -0
  6. package/dist/cli/commands/adapter.d.ts.map +1 -0
  7. package/dist/cli/commands/adapter.js +119 -0
  8. package/dist/cli/commands/adapter.js.map +1 -0
  9. package/dist/cli/commands/add-batch.d.ts +33 -0
  10. package/dist/cli/commands/add-batch.d.ts.map +1 -0
  11. package/dist/cli/commands/add-batch.js +148 -0
  12. package/dist/cli/commands/add-batch.js.map +1 -0
  13. package/dist/cli/commands/add.d.ts +162 -0
  14. package/dist/cli/commands/add.d.ts.map +1 -0
  15. package/dist/cli/commands/add.js +279 -0
  16. package/dist/cli/commands/add.js.map +1 -0
  17. package/dist/cli/commands/admin.d.ts +24 -0
  18. package/dist/cli/commands/admin.d.ts.map +1 -0
  19. package/dist/cli/commands/admin.js +283 -0
  20. package/dist/cli/commands/admin.js.map +1 -0
  21. package/dist/cli/commands/adr.d.ts +33 -0
  22. package/dist/cli/commands/adr.d.ts.map +1 -0
  23. package/dist/cli/commands/adr.js +147 -0
  24. package/dist/cli/commands/adr.js.map +1 -0
  25. package/dist/cli/commands/agent-profile-status.d.ts +98 -0
  26. package/dist/cli/commands/agent-profile-status.d.ts.map +1 -0
  27. package/dist/cli/commands/agent-profile-status.js +71 -0
  28. package/dist/cli/commands/agent-profile-status.js.map +1 -0
  29. package/dist/cli/commands/agent.d.ts +47 -0
  30. package/dist/cli/commands/agent.d.ts.map +1 -0
  31. package/dist/cli/commands/agent.js +2976 -0
  32. package/dist/cli/commands/agent.js.map +1 -0
  33. package/dist/cli/commands/analyze.d.ts +21 -0
  34. package/dist/cli/commands/analyze.d.ts.map +1 -0
  35. package/dist/cli/commands/analyze.js +32 -0
  36. package/dist/cli/commands/analyze.js.map +1 -0
  37. package/dist/cli/commands/archive-stats.d.ts +66 -0
  38. package/dist/cli/commands/archive-stats.d.ts.map +1 -0
  39. package/dist/cli/commands/archive-stats.js +93 -0
  40. package/dist/cli/commands/archive-stats.js.map +1 -0
  41. package/dist/cli/commands/archive.d.ts +42 -0
  42. package/dist/cli/commands/archive.d.ts.map +1 -0
  43. package/dist/cli/commands/archive.js +59 -0
  44. package/dist/cli/commands/archive.js.map +1 -0
  45. package/dist/cli/commands/audit.d.ts +22 -0
  46. package/dist/cli/commands/audit.d.ts.map +1 -0
  47. package/dist/cli/commands/audit.js +137 -0
  48. package/dist/cli/commands/audit.js.map +1 -0
  49. package/dist/cli/commands/backfill.d.ts +56 -0
  50. package/dist/cli/commands/backfill.d.ts.map +1 -0
  51. package/dist/cli/commands/backfill.js +161 -0
  52. package/dist/cli/commands/backfill.js.map +1 -0
  53. package/dist/cli/commands/backup-inspect.d.ts +33 -0
  54. package/dist/cli/commands/backup-inspect.d.ts.map +1 -0
  55. package/dist/cli/commands/backup-inspect.js +430 -0
  56. package/dist/cli/commands/backup-inspect.js.map +1 -0
  57. package/dist/cli/commands/backup.d.ts +23 -0
  58. package/dist/cli/commands/backup.d.ts.map +1 -0
  59. package/dist/cli/commands/backup.js +564 -0
  60. package/dist/cli/commands/backup.js.map +1 -0
  61. package/dist/cli/commands/blockers.d.ts +20 -0
  62. package/dist/cli/commands/blockers.d.ts.map +1 -0
  63. package/dist/cli/commands/blockers.js +31 -0
  64. package/dist/cli/commands/blockers.js.map +1 -0
  65. package/dist/cli/commands/brain.d.ts +37 -0
  66. package/dist/cli/commands/brain.d.ts.map +1 -0
  67. package/dist/cli/commands/brain.js +445 -0
  68. package/dist/cli/commands/brain.js.map +1 -0
  69. package/dist/cli/commands/briefing.d.ts +52 -0
  70. package/dist/cli/commands/briefing.d.ts.map +1 -0
  71. package/dist/cli/commands/briefing.js +69 -0
  72. package/dist/cli/commands/briefing.js.map +1 -0
  73. package/dist/cli/commands/bug.d.ts +61 -0
  74. package/dist/cli/commands/bug.d.ts.map +1 -0
  75. package/dist/cli/commands/bug.js +198 -0
  76. package/dist/cli/commands/bug.js.map +1 -0
  77. package/dist/cli/commands/cancel.d.ts +26 -0
  78. package/dist/cli/commands/cancel.d.ts.map +1 -0
  79. package/dist/cli/commands/cancel.js +40 -0
  80. package/dist/cli/commands/cancel.js.map +1 -0
  81. package/dist/cli/commands/cant.d.ts +13 -0
  82. package/dist/cli/commands/cant.d.ts.map +1 -0
  83. package/dist/cli/commands/cant.js +245 -0
  84. package/dist/cli/commands/cant.js.map +1 -0
  85. package/dist/cli/commands/chain.d.ts +24 -0
  86. package/dist/cli/commands/chain.d.ts.map +1 -0
  87. package/dist/cli/commands/chain.js +116 -0
  88. package/dist/cli/commands/chain.js.map +1 -0
  89. package/dist/cli/commands/check.d.ts +18 -0
  90. package/dist/cli/commands/check.d.ts.map +1 -0
  91. package/dist/cli/commands/check.js +280 -0
  92. package/dist/cli/commands/check.js.map +1 -0
  93. package/dist/cli/commands/checkpoint.d.ts +27 -0
  94. package/dist/cli/commands/checkpoint.d.ts.map +1 -0
  95. package/dist/cli/commands/checkpoint.js +105 -0
  96. package/dist/cli/commands/checkpoint.js.map +1 -0
  97. package/dist/cli/commands/claim.d.ts +35 -0
  98. package/dist/cli/commands/claim.d.ts.map +1 -0
  99. package/dist/cli/commands/claim.js +35 -0
  100. package/dist/cli/commands/claim.js.map +1 -0
  101. package/dist/cli/commands/code.d.ts +22 -0
  102. package/dist/cli/commands/code.d.ts.map +1 -0
  103. package/dist/cli/commands/code.js +161 -0
  104. package/dist/cli/commands/code.js.map +1 -0
  105. package/dist/cli/commands/complete.d.ts +58 -0
  106. package/dist/cli/commands/complete.d.ts.map +1 -0
  107. package/dist/cli/commands/complete.js +83 -0
  108. package/dist/cli/commands/complete.js.map +1 -0
  109. package/dist/cli/commands/complexity.d.ts +13 -0
  110. package/dist/cli/commands/complexity.d.ts.map +1 -0
  111. package/dist/cli/commands/complexity.js +32 -0
  112. package/dist/cli/commands/complexity.js.map +1 -0
  113. package/dist/cli/commands/compliance.d.ts +27 -0
  114. package/dist/cli/commands/compliance.d.ts.map +1 -0
  115. package/dist/cli/commands/compliance.js +233 -0
  116. package/dist/cli/commands/compliance.js.map +1 -0
  117. package/dist/cli/commands/conduit.d.ts +28 -0
  118. package/dist/cli/commands/conduit.d.ts.map +1 -0
  119. package/dist/cli/commands/conduit.js +279 -0
  120. package/dist/cli/commands/conduit.js.map +1 -0
  121. package/dist/cli/commands/config.d.ts +25 -0
  122. package/dist/cli/commands/config.d.ts.map +1 -0
  123. package/dist/cli/commands/config.js +132 -0
  124. package/dist/cli/commands/config.js.map +1 -0
  125. package/dist/cli/commands/consensus.d.ts +21 -0
  126. package/dist/cli/commands/consensus.d.ts.map +1 -0
  127. package/dist/cli/commands/consensus.js +100 -0
  128. package/dist/cli/commands/consensus.js.map +1 -0
  129. package/dist/cli/commands/context.d.ts +19 -0
  130. package/dist/cli/commands/context.d.ts.map +1 -0
  131. package/dist/cli/commands/context.js +111 -0
  132. package/dist/cli/commands/context.js.map +1 -0
  133. package/dist/cli/commands/contribution.d.ts +21 -0
  134. package/dist/cli/commands/contribution.d.ts.map +1 -0
  135. package/dist/cli/commands/contribution.js +90 -0
  136. package/dist/cli/commands/contribution.js.map +1 -0
  137. package/dist/cli/commands/current.d.ts +18 -0
  138. package/dist/cli/commands/current.d.ts.map +1 -0
  139. package/dist/cli/commands/current.js +28 -0
  140. package/dist/cli/commands/current.js.map +1 -0
  141. package/dist/cli/commands/daemon.d.ts +36 -0
  142. package/dist/cli/commands/daemon.d.ts.map +1 -0
  143. package/dist/cli/commands/daemon.js +223 -0
  144. package/dist/cli/commands/daemon.js.map +1 -0
  145. package/dist/cli/commands/dash.d.ts +23 -0
  146. package/dist/cli/commands/dash.d.ts.map +1 -0
  147. package/dist/cli/commands/dash.js +38 -0
  148. package/dist/cli/commands/dash.js.map +1 -0
  149. package/dist/cli/commands/decomposition.d.ts +13 -0
  150. package/dist/cli/commands/decomposition.d.ts.map +1 -0
  151. package/dist/cli/commands/decomposition.js +92 -0
  152. package/dist/cli/commands/decomposition.js.map +1 -0
  153. package/dist/cli/commands/delete.d.ts +29 -0
  154. package/dist/cli/commands/delete.d.ts.map +1 -0
  155. package/dist/cli/commands/delete.js +55 -0
  156. package/dist/cli/commands/delete.js.map +1 -0
  157. package/dist/cli/commands/deps.d.ts +45 -0
  158. package/dist/cli/commands/deps.d.ts.map +1 -0
  159. package/dist/cli/commands/deps.js +170 -0
  160. package/dist/cli/commands/deps.js.map +1 -0
  161. package/dist/cli/commands/detect-drift.d.ts +23 -0
  162. package/dist/cli/commands/detect-drift.d.ts.map +1 -0
  163. package/dist/cli/commands/detect-drift.js +440 -0
  164. package/dist/cli/commands/detect-drift.js.map +1 -0
  165. package/dist/cli/commands/detect.d.ts +3 -0
  166. package/dist/cli/commands/detect.d.ts.map +1 -0
  167. package/dist/cli/commands/detect.js +14 -0
  168. package/dist/cli/commands/detect.js.map +1 -0
  169. package/dist/cli/commands/diagnostics.d.ts +19 -0
  170. package/dist/cli/commands/diagnostics.d.ts.map +1 -0
  171. package/dist/cli/commands/diagnostics.js +109 -0
  172. package/dist/cli/commands/diagnostics.js.map +1 -0
  173. package/dist/cli/commands/docs.d.ts +25 -0
  174. package/dist/cli/commands/docs.d.ts.map +1 -0
  175. package/dist/cli/commands/docs.js +798 -0
  176. package/dist/cli/commands/docs.js.map +1 -0
  177. package/dist/cli/commands/doctor-projects.d.ts +101 -0
  178. package/dist/cli/commands/doctor-projects.d.ts.map +1 -0
  179. package/dist/cli/commands/doctor-projects.js +188 -0
  180. package/dist/cli/commands/doctor-projects.js.map +1 -0
  181. package/dist/cli/commands/doctor.d.ts +66 -0
  182. package/dist/cli/commands/doctor.d.ts.map +1 -0
  183. package/dist/cli/commands/doctor.js +178 -0
  184. package/dist/cli/commands/doctor.js.map +1 -0
  185. package/dist/cli/commands/dynamic.d.ts +15 -0
  186. package/dist/cli/commands/dynamic.d.ts.map +1 -0
  187. package/dist/cli/commands/dynamic.js +21 -0
  188. package/dist/cli/commands/dynamic.js.map +1 -0
  189. package/dist/cli/commands/exists.d.ts +13 -0
  190. package/dist/cli/commands/exists.d.ts.map +1 -0
  191. package/dist/cli/commands/exists.js +40 -0
  192. package/dist/cli/commands/exists.js.map +1 -0
  193. package/dist/cli/commands/export-tasks.d.ts +46 -0
  194. package/dist/cli/commands/export-tasks.d.ts.map +1 -0
  195. package/dist/cli/commands/export-tasks.js +81 -0
  196. package/dist/cli/commands/export-tasks.js.map +1 -0
  197. package/dist/cli/commands/export.d.ts +35 -0
  198. package/dist/cli/commands/export.d.ts.map +1 -0
  199. package/dist/cli/commands/export.js +68 -0
  200. package/dist/cli/commands/export.js.map +1 -0
  201. package/dist/cli/commands/find.d.ts +54 -0
  202. package/dist/cli/commands/find.d.ts.map +1 -0
  203. package/dist/cli/commands/find.js +92 -0
  204. package/dist/cli/commands/find.js.map +1 -0
  205. package/dist/cli/commands/gc.d.ts +25 -0
  206. package/dist/cli/commands/gc.d.ts.map +1 -0
  207. package/dist/cli/commands/gc.js +165 -0
  208. package/dist/cli/commands/gc.js.map +1 -0
  209. package/dist/cli/commands/generate-changelog.d.ts +30 -0
  210. package/dist/cli/commands/generate-changelog.d.ts.map +1 -0
  211. package/dist/cli/commands/generate-changelog.js +270 -0
  212. package/dist/cli/commands/generate-changelog.js.map +1 -0
  213. package/dist/cli/commands/grade.d.ts +13 -0
  214. package/dist/cli/commands/grade.d.ts.map +1 -0
  215. package/dist/cli/commands/grade.js +27 -0
  216. package/dist/cli/commands/grade.js.map +1 -0
  217. package/dist/cli/commands/history.d.ts +13 -0
  218. package/dist/cli/commands/history.d.ts.map +1 -0
  219. package/dist/cli/commands/history.js +65 -0
  220. package/dist/cli/commands/history.js.map +1 -0
  221. package/dist/cli/commands/import-tasks.d.ts +60 -0
  222. package/dist/cli/commands/import-tasks.d.ts.map +1 -0
  223. package/dist/cli/commands/import-tasks.js +83 -0
  224. package/dist/cli/commands/import-tasks.js.map +1 -0
  225. package/dist/cli/commands/import.d.ts +42 -0
  226. package/dist/cli/commands/import.d.ts.map +1 -0
  227. package/dist/cli/commands/import.js +64 -0
  228. package/dist/cli/commands/import.js.map +1 -0
  229. package/dist/cli/commands/init.d.ts +65 -0
  230. package/dist/cli/commands/init.d.ts.map +1 -0
  231. package/dist/cli/commands/init.js +122 -0
  232. package/dist/cli/commands/init.js.map +1 -0
  233. package/dist/cli/commands/inject.d.ts +41 -0
  234. package/dist/cli/commands/inject.d.ts.map +1 -0
  235. package/dist/cli/commands/inject.js +56 -0
  236. package/dist/cli/commands/inject.js.map +1 -0
  237. package/dist/cli/commands/install-global.d.ts +48 -0
  238. package/dist/cli/commands/install-global.d.ts.map +1 -0
  239. package/dist/cli/commands/install-global.js +104 -0
  240. package/dist/cli/commands/install-global.js.map +1 -0
  241. package/dist/cli/commands/intelligence.d.ts +21 -0
  242. package/dist/cli/commands/intelligence.d.ts.map +1 -0
  243. package/dist/cli/commands/intelligence.js +145 -0
  244. package/dist/cli/commands/intelligence.js.map +1 -0
  245. package/dist/cli/commands/issue.d.ts +23 -0
  246. package/dist/cli/commands/issue.d.ts.map +1 -0
  247. package/dist/cli/commands/issue.js +152 -0
  248. package/dist/cli/commands/issue.js.map +1 -0
  249. package/dist/cli/commands/labels.d.ts +21 -0
  250. package/dist/cli/commands/labels.d.ts.map +1 -0
  251. package/dist/cli/commands/labels.js +65 -0
  252. package/dist/cli/commands/labels.js.map +1 -0
  253. package/dist/cli/commands/lifecycle.d.ts +25 -0
  254. package/dist/cli/commands/lifecycle.d.ts.map +1 -0
  255. package/dist/cli/commands/lifecycle.js +221 -0
  256. package/dist/cli/commands/lifecycle.js.map +1 -0
  257. package/dist/cli/commands/list.d.ts +28 -0
  258. package/dist/cli/commands/list.d.ts.map +1 -0
  259. package/dist/cli/commands/list.js +81 -0
  260. package/dist/cli/commands/list.js.map +1 -0
  261. package/dist/cli/commands/log.d.ts +36 -0
  262. package/dist/cli/commands/log.d.ts.map +1 -0
  263. package/dist/cli/commands/log.js +50 -0
  264. package/dist/cli/commands/log.js.map +1 -0
  265. package/dist/cli/commands/manifest.d.ts +15 -0
  266. package/dist/cli/commands/manifest.d.ts.map +1 -0
  267. package/dist/cli/commands/manifest.js +334 -0
  268. package/dist/cli/commands/manifest.js.map +1 -0
  269. package/dist/cli/commands/map.d.ts +25 -0
  270. package/dist/cli/commands/map.d.ts.map +1 -0
  271. package/dist/cli/commands/map.js +37 -0
  272. package/dist/cli/commands/map.js.map +1 -0
  273. package/dist/cli/commands/memory.d.ts +48 -0
  274. package/dist/cli/commands/memory.d.ts.map +1 -0
  275. package/dist/cli/commands/memory.js +2439 -0
  276. package/dist/cli/commands/memory.js.map +1 -0
  277. package/dist/cli/commands/migrate-claude-mem.d.ts +23 -0
  278. package/dist/cli/commands/migrate-claude-mem.d.ts.map +1 -0
  279. package/dist/cli/commands/migrate-claude-mem.js +181 -0
  280. package/dist/cli/commands/migrate-claude-mem.js.map +1 -0
  281. package/dist/cli/commands/next.d.ts +27 -0
  282. package/dist/cli/commands/next.d.ts.map +1 -0
  283. package/dist/cli/commands/next.js +40 -0
  284. package/dist/cli/commands/next.js.map +1 -0
  285. package/dist/cli/commands/nexus.d.ts +15 -0
  286. package/dist/cli/commands/nexus.d.ts.map +1 -0
  287. package/dist/cli/commands/nexus.js +3377 -0
  288. package/dist/cli/commands/nexus.js.map +1 -0
  289. package/dist/cli/commands/ops.d.ts +23 -0
  290. package/dist/cli/commands/ops.d.ts.map +1 -0
  291. package/dist/cli/commands/ops.js +35 -0
  292. package/dist/cli/commands/ops.js.map +1 -0
  293. package/dist/cli/commands/orchestrate.d.ts +48 -0
  294. package/dist/cli/commands/orchestrate.d.ts.map +1 -0
  295. package/dist/cli/commands/orchestrate.js +774 -0
  296. package/dist/cli/commands/orchestrate.js.map +1 -0
  297. package/dist/cli/commands/otel.d.ts +30 -0
  298. package/dist/cli/commands/otel.d.ts.map +1 -0
  299. package/dist/cli/commands/otel.js +193 -0
  300. package/dist/cli/commands/otel.js.map +1 -0
  301. package/dist/cli/commands/phase.d.ts +29 -0
  302. package/dist/cli/commands/phase.d.ts.map +1 -0
  303. package/dist/cli/commands/phase.js +189 -0
  304. package/dist/cli/commands/phase.js.map +1 -0
  305. package/dist/cli/commands/pivot.d.ts +34 -0
  306. package/dist/cli/commands/pivot.d.ts.map +1 -0
  307. package/dist/cli/commands/pivot.js +50 -0
  308. package/dist/cli/commands/pivot.js.map +1 -0
  309. package/dist/cli/commands/plan.d.ts +17 -0
  310. package/dist/cli/commands/plan.d.ts.map +1 -0
  311. package/dist/cli/commands/plan.js +27 -0
  312. package/dist/cli/commands/plan.js.map +1 -0
  313. package/dist/cli/commands/playbook.d.ts +26 -0
  314. package/dist/cli/commands/playbook.d.ts.map +1 -0
  315. package/dist/cli/commands/playbook.js +220 -0
  316. package/dist/cli/commands/playbook.js.map +1 -0
  317. package/dist/cli/commands/promote.d.ts +19 -0
  318. package/dist/cli/commands/promote.d.ts.map +1 -0
  319. package/dist/cli/commands/promote.js +27 -0
  320. package/dist/cli/commands/promote.js.map +1 -0
  321. package/dist/cli/commands/provider.d.ts +23 -0
  322. package/dist/cli/commands/provider.d.ts.map +1 -0
  323. package/dist/cli/commands/provider.js +168 -0
  324. package/dist/cli/commands/provider.js.map +1 -0
  325. package/dist/cli/commands/reason.d.ts +18 -0
  326. package/dist/cli/commands/reason.d.ts.map +1 -0
  327. package/dist/cli/commands/reason.js +102 -0
  328. package/dist/cli/commands/reason.js.map +1 -0
  329. package/dist/cli/commands/reconcile.d.ts +35 -0
  330. package/dist/cli/commands/reconcile.d.ts.map +1 -0
  331. package/dist/cli/commands/reconcile.js +102 -0
  332. package/dist/cli/commands/reconcile.js.map +1 -0
  333. package/dist/cli/commands/refresh-memory.d.ts +16 -0
  334. package/dist/cli/commands/refresh-memory.d.ts.map +1 -0
  335. package/dist/cli/commands/refresh-memory.js +34 -0
  336. package/dist/cli/commands/refresh-memory.js.map +1 -0
  337. package/dist/cli/commands/relates.d.ts +19 -0
  338. package/dist/cli/commands/relates.d.ts.map +1 -0
  339. package/dist/cli/commands/relates.js +129 -0
  340. package/dist/cli/commands/relates.js.map +1 -0
  341. package/dist/cli/commands/release.d.ts +27 -0
  342. package/dist/cli/commands/release.d.ts.map +1 -0
  343. package/dist/cli/commands/release.js +300 -0
  344. package/dist/cli/commands/release.js.map +1 -0
  345. package/dist/cli/commands/remote.d.ts +49 -0
  346. package/dist/cli/commands/remote.d.ts.map +1 -0
  347. package/dist/cli/commands/remote.js +265 -0
  348. package/dist/cli/commands/remote.js.map +1 -0
  349. package/dist/cli/commands/reorder.d.ts +31 -0
  350. package/dist/cli/commands/reorder.d.ts.map +1 -0
  351. package/dist/cli/commands/reorder.js +57 -0
  352. package/dist/cli/commands/reorder.js.map +1 -0
  353. package/dist/cli/commands/reparent.d.ts +27 -0
  354. package/dist/cli/commands/reparent.d.ts.map +1 -0
  355. package/dist/cli/commands/reparent.js +36 -0
  356. package/dist/cli/commands/reparent.js.map +1 -0
  357. package/dist/cli/commands/req.d.ts +37 -0
  358. package/dist/cli/commands/req.d.ts.map +1 -0
  359. package/dist/cli/commands/req.js +121 -0
  360. package/dist/cli/commands/req.js.map +1 -0
  361. package/dist/cli/commands/research.d.ts +25 -0
  362. package/dist/cli/commands/research.d.ts.map +1 -0
  363. package/dist/cli/commands/research.js +327 -0
  364. package/dist/cli/commands/research.js.map +1 -0
  365. package/dist/cli/commands/restore.d.ts +64 -0
  366. package/dist/cli/commands/restore.d.ts.map +1 -0
  367. package/dist/cli/commands/restore.js +539 -0
  368. package/dist/cli/commands/restore.js.map +1 -0
  369. package/dist/cli/commands/revert.d.ts +79 -0
  370. package/dist/cli/commands/revert.d.ts.map +1 -0
  371. package/dist/cli/commands/revert.js +300 -0
  372. package/dist/cli/commands/revert.js.map +1 -0
  373. package/dist/cli/commands/roadmap.d.ts +29 -0
  374. package/dist/cli/commands/roadmap.d.ts.map +1 -0
  375. package/dist/cli/commands/roadmap.js +43 -0
  376. package/dist/cli/commands/roadmap.js.map +1 -0
  377. package/dist/cli/commands/safestop.d.ts +41 -0
  378. package/dist/cli/commands/safestop.d.ts.map +1 -0
  379. package/dist/cli/commands/safestop.js +62 -0
  380. package/dist/cli/commands/safestop.js.map +1 -0
  381. package/dist/cli/commands/schema.d.ts +44 -0
  382. package/dist/cli/commands/schema.d.ts.map +1 -0
  383. package/dist/cli/commands/schema.js +177 -0
  384. package/dist/cli/commands/schema.js.map +1 -0
  385. package/dist/cli/commands/self-update.d.ts +81 -0
  386. package/dist/cli/commands/self-update.d.ts.map +1 -0
  387. package/dist/cli/commands/self-update.js +483 -0
  388. package/dist/cli/commands/self-update.js.map +1 -0
  389. package/dist/cli/commands/sentient.d.ts +44 -0
  390. package/dist/cli/commands/sentient.d.ts.map +1 -0
  391. package/dist/cli/commands/sentient.js +687 -0
  392. package/dist/cli/commands/sentient.js.map +1 -0
  393. package/dist/cli/commands/sequence.d.ts +15 -0
  394. package/dist/cli/commands/sequence.d.ts.map +1 -0
  395. package/dist/cli/commands/sequence.js +68 -0
  396. package/dist/cli/commands/sequence.js.map +1 -0
  397. package/dist/cli/commands/session.d.ts +32 -0
  398. package/dist/cli/commands/session.d.ts.map +1 -0
  399. package/dist/cli/commands/session.js +583 -0
  400. package/dist/cli/commands/session.js.map +1 -0
  401. package/dist/cli/commands/show.d.ts +21 -0
  402. package/dist/cli/commands/show.d.ts.map +1 -0
  403. package/dist/cli/commands/show.js +37 -0
  404. package/dist/cli/commands/show.js.map +1 -0
  405. package/dist/cli/commands/skills.d.ts +31 -0
  406. package/dist/cli/commands/skills.d.ts.map +1 -0
  407. package/dist/cli/commands/skills.js +303 -0
  408. package/dist/cli/commands/skills.js.map +1 -0
  409. package/dist/cli/commands/snapshot.d.ts +17 -0
  410. package/dist/cli/commands/snapshot.d.ts.map +1 -0
  411. package/dist/cli/commands/snapshot.js +95 -0
  412. package/dist/cli/commands/snapshot.js.map +1 -0
  413. package/dist/cli/commands/start.d.ts +21 -0
  414. package/dist/cli/commands/start.d.ts.map +1 -0
  415. package/dist/cli/commands/start.js +32 -0
  416. package/dist/cli/commands/start.js.map +1 -0
  417. package/dist/cli/commands/stats.d.ts +30 -0
  418. package/dist/cli/commands/stats.d.ts.map +1 -0
  419. package/dist/cli/commands/stats.js +71 -0
  420. package/dist/cli/commands/stats.js.map +1 -0
  421. package/dist/cli/commands/sticky.d.ts +23 -0
  422. package/dist/cli/commands/sticky.d.ts.map +1 -0
  423. package/dist/cli/commands/sticky.js +315 -0
  424. package/dist/cli/commands/sticky.js.map +1 -0
  425. package/dist/cli/commands/stop.d.ts +15 -0
  426. package/dist/cli/commands/stop.d.ts.map +1 -0
  427. package/dist/cli/commands/stop.js +25 -0
  428. package/dist/cli/commands/stop.js.map +1 -0
  429. package/dist/cli/commands/sync.d.ts +25 -0
  430. package/dist/cli/commands/sync.d.ts.map +1 -0
  431. package/dist/cli/commands/sync.js +125 -0
  432. package/dist/cli/commands/sync.js.map +1 -0
  433. package/dist/cli/commands/testing.d.ts +22 -0
  434. package/dist/cli/commands/testing.d.ts.map +1 -0
  435. package/dist/cli/commands/testing.js +111 -0
  436. package/dist/cli/commands/testing.js.map +1 -0
  437. package/dist/cli/commands/token.d.ts +22 -0
  438. package/dist/cli/commands/token.d.ts.map +1 -0
  439. package/dist/cli/commands/token.js +197 -0
  440. package/dist/cli/commands/token.js.map +1 -0
  441. package/dist/cli/commands/transcript.d.ts +32 -0
  442. package/dist/cli/commands/transcript.d.ts.map +1 -0
  443. package/dist/cli/commands/transcript.js +526 -0
  444. package/dist/cli/commands/transcript.js.map +1 -0
  445. package/dist/cli/commands/update.d.ts +164 -0
  446. package/dist/cli/commands/update.d.ts.map +1 -0
  447. package/dist/cli/commands/update.js +234 -0
  448. package/dist/cli/commands/update.js.map +1 -0
  449. package/dist/cli/commands/upgrade.d.ts +76 -0
  450. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  451. package/dist/cli/commands/upgrade.js +154 -0
  452. package/dist/cli/commands/upgrade.js.map +1 -0
  453. package/dist/cli/commands/verify.d.ts +83 -0
  454. package/dist/cli/commands/verify.d.ts.map +1 -0
  455. package/dist/cli/commands/verify.js +108 -0
  456. package/dist/cli/commands/verify.js.map +1 -0
  457. package/dist/cli/commands/web.d.ts +27 -0
  458. package/dist/cli/commands/web.d.ts.map +1 -0
  459. package/dist/cli/commands/web.js +414 -0
  460. package/dist/cli/commands/web.js.map +1 -0
  461. package/dist/cli/field-context.d.ts +32 -0
  462. package/dist/cli/field-context.d.ts.map +1 -0
  463. package/dist/cli/field-context.js +47 -0
  464. package/dist/cli/field-context.js.map +1 -0
  465. package/dist/cli/format-context.d.ts +32 -0
  466. package/dist/cli/format-context.d.ts.map +1 -0
  467. package/dist/cli/format-context.js +50 -0
  468. package/dist/cli/format-context.js.map +1 -0
  469. package/dist/cli/help-renderer.d.ts +40 -0
  470. package/dist/cli/help-renderer.d.ts.map +1 -0
  471. package/dist/cli/help-renderer.js +325 -0
  472. package/dist/cli/help-renderer.js.map +1 -0
  473. package/dist/cli/index.d.ts +14 -0
  474. package/dist/cli/index.d.ts.map +1 -0
  475. package/dist/cli/index.js +1712 -9777
  476. package/dist/cli/index.js.map +4 -4
  477. package/dist/cli/infer-files-via-gitnexus.d.ts +12 -0
  478. package/dist/cli/infer-files-via-gitnexus.d.ts.map +1 -0
  479. package/dist/cli/infer-files-via-gitnexus.js +12 -0
  480. package/dist/cli/infer-files-via-gitnexus.js.map +1 -0
  481. package/dist/cli/lib/did-you-mean.d.ts +30 -0
  482. package/dist/cli/lib/did-you-mean.d.ts.map +1 -0
  483. package/dist/cli/lib/did-you-mean.js +63 -0
  484. package/dist/cli/lib/did-you-mean.js.map +1 -0
  485. package/dist/cli/lib/registry-args.d.ts +36 -0
  486. package/dist/cli/lib/registry-args.d.ts.map +1 -0
  487. package/dist/cli/lib/registry-args.js +37 -0
  488. package/dist/cli/lib/registry-args.js.map +1 -0
  489. package/dist/cli/lib/subcommand-guard.d.ts +45 -0
  490. package/dist/cli/lib/subcommand-guard.d.ts.map +1 -0
  491. package/dist/cli/lib/subcommand-guard.js +55 -0
  492. package/dist/cli/lib/subcommand-guard.js.map +1 -0
  493. package/dist/cli/logger-bootstrap.d.ts +6 -0
  494. package/dist/cli/logger-bootstrap.d.ts.map +1 -0
  495. package/dist/cli/logger-bootstrap.js +10 -0
  496. package/dist/cli/logger-bootstrap.js.map +1 -0
  497. package/dist/cli/middleware/output-format.d.ts +30 -0
  498. package/dist/cli/middleware/output-format.d.ts.map +1 -0
  499. package/dist/cli/middleware/output-format.js +35 -0
  500. package/dist/cli/middleware/output-format.js.map +1 -0
  501. package/dist/cli/paths.d.ts +85 -0
  502. package/dist/cli/paths.d.ts.map +1 -0
  503. package/dist/cli/paths.js +108 -0
  504. package/dist/cli/paths.js.map +1 -0
  505. package/dist/cli/progress.d.ts +89 -0
  506. package/dist/cli/progress.d.ts.map +1 -0
  507. package/dist/cli/progress.js +185 -0
  508. package/dist/cli/progress.js.map +1 -0
  509. package/dist/cli/renderers/colors.d.ts +32 -0
  510. package/dist/cli/renderers/colors.d.ts.map +1 -0
  511. package/dist/cli/renderers/colors.js +141 -0
  512. package/dist/cli/renderers/colors.js.map +1 -0
  513. package/dist/cli/renderers/error.d.ts +13 -0
  514. package/dist/cli/renderers/error.d.ts.map +1 -0
  515. package/dist/cli/renderers/error.js +42 -0
  516. package/dist/cli/renderers/error.js.map +1 -0
  517. package/dist/cli/renderers/index.d.ts +90 -0
  518. package/dist/cli/renderers/index.d.ts.map +1 -0
  519. package/dist/cli/renderers/index.js +268 -0
  520. package/dist/cli/renderers/index.js.map +1 -0
  521. package/dist/cli/renderers/lafs-validator.d.ts +91 -0
  522. package/dist/cli/renderers/lafs-validator.d.ts.map +1 -0
  523. package/dist/cli/renderers/lafs-validator.js +176 -0
  524. package/dist/cli/renderers/lafs-validator.js.map +1 -0
  525. package/dist/cli/renderers/normalizer.d.ts +21 -0
  526. package/dist/cli/renderers/normalizer.d.ts.map +1 -0
  527. package/dist/cli/renderers/normalizer.js +106 -0
  528. package/dist/cli/renderers/normalizer.js.map +1 -0
  529. package/dist/cli/renderers/system.d.ts +110 -0
  530. package/dist/cli/renderers/system.d.ts.map +1 -0
  531. package/dist/cli/renderers/system.js +662 -0
  532. package/dist/cli/renderers/system.js.map +1 -0
  533. package/dist/cli/renderers/tasks.d.ts +28 -0
  534. package/dist/cli/renderers/tasks.d.ts.map +1 -0
  535. package/dist/cli/renderers/tasks.js +306 -0
  536. package/dist/cli/renderers/tasks.js.map +1 -0
  537. package/dist/cli/tree-context.d.ts +53 -0
  538. package/dist/cli/tree-context.d.ts.map +1 -0
  539. package/dist/cli/tree-context.js +43 -0
  540. package/dist/cli/tree-context.js.map +1 -0
  541. package/dist/dispatch/adapters/cli.d.ts +67 -0
  542. package/dist/dispatch/adapters/cli.d.ts.map +1 -0
  543. package/dist/dispatch/adapters/cli.js +331 -0
  544. package/dist/dispatch/adapters/cli.js.map +1 -0
  545. package/dist/dispatch/adapters/typed.d.ts +362 -0
  546. package/dist/dispatch/adapters/typed.d.ts.map +1 -0
  547. package/dist/dispatch/adapters/typed.js +278 -0
  548. package/dist/dispatch/adapters/typed.js.map +1 -0
  549. package/dist/dispatch/context/session-context.d.ts +108 -0
  550. package/dist/dispatch/context/session-context.d.ts.map +1 -0
  551. package/dist/dispatch/context/session-context.js +111 -0
  552. package/dist/dispatch/context/session-context.js.map +1 -0
  553. package/dist/dispatch/dispatcher.d.ts +37 -0
  554. package/dist/dispatch/dispatcher.d.ts.map +1 -0
  555. package/dist/dispatch/dispatcher.js +172 -0
  556. package/dist/dispatch/dispatcher.js.map +1 -0
  557. package/dist/dispatch/domains/_base.d.ts +104 -0
  558. package/dist/dispatch/domains/_base.d.ts.map +1 -0
  559. package/dist/dispatch/domains/_base.js +147 -0
  560. package/dist/dispatch/domains/_base.js.map +1 -0
  561. package/dist/dispatch/domains/_meta.d.ts +23 -0
  562. package/dist/dispatch/domains/_meta.d.ts.map +1 -0
  563. package/dist/dispatch/domains/_meta.js +25 -0
  564. package/dist/dispatch/domains/_meta.js.map +1 -0
  565. package/dist/dispatch/domains/_routing.d.ts +8 -0
  566. package/dist/dispatch/domains/_routing.d.ts.map +1 -0
  567. package/dist/dispatch/domains/_routing.js +20 -0
  568. package/dist/dispatch/domains/_routing.js.map +1 -0
  569. package/dist/dispatch/domains/admin/smoke-provider.d.ts +54 -0
  570. package/dist/dispatch/domains/admin/smoke-provider.d.ts.map +1 -0
  571. package/dist/dispatch/domains/admin/smoke-provider.js +309 -0
  572. package/dist/dispatch/domains/admin/smoke-provider.js.map +1 -0
  573. package/dist/dispatch/domains/admin.d.ts +51 -0
  574. package/dist/dispatch/domains/admin.d.ts.map +1 -0
  575. package/dist/dispatch/domains/admin.js +1163 -0
  576. package/dist/dispatch/domains/admin.js.map +1 -0
  577. package/dist/dispatch/domains/check/canon.d.ts +65 -0
  578. package/dist/dispatch/domains/check/canon.d.ts.map +1 -0
  579. package/dist/dispatch/domains/check/canon.js +193 -0
  580. package/dist/dispatch/domains/check/canon.js.map +1 -0
  581. package/dist/dispatch/domains/check.d.ts +37 -0
  582. package/dist/dispatch/domains/check.d.ts.map +1 -0
  583. package/dist/dispatch/domains/check.js +562 -0
  584. package/dist/dispatch/domains/check.js.map +1 -0
  585. package/dist/dispatch/domains/conduit.d.ts +61 -0
  586. package/dist/dispatch/domains/conduit.d.ts.map +1 -0
  587. package/dist/dispatch/domains/conduit.js +609 -0
  588. package/dist/dispatch/domains/conduit.js.map +1 -0
  589. package/dist/dispatch/domains/diagnostics.d.ts +25 -0
  590. package/dist/dispatch/domains/diagnostics.d.ts.map +1 -0
  591. package/dist/dispatch/domains/diagnostics.js +82 -0
  592. package/dist/dispatch/domains/diagnostics.js.map +1 -0
  593. package/dist/dispatch/domains/docs.d.ts +63 -0
  594. package/dist/dispatch/domains/docs.d.ts.map +1 -0
  595. package/dist/dispatch/domains/docs.js +539 -0
  596. package/dist/dispatch/domains/docs.js.map +1 -0
  597. package/dist/dispatch/domains/index.d.ts +33 -0
  598. package/dist/dispatch/domains/index.d.ts.map +1 -0
  599. package/dist/dispatch/domains/index.js +58 -0
  600. package/dist/dispatch/domains/index.js.map +1 -0
  601. package/dist/dispatch/domains/intelligence.d.ts +26 -0
  602. package/dist/dispatch/domains/intelligence.d.ts.map +1 -0
  603. package/dist/dispatch/domains/intelligence.js +154 -0
  604. package/dist/dispatch/domains/intelligence.js.map +1 -0
  605. package/dist/dispatch/domains/ivtr.d.ts +182 -0
  606. package/dist/dispatch/domains/ivtr.d.ts.map +1 -0
  607. package/dist/dispatch/domains/ivtr.js +430 -0
  608. package/dist/dispatch/domains/ivtr.js.map +1 -0
  609. package/dist/dispatch/domains/memory.d.ts +22 -0
  610. package/dist/dispatch/domains/memory.d.ts.map +1 -0
  611. package/dist/dispatch/domains/memory.js +1281 -0
  612. package/dist/dispatch/domains/memory.js.map +1 -0
  613. package/dist/dispatch/domains/nexus.d.ts +78 -0
  614. package/dist/dispatch/domains/nexus.d.ts.map +1 -0
  615. package/dist/dispatch/domains/nexus.js +938 -0
  616. package/dist/dispatch/domains/nexus.js.map +1 -0
  617. package/dist/dispatch/domains/orchestrate.d.ts +307 -0
  618. package/dist/dispatch/domains/orchestrate.d.ts.map +1 -0
  619. package/dist/dispatch/domains/orchestrate.js +986 -0
  620. package/dist/dispatch/domains/orchestrate.js.map +1 -0
  621. package/dist/dispatch/domains/pipeline.d.ts +276 -0
  622. package/dist/dispatch/domains/pipeline.d.ts.map +1 -0
  623. package/dist/dispatch/domains/pipeline.js +689 -0
  624. package/dist/dispatch/domains/pipeline.js.map +1 -0
  625. package/dist/dispatch/domains/playbook.d.ts +131 -0
  626. package/dist/dispatch/domains/playbook.d.ts.map +1 -0
  627. package/dist/dispatch/domains/playbook.js +633 -0
  628. package/dist/dispatch/domains/playbook.js.map +1 -0
  629. package/dist/dispatch/domains/release.d.ts +97 -0
  630. package/dist/dispatch/domains/release.d.ts.map +1 -0
  631. package/dist/dispatch/domains/release.js +177 -0
  632. package/dist/dispatch/domains/release.js.map +1 -0
  633. package/dist/dispatch/domains/sentient.d.ts +60 -0
  634. package/dist/dispatch/domains/sentient.d.ts.map +1 -0
  635. package/dist/dispatch/domains/sentient.js +270 -0
  636. package/dist/dispatch/domains/sentient.js.map +1 -0
  637. package/dist/dispatch/domains/session.d.ts +49 -0
  638. package/dist/dispatch/domains/session.d.ts.map +1 -0
  639. package/dist/dispatch/domains/session.js +459 -0
  640. package/dist/dispatch/domains/session.js.map +1 -0
  641. package/dist/dispatch/domains/sticky.d.ts +82 -0
  642. package/dist/dispatch/domains/sticky.d.ts.map +1 -0
  643. package/dist/dispatch/domains/sticky.js +287 -0
  644. package/dist/dispatch/domains/sticky.js.map +1 -0
  645. package/dist/dispatch/domains/tasks.d.ts +58 -0
  646. package/dist/dispatch/domains/tasks.d.ts.map +1 -0
  647. package/dist/dispatch/domains/tasks.js +497 -0
  648. package/dist/dispatch/domains/tasks.js.map +1 -0
  649. package/dist/dispatch/domains/tools.d.ts +37 -0
  650. package/dist/dispatch/domains/tools.d.ts.map +1 -0
  651. package/dist/dispatch/domains/tools.js +481 -0
  652. package/dist/dispatch/domains/tools.js.map +1 -0
  653. package/dist/dispatch/engines/_error.d.ts +114 -0
  654. package/dist/dispatch/engines/_error.d.ts.map +1 -0
  655. package/dist/dispatch/engines/_error.js +290 -0
  656. package/dist/dispatch/engines/_error.js.map +1 -0
  657. package/dist/dispatch/engines/admin-engine.d.ts +386 -0
  658. package/dist/dispatch/engines/admin-engine.d.ts.map +1 -0
  659. package/dist/dispatch/engines/admin-engine.js +270 -0
  660. package/dist/dispatch/engines/admin-engine.js.map +1 -0
  661. package/dist/dispatch/engines/code-engine.d.ts +14 -0
  662. package/dist/dispatch/engines/code-engine.d.ts.map +1 -0
  663. package/dist/dispatch/engines/code-engine.js +14 -0
  664. package/dist/dispatch/engines/code-engine.js.map +1 -0
  665. package/dist/dispatch/engines/codebase-map-engine.d.ts +31 -0
  666. package/dist/dispatch/engines/codebase-map-engine.d.ts.map +1 -0
  667. package/dist/dispatch/engines/codebase-map-engine.js +43 -0
  668. package/dist/dispatch/engines/codebase-map-engine.js.map +1 -0
  669. package/dist/dispatch/engines/config-engine.d.ts +14 -0
  670. package/dist/dispatch/engines/config-engine.d.ts.map +1 -0
  671. package/dist/dispatch/engines/config-engine.js +14 -0
  672. package/dist/dispatch/engines/config-engine.js.map +1 -0
  673. package/dist/dispatch/engines/diagnostics-engine.d.ts +13 -0
  674. package/dist/dispatch/engines/diagnostics-engine.d.ts.map +1 -0
  675. package/dist/dispatch/engines/diagnostics-engine.js +12 -0
  676. package/dist/dispatch/engines/diagnostics-engine.js.map +1 -0
  677. package/dist/dispatch/engines/hooks-engine.d.ts +13 -0
  678. package/dist/dispatch/engines/hooks-engine.d.ts.map +1 -0
  679. package/dist/dispatch/engines/hooks-engine.js +12 -0
  680. package/dist/dispatch/engines/hooks-engine.js.map +1 -0
  681. package/dist/dispatch/engines/init-engine.d.ts +14 -0
  682. package/dist/dispatch/engines/init-engine.d.ts.map +1 -0
  683. package/dist/dispatch/engines/init-engine.js +14 -0
  684. package/dist/dispatch/engines/init-engine.js.map +1 -0
  685. package/dist/dispatch/engines/lifecycle-engine.d.ts +13 -0
  686. package/dist/dispatch/engines/lifecycle-engine.d.ts.map +1 -0
  687. package/dist/dispatch/engines/lifecycle-engine.js +12 -0
  688. package/dist/dispatch/engines/lifecycle-engine.js.map +1 -0
  689. package/dist/dispatch/engines/memory-engine.d.ts +10 -0
  690. package/dist/dispatch/engines/memory-engine.d.ts.map +1 -0
  691. package/dist/dispatch/engines/memory-engine.js +10 -0
  692. package/dist/dispatch/engines/memory-engine.js.map +1 -0
  693. package/dist/dispatch/engines/nexus-engine.d.ts +603 -0
  694. package/dist/dispatch/engines/nexus-engine.d.ts.map +1 -0
  695. package/dist/dispatch/engines/nexus-engine.js +1438 -0
  696. package/dist/dispatch/engines/nexus-engine.js.map +1 -0
  697. package/dist/dispatch/engines/orchestrate-engine.d.ts +252 -0
  698. package/dist/dispatch/engines/orchestrate-engine.d.ts.map +1 -0
  699. package/dist/dispatch/engines/orchestrate-engine.js +1526 -0
  700. package/dist/dispatch/engines/orchestrate-engine.js.map +1 -0
  701. package/dist/dispatch/engines/pipeline-engine.d.ts +13 -0
  702. package/dist/dispatch/engines/pipeline-engine.d.ts.map +1 -0
  703. package/dist/dispatch/engines/pipeline-engine.js +12 -0
  704. package/dist/dispatch/engines/pipeline-engine.js.map +1 -0
  705. package/dist/dispatch/engines/release-engine.d.ts +13 -0
  706. package/dist/dispatch/engines/release-engine.d.ts.map +1 -0
  707. package/dist/dispatch/engines/release-engine.js +13 -0
  708. package/dist/dispatch/engines/release-engine.js.map +1 -0
  709. package/dist/dispatch/engines/session-engine.d.ts +15 -0
  710. package/dist/dispatch/engines/session-engine.d.ts.map +1 -0
  711. package/dist/dispatch/engines/session-engine.js +12 -0
  712. package/dist/dispatch/engines/session-engine.js.map +1 -0
  713. package/dist/dispatch/engines/sticky-engine.d.ts +13 -0
  714. package/dist/dispatch/engines/sticky-engine.d.ts.map +1 -0
  715. package/dist/dispatch/engines/sticky-engine.js +12 -0
  716. package/dist/dispatch/engines/sticky-engine.js.map +1 -0
  717. package/dist/dispatch/engines/system-engine.d.ts +543 -0
  718. package/dist/dispatch/engines/system-engine.d.ts.map +1 -0
  719. package/dist/dispatch/engines/system-engine.js +1278 -0
  720. package/dist/dispatch/engines/system-engine.js.map +1 -0
  721. package/dist/dispatch/engines/task-engine.d.ts +1161 -0
  722. package/dist/dispatch/engines/task-engine.d.ts.map +1 -0
  723. package/dist/dispatch/engines/task-engine.js +1599 -0
  724. package/dist/dispatch/engines/task-engine.js.map +1 -0
  725. package/dist/dispatch/engines/template-parser.d.ts +85 -0
  726. package/dist/dispatch/engines/template-parser.d.ts.map +1 -0
  727. package/dist/dispatch/engines/template-parser.js +114 -0
  728. package/dist/dispatch/engines/template-parser.js.map +1 -0
  729. package/dist/dispatch/engines/tools-engine.d.ts +13 -0
  730. package/dist/dispatch/engines/tools-engine.d.ts.map +1 -0
  731. package/dist/dispatch/engines/tools-engine.js +12 -0
  732. package/dist/dispatch/engines/tools-engine.js.map +1 -0
  733. package/dist/dispatch/engines/validate-engine.d.ts +13 -0
  734. package/dist/dispatch/engines/validate-engine.d.ts.map +1 -0
  735. package/dist/dispatch/engines/validate-engine.js +13 -0
  736. package/dist/dispatch/engines/validate-engine.js.map +1 -0
  737. package/dist/dispatch/index.d.ts +20 -0
  738. package/dist/dispatch/index.d.ts.map +1 -0
  739. package/dist/dispatch/index.js +19 -0
  740. package/dist/dispatch/index.js.map +1 -0
  741. package/dist/dispatch/lib/background-jobs.d.ts +162 -0
  742. package/dist/dispatch/lib/background-jobs.d.ts.map +1 -0
  743. package/dist/dispatch/lib/background-jobs.js +360 -0
  744. package/dist/dispatch/lib/background-jobs.js.map +1 -0
  745. package/dist/dispatch/lib/budget.d.ts +36 -0
  746. package/dist/dispatch/lib/budget.d.ts.map +1 -0
  747. package/dist/dispatch/lib/budget.js +109 -0
  748. package/dist/dispatch/lib/budget.js.map +1 -0
  749. package/dist/dispatch/lib/capability-matrix.d.ts +11 -0
  750. package/dist/dispatch/lib/capability-matrix.d.ts.map +1 -0
  751. package/dist/dispatch/lib/capability-matrix.js +10 -0
  752. package/dist/dispatch/lib/capability-matrix.js.map +1 -0
  753. package/dist/dispatch/lib/config-loader.d.ts +42 -0
  754. package/dist/dispatch/lib/config-loader.d.ts.map +1 -0
  755. package/dist/dispatch/lib/config-loader.js +218 -0
  756. package/dist/dispatch/lib/config-loader.js.map +1 -0
  757. package/dist/dispatch/lib/config.d.ts +11 -0
  758. package/dist/dispatch/lib/config.d.ts.map +1 -0
  759. package/dist/dispatch/lib/config.js +10 -0
  760. package/dist/dispatch/lib/config.js.map +1 -0
  761. package/dist/dispatch/lib/defaults.d.ts +115 -0
  762. package/dist/dispatch/lib/defaults.d.ts.map +1 -0
  763. package/dist/dispatch/lib/defaults.js +61 -0
  764. package/dist/dispatch/lib/defaults.js.map +1 -0
  765. package/dist/dispatch/lib/engine.d.ts +17 -0
  766. package/dist/dispatch/lib/engine.d.ts.map +1 -0
  767. package/dist/dispatch/lib/engine.js +36 -0
  768. package/dist/dispatch/lib/engine.js.map +1 -0
  769. package/dist/dispatch/lib/exit-codes.d.ts +35 -0
  770. package/dist/dispatch/lib/exit-codes.d.ts.map +1 -0
  771. package/dist/dispatch/lib/exit-codes.js +60 -0
  772. package/dist/dispatch/lib/exit-codes.js.map +1 -0
  773. package/dist/dispatch/lib/gateway-meta.d.ts +37 -0
  774. package/dist/dispatch/lib/gateway-meta.d.ts.map +1 -0
  775. package/dist/dispatch/lib/gateway-meta.js +50 -0
  776. package/dist/dispatch/lib/gateway-meta.js.map +1 -0
  777. package/dist/dispatch/lib/job-manager-accessor.d.ts +9 -0
  778. package/dist/dispatch/lib/job-manager-accessor.d.ts.map +1 -0
  779. package/dist/dispatch/lib/job-manager-accessor.js +13 -0
  780. package/dist/dispatch/lib/job-manager-accessor.js.map +1 -0
  781. package/dist/dispatch/lib/meta.d.ts +26 -0
  782. package/dist/dispatch/lib/meta.d.ts.map +1 -0
  783. package/dist/dispatch/lib/meta.js +37 -0
  784. package/dist/dispatch/lib/meta.js.map +1 -0
  785. package/dist/dispatch/lib/param-utils.d.ts +11 -0
  786. package/dist/dispatch/lib/param-utils.d.ts.map +1 -0
  787. package/dist/dispatch/lib/param-utils.js +10 -0
  788. package/dist/dispatch/lib/param-utils.js.map +1 -0
  789. package/dist/dispatch/lib/projections.d.ts +56 -0
  790. package/dist/dispatch/lib/projections.d.ts.map +1 -0
  791. package/dist/dispatch/lib/projections.js +65 -0
  792. package/dist/dispatch/lib/projections.js.map +1 -0
  793. package/dist/dispatch/lib/proto-envelope.d.ts +56 -0
  794. package/dist/dispatch/lib/proto-envelope.d.ts.map +1 -0
  795. package/dist/dispatch/lib/proto-envelope.js +17 -0
  796. package/dist/dispatch/lib/proto-envelope.js.map +1 -0
  797. package/dist/dispatch/lib/schema-utils.d.ts +39 -0
  798. package/dist/dispatch/lib/schema-utils.d.ts.map +1 -0
  799. package/dist/dispatch/lib/schema-utils.js +88 -0
  800. package/dist/dispatch/lib/schema-utils.js.map +1 -0
  801. package/dist/dispatch/lib/security.d.ts +11 -0
  802. package/dist/dispatch/lib/security.d.ts.map +1 -0
  803. package/dist/dispatch/lib/security.js +10 -0
  804. package/dist/dispatch/lib/security.js.map +1 -0
  805. package/dist/dispatch/middleware/audit.d.ts +23 -0
  806. package/dist/dispatch/middleware/audit.d.ts.map +1 -0
  807. package/dist/dispatch/middleware/audit.js +169 -0
  808. package/dist/dispatch/middleware/audit.js.map +1 -0
  809. package/dist/dispatch/middleware/field-filter.d.ts +25 -0
  810. package/dist/dispatch/middleware/field-filter.d.ts.map +1 -0
  811. package/dist/dispatch/middleware/field-filter.js +70 -0
  812. package/dist/dispatch/middleware/field-filter.js.map +1 -0
  813. package/dist/dispatch/middleware/pipeline.d.ts +33 -0
  814. package/dist/dispatch/middleware/pipeline.d.ts.map +1 -0
  815. package/dist/dispatch/middleware/pipeline.js +60 -0
  816. package/dist/dispatch/middleware/pipeline.js.map +1 -0
  817. package/dist/dispatch/middleware/projection.d.ts +35 -0
  818. package/dist/dispatch/middleware/projection.d.ts.map +1 -0
  819. package/dist/dispatch/middleware/projection.js +146 -0
  820. package/dist/dispatch/middleware/projection.js.map +1 -0
  821. package/dist/dispatch/middleware/protocol-enforcement.d.ts +30 -0
  822. package/dist/dispatch/middleware/protocol-enforcement.d.ts.map +1 -0
  823. package/dist/dispatch/middleware/protocol-enforcement.js +56 -0
  824. package/dist/dispatch/middleware/protocol-enforcement.js.map +1 -0
  825. package/dist/dispatch/middleware/rate-limiter.d.ts +72 -0
  826. package/dist/dispatch/middleware/rate-limiter.d.ts.map +1 -0
  827. package/dist/dispatch/middleware/rate-limiter.js +127 -0
  828. package/dist/dispatch/middleware/rate-limiter.js.map +1 -0
  829. package/dist/dispatch/middleware/sanitizer.d.ts +24 -0
  830. package/dist/dispatch/middleware/sanitizer.d.ts.map +1 -0
  831. package/dist/dispatch/middleware/sanitizer.js +56 -0
  832. package/dist/dispatch/middleware/sanitizer.js.map +1 -0
  833. package/dist/dispatch/middleware/session-resolver.d.ts +26 -0
  834. package/dist/dispatch/middleware/session-resolver.d.ts.map +1 -0
  835. package/dist/dispatch/middleware/session-resolver.js +65 -0
  836. package/dist/dispatch/middleware/session-resolver.js.map +1 -0
  837. package/dist/dispatch/middleware/telemetry.d.ts +21 -0
  838. package/dist/dispatch/middleware/telemetry.d.ts.map +1 -0
  839. package/dist/dispatch/middleware/telemetry.js +50 -0
  840. package/dist/dispatch/middleware/telemetry.js.map +1 -0
  841. package/dist/dispatch/middleware/verification-gates.d.ts +22 -0
  842. package/dist/dispatch/middleware/verification-gates.d.ts.map +1 -0
  843. package/dist/dispatch/middleware/verification-gates.js +59 -0
  844. package/dist/dispatch/middleware/verification-gates.js.map +1 -0
  845. package/dist/dispatch/registry.d.ts +91 -0
  846. package/dist/dispatch/registry.d.ts.map +1 -0
  847. package/dist/dispatch/registry.js +6430 -0
  848. package/dist/dispatch/registry.js.map +1 -0
  849. package/dist/dispatch/types.d.ts +150 -0
  850. package/dist/dispatch/types.d.ts.map +1 -0
  851. package/dist/dispatch/types.js +38 -0
  852. package/dist/dispatch/types.js.map +1 -0
  853. package/dist/migrations/2026-04-25-t991-parent-link-repair.d.ts +88 -0
  854. package/dist/migrations/2026-04-25-t991-parent-link-repair.d.ts.map +1 -0
  855. package/dist/migrations/2026-04-25-t991-parent-link-repair.js +76 -0
  856. package/dist/migrations/2026-04-25-t991-parent-link-repair.js.map +1 -0
  857. package/package.json +9 -9
@@ -0,0 +1,3377 @@
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 { generateGexf, getSymbolImpact } from '@cleocode/core/nexus';
16
+ import { defineCommand, showUsage } from 'citty';
17
+ import { dispatchFromCli, dispatchRaw } from '../../dispatch/adapters/cli.js';
18
+ // ── Subcommand definitions ───────────────────────────────────────────────────
19
+ /** cleo nexus init — initialize NEXUS directory structure and registry */
20
+ const initCommand = defineCommand({
21
+ meta: { name: 'init', description: 'Initialize NEXUS directory structure and registry' },
22
+ async run() {
23
+ await dispatchFromCli('mutate', 'nexus', 'init', {}, { command: 'nexus' });
24
+ },
25
+ });
26
+ /** cleo nexus register — register a project in the global registry */
27
+ const registerCommand = defineCommand({
28
+ meta: { name: 'register', description: 'Register a project in the global registry' },
29
+ args: {
30
+ path: {
31
+ type: 'positional',
32
+ description: 'Path to the project directory',
33
+ required: true,
34
+ },
35
+ name: {
36
+ type: 'string',
37
+ description: 'Custom project name (default: directory name)',
38
+ },
39
+ permissions: {
40
+ type: 'string',
41
+ description: 'Permissions: read|write|execute',
42
+ default: 'read',
43
+ },
44
+ },
45
+ async run({ args }) {
46
+ await dispatchFromCli('mutate', 'nexus', 'register', {
47
+ path: args.path,
48
+ name: args.name,
49
+ permission: args.permissions,
50
+ }, { command: 'nexus' });
51
+ },
52
+ });
53
+ /** cleo nexus unregister — remove a project from the registry */
54
+ const unregisterCommand = defineCommand({
55
+ meta: { name: 'unregister', description: 'Remove a project from the registry' },
56
+ args: {
57
+ nameOrHash: {
58
+ type: 'positional',
59
+ description: 'Project name or hash to unregister',
60
+ required: true,
61
+ },
62
+ },
63
+ async run({ args }) {
64
+ await dispatchFromCli('mutate', 'nexus', 'unregister', { name: args.nameOrHash }, { command: 'nexus' });
65
+ },
66
+ });
67
+ /** cleo nexus list — list all registered projects */
68
+ const listCommand = defineCommand({
69
+ meta: { name: 'list', description: 'List all registered projects' },
70
+ async run() {
71
+ await dispatchFromCli('query', 'nexus', 'list', {}, { command: 'nexus' });
72
+ },
73
+ });
74
+ /** cleo nexus status — show code intelligence index freshness */
75
+ const statusCommand = defineCommand({
76
+ meta: {
77
+ name: 'status',
78
+ 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.',
79
+ },
80
+ args: {
81
+ path: {
82
+ type: 'positional',
83
+ description: 'Path to the project directory (default: cwd)',
84
+ required: false,
85
+ },
86
+ 'project-id': {
87
+ type: 'string',
88
+ description: 'Override the project ID (default: auto-detected from path)',
89
+ },
90
+ json: {
91
+ type: 'boolean',
92
+ description: 'Output as JSON (LAFS envelope format)',
93
+ },
94
+ },
95
+ async run({ args }) {
96
+ const jsonOutput = !!args.json;
97
+ const projectIdOverride = args['project-id'];
98
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
99
+ const startTime = Date.now();
100
+ try {
101
+ // SSoT-EXEMPT:status-index-stats — getIndexStats requires direct pipeline access
102
+ // with db handle + table refs; no dispatch op exposes this level of detail.
103
+ // Dispatch 'nexus.status' is used as fallback on error (see catch block).
104
+ const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
105
+ import('@cleocode/core/store/nexus-sqlite'),
106
+ import('@cleocode/nexus/pipeline'),
107
+ ]);
108
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
109
+ const db = await getNexusDb();
110
+ const tables = {
111
+ nexusNodes: nexusSchema.nexusNodes,
112
+ nexusRelations: nexusSchema.nexusRelations,
113
+ };
114
+ const stats = await getIndexStats(projectId, repoPath, db, tables);
115
+ const durationMs = Date.now() - startTime;
116
+ if (jsonOutput) {
117
+ const envelope = {
118
+ success: true,
119
+ data: { projectId, repoPath, ...stats },
120
+ meta: {
121
+ operation: 'nexus.status',
122
+ duration_ms: durationMs,
123
+ timestamp: new Date().toISOString(),
124
+ },
125
+ };
126
+ process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
127
+ }
128
+ else if (!stats.indexed) {
129
+ process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
130
+ ` Status: NOT INDEXED\n` +
131
+ ` Run 'cleo nexus analyze' to build the index.\n`);
132
+ }
133
+ else {
134
+ const staleLabel = stats.staleFileCount < 0
135
+ ? 'unknown'
136
+ : stats.staleFileCount === 0
137
+ ? 'up to date'
138
+ : `${stats.staleFileCount} stale`;
139
+ process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
140
+ ` Project ID: ${projectId}\n` +
141
+ ` Nodes: ${stats.nodeCount}\n` +
142
+ ` Relations: ${stats.relationCount}\n` +
143
+ ` Files: ${stats.fileCount}\n` +
144
+ ` Last indexed: ${stats.lastIndexedAt ?? 'never'}\n` +
145
+ ` Staleness: ${staleLabel}\n`);
146
+ }
147
+ }
148
+ catch (err) {
149
+ // Fall back to NEXUS registry status on error
150
+ const msg = err instanceof Error ? err.message : String(err);
151
+ if (jsonOutput) {
152
+ process.stdout.write(JSON.stringify({
153
+ success: false,
154
+ error: { code: 'E_STATUS_FAILED', message: msg },
155
+ meta: {
156
+ operation: 'nexus.status',
157
+ duration_ms: Date.now() - startTime,
158
+ timestamp: new Date().toISOString(),
159
+ },
160
+ }, null, 2) + '\n');
161
+ }
162
+ else {
163
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
164
+ await dispatchFromCli('query', 'nexus', 'status', {}, { command: 'nexus' });
165
+ }
166
+ process.exitCode = 1;
167
+ }
168
+ },
169
+ });
170
+ /** cleo nexus show — show details for a registered project by name */
171
+ const showCommand = defineCommand({
172
+ meta: { name: 'show', description: 'Show details for a registered project by name' },
173
+ args: {
174
+ name: {
175
+ type: 'positional',
176
+ description: 'Project name',
177
+ required: true,
178
+ },
179
+ },
180
+ async run({ args }) {
181
+ await dispatchFromCli('query', 'nexus', 'show', { name: args.name }, { command: 'nexus' });
182
+ },
183
+ });
184
+ /** cleo nexus resolve — resolve a task reference across projects */
185
+ const resolveCommand = defineCommand({
186
+ meta: {
187
+ name: 'resolve',
188
+ description: 'Resolve a task reference across projects (project:T### or T###)',
189
+ },
190
+ args: {
191
+ taskRef: {
192
+ type: 'positional',
193
+ description: 'Task reference to resolve',
194
+ required: true,
195
+ },
196
+ },
197
+ async run({ args }) {
198
+ await dispatchFromCli('query', 'nexus', 'resolve', { query: args.taskRef }, { command: 'nexus' });
199
+ },
200
+ });
201
+ /** cleo nexus discover — find related tasks across projects */
202
+ const discoverCommand = defineCommand({
203
+ meta: { name: 'discover', description: 'Find related tasks across projects' },
204
+ args: {
205
+ taskQuery: {
206
+ type: 'positional',
207
+ description: 'Task query string',
208
+ required: true,
209
+ },
210
+ method: {
211
+ type: 'string',
212
+ description: 'Discovery method: labels|description|files|auto',
213
+ default: 'auto',
214
+ },
215
+ limit: {
216
+ type: 'string',
217
+ description: 'Max results',
218
+ default: '10',
219
+ },
220
+ },
221
+ async run({ args }) {
222
+ await dispatchFromCli('query', 'nexus', 'discover', {
223
+ query: args.taskQuery,
224
+ method: args.method,
225
+ limit: parseInt(args.limit, 10),
226
+ }, { command: 'nexus' });
227
+ },
228
+ });
229
+ /**
230
+ * cleo nexus augment — Symbol context augmentation for PreToolUse hooks.
231
+ *
232
+ * BM25-only search against nexus_nodes for pattern, returns top N symbols
233
+ * with callers/callees/community metadata as plain text suitable for hook injection.
234
+ *
235
+ * @task T1061
236
+ * @epic T1042
237
+ */
238
+ const augmentCommand = defineCommand({
239
+ meta: {
240
+ name: 'augment',
241
+ description: 'Augment symbol pattern with code context (for PreToolUse hooks)',
242
+ },
243
+ args: {
244
+ pattern: {
245
+ type: 'positional',
246
+ description: 'Symbol name or file pattern to search',
247
+ required: true,
248
+ },
249
+ limit: {
250
+ type: 'string',
251
+ description: 'Max results to return (default: 5)',
252
+ default: '5',
253
+ },
254
+ },
255
+ async run({ args }) {
256
+ const pattern = args.pattern;
257
+ const limit = parseInt(args.limit, 10) || 5;
258
+ await dispatchFromCli('query', 'nexus', 'augment', {
259
+ pattern,
260
+ limit,
261
+ }, { command: 'nexus' });
262
+ },
263
+ });
264
+ /**
265
+ * cleo nexus setup — Install PreToolUse hook augmenter
266
+ *
267
+ * Writes ~/.cleo/hooks/nexus-augment.sh and registers it in CAAMP config.
268
+ *
269
+ * @task T1061
270
+ * @epic T1042
271
+ */
272
+ const setupCommand = defineCommand({
273
+ meta: {
274
+ name: 'setup',
275
+ description: 'Install Nexus PreToolUse hook augmenter',
276
+ },
277
+ args: {},
278
+ async run() {
279
+ try {
280
+ // SSoT-EXEMPT:cli-install — installs filesystem hook, not a domain operation.
281
+ // Hook installation writes shell scripts to disk and cannot be a LAFS dispatch op.
282
+ const { homedir } = await import('node:os');
283
+ const { installNexusAugmentHook } = await import('@cleocode/core/internal');
284
+ const homeDir = homedir();
285
+ installNexusAugmentHook(homeDir);
286
+ process.stdout.write(`[nexus] Installed PreToolUse hook at ${homeDir}/.cleo/hooks/nexus-augment.sh\n`);
287
+ process.stdout.write(`[nexus] Hook will inject symbol context into Grep/Glob/Read tool calls\n`);
288
+ }
289
+ catch (err) {
290
+ const msg = err instanceof Error ? err.message : String(err);
291
+ process.stderr.write(`[nexus setup] Error: ${msg}\n`);
292
+ process.exitCode = 1;
293
+ }
294
+ },
295
+ });
296
+ /** cleo nexus search — search tasks across projects by pattern */
297
+ const searchCommand = defineCommand({
298
+ meta: { name: 'search', description: 'Search tasks across projects by pattern' },
299
+ args: {
300
+ pattern: {
301
+ type: 'positional',
302
+ description: 'Search pattern',
303
+ required: true,
304
+ },
305
+ project: {
306
+ type: 'string',
307
+ description: 'Limit search to specific project',
308
+ },
309
+ limit: {
310
+ type: 'string',
311
+ description: 'Max results',
312
+ default: '20',
313
+ },
314
+ },
315
+ async run({ args }) {
316
+ await dispatchFromCli('query', 'nexus', 'search', {
317
+ pattern: args.pattern,
318
+ project: args.project,
319
+ limit: parseInt(args.limit, 10),
320
+ }, { command: 'nexus' });
321
+ },
322
+ });
323
+ /** cleo nexus deps — show cross-project dependencies */
324
+ const depsCommand = defineCommand({
325
+ meta: { name: 'deps', description: 'Show cross-project dependencies' },
326
+ args: {
327
+ taskQuery: {
328
+ type: 'positional',
329
+ description: 'Task query string',
330
+ required: true,
331
+ },
332
+ reverse: {
333
+ type: 'boolean',
334
+ description: 'Show reverse dependencies (what depends on this)',
335
+ },
336
+ },
337
+ async run({ args }) {
338
+ await dispatchFromCli('query', 'nexus', 'deps', {
339
+ query: args.taskQuery,
340
+ direction: args.reverse ? 'reverse' : 'forward',
341
+ }, { command: 'nexus' });
342
+ },
343
+ });
344
+ /** cleo nexus critical-path — show global critical path across all registered projects */
345
+ const criticalPathCommand = defineCommand({
346
+ meta: {
347
+ name: 'critical-path',
348
+ description: 'Show global critical path across all registered projects',
349
+ },
350
+ async run() {
351
+ await dispatchFromCli('query', 'nexus', 'path.show', {}, { command: 'nexus' });
352
+ },
353
+ });
354
+ /** cleo nexus blocking — show blocking impact analysis for a task */
355
+ const blockingCommand = defineCommand({
356
+ meta: { name: 'blocking', description: 'Show blocking impact analysis for a task' },
357
+ args: {
358
+ taskQuery: {
359
+ type: 'positional',
360
+ description: 'Task query string',
361
+ required: true,
362
+ },
363
+ },
364
+ async run({ args }) {
365
+ await dispatchFromCli('query', 'nexus', 'blockers.show', { query: args.taskQuery }, { command: 'nexus' });
366
+ },
367
+ });
368
+ /** cleo nexus orphans — detect broken cross-project dependency references */
369
+ const orphansCommand = defineCommand({
370
+ meta: { name: 'orphans', description: 'Detect broken cross-project dependency references' },
371
+ async run() {
372
+ await dispatchFromCli('query', 'nexus', 'orphans.list', {}, { command: 'nexus' });
373
+ },
374
+ });
375
+ /** cleo nexus sync — sync project metadata (task count, labels) */
376
+ const syncCommand = defineCommand({
377
+ meta: { name: 'sync', description: 'Sync project metadata (task count, labels)' },
378
+ args: {
379
+ project: {
380
+ type: 'positional',
381
+ description: 'Project name to sync (default: all)',
382
+ required: false,
383
+ },
384
+ },
385
+ async run({ args }) {
386
+ if (args.project) {
387
+ await dispatchFromCli('mutate', 'nexus', 'sync', { name: args.project }, { command: 'nexus' });
388
+ }
389
+ else {
390
+ await dispatchFromCli('mutate', 'nexus', 'sync', {}, { command: 'nexus' });
391
+ }
392
+ },
393
+ });
394
+ /** cleo nexus reconcile — reconcile current project with NEXUS registry */
395
+ const reconcileCommand = defineCommand({
396
+ meta: {
397
+ name: 'reconcile',
398
+ description: 'Reconcile current project with NEXUS registry (auto-register if new, update path if moved)',
399
+ },
400
+ args: {
401
+ path: {
402
+ type: 'string',
403
+ description: 'Project path (default: current directory)',
404
+ },
405
+ },
406
+ async run({ args }) {
407
+ await dispatchFromCli('mutate', 'nexus', 'reconcile', { projectRoot: args.path }, { command: 'nexus' });
408
+ },
409
+ });
410
+ /** cleo nexus graph — show full dependency graph across all registered projects */
411
+ const graphCommand = defineCommand({
412
+ meta: { name: 'graph', description: 'Show full dependency graph across all registered projects' },
413
+ async run() {
414
+ await dispatchFromCli('query', 'nexus', 'graph', {}, { command: 'nexus' });
415
+ },
416
+ });
417
+ /** cleo nexus share-status — show multi-contributor sharing status */
418
+ const shareStatusCommand = defineCommand({
419
+ meta: {
420
+ name: 'share-status',
421
+ description: 'Show multi-contributor sharing status for the current project',
422
+ },
423
+ async run() {
424
+ await dispatchFromCli('query', 'nexus', 'share.status', {}, { command: 'nexus' });
425
+ },
426
+ });
427
+ /** cleo nexus transfer-preview — preview a task transfer between projects */
428
+ const transferPreviewCommand = defineCommand({
429
+ meta: {
430
+ name: 'transfer-preview',
431
+ description: 'Preview a task transfer between projects (dry-run, no changes made)',
432
+ },
433
+ args: {
434
+ taskIds: {
435
+ type: 'positional',
436
+ description: 'Task IDs to preview transfer for',
437
+ required: true,
438
+ },
439
+ from: {
440
+ type: 'string',
441
+ description: 'Source project name',
442
+ required: true,
443
+ },
444
+ to: {
445
+ type: 'string',
446
+ description: 'Target project name',
447
+ required: true,
448
+ },
449
+ mode: {
450
+ type: 'string',
451
+ description: 'Transfer mode: copy|move',
452
+ default: 'copy',
453
+ },
454
+ scope: {
455
+ type: 'string',
456
+ description: 'Transfer scope: single|subtree',
457
+ default: 'subtree',
458
+ },
459
+ },
460
+ async run({ args }) {
461
+ await dispatchFromCli('query', 'nexus', 'transfer.preview', {
462
+ taskIds: args.taskIds.split(',').map((s) => s.trim()),
463
+ sourceProject: args.from,
464
+ targetProject: args.to,
465
+ mode: args.mode,
466
+ scope: args.scope,
467
+ }, { command: 'nexus' });
468
+ },
469
+ });
470
+ /** cleo nexus transfer — transfer tasks from one project to another */
471
+ const transferCommand = defineCommand({
472
+ meta: { name: 'transfer', description: 'Transfer tasks from one project to another' },
473
+ args: {
474
+ taskIds: {
475
+ type: 'positional',
476
+ description: 'Task IDs to transfer',
477
+ required: true,
478
+ },
479
+ from: {
480
+ type: 'string',
481
+ description: 'Source project name',
482
+ required: true,
483
+ },
484
+ to: {
485
+ type: 'string',
486
+ description: 'Target project name',
487
+ required: true,
488
+ },
489
+ mode: {
490
+ type: 'string',
491
+ description: 'Transfer mode: copy|move',
492
+ default: 'copy',
493
+ },
494
+ scope: {
495
+ type: 'string',
496
+ description: 'Transfer scope: single|subtree',
497
+ default: 'subtree',
498
+ },
499
+ 'on-conflict': {
500
+ type: 'string',
501
+ description: 'Conflict strategy: rename|skip|duplicate|fail',
502
+ default: 'rename',
503
+ },
504
+ 'transfer-brain': {
505
+ type: 'boolean',
506
+ description: 'Also transfer associated brain memory entries',
507
+ },
508
+ },
509
+ async run({ args }) {
510
+ await dispatchFromCli('mutate', 'nexus', 'transfer', {
511
+ taskIds: args.taskIds.split(',').map((s) => s.trim()),
512
+ sourceProject: args.from,
513
+ targetProject: args.to,
514
+ mode: args.mode,
515
+ scope: args.scope,
516
+ onConflict: args['on-conflict'],
517
+ transferBrain: args['transfer-brain'],
518
+ }, { command: 'nexus' });
519
+ },
520
+ });
521
+ /** cleo nexus permission set — set permission level for a registered project */
522
+ const permissionSetCommand = defineCommand({
523
+ meta: {
524
+ name: 'set',
525
+ description: 'Set permission level for a registered project (read|write|execute)',
526
+ },
527
+ args: {
528
+ name: {
529
+ type: 'positional',
530
+ description: 'Project name',
531
+ required: true,
532
+ },
533
+ level: {
534
+ type: 'positional',
535
+ description: 'Permission level: read|write|execute',
536
+ required: true,
537
+ },
538
+ },
539
+ async run({ args }) {
540
+ await dispatchFromCli('mutate', 'nexus', 'permission.set', { name: args.name, level: args.level }, { command: 'nexus' });
541
+ },
542
+ });
543
+ /** cleo nexus permission — manage permissions for registered projects */
544
+ const permissionCommand = defineCommand({
545
+ meta: { name: 'permission', description: 'Manage permissions for registered projects' },
546
+ subCommands: {
547
+ set: permissionSetCommand,
548
+ },
549
+ });
550
+ /** cleo nexus share export — export a snapshot of current project state */
551
+ const shareExportCommand = defineCommand({
552
+ meta: { name: 'export', description: 'Export a snapshot of current project state for sharing' },
553
+ args: {
554
+ output: {
555
+ type: 'string',
556
+ description: 'Output file path (default: auto-generated in current directory)',
557
+ },
558
+ },
559
+ async run({ args }) {
560
+ await dispatchFromCli('mutate', 'nexus', 'share.snapshot.export', { outputPath: args.output }, { command: 'nexus' });
561
+ },
562
+ });
563
+ /** cleo nexus share import — import a shared project snapshot */
564
+ const shareImportCommand = defineCommand({
565
+ meta: { name: 'import', description: 'Import a shared project snapshot' },
566
+ args: {
567
+ file: {
568
+ type: 'positional',
569
+ description: 'Path to snapshot file',
570
+ required: true,
571
+ },
572
+ },
573
+ async run({ args }) {
574
+ await dispatchFromCli('mutate', 'nexus', 'share.snapshot.import', { inputPath: args.file }, { command: 'nexus' });
575
+ },
576
+ });
577
+ /** cleo nexus share — multi-contributor sharing operations */
578
+ const shareCommand = defineCommand({
579
+ meta: { name: 'share', description: 'Multi-contributor sharing operations' },
580
+ subCommands: {
581
+ export: shareExportCommand,
582
+ import: shareImportCommand,
583
+ },
584
+ });
585
+ /** cleo nexus clusters — list all detected communities from the last analysis */
586
+ const clustersCommand = defineCommand({
587
+ meta: {
588
+ name: 'clusters',
589
+ description: 'List all detected communities (Louvain clusters) from the last analysis',
590
+ },
591
+ args: {
592
+ path: {
593
+ type: 'positional',
594
+ description: 'Path to project directory (default: cwd)',
595
+ required: false,
596
+ },
597
+ json: {
598
+ type: 'boolean',
599
+ description: 'Output result as JSON (LAFS envelope format)',
600
+ },
601
+ 'project-id': {
602
+ type: 'string',
603
+ description: 'Override the project ID (default: auto-detected from path)',
604
+ },
605
+ },
606
+ async run({ args }) {
607
+ const startTime = Date.now();
608
+ const jsonOutput = !!args.json;
609
+ const projectIdOverride = args['project-id'];
610
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
611
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
612
+ const response = await dispatchRaw('query', 'nexus', 'clusters', { projectId, repoPath });
613
+ const durationMs = Date.now() - startTime;
614
+ if (!response.success) {
615
+ const msg = response.error?.message ?? 'Unknown error';
616
+ if (jsonOutput) {
617
+ process.stdout.write(JSON.stringify({
618
+ success: false,
619
+ error: { code: response.error?.code ?? 'E_CLUSTERS_FAILED', message: msg },
620
+ meta: {
621
+ operation: 'nexus.clusters',
622
+ duration_ms: durationMs,
623
+ timestamp: new Date().toISOString(),
624
+ },
625
+ }, null, 2) + '\n');
626
+ }
627
+ else {
628
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
629
+ }
630
+ process.exitCode = 1;
631
+ return;
632
+ }
633
+ const result = response.data;
634
+ if (jsonOutput) {
635
+ process.stdout.write(JSON.stringify({
636
+ success: true,
637
+ data: result,
638
+ meta: {
639
+ operation: 'nexus.clusters',
640
+ duration_ms: durationMs,
641
+ timestamp: new Date().toISOString(),
642
+ },
643
+ }, null, 2) + '\n');
644
+ }
645
+ else if (result.communities.length === 0) {
646
+ process.stdout.write(`[nexus] No communities found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
647
+ }
648
+ else {
649
+ process.stdout.write(`[nexus] Communities for project ${projectId} (${result.communities.length} total):\n`);
650
+ for (const c of result.communities) {
651
+ const cohesion = typeof c.cohesion === 'number' ? c.cohesion.toFixed(3) : '0.000';
652
+ process.stdout.write(` ${String(c.id).padEnd(16)} label=${String(c.label ?? '').padEnd(24)} symbols=${String(c.symbolCount).padStart(5)} cohesion=${cohesion}\n`);
653
+ }
654
+ }
655
+ },
656
+ });
657
+ /** cleo nexus flows — list all detected execution flows from the last analysis */
658
+ const flowsCommand = defineCommand({
659
+ meta: {
660
+ name: 'flows',
661
+ description: 'List all detected execution flows (processes) from the last analysis',
662
+ },
663
+ args: {
664
+ path: {
665
+ type: 'positional',
666
+ description: 'Path to project directory (default: cwd)',
667
+ required: false,
668
+ },
669
+ json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
670
+ 'project-id': {
671
+ type: 'string',
672
+ description: 'Override the project ID (default: auto-detected from path)',
673
+ },
674
+ },
675
+ async run({ args }) {
676
+ const startTime = Date.now();
677
+ const jsonOutput = !!args.json;
678
+ const projectIdOverride = args['project-id'];
679
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
680
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
681
+ const response = await dispatchRaw('query', 'nexus', 'flows', { projectId, repoPath });
682
+ const durationMs = Date.now() - startTime;
683
+ if (!response.success) {
684
+ const msg = response.error?.message ?? 'Unknown error';
685
+ if (jsonOutput) {
686
+ process.stdout.write(JSON.stringify({
687
+ success: false,
688
+ error: { code: response.error?.code ?? 'E_FLOWS_FAILED', message: msg },
689
+ meta: {
690
+ operation: 'nexus.flows',
691
+ duration_ms: durationMs,
692
+ timestamp: new Date().toISOString(),
693
+ },
694
+ }, null, 2) + '\n');
695
+ }
696
+ else {
697
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
698
+ }
699
+ process.exitCode = 1;
700
+ return;
701
+ }
702
+ const result = response.data;
703
+ if (jsonOutput) {
704
+ process.stdout.write(JSON.stringify({
705
+ success: true,
706
+ data: result,
707
+ meta: {
708
+ operation: 'nexus.flows',
709
+ duration_ms: durationMs,
710
+ timestamp: new Date().toISOString(),
711
+ },
712
+ }, null, 2) + '\n');
713
+ }
714
+ else if (result.flows.length === 0) {
715
+ process.stdout.write(`[nexus] No execution flows found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
716
+ }
717
+ else {
718
+ process.stdout.write(`[nexus] Execution flows for project ${projectId} (${result.flows.length} total):\n`);
719
+ for (const p of result.flows) {
720
+ const processType = p.processType.replace('_community', '');
721
+ process.stdout.write(` ${String(p.id).padEnd(30)} steps=${String(p.stepCount).padStart(3)} type=${processType.padEnd(12)} ${String(p.label ?? '')}\n`);
722
+ }
723
+ }
724
+ },
725
+ });
726
+ /** cleo nexus context — show callers, callees, community membership, and process participation */
727
+ const contextCommand = defineCommand({
728
+ meta: {
729
+ name: 'context',
730
+ description: 'Show callers, callees, community membership, and process participation for a code symbol',
731
+ },
732
+ args: {
733
+ symbol: { type: 'positional', description: 'Symbol name to look up', required: true },
734
+ json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
735
+ 'project-id': {
736
+ type: 'string',
737
+ description: 'Override the project ID (default: auto-detected from cwd)',
738
+ },
739
+ limit: { type: 'string', description: 'Max callers/callees to show per side', default: '20' },
740
+ content: { type: 'boolean', description: 'Append source code content for the symbol' },
741
+ },
742
+ async run({ args }) {
743
+ const startTime = Date.now();
744
+ const jsonOutput = !!args.json;
745
+ const projectIdOverride = args['project-id'];
746
+ const repoPath = process.cwd();
747
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
748
+ const limit = parseInt(args.limit, 10);
749
+ const symbolName = args.symbol;
750
+ const showContent = !!args.content;
751
+ const response = await dispatchRaw('query', 'nexus', 'context', {
752
+ symbol: symbolName,
753
+ projectId,
754
+ limit,
755
+ content: showContent,
756
+ });
757
+ const durationMs = Date.now() - startTime;
758
+ if (!response.success) {
759
+ const msg = response.error?.message ?? 'Unknown error';
760
+ if (jsonOutput) {
761
+ process.stdout.write(JSON.stringify({
762
+ success: false,
763
+ error: { code: response.error?.code ?? 'E_CONTEXT_FAILED', message: msg },
764
+ meta: {
765
+ operation: 'nexus.context',
766
+ duration_ms: durationMs,
767
+ timestamp: new Date().toISOString(),
768
+ },
769
+ }, null, 2) + '\n');
770
+ }
771
+ else {
772
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
773
+ }
774
+ process.exitCode = 1;
775
+ return;
776
+ }
777
+ const result = response.data;
778
+ if (result.matchCount === 0) {
779
+ if (jsonOutput) {
780
+ process.stdout.write(JSON.stringify({
781
+ success: false,
782
+ error: {
783
+ code: 'E_NOT_FOUND',
784
+ message: `No symbol found matching '${symbolName}' in project ${projectId}`,
785
+ },
786
+ meta: {
787
+ operation: 'nexus.context',
788
+ duration_ms: durationMs,
789
+ timestamp: new Date().toISOString(),
790
+ },
791
+ }, null, 2) + '\n');
792
+ }
793
+ else {
794
+ process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n Run 'cleo nexus analyze' first, or check the symbol name.\n`);
795
+ }
796
+ process.exitCode = 4;
797
+ return;
798
+ }
799
+ if (jsonOutput) {
800
+ process.stdout.write(JSON.stringify({
801
+ success: true,
802
+ data: result,
803
+ meta: {
804
+ operation: 'nexus.context',
805
+ duration_ms: durationMs,
806
+ timestamp: new Date().toISOString(),
807
+ },
808
+ }, null, 2) + '\n');
809
+ }
810
+ else {
811
+ process.stdout.write(`[nexus] Context for symbol '${symbolName}' (${result.matchCount} match${result.matchCount !== 1 ? 'es' : ''}):\n`);
812
+ for (const r of result.results) {
813
+ process.stdout.write(`\n Symbol: ${String(r.name)} (${String(r.kind)})\n File: ${r.filePath ? String(r.filePath) : 'n/a'}${r.startLine ? `:${String(r.startLine)}` : ''}\n` +
814
+ (r.docSummary ? ` Doc: ${String(r.docSummary)}\n` : '') +
815
+ (r.community ? ` Community: ${String(r.community.label ?? r.community.id)}\n` : '') +
816
+ ` Callers (${r.callers.length}): ${r.callers.length === 0 ? 'none' : r.callers.map((c) => `${c.name}[${c.kind}]`).join(', ')}\n` +
817
+ ` Callees (${r.callees.length}): ${r.callees.length === 0 ? 'none' : r.callees.map((c) => `${c.name}[${c.kind}]`).join(', ')}\n` +
818
+ (r.processes.length > 0
819
+ ? ` Processes: ${r.processes.map((p) => `${String(p.label)}(${p.role})`).join(', ')}\n`
820
+ : ''));
821
+ if (r.source?.source) {
822
+ const ext = String(r.filePath).split('.').pop() ?? 'txt';
823
+ process.stdout.write(`\n Source (lines ${r.source.startLine}-${r.source.endLine}):\n \`\`\`${ext}\n${r.source.source
824
+ .split('\n')
825
+ .map((line) => ` ${line}`)
826
+ .join('\n')}\n \`\`\`\n`);
827
+ }
828
+ else if (r.source?.errors?.length) {
829
+ process.stdout.write(`\n [warning] Could not retrieve source: ${r.source.errors[0]}\n`);
830
+ }
831
+ }
832
+ if (result.matchCount > 5) {
833
+ process.stdout.write(`\n (Showing 5 of ${result.matchCount} matches — use --json for full list)\n`);
834
+ }
835
+ }
836
+ },
837
+ });
838
+ /** cleo nexus impact — show blast radius for a code symbol */
839
+ const impactCommand = defineCommand({
840
+ meta: {
841
+ name: 'impact',
842
+ description: 'Show blast radius for a code symbol — direct callers (d=1), indirect callers (d=2), transitive (d=3)',
843
+ },
844
+ args: {
845
+ symbol: { type: 'positional', description: 'Symbol name to analyze', required: true },
846
+ json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
847
+ 'project-id': {
848
+ type: 'string',
849
+ description: 'Override the project ID (default: auto-detected from cwd)',
850
+ },
851
+ depth: { type: 'string', description: 'Maximum traversal depth (default: 3)', default: '3' },
852
+ why: { type: 'boolean', description: 'Append reasons[] path-strings for each affected symbol' },
853
+ },
854
+ async run({ args }) {
855
+ const startTime = Date.now();
856
+ const jsonOutput = !!args.json;
857
+ const whyFlag = !!args.why;
858
+ const projectIdOverride = args['project-id'];
859
+ const repoPath = process.cwd();
860
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
861
+ const maxDepth = Math.min(parseInt(args.depth, 10), 5);
862
+ const symbolName = args.symbol;
863
+ try {
864
+ // SSoT-EXEMPT:shape-mismatch — core NexusImpactResult (targetName/impactByDepth)
865
+ // differs from contracts NexusImpactResult (targetNodeId/affected); routing through
866
+ // dispatch.impact would require changing the output format. Tracked in T1510.
867
+ const result = await getSymbolImpact(symbolName, projectId, repoPath, {
868
+ maxDepth,
869
+ why: whyFlag,
870
+ });
871
+ const durationMs = Date.now() - startTime;
872
+ if (jsonOutput) {
873
+ process.stdout.write(JSON.stringify({
874
+ success: true,
875
+ data: result,
876
+ meta: {
877
+ operation: 'nexus.impact',
878
+ duration_ms: durationMs,
879
+ timestamp: new Date().toISOString(),
880
+ },
881
+ }, null, 2) + '\n');
882
+ }
883
+ else {
884
+ process.stdout.write(`[nexus] Impact analysis for '${symbolName}'\n Target: ${String(result.targetName)} (${String(result.targetKind)})\n File: ${result.targetFilePath ? String(result.targetFilePath) : 'n/a'}\n Risk: ${result.riskLevel} (${result.totalImpactedNodes} impacted node${result.totalImpactedNodes !== 1 ? 's' : ''})\n`);
885
+ if (result.totalImpactedNodes === 0) {
886
+ process.stdout.write(' No callers found — safe to modify.\n');
887
+ }
888
+ else {
889
+ for (let i = 0; i < result.impactByDepth.length; i++) {
890
+ const layer = result.impactByDepth[i];
891
+ if (!layer || layer.nodes.length === 0)
892
+ continue;
893
+ const label = i === 0 ? 'WILL BREAK' : i === 1 ? 'LIKELY AFFECTED' : 'MAY NEED TESTING';
894
+ process.stdout.write(`\n d=${i + 1} ${label} (${layer.nodes.length}):\n`);
895
+ for (const node of layer.nodes.slice(0, 15)) {
896
+ process.stdout.write(` ${String(node.name).padEnd(36)} ${String(node.kind).padEnd(12)} ${node.filePath ?? ''}\n`);
897
+ if (whyFlag && node.reasons.length > 0) {
898
+ for (const reason of node.reasons) {
899
+ process.stdout.write(` why: ${reason}\n`);
900
+ }
901
+ }
902
+ }
903
+ if (layer.nodes.length > 15) {
904
+ process.stdout.write(` ... and ${layer.nodes.length - 15} more\n`);
905
+ }
906
+ }
907
+ }
908
+ }
909
+ }
910
+ catch (err) {
911
+ const code = err instanceof Error && 'code' in err ? err.code : undefined;
912
+ const msg = err instanceof Error ? err.message : String(err);
913
+ const durationMs = Date.now() - startTime;
914
+ if (code === 'E_NOT_FOUND') {
915
+ if (jsonOutput) {
916
+ process.stdout.write(JSON.stringify({
917
+ success: false,
918
+ error: { code: 'E_NOT_FOUND', message: msg },
919
+ meta: {
920
+ operation: 'nexus.impact',
921
+ duration_ms: durationMs,
922
+ timestamp: new Date().toISOString(),
923
+ },
924
+ }, null, 2) + '\n');
925
+ }
926
+ else {
927
+ process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n Run 'cleo nexus analyze' first, or check the symbol name.\n`);
928
+ }
929
+ process.exitCode = 4;
930
+ return;
931
+ }
932
+ if (jsonOutput) {
933
+ process.stdout.write(JSON.stringify({
934
+ success: false,
935
+ error: { code: 'E_IMPACT_FAILED', message: msg },
936
+ meta: {
937
+ operation: 'nexus.impact',
938
+ duration_ms: durationMs,
939
+ timestamp: new Date().toISOString(),
940
+ },
941
+ }, null, 2) + '\n');
942
+ }
943
+ else {
944
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
945
+ }
946
+ process.exitCode = 1;
947
+ }
948
+ },
949
+ });
950
+ /** cleo nexus analyze — run code intelligence pipeline on a repository directory */
951
+ const analyzeCommand = defineCommand({
952
+ meta: {
953
+ name: 'analyze',
954
+ description: 'Run code intelligence pipeline on a repository directory',
955
+ },
956
+ args: {
957
+ path: {
958
+ type: 'positional',
959
+ description: 'Path to repository directory (default: cwd)',
960
+ required: false,
961
+ },
962
+ json: {
963
+ type: 'boolean',
964
+ description: 'Output result as JSON (LAFS envelope format)',
965
+ },
966
+ 'project-id': {
967
+ type: 'string',
968
+ description: 'Override the project ID (default: auto-detected)',
969
+ },
970
+ incremental: {
971
+ type: 'boolean',
972
+ description: 'Only re-index files that have changed since the last run (faster)',
973
+ },
974
+ },
975
+ async run({ args }) {
976
+ const startTime = Date.now();
977
+ const jsonOutput = !!args.json;
978
+ const projectIdOverride = args['project-id'];
979
+ const isIncremental = !!args.incremental;
980
+ // Resolve target path
981
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
982
+ if (!jsonOutput) {
983
+ process.stderr.write(`[nexus] Analyzing: ${repoPath}${isIncremental ? ' (incremental)' : ''}\n`);
984
+ }
985
+ try {
986
+ // SSoT-EXEMPT:pipeline-progress — runPipeline requires a progress callback
987
+ // (CLI-only rendering concern) and direct DB handle access. No dispatch op
988
+ // can expose this without introducing CLI rendering concerns into the dispatch
989
+ // layer. The full analyze pipeline is fundamentally CLI-side-orchestrated.
990
+ // Lazy imports to avoid loading heavy dependencies until needed
991
+ const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot }, { eq }] = await Promise.all([
992
+ import('@cleocode/core/store/nexus-sqlite'),
993
+ import('@cleocode/nexus/pipeline'),
994
+ import('@cleocode/core/internal'),
995
+ import('drizzle-orm'),
996
+ ]);
997
+ // Determine project ID — use override or derive from path
998
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
999
+ // Get DB and table references
1000
+ const db = await getNexusDb();
1001
+ const tables = {
1002
+ nexusNodes: nexusSchema.nexusNodes,
1003
+ nexusRelations: nexusSchema.nexusRelations,
1004
+ };
1005
+ // For full (non-incremental) runs: delete existing index first.
1006
+ // NodeSQLiteDatabase uses sync Drizzle — no await, wrap in try-catch.
1007
+ if (!isIncremental) {
1008
+ if (!jsonOutput) {
1009
+ process.stderr.write('[nexus] Clearing existing index for project...\n');
1010
+ }
1011
+ try {
1012
+ db.delete(nexusSchema.nexusNodes)
1013
+ .where(eq(nexusSchema.nexusNodes.projectId, projectId))
1014
+ .run();
1015
+ }
1016
+ catch {
1017
+ // Table may not have rows — ignore
1018
+ }
1019
+ try {
1020
+ db.delete(nexusSchema.nexusRelations)
1021
+ .where(eq(nexusSchema.nexusRelations.projectId, projectId))
1022
+ .run();
1023
+ }
1024
+ catch {
1025
+ // Table may not have rows — ignore
1026
+ }
1027
+ }
1028
+ // Run the pipeline (full or incremental)
1029
+ const result = await runPipeline(repoPath, projectId, db, tables, jsonOutput
1030
+ ? undefined
1031
+ : (current, total, filePath) => {
1032
+ if (current % 50 === 0 || current === total) {
1033
+ const pct = total > 0 ? Math.round((current / total) * 100) : 100;
1034
+ process.stderr.write(`[nexus] Progress: ${current}/${total} files (${pct}%) — ${filePath}\n`);
1035
+ }
1036
+ }, { incremental: isIncremental });
1037
+ const durationMs = Date.now() - startTime;
1038
+ // Write nexus-bridge.md after a successful pipeline run (best-effort)
1039
+ try {
1040
+ const { refreshNexusBridge } = await import('@cleocode/core/internal');
1041
+ await refreshNexusBridge(repoPath, projectId);
1042
+ if (!jsonOutput) {
1043
+ process.stderr.write(`[nexus] nexus-bridge.md refreshed at ${repoPath}/.cleo/nexus-bridge.md\n`);
1044
+ }
1045
+ }
1046
+ catch {
1047
+ // Non-fatal — bridge refresh failure should not fail the analyze command
1048
+ }
1049
+ // Auto-register project and update index stats in the multi-project registry (best-effort)
1050
+ try {
1051
+ const { nexusUpdateIndexStats } = await import('@cleocode/core/internal');
1052
+ await nexusUpdateIndexStats(repoPath, {
1053
+ nodeCount: result.nodeCount,
1054
+ relationCount: result.relationCount,
1055
+ fileCount: result.fileCount,
1056
+ });
1057
+ if (!jsonOutput) {
1058
+ process.stderr.write('[nexus] Project registered/updated in multi-project registry.\n');
1059
+ }
1060
+ }
1061
+ catch {
1062
+ // Non-fatal — registry update must never fail the analyze command
1063
+ }
1064
+ // Post-hook: sweep git log and link task IDs to symbols (best-effort, idempotent)
1065
+ try {
1066
+ const { runGitLogTaskLinker } = await import('@cleocode/core/nexus');
1067
+ const sweeperResult = await runGitLogTaskLinker(repoPath);
1068
+ if (!jsonOutput && sweeperResult.commitsProcessed > 0) {
1069
+ process.stderr.write(`[nexus] Task-symbol sweep: ${sweeperResult.commitsProcessed} commit(s), ${sweeperResult.tasksFound} task(s), ${sweeperResult.linked} edge(s) linked.\n`);
1070
+ }
1071
+ }
1072
+ catch {
1073
+ // Non-fatal — task sweeper failure must never fail the analyze command
1074
+ }
1075
+ if (jsonOutput) {
1076
+ const envelope = {
1077
+ success: true,
1078
+ data: {
1079
+ projectId,
1080
+ repoPath,
1081
+ incremental: isIncremental,
1082
+ nodeCount: result.nodeCount,
1083
+ relationCount: result.relationCount,
1084
+ fileCount: result.fileCount,
1085
+ durationMs,
1086
+ },
1087
+ meta: {
1088
+ operation: 'nexus.analyze',
1089
+ duration_ms: durationMs,
1090
+ timestamp: new Date().toISOString(),
1091
+ },
1092
+ };
1093
+ process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
1094
+ }
1095
+ else {
1096
+ process.stdout.write(`[nexus] Analysis complete${isIncremental ? ' (incremental)' : ''}:\n` +
1097
+ ` Project ID: ${projectId}\n` +
1098
+ ` Files: ${result.fileCount}\n` +
1099
+ ` Nodes: ${result.nodeCount}\n` +
1100
+ ` Relations: ${result.relationCount}\n` +
1101
+ ` Duration: ${durationMs}ms\n`);
1102
+ }
1103
+ void getProjectRoot; // referenced to satisfy import
1104
+ }
1105
+ catch (err) {
1106
+ const msg = err instanceof Error ? err.message : String(err);
1107
+ if (jsonOutput) {
1108
+ const envelope = {
1109
+ success: false,
1110
+ error: { code: 'E_PIPELINE_FAILED', message: msg },
1111
+ meta: {
1112
+ operation: 'nexus.analyze',
1113
+ duration_ms: Date.now() - startTime,
1114
+ timestamp: new Date().toISOString(),
1115
+ },
1116
+ };
1117
+ process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
1118
+ }
1119
+ else {
1120
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1121
+ }
1122
+ process.exitCode = 1;
1123
+ }
1124
+ },
1125
+ });
1126
+ // ── nexus projects subcommand group ──────────────────────────────────────────
1127
+ /** cleo nexus projects list — list all projects registered in the global nexus registry */
1128
+ const projectsListCommand = defineCommand({
1129
+ meta: {
1130
+ name: 'list',
1131
+ description: 'List all projects registered in the global nexus registry',
1132
+ },
1133
+ args: {
1134
+ json: {
1135
+ type: 'boolean',
1136
+ description: 'Output as JSON (LAFS envelope format)',
1137
+ },
1138
+ },
1139
+ async run({ args }) {
1140
+ const startTime = Date.now();
1141
+ const jsonOutput = !!args.json;
1142
+ const response = await dispatchRaw('query', 'nexus', 'projects.list', {});
1143
+ const durationMs = Date.now() - startTime;
1144
+ if (!response.success) {
1145
+ process.stderr.write(`[nexus] Error: ${response.error?.message ?? 'Unknown error'}\n`);
1146
+ process.exitCode = 1;
1147
+ return;
1148
+ }
1149
+ const data = response.data;
1150
+ const list = data.projects;
1151
+ if (jsonOutput) {
1152
+ process.stdout.write(JSON.stringify({
1153
+ success: true,
1154
+ data,
1155
+ meta: {
1156
+ operation: 'nexus.projects.list',
1157
+ duration_ms: durationMs,
1158
+ timestamp: new Date().toISOString(),
1159
+ },
1160
+ }, null, 2) + '\n');
1161
+ }
1162
+ else if (list.length === 0) {
1163
+ process.stdout.write('[nexus] No projects registered. Run: cleo nexus projects register\n');
1164
+ }
1165
+ else {
1166
+ process.stdout.write(`[nexus] Registered projects (${list.length}):\n\n`);
1167
+ for (const p of list) {
1168
+ const nodes = p.stats?.nodeCount ?? 0;
1169
+ const rels = p.stats?.relationCount ?? 0;
1170
+ const indexed = p.lastIndexed ? p.lastIndexed.slice(0, 10) : 'never';
1171
+ 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` +
1172
+ ` ${''.padEnd(28)} path=${p.path}\n`);
1173
+ }
1174
+ }
1175
+ },
1176
+ });
1177
+ /** cleo nexus projects register — register a project in the global nexus registry */
1178
+ const projectsRegisterCommand = defineCommand({
1179
+ meta: {
1180
+ name: 'register',
1181
+ description: 'Register a project in the global nexus registry (default: current directory)',
1182
+ },
1183
+ args: {
1184
+ path: {
1185
+ type: 'positional',
1186
+ description: 'Path to the project directory (default: cwd)',
1187
+ required: false,
1188
+ },
1189
+ name: {
1190
+ type: 'string',
1191
+ description: 'Custom project name (default: directory name)',
1192
+ },
1193
+ json: {
1194
+ type: 'boolean',
1195
+ description: 'Output as JSON (LAFS envelope format)',
1196
+ },
1197
+ },
1198
+ async run({ args }) {
1199
+ const startTime = Date.now();
1200
+ const jsonOutput = !!args.json;
1201
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
1202
+ const name = args.name;
1203
+ const response = await dispatchRaw('mutate', 'nexus', 'projects.register', {
1204
+ path: repoPath,
1205
+ name,
1206
+ });
1207
+ const durationMs = Date.now() - startTime;
1208
+ if (!response.success) {
1209
+ const msg = response.error?.message ?? 'Unknown error';
1210
+ if (jsonOutput) {
1211
+ process.stdout.write(JSON.stringify({
1212
+ success: false,
1213
+ error: { code: response.error?.code ?? 'E_REGISTER_FAILED', message: msg },
1214
+ meta: {
1215
+ operation: 'nexus.projects.register',
1216
+ duration_ms: durationMs,
1217
+ timestamp: new Date().toISOString(),
1218
+ },
1219
+ }, null, 2) + '\n');
1220
+ }
1221
+ else {
1222
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1223
+ }
1224
+ process.exitCode = 1;
1225
+ return;
1226
+ }
1227
+ const data = response.data;
1228
+ if (jsonOutput) {
1229
+ process.stdout.write(JSON.stringify({
1230
+ success: true,
1231
+ data,
1232
+ meta: {
1233
+ operation: 'nexus.projects.register',
1234
+ duration_ms: durationMs,
1235
+ timestamp: new Date().toISOString(),
1236
+ },
1237
+ }, null, 2) + '\n');
1238
+ }
1239
+ else {
1240
+ process.stdout.write(`[nexus] Registered: ${data.path} (hash: ${data.hash})\n`);
1241
+ }
1242
+ },
1243
+ });
1244
+ /** cleo nexus projects remove — remove a project from the global nexus registry */
1245
+ const projectsRemoveCommand = defineCommand({
1246
+ meta: {
1247
+ name: 'remove',
1248
+ description: 'Remove a project from the global nexus registry',
1249
+ },
1250
+ args: {
1251
+ nameOrHash: {
1252
+ type: 'positional',
1253
+ description: 'Project name or hash to remove',
1254
+ required: true,
1255
+ },
1256
+ json: {
1257
+ type: 'boolean',
1258
+ description: 'Output as JSON (LAFS envelope format)',
1259
+ },
1260
+ },
1261
+ async run({ args }) {
1262
+ const startTime = Date.now();
1263
+ const jsonOutput = !!args.json;
1264
+ const response = await dispatchRaw('mutate', 'nexus', 'projects.remove', {
1265
+ nameOrHash: args.nameOrHash,
1266
+ });
1267
+ const durationMs = Date.now() - startTime;
1268
+ if (!response.success) {
1269
+ const msg = response.error?.message ?? 'Unknown error';
1270
+ if (jsonOutput) {
1271
+ process.stdout.write(JSON.stringify({
1272
+ success: false,
1273
+ error: { code: response.error?.code ?? 'E_REMOVE_FAILED', message: msg },
1274
+ meta: {
1275
+ operation: 'nexus.projects.remove',
1276
+ duration_ms: durationMs,
1277
+ timestamp: new Date().toISOString(),
1278
+ },
1279
+ }, null, 2) + '\n');
1280
+ }
1281
+ else {
1282
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1283
+ }
1284
+ process.exitCode = 1;
1285
+ return;
1286
+ }
1287
+ if (jsonOutput) {
1288
+ process.stdout.write(JSON.stringify({
1289
+ success: true,
1290
+ data: response.data,
1291
+ meta: {
1292
+ operation: 'nexus.projects.remove',
1293
+ duration_ms: durationMs,
1294
+ timestamp: new Date().toISOString(),
1295
+ },
1296
+ }, null, 2) + '\n');
1297
+ }
1298
+ else {
1299
+ process.stdout.write(`[nexus] Removed: ${String(args.nameOrHash)}\n`);
1300
+ }
1301
+ },
1302
+ });
1303
+ /** cleo nexus projects scan — walk filesystem roots to discover .cleo/ directories */
1304
+ const projectsScanCommand = defineCommand({
1305
+ meta: {
1306
+ name: 'scan',
1307
+ description: 'Walk filesystem roots to discover .cleo/ directories not registered in the global nexus registry',
1308
+ },
1309
+ args: {
1310
+ roots: {
1311
+ type: 'string',
1312
+ description: 'Comma-separated search roots (default: ~/code,~/projects,/mnt/projects)',
1313
+ },
1314
+ 'max-depth': {
1315
+ type: 'string',
1316
+ description: 'Maximum directory traversal depth (default: 4)',
1317
+ default: '4',
1318
+ },
1319
+ 'auto-register': {
1320
+ type: 'boolean',
1321
+ description: 'Register all discovered unregistered projects automatically',
1322
+ },
1323
+ 'include-existing': {
1324
+ type: 'boolean',
1325
+ description: 'Also report projects that are already registered',
1326
+ },
1327
+ json: { type: 'boolean', description: 'Output as JSON (LAFS envelope format)' },
1328
+ },
1329
+ async run({ args }) {
1330
+ const startTime = Date.now();
1331
+ const jsonOutput = !!args.json;
1332
+ const autoRegister = !!args['auto-register'];
1333
+ const includeExisting = !!args['include-existing'];
1334
+ const maxDepth = Math.max(1, Math.min(parseInt(args['max-depth'], 10), 20));
1335
+ if (!jsonOutput) {
1336
+ process.stdout.write(`[nexus] Scanning up to depth ${maxDepth} for .cleo/ project roots...\n`);
1337
+ }
1338
+ const response = await dispatchRaw('mutate', 'nexus', 'projects.scan', {
1339
+ roots: args.roots,
1340
+ maxDepth,
1341
+ autoRegister,
1342
+ includeExisting,
1343
+ });
1344
+ const durationMs = Date.now() - startTime;
1345
+ if (!response.success) {
1346
+ process.stderr.write(`[nexus] Error: ${response.error?.message ?? 'Unknown error'}\n`);
1347
+ process.exitCode = 1;
1348
+ return;
1349
+ }
1350
+ const result = response.data;
1351
+ if (!jsonOutput) {
1352
+ process.stdout.write(`[nexus] Scanning ${result.roots.length} root(s) up to depth ${maxDepth}:\n${result.roots.map((r) => ` ${r}`).join('\n')}\n`);
1353
+ }
1354
+ if (jsonOutput) {
1355
+ const data = {
1356
+ roots: result.roots,
1357
+ unregistered: result.unregistered,
1358
+ tally: result.tally,
1359
+ };
1360
+ if (includeExisting)
1361
+ data['registered'] = result.registered;
1362
+ if (autoRegister) {
1363
+ data['autoRegistered'] = result.autoRegistered;
1364
+ data['autoRegisterErrors'] = result.autoRegisterErrors;
1365
+ }
1366
+ process.stdout.write(JSON.stringify({
1367
+ success: true,
1368
+ data,
1369
+ meta: {
1370
+ operation: 'nexus.projects.scan',
1371
+ duration_ms: durationMs,
1372
+ timestamp: new Date().toISOString(),
1373
+ },
1374
+ }, null, 2) + '\n');
1375
+ }
1376
+ else {
1377
+ process.stdout.write(`\n[nexus] Scan complete — ${result.tally.total} project(s) found (${result.tally.unregistered} unregistered, ${result.tally.registered} registered)\n`);
1378
+ if (result.unregistered.length > 0) {
1379
+ process.stdout.write('\n Unregistered:\n');
1380
+ for (const p of result.unregistered) {
1381
+ process.stdout.write(` ${p}\n`);
1382
+ }
1383
+ if (!autoRegister) {
1384
+ process.stdout.write('\n Tip: run with --auto-register to register all of the above.\n');
1385
+ }
1386
+ }
1387
+ if (includeExisting && result.registered.length > 0) {
1388
+ process.stdout.write('\n Already registered:\n');
1389
+ for (const p of result.registered) {
1390
+ process.stdout.write(` ${p}\n`);
1391
+ }
1392
+ }
1393
+ if (autoRegister) {
1394
+ process.stdout.write(`\n Auto-registered: ${result.autoRegistered.length} project(s)${result.autoRegisterErrors.length > 0 ? `, ${result.autoRegisterErrors.length} failed` : ''}\n`);
1395
+ for (const e of result.autoRegisterErrors) {
1396
+ process.stdout.write(` FAILED ${e.path}: ${e.error}\n`);
1397
+ }
1398
+ }
1399
+ }
1400
+ },
1401
+ });
1402
+ /** cleo nexus projects clean — bulk purge project_registry rows matching path criteria */
1403
+ const projectsCleanCommand = defineCommand({
1404
+ meta: {
1405
+ name: 'clean',
1406
+ description: 'Bulk purge project_registry rows matching path criteria (requires at least one filter flag)',
1407
+ },
1408
+ args: {
1409
+ 'dry-run': {
1410
+ type: 'boolean',
1411
+ description: 'List matching projects without deleting anything',
1412
+ },
1413
+ pattern: {
1414
+ type: 'string',
1415
+ description: 'JS regex matched against project_path',
1416
+ },
1417
+ 'include-temp': {
1418
+ type: 'boolean',
1419
+ description: 'Preset: match paths containing a .temp/ segment',
1420
+ },
1421
+ 'include-tests': {
1422
+ type: 'boolean',
1423
+ description: 'Preset: match paths containing tmp/test/fixture/scratch/sandbox segments',
1424
+ },
1425
+ unhealthy: {
1426
+ type: 'boolean',
1427
+ description: 'Also match rows where health_status is "unhealthy"',
1428
+ },
1429
+ 'never-indexed': {
1430
+ type: 'boolean',
1431
+ description: 'Also match rows where last_indexed IS NULL',
1432
+ },
1433
+ yes: {
1434
+ type: 'boolean',
1435
+ description: 'Skip confirmation prompt (still shows preview)',
1436
+ },
1437
+ json: {
1438
+ type: 'boolean',
1439
+ description: 'Output as JSON (LAFS envelope format)',
1440
+ },
1441
+ },
1442
+ async run({ args }) {
1443
+ const startTime = Date.now();
1444
+ const jsonOutput = !!args.json;
1445
+ const dryRun = !!args['dry-run'];
1446
+ const skipPrompt = !!args.yes;
1447
+ const cleanOpts = {
1448
+ pattern: args.pattern,
1449
+ includeTemp: !!args['include-temp'],
1450
+ includeTests: !!args['include-tests'],
1451
+ matchUnhealthy: !!args.unhealthy,
1452
+ matchNeverIndexed: !!args['never-indexed'],
1453
+ };
1454
+ try {
1455
+ // Preview phase via dispatch (always dry-run first to get counts)
1456
+ const previewResp = await dispatchRaw('mutate', 'nexus', 'projects.clean', {
1457
+ ...cleanOpts,
1458
+ dryRun: true,
1459
+ });
1460
+ if (!previewResp.success) {
1461
+ const code = previewResp.error?.code ?? 'E_CLEAN_FAILED';
1462
+ const msg = previewResp.error?.message ?? 'Unknown error';
1463
+ const exitCode = code === 'E_NO_CRITERIA' || code === 'E_INVALID_PATTERN' ? 6 : 1;
1464
+ if (jsonOutput) {
1465
+ process.stdout.write(JSON.stringify({
1466
+ success: false,
1467
+ error: { code, message: msg },
1468
+ meta: {
1469
+ operation: 'nexus.projects.clean',
1470
+ duration_ms: Date.now() - startTime,
1471
+ timestamp: new Date().toISOString(),
1472
+ },
1473
+ }, null, 2) + '\n');
1474
+ }
1475
+ else {
1476
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1477
+ }
1478
+ process.exitCode = exitCode;
1479
+ return;
1480
+ }
1481
+ const preview = previewResp.data;
1482
+ const { matched: matchCount, totalCount, sample: samplePaths } = preview;
1483
+ // Show preview in human mode
1484
+ if (!jsonOutput) {
1485
+ process.stdout.write(`[nexus] Clean preview — ${matchCount} project(s) of ${totalCount} total match criteria:\n`);
1486
+ if (matchCount === 0) {
1487
+ process.stdout.write(' (no matches)\n');
1488
+ }
1489
+ else {
1490
+ for (const p of samplePaths) {
1491
+ process.stdout.write(` ${p}\n`);
1492
+ }
1493
+ if (matchCount > 10) {
1494
+ process.stdout.write(` ... and ${matchCount - 10} more\n`);
1495
+ }
1496
+ }
1497
+ }
1498
+ if (matchCount === 0 || dryRun) {
1499
+ const durationMs = Date.now() - startTime;
1500
+ if (jsonOutput) {
1501
+ process.stdout.write(JSON.stringify({
1502
+ success: true,
1503
+ data: {
1504
+ dryRun: true,
1505
+ matched: matchCount,
1506
+ purged: 0,
1507
+ remaining: totalCount,
1508
+ sample: samplePaths,
1509
+ },
1510
+ meta: {
1511
+ operation: 'nexus.projects.clean',
1512
+ duration_ms: durationMs,
1513
+ timestamp: new Date().toISOString(),
1514
+ },
1515
+ }, null, 2) + '\n');
1516
+ }
1517
+ else if (dryRun && matchCount > 0) {
1518
+ process.stdout.write(`[nexus] Dry-run — ${matchCount} project(s) would be purged. Rerun without --dry-run to delete.\n`);
1519
+ }
1520
+ return;
1521
+ }
1522
+ // Confirmation prompt (skip with --yes) — CLI-side interactive stdin
1523
+ if (!skipPrompt) {
1524
+ const { createInterface } = await import('node:readline');
1525
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
1526
+ const confirmed = await new Promise((resolve) => {
1527
+ rl.question(`\n[nexus] Delete ${matchCount} project(s) from the registry? [y/N] `, (answer) => {
1528
+ rl.close();
1529
+ resolve(answer.trim().toLowerCase() === 'y');
1530
+ });
1531
+ });
1532
+ if (!confirmed) {
1533
+ process.stdout.write('[nexus] Aborted — no projects deleted.\n');
1534
+ return;
1535
+ }
1536
+ }
1537
+ // Actual delete via dispatch
1538
+ const deleteResp = await dispatchRaw('mutate', 'nexus', 'projects.clean', {
1539
+ ...cleanOpts,
1540
+ dryRun: false,
1541
+ });
1542
+ const durationMs = Date.now() - startTime;
1543
+ if (!deleteResp.success) {
1544
+ const code = deleteResp.error?.code ?? 'E_CLEAN_FAILED';
1545
+ const msg = deleteResp.error?.message ?? 'Unknown error';
1546
+ const exitCode = code === 'E_NO_CRITERIA' || code === 'E_INVALID_PATTERN' ? 6 : 1;
1547
+ if (jsonOutput) {
1548
+ process.stdout.write(JSON.stringify({
1549
+ success: false,
1550
+ error: { code, message: msg },
1551
+ meta: {
1552
+ operation: 'nexus.projects.clean',
1553
+ duration_ms: durationMs,
1554
+ timestamp: new Date().toISOString(),
1555
+ },
1556
+ }, null, 2) + '\n');
1557
+ }
1558
+ else {
1559
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1560
+ }
1561
+ process.exitCode = exitCode;
1562
+ return;
1563
+ }
1564
+ const result = deleteResp.data;
1565
+ if (jsonOutput) {
1566
+ process.stdout.write(JSON.stringify({
1567
+ success: true,
1568
+ data: {
1569
+ dryRun: false,
1570
+ matched: result.matched,
1571
+ purged: result.purged,
1572
+ remaining: result.remaining,
1573
+ sample: result.sample,
1574
+ },
1575
+ meta: {
1576
+ operation: 'nexus.projects.clean',
1577
+ duration_ms: durationMs,
1578
+ timestamp: new Date().toISOString(),
1579
+ },
1580
+ }, null, 2) + '\n');
1581
+ }
1582
+ else {
1583
+ process.stdout.write(`[nexus] Purged ${result.purged} project(s). ${result.remaining} project(s) remaining in registry.\n`);
1584
+ }
1585
+ }
1586
+ catch (err) {
1587
+ const durationMs = Date.now() - startTime;
1588
+ const msg = err instanceof Error ? err.message : String(err);
1589
+ if (jsonOutput) {
1590
+ process.stdout.write(JSON.stringify({
1591
+ success: false,
1592
+ error: { code: 'E_CLEAN_FAILED', message: msg },
1593
+ meta: {
1594
+ operation: 'nexus.projects.clean',
1595
+ duration_ms: durationMs,
1596
+ timestamp: new Date().toISOString(),
1597
+ },
1598
+ }, null, 2) + '\n');
1599
+ }
1600
+ else {
1601
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1602
+ }
1603
+ process.exitCode = 1;
1604
+ }
1605
+ },
1606
+ });
1607
+ /** cleo nexus projects — multi-project registry management */
1608
+ const projectsCommand = defineCommand({
1609
+ meta: { name: 'projects', description: 'Multi-project registry management' },
1610
+ subCommands: {
1611
+ list: projectsListCommand,
1612
+ register: projectsRegisterCommand,
1613
+ remove: projectsRemoveCommand,
1614
+ scan: projectsScanCommand,
1615
+ clean: projectsCleanCommand,
1616
+ },
1617
+ });
1618
+ /** cleo nexus refresh-bridge — regenerate .cleo/nexus-bridge.md from existing index */
1619
+ const refreshBridgeCommand = defineCommand({
1620
+ meta: {
1621
+ name: 'refresh-bridge',
1622
+ description: 'Regenerate .cleo/nexus-bridge.md from the existing nexus.db index (does not re-index)',
1623
+ },
1624
+ args: {
1625
+ path: {
1626
+ type: 'positional',
1627
+ description: 'Path to project directory (default: cwd)',
1628
+ required: false,
1629
+ },
1630
+ json: {
1631
+ type: 'boolean',
1632
+ description: 'Output result as JSON (LAFS envelope format)',
1633
+ },
1634
+ 'project-id': {
1635
+ type: 'string',
1636
+ description: 'Override the project ID (default: auto-detected from path)',
1637
+ },
1638
+ },
1639
+ async run({ args }) {
1640
+ const startTime = Date.now();
1641
+ const jsonOutput = !!args.json;
1642
+ const projectIdOverride = args['project-id'];
1643
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
1644
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
1645
+ const response = await dispatchRaw('mutate', 'nexus', 'refresh-bridge', {
1646
+ repoPath,
1647
+ projectId,
1648
+ });
1649
+ const durationMs = Date.now() - startTime;
1650
+ if (!response.success) {
1651
+ const msg = response.error?.message ?? 'Unknown error';
1652
+ if (jsonOutput) {
1653
+ process.stdout.write(JSON.stringify({
1654
+ success: false,
1655
+ error: { code: response.error?.code ?? 'E_BRIDGE_FAILED', message: msg },
1656
+ meta: {
1657
+ operation: 'nexus.refresh-bridge',
1658
+ duration_ms: durationMs,
1659
+ timestamp: new Date().toISOString(),
1660
+ },
1661
+ }, null, 2) + '\n');
1662
+ }
1663
+ else {
1664
+ process.stderr.write(`[nexus] Error refreshing bridge: ${msg}\n`);
1665
+ }
1666
+ process.exitCode = 1;
1667
+ return;
1668
+ }
1669
+ const result = response.data;
1670
+ if (jsonOutput) {
1671
+ process.stdout.write(JSON.stringify({
1672
+ success: true,
1673
+ data: result,
1674
+ meta: {
1675
+ operation: 'nexus.refresh-bridge',
1676
+ duration_ms: durationMs,
1677
+ timestamp: new Date().toISOString(),
1678
+ },
1679
+ }, null, 2) + '\n');
1680
+ }
1681
+ else if (result.written) {
1682
+ process.stdout.write(`[nexus] nexus-bridge.md refreshed at ${result.path}\n`);
1683
+ }
1684
+ else {
1685
+ process.stdout.write(`[nexus] nexus-bridge.md unchanged at ${result.path}\n`);
1686
+ }
1687
+ },
1688
+ });
1689
+ /**
1690
+ * Export nexus graph to GEXF (Gephi) or JSON format.
1691
+ *
1692
+ * Queries graph_nodes and graph_edges from nexus.db and emits GEXF format
1693
+ * suitable for visualization in Gephi. Supports optional project filtering.
1694
+ *
1695
+ * @task T626-M7
1696
+ */
1697
+ const exportCommand = defineCommand({
1698
+ meta: { name: 'export', description: 'Export nexus graph to GEXF (Gephi) or JSON format' },
1699
+ args: {
1700
+ format: {
1701
+ type: 'string',
1702
+ description: 'Output format: gexf, json',
1703
+ default: 'gexf',
1704
+ },
1705
+ output: {
1706
+ type: 'string',
1707
+ description: 'Output file path (stdout if omitted)',
1708
+ },
1709
+ project: {
1710
+ type: 'string',
1711
+ description: 'Filter by project ID (exports all projects if omitted)',
1712
+ },
1713
+ },
1714
+ async run({ args }) {
1715
+ const startTime = Date.now();
1716
+ const format = args.format ?? 'gexf';
1717
+ const outputFile = args.output;
1718
+ const projectFilter = args.project;
1719
+ try {
1720
+ // SSoT-EXEMPT:file-serialization — GEXF/JSON graph export writes raw bytes
1721
+ // to stdout/file; requires direct nexus.db access for node/relation queries.
1722
+ // Cannot be a standard LAFS dispatch envelope without binary data concerns.
1723
+ const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
1724
+ const db = await getNexusDb();
1725
+ // Load all nodes and relations
1726
+ let allNodes = [];
1727
+ let allRelations = [];
1728
+ try {
1729
+ allNodes = db.select().from(nexusSchema.nexusNodes).all();
1730
+ allRelations = db.select().from(nexusSchema.nexusRelations).all();
1731
+ }
1732
+ catch {
1733
+ // DB may be empty
1734
+ }
1735
+ // Filter by project if specified
1736
+ const nodes = projectFilter
1737
+ ? allNodes.filter((n) => n['projectId'] === projectFilter)
1738
+ : allNodes;
1739
+ const relations = projectFilter
1740
+ ? allRelations.filter((r) => r['projectId'] === projectFilter)
1741
+ : allRelations;
1742
+ let output = '';
1743
+ if (format === 'json') {
1744
+ output = JSON.stringify({
1745
+ nodes: nodes.map((n) => ({
1746
+ id: n['id'],
1747
+ kind: n['kind'],
1748
+ label: n['label'],
1749
+ name: n['name'],
1750
+ filePath: n['filePath'],
1751
+ language: n['language'],
1752
+ isExported: n['isExported'],
1753
+ startLine: n['startLine'],
1754
+ endLine: n['endLine'],
1755
+ projectId: n['projectId'],
1756
+ })),
1757
+ edges: relations.map((r) => ({
1758
+ id: r['id'],
1759
+ source: r['sourceId'],
1760
+ target: r['targetId'],
1761
+ type: r['type'],
1762
+ confidence: r['confidence'],
1763
+ reason: r['reason'],
1764
+ })),
1765
+ }, null, 2);
1766
+ }
1767
+ else if (format === 'gexf') {
1768
+ // GEXF format (Gephi standard)
1769
+ output = generateGexf(nodes, relations);
1770
+ }
1771
+ else {
1772
+ process.stderr.write(`[nexus] Error: Unknown format '${format}'. Supported: gexf, json\n`);
1773
+ process.exitCode = 1;
1774
+ return;
1775
+ }
1776
+ if (outputFile) {
1777
+ const { writeFileSync } = await import('node:fs');
1778
+ writeFileSync(outputFile, output, 'utf-8');
1779
+ process.stdout.write(`[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)\n`);
1780
+ }
1781
+ else {
1782
+ process.stdout.write(output);
1783
+ if (!output.endsWith('\n'))
1784
+ process.stdout.write('\n');
1785
+ }
1786
+ const durationMs = Date.now() - startTime;
1787
+ if (outputFile) {
1788
+ process.stderr.write(`[nexus] Export completed in ${durationMs}ms\n`);
1789
+ }
1790
+ }
1791
+ catch (err) {
1792
+ const msg = err instanceof Error ? err.message : String(err);
1793
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1794
+ process.exitCode = 1;
1795
+ }
1796
+ },
1797
+ });
1798
+ /**
1799
+ * Compare NEXUS index state between two git commits.
1800
+ * @task T625
1801
+ */
1802
+ const diffCommand = defineCommand({
1803
+ meta: {
1804
+ name: 'diff',
1805
+ description: 'Compare NEXUS index state between two git commits — shows new/removed relations and broken call chains',
1806
+ },
1807
+ args: {
1808
+ before: {
1809
+ type: 'string',
1810
+ description: 'Git SHA or ref for the "before" snapshot (default: HEAD~1)',
1811
+ },
1812
+ after: {
1813
+ type: 'string',
1814
+ description: 'Git SHA or ref for the "after" snapshot (default: HEAD)',
1815
+ default: 'HEAD',
1816
+ },
1817
+ path: { type: 'string', description: 'Repository directory to analyze (default: cwd)' },
1818
+ json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
1819
+ 'project-id': {
1820
+ type: 'string',
1821
+ description: 'Override the project ID (default: auto-detected from path)',
1822
+ },
1823
+ },
1824
+ async run({ args }) {
1825
+ const startTime = Date.now();
1826
+ const jsonOutput = !!args.json;
1827
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
1828
+ const projectIdOverride = args['project-id'];
1829
+ const beforeRef = args.before ?? 'HEAD~1';
1830
+ const afterRef = args.after ?? 'HEAD';
1831
+ if (!jsonOutput) {
1832
+ process.stderr.write(`[nexus] Diffing relations: ${beforeRef}..${afterRef} in ${repoPath}\n`);
1833
+ }
1834
+ const response = await dispatchRaw('query', 'nexus', 'diff', {
1835
+ repoPath,
1836
+ beforeRef,
1837
+ afterRef,
1838
+ projectId: projectIdOverride,
1839
+ });
1840
+ const durationMs = Date.now() - startTime;
1841
+ if (!response.success) {
1842
+ const msg = response.error?.message ?? 'Unknown error';
1843
+ if (jsonOutput) {
1844
+ process.stdout.write(JSON.stringify({
1845
+ success: false,
1846
+ error: { code: response.error?.code ?? 'E_DIFF_FAILED', message: msg },
1847
+ meta: {
1848
+ operation: 'nexus.diff',
1849
+ duration_ms: durationMs,
1850
+ timestamp: new Date().toISOString(),
1851
+ },
1852
+ }, null, 2) + '\n');
1853
+ }
1854
+ else {
1855
+ process.stderr.write(`[nexus] Error running diff: ${msg}\n`);
1856
+ }
1857
+ process.exitCode = 1;
1858
+ return;
1859
+ }
1860
+ const result = response.data;
1861
+ if (jsonOutput) {
1862
+ process.stdout.write(JSON.stringify({
1863
+ success: true,
1864
+ data: result,
1865
+ meta: {
1866
+ operation: 'nexus.diff',
1867
+ duration_ms: durationMs,
1868
+ timestamp: new Date().toISOString(),
1869
+ },
1870
+ }, null, 2) + '\n');
1871
+ }
1872
+ else {
1873
+ process.stdout.write(`[nexus] Diff: ${result.beforeSha}..${result.afterSha}\n Changed files: ${result.changedFiles.length > 0 ? result.changedFiles.join(', ') : 'n/a'}\n Nodes: before=${result.nodesBefore} after=${result.nodesAfter} new=+${result.newNodes} removed=-${result.removedNodes}\n Relations: before=${result.relationsBefore} after=${result.relationsAfter} new=+${result.newRelations} removed=-${result.removedRelations}\n Health: ${result.healthStatus}\n`);
1874
+ if (result.regressions.length > 0) {
1875
+ process.stdout.write('\n REGRESSIONS:\n');
1876
+ for (const reg of result.regressions) {
1877
+ process.stdout.write(` - ${reg}\n`);
1878
+ }
1879
+ }
1880
+ else {
1881
+ process.stdout.write(' No regressions detected.\n');
1882
+ }
1883
+ }
1884
+ },
1885
+ });
1886
+ /**
1887
+ * cleo nexus query — Execute recursive CTE queries against nexus.db
1888
+ *
1889
+ * Supports raw CTE syntax and 6 template aliases for common code intelligence patterns.
1890
+ * Results returned as markdown table.
1891
+ *
1892
+ * @task T1057
1893
+ */
1894
+ const queryCommand = defineCommand({
1895
+ meta: {
1896
+ name: 'query',
1897
+ description: 'Execute recursive CTE queries against nexus.db',
1898
+ },
1899
+ args: {
1900
+ cte: {
1901
+ type: 'positional',
1902
+ description: 'CTE SQL or template alias (callers-of, callees-of, co-changed, co-cited, path-between, community-members)',
1903
+ required: true,
1904
+ },
1905
+ params: {
1906
+ type: 'string',
1907
+ description: 'Comma-separated parameters (e.g., "sym-id-1,sym-id-2")',
1908
+ },
1909
+ },
1910
+ async run({ args }) {
1911
+ const cteOrAlias = args.cte;
1912
+ const paramsStr = args.params || '';
1913
+ const params = paramsStr
1914
+ .split(',')
1915
+ .map((p) => p.trim())
1916
+ .filter(Boolean);
1917
+ const response = await dispatchRaw('query', 'nexus', 'query-cte', {
1918
+ cte: cteOrAlias,
1919
+ params,
1920
+ });
1921
+ if (!response.success) {
1922
+ const code = response.error?.code;
1923
+ const msg = response.error?.message ?? 'Unknown error';
1924
+ const exitCode = code === 'E_INVALID_INPUT' ? 6 : 77;
1925
+ process.stderr.write(`[nexus] Error: ${msg}\n`);
1926
+ process.exitCode = exitCode;
1927
+ return;
1928
+ }
1929
+ const result = response.data;
1930
+ if (!result.success) {
1931
+ process.stderr.write(`[nexus] Query error: ${result.error ?? 'Unknown'}\n`);
1932
+ process.exitCode = 77;
1933
+ return;
1934
+ }
1935
+ // Format as markdown table using the DSL formatter
1936
+ const { formatCteResultAsMarkdown } = await import('@cleocode/core/nexus/query-dsl.js');
1937
+ const markdown = formatCteResultAsMarkdown(result);
1938
+ process.stdout.write(markdown + '\n');
1939
+ process.stdout.write(`\n[nexus] ${result.row_count} rows in ${result.execution_time_ms.toFixed(2)}ms\n`);
1940
+ },
1941
+ });
1942
+ /**
1943
+ * cleo nexus route-map — Display all routes with their handlers and dependencies.
1944
+ */
1945
+ const routeMapCommand = defineCommand({
1946
+ meta: {
1947
+ name: 'route-map',
1948
+ description: 'Display all routes with their handlers and dependencies',
1949
+ },
1950
+ args: {
1951
+ path: {
1952
+ type: 'positional',
1953
+ description: 'Path to project directory (default: cwd)',
1954
+ required: false,
1955
+ },
1956
+ json: {
1957
+ type: 'boolean',
1958
+ description: 'Output result as JSON (LAFS envelope format)',
1959
+ },
1960
+ 'project-id': {
1961
+ type: 'string',
1962
+ description: 'Override the project ID (default: auto-detected from path)',
1963
+ },
1964
+ },
1965
+ async run({ args }) {
1966
+ const startTime = Date.now();
1967
+ const jsonOutput = !!args.json;
1968
+ const projectIdOverride = args['project-id'];
1969
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
1970
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
1971
+ const response = await dispatchRaw('query', 'nexus', 'route-map', { projectId });
1972
+ const durationMs = Date.now() - startTime;
1973
+ if (!response.success) {
1974
+ const msg = response.error?.message ?? 'Unknown error';
1975
+ if (jsonOutput) {
1976
+ process.stdout.write(JSON.stringify({
1977
+ success: false,
1978
+ error: { code: response.error?.code ?? 'E_ROUTE_MAP_FAILED', message: msg },
1979
+ meta: {
1980
+ operation: 'nexus.route-map',
1981
+ duration_ms: durationMs,
1982
+ timestamp: new Date().toISOString(),
1983
+ },
1984
+ }, null, 2) + '\n');
1985
+ }
1986
+ else {
1987
+ process.stderr.write(`[nexus] Error running route-map: ${msg}\n`);
1988
+ }
1989
+ process.exitCode = 1;
1990
+ return;
1991
+ }
1992
+ const result = response.data;
1993
+ if (jsonOutput) {
1994
+ process.stdout.write(JSON.stringify({
1995
+ success: true,
1996
+ data: result,
1997
+ meta: {
1998
+ operation: 'nexus.route-map',
1999
+ duration_ms: durationMs,
2000
+ timestamp: new Date().toISOString(),
2001
+ },
2002
+ }, null, 2) + '\n');
2003
+ }
2004
+ else {
2005
+ if (result.routes.length === 0) {
2006
+ process.stdout.write(`[nexus] No routes found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
2007
+ }
2008
+ else {
2009
+ process.stdout.write(`[nexus] Route Map for project ${projectId} (${result.routes.length} total):\n\n`);
2010
+ process.stdout.write('| Route ID | Handler | Method | Path | Deps | Callers |\n');
2011
+ process.stdout.write('|----------|---------|--------|------|------|----------|\n');
2012
+ for (const route of result.routes) {
2013
+ const method = route.routeMeta['method'] ?? '—';
2014
+ const routePath = route.routeMeta['path'] ?? '—';
2015
+ const depCount = route.fetchedDeps.length;
2016
+ process.stdout.write(`| ${route.routeId} | ${route.handlerName} | ${method} | ${routePath} | ${depCount} | ${route.callerCount} |\n`);
2017
+ }
2018
+ process.stdout.write('\n');
2019
+ if (result.distinctDeps.length > 0) {
2020
+ process.stdout.write(`External dependencies: ${result.distinctDeps.join(', ')}\n`);
2021
+ }
2022
+ }
2023
+ }
2024
+ },
2025
+ });
2026
+ /**
2027
+ * cleo nexus shape-check — Check response shape compatibility for a route.
2028
+ */
2029
+ const shapeCheckCommand = defineCommand({
2030
+ meta: {
2031
+ name: 'shape-check',
2032
+ description: 'Check response shape compatibility for a route handler',
2033
+ },
2034
+ args: {
2035
+ routeSymbol: {
2036
+ type: 'positional',
2037
+ description: 'Route symbol ID (format: <filePath>::<routeName>)',
2038
+ required: true,
2039
+ },
2040
+ path: {
2041
+ type: 'positional',
2042
+ description: 'Path to project directory (default: cwd)',
2043
+ required: false,
2044
+ },
2045
+ json: {
2046
+ type: 'boolean',
2047
+ description: 'Output result as JSON (LAFS envelope format)',
2048
+ },
2049
+ 'project-id': {
2050
+ type: 'string',
2051
+ description: 'Override the project ID (default: auto-detected from path)',
2052
+ },
2053
+ },
2054
+ async run({ args }) {
2055
+ const startTime = Date.now();
2056
+ const routeSymbol = args.routeSymbol;
2057
+ const jsonOutput = !!args.json;
2058
+ const projectIdOverride = args['project-id'];
2059
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
2060
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
2061
+ const response = await dispatchRaw('query', 'nexus', 'shape-check', { routeSymbol, projectId });
2062
+ const durationMs = Date.now() - startTime;
2063
+ if (!response.success) {
2064
+ const msg = response.error?.message ?? 'Unknown error';
2065
+ if (jsonOutput) {
2066
+ process.stdout.write(JSON.stringify({
2067
+ success: false,
2068
+ error: { code: response.error?.code ?? 'E_SHAPE_CHECK_FAILED', message: msg },
2069
+ meta: {
2070
+ operation: 'nexus.shape-check',
2071
+ duration_ms: durationMs,
2072
+ timestamp: new Date().toISOString(),
2073
+ },
2074
+ }, null, 2) + '\n');
2075
+ }
2076
+ else {
2077
+ process.stderr.write(`[nexus] Error running shape-check: ${msg}\n`);
2078
+ }
2079
+ process.exitCode = 1;
2080
+ return;
2081
+ }
2082
+ const result = response.data;
2083
+ if (jsonOutput) {
2084
+ process.stdout.write(JSON.stringify({
2085
+ success: true,
2086
+ data: result,
2087
+ meta: {
2088
+ operation: 'nexus.shape-check',
2089
+ duration_ms: durationMs,
2090
+ timestamp: new Date().toISOString(),
2091
+ },
2092
+ }, null, 2) + '\n');
2093
+ }
2094
+ else {
2095
+ process.stdout.write(`[nexus] Shape Check for route ${routeSymbol}\n\n`);
2096
+ process.stdout.write(`Handler: ${result.handlerId}\n`);
2097
+ process.stdout.write(`Declared Shape: ${result.declaredShape}\n`);
2098
+ process.stdout.write(`Overall Status: ${result.overallStatus}\n`);
2099
+ process.stdout.write(`Recommendation: ${result.recommendation}\n\n`);
2100
+ if (result.callers.length === 0) {
2101
+ process.stdout.write('No callers found.\n');
2102
+ }
2103
+ else {
2104
+ process.stdout.write(`Callers (${result.callers.length} total):\n`);
2105
+ process.stdout.write('| Caller | File | Expected Shape | Status |\n');
2106
+ process.stdout.write('|--------|------|---------------|---------|\n');
2107
+ for (const caller of result.callers) {
2108
+ process.stdout.write(`| ${caller.callerName} | ${caller.callerFile} | ${caller.expectedShape} | ${caller.status} |\n`);
2109
+ }
2110
+ if (result.callers.some((c) => c.status !== 'compatible')) {
2111
+ process.stdout.write('\nIncompatibilities:\n');
2112
+ for (const caller of result.callers) {
2113
+ if (caller.status !== 'compatible') {
2114
+ process.stdout.write(` - ${caller.callerName}: ${caller.diagnosis}\n`);
2115
+ }
2116
+ }
2117
+ }
2118
+ }
2119
+ }
2120
+ },
2121
+ });
2122
+ /**
2123
+ * Root nexus command group — registers all nexus subcommands.
2124
+ *
2125
+ * Dispatches to nexus domain registry operations.
2126
+ * @task T4554
2127
+ */
2128
+ // ---------------------------------------------------------------------------
2129
+ // Living Brain traversal commands (T1068)
2130
+ // ---------------------------------------------------------------------------
2131
+ /** cleo nexus full-context — show all 5-substrate context for a code symbol */
2132
+ const fullContextCommand = defineCommand({
2133
+ meta: {
2134
+ name: 'full-context',
2135
+ description: 'Show full Living Brain context for a symbol: NEXUS callers/callees, BRAIN memories, TASKS, sentient proposals, conduit threads',
2136
+ },
2137
+ args: {
2138
+ symbol: {
2139
+ type: 'positional',
2140
+ description: 'Symbol name or nexus node ID',
2141
+ required: true,
2142
+ },
2143
+ json: {
2144
+ type: 'boolean',
2145
+ description: 'Output result as JSON (LAFS envelope format)',
2146
+ },
2147
+ },
2148
+ async run({ args }) {
2149
+ const startTime = Date.now();
2150
+ const jsonOutput = !!args.json;
2151
+ const symbolId = args.symbol;
2152
+ const response = await dispatchRaw('query', 'nexus', 'full-context', { symbol: symbolId });
2153
+ if (!response.success) {
2154
+ process.stderr.write(`[nexus] Error running full-context: ${response.error?.message ?? 'Unknown error'}\n`);
2155
+ process.exitCode = 1;
2156
+ return;
2157
+ }
2158
+ const result = response.data;
2159
+ const durationMs = Date.now() - startTime;
2160
+ if (jsonOutput) {
2161
+ process.stdout.write(JSON.stringify({
2162
+ success: true,
2163
+ data: result,
2164
+ meta: {
2165
+ operation: 'nexus.full-context',
2166
+ duration_ms: durationMs,
2167
+ timestamp: new Date().toISOString(),
2168
+ },
2169
+ }, null, 2) + '\n');
2170
+ return;
2171
+ }
2172
+ process.stdout.write(`\n## Living Brain: ${result.symbolId}\n\n`);
2173
+ process.stdout.write(`### NEXUS\n`);
2174
+ if (!result.nexus) {
2175
+ process.stdout.write(` (no nexus data — run 'cleo nexus analyze' first)\n`);
2176
+ }
2177
+ else {
2178
+ const n = result.nexus;
2179
+ process.stdout.write(` Kind: ${n.kind} File: ${n.filePath ?? '—'}\n`);
2180
+ process.stdout.write(` Callers (${n.callers.length}): ${n.callers
2181
+ .map((c) => c.name)
2182
+ .slice(0, 10)
2183
+ .join(', ') || '—'}\n`);
2184
+ process.stdout.write(` Callees (${n.callees.length}): ${n.callees
2185
+ .map((c) => c.name)
2186
+ .slice(0, 10)
2187
+ .join(', ') || '—'}\n`);
2188
+ process.stdout.write(` Plasticity: w=${result.plasticityWeight.totalWeight.toFixed(2)} edges=${result.plasticityWeight.edgeCount}\n`);
2189
+ }
2190
+ process.stdout.write(`\n### BRAIN memories (${result.brainMemories.length})\n`);
2191
+ for (const m of result.brainMemories.slice(0, 10)) {
2192
+ process.stdout.write(` [${m.nodeType}] ${m.label.slice(0, 80)} (edge=${m.edgeType} w=${m.weight.toFixed(2)})\n`);
2193
+ }
2194
+ if (result.brainMemories.length === 0)
2195
+ process.stdout.write(` (none)\n`);
2196
+ process.stdout.write(`\n### TASKS (${result.tasks.length})\n`);
2197
+ for (const t of result.tasks.slice(0, 10))
2198
+ process.stdout.write(` ${t.taskId} w=${t.weight.toFixed(2)}\n`);
2199
+ if (result.tasks.length === 0)
2200
+ process.stdout.write(` (none)\n`);
2201
+ process.stdout.write(`\n### SENTIENT proposals (${result.sentientProposals.length})\n`);
2202
+ for (const p of result.sentientProposals.slice(0, 5))
2203
+ process.stdout.write(` ${p.title.slice(0, 80)} (w=${p.weight.toFixed(2)})\n`);
2204
+ if (result.sentientProposals.length === 0)
2205
+ process.stdout.write(` (none)\n`);
2206
+ process.stdout.write(`\n### CONDUIT threads (${result.conduitThreads.length})\n`);
2207
+ for (const c of result.conduitThreads.slice(0, 5))
2208
+ process.stdout.write(` ${c.nodeId} w=${c.weight.toFixed(2)}\n`);
2209
+ if (result.conduitThreads.length === 0)
2210
+ process.stdout.write(` (none)\n`);
2211
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2212
+ },
2213
+ });
2214
+ /** cleo nexus task-footprint — show full code impact for a task */
2215
+ const taskFootprintCommand = defineCommand({
2216
+ meta: {
2217
+ name: 'task-footprint',
2218
+ description: 'Show full code impact of a task: files, symbols, blast radius, brain observations, decisions, risk tier',
2219
+ },
2220
+ args: {
2221
+ taskId: {
2222
+ type: 'positional',
2223
+ description: 'Task ID (e.g., T001)',
2224
+ required: true,
2225
+ },
2226
+ json: {
2227
+ type: 'boolean',
2228
+ description: 'Output result as JSON (LAFS envelope format)',
2229
+ },
2230
+ },
2231
+ async run({ args }) {
2232
+ const startTime = Date.now();
2233
+ const jsonOutput = !!args.json;
2234
+ const taskId = args.taskId;
2235
+ const response = await dispatchRaw('query', 'nexus', 'task-footprint', { taskId });
2236
+ if (!response.success) {
2237
+ process.stderr.write(`[nexus] Error running task-footprint: ${response.error?.message ?? 'Unknown error'}\n`);
2238
+ process.exitCode = 1;
2239
+ return;
2240
+ }
2241
+ const result = response.data;
2242
+ const durationMs = Date.now() - startTime;
2243
+ if (jsonOutput) {
2244
+ process.stdout.write(JSON.stringify({
2245
+ success: true,
2246
+ data: result,
2247
+ meta: {
2248
+ operation: 'nexus.task-footprint',
2249
+ duration_ms: durationMs,
2250
+ timestamp: new Date().toISOString(),
2251
+ },
2252
+ }, null, 2) + '\n');
2253
+ return;
2254
+ }
2255
+ process.stdout.write(`\n## Task Code Impact: ${result.taskId}\n\n`);
2256
+ process.stdout.write(`**Risk Score**: ${result.riskScore}\n`);
2257
+ process.stdout.write(`**Files** (${result.files.length}): ${result.files.slice(0, 10).join(', ') || '—'}\n\n`);
2258
+ process.stdout.write(`### Symbols (${result.symbols.length})\n`);
2259
+ for (const s of result.symbols.slice(0, 20)) {
2260
+ process.stdout.write(` [${s.riskLevel}] ${s.label} (${s.kind}) d1=${s.directCallers} total=${s.totalAffected}\n`);
2261
+ }
2262
+ if (result.symbols.length === 0)
2263
+ process.stdout.write(` (none — run 'cleo nexus analyze' or link task to symbols first)\n`);
2264
+ process.stdout.write(`\n### Blast Radius\n`);
2265
+ process.stdout.write(` analyzed=${result.blastRadius.symbolsAnalyzed} total_affected=${result.blastRadius.totalAffected} max_risk=${result.blastRadius.maxRisk}\n`);
2266
+ process.stdout.write(`\n### Brain Observations (${result.brainObservations.length})\n`);
2267
+ for (const o of result.brainObservations.slice(0, 5))
2268
+ process.stdout.write(` [${o.nodeType}] ${o.label.slice(0, 80)}\n`);
2269
+ process.stdout.write(`\n### Decisions (${result.decisions.length})\n`);
2270
+ for (const d of result.decisions.slice(0, 5))
2271
+ process.stdout.write(` [${d.linkType}] ${d.decision.slice(0, 80)}\n`);
2272
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2273
+ },
2274
+ });
2275
+ /** cleo nexus brain-anchors — show code anchors for a brain memory entry */
2276
+ const brainAnchorsCommand = defineCommand({
2277
+ meta: {
2278
+ name: 'brain-anchors',
2279
+ description: 'Show code anchors for a brain memory entry: linked nexus nodes, tasks that touched them, plasticity signal',
2280
+ },
2281
+ args: {
2282
+ entryId: {
2283
+ type: 'positional',
2284
+ description: 'Brain entry node ID (e.g., observation:abc123)',
2285
+ required: true,
2286
+ },
2287
+ json: {
2288
+ type: 'boolean',
2289
+ description: 'Output result as JSON (LAFS envelope format)',
2290
+ },
2291
+ },
2292
+ async run({ args }) {
2293
+ const startTime = Date.now();
2294
+ const jsonOutput = !!args.json;
2295
+ const entryId = args.entryId;
2296
+ const response = await dispatchRaw('query', 'nexus', 'brain-anchors', { entryId });
2297
+ if (!response.success) {
2298
+ process.stderr.write(`[nexus] Error running brain-anchors: ${response.error?.message ?? 'Unknown error'}\n`);
2299
+ process.exitCode = 1;
2300
+ return;
2301
+ }
2302
+ const result = response.data;
2303
+ const durationMs = Date.now() - startTime;
2304
+ if (jsonOutput) {
2305
+ process.stdout.write(JSON.stringify({
2306
+ success: true,
2307
+ data: result,
2308
+ meta: {
2309
+ operation: 'nexus.brain-anchors',
2310
+ duration_ms: durationMs,
2311
+ timestamp: new Date().toISOString(),
2312
+ },
2313
+ }, null, 2) + '\n');
2314
+ return;
2315
+ }
2316
+ process.stdout.write(`\n## Brain Code Anchors: ${result.entryId}\n\n`);
2317
+ process.stdout.write(`**Plasticity Signal**: ${result.plasticitySignal.toFixed(2)}\n\n`);
2318
+ process.stdout.write(`### Nexus Nodes (${result.nexusNodes.length})\n`);
2319
+ for (const n of result.nexusNodes.slice(0, 20)) {
2320
+ process.stdout.write(` [${n.kind}] ${n.label} file=${n.filePath ?? '—'} edge=${n.edgeType} w=${n.weight.toFixed(2)}\n`);
2321
+ }
2322
+ if (result.nexusNodes.length === 0)
2323
+ process.stdout.write(` (none)\n`);
2324
+ process.stdout.write(`\n### Tasks for Nodes (${result.tasksForNodes.length} nodes with task links)\n`);
2325
+ for (const entry of result.tasksForNodes.slice(0, 10)) {
2326
+ const taskList = entry.tasks.map((t) => t.taskId).join(', ');
2327
+ process.stdout.write(` ${entry.nexusNodeId}: ${taskList}\n`);
2328
+ }
2329
+ if (result.tasksForNodes.length === 0)
2330
+ process.stdout.write(` (none)\n`);
2331
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2332
+ },
2333
+ });
2334
+ // ---------------------------------------------------------------------------
2335
+ // Extended Code Reasoning commands (T1069)
2336
+ // ---------------------------------------------------------------------------
2337
+ /** cleo nexus why <symbol> — trace why a code symbol is structured this way */
2338
+ const whyCommand = defineCommand({
2339
+ meta: {
2340
+ name: 'why',
2341
+ description: 'Trace why a code symbol is structured this way: walks BRAIN decisions, observations, and tasks via code_reference+documents+applies_to edges',
2342
+ },
2343
+ args: {
2344
+ symbol: {
2345
+ type: 'positional',
2346
+ description: 'Symbol name or nexus node ID to trace',
2347
+ required: true,
2348
+ },
2349
+ json: {
2350
+ type: 'boolean',
2351
+ description: 'Output result as JSON (LAFS envelope format)',
2352
+ },
2353
+ },
2354
+ async run({ args }) {
2355
+ const startTime = Date.now();
2356
+ const jsonOutput = !!args.json;
2357
+ const symbolId = args.symbol;
2358
+ const response = await dispatchRaw('query', 'nexus', 'why', { symbol: symbolId });
2359
+ if (!response.success) {
2360
+ process.stderr.write(`[nexus] Error running why: ${response.error?.message ?? 'Unknown error'}\n`);
2361
+ process.exitCode = 1;
2362
+ return;
2363
+ }
2364
+ const result = response.data;
2365
+ const durationMs = Date.now() - startTime;
2366
+ if (jsonOutput) {
2367
+ process.stdout.write(JSON.stringify({
2368
+ success: true,
2369
+ data: result,
2370
+ meta: {
2371
+ operation: 'nexus.why',
2372
+ duration_ms: durationMs,
2373
+ timestamp: new Date().toISOString(),
2374
+ },
2375
+ }, null, 2) + '\n');
2376
+ return;
2377
+ }
2378
+ process.stdout.write(`\n## Code Reasoning: ${result.symbolId}\n\n`);
2379
+ process.stdout.write(`**Narrative**: ${result.narrative}\n\n`);
2380
+ process.stdout.write(`### Trace Chain (${result.chain.length} steps)\n`);
2381
+ if (result.chain.length === 0) {
2382
+ process.stdout.write(` (no trace — run 'cleo nexus analyze' and 'cleo memory code-links' first)\n`);
2383
+ }
2384
+ else {
2385
+ for (const step of result.chain) {
2386
+ const refsStr = step.refs.length > 0 ? ` refs=[${step.refs.join(', ')}]` : '';
2387
+ process.stdout.write(` [${step.type}] ${step.id}: ${step.title.slice(0, 80)}${refsStr}\n`);
2388
+ }
2389
+ }
2390
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2391
+ },
2392
+ });
2393
+ /** cleo nexus impact-full <symbol> — merged structural + task + brain impact report */
2394
+ const impactFullCommand = defineCommand({
2395
+ meta: {
2396
+ name: 'impact-full',
2397
+ description: 'Full merged impact report for a code symbol: structural blast radius + open tasks + brain risk notes',
2398
+ },
2399
+ args: {
2400
+ symbol: {
2401
+ type: 'positional',
2402
+ description: 'Symbol name or nexus node ID to analyze',
2403
+ required: true,
2404
+ },
2405
+ json: {
2406
+ type: 'boolean',
2407
+ description: 'Output result as JSON (LAFS envelope format)',
2408
+ },
2409
+ },
2410
+ async run({ args }) {
2411
+ const startTime = Date.now();
2412
+ const jsonOutput = !!args.json;
2413
+ const symbolId = args.symbol;
2414
+ const response = await dispatchRaw('query', 'nexus', 'impact-full', { symbol: symbolId });
2415
+ if (!response.success) {
2416
+ process.stderr.write(`[nexus] Error running impact-full: ${response.error?.message ?? 'Unknown error'}\n`);
2417
+ process.exitCode = 1;
2418
+ return;
2419
+ }
2420
+ const result = response.data;
2421
+ const durationMs = Date.now() - startTime;
2422
+ if (jsonOutput) {
2423
+ process.stdout.write(JSON.stringify({
2424
+ success: true,
2425
+ data: result,
2426
+ meta: {
2427
+ operation: 'nexus.impact-full',
2428
+ duration_ms: durationMs,
2429
+ timestamp: new Date().toISOString(),
2430
+ },
2431
+ }, null, 2) + '\n');
2432
+ return;
2433
+ }
2434
+ process.stdout.write(`\n## Full Impact: ${result.symbolId}\n\n`);
2435
+ process.stdout.write(`**Merged Risk Score**: ${result.mergedRiskScore}\n`);
2436
+ process.stdout.write(`**Narrative**: ${result.narrative}\n\n`);
2437
+ process.stdout.write(`### Structural Blast Radius\n`);
2438
+ process.stdout.write(` d=1 (will break)=${result.structural.directCallers}` +
2439
+ ` d=2 (likely affected)=${result.structural.likelyAffected}` +
2440
+ ` d=3 (may need testing)=${result.structural.mayNeedTesting}` +
2441
+ ` total=${result.structural.totalAffected}` +
2442
+ ` risk=${result.structural.riskLevel}\n`);
2443
+ process.stdout.write(`\n### Open Tasks (${result.openTasks.length})\n`);
2444
+ for (const t of result.openTasks.slice(0, 10)) {
2445
+ process.stdout.write(` ${t.taskId} ${t.label.slice(0, 60)} w=${t.weight.toFixed(2)}\n`);
2446
+ }
2447
+ if (result.openTasks.length === 0)
2448
+ process.stdout.write(` (none)\n`);
2449
+ process.stdout.write(`\n### Brain Risk Notes (${result.brainRiskNotes.length})\n`);
2450
+ for (const n of result.brainRiskNotes.slice(0, 10)) {
2451
+ process.stdout.write(` [${n.nodeType}] ${n.label.slice(0, 70)} edge=${n.edgeType} w=${n.weight.toFixed(2)}\n`);
2452
+ }
2453
+ if (result.brainRiskNotes.length === 0)
2454
+ process.stdout.write(` (none)\n`);
2455
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2456
+ },
2457
+ });
2458
+ // ---------------------------------------------------------------------------
2459
+ // T1071 — conduit-scan: link conduit messages to nexus symbols
2460
+ // ---------------------------------------------------------------------------
2461
+ /**
2462
+ * cleo nexus conduit-scan — Scan conduit messages and link them to nexus symbols.
2463
+ *
2464
+ * Writes `conduit_mentions_symbol` edges to brain_page_edges (idempotent).
2465
+ * Gracefully no-ops when conduit.db or nexus.db is absent.
2466
+ *
2467
+ * @task T1071
2468
+ * @epic T1042
2469
+ */
2470
+ const conduitScanCommand = defineCommand({
2471
+ meta: {
2472
+ name: 'conduit-scan',
2473
+ description: 'Scan conduit messages for symbol mentions and link them to nexus nodes (conduit_mentions_symbol edges)',
2474
+ },
2475
+ args: {
2476
+ json: {
2477
+ type: 'boolean',
2478
+ description: 'Output result as JSON (LAFS envelope format)',
2479
+ },
2480
+ },
2481
+ async run({ args }) {
2482
+ const startTime = Date.now();
2483
+ const jsonOutput = !!args.json;
2484
+ const response = await dispatchRaw('mutate', 'nexus', 'conduit-scan', {});
2485
+ const durationMs = Date.now() - startTime;
2486
+ if (!response.success) {
2487
+ const msg = response.error?.message ?? 'Unknown error';
2488
+ if (jsonOutput) {
2489
+ process.stdout.write(JSON.stringify({
2490
+ success: false,
2491
+ error: { code: response.error?.code ?? 'E_CONDUIT_SCAN_FAILED', message: msg },
2492
+ meta: {
2493
+ operation: 'nexus.conduit-scan',
2494
+ duration_ms: durationMs,
2495
+ timestamp: new Date().toISOString(),
2496
+ },
2497
+ }, null, 2) + '\n');
2498
+ }
2499
+ else {
2500
+ process.stderr.write(`[nexus] Error running conduit-scan: ${msg}\n`);
2501
+ }
2502
+ process.exitCode = 1;
2503
+ return;
2504
+ }
2505
+ const result = response.data;
2506
+ if (jsonOutput) {
2507
+ process.stdout.write(JSON.stringify({
2508
+ success: true,
2509
+ data: result,
2510
+ meta: {
2511
+ operation: 'nexus.conduit-scan',
2512
+ duration_ms: durationMs,
2513
+ timestamp: new Date().toISOString(),
2514
+ },
2515
+ }, null, 2) + '\n');
2516
+ }
2517
+ else {
2518
+ process.stdout.write(`[nexus] conduit-scan complete: scanned=${result.scanned} linked=${result.linked} (${durationMs}ms)\n`);
2519
+ }
2520
+ },
2521
+ });
2522
+ // ---------------------------------------------------------------------------
2523
+ // T1067 — task-symbols: show symbols touched by a task
2524
+ // ---------------------------------------------------------------------------
2525
+ /**
2526
+ * cleo nexus task-symbols <taskId> — Show code symbols touched by a task.
2527
+ *
2528
+ * Forward-lookup (task → symbols) via task_touches_symbol edges.
2529
+ *
2530
+ * @task T1067
2531
+ * @epic T1042
2532
+ */
2533
+ const taskSymbolsCommand = defineCommand({
2534
+ meta: {
2535
+ name: 'task-symbols',
2536
+ description: 'Show code symbols touched by a task (task_touches_symbol forward-lookup)',
2537
+ },
2538
+ args: {
2539
+ taskId: {
2540
+ type: 'positional',
2541
+ description: 'Task ID (e.g., T001)',
2542
+ required: true,
2543
+ },
2544
+ json: {
2545
+ type: 'boolean',
2546
+ description: 'Output result as JSON (LAFS envelope format)',
2547
+ },
2548
+ },
2549
+ async run({ args }) {
2550
+ const startTime = Date.now();
2551
+ const jsonOutput = !!args.json;
2552
+ const taskId = args.taskId;
2553
+ const response = await dispatchRaw('query', 'nexus', 'task-symbols', { taskId });
2554
+ const durationMs = Date.now() - startTime;
2555
+ if (!response.success) {
2556
+ const msg = response.error?.message ?? 'Unknown error';
2557
+ if (jsonOutput) {
2558
+ process.stdout.write(JSON.stringify({
2559
+ success: false,
2560
+ error: { code: response.error?.code ?? 'E_TASK_SYMBOLS_FAILED', message: msg },
2561
+ meta: {
2562
+ operation: 'nexus.task-symbols',
2563
+ duration_ms: durationMs,
2564
+ timestamp: new Date().toISOString(),
2565
+ },
2566
+ }, null, 2) + '\n');
2567
+ }
2568
+ else {
2569
+ process.stderr.write(`[nexus] Error running task-symbols: ${msg}\n`);
2570
+ }
2571
+ process.exitCode = 1;
2572
+ return;
2573
+ }
2574
+ const data = response.data;
2575
+ const { symbols } = data;
2576
+ if (jsonOutput) {
2577
+ process.stdout.write(JSON.stringify({
2578
+ success: true,
2579
+ data: { taskId, count: symbols.length, symbols },
2580
+ meta: {
2581
+ operation: 'nexus.task-symbols',
2582
+ duration_ms: durationMs,
2583
+ timestamp: new Date().toISOString(),
2584
+ },
2585
+ }, null, 2) + '\n');
2586
+ }
2587
+ else {
2588
+ if (symbols.length === 0) {
2589
+ process.stdout.write(`[nexus] No symbols found for task ${taskId}.\n Run 'cleo nexus analyze' and ensure git history is available.\n`);
2590
+ }
2591
+ else {
2592
+ process.stdout.write(`[nexus] Symbols touched by ${taskId} (${symbols.length} total):\n\n`);
2593
+ for (const s of symbols) {
2594
+ process.stdout.write(` [${s.kind.padEnd(12)}] ${s.label.padEnd(50)} w=${s.weight.toFixed(2)} via=${s.matchStrategy}\n`);
2595
+ }
2596
+ }
2597
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2598
+ }
2599
+ },
2600
+ });
2601
+ // ---------------------------------------------------------------------------
2602
+ // T1058 — search-code: BM25 code symbol search against nexus.db
2603
+ // ---------------------------------------------------------------------------
2604
+ /**
2605
+ * cleo nexus search-code <query> — BM25 search of code symbols in nexus.db.
2606
+ *
2607
+ * Uses the same BM25 index as the augment hook. Returns symbol names, kinds,
2608
+ * file paths, and relevance scores.
2609
+ *
2610
+ * @task T1058
2611
+ * @epic T1042
2612
+ */
2613
+ const searchCodeCommand = defineCommand({
2614
+ meta: {
2615
+ name: 'search-code',
2616
+ description: 'BM25 search of code symbols in nexus.db (augment BM25 index)',
2617
+ },
2618
+ args: {
2619
+ query: {
2620
+ type: 'positional',
2621
+ description: 'Search query (symbol name, file pattern, or keyword)',
2622
+ required: true,
2623
+ },
2624
+ limit: {
2625
+ type: 'string',
2626
+ description: 'Max results (default: 10)',
2627
+ default: '10',
2628
+ },
2629
+ json: {
2630
+ type: 'boolean',
2631
+ description: 'Output result as JSON (LAFS envelope format)',
2632
+ },
2633
+ },
2634
+ async run({ args }) {
2635
+ const startTime = Date.now();
2636
+ const jsonOutput = !!args.json;
2637
+ const query = args.query;
2638
+ const limit = parseInt(args.limit, 10) || 10;
2639
+ await dispatchFromCli('query', 'nexus', 'augment', { pattern: query, limit }, { command: 'nexus' });
2640
+ const durationMs = Date.now() - startTime;
2641
+ if (!jsonOutput) {
2642
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2643
+ }
2644
+ },
2645
+ });
2646
+ // ---------------------------------------------------------------------------
2647
+ // T1065 — contracts: contract extraction and compatibility commands
2648
+ // ---------------------------------------------------------------------------
2649
+ /** cleo nexus contracts sync — extract and store contracts from current project */
2650
+ const contractsSyncCommand = defineCommand({
2651
+ meta: {
2652
+ name: 'sync',
2653
+ description: 'Extract contracts (HTTP/gRPC/topic) from the current project and store them',
2654
+ },
2655
+ args: {
2656
+ path: {
2657
+ type: 'positional',
2658
+ description: 'Path to project directory (default: cwd)',
2659
+ required: false,
2660
+ },
2661
+ json: {
2662
+ type: 'boolean',
2663
+ description: 'Output result as JSON (LAFS envelope format)',
2664
+ },
2665
+ 'project-id': {
2666
+ type: 'string',
2667
+ description: 'Override the project ID (default: auto-detected)',
2668
+ },
2669
+ },
2670
+ async run({ args }) {
2671
+ const startTime = Date.now();
2672
+ const jsonOutput = !!args.json;
2673
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
2674
+ const projectIdOverride = args['project-id'];
2675
+ const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
2676
+ const response = await dispatchRaw('mutate', 'nexus', 'contracts-sync', {
2677
+ projectId,
2678
+ repoPath,
2679
+ });
2680
+ const durationMs = Date.now() - startTime;
2681
+ if (!response.success) {
2682
+ const msg = response.error?.message ?? 'Unknown error';
2683
+ if (jsonOutput) {
2684
+ process.stdout.write(JSON.stringify({
2685
+ success: false,
2686
+ error: { code: response.error?.code ?? 'E_CONTRACTS_SYNC_FAILED', message: msg },
2687
+ meta: {
2688
+ operation: 'nexus.contracts.sync',
2689
+ duration_ms: durationMs,
2690
+ timestamp: new Date().toISOString(),
2691
+ },
2692
+ }, null, 2) + '\n');
2693
+ }
2694
+ else {
2695
+ process.stderr.write(`[nexus] Error running contracts sync: ${msg}\n`);
2696
+ }
2697
+ process.exitCode = 1;
2698
+ return;
2699
+ }
2700
+ const result = response.data;
2701
+ if (jsonOutput) {
2702
+ process.stdout.write(JSON.stringify({
2703
+ success: true,
2704
+ data: result,
2705
+ meta: {
2706
+ operation: 'nexus.contracts.sync',
2707
+ duration_ms: durationMs,
2708
+ timestamp: new Date().toISOString(),
2709
+ },
2710
+ }, null, 2) + '\n');
2711
+ }
2712
+ else {
2713
+ process.stdout.write(`[nexus] Contracts extracted from ${projectId}:\n` +
2714
+ ` HTTP: ${result.http}\n` +
2715
+ ` gRPC: ${result.grpc}\n` +
2716
+ ` Topic: ${result.topic}\n` +
2717
+ ` Total: ${result.totalCount}\n` +
2718
+ ` (${durationMs}ms)\n`);
2719
+ }
2720
+ },
2721
+ });
2722
+ /** cleo nexus contracts show — show contract compatibility between two projects */
2723
+ const contractsShowCommand = defineCommand({
2724
+ meta: {
2725
+ name: 'show',
2726
+ description: 'Show contract compatibility matrix between two registered projects',
2727
+ },
2728
+ args: {
2729
+ 'project-a': {
2730
+ type: 'string',
2731
+ description: 'First project name or ID',
2732
+ required: true,
2733
+ },
2734
+ 'project-b': {
2735
+ type: 'string',
2736
+ description: 'Second project name or ID',
2737
+ required: true,
2738
+ },
2739
+ json: {
2740
+ type: 'boolean',
2741
+ description: 'Output result as JSON (LAFS envelope format)',
2742
+ },
2743
+ },
2744
+ async run({ args }) {
2745
+ const startTime = Date.now();
2746
+ const jsonOutput = !!args.json;
2747
+ const projectA = args['project-a'];
2748
+ const projectB = args['project-b'];
2749
+ const response = await dispatchRaw('query', 'nexus', 'contracts-show', { projectA, projectB });
2750
+ const durationMs = Date.now() - startTime;
2751
+ if (!response.success) {
2752
+ const msg = response.error?.message ?? 'Unknown error';
2753
+ if (jsonOutput) {
2754
+ process.stdout.write(JSON.stringify({
2755
+ success: false,
2756
+ error: { code: response.error?.code ?? 'E_CONTRACTS_SHOW_FAILED', message: msg },
2757
+ meta: {
2758
+ operation: 'nexus.contracts.show',
2759
+ duration_ms: durationMs,
2760
+ timestamp: new Date().toISOString(),
2761
+ },
2762
+ }, null, 2) + '\n');
2763
+ }
2764
+ else {
2765
+ process.stderr.write(`[nexus] Error running contracts show: ${msg}\n`);
2766
+ }
2767
+ process.exitCode = 1;
2768
+ return;
2769
+ }
2770
+ const result = response.data;
2771
+ if (jsonOutput) {
2772
+ process.stdout.write(JSON.stringify({
2773
+ success: true,
2774
+ data: result,
2775
+ meta: {
2776
+ operation: 'nexus.contracts.show',
2777
+ duration_ms: durationMs,
2778
+ timestamp: new Date().toISOString(),
2779
+ },
2780
+ }, null, 2) + '\n');
2781
+ }
2782
+ else {
2783
+ if (result.matches.length === 0) {
2784
+ process.stdout.write(`[nexus] No contract matches found between ${projectA} and ${projectB}.\n Run 'cleo nexus contracts sync' on both projects first.\n`);
2785
+ }
2786
+ else {
2787
+ process.stdout.write(`[nexus] Contract compatibility: ${projectA} ↔ ${projectB}\n Compatible: ${result.compatibleCount} Incompatible: ${result.incompatibleCount} Partial: ${result.partialCount}\n Overall: ${result.overallCompatibility}%\n\n`);
2788
+ for (const m of result.matches.slice(0, 20)) {
2789
+ process.stdout.write(` [${m.compatibility.toUpperCase().padEnd(12)}] ${m.contractA.id} ↔ ${m.contractB.id} score=${m.score.toFixed(2)}\n`);
2790
+ }
2791
+ if (result.matches.length > 20) {
2792
+ process.stdout.write(` (showing 20 of ${result.matches.length} matches)\n`);
2793
+ }
2794
+ }
2795
+ process.stdout.write(`\n(${durationMs}ms)\n`);
2796
+ }
2797
+ },
2798
+ });
2799
+ /** cleo nexus contracts link-tasks — link contracts to tasks via task_touches_symbol edges */
2800
+ const contractsLinkTasksCommand = defineCommand({
2801
+ meta: {
2802
+ name: 'link-tasks',
2803
+ description: 'Link extracted contracts to tasks that touch their source symbols',
2804
+ },
2805
+ args: {
2806
+ path: {
2807
+ type: 'positional',
2808
+ description: 'Path to project directory (default: cwd)',
2809
+ required: false,
2810
+ },
2811
+ json: {
2812
+ type: 'boolean',
2813
+ description: 'Output result as JSON (LAFS envelope format)',
2814
+ },
2815
+ },
2816
+ async run({ args }) {
2817
+ const startTime = Date.now();
2818
+ const jsonOutput = !!args.json;
2819
+ const repoPath = args.path ? path.resolve(args.path) : process.cwd();
2820
+ const projectId = Buffer.from(repoPath).toString('base64url').slice(0, 32);
2821
+ const response = await dispatchRaw('mutate', 'nexus', 'contracts-link-tasks', {
2822
+ projectId,
2823
+ repoPath,
2824
+ });
2825
+ const durationMs = Date.now() - startTime;
2826
+ if (!response.success) {
2827
+ const msg = response.error?.message ?? 'Unknown error';
2828
+ if (jsonOutput) {
2829
+ process.stdout.write(JSON.stringify({
2830
+ success: false,
2831
+ error: { code: response.error?.code ?? 'E_CONTRACTS_LINK_FAILED', message: msg },
2832
+ meta: {
2833
+ operation: 'nexus.contracts.link-tasks',
2834
+ duration_ms: durationMs,
2835
+ timestamp: new Date().toISOString(),
2836
+ },
2837
+ }, null, 2) + '\n');
2838
+ }
2839
+ else {
2840
+ process.stderr.write(`[nexus] Error running contracts link-tasks: ${msg}\n`);
2841
+ }
2842
+ process.exitCode = 1;
2843
+ return;
2844
+ }
2845
+ const result = response.data;
2846
+ if (jsonOutput) {
2847
+ process.stdout.write(JSON.stringify({
2848
+ success: true,
2849
+ data: result,
2850
+ meta: {
2851
+ operation: 'nexus.contracts.link-tasks',
2852
+ duration_ms: durationMs,
2853
+ timestamp: new Date().toISOString(),
2854
+ },
2855
+ }, null, 2) + '\n');
2856
+ }
2857
+ else {
2858
+ process.stdout.write(`[nexus] contracts link-tasks:\n` +
2859
+ ` Commits processed: ${result.commitsProcessed}\n` +
2860
+ ` Tasks found: ${result.tasksFound}\n` +
2861
+ ` Edges linked: ${result.linked}\n` +
2862
+ ` Last commit: ${result.lastCommitHash ?? '—'}\n` +
2863
+ ` (${durationMs}ms)\n`);
2864
+ }
2865
+ },
2866
+ });
2867
+ /** cleo nexus contracts — contract extraction and compatibility operations */
2868
+ const contractsCommand = defineCommand({
2869
+ meta: { name: 'contracts', description: 'Contract extraction and compatibility operations' },
2870
+ subCommands: {
2871
+ sync: contractsSyncCommand,
2872
+ show: contractsShowCommand,
2873
+ 'link-tasks': contractsLinkTasksCommand,
2874
+ },
2875
+ });
2876
+ /** cleo nexus group — alias for contracts subcommand (spec parity: T1114) */
2877
+ const groupCommand = defineCommand({
2878
+ meta: {
2879
+ name: 'group',
2880
+ description: 'Contract extraction and compatibility operations (alias for contracts)',
2881
+ },
2882
+ subCommands: {
2883
+ sync: contractsSyncCommand,
2884
+ show: contractsShowCommand,
2885
+ 'link-tasks': contractsLinkTasksCommand,
2886
+ },
2887
+ });
2888
+ /** cleo nexus wiki — community-grouped wiki index with optional LOOM LLM summaries */
2889
+ const wikiCommand = defineCommand({
2890
+ meta: {
2891
+ name: 'wiki',
2892
+ description: 'Generate community-grouped wiki index from nexus code graph',
2893
+ },
2894
+ args: {
2895
+ output: {
2896
+ type: 'string',
2897
+ description: 'Output directory for wiki files (default: .cleo/wiki)',
2898
+ alias: 'o',
2899
+ },
2900
+ community: {
2901
+ type: 'string',
2902
+ description: 'Filter generation to a single community ID (e.g. "community:3")',
2903
+ alias: 'c',
2904
+ },
2905
+ incremental: {
2906
+ type: 'boolean',
2907
+ description: 'Only regenerate communities whose symbols changed since last wiki run (uses .cleo/wiki-state.json)',
2908
+ },
2909
+ json: {
2910
+ type: 'boolean',
2911
+ description: 'Output result as JSON (LAFS envelope format)',
2912
+ },
2913
+ },
2914
+ async run({ args }) {
2915
+ const startTime = Date.now();
2916
+ const jsonOutput = !!args.json;
2917
+ const outputDir = args.output ?? path.join(process.cwd(), '.cleo', 'wiki');
2918
+ const communityFilter = args.community ?? undefined;
2919
+ const isIncremental = !!args.incremental;
2920
+ // SSoT-EXEMPT:loom-provider — LLM backend resolution for wiki generation requires
2921
+ // CLI-side async provider wiring that cannot be passed through the dispatch layer.
2922
+ // The dispatch 'wiki' op always uses loomProvider=null (scaffold mode). CLI-side
2923
+ // wiring enables real LLM narratives when a backend is available.
2924
+ // Resolve LOOM provider via the existing LLM backend resolver (warm tier).
2925
+ // Falls back gracefully — null means scaffold mode.
2926
+ // The 'ai' package lives in @cleocode/core's deps; we load it transitively.
2927
+ let loomProvider = null;
2928
+ try {
2929
+ const { resolveLlmBackend } = await import('@cleocode/core/memory/llm-backend-resolver.js');
2930
+ const backend = await resolveLlmBackend('warm');
2931
+ if (backend !== null && backend.name !== 'transformers') {
2932
+ // Wire as a simple text-completion function using the 'ai' package
2933
+ // loaded via @cleocode/core's node_modules (avoids duplicate dep in cleo).
2934
+ loomProvider = async (prompt) => {
2935
+ // Dynamic import at call time to avoid top-level resolution in cleo
2936
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2937
+ const aiMod = await import('ai');
2938
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
2939
+ const generateTextFn = aiMod.generateText;
2940
+ const { text } = await generateTextFn({
2941
+ model: backend.model,
2942
+ prompt,
2943
+ maxTokens: 256,
2944
+ });
2945
+ return text;
2946
+ };
2947
+ }
2948
+ }
2949
+ catch {
2950
+ // LOOM unavailable — scaffold mode (logged inside generateNexusWikiIndex)
2951
+ loomProvider = null;
2952
+ }
2953
+ try {
2954
+ // SSoT-EXEMPT:loom-provider — must call generateNexusWikiIndex directly to pass
2955
+ // loomProvider. The dispatch 'wiki' op does not accept a loomProvider param.
2956
+ const { generateNexusWikiIndex } = await import('@cleocode/core/nexus/wiki-index.js');
2957
+ const result = await generateNexusWikiIndex(outputDir, process.cwd(), {
2958
+ communityFilter,
2959
+ incremental: isIncremental,
2960
+ loomProvider,
2961
+ projectRoot: process.cwd(),
2962
+ });
2963
+ const durationMs = Date.now() - startTime;
2964
+ if (jsonOutput) {
2965
+ process.stdout.write(JSON.stringify({
2966
+ success: result.success,
2967
+ data: result,
2968
+ meta: {
2969
+ operation: 'nexus.wiki',
2970
+ duration_ms: durationMs,
2971
+ timestamp: new Date().toISOString(),
2972
+ },
2973
+ }, null, 2) + '\n');
2974
+ }
2975
+ else {
2976
+ if (result.success) {
2977
+ const skippedNote = result.skippedCommunities && result.skippedCommunities.length > 0
2978
+ ? `\n Skipped: ${result.skippedCommunities.length} unchanged communities`
2979
+ : '';
2980
+ const loomNote = result.loomEnabled ? ' (LOOM narratives enabled)' : ' (scaffold mode)';
2981
+ process.stdout.write(`[nexus] wiki generated${loomNote}:\n` +
2982
+ ` Communities: ${result.communityCount}\n` +
2983
+ ` Files: ${result.fileCount}\n` +
2984
+ ` Output: ${outputDir}` +
2985
+ skippedNote +
2986
+ `\n (${durationMs}ms)\n`);
2987
+ }
2988
+ else {
2989
+ process.stderr.write(`[nexus] wiki generation failed: ${result.error}\n`);
2990
+ process.exitCode = 1;
2991
+ }
2992
+ }
2993
+ }
2994
+ catch (err) {
2995
+ const msg = err instanceof Error ? err.message : String(err);
2996
+ if (jsonOutput) {
2997
+ process.stdout.write(JSON.stringify({
2998
+ success: false,
2999
+ error: { code: 'E_WIKI_GENERATION_FAILED', message: msg },
3000
+ meta: {
3001
+ operation: 'nexus.wiki',
3002
+ duration_ms: Date.now() - startTime,
3003
+ timestamp: new Date().toISOString(),
3004
+ },
3005
+ }, null, 2) + '\n');
3006
+ }
3007
+ else {
3008
+ process.stderr.write(`[nexus] Error generating wiki: ${msg}\n`);
3009
+ }
3010
+ process.exitCode = 1;
3011
+ }
3012
+ },
3013
+ });
3014
+ // ---------------------------------------------------------------------------
3015
+ // T1108 — Plasticity Query Commands (hot-paths, hot-nodes, cold-symbols)
3016
+ // ---------------------------------------------------------------------------
3017
+ /**
3018
+ * cleo nexus hot-paths — List highest-weight relation edges (Hebbian plasticity).
3019
+ *
3020
+ * Reads nexus_relations ORDER BY weight DESC, co_accessed_count DESC.
3021
+ * If no dream cycle has run yet (all weights 0), prints an informational
3022
+ * note and exits cleanly with an empty table.
3023
+ *
3024
+ * @task T1108
3025
+ */
3026
+ const hotPathsCommand = defineCommand({
3027
+ meta: {
3028
+ name: 'hot-paths',
3029
+ description: 'List highest-weight relation edges by Hebbian plasticity weight',
3030
+ },
3031
+ args: {
3032
+ limit: {
3033
+ type: 'string',
3034
+ description: 'Maximum number of edges to return (default: 20)',
3035
+ default: '20',
3036
+ },
3037
+ json: {
3038
+ type: 'boolean',
3039
+ description: 'Output raw JSON',
3040
+ default: false,
3041
+ },
3042
+ },
3043
+ async run({ args }) {
3044
+ const limit = Number.parseInt(args.limit, 10) || 20;
3045
+ const jsonOutput = args.json;
3046
+ const startTime = Date.now();
3047
+ const response = await dispatchRaw('query', 'nexus', 'hot-paths', { limit });
3048
+ const durationMs = Date.now() - startTime;
3049
+ if (!response.success) {
3050
+ process.stderr.write(`[nexus hot-paths] Error: ${response.error?.message ?? 'Unknown error'}\n`);
3051
+ process.exitCode = 1;
3052
+ return;
3053
+ }
3054
+ const result = response.data;
3055
+ if (jsonOutput) {
3056
+ process.stdout.write(JSON.stringify({
3057
+ success: true,
3058
+ data: result,
3059
+ meta: {
3060
+ operation: 'nexus.hot-paths',
3061
+ duration_ms: durationMs,
3062
+ timestamp: new Date().toISOString(),
3063
+ },
3064
+ }, null, 2) + '\n');
3065
+ return;
3066
+ }
3067
+ if (result.note) {
3068
+ process.stdout.write(`[nexus] Note: ${result.note}\n`);
3069
+ }
3070
+ if (result.paths.length === 0) {
3071
+ process.stdout.write('[nexus] No hot paths found.\n');
3072
+ return;
3073
+ }
3074
+ process.stdout.write('| Source | Target | Edge Type | Weight | Co-Access |\n| --- | --- | --- | --- | --- |\n');
3075
+ for (const p of result.paths) {
3076
+ process.stdout.write(`| ${p.sourceId} | ${p.targetId} | ${p.type} | ${p.weight.toFixed(4)} | ${p.coAccessedCount} |\n`);
3077
+ }
3078
+ process.stdout.write(`\n${result.count} edge(s) shown.\n`);
3079
+ },
3080
+ });
3081
+ /**
3082
+ * cleo nexus hot-nodes — List nodes with the highest aggregate Hebbian weight.
3083
+ *
3084
+ * Aggregates SUM(weight) per source node in nexus_relations, then joins
3085
+ * nexus_nodes for label/kind/file. If no dream cycle has run yet the table
3086
+ * is empty and an informational note is printed.
3087
+ *
3088
+ * @task T1108
3089
+ */
3090
+ const hotNodesCommand = defineCommand({
3091
+ meta: {
3092
+ name: 'hot-nodes',
3093
+ description: 'List symbols with highest aggregate Hebbian weight',
3094
+ },
3095
+ args: {
3096
+ limit: {
3097
+ type: 'string',
3098
+ description: 'Maximum number of nodes to return (default: 20)',
3099
+ default: '20',
3100
+ },
3101
+ json: {
3102
+ type: 'boolean',
3103
+ description: 'Output raw JSON',
3104
+ default: false,
3105
+ },
3106
+ },
3107
+ async run({ args }) {
3108
+ const limit = Number.parseInt(args.limit, 10) || 20;
3109
+ const jsonOutput = args.json;
3110
+ const startTime = Date.now();
3111
+ const response = await dispatchRaw('query', 'nexus', 'hot-nodes', { limit });
3112
+ const durationMs = Date.now() - startTime;
3113
+ if (!response.success) {
3114
+ process.stderr.write(`[nexus hot-nodes] Error: ${response.error?.message ?? 'Unknown error'}\n`);
3115
+ process.exitCode = 1;
3116
+ return;
3117
+ }
3118
+ const result = response.data;
3119
+ if (jsonOutput) {
3120
+ process.stdout.write(JSON.stringify({
3121
+ success: true,
3122
+ data: result,
3123
+ meta: {
3124
+ operation: 'nexus.hot-nodes',
3125
+ duration_ms: durationMs,
3126
+ timestamp: new Date().toISOString(),
3127
+ },
3128
+ }, null, 2) + '\n');
3129
+ return;
3130
+ }
3131
+ if (result.note) {
3132
+ process.stdout.write(`[nexus] Note: ${result.note}\n`);
3133
+ }
3134
+ if (result.nodes.length === 0) {
3135
+ process.stdout.write('[nexus] No hot nodes found.\n');
3136
+ return;
3137
+ }
3138
+ process.stdout.write('| Symbol | Total Weight | File | Kind |\n| --- | --- | --- | --- |\n');
3139
+ for (const n of result.nodes) {
3140
+ const file = n.filePath ?? '(unknown)';
3141
+ process.stdout.write(`| ${n.label} | ${n.totalWeight.toFixed(4)} | ${file} | ${n.kind} |\n`);
3142
+ }
3143
+ process.stdout.write(`\n${result.count} node(s) shown.\n`);
3144
+ },
3145
+ });
3146
+ /**
3147
+ * cleo nexus cold-symbols — List symbols that have gone cold.
3148
+ *
3149
+ * Returns symbols whose most-recent access (max last_accessed_at across
3150
+ * incident edges) is older than `--days` ago AND max weight < 0.1.
3151
+ * If last_accessed_at is NULL for all incident edges (no dream cycle run)
3152
+ * those symbols are included as infinitely cold.
3153
+ *
3154
+ * @task T1108
3155
+ */
3156
+ const coldSymbolsCommand = defineCommand({
3157
+ meta: {
3158
+ name: 'cold-symbols',
3159
+ description: 'List cold symbols (stale access + low weight) for pruning candidates',
3160
+ },
3161
+ args: {
3162
+ days: {
3163
+ type: 'string',
3164
+ description: 'Age threshold in days (default: 30)',
3165
+ default: '30',
3166
+ },
3167
+ json: {
3168
+ type: 'boolean',
3169
+ description: 'Output raw JSON',
3170
+ default: false,
3171
+ },
3172
+ },
3173
+ async run({ args }) {
3174
+ const thresholdDays = Number.parseInt(args.days, 10) || 30;
3175
+ const jsonOutput = args.json;
3176
+ const startTime = Date.now();
3177
+ const response = await dispatchRaw('query', 'nexus', 'cold-symbols', { days: thresholdDays });
3178
+ const durationMs = Date.now() - startTime;
3179
+ if (!response.success) {
3180
+ process.stderr.write(`[nexus cold-symbols] Error: ${response.error?.message ?? 'Unknown error'}\n`);
3181
+ process.exitCode = 1;
3182
+ return;
3183
+ }
3184
+ const result = response.data;
3185
+ if (jsonOutput) {
3186
+ process.stdout.write(JSON.stringify({
3187
+ success: true,
3188
+ data: result,
3189
+ meta: {
3190
+ operation: 'nexus.cold-symbols',
3191
+ duration_ms: durationMs,
3192
+ timestamp: new Date().toISOString(),
3193
+ },
3194
+ }, null, 2) + '\n');
3195
+ return;
3196
+ }
3197
+ if (result.note) {
3198
+ process.stdout.write(`[nexus] Note: ${result.note}\n`);
3199
+ }
3200
+ if (result.symbols.length === 0) {
3201
+ process.stdout.write(`[nexus] No cold symbols found (threshold: ${thresholdDays} days, weight < 0.1).\n`);
3202
+ return;
3203
+ }
3204
+ process.stdout.write('| Symbol | Last Accessed | Weight | File |\n| --- | --- | --- | --- |\n');
3205
+ for (const s of result.symbols) {
3206
+ const lastAccessed = s.lastAccessed ?? '(never)';
3207
+ const file = s.filePath ?? '(unknown)';
3208
+ process.stdout.write(`| ${s.label} | ${lastAccessed} | ${s.maxWeight.toFixed(4)} | ${file} |\n`);
3209
+ }
3210
+ process.stdout.write(`\n${result.count} cold symbol(s) found (threshold: ${thresholdDays} days).\n`);
3211
+ },
3212
+ });
3213
+ /**
3214
+ * cleo nexus top-entries — List top-weighted symbols from nexus_relations.
3215
+ *
3216
+ * Returns the highest-weighted source nodes from the Hebbian plasticity
3217
+ * relation graph (T998). Each entry is aggregated SUM(weight) per source_id
3218
+ * joined with nexus_nodes for label / kind / file-path. Supports optional
3219
+ * `--kind` filter (e.g. function, method, class) and `--limit` (default 20).
3220
+ *
3221
+ * Routes through the dispatch layer so all transports (CLI, TUI, agents) see
3222
+ * the same LAFS envelope shape (see `handleTopEntries` in
3223
+ * `packages/cleo/src/dispatch/domains/nexus.ts`).
3224
+ *
3225
+ * @task T1013
3226
+ * @epic T1006
3227
+ */
3228
+ // ── T1386: sigil sync + list ─────────────────────────────────────────
3229
+ /** cleo nexus sigil sync — populate sigils table from canonical CANT agents */
3230
+ const sigilSyncCommand = defineCommand({
3231
+ meta: {
3232
+ name: 'sync',
3233
+ description: 'Populate the nexus.db sigils table with one row per canonical CANT agent (cleo-subagent + 5 seed roles + 2 meta agents). Idempotent.',
3234
+ },
3235
+ args: {
3236
+ json: {
3237
+ type: 'boolean',
3238
+ description: 'Output as JSON (LAFS envelope format)',
3239
+ },
3240
+ },
3241
+ async run() {
3242
+ await dispatchFromCli('mutate', 'nexus', 'sigil.sync', {}, { command: 'nexus' });
3243
+ },
3244
+ });
3245
+ /** cleo nexus sigil list — list every sigil currently stored in nexus.db */
3246
+ const sigilListCommand = defineCommand({
3247
+ meta: {
3248
+ name: 'list',
3249
+ description: 'List every sigil currently stored in nexus.db, optionally filtered by role.',
3250
+ },
3251
+ args: {
3252
+ role: {
3253
+ type: 'string',
3254
+ description: 'Filter by role (e.g. "orchestrator", "lead", "worker", "specialist", "subagent")',
3255
+ },
3256
+ },
3257
+ async run({ args }) {
3258
+ await dispatchFromCli('query', 'nexus', 'sigil.list', { role: args.role }, { command: 'nexus' });
3259
+ },
3260
+ });
3261
+ /** cleo nexus sigil — group alias for `sync` and `list`. */
3262
+ const sigilCommand = defineCommand({
3263
+ meta: {
3264
+ name: 'sigil',
3265
+ description: 'Sigil (peer-card) operations — sync from canonical CANT agents, list current rows',
3266
+ },
3267
+ subCommands: {
3268
+ sync: sigilSyncCommand,
3269
+ list: sigilListCommand,
3270
+ },
3271
+ });
3272
+ const topEntriesCommand = defineCommand({
3273
+ meta: {
3274
+ name: 'top-entries',
3275
+ description: 'List top-weighted symbols from nexus_relations by weight DESC',
3276
+ },
3277
+ args: {
3278
+ limit: {
3279
+ type: 'string',
3280
+ description: 'Maximum number of entries to return (default: 20)',
3281
+ default: '20',
3282
+ },
3283
+ kind: {
3284
+ type: 'string',
3285
+ description: 'Filter by nexus_nodes.kind (e.g. function, method, class, interface, type_alias)',
3286
+ },
3287
+ json: {
3288
+ type: 'boolean',
3289
+ description: 'Output result as JSON (LAFS envelope format)',
3290
+ },
3291
+ },
3292
+ async run({ args }) {
3293
+ const limit = Number.parseInt(args.limit, 10) || 20;
3294
+ const kind = args.kind ?? undefined;
3295
+ const jsonOutput = !!args.json;
3296
+ const params = { limit };
3297
+ if (kind !== undefined && kind.length > 0)
3298
+ params.kind = kind;
3299
+ await dispatchFromCli('query', 'nexus', 'top-entries', params, {
3300
+ command: 'nexus',
3301
+ operation: 'nexus.top-entries',
3302
+ ...(jsonOutput ? { json: true } : {}),
3303
+ });
3304
+ },
3305
+ });
3306
+ export const nexusCommand = defineCommand({
3307
+ meta: { name: 'nexus', description: 'Cross-project NEXUS operations' },
3308
+ subCommands: {
3309
+ init: initCommand,
3310
+ register: registerCommand,
3311
+ unregister: unregisterCommand,
3312
+ list: listCommand,
3313
+ status: statusCommand,
3314
+ show: showCommand,
3315
+ resolve: resolveCommand,
3316
+ discover: discoverCommand,
3317
+ search: searchCommand,
3318
+ augment: augmentCommand,
3319
+ setup: setupCommand,
3320
+ deps: depsCommand,
3321
+ 'critical-path': criticalPathCommand,
3322
+ blocking: blockingCommand,
3323
+ orphans: orphansCommand,
3324
+ sync: syncCommand,
3325
+ reconcile: reconcileCommand,
3326
+ graph: graphCommand,
3327
+ 'share-status': shareStatusCommand,
3328
+ 'transfer-preview': transferPreviewCommand,
3329
+ transfer: transferCommand,
3330
+ permission: permissionCommand,
3331
+ share: shareCommand,
3332
+ clusters: clustersCommand,
3333
+ flows: flowsCommand,
3334
+ context: contextCommand,
3335
+ impact: impactCommand,
3336
+ analyze: analyzeCommand,
3337
+ query: queryCommand,
3338
+ projects: projectsCommand,
3339
+ 'refresh-bridge': refreshBridgeCommand,
3340
+ export: exportCommand,
3341
+ diff: diffCommand,
3342
+ 'route-map': routeMapCommand,
3343
+ 'shape-check': shapeCheckCommand,
3344
+ 'full-context': fullContextCommand,
3345
+ 'task-footprint': taskFootprintCommand,
3346
+ 'brain-anchors': brainAnchorsCommand,
3347
+ why: whyCommand,
3348
+ 'impact-full': impactFullCommand,
3349
+ // T1071 — conduit scan
3350
+ 'conduit-scan': conduitScanCommand,
3351
+ // T1067 — task symbols
3352
+ 'task-symbols': taskSymbolsCommand,
3353
+ // T1058 — code symbol search
3354
+ 'search-code': searchCodeCommand,
3355
+ // T1065 — contract registry
3356
+ contracts: contractsCommand,
3357
+ // T1114 — group alias for contracts
3358
+ group: groupCommand,
3359
+ // T1060 — wiki index
3360
+ wiki: wikiCommand,
3361
+ // T1108 — plasticity queries
3362
+ 'hot-paths': hotPathsCommand,
3363
+ 'hot-nodes': hotNodesCommand,
3364
+ 'cold-symbols': coldSymbolsCommand,
3365
+ // T1013 / T1006 — top-weighted symbols by nexus_relations.weight
3366
+ 'top-entries': topEntriesCommand,
3367
+ // T1386 — sigil sync + list (canonical CANT agent peer cards)
3368
+ sigil: sigilCommand,
3369
+ },
3370
+ async run({ cmd, rawArgs }) {
3371
+ const firstArg = rawArgs?.find((a) => !a.startsWith('-'));
3372
+ if (firstArg && cmd.subCommands && firstArg in cmd.subCommands)
3373
+ return;
3374
+ await showUsage(cmd);
3375
+ },
3376
+ });
3377
+ //# sourceMappingURL=nexus.js.map