@cleocode/core 2026.9.20 → 2026.9.21

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 (855) hide show
  1. package/dist/adapters/discovery.d.ts.map +1 -1
  2. package/dist/adapters/discovery.js +3 -10
  3. package/dist/adapters/discovery.js.map +1 -1
  4. package/dist/adrs/link-pipeline.js +2 -2
  5. package/dist/adrs/link-pipeline.js.map +1 -1
  6. package/dist/adrs/parse.js +3 -3
  7. package/dist/adrs/parse.js.map +1 -1
  8. package/dist/agents/invoke-meta-agent.d.ts.map +1 -1
  9. package/dist/agents/invoke-meta-agent.js +8 -4
  10. package/dist/agents/invoke-meta-agent.js.map +1 -1
  11. package/dist/bootstrap.d.ts +5 -1
  12. package/dist/bootstrap.d.ts.map +1 -1
  13. package/dist/bootstrap.js +41 -21
  14. package/dist/bootstrap.js.map +1 -1
  15. package/dist/cloud/crypto.d.ts +47 -0
  16. package/dist/cloud/crypto.d.ts.map +1 -0
  17. package/dist/cloud/crypto.js +223 -0
  18. package/dist/cloud/crypto.js.map +1 -0
  19. package/dist/cloud/http.d.ts +52 -0
  20. package/dist/cloud/http.d.ts.map +1 -0
  21. package/dist/cloud/http.js +98 -0
  22. package/dist/cloud/http.js.map +1 -0
  23. package/dist/cloud/index.d.ts +19 -0
  24. package/dist/cloud/index.d.ts.map +1 -0
  25. package/dist/cloud/index.js +19 -0
  26. package/dist/cloud/index.js.map +1 -0
  27. package/dist/cloud/journal.d.ts +169 -0
  28. package/dist/cloud/journal.d.ts.map +1 -0
  29. package/dist/cloud/journal.js +428 -0
  30. package/dist/cloud/journal.js.map +1 -0
  31. package/dist/cloud/keys.d.ts +213 -0
  32. package/dist/cloud/keys.d.ts.map +1 -0
  33. package/dist/cloud/keys.js +362 -0
  34. package/dist/cloud/keys.js.map +1 -0
  35. package/dist/cloud/manifest-check.d.ts +36 -0
  36. package/dist/cloud/manifest-check.d.ts.map +1 -0
  37. package/dist/cloud/manifest-check.js +70 -0
  38. package/dist/cloud/manifest-check.js.map +1 -0
  39. package/dist/cloud/projects.d.ts +13 -0
  40. package/dist/cloud/projects.d.ts.map +1 -0
  41. package/dist/cloud/projects.js +11 -0
  42. package/dist/cloud/projects.js.map +1 -0
  43. package/dist/cloud/signing.d.ts +105 -0
  44. package/dist/cloud/signing.d.ts.map +1 -0
  45. package/dist/cloud/signing.js +117 -0
  46. package/dist/cloud/signing.js.map +1 -0
  47. package/dist/cloud/streams.d.ts +6 -0
  48. package/dist/cloud/streams.d.ts.map +1 -0
  49. package/dist/cloud/streams.js +5 -0
  50. package/dist/cloud/streams.js.map +1 -0
  51. package/dist/decide/audit.d.ts +131 -0
  52. package/dist/decide/audit.d.ts.map +1 -0
  53. package/dist/decide/audit.js +98 -0
  54. package/dist/decide/audit.js.map +1 -0
  55. package/dist/decide/budget.d.ts +91 -0
  56. package/dist/decide/budget.d.ts.map +1 -0
  57. package/dist/decide/budget.js +194 -0
  58. package/dist/decide/budget.js.map +1 -0
  59. package/dist/decide/cache.d.ts +49 -0
  60. package/dist/decide/cache.d.ts.map +1 -0
  61. package/dist/decide/cache.js +87 -0
  62. package/dist/decide/cache.js.map +1 -0
  63. package/dist/decide/client.d.ts +103 -0
  64. package/dist/decide/client.d.ts.map +1 -0
  65. package/dist/decide/client.js +262 -0
  66. package/dist/decide/client.js.map +1 -0
  67. package/dist/decide/credentials.d.ts +159 -0
  68. package/dist/decide/credentials.d.ts.map +1 -0
  69. package/dist/decide/credentials.js +383 -0
  70. package/dist/decide/credentials.js.map +1 -0
  71. package/dist/decide/index.d.ts +18 -0
  72. package/dist/decide/index.d.ts.map +1 -0
  73. package/dist/decide/index.js +18 -0
  74. package/dist/decide/index.js.map +1 -0
  75. package/dist/decide/jev-wire.d.ts +155 -0
  76. package/dist/decide/jev-wire.d.ts.map +1 -0
  77. package/dist/decide/jev-wire.js +420 -0
  78. package/dist/decide/jev-wire.js.map +1 -0
  79. package/dist/decide/operations.d.ts +152 -0
  80. package/dist/decide/operations.d.ts.map +1 -0
  81. package/dist/decide/operations.js +199 -0
  82. package/dist/decide/operations.js.map +1 -0
  83. package/dist/decide/provider.d.ts +90 -0
  84. package/dist/decide/provider.d.ts.map +1 -0
  85. package/dist/decide/provider.js +43 -0
  86. package/dist/decide/provider.js.map +1 -0
  87. package/dist/decide/site.d.ts +148 -0
  88. package/dist/decide/site.d.ts.map +1 -0
  89. package/dist/decide/site.js +181 -0
  90. package/dist/decide/site.js.map +1 -0
  91. package/dist/decide/transport.d.ts +67 -0
  92. package/dist/decide/transport.d.ts.map +1 -0
  93. package/dist/decide/transport.js +350 -0
  94. package/dist/decide/transport.js.map +1 -0
  95. package/dist/docs/export-document.js +5908 -2436
  96. package/dist/docs/export-document.js.map +3 -3
  97. package/dist/docs/index.d.ts +2 -2
  98. package/dist/docs/index.d.ts.map +1 -1
  99. package/dist/docs/index.js +1 -1
  100. package/dist/docs/index.js.map +1 -1
  101. package/dist/docs/projection.d.ts.map +1 -1
  102. package/dist/docs/projection.js +2 -3
  103. package/dist/docs/projection.js.map +1 -1
  104. package/dist/docs/publish-pr.d.ts +69 -1
  105. package/dist/docs/publish-pr.d.ts.map +1 -1
  106. package/dist/docs/publish-pr.js +112 -10
  107. package/dist/docs/publish-pr.js.map +1 -1
  108. package/dist/doctor/db-substrate.d.ts +13 -8
  109. package/dist/doctor/db-substrate.d.ts.map +1 -1
  110. package/dist/doctor/db-substrate.js +39 -26
  111. package/dist/doctor/db-substrate.js.map +1 -1
  112. package/dist/doctor/index.d.ts +2 -0
  113. package/dist/doctor/index.d.ts.map +1 -1
  114. package/dist/doctor/index.js +1 -0
  115. package/dist/doctor/index.js.map +1 -1
  116. package/dist/doctor/knowledge.d.ts.map +1 -1
  117. package/dist/doctor/knowledge.js +5 -15
  118. package/dist/doctor/knowledge.js.map +1 -1
  119. package/dist/doctor/nexus-schema-residency.d.ts +1 -1
  120. package/dist/doctor/nexus-schema-residency.d.ts.map +1 -1
  121. package/dist/doctor/nexus-schema-residency.js +3 -0
  122. package/dist/doctor/nexus-schema-residency.js.map +1 -1
  123. package/dist/doctor/project-identity.d.ts +44 -1
  124. package/dist/doctor/project-identity.d.ts.map +1 -1
  125. package/dist/doctor/project-identity.js +237 -10
  126. package/dist/doctor/project-identity.js.map +1 -1
  127. package/dist/doctor/projects.d.ts +170 -0
  128. package/dist/doctor/projects.d.ts.map +1 -0
  129. package/dist/doctor/projects.js +1075 -0
  130. package/dist/doctor/projects.js.map +1 -0
  131. package/dist/doctor/twin-collapse.d.ts +97 -0
  132. package/dist/doctor/twin-collapse.d.ts.map +1 -0
  133. package/dist/doctor/twin-collapse.js +168 -0
  134. package/dist/doctor/twin-collapse.js.map +1 -0
  135. package/dist/doctor/worktree-orphans.d.ts.map +1 -1
  136. package/dist/doctor/worktree-orphans.js +13 -29
  137. package/dist/doctor/worktree-orphans.js.map +1 -1
  138. package/dist/doctor/worktree-stores.d.ts +128 -0
  139. package/dist/doctor/worktree-stores.d.ts.map +1 -0
  140. package/dist/doctor/worktree-stores.js +374 -0
  141. package/dist/doctor/worktree-stores.js.map +1 -0
  142. package/dist/error-catalog.d.ts.map +1 -1
  143. package/dist/error-catalog.js +21 -0
  144. package/dist/error-catalog.js.map +1 -1
  145. package/dist/error-registry.d.ts.map +1 -1
  146. package/dist/error-registry.js +40 -0
  147. package/dist/error-registry.js.map +1 -1
  148. package/dist/gc/cleanup.d.ts.map +1 -1
  149. package/dist/gc/cleanup.js +32 -19
  150. package/dist/gc/cleanup.js.map +1 -1
  151. package/dist/git/bounded-git.d.ts +170 -0
  152. package/dist/git/bounded-git.d.ts.map +1 -0
  153. package/dist/git/bounded-git.js +371 -0
  154. package/dist/git/bounded-git.js.map +1 -0
  155. package/dist/git/work-tree.d.ts +20 -0
  156. package/dist/git/work-tree.d.ts.map +1 -1
  157. package/dist/git/work-tree.js +20 -2
  158. package/dist/git/work-tree.js.map +1 -1
  159. package/dist/hooks/handlers/session-hooks.d.ts +11 -26
  160. package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
  161. package/dist/hooks/handlers/session-hooks.js +18 -47
  162. package/dist/hooks/handlers/session-hooks.js.map +1 -1
  163. package/dist/hooks/payload-schemas.d.ts +2 -2
  164. package/dist/index.d.ts +6 -5
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +5 -3
  167. package/dist/index.js.map +1 -1
  168. package/dist/init/engine-ops.d.ts.map +1 -1
  169. package/dist/init/engine-ops.js +23 -1
  170. package/dist/init/engine-ops.js.map +1 -1
  171. package/dist/init.d.ts +158 -1
  172. package/dist/init.d.ts.map +1 -1
  173. package/dist/init.js +527 -42
  174. package/dist/init.js.map +1 -1
  175. package/dist/injection.d.ts +55 -0
  176. package/dist/injection.d.ts.map +1 -1
  177. package/dist/injection.js +102 -6
  178. package/dist/injection.js.map +1 -1
  179. package/dist/internal.d.ts +9 -5
  180. package/dist/internal.d.ts.map +1 -1
  181. package/dist/internal.js +8 -4
  182. package/dist/internal.js.map +1 -1
  183. package/dist/issue/diagnostics.d.ts.map +1 -1
  184. package/dist/issue/diagnostics.js +2 -1
  185. package/dist/issue/diagnostics.js.map +1 -1
  186. package/dist/lib/concurrency.d.ts +25 -0
  187. package/dist/lib/concurrency.d.ts.map +1 -0
  188. package/dist/lib/concurrency.js +43 -0
  189. package/dist/lib/concurrency.js.map +1 -0
  190. package/dist/lib/index.d.ts +1 -0
  191. package/dist/lib/index.d.ts.map +1 -1
  192. package/dist/lib/index.js +1 -0
  193. package/dist/lib/index.js.map +1 -1
  194. package/dist/lifecycle/engine-ops.d.ts.map +1 -1
  195. package/dist/lifecycle/engine-ops.js +4 -2
  196. package/dist/lifecycle/engine-ops.js.map +1 -1
  197. package/dist/lifecycle/stage-guidance.d.ts +5 -0
  198. package/dist/lifecycle/stage-guidance.d.ts.map +1 -1
  199. package/dist/lifecycle/stage-guidance.js +14 -4
  200. package/dist/lifecycle/stage-guidance.js.map +1 -1
  201. package/dist/llm/catalog-cache.d.ts +3 -2
  202. package/dist/llm/catalog-cache.d.ts.map +1 -1
  203. package/dist/llm/catalog-cache.js +5 -5
  204. package/dist/llm/catalog-cache.js.map +1 -1
  205. package/dist/llm/credentials.d.ts +4 -4
  206. package/dist/llm/credentials.js +6 -6
  207. package/dist/llm/credentials.js.map +1 -1
  208. package/dist/llm/plugin-facade.js +4312 -1798
  209. package/dist/llm/plugin-facade.js.map +3 -3
  210. package/dist/llm/stable-device-id.d.ts.map +1 -1
  211. package/dist/llm/stable-device-id.js +3 -5
  212. package/dist/llm/stable-device-id.js.map +1 -1
  213. package/dist/memory/attention.d.ts.map +1 -1
  214. package/dist/memory/attention.js +30 -30
  215. package/dist/memory/attention.js.map +1 -1
  216. package/dist/memory/decision-contradiction.d.ts +152 -0
  217. package/dist/memory/decision-contradiction.d.ts.map +1 -0
  218. package/dist/memory/decision-contradiction.js +273 -0
  219. package/dist/memory/decision-contradiction.js.map +1 -0
  220. package/dist/memory/decisions.d.ts +42 -11
  221. package/dist/memory/decisions.d.ts.map +1 -1
  222. package/dist/memory/decisions.js +153 -56
  223. package/dist/memory/decisions.js.map +1 -1
  224. package/dist/memory/dialectic-evaluator.d.ts +7 -0
  225. package/dist/memory/dialectic-evaluator.d.ts.map +1 -1
  226. package/dist/memory/dialectic-evaluator.js +23 -8
  227. package/dist/memory/dialectic-evaluator.js.map +1 -1
  228. package/dist/memory/dispatch-trace-format.d.ts +39 -0
  229. package/dist/memory/dispatch-trace-format.d.ts.map +1 -0
  230. package/dist/memory/dispatch-trace-format.js +54 -0
  231. package/dist/memory/dispatch-trace-format.js.map +1 -0
  232. package/dist/memory/dispatch-trace.d.ts.map +1 -1
  233. package/dist/memory/dispatch-trace.js +1 -27
  234. package/dist/memory/dispatch-trace.js.map +1 -1
  235. package/dist/memory/engine-compat.d.ts +2 -0
  236. package/dist/memory/engine-compat.d.ts.map +1 -1
  237. package/dist/memory/engine-compat.js +1 -0
  238. package/dist/memory/engine-compat.js.map +1 -1
  239. package/dist/memory/import-from-provider.js +3 -3
  240. package/dist/memory/import-from-provider.js.map +1 -1
  241. package/dist/memory/learnings.d.ts +2 -2
  242. package/dist/memory/observation-type-decision.d.ts +96 -0
  243. package/dist/memory/observation-type-decision.d.ts.map +1 -0
  244. package/dist/memory/observation-type-decision.js +218 -0
  245. package/dist/memory/observation-type-decision.js.map +1 -0
  246. package/dist/memory/redaction.js +2 -0
  247. package/dist/memory/redaction.js.map +1 -1
  248. package/dist/memory/retrieval/build-retrieval-bundle.d.ts +9 -2
  249. package/dist/memory/retrieval/build-retrieval-bundle.d.ts.map +1 -1
  250. package/dist/memory/retrieval/build-retrieval-bundle.js +42 -11
  251. package/dist/memory/retrieval/build-retrieval-bundle.js.map +1 -1
  252. package/dist/memory/retrieval/get-current-session-id.d.ts +5 -0
  253. package/dist/memory/retrieval/get-current-session-id.d.ts.map +1 -1
  254. package/dist/memory/retrieval/get-current-session-id.js +7 -2
  255. package/dist/memory/retrieval/get-current-session-id.js.map +1 -1
  256. package/dist/memory/retrieval/observe.d.ts.map +1 -1
  257. package/dist/memory/retrieval/observe.js +30 -29
  258. package/dist/memory/retrieval/observe.js.map +1 -1
  259. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  260. package/dist/nexus/analyze-orchestrator.js +42 -29
  261. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  262. package/dist/nexus/assessment-projection.d.ts +76 -0
  263. package/dist/nexus/assessment-projection.d.ts.map +1 -0
  264. package/dist/nexus/assessment-projection.js +143 -0
  265. package/dist/nexus/assessment-projection.js.map +1 -0
  266. package/dist/nexus/assessment-store.d.ts +14 -2
  267. package/dist/nexus/assessment-store.d.ts.map +1 -1
  268. package/dist/nexus/assessment-store.js +21 -3
  269. package/dist/nexus/assessment-store.js.map +1 -1
  270. package/dist/nexus/checkout-nonce.d.ts +48 -0
  271. package/dist/nexus/checkout-nonce.d.ts.map +1 -0
  272. package/dist/nexus/checkout-nonce.js +84 -0
  273. package/dist/nexus/checkout-nonce.js.map +1 -0
  274. package/dist/nexus/devices.d.ts +93 -0
  275. package/dist/nexus/devices.d.ts.map +1 -0
  276. package/dist/nexus/devices.js +141 -0
  277. package/dist/nexus/devices.js.map +1 -0
  278. package/dist/nexus/freshness.d.ts.map +1 -1
  279. package/dist/nexus/freshness.js +25 -6
  280. package/dist/nexus/freshness.js.map +1 -1
  281. package/dist/nexus/git-state.d.ts +225 -0
  282. package/dist/nexus/git-state.d.ts.map +1 -0
  283. package/dist/nexus/git-state.js +677 -0
  284. package/dist/nexus/git-state.js.map +1 -0
  285. package/dist/nexus/graph-manifest.d.ts +20 -4
  286. package/dist/nexus/graph-manifest.d.ts.map +1 -1
  287. package/dist/nexus/graph-manifest.js +40 -5
  288. package/dist/nexus/graph-manifest.js.map +1 -1
  289. package/dist/nexus/identity.d.ts +68 -23
  290. package/dist/nexus/identity.d.ts.map +1 -1
  291. package/dist/nexus/identity.js +99 -22
  292. package/dist/nexus/identity.js.map +1 -1
  293. package/dist/nexus/index.d.ts +5 -2
  294. package/dist/nexus/index.d.ts.map +1 -1
  295. package/dist/nexus/index.js +10 -4
  296. package/dist/nexus/index.js.map +1 -1
  297. package/dist/nexus/knowledge.d.ts +5 -0
  298. package/dist/nexus/knowledge.d.ts.map +1 -1
  299. package/dist/nexus/knowledge.js +26 -2
  300. package/dist/nexus/knowledge.js.map +1 -1
  301. package/dist/nexus/legacy-alias.d.ts +60 -0
  302. package/dist/nexus/legacy-alias.d.ts.map +1 -0
  303. package/dist/nexus/legacy-alias.js +68 -0
  304. package/dist/nexus/legacy-alias.js.map +1 -0
  305. package/dist/nexus/migrate-json-to-sqlite.js +2 -2
  306. package/dist/nexus/migrate-json-to-sqlite.js.map +1 -1
  307. package/dist/nexus/ops.d.ts +1 -0
  308. package/dist/nexus/ops.d.ts.map +1 -1
  309. package/dist/nexus/path-map.d.ts +264 -20
  310. package/dist/nexus/path-map.d.ts.map +1 -1
  311. package/dist/nexus/path-map.js +580 -44
  312. package/dist/nexus/path-map.js.map +1 -1
  313. package/dist/nexus/projects-clean.d.ts +9 -1
  314. package/dist/nexus/projects-clean.d.ts.map +1 -1
  315. package/dist/nexus/projects-clean.js +126 -14
  316. package/dist/nexus/projects-clean.js.map +1 -1
  317. package/dist/nexus/projects-scan.d.ts +56 -1
  318. package/dist/nexus/projects-scan.d.ts.map +1 -1
  319. package/dist/nexus/projects-scan.js +144 -3
  320. package/dist/nexus/projects-scan.js.map +1 -1
  321. package/dist/nexus/registry-hygiene.d.ts +18 -2
  322. package/dist/nexus/registry-hygiene.d.ts.map +1 -1
  323. package/dist/nexus/registry-hygiene.js +37 -11
  324. package/dist/nexus/registry-hygiene.js.map +1 -1
  325. package/dist/nexus/registry-roots.d.ts +47 -0
  326. package/dist/nexus/registry-roots.d.ts.map +1 -0
  327. package/dist/nexus/registry-roots.js +79 -0
  328. package/dist/nexus/registry-roots.js.map +1 -0
  329. package/dist/nexus/registry.d.ts +50 -9
  330. package/dist/nexus/registry.d.ts.map +1 -1
  331. package/dist/nexus/registry.js +311 -156
  332. package/dist/nexus/registry.js.map +1 -1
  333. package/dist/nexus/stored-roots.d.ts +106 -0
  334. package/dist/nexus/stored-roots.d.ts.map +1 -0
  335. package/dist/nexus/stored-roots.js +180 -0
  336. package/dist/nexus/stored-roots.js.map +1 -0
  337. package/dist/nexus/transfer.d.ts.map +1 -1
  338. package/dist/nexus/transfer.js +3 -0
  339. package/dist/nexus/transfer.js.map +1 -1
  340. package/dist/nexus/user-profile-hygiene.d.ts +168 -0
  341. package/dist/nexus/user-profile-hygiene.d.ts.map +1 -0
  342. package/dist/nexus/user-profile-hygiene.js +305 -0
  343. package/dist/nexus/user-profile-hygiene.js.map +1 -0
  344. package/dist/nexus/user-profile.d.ts +53 -2
  345. package/dist/nexus/user-profile.d.ts.map +1 -1
  346. package/dist/nexus/user-profile.js +106 -4
  347. package/dist/nexus/user-profile.js.map +1 -1
  348. package/dist/orchestrate/pivot.d.ts.map +1 -1
  349. package/dist/orchestrate/pivot.js +5 -1
  350. package/dist/orchestrate/pivot.js.map +1 -1
  351. package/dist/orchestrate/spawn-ops.d.ts +12 -0
  352. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  353. package/dist/orchestrate/spawn-ops.js +152 -57
  354. package/dist/orchestrate/spawn-ops.js.map +1 -1
  355. package/dist/orchestration/classify-readiness.d.ts +37 -1
  356. package/dist/orchestration/classify-readiness.d.ts.map +1 -1
  357. package/dist/orchestration/classify-readiness.js +48 -19
  358. package/dist/orchestration/classify-readiness.js.map +1 -1
  359. package/dist/orchestration/index.d.ts +3 -2
  360. package/dist/orchestration/index.d.ts.map +1 -1
  361. package/dist/orchestration/index.js +2 -1
  362. package/dist/orchestration/index.js.map +1 -1
  363. package/dist/orchestration/owner-decision-readiness.d.ts +88 -0
  364. package/dist/orchestration/owner-decision-readiness.d.ts.map +1 -0
  365. package/dist/orchestration/owner-decision-readiness.js +152 -0
  366. package/dist/orchestration/owner-decision-readiness.js.map +1 -0
  367. package/dist/orchestration/psyche-memory-budget.d.ts +105 -0
  368. package/dist/orchestration/psyche-memory-budget.d.ts.map +1 -0
  369. package/dist/orchestration/psyche-memory-budget.js +383 -0
  370. package/dist/orchestration/psyche-memory-budget.js.map +1 -0
  371. package/dist/orchestration/spawn-prompt.d.ts +12 -1
  372. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  373. package/dist/orchestration/spawn-prompt.js +141 -179
  374. package/dist/orchestration/spawn-prompt.js.map +1 -1
  375. package/dist/orchestration/spawn.d.ts +7 -0
  376. package/dist/orchestration/spawn.d.ts.map +1 -1
  377. package/dist/orchestration/spawn.js +1 -0
  378. package/dist/orchestration/spawn.js.map +1 -1
  379. package/dist/paths.d.ts +24 -8
  380. package/dist/paths.d.ts.map +1 -1
  381. package/dist/paths.js +135 -71
  382. package/dist/paths.js.map +1 -1
  383. package/dist/platform.d.ts +6 -1
  384. package/dist/platform.d.ts.map +1 -1
  385. package/dist/platform.js +8 -19
  386. package/dist/platform.js.map +1 -1
  387. package/dist/project-info.d.ts +18 -0
  388. package/dist/project-info.d.ts.map +1 -1
  389. package/dist/project-info.js +29 -1
  390. package/dist/project-info.js.map +1 -1
  391. package/dist/project-lifecycle.d.ts +91 -32
  392. package/dist/project-lifecycle.d.ts.map +1 -1
  393. package/dist/project-lifecycle.js +639 -75
  394. package/dist/project-lifecycle.js.map +1 -1
  395. package/dist/project-scope.d.ts +86 -4
  396. package/dist/project-scope.d.ts.map +1 -1
  397. package/dist/project-scope.js +226 -13
  398. package/dist/project-scope.js.map +1 -1
  399. package/dist/project-tombstone.d.ts +111 -0
  400. package/dist/project-tombstone.d.ts.map +1 -0
  401. package/dist/project-tombstone.js +220 -0
  402. package/dist/project-tombstone.js.map +1 -0
  403. package/dist/release/artifacts.d.ts.map +1 -1
  404. package/dist/release/artifacts.js +14 -9
  405. package/dist/release/artifacts.js.map +1 -1
  406. package/dist/release/ci-evidence.d.ts +223 -0
  407. package/dist/release/ci-evidence.d.ts.map +1 -0
  408. package/dist/release/ci-evidence.js +652 -0
  409. package/dist/release/ci-evidence.js.map +1 -0
  410. package/dist/release/engine-ops.d.ts.map +1 -1
  411. package/dist/release/engine-ops.js +3 -3
  412. package/dist/release/engine-ops.js.map +1 -1
  413. package/dist/release/plan.d.ts.map +1 -1
  414. package/dist/release/plan.js +7 -6
  415. package/dist/release/plan.js.map +1 -1
  416. package/dist/release/pr-evidence.d.ts +38 -0
  417. package/dist/release/pr-evidence.d.ts.map +1 -1
  418. package/dist/release/pr-evidence.js +67 -11
  419. package/dist/release/pr-evidence.js.map +1 -1
  420. package/dist/release/reconcile.d.ts.map +1 -1
  421. package/dist/release/reconcile.js +3 -2
  422. package/dist/release/reconcile.js.map +1 -1
  423. package/dist/release/release-manifest.d.ts +2 -1
  424. package/dist/release/release-manifest.d.ts.map +1 -1
  425. package/dist/release/release-manifest.js +6 -5
  426. package/dist/release/release-manifest.js.map +1 -1
  427. package/dist/render/nexus/graph/index.d.ts +4 -0
  428. package/dist/render/nexus/graph/index.d.ts.map +1 -1
  429. package/dist/render/nexus/graph/index.js +57 -0
  430. package/dist/render/nexus/graph/index.js.map +1 -1
  431. package/dist/resources/spawn-wrapper.d.ts +8 -1
  432. package/dist/resources/spawn-wrapper.d.ts.map +1 -1
  433. package/dist/resources/spawn-wrapper.js +42 -5
  434. package/dist/resources/spawn-wrapper.js.map +1 -1
  435. package/dist/routing/build-command-groups.d.ts.map +1 -1
  436. package/dist/routing/build-command-groups.js +1 -0
  437. package/dist/routing/build-command-groups.js.map +1 -1
  438. package/dist/sagas/index.d.ts +1 -1
  439. package/dist/sagas/index.d.ts.map +1 -1
  440. package/dist/sagas/index.js +1 -1
  441. package/dist/sagas/index.js.map +1 -1
  442. package/dist/sagas/reconcile.d.ts +24 -4
  443. package/dist/sagas/reconcile.d.ts.map +1 -1
  444. package/dist/sagas/reconcile.js +226 -100
  445. package/dist/sagas/reconcile.js.map +1 -1
  446. package/dist/scaffold/ensure-config.d.ts.map +1 -1
  447. package/dist/scaffold/ensure-config.js +31 -1
  448. package/dist/scaffold/ensure-config.js.map +1 -1
  449. package/dist/scaffold/project-identity.d.ts +2 -8
  450. package/dist/scaffold/project-identity.d.ts.map +1 -1
  451. package/dist/scaffold/project-identity.js +5 -21
  452. package/dist/scaffold/project-identity.js.map +1 -1
  453. package/dist/security/input-sanitization.d.ts +9 -1
  454. package/dist/security/input-sanitization.d.ts.map +1 -1
  455. package/dist/security/input-sanitization.js +12 -2
  456. package/dist/security/input-sanitization.js.map +1 -1
  457. package/dist/selfimprove/fix-gen.js +4321 -1807
  458. package/dist/selfimprove/fix-gen.js.map +3 -3
  459. package/dist/sentient/propose-tick.d.ts.map +1 -1
  460. package/dist/sentient/propose-tick.js +4 -2
  461. package/dist/sentient/propose-tick.js.map +1 -1
  462. package/dist/sequence/index.d.ts.map +1 -1
  463. package/dist/sequence/index.js +6 -23
  464. package/dist/sequence/index.js.map +1 -1
  465. package/dist/session/engine-ops.d.ts +9 -0
  466. package/dist/session/engine-ops.d.ts.map +1 -1
  467. package/dist/session/engine-ops.js +110 -18
  468. package/dist/session/engine-ops.js.map +1 -1
  469. package/dist/sessions/assumptions.d.ts.map +1 -1
  470. package/dist/sessions/assumptions.js +7 -4
  471. package/dist/sessions/assumptions.js.map +1 -1
  472. package/dist/sessions/briefing.d.ts +6 -0
  473. package/dist/sessions/briefing.d.ts.map +1 -1
  474. package/dist/sessions/briefing.js +12 -1
  475. package/dist/sessions/briefing.js.map +1 -1
  476. package/dist/sessions/decisions.d.ts +38 -3
  477. package/dist/sessions/decisions.d.ts.map +1 -1
  478. package/dist/sessions/decisions.js +235 -21
  479. package/dist/sessions/decisions.js.map +1 -1
  480. package/dist/sessions/drift-watchdog.d.ts.map +1 -1
  481. package/dist/sessions/drift-watchdog.js +4 -2
  482. package/dist/sessions/drift-watchdog.js.map +1 -1
  483. package/dist/sessions/index.d.ts.map +1 -1
  484. package/dist/sessions/index.js +33 -4
  485. package/dist/sessions/index.js.map +1 -1
  486. package/dist/sessions/session-end-snapshot-entry.d.ts +26 -0
  487. package/dist/sessions/session-end-snapshot-entry.d.ts.map +1 -0
  488. package/dist/sessions/session-end-snapshot-entry.js +59 -0
  489. package/dist/sessions/session-end-snapshot-entry.js.map +1 -0
  490. package/dist/sessions/session-end-snapshot.d.ts +114 -0
  491. package/dist/sessions/session-end-snapshot.d.ts.map +1 -0
  492. package/dist/sessions/session-end-snapshot.js +446 -0
  493. package/dist/sessions/session-end-snapshot.js.map +1 -0
  494. package/dist/sessions/session-manifest-mirror.d.ts.map +1 -1
  495. package/dist/sessions/session-manifest-mirror.js +10 -17
  496. package/dist/sessions/session-manifest-mirror.js.map +1 -1
  497. package/dist/sessions/session-switch.d.ts.map +1 -1
  498. package/dist/sessions/session-switch.js +5 -3
  499. package/dist/sessions/session-switch.js.map +1 -1
  500. package/dist/sessions/snapshot.d.ts.map +1 -1
  501. package/dist/sessions/snapshot.js +5 -4
  502. package/dist/sessions/snapshot.js.map +1 -1
  503. package/dist/sessions/terminal-identity.d.ts +169 -0
  504. package/dist/sessions/terminal-identity.d.ts.map +1 -0
  505. package/dist/sessions/terminal-identity.js +273 -0
  506. package/dist/sessions/terminal-identity.js.map +1 -0
  507. package/dist/setup/sections/verification.d.ts +1 -1
  508. package/dist/setup/sections/verification.d.ts.map +1 -1
  509. package/dist/setup/sections/verification.js +11 -15
  510. package/dist/setup/sections/verification.js.map +1 -1
  511. package/dist/skills/discovery.d.ts +8 -2
  512. package/dist/skills/discovery.d.ts.map +1 -1
  513. package/dist/skills/discovery.js +15 -3
  514. package/dist/skills/discovery.js.map +1 -1
  515. package/dist/skills/dispatch.d.ts +5 -2
  516. package/dist/skills/dispatch.d.ts.map +1 -1
  517. package/dist/skills/dispatch.js +5 -2
  518. package/dist/skills/dispatch.js.map +1 -1
  519. package/dist/skills/doctor.d.ts.map +1 -1
  520. package/dist/skills/doctor.js +5 -1
  521. package/dist/skills/doctor.js.map +1 -1
  522. package/dist/skills/federated-search.js +2 -2
  523. package/dist/skills/federated-search.js.map +1 -1
  524. package/dist/skills/index.d.ts +3 -3
  525. package/dist/skills/index.d.ts.map +1 -1
  526. package/dist/skills/index.js +1 -1
  527. package/dist/skills/index.js.map +1 -1
  528. package/dist/skills/migration.d.ts +5 -5
  529. package/dist/skills/migration.d.ts.map +1 -1
  530. package/dist/skills/migration.js +7 -9
  531. package/dist/skills/migration.js.map +1 -1
  532. package/dist/skills/orchestrator/startup.d.ts.map +1 -1
  533. package/dist/skills/orchestrator/startup.js +4 -2
  534. package/dist/skills/orchestrator/startup.js.map +1 -1
  535. package/dist/skills/skill-paths.d.ts +30 -3
  536. package/dist/skills/skill-paths.d.ts.map +1 -1
  537. package/dist/skills/skill-paths.js +28 -9
  538. package/dist/skills/skill-paths.js.map +1 -1
  539. package/dist/skills/skill-root.d.ts +60 -11
  540. package/dist/skills/skill-root.d.ts.map +1 -1
  541. package/dist/skills/skill-root.js +100 -14
  542. package/dist/skills/skill-root.js.map +1 -1
  543. package/dist/skills/skills-guard.js +5 -5
  544. package/dist/skills/skills-guard.js.map +1 -1
  545. package/dist/skills/types.d.ts +23 -0
  546. package/dist/skills/types.d.ts.map +1 -1
  547. package/dist/skills/types.js.map +1 -1
  548. package/dist/spawn/agent-identity.d.ts +51 -2
  549. package/dist/spawn/agent-identity.d.ts.map +1 -1
  550. package/dist/spawn/agent-identity.js +89 -26
  551. package/dist/spawn/agent-identity.js.map +1 -1
  552. package/dist/spawn/branch-lock.d.ts.map +1 -1
  553. package/dist/spawn/branch-lock.js +56 -79
  554. package/dist/spawn/branch-lock.js.map +1 -1
  555. package/dist/spawn/index.d.ts +2 -2
  556. package/dist/spawn/index.d.ts.map +1 -1
  557. package/dist/spawn/index.js +1 -1
  558. package/dist/spawn/index.js.map +1 -1
  559. package/dist/spawn/worktree-lock-holder.d.ts +37 -0
  560. package/dist/spawn/worktree-lock-holder.d.ts.map +1 -0
  561. package/dist/spawn/worktree-lock-holder.js +41 -0
  562. package/dist/spawn/worktree-lock-holder.js.map +1 -0
  563. package/dist/sticky/convert.d.ts.map +1 -1
  564. package/dist/sticky/convert.js +16 -4
  565. package/dist/sticky/convert.js.map +1 -1
  566. package/dist/store/attachment-store.d.ts +14 -0
  567. package/dist/store/attachment-store.d.ts.map +1 -1
  568. package/dist/store/attachment-store.js +11 -1
  569. package/dist/store/attachment-store.js.map +1 -1
  570. package/dist/store/backup-inspect.d.ts +7 -3
  571. package/dist/store/backup-inspect.d.ts.map +1 -1
  572. package/dist/store/backup-inspect.js +18 -7
  573. package/dist/store/backup-inspect.js.map +1 -1
  574. package/dist/store/backup-sidecar.d.ts +60 -0
  575. package/dist/store/backup-sidecar.d.ts.map +1 -0
  576. package/dist/store/backup-sidecar.js +96 -0
  577. package/dist/store/backup-sidecar.js.map +1 -0
  578. package/dist/store/data-accessor.d.ts +1 -1
  579. package/dist/store/data-accessor.d.ts.map +1 -1
  580. package/dist/store/data-accessor.js +6 -6
  581. package/dist/store/data-accessor.js.map +1 -1
  582. package/dist/store/data-safety-central.d.ts +13 -4
  583. package/dist/store/data-safety-central.d.ts.map +1 -1
  584. package/dist/store/data-safety-central.js +31 -4
  585. package/dist/store/data-safety-central.js.map +1 -1
  586. package/dist/store/dual-scope-db.d.ts.map +1 -1
  587. package/dist/store/dual-scope-db.js +10 -0
  588. package/dist/store/dual-scope-db.js.map +1 -1
  589. package/dist/store/exodus/__fixtures__/representative-fixture.d.ts.map +1 -1
  590. package/dist/store/exodus/__fixtures__/representative-fixture.js +4 -0
  591. package/dist/store/exodus/__fixtures__/representative-fixture.js.map +1 -1
  592. package/dist/store/exodus/migrate.js +1 -1
  593. package/dist/store/exodus/migrate.js.map +1 -1
  594. package/dist/store/exodus/reconcile.js +1 -1
  595. package/dist/store/exodus/reconcile.js.map +1 -1
  596. package/dist/store/exodus/runtime-targets.d.ts +4 -3
  597. package/dist/store/exodus/runtime-targets.d.ts.map +1 -1
  598. package/dist/store/exodus/runtime-targets.js +4 -3
  599. package/dist/store/exodus/runtime-targets.js.map +1 -1
  600. package/dist/store/import-logging.d.ts.map +1 -1
  601. package/dist/store/import-logging.js +5 -4
  602. package/dist/store/import-logging.js.map +1 -1
  603. package/dist/store/legacy-tasks-lineage.d.ts.map +1 -1
  604. package/dist/store/legacy-tasks-lineage.js +2 -7
  605. package/dist/store/legacy-tasks-lineage.js.map +1 -1
  606. package/dist/store/lock.d.ts +1 -0
  607. package/dist/store/lock.d.ts.map +1 -1
  608. package/dist/store/lock.js +1 -0
  609. package/dist/store/lock.js.map +1 -1
  610. package/dist/store/memory-accessor.d.ts +8 -3
  611. package/dist/store/memory-accessor.d.ts.map +1 -1
  612. package/dist/store/memory-accessor.js +29 -13
  613. package/dist/store/memory-accessor.js.map +1 -1
  614. package/dist/store/memory-sqlite.d.ts.map +1 -1
  615. package/dist/store/memory-sqlite.js +5 -0
  616. package/dist/store/memory-sqlite.js.map +1 -1
  617. package/dist/store/open-cleo-db.d.ts.map +1 -1
  618. package/dist/store/open-cleo-db.js +11 -6
  619. package/dist/store/open-cleo-db.js.map +1 -1
  620. package/dist/store/portable-bundle-relocate.d.ts +13 -8
  621. package/dist/store/portable-bundle-relocate.d.ts.map +1 -1
  622. package/dist/store/portable-bundle-relocate.js +75 -31
  623. package/dist/store/portable-bundle-relocate.js.map +1 -1
  624. package/dist/store/portable-bundle-scan.d.ts.map +1 -1
  625. package/dist/store/portable-bundle-scan.js +2 -1
  626. package/dist/store/portable-bundle-scan.js.map +1 -1
  627. package/dist/store/portable-bundle.d.ts.map +1 -1
  628. package/dist/store/portable-bundle.js +7 -3
  629. package/dist/store/portable-bundle.js.map +1 -1
  630. package/dist/store/pre-repair-snapshot.d.ts +77 -0
  631. package/dist/store/pre-repair-snapshot.d.ts.map +1 -0
  632. package/dist/store/pre-repair-snapshot.js +122 -0
  633. package/dist/store/pre-repair-snapshot.js.map +1 -0
  634. package/dist/store/regenerators.d.ts +2 -1
  635. package/dist/store/regenerators.d.ts.map +1 -1
  636. package/dist/store/regenerators.js +17 -3
  637. package/dist/store/regenerators.js.map +1 -1
  638. package/dist/store/relocated-store-guard.d.ts +71 -0
  639. package/dist/store/relocated-store-guard.d.ts.map +1 -0
  640. package/dist/store/relocated-store-guard.js +138 -0
  641. package/dist/store/relocated-store-guard.js.map +1 -0
  642. package/dist/store/safety-data-accessor.d.ts +2 -2
  643. package/dist/store/safety-data-accessor.d.ts.map +1 -1
  644. package/dist/store/safety-data-accessor.js +2 -2
  645. package/dist/store/safety-data-accessor.js.map +1 -1
  646. package/dist/store/schema/attachments.d.ts +2 -2
  647. package/dist/store/schema/audit.d.ts +5 -5
  648. package/dist/store/schema/background-jobs.d.ts +1 -1
  649. package/dist/store/schema/cleo-global/models-catalog.d.ts +1 -1
  650. package/dist/store/schema/cleo-global/nexus.d.ts +686 -0
  651. package/dist/store/schema/cleo-global/nexus.d.ts.map +1 -1
  652. package/dist/store/schema/cleo-global/nexus.js +175 -7
  653. package/dist/store/schema/cleo-global/nexus.js.map +1 -1
  654. package/dist/store/schema/cleo-global/skills.d.ts +2 -2
  655. package/dist/store/schema/cleo-project/audit.d.ts +5 -5
  656. package/dist/store/schema/cleo-project/docs.d.ts +3 -3
  657. package/dist/store/schema/cleo-project/lifecycle.d.ts +3 -3
  658. package/dist/store/schema/cleo-project/provenance-commits.d.ts +2 -2
  659. package/dist/store/schema/cleo-project/provenance-rest.d.ts +3 -3
  660. package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts +1 -1
  661. package/dist/store/schema/cleo-project/tasks-core.d.ts +6 -6
  662. package/dist/store/schema/cleo-shared/brain.d.ts +26 -26
  663. package/dist/store/schema/lifecycle.d.ts +3 -3
  664. package/dist/store/schema/manifest.d.ts +1 -1
  665. package/dist/store/schema/memory-schema.d.ts +26 -26
  666. package/dist/store/schema/nexus-schema.d.ts +696 -2
  667. package/dist/store/schema/nexus-schema.d.ts.map +1 -1
  668. package/dist/store/schema/nexus-schema.js +175 -19
  669. package/dist/store/schema/nexus-schema.js.map +1 -1
  670. package/dist/store/schema/provenance/releases.d.ts +1 -1
  671. package/dist/store/schema/skills-schema.d.ts +2 -2
  672. package/dist/store/schema/tasks.d.ts +5 -5
  673. package/dist/store/session-binding-schema.d.ts +132 -0
  674. package/dist/store/session-binding-schema.d.ts.map +1 -0
  675. package/dist/store/session-binding-schema.js +53 -0
  676. package/dist/store/session-binding-schema.js.map +1 -0
  677. package/dist/store/session-store.d.ts +262 -4
  678. package/dist/store/session-store.d.ts.map +1 -1
  679. package/dist/store/session-store.js +486 -26
  680. package/dist/store/session-store.js.map +1 -1
  681. package/dist/store/snapshot-gate.d.ts +239 -0
  682. package/dist/store/snapshot-gate.d.ts.map +1 -0
  683. package/dist/store/snapshot-gate.js +398 -0
  684. package/dist/store/snapshot-gate.js.map +1 -0
  685. package/dist/store/split-brain-import.js +2 -2
  686. package/dist/store/split-brain-import.js.map +1 -1
  687. package/dist/store/sqlite-backup.d.ts +55 -13
  688. package/dist/store/sqlite-backup.d.ts.map +1 -1
  689. package/dist/store/sqlite-backup.js +414 -106
  690. package/dist/store/sqlite-backup.js.map +1 -1
  691. package/dist/store/sqlite-data-accessor.d.ts +15 -0
  692. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  693. package/dist/store/sqlite-data-accessor.js +63 -4
  694. package/dist/store/sqlite-data-accessor.js.map +1 -1
  695. package/dist/store/sqlite.d.ts +1 -1
  696. package/dist/store/sqlite.d.ts.map +1 -1
  697. package/dist/store/sqlite.js +53 -5
  698. package/dist/store/sqlite.js.map +1 -1
  699. package/dist/store/store-write-guard.d.ts +28 -0
  700. package/dist/store/store-write-guard.d.ts.map +1 -0
  701. package/dist/store/store-write-guard.js +50 -0
  702. package/dist/store/store-write-guard.js.map +1 -0
  703. package/dist/store/table-classification.d.ts +143 -0
  704. package/dist/store/table-classification.d.ts.map +1 -0
  705. package/dist/store/table-classification.js +1866 -0
  706. package/dist/store/table-classification.js.map +1 -0
  707. package/dist/store/task-version.d.ts +72 -0
  708. package/dist/store/task-version.d.ts.map +1 -0
  709. package/dist/store/task-version.js +93 -0
  710. package/dist/store/task-version.js.map +1 -0
  711. package/dist/store/tasks-schema.d.ts +1 -0
  712. package/dist/store/tasks-schema.d.ts.map +1 -1
  713. package/dist/store/tasks-schema.js +13 -0
  714. package/dist/store/tasks-schema.js.map +1 -1
  715. package/dist/store/tasks-sqlite.d.ts +10 -3
  716. package/dist/store/tasks-sqlite.d.ts.map +1 -1
  717. package/dist/store/tasks-sqlite.js +12 -3
  718. package/dist/store/tasks-sqlite.js.map +1 -1
  719. package/dist/store/twin-collapse.d.ts +275 -0
  720. package/dist/store/twin-collapse.d.ts.map +1 -0
  721. package/dist/store/twin-collapse.js +805 -0
  722. package/dist/store/twin-collapse.js.map +1 -0
  723. package/dist/store/umbrella-data-accessor.d.ts +2 -2
  724. package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
  725. package/dist/store/umbrella-data-accessor.js +2 -2
  726. package/dist/store/umbrella-data-accessor.js.map +1 -1
  727. package/dist/store/validation-schemas.d.ts +63 -63
  728. package/dist/store/worktree-isolation-guard.d.ts +46 -24
  729. package/dist/store/worktree-isolation-guard.d.ts.map +1 -1
  730. package/dist/store/worktree-isolation-guard.js +69 -50
  731. package/dist/store/worktree-isolation-guard.js.map +1 -1
  732. package/dist/system/backup.d.ts.map +1 -1
  733. package/dist/system/backup.js +3 -67
  734. package/dist/system/backup.js.map +1 -1
  735. package/dist/system/cleo-link.d.ts +163 -0
  736. package/dist/system/cleo-link.d.ts.map +1 -0
  737. package/dist/system/cleo-link.js +246 -0
  738. package/dist/system/cleo-link.js.map +1 -0
  739. package/dist/system/dependencies.d.ts.map +1 -1
  740. package/dist/system/dependencies.js +3 -6
  741. package/dist/system/dependencies.js.map +1 -1
  742. package/dist/system/global-delivery.d.ts +205 -0
  743. package/dist/system/global-delivery.d.ts.map +1 -0
  744. package/dist/system/global-delivery.js +320 -0
  745. package/dist/system/global-delivery.js.map +1 -0
  746. package/dist/system/health.d.ts.map +1 -1
  747. package/dist/system/health.js +29 -6
  748. package/dist/system/health.js.map +1 -1
  749. package/dist/system/project-health.d.ts.map +1 -1
  750. package/dist/system/project-health.js +1 -20
  751. package/dist/system/project-health.js.map +1 -1
  752. package/dist/system/runtime.d.ts.map +1 -1
  753. package/dist/system/runtime.js +2 -12
  754. package/dist/system/runtime.js.map +1 -1
  755. package/dist/system/safestop.d.ts.map +1 -1
  756. package/dist/system/safestop.js +5 -2
  757. package/dist/system/safestop.js.map +1 -1
  758. package/dist/system/skill-fixtures.d.ts +200 -0
  759. package/dist/system/skill-fixtures.d.ts.map +1 -0
  760. package/dist/system/skill-fixtures.js +331 -0
  761. package/dist/system/skill-fixtures.js.map +1 -0
  762. package/dist/tasks/add.d.ts.map +1 -1
  763. package/dist/tasks/add.js +4 -2
  764. package/dist/tasks/add.js.map +1 -1
  765. package/dist/tasks/affected-packages.d.ts +173 -0
  766. package/dist/tasks/affected-packages.d.ts.map +1 -0
  767. package/dist/tasks/affected-packages.js +389 -0
  768. package/dist/tasks/affected-packages.js.map +1 -0
  769. package/dist/tasks/change-set.d.ts +151 -0
  770. package/dist/tasks/change-set.d.ts.map +1 -0
  771. package/dist/tasks/change-set.js +634 -0
  772. package/dist/tasks/change-set.js.map +1 -0
  773. package/dist/tasks/complete.d.ts.map +1 -1
  774. package/dist/tasks/complete.js +10 -5
  775. package/dist/tasks/complete.js.map +1 -1
  776. package/dist/tasks/done-plan.d.ts +103 -0
  777. package/dist/tasks/done-plan.d.ts.map +1 -0
  778. package/dist/tasks/done-plan.js +541 -0
  779. package/dist/tasks/done-plan.js.map +1 -0
  780. package/dist/tasks/done-record.d.ts +127 -0
  781. package/dist/tasks/done-record.d.ts.map +1 -0
  782. package/dist/tasks/done-record.js +373 -0
  783. package/dist/tasks/done-record.js.map +1 -0
  784. package/dist/tasks/duplicate-detector.d.ts +68 -11
  785. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  786. package/dist/tasks/duplicate-detector.js +314 -58
  787. package/dist/tasks/duplicate-detector.js.map +1 -1
  788. package/dist/tasks/evidence-paths.d.ts +78 -0
  789. package/dist/tasks/evidence-paths.d.ts.map +1 -0
  790. package/dist/tasks/evidence-paths.js +150 -0
  791. package/dist/tasks/evidence-paths.js.map +1 -0
  792. package/dist/tasks/evidence.d.ts +55 -0
  793. package/dist/tasks/evidence.d.ts.map +1 -1
  794. package/dist/tasks/evidence.js +223 -26
  795. package/dist/tasks/evidence.js.map +1 -1
  796. package/dist/tasks/gate-preview.d.ts +5 -0
  797. package/dist/tasks/gate-preview.d.ts.map +1 -1
  798. package/dist/tasks/gate-preview.js +25 -21
  799. package/dist/tasks/gate-preview.js.map +1 -1
  800. package/dist/tasks/gate-result-cache.d.ts +205 -0
  801. package/dist/tasks/gate-result-cache.d.ts.map +1 -0
  802. package/dist/tasks/gate-result-cache.js +285 -0
  803. package/dist/tasks/gate-result-cache.js.map +1 -0
  804. package/dist/tasks/gate-runner.d.ts +126 -3
  805. package/dist/tasks/gate-runner.d.ts.map +1 -1
  806. package/dist/tasks/gate-runner.js +483 -28
  807. package/dist/tasks/gate-runner.js.map +1 -1
  808. package/dist/tasks/session-scope.d.ts +3 -1
  809. package/dist/tasks/session-scope.d.ts.map +1 -1
  810. package/dist/tasks/session-scope.js +18 -3
  811. package/dist/tasks/session-scope.js.map +1 -1
  812. package/dist/tasks/tool-resolver.d.ts +23 -6
  813. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  814. package/dist/tasks/tool-resolver.js +146 -8
  815. package/dist/tasks/tool-resolver.js.map +1 -1
  816. package/dist/tasks/tool-vacuity.d.ts +71 -0
  817. package/dist/tasks/tool-vacuity.d.ts.map +1 -0
  818. package/dist/tasks/tool-vacuity.js +334 -0
  819. package/dist/tasks/tool-vacuity.js.map +1 -0
  820. package/dist/tasks/update.d.ts +8 -0
  821. package/dist/tasks/update.d.ts.map +1 -1
  822. package/dist/tasks/update.js +159 -78
  823. package/dist/tasks/update.js.map +1 -1
  824. package/dist/upgrade.d.ts.map +1 -1
  825. package/dist/upgrade.js +18 -2
  826. package/dist/upgrade.js.map +1 -1
  827. package/dist/validation/doctor/checks.d.ts +20 -2
  828. package/dist/validation/doctor/checks.d.ts.map +1 -1
  829. package/dist/validation/doctor/checks.js +64 -4
  830. package/dist/validation/doctor/checks.js.map +1 -1
  831. package/dist/validation/doctor/index.d.ts +1 -1
  832. package/dist/validation/doctor/index.d.ts.map +1 -1
  833. package/dist/validation/doctor/index.js +1 -1
  834. package/dist/validation/doctor/index.js.map +1 -1
  835. package/dist/validation/doctor/utils.d.ts.map +1 -1
  836. package/dist/validation/doctor/utils.js +7 -2
  837. package/dist/validation/doctor/utils.js.map +1 -1
  838. package/dist/validation/engine-ops.d.ts +15 -0
  839. package/dist/validation/engine-ops.d.ts.map +1 -1
  840. package/dist/validation/engine-ops.js +249 -98
  841. package/dist/validation/engine-ops.js.map +1 -1
  842. package/migrations/drizzle-cleo-global/20260927000000_t12469-project-locations/migration.sql +121 -0
  843. package/migrations/drizzle-cleo-global/20260927010000_t12543-user-profile-project-scope/migration.sql +23 -0
  844. package/migrations/drizzle-cleo-global/20260928010000_t12470-location-candidates/migration.sql +72 -0
  845. package/migrations/drizzle-cleo-global/20260928020000_t12510-nexus-devices/migration.sql +34 -0
  846. package/migrations/drizzle-cleo-global/20260928030000_t12511-project-git-state/migration.sql +62 -0
  847. package/migrations/drizzle-cleo-project/20260927000000_t12499-session-terminal-bindings/migration.sql +34 -0
  848. package/migrations/drizzle-cleo-project/20260928000000_t12500-binding-provider-flag/migration.sql +15 -0
  849. package/package.json +23 -13
  850. package/schemas/config.schema.json +54 -0
  851. package/schemas/project-context.schema.json +51 -3
  852. package/schemas/project-info.schema.json +28 -1
  853. package/templates/CLEO-INJECTION.md +40 -332
  854. package/templates/CLEO-REFERENCE.md +303 -0
  855. package/templates/workflows/README.md +36 -14
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Project lifecycle engine — move, rename, and re-register CLEO projects.
2
+ * Project lifecycle engine — move, reroot, rename, and re-register CLEO projects.
3
3
  *
4
4
  * Provides the core operations for relocating a CLEO project on disk,
5
5
  * renaming it, and reconciling the nexus registry after manual moves.
@@ -7,12 +7,19 @@
7
7
  * All functions accept explicit absolute paths — no CWD-walk-up (AC7).
8
8
  *
9
9
  * @task T11010 — T10298-1
10
+ * @task T12552 — dry runs are pure
11
+ * @task T12556 — relocations RENAME; nothing is copied, so no stale copy exists
12
+ * @task T12558 — `rerootProject`, child/ancestor targets refused, tombstone
10
13
  */
11
- import { existsSync } from 'node:fs';
12
- import { cp, readFile, rename, writeFile } from 'node:fs/promises';
13
- import { basename, dirname, join, resolve as resolvePath } from 'node:path';
14
+ import { existsSync, statSync } from 'node:fs';
15
+ import { copyFile, mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';
16
+ import { basename, dirname, join, relative, resolve as resolvePath, sep } from 'node:path';
17
+ import { ExitCode } from '@cleocode/contracts';
18
+ import { canonicalizePath, computeProjectHash, readPortableProjectId, resolveWorktreeRootForHash, } from '@cleocode/paths';
19
+ import { withStrippedFieldsReceipt } from './doctor/project-identity.js';
14
20
  import { engineError, engineSuccess } from './engine-result.js';
15
21
  import { generateProjectHash, nexusReconcile, nexusRenameProject } from './nexus/index.js';
22
+ import { computeStableProjectHash } from './project-scope.js';
16
23
  // ── Internal helpers ─────────────────────────────────────────────────
17
24
  /**
18
25
  * Read and parse project-info.json from the given project root.
@@ -51,103 +58,650 @@ function validateAbsolutePath(label, p) {
51
58
  }
52
59
  return null; // valid
53
60
  }
54
- // ── Public API ───────────────────────────────────────────────────────
61
+ // ── Relocation helpers (T12552 · T12556 · T12558) ─────────────────────
55
62
  /**
56
- * Move a CLEO project to a new filesystem location.
57
- *
58
- * Copies the entire project directory tree to `newPath`, updates
59
- * `project-info.json` with the new project root and hash, reconciles
60
- * the nexus registry, and returns the result.
61
- *
62
- * The original directory is NOT removed — callers should verify the
63
- * move succeeded before cleaning up the old location.
64
- *
65
- * @param newPath - Absolute path to the new project root location.
66
- * @param projectRoot - Absolute path to the current project root.
67
- * @returns EngineResult with {@link MoveProjectResult} on success.
68
- *
69
- * @remarks AC3: Uses fs.cp for the filesystem move. The projectId is
70
- * preserved across moves; projectHash is recomputed from the new path.
63
+ * Top-level entries `reroot` renames into the child, in order. `.github` is
64
+ * included only when it holds nothing but CLEO's own init templates (see
65
+ * {@link isCleoOwnedGithubDir}); a parent repository's real `.github` stays.
66
+ */
67
+ const REROOT_ENTRIES = ['.cleo', '.worktreeinclude', '.github'];
68
+ /** Nearest existing ancestor of `p` (itself when it exists). */
69
+ function nearestExisting(p) {
70
+ let head = resolvePath(p);
71
+ while (!existsSync(head)) {
72
+ const parent = dirname(head);
73
+ if (parent === head)
74
+ break;
75
+ head = parent;
76
+ }
77
+ return head;
78
+ }
79
+ /**
80
+ * Canonical form of a path whose tail may not exist yet: the nearest existing
81
+ * ancestor is resolved through symlinks (macOS `/tmp` → `/private/tmp`) and
82
+ * the missing tail is appended, so containment compares like with like.
83
+ */
84
+ function canonicalTarget(p) {
85
+ const resolved = resolvePath(p);
86
+ const head = nearestExisting(resolved);
87
+ return join(canonicalizePath(head), relative(head, resolved));
88
+ }
89
+ /** `true` when `inner` is strictly inside `outer` (both canonical). */
90
+ function isStrictlyInside(outer, inner) {
91
+ const rel = relative(outer, inner);
92
+ return rel.length > 0 && !rel.startsWith(`..${sep}`) && rel !== '..' && !rel.startsWith(sep);
93
+ }
94
+ /** `true` when `target` (or its nearest existing ancestor) is on `source`'s device. */
95
+ function sameDevice(source, target) {
96
+ return statSync(source).dev === statSync(nearestExisting(target)).dev;
97
+ }
98
+ /**
99
+ * `E_CROSS_DEVICE`: a relocation only renames within one device. The fix says
100
+ * to quiesce the project first — a plain `mv` across devices is a copy, so a
101
+ * live writer during it tears the database exactly as the old copy did.
102
+ */
103
+ function crossDeviceRefusal(source, target, command) {
104
+ return engineError('E_CROSS_DEVICE', `"${target}" is on another device than "${source}"; cleo only relocates by rename within one device`, {
105
+ exitCode: ExitCode.INVALID_INPUT,
106
+ fix: `First end every session (\`cleo session end\`), stop every process writing to the project, and run \`cleo backup add\`. Then: ${command}`,
107
+ });
108
+ }
109
+ /** Read `projectId` from project-info.json, or the failure to return. */
110
+ async function readRelocatableIdentity(projectRoot) {
111
+ const info = await readProjectInfo(projectRoot);
112
+ if (!info) {
113
+ return engineError('E_PROJECT_INFO_MISSING', `Failed to read project-info.json at "${projectRoot}"`, { exitCode: ExitCode.CONFIG_ERROR });
114
+ }
115
+ const projectId = typeof info.projectId === 'string' ? info.projectId : '';
116
+ if (!projectId) {
117
+ return engineError('E_NO_PROJECT_ID', `project-info.json at "${projectRoot}" is missing projectId`, { fix: 'Run `cleo init` to generate a projectId', exitCode: ExitCode.CONFIG_ERROR });
118
+ }
119
+ return { projectId };
120
+ }
121
+ /**
122
+ * CLEO worktrees provisioned for the project at `projectRoot`, plus git
123
+ * worktrees registered in its `.git/`. Both are keyed by absolute path, so a
124
+ * relocation would strand them.
125
+ */
126
+ async function listBoundWorktrees(projectRoot, includeGit) {
127
+ const found = new Set();
128
+ const dir = resolveWorktreeRootForHash(computeProjectHash(projectRoot));
129
+ if (existsSync(dir)) {
130
+ for (const entry of await readdir(dir))
131
+ found.add(`CLEO worktree ${join(dir, entry)}`);
132
+ }
133
+ const { readSentinelIndex } = await import('./worktree/sentinel-index.js');
134
+ for (const entry of readSentinelIndex(projectRoot)) {
135
+ if (existsSync(entry.path))
136
+ found.add(`CLEO worktree ${entry.path}`);
137
+ }
138
+ const gitWorktrees = join(projectRoot, '.git', 'worktrees');
139
+ if (includeGit && existsSync(gitWorktrees)) {
140
+ for (const entry of await readdir(gitWorktrees)) {
141
+ found.add(`git worktree ${join(gitWorktrees, entry)}`);
142
+ }
143
+ }
144
+ return [...found].sort();
145
+ }
146
+ /**
147
+ * The refusal for a relocation while something is bound to the project. The
148
+ * fix names the exact command for each session, bound by `CLEO_SESSION_ID` so
149
+ * it ends THAT session rather than the caller's (T12500).
150
+ */
151
+ function blockedError(code, worktrees, activeSessions) {
152
+ const steps = [
153
+ ...activeSessions.map((id) => `CLEO_SESSION_ID=${id} cleo session end`),
154
+ ...(worktrees.length > 0 ? ['remove each worktree listed in details.worktrees'] : []),
155
+ ...(worktrees.some((w) => w.startsWith('git worktree '))
156
+ ? ['for a git worktree whose directory is already gone, run `git worktree prune`']
157
+ : []),
158
+ ];
159
+ return engineError(code, `Cannot relocate while bound: ${[...worktrees, ...activeSessions.map((s) => `active session ${s}`)].join('; ')}`, {
160
+ exitCode: ExitCode.CONCURRENT_MODIFICATION,
161
+ details: { worktrees, activeSessions },
162
+ fix: `${steps.join(' && ')}, then retry`,
163
+ });
164
+ }
165
+ /** Ids of active sessions in the project store at `projectRoot`. */
166
+ async function activeSessionIds(projectRoot) {
167
+ const { listSessions } = await import('./store/session-store.js');
168
+ return (await listSessions({ active: true }, projectRoot)).map((s) => s.id);
169
+ }
170
+ /**
171
+ * Required checkpoint before a relocation: the `cleo backup add` snapshot,
172
+ * then COPIED to `<cleoHome>/backups/<projectId>/<backupId>/` so it does not
173
+ * share fate with the tree it protects.
174
+ */
175
+ async function takeCheckpoint(projectRoot, projectId, kind, target) {
176
+ try {
177
+ const { createBackup } = await import('./system/backup.js');
178
+ const backup = await createBackup(projectRoot, {
179
+ type: kind,
180
+ note: `before cleo project ${kind} ${target}`,
181
+ });
182
+ if (!backup.files.includes('tasks.db')) {
183
+ throw new Error('the project database was not captured');
184
+ }
185
+ const { getCleoHome } = await import('./paths.js');
186
+ const outside = join(getCleoHome(), 'backups', projectId, backup.backupId);
187
+ await mkdir(outside, { recursive: true });
188
+ const names = [
189
+ ...backup.files.map((f) => `${f}.${backup.backupId}`),
190
+ `${backup.backupId}.meta.json`,
191
+ ];
192
+ for (const name of names) {
193
+ const src = join(backup.path, name);
194
+ if (existsSync(src))
195
+ await copyFile(src, join(outside, name));
196
+ }
197
+ return engineSuccess({ id: backup.backupId, path: outside });
198
+ }
199
+ catch (err) {
200
+ return engineError('E_CHECKPOINT_FAILED', `Checkpoint before ${kind} failed: ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Run `cleo backup add` to diagnose, then retry' });
201
+ }
202
+ }
203
+ /** Where the checkpoint will be written, for a plan (nothing is created). */
204
+ async function checkpointLocation(projectId) {
205
+ const { getCleoHome } = await import('./paths.js');
206
+ return join(getCleoHome(), 'backups', projectId, '<backupId>');
207
+ }
208
+ /** Open the global registry (dynamic: keeps the store graph off import). */
209
+ async function openRegistry() {
210
+ const { getNexusRegistryDb } = await import('./store/nexus-sqlite.js');
211
+ const { getCleoHome } = await import('./paths.js');
212
+ return getNexusRegistryDb(getCleoHome());
213
+ }
214
+ /**
215
+ * Rebind the registry to `livePath` explicitly, then demote `demotedPath` to
216
+ * `missing` — exactly one live location remains.
71
217
  *
72
- * @example
73
- * ```typescript
74
- * const result = await moveProject('/new/location/project', '/old/project');
75
- * if (result.success) {
76
- * console.log(`Moved to ${result.data.newPath}, hash=${result.data.newProjectHash}`);
77
- * }
78
- * ```
218
+ * Runs with the project scope pinned to `livePath`: the nexus handle is the
219
+ * AMBIENT project's `cleo.db`, and the ambient root is still the caller's cwd
220
+ * (the old root). Opening it there would create an empty store beside the
221
+ * moved one.
222
+ */
223
+ async function rebindRegistry(projectId, livePath, demotedPath) {
224
+ const { captureProjectScope, worktreeScope } = await import('./project-scope.js');
225
+ const scope = captureProjectScope(livePath, worktreeScope.getStore());
226
+ try {
227
+ const reconcile = await worktreeScope.run(scope, () => nexusReconcile(livePath, { forceRebind: true }));
228
+ const { demoteProjectLocation } = await import('./nexus/path-map.js');
229
+ demoteProjectLocation(await openRegistry(), { projectId, projectPath: demotedPath, now: new Date().toISOString() }, 'missing');
230
+ return engineSuccess(reconcile.status);
231
+ }
232
+ catch (err) {
233
+ return engineError('E_NEXUS_RECONCILE_FAILED', `Files were relocated to "${livePath}" but the registry rebind failed: ${err.message}`, {
234
+ exitCode: ExitCode.GENERAL_ERROR,
235
+ details: { originalError: err.message },
236
+ fix: `Run \`cleo nexus reconcile --force-rebind\` in ${livePath}`,
237
+ });
238
+ }
239
+ }
240
+ /** Every file under `dir`, relative to it. */
241
+ async function listFiles(dir, prefix = '') {
242
+ const out = [];
243
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
244
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
245
+ if (entry.isDirectory())
246
+ out.push(...(await listFiles(join(dir, entry.name), rel)));
247
+ else
248
+ out.push(rel);
249
+ }
250
+ return out;
251
+ }
252
+ /**
253
+ * `true` when `<root>/.github` holds only files byte-identical to the GitHub
254
+ * templates `cleo init` installs — i.e. CLEO created it, not the repository.
255
+ */
256
+ async function isCleoOwnedGithubDir(root) {
257
+ const { getPackageRoot } = await import('./scaffold/ensure-config.js');
258
+ const templates = join(getPackageRoot(), 'templates', 'github');
259
+ const githubDir = join(root, '.github');
260
+ if (!existsSync(templates))
261
+ return false;
262
+ const files = await listFiles(githubDir);
263
+ if (files.length === 0)
264
+ return false;
265
+ for (const file of files) {
266
+ const template = join(templates, file);
267
+ if (!existsSync(template))
268
+ return false;
269
+ const [a, b] = await Promise.all([readFile(join(githubDir, file)), readFile(template)]);
270
+ if (!a.equals(b))
271
+ return false;
272
+ }
273
+ return true;
274
+ }
275
+ /**
276
+ * Split CLEO's top-level entries at `root` into those reroot moves and those
277
+ * it must leave, given what `childDir` already holds.
79
278
  */
80
- export async function moveProject(newPath, projectRoot) {
81
- // AC7: Validate absolute paths
279
+ async function rerootEntries(root, childDir) {
280
+ const entries = [];
281
+ const excluded = [];
282
+ const clashes = [];
283
+ for (const entry of REROOT_ENTRIES) {
284
+ if (!existsSync(join(root, entry)))
285
+ continue;
286
+ if (entry === '.github') {
287
+ if (!(await isCleoOwnedGithubDir(root))) {
288
+ excluded.push({ entry, reason: 'holds files that are not CLEO init templates' });
289
+ }
290
+ else if (existsSync(join(childDir, entry))) {
291
+ excluded.push({ entry, reason: 'the child already has its own .github' });
292
+ }
293
+ else {
294
+ entries.push(entry);
295
+ }
296
+ continue;
297
+ }
298
+ if (existsSync(join(childDir, entry)))
299
+ clashes.push(entry);
300
+ else
301
+ entries.push(entry);
302
+ }
303
+ return { entries, excluded, clashes };
304
+ }
305
+ /** Rename `entries` from `from` to `to`; on any failure put back what moved. */
306
+ async function renameEntries(from, to, entries) {
307
+ const done = [];
308
+ try {
309
+ for (const entry of entries) {
310
+ await rename(join(from, entry), join(to, entry));
311
+ done.push(entry);
312
+ }
313
+ }
314
+ catch (err) {
315
+ await renameBack(from, to, done);
316
+ throw err;
317
+ }
318
+ }
319
+ /** Undo {@link renameEntries} for `entries` (best effort, reverse order). */
320
+ async function renameBack(from, to, entries) {
321
+ for (const entry of [...entries].reverse()) {
322
+ await rename(join(to, entry), join(from, entry)).catch(() => undefined);
323
+ }
324
+ }
325
+ export async function moveProject(newPath, projectRoot, opts = {}) {
82
326
  const pathErr = validateAbsolutePath('newPath', newPath);
83
327
  if (pathErr)
84
328
  return pathErr;
85
329
  const rootErr = validateAbsolutePath('projectRoot', projectRoot);
86
330
  if (rootErr)
87
331
  return rootErr;
88
- // Validate source exists and has project-info.json
332
+ newPath = resolvePath(newPath);
89
333
  if (!existsSync(join(projectRoot, '.cleo', 'project-info.json'))) {
90
334
  return engineError('E_NOT_CLEO_PROJECT', `No CLEO project found at "${projectRoot}"`, {
91
335
  fix: 'Ensure the project was initialized with `cleo init`',
336
+ exitCode: ExitCode.CONFIG_ERROR,
92
337
  });
93
338
  }
94
- if (resolvePath(newPath) === resolvePath(projectRoot)) {
95
- return engineError('E_SAME_PATH', `newPath and projectRoot resolve to the same location: "${projectRoot}"`);
339
+ const source = canonicalizePath(projectRoot);
340
+ const target = canonicalTarget(newPath);
341
+ if (newPath === resolvePath(projectRoot) || source === target) {
342
+ return engineError('E_SAME_PATH', `newPath and projectRoot resolve to the same location: "${projectRoot}"`, { exitCode: ExitCode.INVALID_INPUT });
96
343
  }
97
- // Read current project info
98
- const info = await readProjectInfo(projectRoot);
99
- if (!info) {
100
- return engineError('E_PROJECT_INFO_MISSING', `Failed to read project-info.json at "${projectRoot}"`);
344
+ // Refused before any IO: a directory cannot be renamed into its own subtree
345
+ // or onto an ancestor.
346
+ const targetIsFile = existsSync(newPath) && !statSync(newPath).isDirectory();
347
+ if (isStrictlyInside(source, target)) {
348
+ return engineError('E_INVALID_TARGET', `newPath "${newPath}" is inside the project at "${projectRoot}"; a project cannot move into itself`, {
349
+ exitCode: ExitCode.INVALID_INPUT,
350
+ fix: targetIsFile
351
+ ? 'Choose a directory outside the project tree'
352
+ : `To make that directory the project root, run \`cleo project reroot ${relative(source, target)}\` from ${projectRoot}`,
353
+ });
101
354
  }
102
- const projectId = typeof info.projectId === 'string' ? info.projectId : '';
103
- if (!projectId) {
104
- return engineError('E_NO_PROJECT_ID', `project-info.json at "${projectRoot}" is missing projectId`, { fix: 'Run `cleo init` to generate a projectId' });
355
+ if (isStrictlyInside(target, source)) {
356
+ return engineError('E_INVALID_TARGET', `newPath "${newPath}" contains the project at "${projectRoot}"; a project cannot move onto its own ancestor`, { exitCode: ExitCode.INVALID_INPUT, fix: 'Choose a path outside the project tree' });
105
357
  }
106
- // AC3: Filesystem move via copy
107
- // We copy rather than rename so the caller can verify before cleanup.
108
- try {
109
- // Create parent dirs if needed
110
- const newParent = dirname(newPath);
111
- const { mkdir } = await import('node:fs/promises');
112
- await mkdir(newParent, { recursive: true });
113
- // Copy the project tree (exclude node_modules for performance)
114
- await cp(projectRoot, newPath, {
115
- recursive: true,
116
- filter: (src) => {
117
- // Skip node_modules and .git directories during copy (they'll be
118
- // reconstructed or linked by the caller after the move).
119
- const base = basename(src);
120
- return base !== 'node_modules' && base !== '.git';
358
+ if (targetIsFile) {
359
+ return engineError('E_INVALID_TARGET', `newPath is an existing file: "${newPath}"`, {
360
+ exitCode: ExitCode.INVALID_INPUT,
361
+ fix: 'Choose a path that does not exist yet, or an empty directory',
362
+ });
363
+ }
364
+ if (existsSync(newPath) && (await readdir(newPath)).length > 0) {
365
+ return engineError('E_INVALID_TARGET', `newPath is not empty: "${newPath}"`, {
366
+ exitCode: ExitCode.INVALID_INPUT,
367
+ fix: 'Choose a path that does not exist yet, or an empty directory',
368
+ });
369
+ }
370
+ const identity = await readRelocatableIdentity(projectRoot);
371
+ if ('success' in identity)
372
+ return identity;
373
+ const { projectId } = identity;
374
+ const crossDevice = !sameDevice(projectRoot, newPath);
375
+ const crossDeviceError = crossDeviceRefusal(projectRoot, newPath, `mv "${projectRoot}" "${newPath}" && cd "${newPath}" && cleo nexus reconcile — the carried nonce proves the move and git stays intact`);
376
+ const worktrees = await listBoundWorktrees(projectRoot, true);
377
+ if (opts.dryRun) {
378
+ return engineSuccess({
379
+ dryRun: true,
380
+ kind: 'move',
381
+ projectId,
382
+ source: projectRoot,
383
+ target: newPath,
384
+ transfer: 'rename',
385
+ entries: ['.'],
386
+ excluded: [],
387
+ writes: [],
388
+ registry: {
389
+ action: 'rebind',
390
+ livePath: newPath,
391
+ demotedPath: projectRoot,
392
+ demotedState: 'missing',
393
+ nonce: 'carried',
121
394
  },
395
+ checkpoint: await checkpointLocation(projectId),
396
+ blockers: [
397
+ ...(crossDevice ? ['E_CROSS_DEVICE: the target is on another device'] : []),
398
+ ...worktrees,
399
+ ],
400
+ deferredChecks: ['no active session (reads the project database)'],
122
401
  });
123
402
  }
124
- catch (err) {
125
- return engineError('E_MOVE_FAILED', `Failed to copy project from "${projectRoot}" to "${newPath}": ${err.message}`);
403
+ if (crossDevice)
404
+ return crossDeviceError;
405
+ const sessions = await activeSessionIds(projectRoot);
406
+ if (worktrees.length > 0 || sessions.length > 0) {
407
+ return blockedError('E_MOVE_BLOCKED', worktrees, sessions);
126
408
  }
127
- // AC3: Update project-info.json with new path and hash
128
- const newProjectHash = generateProjectHash(newPath);
129
- const newInfo = {
130
- ...info,
131
- projectRoot: newPath,
132
- projectHash: newProjectHash,
133
- lastUpdated: new Date().toISOString(),
134
- };
135
- await writeProjectInfo(newPath, newInfo);
136
- // Reconcile nexus registry with the new path
137
- let reconcile;
409
+ const checkpoint = await takeCheckpoint(projectRoot, projectId, 'move', newPath);
410
+ if (!checkpoint.success)
411
+ return checkpoint;
412
+ const { closeAllDatabases } = await import('./store/sqlite.js');
413
+ await closeAllDatabases();
138
414
  try {
139
- reconcile = await nexusReconcile(newPath);
415
+ await mkdir(dirname(newPath), { recursive: true });
416
+ await rename(projectRoot, newPath);
140
417
  }
141
418
  catch (err) {
142
- return engineError('E_NEXUS_RECONCILE_FAILED', `Nexus reconcile failed for "${newPath}": ${err.message}`, { details: { originalError: err.message } });
419
+ if (err.code === 'EXDEV')
420
+ return crossDeviceError;
421
+ return engineError('E_MOVE_FAILED', `Failed to rename "${projectRoot}" to "${newPath}": ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Nothing was moved; check permissions and retry' });
143
422
  }
423
+ const rebound = await rebindRegistry(projectId, newPath, projectRoot);
424
+ if (!rebound.success)
425
+ return rebound;
144
426
  return engineSuccess({
427
+ dryRun: false,
145
428
  projectId,
146
429
  oldPath: projectRoot,
147
430
  newPath,
148
- newProjectHash,
149
- reconcileStatus: reconcile.status,
431
+ checkpointId: checkpoint.data.id,
432
+ checkpointPath: checkpoint.data.path,
433
+ reconcileStatus: rebound.data,
434
+ });
435
+ }
436
+ /**
437
+ * The registry path of `projectId` when it is a strict ancestor of `childDir`
438
+ * that no longer holds the project — i.e. an earlier reroot renamed `.cleo/`
439
+ * into `childDir` and stopped before rebinding.
440
+ */
441
+ async function interruptedRerootSource(projectId, childDir) {
442
+ const { projectRegistry } = await import('./store/schema/nexus-schema.js');
443
+ const { eq } = await import('drizzle-orm');
444
+ const row = (await openRegistry())
445
+ .select({ projectPath: projectRegistry.projectPath })
446
+ .from(projectRegistry)
447
+ .where(eq(projectRegistry.projectId, projectId))
448
+ .get();
449
+ const oldRoot = row?.projectPath;
450
+ if (!oldRoot || !existsSync(oldRoot))
451
+ return null;
452
+ if (!isStrictlyInside(canonicalizePath(oldRoot), canonicalizePath(childDir)))
453
+ return null;
454
+ return existsSync(join(oldRoot, '.cleo', 'project-info.json')) ? null : oldRoot;
455
+ }
456
+ /**
457
+ * Keep `entry` out of commits in the repository containing `root` (T12558).
458
+ *
459
+ * Asks git for the exclude file (`rev-parse --git-path info/exclude`) and for
460
+ * `root`'s path inside the work tree (`--show-prefix`), so it works when
461
+ * `root` is a subdirectory of a repository and when `.git` is a FILE (a
462
+ * linked worktree or a submodule). The line is anchored to that repo-relative
463
+ * path. Local to this checkout — nothing tracked changes. Best effort: `root`
464
+ * may not be in a repository, and a tombstone is validated on read anyway.
465
+ */
466
+ async function excludeFromGit(root, entry) {
467
+ const { execFile } = await import('node:child_process');
468
+ const { promisify } = await import('node:util');
469
+ const git = async (...args) => (await promisify(execFile)('git', ['-C', root, ...args], { encoding: 'utf-8' })).stdout.trim();
470
+ try {
471
+ const exclude = resolvePath(root, await git('rev-parse', '--git-path', 'info/exclude'));
472
+ const line = `/${await git('rev-parse', '--show-prefix')}${entry}`;
473
+ await mkdir(dirname(exclude), { recursive: true });
474
+ const current = existsSync(exclude) ? await readFile(exclude, 'utf-8') : '';
475
+ if (current.split(/\r?\n/).includes(line))
476
+ return;
477
+ const joiner = current.length === 0 || current.endsWith('\n') ? '' : '\n';
478
+ await writeFile(exclude, `${current}${joiner}${line}\n`);
479
+ }
480
+ catch {
481
+ // Not in a repository, or git unavailable: the tombstone is still validated on read.
482
+ }
483
+ }
484
+ /**
485
+ * Finish a reroot from the child: identity, tombstone, rebind. Shared by the
486
+ * normal path (after the rename) and a resume.
487
+ */
488
+ async function completeReroot(projectId, childDir, oldRoot) {
489
+ const { ensurePortableProjectId } = await import('./scaffold/project-identity.js');
490
+ const idOutcome = await ensurePortableProjectId(childDir, projectId);
491
+ if (idOutcome !== 'present' && idOutcome !== 'written') {
492
+ throw new Error(`.cleo/project-id could not record ${projectId} (${idOutcome})`);
493
+ }
494
+ const { PROJECT_TOMBSTONE_FILE, writeProjectTombstone } = await import('./project-tombstone.js');
495
+ const tombstone = writeProjectTombstone(oldRoot, {
496
+ projectId,
497
+ movedTo: childDir,
498
+ at: new Date().toISOString(),
150
499
  });
500
+ await excludeFromGit(oldRoot, PROJECT_TOMBSTONE_FILE);
501
+ const rebound = await rebindRegistry(projectId, childDir, oldRoot);
502
+ if (!rebound.success)
503
+ return rebound;
504
+ return engineSuccess({ projectIdFile: idOutcome, tombstone, status: rebound.data });
505
+ }
506
+ export async function rerootProject(childDir, projectRoot, opts = {}) {
507
+ const pathErr = validateAbsolutePath('childDir', childDir);
508
+ if (pathErr)
509
+ return pathErr;
510
+ const rootErr = validateAbsolutePath('projectRoot', projectRoot);
511
+ if (rootErr)
512
+ return rootErr;
513
+ if (!existsSync(join(projectRoot, '.cleo', 'project-info.json'))) {
514
+ return engineError('E_NOT_CLEO_PROJECT', `No CLEO project found at "${projectRoot}"`, {
515
+ fix: 'Run `cleo project reroot` from inside the project',
516
+ exitCode: ExitCode.CONFIG_ERROR,
517
+ });
518
+ }
519
+ if (!existsSync(childDir) || !statSync(childDir).isDirectory()) {
520
+ return engineError('E_INVALID_TARGET', `childDir is not an existing directory: "${childDir}"`, {
521
+ exitCode: ExitCode.INVALID_INPUT,
522
+ fix: 'Pass an existing subdirectory of the project',
523
+ });
524
+ }
525
+ const identity = await readRelocatableIdentity(projectRoot);
526
+ if ('success' in identity)
527
+ return identity;
528
+ const { projectId } = identity;
529
+ const source = canonicalizePath(projectRoot);
530
+ const target = canonicalizePath(childDir);
531
+ // Resume: `.cleo/` is already in this directory and the registry still names
532
+ // an ancestor that no longer holds the project.
533
+ if (source === target) {
534
+ const oldRoot = await interruptedRerootSource(projectId, childDir);
535
+ if (!oldRoot) {
536
+ return engineError('E_SAME_PATH', `"${childDir}" is already the project root and no interrupted reroot was found`, {
537
+ exitCode: ExitCode.INVALID_INPUT,
538
+ fix: 'Pass a subdirectory: `cleo project reroot <childDir>`',
539
+ });
540
+ }
541
+ if (opts.dryRun) {
542
+ return engineSuccess({
543
+ dryRun: true,
544
+ kind: 'reroot',
545
+ projectId,
546
+ source: oldRoot,
547
+ target: childDir,
548
+ transfer: 'rename',
549
+ entries: [],
550
+ excluded: [],
551
+ writes: [join(oldRoot, '.cleo-moved.json')],
552
+ registry: {
553
+ action: 'rebind',
554
+ livePath: childDir,
555
+ demotedPath: oldRoot,
556
+ demotedState: 'missing',
557
+ nonce: 'carried',
558
+ },
559
+ checkpoint: 'none: resuming an interrupted reroot',
560
+ blockers: [],
561
+ deferredChecks: [],
562
+ });
563
+ }
564
+ try {
565
+ const done = await completeReroot(projectId, childDir, oldRoot);
566
+ if (!done.success)
567
+ return done;
568
+ return engineSuccess({
569
+ dryRun: false,
570
+ projectId,
571
+ oldRoot,
572
+ newRoot: childDir,
573
+ resumed: true,
574
+ checkpointId: '',
575
+ checkpointPath: '',
576
+ renamed: [],
577
+ projectIdFile: done.data.projectIdFile,
578
+ tombstone: done.data.tombstone,
579
+ reconcileStatus: done.data.status,
580
+ notes: rerootNotes(oldRoot, childDir),
581
+ });
582
+ }
583
+ catch (err) {
584
+ return engineError('E_IDENTITY_CONFLICT', err.message, {
585
+ exitCode: ExitCode.CONFIG_ERROR,
586
+ fix: 'Run `cleo doctor project-identity --resolve`, then `cleo project reroot .` again',
587
+ });
588
+ }
589
+ }
590
+ if (!isStrictlyInside(source, target)) {
591
+ return engineError('E_INVALID_TARGET', `childDir "${childDir}" is not inside the project at "${projectRoot}"`, {
592
+ exitCode: ExitCode.INVALID_INPUT,
593
+ fix: `To relocate the whole project, run \`cleo project move ${childDir}\``,
594
+ });
595
+ }
596
+ const { entries, excluded, clashes } = await rerootEntries(projectRoot, childDir);
597
+ if (clashes.length > 0) {
598
+ return engineError('E_INVALID_TARGET', `childDir already holds ${clashes.join(', ')}: "${childDir}"`, {
599
+ exitCode: ExitCode.INVALID_INPUT,
600
+ fix: `Move ${clashes.map((c) => join(childDir, c)).join(', ')} aside first; reroot never merges or overwrites`,
601
+ });
602
+ }
603
+ const tracked = readPortableProjectId(projectRoot);
604
+ if (tracked.status === 'invalid' ||
605
+ (tracked.status === 'valid' && tracked.projectId !== projectId)) {
606
+ return engineError('E_IDENTITY_CONFLICT', `.cleo/project-id does not agree with project-info.json at "${projectRoot}"`, {
607
+ exitCode: ExitCode.CONFIG_ERROR,
608
+ fix: 'Run `cleo doctor project-identity` and resolve it first',
609
+ });
610
+ }
611
+ const worktrees = await listBoundWorktrees(projectRoot, false);
612
+ // A child can be a mount point: then `.cleo/` cannot be renamed into it.
613
+ const crossDevice = !sameDevice(projectRoot, childDir);
614
+ const crossDeviceError = crossDeviceRefusal(projectRoot, childDir, `mv "${join(projectRoot, '.cleo')}" "${join(childDir, '.cleo')}" && cd "${childDir}" && cleo project reroot .`);
615
+ if (opts.dryRun) {
616
+ return engineSuccess({
617
+ dryRun: true,
618
+ kind: 'reroot',
619
+ projectId,
620
+ source: projectRoot,
621
+ target: childDir,
622
+ transfer: 'rename',
623
+ entries,
624
+ excluded,
625
+ writes: [
626
+ ...(tracked.status === 'absent' ? [join(childDir, '.cleo', 'project-id')] : []),
627
+ join(projectRoot, '.cleo-moved.json'),
628
+ ],
629
+ registry: {
630
+ action: 'rebind',
631
+ livePath: childDir,
632
+ demotedPath: projectRoot,
633
+ demotedState: 'missing',
634
+ nonce: 'carried',
635
+ },
636
+ checkpoint: await checkpointLocation(projectId),
637
+ blockers: [
638
+ ...(crossDevice ? ['E_CROSS_DEVICE: the child is on another device'] : []),
639
+ ...worktrees,
640
+ ],
641
+ deferredChecks: ['no active session (reads the project database)'],
642
+ });
643
+ }
644
+ if (crossDevice)
645
+ return crossDeviceError;
646
+ const sessions = await activeSessionIds(projectRoot);
647
+ if (worktrees.length > 0 || sessions.length > 0) {
648
+ return blockedError('E_REROOT_BLOCKED', worktrees, sessions);
649
+ }
650
+ const checkpoint = await takeCheckpoint(projectRoot, projectId, 'reroot', childDir);
651
+ if (!checkpoint.success)
652
+ return checkpoint;
653
+ const { closeAllDatabases } = await import('./store/sqlite.js');
654
+ await closeAllDatabases();
655
+ try {
656
+ await renameEntries(projectRoot, childDir, entries);
657
+ }
658
+ catch (err) {
659
+ if (err.code === 'EXDEV')
660
+ return crossDeviceError;
661
+ return engineError('E_MOVE_FAILED', `Failed to rename ${entries.join(', ')} into "${childDir}": ${err.message}`, { exitCode: ExitCode.FILE_ERROR, fix: 'Nothing was moved; check permissions and retry' });
662
+ }
663
+ let done;
664
+ try {
665
+ done = await completeReroot(projectId, childDir, projectRoot);
666
+ }
667
+ catch (err) {
668
+ // Identity or tombstone failed before the registry changed: undo the renames.
669
+ await renameBack(projectRoot, childDir, entries);
670
+ const { rm } = await import('node:fs/promises');
671
+ await rm(join(projectRoot, '.cleo-moved.json'), { force: true });
672
+ return engineError('E_REROOT_FAILED', `Reroot rolled back: ${err.message}`, {
673
+ exitCode: ExitCode.FILE_ERROR,
674
+ fix: 'Nothing changed. Run `cleo doctor project-identity`, then retry',
675
+ });
676
+ }
677
+ if (!done.success) {
678
+ return engineError(done.error.code, done.error.message, {
679
+ exitCode: done.error.exitCode,
680
+ details: done.error.details,
681
+ fix: `The files are already in ${childDir}; run \`cleo project reroot .\` there to finish`,
682
+ });
683
+ }
684
+ return engineSuccess({
685
+ dryRun: false,
686
+ projectId,
687
+ oldRoot: projectRoot,
688
+ newRoot: childDir,
689
+ resumed: false,
690
+ checkpointId: checkpoint.data.id,
691
+ checkpointPath: checkpoint.data.path,
692
+ renamed: entries,
693
+ projectIdFile: done.data.projectIdFile,
694
+ tombstone: done.data.tombstone,
695
+ reconcileStatus: done.data.status,
696
+ notes: rerootNotes(projectRoot, childDir),
697
+ });
698
+ }
699
+ /** Git bookkeeping a reroot leaves to the operator. */
700
+ function rerootNotes(oldRoot, newRoot) {
701
+ return [
702
+ `Commit .cleo/project-id in the repository at ${newRoot}`,
703
+ `The repository at ${oldRoot} now shows .cleo/ as deleted; do not restore it (commands there refuse with E_PROJECT_MOVED)`,
704
+ ];
151
705
  }
152
706
  /**
153
707
  * Rename a CLEO project (updates project-info.json name and hash).
@@ -191,13 +745,23 @@ export async function renameProject(newName, projectRoot) {
191
745
  const oldName = (typeof info.name === 'string' ? info.name : '') ||
192
746
  (typeof info.projectName === 'string' ? info.projectName : '') ||
193
747
  basename(projectRoot);
194
- // AC4: Update project-info.json — only name changes, path stays same
195
- const newProjectHash = generateProjectHash(projectRoot);
748
+ // AC4: Update project-info.json — only name changes. T12557: projectHash is
749
+ // a write-once identity key (release ids, audit rows), so the stored value is
750
+ // kept byte-identical. projectRoot is a path fact and is never written back:
751
+ // a legacy value is dropped into the same `strippedFields` receipt that
752
+ // `cleo doctor project-identity --resolve` keeps.
753
+ const newProjectHash = typeof info.projectHash === 'string' && info.projectHash.length > 0
754
+ ? info.projectHash
755
+ : computeStableProjectHash(projectRoot);
756
+ const now = new Date().toISOString();
757
+ const kept = info.projectRoot === undefined
758
+ ? info
759
+ : withStrippedFieldsReceipt(info, [{ file: 'project-info.json', field: 'projectRoot', value: info.projectRoot }], now, true);
196
760
  const newInfo = {
197
- ...info,
761
+ ...kept,
198
762
  name: newName.trim(),
199
763
  projectHash: newProjectHash,
200
- lastUpdated: new Date().toISOString(),
764
+ lastUpdated: now,
201
765
  };
202
766
  await writeProjectInfo(projectRoot, newInfo);
203
767
  // AC1, AC3, AC5: Register self-alias in nexus projectIdAliases table