@cleocode/cleo 2026.10.2 → 2026.10.4

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 (307) hide show
  1. package/bin/cleo.js +11 -1
  2. package/dist/cli/adapter-LVXHFBC4.js +158 -0
  3. package/dist/cli/add-WUAV7LDT.js +443 -0
  4. package/dist/cli/add-batch-U2DLKAQC.js +163 -0
  5. package/dist/cli/admin-I7BQYVZD.js +340 -0
  6. package/dist/cli/adr-K2THMQBS.js +171 -0
  7. package/dist/cli/agent-WQ6XY2DW.js +2366 -0
  8. package/dist/cli/agent-outputs-BJIYLVTU.js +84 -0
  9. package/dist/cli/analyze-PGQZWGOC.js +48 -0
  10. package/dist/cli/archive-5LZPF7C3.js +64 -0
  11. package/dist/cli/archive-stats-U6CYC6JM.js +100 -0
  12. package/dist/cli/attention-SOURWCNI.js +167 -0
  13. package/dist/cli/audit-FO2Y4LH2.js +122 -0
  14. package/dist/cli/auth-ED7TAIXI.js +491 -0
  15. package/dist/cli/backfill-32TRAYRD.js +156 -0
  16. package/dist/cli/backup-LEJMZJKL.js +587 -0
  17. package/dist/cli/backup-inspect-6HPLUEI2.js +26 -0
  18. package/dist/cli/backup-recover-2BTYBZU2.js +29 -0
  19. package/dist/cli/blockers-5JULUJTV.js +54 -0
  20. package/dist/cli/brain-273N3FW4.js +400 -0
  21. package/dist/cli/briefing-7H6OLECX.js +212 -0
  22. package/dist/cli/caamp-MFQVN6VU.js +181 -0
  23. package/dist/cli/cancel-SCMJTXZB.js +84 -0
  24. package/dist/cli/canon-NPF5RODM.js +142 -0
  25. package/dist/cli/canon-docs-2GTOLF7Y.js +26 -0
  26. package/dist/cli/cant-46XCUP4P.js +239 -0
  27. package/dist/cli/changeset-32NMBGG2.js +248 -0
  28. package/dist/cli/check-RWJLBCI2.js +907 -0
  29. package/dist/cli/checkpoint-37HMMKD7.js +128 -0
  30. package/dist/cli/chunk-2JIJD2I7.js +108 -0
  31. package/dist/cli/chunk-37NU2XDP.js +171 -0
  32. package/dist/cli/chunk-3IOQVUO7.js +17308 -0
  33. package/dist/cli/chunk-3PGH67MT.js +175 -0
  34. package/dist/cli/chunk-3ZO3M37V.js +1002 -0
  35. package/dist/cli/chunk-47JYZAMS.js +30 -0
  36. package/dist/cli/chunk-5J2VH3BC.js +66 -0
  37. package/dist/cli/chunk-5ZFFUFH7.js +92 -0
  38. package/dist/cli/chunk-6JSJNYH2.js +114 -0
  39. package/dist/cli/chunk-7INMKEAD.js +85 -0
  40. package/dist/cli/chunk-A2IUEIM5.js +278 -0
  41. package/dist/cli/chunk-AWCQH2W5.js +35 -0
  42. package/dist/cli/chunk-AYA6F4ZT.js +56 -0
  43. package/dist/cli/chunk-BCEXRFA2.js +76 -0
  44. package/dist/cli/chunk-BPEVD37G.js +124 -0
  45. package/dist/cli/chunk-C3B7C43W.js +16 -0
  46. package/dist/cli/chunk-DVTPIZJM.js +72 -0
  47. package/dist/cli/chunk-DYABOIHB.js +96 -0
  48. package/dist/cli/chunk-EBRZ76HS.js +51 -0
  49. package/dist/cli/chunk-EGOTK2HA.js +57 -0
  50. package/dist/cli/chunk-EOPQFCSR.js +148 -0
  51. package/dist/cli/chunk-FORFDPP5.js +288 -0
  52. package/dist/cli/chunk-GFGLLDXX.js +110 -0
  53. package/dist/cli/chunk-GH37QXW5.js +280 -0
  54. package/dist/cli/chunk-GZFVDR44.js +320 -0
  55. package/dist/cli/chunk-I3CRQQAD.js +225 -0
  56. package/dist/cli/chunk-J3ZFM3UQ.js +754 -0
  57. package/dist/cli/chunk-JNZJPIPJ.js +90 -0
  58. package/dist/cli/chunk-KHB52JNB.js +209 -0
  59. package/dist/cli/chunk-KJDWWQFY.js +46 -0
  60. package/dist/cli/chunk-LKNUA3SB.js +83 -0
  61. package/dist/cli/chunk-LVGIFMCV.js +163 -0
  62. package/dist/cli/chunk-LWQBJQSE.js +67 -0
  63. package/dist/cli/chunk-MNJRLSEQ.js +107 -0
  64. package/dist/cli/chunk-NRKWJLMS.js +91 -0
  65. package/dist/cli/chunk-NSHV2JNM.js +48 -0
  66. package/dist/cli/chunk-NWTATTEQ.js +210 -0
  67. package/dist/cli/chunk-OAPN46TC.js +89 -0
  68. package/dist/cli/chunk-OGV57L4J.js +59 -0
  69. package/dist/cli/chunk-OILHT47L.js +252 -0
  70. package/dist/cli/chunk-OPTEQKBB.js +258 -0
  71. package/dist/cli/chunk-PKKZPOOP.js +352 -0
  72. package/dist/cli/chunk-QA6T2LQ5.js +71 -0
  73. package/dist/cli/chunk-QFFQSKRC.js +4497 -0
  74. package/dist/cli/chunk-QPUY2HQZ.js +74 -0
  75. package/dist/cli/chunk-REUTEW3O.js +258 -0
  76. package/dist/cli/chunk-S24YI723.js +88 -0
  77. package/dist/cli/chunk-SXXOC6KZ.js +209 -0
  78. package/dist/cli/chunk-ULN4OKQQ.js +259 -0
  79. package/dist/cli/chunk-V5GBGOGM.js +46 -0
  80. package/dist/cli/chunk-VLEYOOPH.js +31 -0
  81. package/dist/cli/chunk-W33Q3FBH.js +66 -0
  82. package/dist/cli/chunk-W3JLYKKY.js +140 -0
  83. package/dist/cli/chunk-XRAX6XFP.js +48 -0
  84. package/dist/cli/chunk-YGKEECTI.js +78 -0
  85. package/dist/cli/chunk-YUZJI67I.js +108 -0
  86. package/dist/cli/chunk-YY66LFZF.js +29 -0
  87. package/dist/cli/chunk-ZBISIPCK.js +78 -0
  88. package/dist/cli/chunk-ZZTHTMQP.js +77 -0
  89. package/dist/cli/claim-KPENYHIQ.js +96 -0
  90. package/dist/cli/classify-DRVMCFQU.js +117 -0
  91. package/dist/cli/cli-T3CR7J57.js +48 -0
  92. package/dist/cli/cloud-PPQ4O5TX.js +565 -0
  93. package/dist/cli/cockpit-RZKLGYPN.js +790 -0
  94. package/dist/cli/code-Z5CTMVTD.js +178 -0
  95. package/dist/cli/complete-UBOCOBRB.js +34 -0
  96. package/dist/cli/complexity-BV2AGQRZ.js +56 -0
  97. package/dist/cli/compliance-32PD5Y47.js +276 -0
  98. package/dist/cli/conduit-VDKCH33F.js +307 -0
  99. package/dist/cli/config-I72JAXK4.js +516 -0
  100. package/dist/cli/consensus-LFILLSTK.js +121 -0
  101. package/dist/cli/context-XUUVFVTP.js +141 -0
  102. package/dist/cli/contribution-37NQ4N5R.js +111 -0
  103. package/dist/cli/curator-TFDXU2EX.js +139 -0
  104. package/dist/cli/current-C4SN5BWV.js +42 -0
  105. package/dist/cli/daemon-DV25JQ62.js +451 -0
  106. package/dist/cli/dash-TFU4RLQW.js +70 -0
  107. package/dist/cli/decide-5VPMNTSI.js +419 -0
  108. package/dist/cli/decompose-KOYEZNJL.js +77 -0
  109. package/dist/cli/decomposition-7OHUFIQN.js +121 -0
  110. package/dist/cli/delete-Q7YCAFY5.js +68 -0
  111. package/dist/cli/deps-6UZKLDGJ.js +463 -0
  112. package/dist/cli/detect-FERY35UL.js +45 -0
  113. package/dist/cli/detect-drift-UL2JTPUK.js +408 -0
  114. package/dist/cli/diagnostics-TI5QAZXR.js +132 -0
  115. package/dist/cli/docs-QI2PRN3T.js +3095 -0
  116. package/dist/cli/doctor-AX5TICQO.js +1253 -0
  117. package/dist/cli/doctor-ac-bindings-YPMYHU2G.js +26 -0
  118. package/dist/cli/doctor-acceptance-drift-PYNFGMKB.js +26 -0
  119. package/dist/cli/doctor-credentials-UZRIADKM.js +26 -0
  120. package/dist/cli/doctor-db-substrate-Q2TOYM2S.js +27 -0
  121. package/dist/cli/doctor-dep-cycles-GCVYZY6F.js +26 -0
  122. package/dist/cli/doctor-exodus-RO5SUTC2.js +26 -0
  123. package/dist/cli/doctor-exodus-residue-EM2AWQXP.js +26 -0
  124. package/dist/cli/doctor-fk-check-Q3FOLECE.js +26 -0
  125. package/dist/cli/doctor-global-delivery-TNOAQ3NP.js +26 -0
  126. package/dist/cli/doctor-heavy-command-hook-IO3QAQLG.js +26 -0
  127. package/dist/cli/doctor-legacy-backups-O2YH5VLS.js +26 -0
  128. package/dist/cli/doctor-legacy-reaper-VSEJEIFA.js +26 -0
  129. package/dist/cli/doctor-malformed-ids-LQ766V5K.js +26 -0
  130. package/dist/cli/doctor-manifest-rows-6FQDNHLH.js +26 -0
  131. package/dist/cli/doctor-memory-guard-J4PSEKB5.js +26 -0
  132. package/dist/cli/doctor-migrations-ONOH56YM.js +26 -0
  133. package/dist/cli/doctor-nexus-residency-FUQAX7PV.js +26 -0
  134. package/dist/cli/doctor-project-identity-GUDK3HYX.js +26 -0
  135. package/dist/cli/doctor-projects-7L3BNL4O.js +30 -0
  136. package/dist/cli/doctor-projects-registry-TEAVHFQU.js +26 -0
  137. package/dist/cli/doctor-release-readiness-IEGHX6SL.js +26 -0
  138. package/dist/cli/doctor-repair-NBONOSZU.js +26 -0
  139. package/dist/cli/doctor-skill-fixtures-7Y6L34A3.js +26 -0
  140. package/dist/cli/doctor-split-brain-TUKIGVHF.js +26 -0
  141. package/dist/cli/doctor-superseded-store-BHZY2B2L.js +26 -0
  142. package/dist/cli/doctor-tool-locks-REQMIVYK.js +26 -0
  143. package/dist/cli/doctor-twin-collapse-222GOSPE.js +26 -0
  144. package/dist/cli/doctor-worktree-stores-J7TCRVJ3.js +26 -0
  145. package/dist/cli/done-V3AOO65B.js +195 -0
  146. package/dist/cli/dynamic-RR4HB7BB.js +29 -0
  147. package/dist/cli/event-EGNPGE5A.js +372 -0
  148. package/dist/cli/exists-H4SDCBPL.js +65 -0
  149. package/dist/cli/exodus-KALO3B3X.js +401 -0
  150. package/dist/cli/export-ROFOCG4M.js +92 -0
  151. package/dist/cli/export-tasks-US3WBIEQ.js +96 -0
  152. package/dist/cli/federation-SUIB5QWT.js +145 -0
  153. package/dist/cli/find-YICG4BG6.js +177 -0
  154. package/dist/cli/focus-TKCZPKOM.js +55 -0
  155. package/dist/cli/gateway-H4HFDC3E.js +77 -0
  156. package/dist/cli/gateway-auto-start-EDK7XI6E.js +36 -0
  157. package/dist/cli/gc-5R2TUY5T.js +291 -0
  158. package/dist/cli/go-PRQFK5YG.js +206 -0
  159. package/dist/cli/goal-7CZRMLHC.js +212 -0
  160. package/dist/cli/grade-PY2YRPUS.js +56 -0
  161. package/dist/cli/graph-XIXMCFKG.js +878 -0
  162. package/dist/cli/history-EIXADPAD.js +137 -0
  163. package/dist/cli/hook-UF7J7R6D.js +57 -0
  164. package/dist/cli/hook-entry.js +244 -19
  165. package/dist/cli/hygiene-3QZ2NI7P.js +55 -0
  166. package/dist/cli/import-R73SO444.js +88 -0
  167. package/dist/cli/import-tasks-O22FZJ4U.js +108 -0
  168. package/dist/cli/index.js +419 -94607
  169. package/dist/cli/init-IHEJDQWU.js +40 -0
  170. package/dist/cli/inject-LSRVWNCP.js +82 -0
  171. package/dist/cli/install-global-4AZUCH6U.js +95 -0
  172. package/dist/cli/intelligence-2OSFOGD2.js +181 -0
  173. package/dist/cli/issue-IIWEDNFC.js +158 -0
  174. package/dist/cli/janitor-GPMC7VOR.js +111 -0
  175. package/dist/cli/labels-5NPOIQXN.js +87 -0
  176. package/dist/cli/lifecycle-4FFS2K2T.js +272 -0
  177. package/dist/cli/list-47KEUGPQ.js +108 -0
  178. package/dist/cli/llm-G5B3I6GD.js +703 -0
  179. package/dist/cli/llm-cost-S7RS6BVA.js +25 -0
  180. package/dist/cli/llm-stream-24A45NTS.js +27 -0
  181. package/dist/cli/log-XF6H2XSD.js +75 -0
  182. package/dist/cli/login-LBPLGHYG.js +43 -0
  183. package/dist/cli/logout-SX4JSJIV.js +74 -0
  184. package/dist/cli/manifest-NMCW4PIW.js +353 -0
  185. package/dist/cli/map-BU72KMGF.js +52 -0
  186. package/dist/cli/memory-UHYIVGVM.js +1956 -0
  187. package/dist/cli/migrate-agents-v2-OO7OILZK.js +33 -0
  188. package/dist/cli/migrate-claude-mem-EDNYUY3K.js +201 -0
  189. package/dist/cli/next-RZFRG5X7.js +56 -0
  190. package/dist/cli/nexus-4S4Z5EVU.js +2923 -0
  191. package/dist/cli/ops-KR7AWCG3.js +51 -0
  192. package/dist/cli/orchestrate-HOYZY3VX.js +948 -0
  193. package/dist/cli/otel-U7IIRBCT.js +188 -0
  194. package/dist/cli/phase-NYZFHUE5.js +220 -0
  195. package/dist/cli/pivot-FF2CVUZL.js +87 -0
  196. package/dist/cli/plan-3SL2NTRV.js +48 -0
  197. package/dist/cli/playbook-2FCBV7N3.js +229 -0
  198. package/dist/cli/project-WDX2TGMC.js +330 -0
  199. package/dist/cli/promote-YINYFBZY.js +52 -0
  200. package/dist/cli/provenance-C7AYD7WG.js +128 -0
  201. package/dist/cli/provider-QLJEDQBR.js +212 -0
  202. package/dist/cli/reason-JF5BHBM5.js +137 -0
  203. package/dist/cli/reconcile-NMISHDGX.js +127 -0
  204. package/dist/cli/refresh-memory-EY5YNICV.js +45 -0
  205. package/dist/cli/relates-R3ZPICAY.js +259 -0
  206. package/dist/cli/release-4ZJTMUUT.js +524 -0
  207. package/dist/cli/remote-QSONJDIK.js +279 -0
  208. package/dist/cli/renderers-64OR3IWX.js +37 -0
  209. package/dist/cli/reorder-J3DOE7ST.js +86 -0
  210. package/dist/cli/reparent-2OUMKEZX.js +58 -0
  211. package/dist/cli/req-TZB7OFKO.js +129 -0
  212. package/dist/cli/research-MTD7EX45.js +365 -0
  213. package/dist/cli/restore-VEUOX7NF.js +423 -0
  214. package/dist/cli/revert-3YF2IL5G.js +240 -0
  215. package/dist/cli/roadmap-7OOQLXKG.js +61 -0
  216. package/dist/cli/run-2U5NZV5Z.js +211 -0
  217. package/dist/cli/safestop-VR4VK56D.js +88 -0
  218. package/dist/cli/saga-SEWPIOX2.js +285 -0
  219. package/dist/cli/schema-C52WZ35V.js +195 -0
  220. package/dist/cli/self-update-GQIGUDPS.js +504 -0
  221. package/dist/cli/selfimprove-3Y5L4ECT.js +88 -0
  222. package/dist/cli/sentient-M4YMAVGV.js +1088 -0
  223. package/dist/cli/sequence-6UBMA4IF.js +93 -0
  224. package/dist/cli/service-5R7SILZ7.js +155 -0
  225. package/dist/cli/session-3C6AAC4Y.js +707 -0
  226. package/dist/cli/setup-BTUBW5PU.js +323 -0
  227. package/dist/cli/show-MXT2V7TF.js +122 -0
  228. package/dist/cli/skill-GFUZOU2C.js +84 -0
  229. package/dist/cli/skills-EDWLKAF3.js +928 -0
  230. package/dist/cli/smoke-provider-SKUFMZXU.js +218 -0
  231. package/dist/cli/snapshot-GUWMURCM.js +119 -0
  232. package/dist/cli/src-66GAKPXR.js +80 -0
  233. package/dist/cli/start-QFG56RGN.js +67 -0
  234. package/dist/cli/stats-GW55P7RR.js +95 -0
  235. package/dist/cli/status-46HTKNRR.js +157 -0
  236. package/dist/cli/sticky-2DUZOUGI.js +338 -0
  237. package/dist/cli/stop-J2QEUKHX.js +42 -0
  238. package/dist/cli/sync-GJP2QYT5.js +154 -0
  239. package/dist/cli/tasks-BNXTM7PB.js +174 -0
  240. package/dist/cli/telemetry-55Z2XJWL.js +120 -0
  241. package/dist/cli/templates-7O77TKPV.js +611 -0
  242. package/dist/cli/testing-37YTBNKP.js +146 -0
  243. package/dist/cli/token-UAVJMNUI.js +220 -0
  244. package/dist/cli/transcript-LORQTV5Z.js +440 -0
  245. package/dist/cli/tui-BPUFHYKK.js +51 -0
  246. package/dist/cli/update-NVCYV2FT.js +476 -0
  247. package/dist/cli/upgrade-OXJXOGEF.js +243 -0
  248. package/dist/cli/verify-LYLDHPT2.js +190 -0
  249. package/dist/cli/web-QP2RP266.js +275 -0
  250. package/dist/cli/workgraph-FXBSZDQE.js +232 -0
  251. package/dist/cli/worktree-6RXAJIST.js +370 -0
  252. package/package.json +13 -13
  253. package/studio-dist/client/_app/immutable/chunks/{Buaay_Q8.js → Btgeq_wq.js} +1 -1
  254. package/studio-dist/client/_app/immutable/chunks/{BJp57kf2.js → CgBjxmu6.js} +1 -1
  255. package/studio-dist/client/_app/immutable/chunks/{CLP4JZvZ.js → DgEKqO6r.js} +1 -1
  256. package/studio-dist/client/_app/immutable/chunks/t81h7afa.js +1 -0
  257. package/studio-dist/client/_app/immutable/entry/{app.CczVILch.js → app.a02HWaRB.js} +2 -2
  258. package/studio-dist/client/_app/immutable/entry/start.BreMSngo.js +1 -0
  259. package/studio-dist/client/_app/immutable/nodes/{0.Zy2IsLEl.js → 0.nTXyRfc-.js} +1 -1
  260. package/studio-dist/client/_app/immutable/nodes/{1.DJN1QI3l.js → 1.4zrWeHtl.js} +1 -1
  261. package/studio-dist/client/_app/immutable/nodes/{15.B4rwqbHV.js → 15.D9mk4JyY.js} +1 -1
  262. package/studio-dist/client/_app/immutable/nodes/{16.jn-5BG_L.js → 16._-wt-sQf.js} +1 -1
  263. package/studio-dist/client/_app/immutable/nodes/{17.DnWGC4t9.js → 17.CUu6LQDj.js} +1 -1
  264. package/studio-dist/client/_app/immutable/nodes/{18.0zddLZOY.js → 18.Dz4QRTkX.js} +1 -1
  265. package/studio-dist/client/_app/immutable/nodes/{20.DEKHq9Tc.js → 20.CJ2_EB0U.js} +1 -1
  266. package/studio-dist/client/_app/immutable/nodes/{24.CQB9KP-p.js → 24.Igj2FS7k.js} +1 -1
  267. package/studio-dist/client/_app/immutable/nodes/{25.BaqToZD-.js → 25.BnATjVGN.js} +2 -2
  268. package/studio-dist/client/_app/immutable/nodes/{26.BiE1i4iE.js → 26.6iPyjT44.js} +1 -1
  269. package/studio-dist/client/_app/immutable/nodes/{3.BObAOu_-.js → 3.AA5GwNgP.js} +1 -1
  270. package/studio-dist/client/_app/version.json +1 -1
  271. package/studio-dist/server/chunks/{0-BmUoS2yd.js → 0-DGmsoBYm.js} +3 -3
  272. package/studio-dist/server/chunks/1-8PfxPvlK.js +9 -0
  273. package/studio-dist/server/chunks/{15-Dt4kqUxW.js → 15-Bg6YTndh.js} +3 -3
  274. package/studio-dist/server/chunks/{16-kgTLJvbO.js → 16-BObLwgyD.js} +3 -3
  275. package/studio-dist/server/chunks/{17-mRYB5141.js → 17-BNXGyAHX.js} +3 -3
  276. package/studio-dist/server/chunks/{18-BjZ325q5.js → 18-UqQFRIID.js} +3 -3
  277. package/studio-dist/server/chunks/{20-DQ2Vrujq.js → 20-CMn8a_yP.js} +3 -3
  278. package/studio-dist/server/chunks/{24-DAeuAfXN.js → 24-BuOTDzib.js} +3 -3
  279. package/studio-dist/server/chunks/{25-DGCNmzAS.js → 25-CIMSmjVx.js} +4 -4
  280. package/studio-dist/server/chunks/{26-CiN6bbmR.js → 26-DWGObn2T.js} +3 -3
  281. package/studio-dist/server/chunks/{3-BS2FXYjP.js → 3-CyiffdJZ.js} +3 -3
  282. package/studio-dist/server/chunks/{_layout.svelte-DJ_UWmGp.js → _layout.svelte-DYtClaIk.js} +4 -4
  283. package/studio-dist/server/chunks/{_page.svelte-WR6jUiQE.js → _page.svelte-1h9E6s_f.js} +3 -3
  284. package/studio-dist/server/chunks/{_page.svelte-BUq8_eQH.js → _page.svelte-BNNF62Nm.js} +3 -3
  285. package/studio-dist/server/chunks/{_page.svelte-CRnYa4cW.js → _page.svelte-BT1EUadj.js} +5 -5
  286. package/studio-dist/server/chunks/{_page.svelte-Dk0znswQ.js → _page.svelte-Bip079LT.js} +3 -3
  287. package/studio-dist/server/chunks/{_page.svelte-CcP_KW3Y.js → _page.svelte-CEATWp_5.js} +3 -3
  288. package/studio-dist/server/chunks/{_page.svelte-Ca7x-ZvH.js → _page.svelte-CV3xiD1y.js} +4 -4
  289. package/studio-dist/server/chunks/{_page.svelte-Cfv9tDBA.js → _page.svelte-Cv_KVJDV.js} +3 -3
  290. package/studio-dist/server/chunks/{_page.svelte-J4HjPhfO.js → _page.svelte-DSSy6LuK.js} +3 -3
  291. package/studio-dist/server/chunks/{_page.svelte-D8dLEr7O.js → _page.svelte-TF795TAS.js} +3 -3
  292. package/studio-dist/server/chunks/{_server.ts-Bih2-_5O.js → _server.ts-BlhRFLY3.js} +2 -2
  293. package/studio-dist/server/chunks/{_server.ts-Cr57EKWf.js → _server.ts-C4w6UdU0.js} +3 -3
  294. package/studio-dist/server/chunks/{_server.ts-P4wVVksg.js → _server.ts-CzrwbhkQ.js} +3 -3
  295. package/studio-dist/server/chunks/{_server.ts-2BazvYRP.js → _server.ts-DWt8Dziu.js} +3 -3
  296. package/studio-dist/server/chunks/{_server.ts-C0evMKCk.js → _server.ts-Db6mEile.js} +3 -3
  297. package/studio-dist/server/chunks/{client-Cl295FWH.js → client-D8f2k-H_.js} +2 -2
  298. package/studio-dist/server/chunks/{dist-CdoCt9zT.js → dist-B8xbIrdB.js} +3 -1
  299. package/studio-dist/server/chunks/{error.svelte-ajn1HNOb.js → error.svelte-DbbOwIme.js} +3 -3
  300. package/studio-dist/server/chunks/{http-BiQjEmVU.js → http-1ftNGTs5.js} +2 -2
  301. package/studio-dist/server/chunks/{internal-D9MtKHIF.js → internal-CTULuLPB.js} +2 -2
  302. package/studio-dist/server/chunks/{stores-BlknvZ80.js → stores-CS5XOReX.js} +2 -2
  303. package/studio-dist/server/index.js +1 -1
  304. package/studio-dist/server/manifest.js +17 -17
  305. package/studio-dist/client/_app/immutable/chunks/C3l-lTkq.js +0 -1
  306. package/studio-dist/client/_app/immutable/entry/start.D7gHmBNS.js +0 -1
  307. package/studio-dist/server/chunks/1-CTjj2MYz.js +0 -9
@@ -0,0 +1,1253 @@
1
+ (() => {
2
+ const _installed = Symbol.for('cleocode.cli.sqliteWarningFilter');
3
+ if (globalThis[_installed]) return;
4
+ globalThis[_installed] = true;
5
+ const _origEmitWarning = process.emitWarning;
6
+ process.emitWarning = function(warning, type, code, ctor) {
7
+ if (typeof warning === 'object' && warning.name === 'ExperimentalWarning' && typeof warning.message === 'string' && /SQLite is an experimental feature/i.test(warning.message)) {
8
+ return;
9
+ }
10
+ if (typeof warning === 'string' && /SQLite is an experimental feature/i.test(warning)) {
11
+ return;
12
+ }
13
+ return _origEmitWarning.call(process, warning, type, code, ctor);
14
+ };
15
+ })();
16
+ import {
17
+ createDoctorProgress
18
+ } from "./chunk-W3JLYKKY.js";
19
+ import {
20
+ readMigrationConflicts
21
+ } from "./chunk-REUTEW3O.js";
22
+ import {
23
+ doctorReleaseReadinessCommand
24
+ } from "./chunk-A2IUEIM5.js";
25
+ import {
26
+ doctorRepairCommand
27
+ } from "./chunk-DYABOIHB.js";
28
+ import {
29
+ doctorSkillFixturesCommand
30
+ } from "./chunk-YUZJI67I.js";
31
+ import {
32
+ doctorSplitBrainCommand
33
+ } from "./chunk-5ZFFUFH7.js";
34
+ import {
35
+ doctorSupersededStoreCommand
36
+ } from "./chunk-S24YI723.js";
37
+ import {
38
+ doctorToolLocksCommand
39
+ } from "./chunk-OAPN46TC.js";
40
+ import {
41
+ doctorTwinCollapseCommand
42
+ } from "./chunk-37NU2XDP.js";
43
+ import {
44
+ doctorWorktreeStoresCommand
45
+ } from "./chunk-EGOTK2HA.js";
46
+ import {
47
+ doctorMalformedIdsCommand
48
+ } from "./chunk-AYA6F4ZT.js";
49
+ import {
50
+ doctorManifestRowsCommand
51
+ } from "./chunk-NRKWJLMS.js";
52
+ import {
53
+ doctorMemoryGuardCommand
54
+ } from "./chunk-YGKEECTI.js";
55
+ import {
56
+ doctorMigrationsCommand
57
+ } from "./chunk-KJDWWQFY.js";
58
+ import {
59
+ doctorNexusResidencyCommand
60
+ } from "./chunk-EBRZ76HS.js";
61
+ import {
62
+ doctorProjectIdentityCommand
63
+ } from "./chunk-5J2VH3BC.js";
64
+ import {
65
+ doctorRegistryCommand
66
+ } from "./chunk-MNJRLSEQ.js";
67
+ import {
68
+ runDoctorProjects
69
+ } from "./chunk-3PGH67MT.js";
70
+ import {
71
+ doctorDepCyclesCommand
72
+ } from "./chunk-XRAX6XFP.js";
73
+ import {
74
+ doctorExodusResidueCommand
75
+ } from "./chunk-GFGLLDXX.js";
76
+ import {
77
+ doctorExodusCommand
78
+ } from "./chunk-DVTPIZJM.js";
79
+ import {
80
+ doctorFkCheckCommand
81
+ } from "./chunk-2JIJD2I7.js";
82
+ import {
83
+ doctorGlobalDeliveryCommand
84
+ } from "./chunk-LKNUA3SB.js";
85
+ import {
86
+ doctorHeavyCommandHookCommand
87
+ } from "./chunk-QPUY2HQZ.js";
88
+ import {
89
+ doctorLegacyBackupsCommand
90
+ } from "./chunk-JNZJPIPJ.js";
91
+ import {
92
+ doctorLegacyReaperCommand
93
+ } from "./chunk-NSHV2JNM.js";
94
+ import {
95
+ doctorAcBindingsCommand
96
+ } from "./chunk-ZZTHTMQP.js";
97
+ import {
98
+ doctorAcceptanceDriftCommand
99
+ } from "./chunk-LWQBJQSE.js";
100
+ import {
101
+ doctorCredentialsCommand
102
+ } from "./chunk-BCEXRFA2.js";
103
+ import {
104
+ doctorDbSubstrateCommand
105
+ } from "./chunk-KHB52JNB.js";
106
+ import "./chunk-47JYZAMS.js";
107
+ import "./chunk-C3B7C43W.js";
108
+ import {
109
+ isSubCommandDispatch
110
+ } from "./chunk-YY66LFZF.js";
111
+ import {
112
+ defineCommand
113
+ } from "./chunk-PKKZPOOP.js";
114
+ import {
115
+ dispatchFromCli,
116
+ dispatchRaw
117
+ } from "./chunk-3IOQVUO7.js";
118
+ import "./chunk-AWCQH2W5.js";
119
+ import "./chunk-OGV57L4J.js";
120
+ import "./chunk-ZBISIPCK.js";
121
+ import {
122
+ cliError,
123
+ cliOutput,
124
+ humanLine
125
+ } from "./chunk-3ZO3M37V.js";
126
+ import "./chunk-6JSJNYH2.js";
127
+ import "./chunk-QFFQSKRC.js";
128
+
129
+ // packages/cleo/src/cli/commands/doctor.ts
130
+ import { mkdirSync, writeFileSync } from "node:fs";
131
+ import { join } from "node:path";
132
+ import { getProjectRoot as getProjectRoot2, pushWarning } from "@cleocode/core";
133
+ import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
134
+ import {
135
+ quarantineRogueCleoDir,
136
+ scanRogueCleoDirs
137
+ } from "@cleocode/core/system/rogue-cleo-detector.js";
138
+
139
+ // packages/cleo/src/cli/commands/doctor-knowledge.ts
140
+ import { readFile } from "node:fs/promises";
141
+ import {
142
+ applyPreparedKnowledgeRepair,
143
+ cancelPreparedKnowledgeRepair,
144
+ createKnowledgeRepairInvocation,
145
+ inspectPreparedKnowledgeRepair,
146
+ KnowledgeRepairError,
147
+ listPreparedKnowledgeRepairs,
148
+ parseKnowledgeRepairProposal,
149
+ prepareKnowledgeRepair,
150
+ prepareKnowledgeRollback,
151
+ resumePreparedKnowledgeRepair,
152
+ runKnowledgeDoctor
153
+ } from "@cleocode/core/doctor/knowledge.js";
154
+ import { getProjectRoot } from "@cleocode/core/paths.js";
155
+ var doctorKnowledgeSubcommand = defineCommand({
156
+ meta: {
157
+ name: "knowledge",
158
+ description: "Assess project knowledge and apply bounded, sourced, reversible repairs"
159
+ },
160
+ args: {
161
+ fix: {
162
+ type: "boolean",
163
+ description: "Apply deterministic repairs to confirmed derived defects"
164
+ },
165
+ "dry-run": { type: "boolean", description: "Preview findings and proposals without mutations" },
166
+ resolve: { type: "string", description: "Apply a sourced repair proposal from a JSON file" },
167
+ prepare: { type: "string", description: "Persist a sourced JSON proposal without applying it" },
168
+ apply: {
169
+ type: "string",
170
+ description: "Apply an immutable prepared job under a fresh bounded attempt"
171
+ },
172
+ jobs: {
173
+ type: "boolean",
174
+ description: "Discover durable repairs for an explicit original actor"
175
+ },
176
+ cursor: { type: "string", description: "Exact JSON nextCursor from the preceding --jobs page" },
177
+ inspect: {
178
+ type: "string",
179
+ description: "Inspect a prepared job, retained receipts and lifecycle ledger"
180
+ },
181
+ cancel: {
182
+ type: "string",
183
+ description: "Request cancellation; committed repair effects are preserved"
184
+ },
185
+ resume: {
186
+ type: "string",
187
+ description: "Explicitly retry recoverable work while retaining prior attempts"
188
+ },
189
+ actor: {
190
+ type: "string",
191
+ description: "Explicit stable repair actor; must match prepared work"
192
+ },
193
+ "proposal-id": {
194
+ type: "string",
195
+ description: "Immutable proposal identity for job operations or new rollback"
196
+ },
197
+ limit: {
198
+ type: "string",
199
+ description: "Page size: --jobs 1\u2013100 (default 25); inspection 1\u20131000 (default 100)"
200
+ },
201
+ offset: { type: "string", default: "0", description: "Inspection ledger page offset" },
202
+ rollback: {
203
+ type: "string",
204
+ description: "Restore a prior repair receipt after checking its post-state"
205
+ },
206
+ decision: {
207
+ type: "string",
208
+ description: "Assess explicit decision-to-task-to-code evidence and supported linking actions"
209
+ },
210
+ task: {
211
+ type: "string",
212
+ description: "Include evidence-derived footprint findings for one task"
213
+ },
214
+ "budget-ms": {
215
+ type: "string",
216
+ default: "2000",
217
+ description: "Shared invocation budget in milliseconds (1\u2013120000), default 2000; synchronous work is cooperative"
218
+ },
219
+ json: { type: "boolean", description: "Output one structured envelope" }
220
+ },
221
+ async run({ args }) {
222
+ const startedAt = Date.now();
223
+ const root = getProjectRoot();
224
+ let context;
225
+ let pending;
226
+ try {
227
+ const budgetMs = Number(args["budget-ms"]);
228
+ if (!Number.isSafeInteger(budgetMs) || budgetMs < 1 || budgetMs > 12e4)
229
+ throw new KnowledgeRepairError(
230
+ "E_REPAIR_INPUT",
231
+ "--budget-ms must be an integer between 1 and 120000."
232
+ );
233
+ const deadlineAt = startedAt + budgetMs;
234
+ const actions = [
235
+ args.fix,
236
+ args.resolve,
237
+ args.rollback,
238
+ args.prepare,
239
+ args.apply,
240
+ args.inspect,
241
+ args.cancel,
242
+ args.resume,
243
+ args.jobs
244
+ ];
245
+ if (actions.filter(Boolean).length > 1)
246
+ throw new KnowledgeRepairError(
247
+ "E_REPAIR_INPUT",
248
+ "Select exactly one repair lifecycle action."
249
+ );
250
+ if (args["dry-run"] && (args.prepare || args.apply || args.inspect || args.cancel || args.resume || args.rollback || args.jobs))
251
+ throw new KnowledgeRepairError(
252
+ "E_REPAIR_INPUT",
253
+ "--dry-run cannot execute a repair lifecycle action."
254
+ );
255
+ const lifecycle = actions.some(Boolean) && !args["dry-run"];
256
+ if (lifecycle && !args.actor?.trim())
257
+ throw new KnowledgeRepairError(
258
+ "E_REPAIR_ACTOR",
259
+ "--actor explicitly identifies the stable repair caller."
260
+ );
261
+ if ((args.apply || args.inspect || args.cancel || args.resume || args.rollback) && !args["proposal-id"]?.trim())
262
+ throw new KnowledgeRepairError(
263
+ "E_REPAIR_INPUT",
264
+ "--proposal-id must identify the immutable prepared input or new rollback."
265
+ );
266
+ if (args.cursor && !args.jobs)
267
+ throw new KnowledgeRepairError("E_REPAIR_INPUT", "--cursor requires --jobs.");
268
+ if (args.jobs) {
269
+ if (args["proposal-id"] || Number(args.offset) !== 0)
270
+ throw new KnowledgeRepairError(
271
+ "E_REPAIR_INPUT",
272
+ "--jobs uses its returned cursor, not proposal identity or offset."
273
+ );
274
+ context = await createKnowledgeRepairInvocation(
275
+ root,
276
+ args.actor,
277
+ "knowledge-inventory",
278
+ deadlineAt
279
+ );
280
+ cliOutput(
281
+ await listPreparedKnowledgeRepairs(context, {
282
+ limit: Number(args.limit ?? "25"),
283
+ after: args.cursor === void 0 ? void 0 : JSON.parse(args.cursor)
284
+ }),
285
+ { command: "doctor", operation: "doctor.knowledge" }
286
+ );
287
+ return;
288
+ }
289
+ let proposal = args.prepare || args.resolve ? parseKnowledgeRepairProposal(await readFile(args.prepare || args.resolve, "utf8")) : void 0;
290
+ if (proposal && args["proposal-id"] && proposal.id !== args["proposal-id"])
291
+ throw new KnowledgeRepairError(
292
+ "E_REPAIR_INPUT",
293
+ "--proposal-id differs from the sourced proposal."
294
+ );
295
+ if (!lifecycle || args.fix) {
296
+ const report = await runKnowledgeDoctor(root, {
297
+ budgetMs: Math.max(0, deadlineAt - Date.now()),
298
+ fix: args.fix,
299
+ dryRun: true,
300
+ proposal,
301
+ taskId: args.task,
302
+ decisionId: args.decision
303
+ });
304
+ if (!lifecycle || report.health.coverage.maintenanceState === "pending" || !report.proposals[0]) {
305
+ cliOutput(report, { command: "doctor", operation: "doctor.knowledge" });
306
+ return;
307
+ }
308
+ proposal = report.proposals[0];
309
+ }
310
+ if (proposal && args["proposal-id"] && proposal.id !== args["proposal-id"])
311
+ throw new KnowledgeRepairError(
312
+ "E_REPAIR_INPUT",
313
+ "--proposal-id differs from the assessed proposal."
314
+ );
315
+ const proposalId = proposal?.id ?? args["proposal-id"];
316
+ if (!proposalId || !args.actor)
317
+ throw new KnowledgeRepairError(
318
+ "E_REPAIR_INPUT",
319
+ "Explicit actor and immutable proposal identity are required."
320
+ );
321
+ context = await createKnowledgeRepairInvocation(root, args.actor, proposalId, deadlineAt);
322
+ if (args.inspect) {
323
+ cliOutput(
324
+ await inspectPreparedKnowledgeRepair(
325
+ context,
326
+ args.inspect,
327
+ Number(args.limit ?? "100"),
328
+ Number(args.offset)
329
+ ),
330
+ { command: "doctor", operation: "doctor.knowledge" }
331
+ );
332
+ return;
333
+ }
334
+ if (args.cancel) {
335
+ cliOutput(await cancelPreparedKnowledgeRepair(context, args.cancel), {
336
+ command: "doctor",
337
+ operation: "doctor.knowledge"
338
+ });
339
+ return;
340
+ }
341
+ if (proposal) pending = await prepareKnowledgeRepair(context, proposal);
342
+ else if (args.rollback) pending = await prepareKnowledgeRollback(context, args.rollback);
343
+ if (args.prepare) {
344
+ cliOutput(pending, { command: "doctor", operation: "doctor.knowledge" });
345
+ return;
346
+ }
347
+ const jobId = pending?.jobId ?? args.apply ?? args.resume;
348
+ if (!jobId) throw new KnowledgeRepairError("E_REPAIR_INPUT", "A prepared job is required.");
349
+ const result = args.resume ? await resumePreparedKnowledgeRepair(context, jobId) : await applyPreparedKnowledgeRepair(context, jobId);
350
+ cliOutput(result, { command: "doctor", operation: "doctor.knowledge" });
351
+ } catch (error) {
352
+ cliError(
353
+ error instanceof Error ? error.message : String(error),
354
+ 6,
355
+ {
356
+ name: error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "E_REPAIR_INPUT",
357
+ details: {
358
+ prepared: pending,
359
+ attemptFailure: error instanceof KnowledgeRepairError ? error.attemptFailure : void 0,
360
+ recoveryState: error instanceof KnowledgeRepairError ? error.recoveryState : void 0,
361
+ deadlineAt: context?.deadlineAt,
362
+ elapsedMs: Date.now() - startedAt
363
+ }
364
+ },
365
+ { operation: "doctor.knowledge" }
366
+ );
367
+ process.exitCode = 6;
368
+ } finally {
369
+ context?.close();
370
+ }
371
+ }
372
+ });
373
+
374
+ // packages/cleo/src/cli/commands/doctor.ts
375
+ var FIXTURE_ID_PATTERNS = [/^E\d+$/, /^T\d+EP$/];
376
+ var FIXTURE_TITLE_KEYWORDS = [
377
+ "test epic",
378
+ "with no files",
379
+ "standalone epic",
380
+ "fixture"
381
+ ];
382
+ async function scanTestFixturesInProd(projectRoot) {
383
+ const { getDb, getNativeDb } = await import("@cleocode/core/store/sqlite.js");
384
+ await getDb(projectRoot);
385
+ const nativeDb = getNativeDb(projectRoot);
386
+ if (!nativeDb) return [];
387
+ const rows = nativeDb.prepare("SELECT id, title, type, status FROM tasks WHERE status != 'deleted' LIMIT 2000").all();
388
+ const matches = [];
389
+ for (const row of rows) {
390
+ const lower = (row.title ?? "").toLowerCase();
391
+ const idPatternMatch = FIXTURE_ID_PATTERNS.some((p) => p.test(row.id));
392
+ const titleKeywordMatch = FIXTURE_TITLE_KEYWORDS.find((kw) => lower.includes(kw));
393
+ if (idPatternMatch) {
394
+ matches.push({
395
+ id: row.id,
396
+ title: row.title ?? "",
397
+ type: row.type ?? "",
398
+ confidence: "HIGH",
399
+ rationale: `id matches fixture pattern (^E\\d+$ or ^T\\d+EP$)`
400
+ });
401
+ } else if (titleKeywordMatch) {
402
+ matches.push({
403
+ id: row.id,
404
+ title: row.title ?? "",
405
+ type: row.type ?? "",
406
+ confidence: "MED",
407
+ rationale: `title contains fixture keyword "${titleKeywordMatch}"`
408
+ });
409
+ }
410
+ }
411
+ return matches;
412
+ }
413
+ async function quarantineTestFixtures(projectRoot, matches) {
414
+ if (matches.length === 0) return 0;
415
+ const cleoDir = join(projectRoot, ".cleo");
416
+ const quarantineDir = join(
417
+ cleoDir,
418
+ "quarantine",
419
+ `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
420
+ );
421
+ mkdirSync(quarantineDir, { recursive: true });
422
+ const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
423
+ writeFileSync(
424
+ join(quarantineDir, "manifest.jsonl"),
425
+ manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
426
+ );
427
+ const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
428
+ const nativeDb = getNativeDb();
429
+ if (nativeDb) {
430
+ for (const m of matches) {
431
+ try {
432
+ nativeDb.prepare(
433
+ "UPDATE tasks SET labels_json = json_insert(COALESCE(labels_json, '[]'), '$[#]', 'fixture-quarantine'), status = 'cancelled' WHERE id = ?"
434
+ ).run(m.id);
435
+ } catch {
436
+ }
437
+ }
438
+ }
439
+ return matches.length;
440
+ }
441
+ function renderHookMatrixHuman(data) {
442
+ const { events, providers, matrix, summary, caampVersion, detectedProvider } = data;
443
+ humanLine(`
444
+ Provider Hook Matrix (CAAMP ${caampVersion} canonical taxonomy)
445
+ `);
446
+ if (detectedProvider) {
447
+ humanLine(`Detected provider: ${detectedProvider}
448
+ `);
449
+ }
450
+ if (providers.length === 0) {
451
+ humanLine("No providers found in CAAMP registry.");
452
+ return;
453
+ }
454
+ const EVENT_COL = Math.max(...events.map((e) => e.length), "Event".length);
455
+ const provCols = providers.map((p) => Math.max(p.length, 5));
456
+ const headerParts = [
457
+ "Event".padEnd(EVENT_COL),
458
+ ...providers.map((p, i) => p.padEnd(provCols[i]))
459
+ ];
460
+ humanLine(` ${headerParts.join(" ")}`);
461
+ const sepParts = ["-".repeat(EVENT_COL), ...provCols.map((w) => "-".repeat(w))];
462
+ humanLine(` ${sepParts.join(" ")}`);
463
+ for (const event of events) {
464
+ const cells = providers.map((p, i) => {
465
+ const supported = matrix[event]?.[p] === true;
466
+ const symbol = supported ? "\u2713" : "-";
467
+ return symbol.padEnd(provCols[i]);
468
+ });
469
+ humanLine(` ${event.padEnd(EVENT_COL)} ${cells.join(" ")}`);
470
+ }
471
+ humanLine("");
472
+ const coverageParts = summary.map(
473
+ (s) => `${s.providerId} ${s.supportedCount}/${s.totalCanonical} (${s.coverage}%)`
474
+ );
475
+ humanLine(`Coverage: ${coverageParts.join(", ")}
476
+ `);
477
+ }
478
+ function renderInvariantAuditHuman(result) {
479
+ for (const line of renderInvariantAuditLines(result)) {
480
+ humanLine(line);
481
+ }
482
+ }
483
+ var doctorCommand = defineCommand({
484
+ meta: { name: "doctor", description: "Run system diagnostics and health checks" },
485
+ subCommands: {
486
+ knowledge: doctorKnowledgeSubcommand,
487
+ // T10307 / Saga T10281 / Epic T10282 — DB-substrate walker
488
+ "db-substrate": doctorDbSubstrateCommand,
489
+ // T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
490
+ "legacy-backups": doctorLegacyBackupsCommand,
491
+ // T12131 — the reaper that kills live Codex sessions
492
+ "legacy-reaper": doctorLegacyReaperCommand,
493
+ // T12128 — task ids that fail the write-path validator
494
+ "malformed-ids": doctorMalformedIdsCommand,
495
+ // T12796 — the migration journal of each store (read-only; the live journal count)
496
+ migrations: doctorMigrationsCommand,
497
+ // T12686 — manifest rows whose metadata violates the stored field contract (+ --repair/--rollback)
498
+ "manifest-rows": doctorManifestRowsCommand,
499
+ // T12095 — pre-dual-scope store files still on disk under their old LIVE names
500
+ "superseded-store": doctorSupersededStoreCommand,
501
+ // T12535 — twin collapses (bare schema_meta / sticky_tags → prefixed twins): report + --retry
502
+ "twin-collapse": doctorTwinCollapseCommand,
503
+ // T12460 — project stores stranded inside CLEO worktrees (read-only report)
504
+ "worktree-stores": doctorWorktreeStoresCommand,
505
+ // T12097 — machine-wide guard for test runs started OUTSIDE cleo verify
506
+ "memory-guard": doctorMemoryGuardCommand,
507
+ // T13124 — the heavy-command hook per agent harness in use (+ --fix installs it)
508
+ "heavy-command-hook": doctorHeavyCommandHookCommand,
509
+ // T12353 · T12716 — tracked .cleo/project.json / project-id vs project-info.json (+ --resolve migrate / re-key)
510
+ "project-identity": doctorProjectIdentityCommand,
511
+ // T12596 · T12598 — ~/.cleo, the global hub and every harness skill install must resolve
512
+ "global-delivery": doctorGlobalDeliveryCommand,
513
+ // T12645 — caamp test fixtures left in the real skills root (quarantine with a receipt)
514
+ "skill-fixtures": doctorSkillFixturesCommand,
515
+ // T12471 — machine-wide registry integrity: rebind moved by id, flag split/missing/temp
516
+ projects: doctorRegistryCommand,
517
+ // T12329 — import rows only a diverged store copy has, under new ids (dry-run first)
518
+ "split-brain": doctorSplitBrainCommand,
519
+ // T12157 — the two acceptance stores (json column vs text+child rows) must agree
520
+ "acceptance-drift": doctorAcceptanceDriftCommand,
521
+ // T12790 — evidence bindings whose AC row is gone (no FK): report + --fix (audited)
522
+ "ac-bindings": doctorAcBindingsCommand,
523
+ // T12886 — stored task dependency cycles + repair plan (read-only)
524
+ "dep-cycles": doctorDepCyclesCommand,
525
+ // T12158 — tables nexus resolves by bare name must actually live where it assumes
526
+ "nexus-residency": doctorNexusResidencyCommand,
527
+ // T12113 (gh#1222) — evidence-tool semaphore holders + orphan reaping
528
+ "tool-locks": doctorToolLocksCommand,
529
+ // T12326 — project credentials still keyed by project PATH (+ --fix re-keys)
530
+ credentials: doctorCredentialsCommand,
531
+ // T11777 / Saga T11242 / Epic T11249 — exodus stranded-residue check (+ --fix)
532
+ "exodus-residue": doctorExodusResidueCommand,
533
+ // T11837 / Saga T11242 / Epic T11833 — read-only exodus health report
534
+ "exodus-health": doctorExodusCommand,
535
+ // T11530 / Saga T11242 / Epic T11249 — consolidated FK integrity check
536
+ "fk-check": doctorFkCheckCommand,
537
+ // T11829 / Saga T11242 / Epic T11833 — DHQ-060 malformed-DB repair entry point
538
+ repair: doctorRepairCommand,
539
+ // T10458 / Saga T10431 / Epic T10436 — Release-readiness preflight
540
+ "release-readiness": doctorReleaseReadinessCommand
541
+ },
542
+ args: {
543
+ detailed: {
544
+ type: "boolean",
545
+ description: "Show detailed health check results"
546
+ },
547
+ comprehensive: {
548
+ type: "boolean",
549
+ description: "Run comprehensive doctor report"
550
+ },
551
+ full: {
552
+ type: "boolean",
553
+ description: "Run operational smoke tests across all domains"
554
+ },
555
+ fix: {
556
+ type: "boolean",
557
+ description: "Auto-fix failed checks"
558
+ },
559
+ coherence: {
560
+ type: "boolean",
561
+ description: "Run coherence check across task data"
562
+ },
563
+ hooks: {
564
+ type: "boolean",
565
+ description: "Show cross-provider hook support matrix (CAAMP canonical taxonomy)"
566
+ },
567
+ "all-projects": {
568
+ type: "boolean",
569
+ description: "Probe DB + config health for every registered project (nexus.db)"
570
+ },
571
+ "ignore-unreachable": {
572
+ type: "boolean",
573
+ description: "When used with --all-projects, exit 1 instead of 2 on unreachable projects"
574
+ },
575
+ "scan-rogue-cleo-dirs": {
576
+ type: "boolean",
577
+ description: "Scan for rogue .cleo/ directories inside sub-packages and print forensic report"
578
+ },
579
+ "quarantine-rogue-cleo-dirs": {
580
+ type: "boolean",
581
+ description: "Move all rogue .cleo/ sub-package directories to .cleo/quarantine/ (never deletes)"
582
+ },
583
+ "scan-stray-nexus-dbs": {
584
+ type: "boolean",
585
+ description: "Scan ~/.local/share/cleo/ for orphaned nexus.db files and print report (T9052)"
586
+ },
587
+ "audit-worktrees": {
588
+ type: "boolean",
589
+ description: "Audit orphaned agent worktree directories and report what cleo gc --worktrees would remove (T9043)"
590
+ },
591
+ /**
592
+ * T9790: list orphan `.cleo/` directories under
593
+ * `<projectRoot>/.claude/worktrees/` with full provenance. Read-only.
594
+ */
595
+ "audit-worktree-orphans": {
596
+ type: "boolean",
597
+ description: "List orphan .cleo/ directories under .claude/worktrees/ (T9790, fallout from T9550/T9580)"
598
+ },
599
+ /**
600
+ * T9962: timeout in seconds for --audit-worktree-orphans and
601
+ * --prune-worktree-orphans. On expiry the scan returns a partial result.
602
+ * Default: 30 seconds.
603
+ */
604
+ timeout: {
605
+ type: "string",
606
+ description: "Timeout in seconds for worktree-orphan audit/prune scan (default: 30). Partial results are returned on expiry."
607
+ },
608
+ /**
609
+ * T9962: per-level fan-out cap for --audit-worktree-orphans.
610
+ * Default: 500.
611
+ */
612
+ "max-entries-per-level": {
613
+ type: "string",
614
+ description: "Per-level entry hard-stop for worktree-orphan scan (default: 500). Scan aborts with partial result when exceeded."
615
+ },
616
+ /**
617
+ * T9790: archive then remove every orphan reported by
618
+ * `--audit-worktree-orphans`. Combine with `--dry-run` to preview
619
+ * without touching the filesystem.
620
+ */
621
+ "prune-worktree-orphans": {
622
+ type: "boolean",
623
+ description: "Archive then remove orphan .cleo/ directories under .claude/worktrees/ (T9790)"
624
+ },
625
+ "audit-temp": {
626
+ type: "boolean",
627
+ description: "Audit orphaned CLEO-generated temp directories and report what cleo gc --temp would remove (T9043)"
628
+ },
629
+ /**
630
+ * T10119: audit every Saga (`type='epic'` + `label='saga'`) for
631
+ * ADR-073 §1.2 invariant violations (I5/I7 + depth ladder) and
632
+ * auto-close drift. Read-only; non-zero exit when any I-invariant
633
+ * fails so the check is CI-gateable.
634
+ *
635
+ * As of T10340 (R6), `--audit-sagas` is a focused alias on top of
636
+ * `--audit-invariants` — it filters the registry walk to ADR-073
637
+ * only. The implementation re-uses the central walker so the two
638
+ * surfaces stay in lock-step.
639
+ *
640
+ * @task T10119
641
+ * @task T10340
642
+ * @saga T10113
643
+ * @epic T10209
644
+ */
645
+ "audit-sagas": {
646
+ type: "boolean",
647
+ description: "Audit every Saga for ADR-073 \xA71.2 invariant violations (I5/I7/depth) + auto-close drift \u2014 focused alias on top of --audit-invariants (T10119, T10340)"
648
+ },
649
+ /**
650
+ * T10340: walk the central `INVARIANTS_REGISTRY` and audit every
651
+ * registered invariant against the project's current state.
652
+ *
653
+ * Output groups violations by ADR + severity and includes an
654
+ * actionable repair command per violation. Supports `--json` for
655
+ * machine consumption. Exit code is non-zero when any
656
+ * `severity:'error'` violation is observed.
657
+ *
658
+ * @task T10340 — R6
659
+ * @epic T10327 — E-INVARIANT-REGISTRY-SSOT
660
+ * @saga T10326 — SG-SUBSTRATE-RECONCILIATION
661
+ */
662
+ "audit-invariants": {
663
+ type: "boolean",
664
+ description: "Walk the central INVARIANTS_REGISTRY and audit every registered invariant \u2014 groups by ADR + severity with repair commands (T10340 / Saga T10326 R6)"
665
+ },
666
+ /**
667
+ * T9983: migrate the worktree-include file location from
668
+ * `<root>/.cleo/worktree-include` (legacy) to `<root>/.worktreeinclude`
669
+ * (canonical, matches Claude Code Desktop + worktrunk-core). Backs the
670
+ * legacy file up to `.cleo/backups/worktree-include-<iso>.bak` before
671
+ * removing it from the legacy path. Combine with `--dry-run` to preview.
672
+ */
673
+ "migrate-worktree-include": {
674
+ type: "boolean",
675
+ description: "Migrate <root>/.cleo/worktree-include (legacy) \u2192 <root>/.worktreeinclude (canonical, T9983). Combine with --dry-run to preview."
676
+ },
677
+ /**
678
+ * T11489 — DHQ-037/019: detect and auto-heal a leaked `core.worktree` key
679
+ * in the shared `.git/config`. Reports E_WT_CONFIG_LEAK when found; heals
680
+ * automatically unless `--dry-run` is passed.
681
+ */
682
+ "check-worktree-config": {
683
+ type: "boolean",
684
+ description: "Detect and auto-heal a leaked core.worktree key in .git/config (T11489 / DHQ-037). Combine with --dry-run to report without healing."
685
+ },
686
+ "dry-run": {
687
+ type: "boolean",
688
+ description: "With --quarantine-rogue-cleo-dirs, --scan-stray-nexus-dbs, or --check-worktree-config: print what would be done without acting"
689
+ },
690
+ /**
691
+ * Show brain.db health dashboard (T1908 / BBTT-W2-4).
692
+ * Aggregates 8 named flags: row counts, dedup ratio, last consolidation,
693
+ * recency violations, learnings ratio, pattern bloat, fixture pollution,
694
+ * daemon liveness. Exits 1 on any P0 flag failure.
695
+ */
696
+ brain: {
697
+ type: "boolean",
698
+ description: "Show brain.db health dashboard with 8 named BBTT flags (T1908)"
699
+ },
700
+ /**
701
+ * T1909 / BBTT-W3-3: Scan tasks.db for test-fixture rows using heuristics.
702
+ *
703
+ * Detects rows matching: id ^E\d+$, id ^T\d+EP$, or title containing
704
+ * "Test Epic", "with no files", "standalone epic", "fixture".
705
+ * Reports each match with a confidence score (HIGH/MED/LOW).
706
+ *
707
+ * Pass --quarantine to move matched rows to .cleo/quarantine/
708
+ * (T1864 pattern — NEVER deletes). Dry-run by default.
709
+ */
710
+ "scan-test-fixtures-in-prod": {
711
+ type: "boolean",
712
+ description: "Scan tasks.db for test-fixture rows using heuristics (T1909)"
713
+ },
714
+ quarantine: {
715
+ type: "boolean",
716
+ description: "With --scan-test-fixtures-in-prod: move matches to .cleo/quarantine/ (no delete)"
717
+ },
718
+ // Global output format flags — read directly from args (no optsWithGlobals in citty)
719
+ json: {
720
+ type: "boolean",
721
+ description: "Output as JSON"
722
+ },
723
+ human: {
724
+ type: "boolean",
725
+ description: "Force human-readable output"
726
+ },
727
+ quiet: {
728
+ type: "boolean",
729
+ description: "Suppress non-essential output"
730
+ }
731
+ },
732
+ async run({ args, cmd, rawArgs }) {
733
+ if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
734
+ const isHuman = args.human === true || !!process.stdout.isTTY && args.json !== true;
735
+ const progress = createDoctorProgress(isHuman);
736
+ progress.start();
737
+ try {
738
+ if (args["check-worktree-config"]) {
739
+ const { execFileSync: execFile } = await import("node:child_process");
740
+ const { join: pathJoin } = await import("node:path");
741
+ const { existsSync } = await import("node:fs");
742
+ const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
743
+ const projectRoot = getProjectRoot2();
744
+ let gitRoot = projectRoot;
745
+ try {
746
+ gitRoot = execFile("git", ["rev-parse", "--show-toplevel"], {
747
+ cwd: projectRoot,
748
+ encoding: "utf-8",
749
+ stdio: ["pipe", "pipe", "pipe"]
750
+ }).trim();
751
+ } catch {
752
+ }
753
+ const isDryRun = args["dry-run"] === true;
754
+ progress.step(0, "Checking for leaked core.worktree in .git/config");
755
+ if (isDryRun) {
756
+ const gitConfigPath = pathJoin(gitRoot, ".git", "config");
757
+ let leakedValue;
758
+ if (existsSync(gitConfigPath)) {
759
+ try {
760
+ leakedValue = execFile("git", ["config", "--file", gitConfigPath, "--get", "core.worktree"], {
761
+ encoding: "utf-8",
762
+ stdio: ["pipe", "pipe", "pipe"]
763
+ }).trim() || void 0;
764
+ } catch {
765
+ }
766
+ }
767
+ const report = {
768
+ gitRoot,
769
+ gitConfigPath,
770
+ leakDetected: !!leakedValue,
771
+ leakedValue,
772
+ healed: false,
773
+ dryRun: true,
774
+ message: leakedValue ? `DRY-RUN: core.worktree="${leakedValue}" found \u2014 would unset` : "No core.worktree leak detected"
775
+ };
776
+ progress.complete(report.message);
777
+ cliOutput(report, { command: "doctor", operation: "doctor.check-worktree-config" });
778
+ if (leakedValue) process.exitCode = 2;
779
+ } else {
780
+ const result = detectAndHealCoreWorktreeLeak(gitRoot);
781
+ const report = {
782
+ gitRoot,
783
+ ...result,
784
+ dryRun: false,
785
+ message: result.leakDetected ? result.healed ? `E_WT_CONFIG_LEAK healed: removed core.worktree="${result.leakedValue}"` : `E_WT_CONFIG_LEAK detected but heal FAILED: ${result.healError}` : "No core.worktree leak detected"
786
+ };
787
+ progress.complete(report.message);
788
+ cliOutput(report, { command: "doctor", operation: "doctor.check-worktree-config" });
789
+ if (result.leakDetected && !result.healed) process.exitCode = 1;
790
+ }
791
+ return;
792
+ }
793
+ if (args.brain) {
794
+ const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
795
+ const projectRoot = getProjectRoot2();
796
+ const dashboard = await computeBrainHealthDashboard(projectRoot);
797
+ cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
798
+ if (dashboard.hasP0Failure) {
799
+ process.exitCode = 1;
800
+ }
801
+ return;
802
+ }
803
+ if (args["scan-test-fixtures-in-prod"]) {
804
+ const projectRoot = getProjectRoot2();
805
+ const matches = await scanTestFixturesInProd(projectRoot);
806
+ const dryRun = args["dry-run"] !== false && args.quarantine !== true;
807
+ const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
808
+ cliOutput(
809
+ { matches, dryRun, quarantined },
810
+ { command: "doctor", operation: "doctor.scan-test-fixtures" }
811
+ );
812
+ if (matches.some((m) => m.confidence === "HIGH")) {
813
+ process.exitCode = 1;
814
+ }
815
+ return;
816
+ }
817
+ if (args["all-projects"]) {
818
+ progress.step(0, "Probing registered projects");
819
+ await runDoctorProjects({
820
+ json: args.json === true,
821
+ quiet: args.quiet === true,
822
+ ignoreUnreachable: args["ignore-unreachable"] === true
823
+ });
824
+ progress.complete("Project health report complete");
825
+ } else if (args.hooks) {
826
+ progress.step(0, "Building provider hook matrix");
827
+ if (isHuman) {
828
+ const response = await dispatchRaw("query", "admin", "hooks.matrix", {
829
+ detectProvider: true
830
+ });
831
+ progress.complete("Hook matrix complete");
832
+ if (response.success && response.data) {
833
+ renderHookMatrixHuman(response.data);
834
+ } else {
835
+ cliError(response.error?.message ?? "Failed to build hook matrix", 1, {
836
+ name: "E_INTERNAL"
837
+ });
838
+ process.exitCode = 1;
839
+ }
840
+ } else {
841
+ await dispatchFromCli(
842
+ "query",
843
+ "admin",
844
+ "hooks.matrix",
845
+ { detectProvider: true },
846
+ { command: "doctor", operation: "admin.hooks.matrix" }
847
+ );
848
+ progress.complete("Hook matrix complete");
849
+ }
850
+ } else if (args.full) {
851
+ progress.step(0, "Running operational smoke tests");
852
+ await dispatchFromCli(
853
+ "query",
854
+ "admin",
855
+ "smoke",
856
+ {},
857
+ { command: "doctor", operation: "admin.smoke" }
858
+ );
859
+ progress.complete("Smoke tests complete");
860
+ } else if (args.coherence) {
861
+ progress.step(0, "Running coherence check");
862
+ await dispatchFromCli(
863
+ "query",
864
+ "check",
865
+ "coherence",
866
+ {},
867
+ { command: "doctor", operation: "check.coherence" }
868
+ );
869
+ progress.complete("Coherence check complete");
870
+ } else if (args.fix) {
871
+ progress.step(4, "Applying fixes");
872
+ await dispatchFromCli(
873
+ "mutate",
874
+ "admin",
875
+ "health",
876
+ { mode: "repair" },
877
+ { command: "doctor", operation: "admin.health" }
878
+ );
879
+ progress.complete("Fixes applied");
880
+ } else if (args.comprehensive) {
881
+ progress.step(0, "Checking CLEO directory");
882
+ await dispatchFromCli(
883
+ "query",
884
+ "admin",
885
+ "health",
886
+ { mode: "diagnose" },
887
+ { command: "doctor", operation: "admin.health" }
888
+ );
889
+ progress.complete("Comprehensive diagnostics complete");
890
+ } else if (args["scan-rogue-cleo-dirs"]) {
891
+ progress.step(0, "Scanning for rogue .cleo/ directories");
892
+ const projectRoot = getProjectRoot2();
893
+ const reports = scanRogueCleoDirs(projectRoot);
894
+ progress.complete(
895
+ `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
896
+ );
897
+ cliOutput(reports, { command: "doctor", operation: "doctor.scan-rogue-cleo-dirs" });
898
+ } else if (args["quarantine-rogue-cleo-dirs"]) {
899
+ const isDryRun = args["dry-run"] === true;
900
+ progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
901
+ const projectRoot = getProjectRoot2();
902
+ const reports = scanRogueCleoDirs(projectRoot);
903
+ if (reports.length === 0) {
904
+ progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
905
+ cliOutput(
906
+ { quarantined: [] },
907
+ { command: "doctor", operation: "doctor.quarantine-rogue-dirs" }
908
+ );
909
+ return;
910
+ }
911
+ const quarantined = [];
912
+ const errors = [];
913
+ for (const report of reports) {
914
+ if (isDryRun) {
915
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
916
+ const targetPath = `${projectRoot}/.cleo/quarantine/${report.packageName}-${timestamp}`;
917
+ quarantined.push({
918
+ packageName: report.packageName,
919
+ from: report.path,
920
+ to: targetPath
921
+ });
922
+ } else {
923
+ try {
924
+ const { quarantinePath } = quarantineRogueCleoDir(report, projectRoot);
925
+ quarantined.push({
926
+ packageName: report.packageName,
927
+ from: report.path,
928
+ to: quarantinePath
929
+ });
930
+ } catch (err) {
931
+ errors.push({
932
+ packageName: report.packageName,
933
+ path: report.path,
934
+ error: err instanceof Error ? err.message : String(err)
935
+ });
936
+ }
937
+ }
938
+ }
939
+ const verb = isDryRun ? "Would quarantine" : "Quarantined";
940
+ progress.complete(
941
+ `${verb} ${quarantined.length} director${quarantined.length === 1 ? "y" : "ies"}${errors.length > 0 ? `, ${errors.length} failed` : ""}`
942
+ );
943
+ cliOutput(
944
+ { dryRun: isDryRun, quarantined, errors },
945
+ { command: "doctor", operation: "doctor.quarantine-rogue-dirs" }
946
+ );
947
+ if (errors.length > 0) {
948
+ process.exitCode = 1;
949
+ }
950
+ } else if (args["scan-stray-nexus-dbs"]) {
951
+ progress.step(0, "Scanning for stray nexus.db files");
952
+ const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
953
+ const { getCleoHome } = await import("@cleocode/core");
954
+ const cleoHome = getCleoHome();
955
+ const projectRoot = getProjectRoot2();
956
+ const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
957
+ const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
958
+ const isDryRun = args["dry-run"] === true;
959
+ const report = {
960
+ cleoHome,
961
+ projectRoot,
962
+ legacy: {
963
+ removed: legacyResult.removed.length,
964
+ files: legacyResult.removed
965
+ },
966
+ stray: {
967
+ removed: strayResult.removed,
968
+ path: strayResult.path
969
+ },
970
+ dryRun: isDryRun
971
+ };
972
+ progress.complete(
973
+ `Found ${legacyResult.removed.length} legacy + ${strayResult.removed ? 1 : 0} stray nexus.db`
974
+ );
975
+ cliOutput(report, { command: "doctor", operation: "doctor.scan-stray-nexus-dbs" });
976
+ } else if (args["audit-worktrees"]) {
977
+ progress.step(0, "Auditing orphaned agent worktrees");
978
+ const { auditOrphanWorktrees } = await import("@cleocode/core/gc/index.js");
979
+ const checkResult = auditOrphanWorktrees();
980
+ progress.complete(`Worktree audit complete \u2014 ${checkResult.status}`);
981
+ cliOutput(checkResult, { command: "doctor", operation: "doctor.audit-worktrees" });
982
+ if (checkResult.details?.["orphans"] && checkResult.details["orphans"].length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
983
+ process.exitCode = 2;
984
+ }
985
+ } else if (args["audit-worktree-orphans"]) {
986
+ progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
987
+ const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
988
+ const projectRoot = getProjectRoot2();
989
+ const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
990
+ const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
991
+ const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
992
+ const [comprehensive, legacyScanResult] = await Promise.all([
993
+ auditWorktreeOrphansComprehensive(projectRoot),
994
+ scanWorktreeOrphansBudgeted(projectRoot, {
995
+ timeoutMs,
996
+ maxEntriesPerLevel: Number.isFinite(maxEntriesPerLevel) ? maxEntriesPerLevel : 500
997
+ })
998
+ ]);
999
+ const legacyOrphans = legacyScanResult.orphans;
1000
+ const totalAnomalies = comprehensive.count;
1001
+ if (legacyScanResult.softWarnMessage) {
1002
+ pushWarning({
1003
+ code: "W_DOCTOR_SCAN_SOFT_WARN",
1004
+ message: legacyScanResult.softWarnMessage,
1005
+ severity: "warn"
1006
+ });
1007
+ }
1008
+ if (legacyScanResult.isPartial) {
1009
+ const reason = legacyScanResult.partialReason === "timeout" ? `timed out after ${timeoutSecs}s (use --timeout <seconds> to adjust)` : `per-level entry cap of ${maxEntriesPerLevel} exceeded (use --max-entries-per-level <n> to adjust)`;
1010
+ pushWarning({
1011
+ code: "W_DOCTOR_SCAN_PARTIAL",
1012
+ message: `legacy orphan scan is PARTIAL \u2014 ${reason}. Results may be incomplete.`,
1013
+ severity: "warn",
1014
+ context: {
1015
+ partialReason: legacyScanResult.partialReason,
1016
+ timeoutSecs,
1017
+ maxEntriesPerLevel
1018
+ }
1019
+ });
1020
+ }
1021
+ progress.complete(
1022
+ `Found ${totalAnomalies} anomal${totalAnomalies === 1 ? "y" : "ies"}` + (legacyOrphans.length > 0 ? ` (${legacyOrphans.length} legacy orphan(s))` : "") + (legacyScanResult.isPartial ? " [PARTIAL]" : "")
1023
+ );
1024
+ cliOutput(
1025
+ {
1026
+ projectRoot,
1027
+ comprehensive,
1028
+ legacyOrphans,
1029
+ legacyScanPartial: legacyScanResult.isPartial,
1030
+ legacyScanPartialReason: legacyScanResult.partialReason,
1031
+ count: totalAnomalies
1032
+ },
1033
+ { command: "doctor", operation: "doctor.audit-worktree-orphans" }
1034
+ );
1035
+ if (totalAnomalies > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
1036
+ process.exitCode = 2;
1037
+ }
1038
+ } else if (args["prune-worktree-orphans"]) {
1039
+ const isDryRun = args["dry-run"] === true;
1040
+ progress.step(
1041
+ 0,
1042
+ `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
1043
+ );
1044
+ const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
1045
+ const projectRoot = getProjectRoot2();
1046
+ const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
1047
+ const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
1048
+ const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
1049
+ const scanResult = await scanWorktreeOrphansBudgeted(projectRoot, {
1050
+ timeoutMs,
1051
+ maxEntriesPerLevel: Number.isFinite(maxEntriesPerLevel) ? maxEntriesPerLevel : 500
1052
+ });
1053
+ if (scanResult.softWarnMessage) {
1054
+ pushWarning({
1055
+ code: "W_DOCTOR_SCAN_SOFT_WARN",
1056
+ message: scanResult.softWarnMessage,
1057
+ severity: "warn"
1058
+ });
1059
+ }
1060
+ if (scanResult.isPartial) {
1061
+ const reason = scanResult.partialReason === "timeout" ? `timed out after ${timeoutSecs}s (use --timeout <seconds> to adjust)` : `per-level entry cap of ${maxEntriesPerLevel} exceeded (use --max-entries-per-level <n> to adjust)`;
1062
+ pushWarning({
1063
+ code: "W_DOCTOR_SCAN_PARTIAL",
1064
+ message: `orphan scan is PARTIAL \u2014 ${reason}. Only orphans found before abort will be pruned.`,
1065
+ severity: "warn",
1066
+ context: {
1067
+ partialReason: scanResult.partialReason,
1068
+ timeoutSecs,
1069
+ maxEntriesPerLevel
1070
+ }
1071
+ });
1072
+ }
1073
+ const orphans = scanResult.orphans;
1074
+ if (orphans.length === 0) {
1075
+ progress.complete(
1076
+ `No worktree orphans found \u2014 nothing to prune${scanResult.isPartial ? " [PARTIAL SCAN]" : ""}`
1077
+ );
1078
+ cliOutput(
1079
+ {
1080
+ projectRoot,
1081
+ dryRun: isDryRun,
1082
+ archivePath: null,
1083
+ pruned: [],
1084
+ rejected: [],
1085
+ totalSizeBytes: 0,
1086
+ scanPartial: scanResult.isPartial,
1087
+ scanPartialReason: scanResult.partialReason
1088
+ },
1089
+ { command: "doctor", operation: "doctor.prune-worktree-orphans" }
1090
+ );
1091
+ return;
1092
+ }
1093
+ const archiveDir = join(projectRoot, ".cleo", "backups");
1094
+ const auditLogPath = join(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
1095
+ const result = await pruneWorktreeOrphans(orphans, {
1096
+ archiveDir,
1097
+ auditLogPath,
1098
+ dryRun: isDryRun,
1099
+ projectRoot
1100
+ });
1101
+ const verb = isDryRun ? "Would prune" : "Pruned";
1102
+ progress.complete(
1103
+ `${verb} ${result.pruned.length} orphan${result.pruned.length === 1 ? "" : "s"}${result.rejected.length > 0 ? `, ${result.rejected.length} rejected` : ""}${scanResult.isPartial ? " [PARTIAL SCAN]" : ""}`
1104
+ );
1105
+ cliOutput(
1106
+ {
1107
+ projectRoot,
1108
+ ...result,
1109
+ scanPartial: scanResult.isPartial,
1110
+ scanPartialReason: scanResult.partialReason
1111
+ },
1112
+ { command: "doctor", operation: "doctor.prune-worktree-orphans" }
1113
+ );
1114
+ if (result.rejected.length > 0) {
1115
+ process.exitCode = 1;
1116
+ }
1117
+ } else if (args["migrate-worktree-include"]) {
1118
+ const isDryRun = args["dry-run"] === true;
1119
+ progress.step(
1120
+ 0,
1121
+ `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
1122
+ );
1123
+ const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
1124
+ const projectRoot = getProjectRoot2();
1125
+ const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
1126
+ progress.complete(`Migration ${result.action}`);
1127
+ cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
1128
+ } else if (args["audit-temp"]) {
1129
+ progress.step(0, "Auditing orphaned CLEO temp directories");
1130
+ const { auditOrphanTempDirs } = await import("@cleocode/core/gc/index.js");
1131
+ const checkResult = await auditOrphanTempDirs();
1132
+ progress.complete(`Temp audit complete \u2014 ${checkResult.status}`);
1133
+ cliOutput(checkResult, { command: "doctor", operation: "doctor.audit-temp" });
1134
+ if (checkResult.details?.["orphans"] && checkResult.details["orphans"].length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
1135
+ process.exitCode = 2;
1136
+ }
1137
+ } else if (args["audit-invariants"] || args["audit-sagas"]) {
1138
+ const isFocusedAlias = args["audit-sagas"] === true && args["audit-invariants"] !== true;
1139
+ const adrFilter = isFocusedAlias ? "ADR-073" : void 0;
1140
+ const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
1141
+ progress.step(0, stepLabel);
1142
+ const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
1143
+ const projectRoot = getProjectRoot2();
1144
+ const result = await auditInvariantRegistry(projectRoot, { adrFilter });
1145
+ const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
1146
+ const summary = `Invariant audit complete \u2014 ${result.totalCount} entries walked, ${result.errorCount} error / ${result.warningCount} warning / ${result.infoCount} info violation(s), ${result.notApplicableCount} not-applicable, ${result.documentedCount} documented`;
1147
+ progress.complete(summary);
1148
+ if (isHuman && args.json !== true) {
1149
+ renderInvariantAuditHuman(result);
1150
+ }
1151
+ cliOutput(result, { command: "doctor", operation });
1152
+ if (result.errorCount > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
1153
+ process.exitCode = 2;
1154
+ }
1155
+ } else {
1156
+ progress.step(0, "Checking CLEO directory");
1157
+ await dispatchFromCli(
1158
+ "query",
1159
+ "admin",
1160
+ "health",
1161
+ { detailed: args.detailed },
1162
+ { command: "doctor", operation: "admin.health" }
1163
+ );
1164
+ try {
1165
+ const projectRoot = getProjectRoot2();
1166
+ const conflicts = readMigrationConflicts(projectRoot);
1167
+ if (conflicts.length > 0) {
1168
+ progress.complete(
1169
+ `Health check complete \u2014 ${conflicts.length} agent migration conflict(s) detected`
1170
+ );
1171
+ humanLine(
1172
+ `
1173
+ [MIGRATE-AGENTS-V2-CONFLICT] ${conflicts.length} agent(s) have conflicting .cant content between disk and signaldock.db:`
1174
+ );
1175
+ for (const c of conflicts) {
1176
+ humanLine(
1177
+ ` - ${c.agentName} (${c.filePath})
1178
+ disk sha256: ${c.newSha256 ?? "unknown"}
1179
+ registry sha256: ${c.existingSha256 ?? "unknown"}
1180
+ Resolve: inspect the conflict and either update the registry via
1181
+ 'cleo agent install --force <path>' or remove the conflicting file.`
1182
+ );
1183
+ }
1184
+ humanLine(` Audit log: .cleo/audit/migration-agents-v2.jsonl
1185
+ `);
1186
+ if (process.exitCode === void 0 || process.exitCode === 0) {
1187
+ process.exitCode = 2;
1188
+ }
1189
+ } else {
1190
+ progress.complete("Health check complete");
1191
+ }
1192
+ } catch {
1193
+ progress.complete("Health check complete");
1194
+ }
1195
+ try {
1196
+ const projectRoot = getProjectRoot2();
1197
+ const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
1198
+ const sagaAudit = await auditSagaHierarchy(projectRoot);
1199
+ if (sagaAudit.sagas.length === 0) {
1200
+ humanLine("\nSaga Hierarchy: no sagas found in tasks.db");
1201
+ } else {
1202
+ const header = `
1203
+ Saga Hierarchy (${sagaAudit.sagas.length} saga(s), ${sagaAudit.count} violation(s), ${sagaAudit.driftCount} drift warning(s)):`;
1204
+ humanLine(header);
1205
+ for (const s of sagaAudit.sagas) {
1206
+ const violationSuffix = s.violations.length > 0 ? `, ${s.violations.length} violation(s)` : "";
1207
+ humanLine(
1208
+ ` ${s.sagaId} \xB7 status=${s.status} \xB7 ${s.doneCount}/${s.memberCount} members done${violationSuffix}`
1209
+ );
1210
+ for (const v of s.violations) {
1211
+ humanLine(` [${v.kind}] ${v.message}`);
1212
+ }
1213
+ }
1214
+ }
1215
+ if (sagaAudit.count > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
1216
+ process.exitCode = 2;
1217
+ }
1218
+ } catch (err) {
1219
+ const msg = err instanceof Error ? err.message : String(err);
1220
+ humanLine(`
1221
+ Saga Hierarchy: audit skipped (${msg})`);
1222
+ }
1223
+ try {
1224
+ const { scanDependencyCycles } = await import("@cleocode/core/doctor/dependency-cycles.js");
1225
+ const cycles = await scanDependencyCycles(getProjectRoot2());
1226
+ humanLine(
1227
+ `
1228
+ Dependency cycles: ${cycles.cycleCount} (${cycles.edgeCount} edge(s) checked)`
1229
+ );
1230
+ for (const c of cycles.components) humanLine(` ${c.cycle.join(" \u2192 ")}`);
1231
+ if (cycles.repairPlan.length > 0) {
1232
+ humanLine(" Repair plan (review first; `cleo doctor dep-cycles` for JSON):");
1233
+ for (const r of cycles.repairPlan) humanLine(` ${r.command}`);
1234
+ }
1235
+ if (cycles.cycleCount > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
1236
+ process.exitCode = 2;
1237
+ }
1238
+ } catch (err) {
1239
+ const msg = err instanceof Error ? err.message : String(err);
1240
+ humanLine(`
1241
+ Dependency cycles: check skipped (${msg})`);
1242
+ }
1243
+ }
1244
+ } catch (err) {
1245
+ progress.error("Health check failed");
1246
+ throw err;
1247
+ }
1248
+ }
1249
+ });
1250
+ export {
1251
+ doctorCommand
1252
+ };
1253
+ //# sourceMappingURL=doctor-AX5TICQO.js.map