@cleocode/core 2026.9.21 → 2026.9.23

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 (491) hide show
  1. package/dist/agents/scaffold.d.ts.map +1 -1
  2. package/dist/agents/scaffold.js +0 -1
  3. package/dist/agents/scaffold.js.map +1 -1
  4. package/dist/bootstrap.d.ts.map +1 -1
  5. package/dist/bootstrap.js +4 -0
  6. package/dist/bootstrap.js.map +1 -1
  7. package/dist/build-provenance.json +6 -0
  8. package/dist/decide/audit.d.ts +7 -1
  9. package/dist/decide/audit.d.ts.map +1 -1
  10. package/dist/decide/audit.js.map +1 -1
  11. package/dist/decide/client.d.ts +46 -4
  12. package/dist/decide/client.d.ts.map +1 -1
  13. package/dist/decide/client.js +328 -33
  14. package/dist/decide/client.js.map +1 -1
  15. package/dist/decide/credentials.d.ts +28 -4
  16. package/dist/decide/credentials.d.ts.map +1 -1
  17. package/dist/decide/credentials.js +50 -12
  18. package/dist/decide/credentials.js.map +1 -1
  19. package/dist/decide/index.d.ts +10 -4
  20. package/dist/decide/index.d.ts.map +1 -1
  21. package/dist/decide/index.js +10 -4
  22. package/dist/decide/index.js.map +1 -1
  23. package/dist/decide/jev-wire.d.ts +100 -8
  24. package/dist/decide/jev-wire.d.ts.map +1 -1
  25. package/dist/decide/jev-wire.js +402 -55
  26. package/dist/decide/jev-wire.js.map +1 -1
  27. package/dist/decide/operations.d.ts +97 -20
  28. package/dist/decide/operations.d.ts.map +1 -1
  29. package/dist/decide/operations.js +180 -28
  30. package/dist/decide/operations.js.map +1 -1
  31. package/dist/decide/provider-state.d.ts +89 -0
  32. package/dist/decide/provider-state.d.ts.map +1 -0
  33. package/dist/decide/provider-state.js +134 -0
  34. package/dist/decide/provider-state.js.map +1 -0
  35. package/dist/decide/provider.d.ts +26 -5
  36. package/dist/decide/provider.d.ts.map +1 -1
  37. package/dist/decide/provider.js.map +1 -1
  38. package/dist/decide/providers.d.ts +58 -0
  39. package/dist/decide/providers.d.ts.map +1 -0
  40. package/dist/decide/providers.js +69 -0
  41. package/dist/decide/providers.js.map +1 -0
  42. package/dist/decide/site.d.ts +2 -2
  43. package/dist/decide/site.d.ts.map +1 -1
  44. package/dist/decide/site.js +2 -0
  45. package/dist/decide/site.js.map +1 -1
  46. package/dist/decide/sites/list.d.ts +46 -0
  47. package/dist/decide/sites/list.d.ts.map +1 -0
  48. package/dist/decide/sites/list.js +206 -0
  49. package/dist/decide/sites/list.js.map +1 -0
  50. package/dist/decide/sites/registry.d.ts +130 -0
  51. package/dist/decide/sites/registry.d.ts.map +1 -0
  52. package/dist/decide/sites/registry.js +375 -0
  53. package/dist/decide/sites/registry.js.map +1 -0
  54. package/dist/decide/spend.d.ts +196 -0
  55. package/dist/decide/spend.d.ts.map +1 -0
  56. package/dist/decide/spend.js +387 -0
  57. package/dist/decide/spend.js.map +1 -0
  58. package/dist/decide/wizard.d.ts +53 -0
  59. package/dist/decide/wizard.d.ts.map +1 -0
  60. package/dist/decide/wizard.js +144 -0
  61. package/dist/decide/wizard.js.map +1 -0
  62. package/dist/dispatch/mutate-projection.d.ts.map +1 -1
  63. package/dist/dispatch/mutate-projection.js +5 -0
  64. package/dist/dispatch/mutate-projection.js.map +1 -1
  65. package/dist/docs/docs-audit.d.ts.map +1 -1
  66. package/dist/docs/docs-audit.js +1 -2
  67. package/dist/docs/docs-audit.js.map +1 -1
  68. package/dist/docs/docs-update.d.ts.map +1 -1
  69. package/dist/docs/docs-update.js +25 -9
  70. package/dist/docs/docs-update.js.map +1 -1
  71. package/dist/docs/export-document.js +1073 -628
  72. package/dist/docs/export-document.js.map +3 -3
  73. package/dist/doctor/knowledge.d.ts +16 -1
  74. package/dist/doctor/knowledge.d.ts.map +1 -1
  75. package/dist/doctor/knowledge.js +53 -17
  76. package/dist/doctor/knowledge.js.map +1 -1
  77. package/dist/engine/engine-ops.d.ts +36 -6
  78. package/dist/engine/engine-ops.d.ts.map +1 -1
  79. package/dist/engine/engine-ops.js +115 -14
  80. package/dist/engine/engine-ops.js.map +1 -1
  81. package/dist/gateway-client/generated/types.gen.d.ts +1 -1
  82. package/dist/index.d.ts +2 -0
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +1 -0
  85. package/dist/index.js.map +1 -1
  86. package/dist/init/scaffold-workflows.d.ts.map +1 -1
  87. package/dist/init/scaffold-workflows.js +6 -3
  88. package/dist/init/scaffold-workflows.js.map +1 -1
  89. package/dist/init/upgrade-workflows.d.ts.map +1 -1
  90. package/dist/init/upgrade-workflows.js +6 -3
  91. package/dist/init/upgrade-workflows.js.map +1 -1
  92. package/dist/init.d.ts.map +1 -1
  93. package/dist/init.js +51 -11
  94. package/dist/init.js.map +1 -1
  95. package/dist/inject/index.d.ts.map +1 -1
  96. package/dist/inject/index.js +8 -3
  97. package/dist/inject/index.js.map +1 -1
  98. package/dist/internal.d.ts +3 -3
  99. package/dist/internal.d.ts.map +1 -1
  100. package/dist/internal.js +2 -2
  101. package/dist/internal.js.map +1 -1
  102. package/dist/llm/plugin-facade.js +1184 -739
  103. package/dist/llm/plugin-facade.js.map +3 -3
  104. package/dist/memory/attention.d.ts.map +1 -1
  105. package/dist/memory/attention.js +2 -2
  106. package/dist/memory/attention.js.map +1 -1
  107. package/dist/memory/decision-contradiction.d.ts +3 -3
  108. package/dist/memory/decision-contradiction.d.ts.map +1 -1
  109. package/dist/memory/decision-contradiction.js +4 -3
  110. package/dist/memory/decision-contradiction.js.map +1 -1
  111. package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
  112. package/dist/memory/graph-memory-bridge.js +2 -0
  113. package/dist/memory/graph-memory-bridge.js.map +1 -1
  114. package/dist/memory/observation-type-decision.d.ts +2 -2
  115. package/dist/memory/observation-type-decision.d.ts.map +1 -1
  116. package/dist/memory/observation-type-decision.js +3 -2
  117. package/dist/memory/observation-type-decision.js.map +1 -1
  118. package/dist/memory/pipeline-manifest-sqlite.d.ts +111 -0
  119. package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
  120. package/dist/memory/pipeline-manifest-sqlite.js +230 -2
  121. package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
  122. package/dist/nexus/analyze-orchestrator.d.ts +38 -0
  123. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  124. package/dist/nexus/analyze-orchestrator.js +96 -21
  125. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  126. package/dist/nexus/knowledge.d.ts.map +1 -1
  127. package/dist/nexus/knowledge.js +15 -4
  128. package/dist/nexus/knowledge.js.map +1 -1
  129. package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
  130. package/dist/nexus/migrations/M-split-graph.js +4 -0
  131. package/dist/nexus/migrations/M-split-graph.js.map +1 -1
  132. package/dist/nexus/store.d.ts.map +1 -1
  133. package/dist/nexus/store.js +2 -0
  134. package/dist/nexus/store.js.map +1 -1
  135. package/dist/nexus/stored-roots.d.ts +65 -0
  136. package/dist/nexus/stored-roots.d.ts.map +1 -1
  137. package/dist/nexus/stored-roots.js +73 -0
  138. package/dist/nexus/stored-roots.js.map +1 -1
  139. package/dist/orchestrate/lifecycle-ops.d.ts.map +1 -1
  140. package/dist/orchestrate/lifecycle-ops.js +4 -1
  141. package/dist/orchestrate/lifecycle-ops.js.map +1 -1
  142. package/dist/orchestrate/pivot.d.ts.map +1 -1
  143. package/dist/orchestrate/pivot.js +13 -8
  144. package/dist/orchestrate/pivot.js.map +1 -1
  145. package/dist/orchestrate/plan.d.ts.map +1 -1
  146. package/dist/orchestrate/plan.js +8 -2
  147. package/dist/orchestrate/plan.js.map +1 -1
  148. package/dist/orchestrate/query-ops.d.ts +7 -2
  149. package/dist/orchestrate/query-ops.d.ts.map +1 -1
  150. package/dist/orchestrate/query-ops.js +17 -6
  151. package/dist/orchestrate/query-ops.js.map +1 -1
  152. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  153. package/dist/orchestrate/spawn-ops.js +5 -14
  154. package/dist/orchestrate/spawn-ops.js.map +1 -1
  155. package/dist/orchestration/bootstrap.d.ts.map +1 -1
  156. package/dist/orchestration/bootstrap.js +4 -2
  157. package/dist/orchestration/bootstrap.js.map +1 -1
  158. package/dist/orchestration/index.d.ts +1 -0
  159. package/dist/orchestration/index.d.ts.map +1 -1
  160. package/dist/orchestration/index.js +4 -3
  161. package/dist/orchestration/index.js.map +1 -1
  162. package/dist/orchestration/lead-rollup.d.ts +8 -5
  163. package/dist/orchestration/lead-rollup.d.ts.map +1 -1
  164. package/dist/orchestration/lead-rollup.js +46 -17
  165. package/dist/orchestration/lead-rollup.js.map +1 -1
  166. package/dist/orchestration/owner-decision-readiness.d.ts +2 -2
  167. package/dist/orchestration/owner-decision-readiness.d.ts.map +1 -1
  168. package/dist/orchestration/owner-decision-readiness.js +3 -2
  169. package/dist/orchestration/owner-decision-readiness.js.map +1 -1
  170. package/dist/orchestration/parallel.d.ts.map +1 -1
  171. package/dist/orchestration/parallel.js +10 -17
  172. package/dist/orchestration/parallel.js.map +1 -1
  173. package/dist/orchestration/spawn-prompt.d.ts +4 -1
  174. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  175. package/dist/orchestration/spawn-prompt.js +3 -2
  176. package/dist/orchestration/spawn-prompt.js.map +1 -1
  177. package/dist/orchestration/status.d.ts +8 -3
  178. package/dist/orchestration/status.d.ts.map +1 -1
  179. package/dist/orchestration/status.js +9 -6
  180. package/dist/orchestration/status.js.map +1 -1
  181. package/dist/orchestration/validate-spawn.d.ts.map +1 -1
  182. package/dist/orchestration/validate-spawn.js +2 -0
  183. package/dist/orchestration/validate-spawn.js.map +1 -1
  184. package/dist/orchestration/wave-topic.d.ts +54 -0
  185. package/dist/orchestration/wave-topic.d.ts.map +1 -0
  186. package/dist/orchestration/wave-topic.js +68 -0
  187. package/dist/orchestration/wave-topic.js.map +1 -0
  188. package/dist/orchestration/waves.d.ts +47 -8
  189. package/dist/orchestration/waves.d.ts.map +1 -1
  190. package/dist/orchestration/waves.js +152 -43
  191. package/dist/orchestration/waves.js.map +1 -1
  192. package/dist/phases/index.d.ts.map +1 -1
  193. package/dist/phases/index.js +6 -2
  194. package/dist/phases/index.js.map +1 -1
  195. package/dist/project-scope.d.ts +34 -0
  196. package/dist/project-scope.d.ts.map +1 -1
  197. package/dist/project-scope.js +73 -0
  198. package/dist/project-scope.js.map +1 -1
  199. package/dist/release/ci-evidence.d.ts +10 -0
  200. package/dist/release/ci-evidence.d.ts.map +1 -1
  201. package/dist/release/ci-evidence.js +23 -7
  202. package/dist/release/ci-evidence.js.map +1 -1
  203. package/dist/release/github-pr.d.ts +30 -0
  204. package/dist/release/github-pr.d.ts.map +1 -1
  205. package/dist/release/github-pr.js +42 -1
  206. package/dist/release/github-pr.js.map +1 -1
  207. package/dist/release/plan.d.ts.map +1 -1
  208. package/dist/release/plan.js +6 -3
  209. package/dist/release/plan.js.map +1 -1
  210. package/dist/release/pr-evidence.d.ts.map +1 -1
  211. package/dist/release/pr-evidence.js +12 -4
  212. package/dist/release/pr-evidence.js.map +1 -1
  213. package/dist/routing/capability-matrix.d.ts.map +1 -1
  214. package/dist/routing/capability-matrix.js +7 -0
  215. package/dist/routing/capability-matrix.js.map +1 -1
  216. package/dist/security/input-sanitization.d.ts.map +1 -1
  217. package/dist/security/input-sanitization.js +9 -2
  218. package/dist/security/input-sanitization.js.map +1 -1
  219. package/dist/selfimprove/fix-gen.js +1193 -748
  220. package/dist/selfimprove/fix-gen.js.map +3 -3
  221. package/dist/session/engine-ops.d.ts +6 -0
  222. package/dist/session/engine-ops.d.ts.map +1 -1
  223. package/dist/session/engine-ops.js +36 -4
  224. package/dist/session/engine-ops.js.map +1 -1
  225. package/dist/sessions/briefing.d.ts +17 -0
  226. package/dist/sessions/briefing.d.ts.map +1 -1
  227. package/dist/sessions/briefing.js +68 -68
  228. package/dist/sessions/briefing.js.map +1 -1
  229. package/dist/sessions/drift-watchdog.d.ts.map +1 -1
  230. package/dist/sessions/drift-watchdog.js +4 -3
  231. package/dist/sessions/drift-watchdog.js.map +1 -1
  232. package/dist/sessions/focus-state-store.d.ts +94 -1
  233. package/dist/sessions/focus-state-store.d.ts.map +1 -1
  234. package/dist/sessions/focus-state-store.js +100 -1
  235. package/dist/sessions/focus-state-store.js.map +1 -1
  236. package/dist/sessions/index.d.ts +2 -2
  237. package/dist/sessions/index.d.ts.map +1 -1
  238. package/dist/sessions/index.js +1 -1
  239. package/dist/sessions/index.js.map +1 -1
  240. package/dist/sessions/session-drift.d.ts.map +1 -1
  241. package/dist/sessions/session-drift.js +4 -3
  242. package/dist/sessions/session-drift.js.map +1 -1
  243. package/dist/setup/config-json-merge.d.ts +28 -0
  244. package/dist/setup/config-json-merge.d.ts.map +1 -1
  245. package/dist/setup/config-json-merge.js +51 -0
  246. package/dist/setup/config-json-merge.js.map +1 -1
  247. package/dist/setup/index.d.ts +13 -10
  248. package/dist/setup/index.d.ts.map +1 -1
  249. package/dist/setup/index.js +15 -10
  250. package/dist/setup/index.js.map +1 -1
  251. package/dist/setup/sections/llm.js +1 -1
  252. package/dist/setup/sections/llm.js.map +1 -1
  253. package/dist/setup/sections/system-one.d.ts +28 -0
  254. package/dist/setup/sections/system-one.d.ts.map +1 -0
  255. package/dist/setup/sections/system-one.js +53 -0
  256. package/dist/setup/sections/system-one.js.map +1 -0
  257. package/dist/setup/wizard.d.ts +15 -1
  258. package/dist/setup/wizard.d.ts.map +1 -1
  259. package/dist/setup/wizard.js +15 -0
  260. package/dist/setup/wizard.js.map +1 -1
  261. package/dist/skills/discovery.d.ts +12 -1
  262. package/dist/skills/discovery.d.ts.map +1 -1
  263. package/dist/skills/discovery.js +27 -2
  264. package/dist/skills/discovery.js.map +1 -1
  265. package/dist/skills/orchestrator/startup.d.ts.map +1 -1
  266. package/dist/skills/orchestrator/startup.js +10 -5
  267. package/dist/skills/orchestrator/startup.js.map +1 -1
  268. package/dist/skills/prune-bundled.d.ts +306 -0
  269. package/dist/skills/prune-bundled.d.ts.map +1 -0
  270. package/dist/skills/prune-bundled.js +652 -0
  271. package/dist/skills/prune-bundled.js.map +1 -0
  272. package/dist/skills/types.d.ts +9 -1
  273. package/dist/skills/types.d.ts.map +1 -1
  274. package/dist/skills/types.js +17 -34
  275. package/dist/skills/types.js.map +1 -1
  276. package/dist/spawn/branch-lock.d.ts.map +1 -1
  277. package/dist/spawn/branch-lock.js +26 -2
  278. package/dist/spawn/branch-lock.js.map +1 -1
  279. package/dist/stats/index.d.ts.map +1 -1
  280. package/dist/stats/index.js +4 -2
  281. package/dist/stats/index.js.map +1 -1
  282. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  283. package/dist/store/agent-registry-accessor.js +2 -0
  284. package/dist/store/agent-registry-accessor.js.map +1 -1
  285. package/dist/store/backup-pack.js +1 -1
  286. package/dist/store/backup-pack.js.map +1 -1
  287. package/dist/store/backup.d.ts +15 -1
  288. package/dist/store/backup.d.ts.map +1 -1
  289. package/dist/store/backup.js +18 -2
  290. package/dist/store/backup.js.map +1 -1
  291. package/dist/store/conduit-sqlite.d.ts.map +1 -1
  292. package/dist/store/conduit-sqlite.js +3 -0
  293. package/dist/store/conduit-sqlite.js.map +1 -1
  294. package/dist/store/credential-transfer.d.ts.map +1 -1
  295. package/dist/store/credential-transfer.js +2 -0
  296. package/dist/store/credential-transfer.js.map +1 -1
  297. package/dist/store/cross-db-cleanup.d.ts.map +1 -1
  298. package/dist/store/cross-db-cleanup.js +2 -0
  299. package/dist/store/cross-db-cleanup.js.map +1 -1
  300. package/dist/store/dual-scope-db.d.ts.map +1 -1
  301. package/dist/store/dual-scope-db.js +13 -2
  302. package/dist/store/dual-scope-db.js.map +1 -1
  303. package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -1
  304. package/dist/store/migrate-signaldock-to-conduit.js +3 -0
  305. package/dist/store/migrate-signaldock-to-conduit.js.map +1 -1
  306. package/dist/store/migration-manager.d.ts.map +1 -1
  307. package/dist/store/migration-manager.js +37 -3
  308. package/dist/store/migration-manager.js.map +1 -1
  309. package/dist/store/migration-sqlite.d.ts.map +1 -1
  310. package/dist/store/migration-sqlite.js +2 -0
  311. package/dist/store/migration-sqlite.js.map +1 -1
  312. package/dist/store/nexus-sqlite.d.ts.map +1 -1
  313. package/dist/store/nexus-sqlite.js +3 -0
  314. package/dist/store/nexus-sqlite.js.map +1 -1
  315. package/dist/store/open-cleo-db.d.ts.map +1 -1
  316. package/dist/store/open-cleo-db.js +3 -0
  317. package/dist/store/open-cleo-db.js.map +1 -1
  318. package/dist/store/portable-bundle-import.d.ts.map +1 -1
  319. package/dist/store/portable-bundle-import.js +2 -0
  320. package/dist/store/portable-bundle-import.js.map +1 -1
  321. package/dist/store/portable-bundle-relocate.d.ts.map +1 -1
  322. package/dist/store/portable-bundle-relocate.js +2 -0
  323. package/dist/store/portable-bundle-relocate.js.map +1 -1
  324. package/dist/store/portable-bundle-scan.js +1 -1
  325. package/dist/store/portable-bundle-scan.js.map +1 -1
  326. package/dist/store/ports/domain-binding.d.ts.map +1 -1
  327. package/dist/store/ports/domain-binding.js +5 -0
  328. package/dist/store/ports/domain-binding.js.map +1 -1
  329. package/dist/store/skills-db.d.ts +17 -0
  330. package/dist/store/skills-db.d.ts.map +1 -1
  331. package/dist/store/skills-db.js +30 -0
  332. package/dist/store/skills-db.js.map +1 -1
  333. package/dist/store/snapshot-gate.d.ts.map +1 -1
  334. package/dist/store/snapshot-gate.js +3 -0
  335. package/dist/store/snapshot-gate.js.map +1 -1
  336. package/dist/store/split-brain-import.d.ts.map +1 -1
  337. package/dist/store/split-brain-import.js +2 -0
  338. package/dist/store/split-brain-import.js.map +1 -1
  339. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  340. package/dist/store/sqlite-data-accessor.js +19 -2
  341. package/dist/store/sqlite-data-accessor.js.map +1 -1
  342. package/dist/store/sqlite-native.d.ts.map +1 -1
  343. package/dist/store/sqlite-native.js +1 -0
  344. package/dist/store/sqlite-native.js.map +1 -1
  345. package/dist/store/sqlite.d.ts +14 -0
  346. package/dist/store/sqlite.d.ts.map +1 -1
  347. package/dist/store/sqlite.js +31 -4
  348. package/dist/store/sqlite.js.map +1 -1
  349. package/dist/store/twin-collapse.d.ts +46 -1
  350. package/dist/store/twin-collapse.d.ts.map +1 -1
  351. package/dist/store/twin-collapse.js +131 -5
  352. package/dist/store/twin-collapse.js.map +1 -1
  353. package/dist/store/worktree-build-guard.d.ts +191 -0
  354. package/dist/store/worktree-build-guard.d.ts.map +1 -0
  355. package/dist/store/worktree-build-guard.js +486 -0
  356. package/dist/store/worktree-build-guard.js.map +1 -0
  357. package/dist/store/worktree-isolation-guard.d.ts +27 -0
  358. package/dist/store/worktree-isolation-guard.d.ts.map +1 -1
  359. package/dist/store/worktree-isolation-guard.js +71 -3
  360. package/dist/store/worktree-isolation-guard.js.map +1 -1
  361. package/dist/store/writer-lease.d.ts.map +1 -1
  362. package/dist/store/writer-lease.js +2 -0
  363. package/dist/store/writer-lease.js.map +1 -1
  364. package/dist/system/backup.d.ts +6 -2
  365. package/dist/system/backup.d.ts.map +1 -1
  366. package/dist/system/backup.js +6 -3
  367. package/dist/system/backup.js.map +1 -1
  368. package/dist/system/inject-generate.d.ts.map +1 -1
  369. package/dist/system/inject-generate.js +4 -4
  370. package/dist/system/inject-generate.js.map +1 -1
  371. package/dist/task-tools/index.d.ts +4 -2
  372. package/dist/task-tools/index.d.ts.map +1 -1
  373. package/dist/task-tools/index.js +3 -2
  374. package/dist/task-tools/index.js.map +1 -1
  375. package/dist/task-tools/score-task-priority.d.ts +93 -18
  376. package/dist/task-tools/score-task-priority.d.ts.map +1 -1
  377. package/dist/task-tools/score-task-priority.js +193 -81
  378. package/dist/task-tools/score-task-priority.js.map +1 -1
  379. package/dist/task-work/index.d.ts +6 -0
  380. package/dist/task-work/index.d.ts.map +1 -1
  381. package/dist/task-work/index.js +6 -3
  382. package/dist/task-work/index.js.map +1 -1
  383. package/dist/tasks/affected-packages.d.ts +62 -13
  384. package/dist/tasks/affected-packages.d.ts.map +1 -1
  385. package/dist/tasks/affected-packages.js +158 -33
  386. package/dist/tasks/affected-packages.js.map +1 -1
  387. package/dist/tasks/affected-scope.d.ts +59 -0
  388. package/dist/tasks/affected-scope.d.ts.map +1 -0
  389. package/dist/tasks/affected-scope.js +81 -0
  390. package/dist/tasks/affected-scope.js.map +1 -0
  391. package/dist/tasks/analyze.d.ts +29 -1
  392. package/dist/tasks/analyze.d.ts.map +1 -1
  393. package/dist/tasks/analyze.js +52 -36
  394. package/dist/tasks/analyze.js.map +1 -1
  395. package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
  396. package/dist/tasks/backfill-child-projections.js +4 -1
  397. package/dist/tasks/backfill-child-projections.js.map +1 -1
  398. package/dist/tasks/change-set.d.ts +24 -0
  399. package/dist/tasks/change-set.d.ts.map +1 -1
  400. package/dist/tasks/change-set.js +143 -11
  401. package/dist/tasks/change-set.js.map +1 -1
  402. package/dist/tasks/command-line.d.ts +54 -0
  403. package/dist/tasks/command-line.d.ts.map +1 -0
  404. package/dist/tasks/command-line.js +151 -0
  405. package/dist/tasks/command-line.js.map +1 -0
  406. package/dist/tasks/complete.d.ts +10 -0
  407. package/dist/tasks/complete.d.ts.map +1 -1
  408. package/dist/tasks/complete.js +49 -0
  409. package/dist/tasks/complete.js.map +1 -1
  410. package/dist/tasks/component-pr.d.ts +106 -0
  411. package/dist/tasks/component-pr.d.ts.map +1 -0
  412. package/dist/tasks/component-pr.js +275 -0
  413. package/dist/tasks/component-pr.js.map +1 -0
  414. package/dist/tasks/delete.d.ts.map +1 -1
  415. package/dist/tasks/delete.js +20 -0
  416. package/dist/tasks/delete.js.map +1 -1
  417. package/dist/tasks/done-plan.d.ts +21 -1
  418. package/dist/tasks/done-plan.d.ts.map +1 -1
  419. package/dist/tasks/done-plan.js +170 -15
  420. package/dist/tasks/done-plan.js.map +1 -1
  421. package/dist/tasks/done-record.d.ts.map +1 -1
  422. package/dist/tasks/done-record.js +9 -80
  423. package/dist/tasks/done-record.js.map +1 -1
  424. package/dist/tasks/duplicate-detector.d.ts +3 -3
  425. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  426. package/dist/tasks/duplicate-detector.js +4 -3
  427. package/dist/tasks/duplicate-detector.js.map +1 -1
  428. package/dist/tasks/engine-wrap-ops.d.ts +29 -0
  429. package/dist/tasks/engine-wrap-ops.d.ts.map +1 -1
  430. package/dist/tasks/engine-wrap-ops.js +40 -0
  431. package/dist/tasks/engine-wrap-ops.js.map +1 -1
  432. package/dist/tasks/engine-wrap.d.ts +1 -1
  433. package/dist/tasks/engine-wrap.d.ts.map +1 -1
  434. package/dist/tasks/engine-wrap.js +1 -1
  435. package/dist/tasks/engine-wrap.js.map +1 -1
  436. package/dist/tasks/evidence.d.ts +49 -2
  437. package/dist/tasks/evidence.d.ts.map +1 -1
  438. package/dist/tasks/evidence.js +85 -9
  439. package/dist/tasks/evidence.js.map +1 -1
  440. package/dist/tasks/gate-runner.d.ts.map +1 -1
  441. package/dist/tasks/gate-runner.js +48 -12
  442. package/dist/tasks/gate-runner.js.map +1 -1
  443. package/dist/tasks/index.d.ts +1 -1
  444. package/dist/tasks/index.d.ts.map +1 -1
  445. package/dist/tasks/index.js +1 -1
  446. package/dist/tasks/index.js.map +1 -1
  447. package/dist/tasks/ops.d.ts +1 -0
  448. package/dist/tasks/ops.d.ts.map +1 -1
  449. package/dist/tasks/ranking-audit.d.ts +122 -0
  450. package/dist/tasks/ranking-audit.d.ts.map +1 -0
  451. package/dist/tasks/ranking-audit.js +193 -0
  452. package/dist/tasks/ranking-audit.js.map +1 -0
  453. package/dist/tasks/task-analyze.d.ts.map +1 -1
  454. package/dist/tasks/task-analyze.js +19 -32
  455. package/dist/tasks/task-analyze.js.map +1 -1
  456. package/dist/tasks/task-next.d.ts +48 -2
  457. package/dist/tasks/task-next.d.ts.map +1 -1
  458. package/dist/tasks/task-next.js +84 -102
  459. package/dist/tasks/task-next.js.map +1 -1
  460. package/dist/tasks/task-ops.d.ts +1 -1
  461. package/dist/tasks/task-ops.d.ts.map +1 -1
  462. package/dist/tasks/task-ops.js +1 -1
  463. package/dist/tasks/task-ops.js.map +1 -1
  464. package/dist/tasks/tool-resolver.d.ts +7 -1
  465. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  466. package/dist/tasks/tool-resolver.js +24 -10
  467. package/dist/tasks/tool-resolver.js.map +1 -1
  468. package/dist/tasks/update.d.ts +8 -2
  469. package/dist/tasks/update.d.ts.map +1 -1
  470. package/dist/tasks/update.js +28 -1
  471. package/dist/tasks/update.js.map +1 -1
  472. package/dist/telemetry/sqlite.d.ts.map +1 -1
  473. package/dist/telemetry/sqlite.js +2 -0
  474. package/dist/telemetry/sqlite.js.map +1 -1
  475. package/dist/validation/doctor/checks.d.ts.map +1 -1
  476. package/dist/validation/doctor/checks.js +2 -2
  477. package/dist/validation/doctor/checks.js.map +1 -1
  478. package/dist/validation/engine-ops.d.ts +9 -1
  479. package/dist/validation/engine-ops.d.ts.map +1 -1
  480. package/dist/validation/engine-ops.js +24 -1
  481. package/dist/validation/engine-ops.js.map +1 -1
  482. package/dist/validation/validate-ops.d.ts.map +1 -1
  483. package/dist/validation/validate-ops.js +9 -3
  484. package/dist/validation/validate-ops.js.map +1 -1
  485. package/dist/worktree/worktree-adopt.d.ts.map +1 -1
  486. package/dist/worktree/worktree-adopt.js +5 -2
  487. package/dist/worktree/worktree-adopt.js.map +1 -1
  488. package/package.json +14 -14
  489. package/schemas/config.schema.json +13 -0
  490. package/templates/CLEO-INJECTION.md +1 -1
  491. package/templates/CLEO-REFERENCE.md +5 -1
@@ -344,7 +344,7 @@ var init_acceptance_gate_schema = __esm({
344
344
  message: "Result cannot precede input capture"
345
345
  });
346
346
  const executable = ["test", "command", "lint"].includes(result.kind);
347
- if (executable && !binding.invocation)
347
+ if (executable && !binding.invocation && result.result !== "error")
348
348
  context.addIssue({
349
349
  code: "custom",
350
350
  path: ["binding", "invocation"],
@@ -3110,12 +3110,21 @@ var init_operations_registry = __esm({
3110
3110
  gateway: "query",
3111
3111
  domain: "tasks",
3112
3112
  operation: "history",
3113
- description: "Show task work history (time tracked per task)",
3113
+ description: "Show task work history; with taskId, the task audit trail; with ranking, who changed its priority/severity/kind/depends and why (T12693)",
3114
3114
  tier: 1,
3115
3115
  idempotent: true,
3116
3116
  sessionRequired: false,
3117
3117
  requiredParams: [],
3118
- params: []
3118
+ params: [
3119
+ { name: "taskId", type: "string", required: false, description: "Task to show history for" },
3120
+ { name: "limit", type: "number", required: false, description: "Maximum entries" },
3121
+ {
3122
+ name: "ranking",
3123
+ type: "boolean",
3124
+ required: false,
3125
+ description: "Only ranking-input changes (actor, session, reason, before/after)"
3126
+ }
3127
+ ]
3119
3128
  },
3120
3129
  {
3121
3130
  gateway: "query",
@@ -5610,6 +5619,32 @@ var init_operations_registry = __esm({
5610
5619
  ],
5611
5620
  outputSchema: OUTPUT_CONTRACTS["tasks.assignee"]
5612
5621
  },
5622
+ {
5623
+ gateway: "mutate",
5624
+ domain: "tasks",
5625
+ operation: "ranking.revert",
5626
+ description: "tasks.ranking.revert (mutate) \u2014 undo one recorded ranking change (priority/severity/kind/depends) as a new audited change (T12693, D11161)",
5627
+ tier: 1,
5628
+ idempotent: false,
5629
+ sessionRequired: false,
5630
+ requiredParams: ["entryId"],
5631
+ params: [
5632
+ {
5633
+ name: "entryId",
5634
+ type: "string",
5635
+ required: true,
5636
+ description: "ranking_changed audit row id (cleo history ranking <taskId>)",
5637
+ cli: { positional: true }
5638
+ },
5639
+ { name: "reason", type: "string", required: false, description: "Why it is reverted" },
5640
+ {
5641
+ name: "force",
5642
+ type: "boolean",
5643
+ required: false,
5644
+ description: "Revert even though a field changed again since"
5645
+ }
5646
+ ]
5647
+ },
5613
5648
  {
5614
5649
  gateway: "mutate",
5615
5650
  domain: "tasks",
@@ -10533,7 +10568,7 @@ var init_operations_registry = __esm({
10533
10568
  type: "string",
10534
10569
  required: false,
10535
10570
  enum: DOCS_LIFECYCLE_STATUSES,
10536
- description: `Override the new lifecycle status. Defaults to "draft" on every update. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
10571
+ description: `Override the new lifecycle status. Defaults to "draft" on every update. Alone (no file or content) it changes only the lifecycle status. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
10537
10572
  },
10538
10573
  {
10539
10574
  name: "dryRun",
@@ -13020,11 +13055,13 @@ var init_evidence_atom_schema = __esm({
13020
13055
  });
13021
13056
  prAtomSchema = z10.object({
13022
13057
  kind: z10.literal("pr"),
13023
- prNumber: z10.number().int().positive("pr atom requires a positive integer PR number")
13058
+ prNumber: z10.number().int().positive("pr atom requires a positive integer PR number"),
13059
+ componentPrNumber: z10.number().int().positive().optional()
13024
13060
  });
13025
13061
  ciAtomSchema = z10.object({
13026
13062
  kind: z10.literal("ci"),
13027
- prNumber: z10.number().int().positive("ci atom requires a positive integer PR number")
13063
+ prNumber: z10.number().int().positive("ci atom requires a positive integer PR number"),
13064
+ componentPrNumber: z10.number().int().positive().optional()
13028
13065
  });
13029
13066
  locDropAtomSchema = z10.object({
13030
13067
  kind: z10.literal("loc-drop"),
@@ -13075,7 +13112,10 @@ var init_evidence_atom_schema = __esm({
13075
13112
  ["commit", "note"],
13076
13113
  ["decision", "files"],
13077
13114
  ["decision", "note"],
13078
- ["pr", "files"]
13115
+ ["pr", "files"],
13116
+ // T12689: a deletion-only PR (no bytes to hash). Contextual validation
13117
+ // accepts this only when every change the PR made is a deletion.
13118
+ ["pr", "note"]
13079
13119
  ]
13080
13120
  },
13081
13121
  testsPassed: { oneOf: [["test-run"], ["tool"], ["ci"]] },
@@ -17050,7 +17090,7 @@ var init_collection_keys = __esm({
17050
17090
 
17051
17091
  // packages/contracts/src/decide.ts
17052
17092
  import { z as z24 } from "zod";
17053
- var DECISION_QUESTION_TYPES, DECISION_OUTCOME_SOURCES, DECISION_REQUEST_LIMITS, decisionQuestionTypeSchema, decisionOutcomeSourceSchema, decisionInstructionsSchema, unitIntervalSchema, decisionStateSchema, noulDecisionQuestionSchema, choiceDecisionQuestionSchema, scoreDecisionQuestionSchema, decisionQuestionSchema, decisionRequestSchema, noulDecisionAnswerSchema, choiceDecisionAnswerSchema, scoreDecisionAnswerSchema, decisionAnswerSchema, decisionOutcomeSchema, decisionProviderConfigSchema;
17093
+ var DECISION_QUESTION_TYPES, DECISION_OUTCOME_SOURCES, DECISION_REQUEST_LIMITS, DECISION_PROVIDER_KINDS, decisionQuestionTypeSchema, decisionOutcomeSourceSchema, decisionInstructionsSchema, unitIntervalSchema, decisionStateSchema, noulDecisionQuestionSchema, choiceDecisionQuestionSchema, scoreDecisionQuestionSchema, decisionQuestionSchema, decisionRequestSchema, noulDecisionAnswerSchema, choiceDecisionAnswerSchema, scoreDecisionAnswerSchema, decisionAnswerSchema, decisionOutcomeSchema, decisionProviderKindSchema, decisionProviderConfigSchema;
17054
17094
  var init_decide = __esm({
17055
17095
  "packages/contracts/src/decide.ts"() {
17056
17096
  "use strict";
@@ -17074,6 +17114,7 @@ var init_decide = __esm({
17074
17114
  /** Maximum number of levels on a `score` question's scale. */
17075
17115
  maxScoreLevels: 10
17076
17116
  };
17117
+ DECISION_PROVIDER_KINDS = ["layahost", "jev"];
17077
17118
  decisionQuestionTypeSchema = z24.enum(DECISION_QUESTION_TYPES);
17078
17119
  decisionOutcomeSourceSchema = z24.enum(DECISION_OUTCOME_SOURCES);
17079
17120
  decisionInstructionsSchema = z24.union([z24.string(), z24.record(z24.string(), z24.json())]);
@@ -17111,6 +17152,8 @@ var init_decide = __esm({
17111
17152
  ]);
17112
17153
  decisionRequestSchema = z24.object({
17113
17154
  model: z24.string().min(1).optional(),
17155
+ lang: z24.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$/).optional(),
17156
+ cache: z24.boolean().optional(),
17114
17157
  state: decisionStateSchema,
17115
17158
  questions: z24.record(z24.string().min(1), decisionQuestionSchema).refine(
17116
17159
  (questions) => {
@@ -17151,14 +17194,26 @@ var init_decide = __esm({
17151
17194
  requestId: z24.string().min(1).optional(),
17152
17195
  latencyMs: z24.number().nonnegative(),
17153
17196
  costUsd: z24.number().nonnegative().optional(),
17197
+ costMicros: z24.number().int().nonnegative().optional(),
17198
+ balanceMicros: z24.number().int().optional(),
17199
+ checkpoint: z24.string().min(1).optional(),
17154
17200
  inputTokens: z24.number().int().nonnegative().optional()
17155
17201
  });
17202
+ decisionProviderKindSchema = z24.enum(DECISION_PROVIDER_KINDS);
17156
17203
  decisionProviderConfigSchema = z24.object({
17157
- baseUrl: z24.url()
17204
+ baseUrl: z24.url(),
17205
+ provider: decisionProviderKindSchema.optional()
17158
17206
  });
17159
17207
  }
17160
17208
  });
17161
17209
 
17210
+ // packages/contracts/src/decide-sites.ts
17211
+ var init_decide_sites = __esm({
17212
+ "packages/contracts/src/decide-sites.ts"() {
17213
+ "use strict";
17214
+ }
17215
+ });
17216
+
17162
17217
  // packages/contracts/src/task-id.ts
17163
17218
  var init_task_id = __esm({
17164
17219
  "packages/contracts/src/task-id.ts"() {
@@ -17240,6 +17295,7 @@ var init_src = __esm({
17240
17295
  init_caamp_markers();
17241
17296
  init_collection_keys();
17242
17297
  init_decide();
17298
+ init_decide_sites();
17243
17299
  init_task_id();
17244
17300
  }
17245
17301
  });
@@ -18759,6 +18815,37 @@ function linkedWorktreeMainRoot(dir) {
18759
18815
  if (basename2(commonDir) === ".git") return dirname2(commonDir);
18760
18816
  return readCoreWorktree(commonDir);
18761
18817
  }
18818
+ function describeWorktreeOwner(dir) {
18819
+ const mainRoot = linkedWorktreeMainRoot(dir);
18820
+ if (mainRoot === null) {
18821
+ const bare = bareRepositoryOfWorktree(dir);
18822
+ return bare === null ? "owning repository unknown (unreadable gitlink)" : `owning repository ${bare} is a bare git repository with no main checkout to hold a CLEO store; clone it to a regular checkout, run \`cleo init\` there, and create worktrees from that checkout`;
18823
+ }
18824
+ let projectId = null;
18825
+ try {
18826
+ const parsed = JSON.parse(
18827
+ readFileSync2(join3(mainRoot, ".cleo", "project-info.json"), "utf-8")
18828
+ );
18829
+ if (typeof parsed === "object" && parsed !== null && "projectId" in parsed) {
18830
+ const value = parsed.projectId;
18831
+ if (typeof value === "string" && value !== "") projectId = value;
18832
+ }
18833
+ } catch {
18834
+ }
18835
+ return projectId === null ? `owning repository ${mainRoot} (not an initialised CLEO project)` : `owning project ${mainRoot} (projectId ${projectId})`;
18836
+ }
18837
+ function bareRepositoryOfWorktree(dir) {
18838
+ const gitdir = readGitlinkTarget(dir);
18839
+ if (!gitdir || basename2(dirname2(gitdir)) !== "worktrees") return null;
18840
+ const commonDir = dirname2(dirname2(gitdir));
18841
+ try {
18842
+ const config2 = readFileSync2(join3(commonDir, "config"), "utf-8");
18843
+ const core = /^\[core\][^[]*/m.exec(config2)?.[0] ?? "";
18844
+ return /^\s*bare\s*=\s*true\s*$/im.test(core) ? commonDir : null;
18845
+ } catch {
18846
+ return null;
18847
+ }
18848
+ }
18762
18849
  function readCoreWorktree(gitDir) {
18763
18850
  try {
18764
18851
  const config2 = readFileSync2(join3(gitDir, "config"), "utf-8");
@@ -19208,13 +19295,13 @@ function captureWriteFence(input) {
19208
19295
  return writeFence;
19209
19296
  }
19210
19297
  function observeOperation(context, work) {
19211
- return new Promise((resolve15) => {
19298
+ return new Promise((resolve17) => {
19212
19299
  let observed = false;
19213
19300
  const finish = (result) => {
19214
19301
  if (observed) return;
19215
19302
  observed = true;
19216
19303
  context.signal.removeEventListener("abort", abort);
19217
- resolve15(result);
19304
+ resolve17(result);
19218
19305
  };
19219
19306
  const abort = () => {
19220
19307
  const reason = context.signal.reason;
@@ -19848,7 +19935,7 @@ var init_sql = __esm({
19848
19935
  return new SQL([new StringChunk(str)]);
19849
19936
  }
19850
19937
  _sql.raw = raw;
19851
- function join49(chunks, separator) {
19938
+ function join50(chunks, separator) {
19852
19939
  const result = [];
19853
19940
  for (const [i, chunk] of chunks.entries()) {
19854
19941
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -19856,7 +19943,7 @@ var init_sql = __esm({
19856
19943
  }
19857
19944
  return new SQL(result);
19858
19945
  }
19859
- _sql.join = join49;
19946
+ _sql.join = join50;
19860
19947
  function identifier2(value) {
19861
19948
  return new Name(value);
19862
19949
  }
@@ -21871,7 +21958,7 @@ var init_select = __esm({
21871
21958
  const baseTableName = this.tableName;
21872
21959
  const tableName = getTableLikeName(table);
21873
21960
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
21874
- if (typeof tableName === "string" && this.config.joins?.some((join49) => join49.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21961
+ if (typeof tableName === "string" && this.config.joins?.some((join50) => join50.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21875
21962
  if (!this.isPartialSelect) {
21876
21963
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
21877
21964
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -23468,7 +23555,7 @@ var init_dialect = __esm({
23468
23555
  if (!joins2) return;
23469
23556
  const withEntries = Object.entries(joins2).filter(([_, v]) => v);
23470
23557
  if (!withEntries.length) return;
23471
- return sql.join(withEntries.map(([k, join49]) => {
23558
+ return sql.join(withEntries.map(([k, join50]) => {
23472
23559
  const relation = tableConfig.relations[k];
23473
23560
  const isSingle2 = is(relation, One);
23474
23561
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -23479,7 +23566,7 @@ var init_dialect = __esm({
23479
23566
  table: targetTable,
23480
23567
  mode: isSingle2 ? "first" : "many",
23481
23568
  schema,
23482
- queryConfig: join49,
23569
+ queryConfig: join50,
23483
23570
  tableConfig: schema[relation.targetTableName],
23484
23571
  relationWhere: filter2,
23485
23572
  isNested: true,
@@ -23493,7 +23580,7 @@ var init_dialect = __esm({
23493
23580
  key: k,
23494
23581
  selection: innerQuery.selection,
23495
23582
  isArray: !isSingle2,
23496
- isOptional: (relation.optional ?? false) || join49 !== true && !!join49.where
23583
+ isOptional: (relation.optional ?? false) || join50 !== true && !!join50.where
23497
23584
  });
23498
23585
  const jsonColumns = sql.join(innerQuery.selection.map((s) => {
23499
23586
  return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
@@ -23915,7 +24002,7 @@ var init_update = __esm({
23915
24002
  createJoin(joinType) {
23916
24003
  return ((table, on) => {
23917
24004
  const tableName = getTableLikeName(table);
23918
- if (typeof tableName === "string" && this.config.joins.some((join49) => join49.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
24005
+ if (typeof tableName === "string" && this.config.joins.some((join50) => join50.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
23919
24006
  if (typeof on === "function") {
23920
24007
  const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
23921
24008
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -25063,7 +25150,7 @@ async function withWriteRetry(fn, opts = {}) {
25063
25150
  throw contentionErr;
25064
25151
  }
25065
25152
  function sleep(ms) {
25066
- return new Promise((resolve15) => setTimeout(resolve15, ms));
25153
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
25067
25154
  }
25068
25155
  var DEFAULT_MAX_ATTEMPTS, DEFAULT_BASE_DELAY_MS, DEFAULT_JITTER_MS;
25069
25156
  var init_with_retry = __esm({
@@ -25075,9 +25162,250 @@ var init_with_retry = __esm({
25075
25162
  }
25076
25163
  });
25077
25164
 
25165
+ // packages/core/src/store/worktree-build-guard.ts
25166
+ import { existsSync as existsSync4, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "node:fs";
25167
+ import { createRequire } from "node:module";
25168
+ import { dirname as dirname3, isAbsolute as isAbsolute3, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
25169
+ import { fileURLToPath } from "node:url";
25170
+ function realOrResolved(path) {
25171
+ try {
25172
+ return realpathSync3(path);
25173
+ } catch {
25174
+ return resolve2(path);
25175
+ }
25176
+ }
25177
+ function isWithin(root, path) {
25178
+ const local = relative2(root, path);
25179
+ return local === "" || !isAbsolute3(local) && local !== ".." && !local.startsWith(`..${sep2}`);
25180
+ }
25181
+ function insideGitCheckout(dir) {
25182
+ let current = dir;
25183
+ for (; ; ) {
25184
+ if (existsSync4(join5(current, ".git"))) return true;
25185
+ const parent = dirname3(current);
25186
+ if (parent === current) return false;
25187
+ current = parent;
25188
+ }
25189
+ }
25190
+ function insideTestSandbox(path) {
25191
+ let dir = dirname3(path);
25192
+ for (; ; ) {
25193
+ if (existsSync4(join5(dir, TEST_SANDBOX_MARKER))) return !insideGitCheckout(dir);
25194
+ const parent = dirname3(dir);
25195
+ if (parent === dir) return false;
25196
+ dir = parent;
25197
+ }
25198
+ }
25199
+ function linkedWorktreeRootOf(path) {
25200
+ let dir = realOrResolved(path);
25201
+ for (; ; ) {
25202
+ if (isGitLinkedCheckout(dir)) return dir;
25203
+ if (existsSync4(join5(dir, ".git"))) return null;
25204
+ const parent = dirname3(dir);
25205
+ if (parent === dir) return null;
25206
+ dir = parent;
25207
+ }
25208
+ }
25209
+ function readBuildProvenance(codePath) {
25210
+ let dir = dirname3(codePath);
25211
+ for (; ; ) {
25212
+ const stamp = join5(dir, "build-provenance.json");
25213
+ if (existsSync4(stamp)) {
25214
+ try {
25215
+ const parsed = JSON.parse(readFileSync3(stamp, "utf8"));
25216
+ if (typeof parsed === "object" && parsed !== null && "linkedWorktree" in parsed) {
25217
+ const value = parsed.linkedWorktree;
25218
+ if (value === null || typeof value === "string") return { linkedWorktree: value };
25219
+ }
25220
+ } catch {
25221
+ }
25222
+ return null;
25223
+ }
25224
+ if (existsSync4(join5(dir, "package.json"))) return null;
25225
+ const parent = dirname3(dir);
25226
+ if (parent === dir) return null;
25227
+ dir = parent;
25228
+ }
25229
+ }
25230
+ function devBuildWorktree(options = {}) {
25231
+ const codePath = options.codePath ?? overrides?.codePath ?? fileURLToPath(import.meta.url);
25232
+ const provenance = options.provenance !== void 0 ? options.provenance : overrides?.provenance !== void 0 ? overrides.provenance : readBuildProvenance(codePath);
25233
+ if (provenance) return provenance.linkedWorktree;
25234
+ if (codePath.split(/[\\/]/).includes("node_modules")) return null;
25235
+ return linkedWorktreeRootOf(codePath);
25236
+ }
25237
+ function schemaWriteRefusal(dbPath, options = {}) {
25238
+ const env = options.env ?? overrides?.env ?? process.env;
25239
+ const buildWorktree = devBuildWorktree(options);
25240
+ if (buildWorktree === null) return null;
25241
+ const store = realOrResolved(dbPath);
25242
+ if (isWithin(realOrResolved(buildWorktree), store)) return null;
25243
+ if (env["VITEST"]) return null;
25244
+ const honourTestSandbox = options.honourTestSandbox ?? overrides?.honourTestSandbox ?? true;
25245
+ if (honourTestSandbox && insideTestSandbox(store)) return null;
25246
+ if (env[ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV] === "1") return null;
25247
+ return `Refusing to change the schema of ${store}: this CLI was built inside the git worktree ${buildWorktree}, and its schema may be unreleased. Run the released \`cleo\` against this store, or opt in with ${ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV}=1 (T12687).`;
25248
+ }
25249
+ function decisionFor(dbPath) {
25250
+ const key = realOrResolved(dbPath);
25251
+ if (!decisions.has(key)) decisions.set(key, schemaWriteRefusal(key));
25252
+ return decisions.get(key) ?? null;
25253
+ }
25254
+ function isWorktreeBuildSchemaError(error48) {
25255
+ return error48 instanceof Error && error48.message.includes(E_WORKTREE_BUILD_SCHEMA);
25256
+ }
25257
+ function codes() {
25258
+ if (authorizerCodes) return authorizerCodes;
25259
+ const sqlite = createRequire(import.meta.url)("node:sqlite").constants;
25260
+ authorizerCodes = {
25261
+ sqlite,
25262
+ creates: /* @__PURE__ */ new Map([
25263
+ [sqlite.SQLITE_CREATE_TABLE, "table"],
25264
+ [sqlite.SQLITE_CREATE_VTABLE, "table"],
25265
+ [sqlite.SQLITE_CREATE_INDEX, "index"],
25266
+ [sqlite.SQLITE_CREATE_TRIGGER, "trigger"],
25267
+ [sqlite.SQLITE_CREATE_VIEW, "view"]
25268
+ ]),
25269
+ changes: /* @__PURE__ */ new Set([
25270
+ sqlite.SQLITE_ALTER_TABLE,
25271
+ sqlite.SQLITE_DROP_TABLE,
25272
+ sqlite.SQLITE_DROP_INDEX,
25273
+ sqlite.SQLITE_DROP_TRIGGER,
25274
+ sqlite.SQLITE_DROP_VIEW,
25275
+ sqlite.SQLITE_DROP_VTABLE
25276
+ ])
25277
+ };
25278
+ return authorizerCodes;
25279
+ }
25280
+ function attachRefusal(name15) {
25281
+ if (name15 === "" || name15 === ":memory:") return null;
25282
+ if (typeof name15 !== "string" || /^file:/i.test(name15) || name15.includes("?")) {
25283
+ return UNKNOWN_ATTACH_REFUSAL;
25284
+ }
25285
+ return decisionFor(name15);
25286
+ }
25287
+ function readSchemas(nativeDb) {
25288
+ const schemas = /* @__PURE__ */ new Map();
25289
+ const list = nativeDb.prepare("PRAGMA database_list").all();
25290
+ for (const { name: name15, file: file2 } of list) {
25291
+ if (name15 === "temp") continue;
25292
+ const rows = nativeDb.prepare(`SELECT type, name FROM "${name15.replaceAll('"', '""')}".sqlite_master`).all();
25293
+ schemas.set(name15.toLowerCase(), {
25294
+ refusal: file2 ? decisionFor(file2) : null,
25295
+ // '' = in-memory
25296
+ objects: new Set(rows.map((r) => `${r.type}:${r.name}`))
25297
+ });
25298
+ }
25299
+ return schemas;
25300
+ }
25301
+ function guardActive() {
25302
+ const env = overrides?.env ?? process.env;
25303
+ if (env["VITEST"]) return false;
25304
+ if (overrides) return devBuildWorktree() !== null;
25305
+ if (processBuildWorktree === void 0) processBuildWorktree = devBuildWorktree();
25306
+ return processBuildWorktree !== null;
25307
+ }
25308
+ function installSchemaWriteGuard(nativeDb) {
25309
+ if (!guardActive()) return false;
25310
+ const location = nativeDb.location();
25311
+ const mainRefusal = location ? decisionFor(location) : null;
25312
+ if (typeof nativeDb.setAuthorizer !== "function") {
25313
+ if (mainRefusal) throw new WorktreeBuildSchemaError(mainRefusal);
25314
+ return false;
25315
+ }
25316
+ const state = {
25317
+ schemas: readSchemas(nativeDb),
25318
+ unmappedAttachRefusal: null,
25319
+ stale: false,
25320
+ lastDenied: null
25321
+ };
25322
+ guards.set(nativeDb, state);
25323
+ const { sqlite, creates, changes } = codes();
25324
+ nativeDb.setAuthorizer((action, arg1, arg2, dbName) => {
25325
+ if (action === sqlite.SQLITE_ATTACH) {
25326
+ const refusal2 = attachRefusal(arg1);
25327
+ if (refusal2 && !state.unmappedAttachRefusal) state.unmappedAttachRefusal = refusal2;
25328
+ return sqlite.SQLITE_OK;
25329
+ }
25330
+ if (action === sqlite.SQLITE_DETACH) {
25331
+ state.stale = true;
25332
+ return sqlite.SQLITE_OK;
25333
+ }
25334
+ const createType = creates.get(action);
25335
+ if (createType === void 0 && !changes.has(action)) return sqlite.SQLITE_OK;
25336
+ const schema = ((action === sqlite.SQLITE_ALTER_TABLE ? arg1 : dbName) ?? "main").toLowerCase();
25337
+ if (schema === "temp") return sqlite.SQLITE_OK;
25338
+ const mapped = state.schemas.get(schema);
25339
+ const policy = state.stale ? void 0 : mapped;
25340
+ const refusal = policy ? policy.refusal : (mapped?.refusal ?? null) || state.unmappedAttachRefusal;
25341
+ if (refusal === null) return sqlite.SQLITE_OK;
25342
+ if (createType !== void 0 && policy?.objects.has(`${createType}:${arg1}`)) {
25343
+ return sqlite.SQLITE_OK;
25344
+ }
25345
+ state.lastDenied = {
25346
+ what: createType !== void 0 ? `CREATE ${createType} ${schema}.${arg1}` : `schema change on ${schema}.${(action === sqlite.SQLITE_ALTER_TABLE ? arg2 : arg1) ?? ""}`,
25347
+ refusal
25348
+ };
25349
+ return sqlite.SQLITE_DENY;
25350
+ });
25351
+ return mainRefusal !== null;
25352
+ }
25353
+ function refreshSchemaWriteGuard(nativeDb) {
25354
+ const state = guards.get(nativeDb);
25355
+ if (!state) return;
25356
+ state.schemas = readSchemas(nativeDb);
25357
+ state.unmappedAttachRefusal = null;
25358
+ state.stale = false;
25359
+ }
25360
+ function explainSchemaWriteDenial(nativeDb, error48) {
25361
+ if (!(error48 instanceof Error) || !/not authorized/i.test(error48.message)) return error48;
25362
+ const denied = guards.get(nativeDb)?.lastDenied;
25363
+ if (!denied) return error48;
25364
+ return new WorktreeBuildSchemaError(`${denied.refusal} Denied: ${denied.what}.`);
25365
+ }
25366
+ function pendingMigrations(nativeDb, migrations) {
25367
+ const hasJournal = nativeDb.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '__drizzle_migrations'").get();
25368
+ const applied = hasJournal ? new Set(
25369
+ nativeDb.prepare('SELECT hash FROM main."__drizzle_migrations"').all().map((row) => row.hash)
25370
+ ) : /* @__PURE__ */ new Set();
25371
+ return migrations.filter((m) => !applied.has(m.hash)).map((m) => m.name ?? m.hash);
25372
+ }
25373
+ function assertNoPendingMigrationsForWorktreeBuild(nativeDb, migrations) {
25374
+ const dbPath = nativeDb.location();
25375
+ if (!dbPath) return;
25376
+ const refusal = decisionFor(dbPath);
25377
+ if (refusal === null) return;
25378
+ const pending = pendingMigrations(nativeDb, migrations);
25379
+ if (pending.length === 0) return;
25380
+ throw new WorktreeBuildSchemaError(`${refusal} Pending migrations: ${pending.join(", ")}.`);
25381
+ }
25382
+ var ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV, TEST_SANDBOX_MARKER, E_WORKTREE_BUILD_SCHEMA, overrides, decisions, WorktreeBuildSchemaError, authorizerCodes, guards, UNKNOWN_ATTACH_REFUSAL, processBuildWorktree;
25383
+ var init_worktree_build_guard = __esm({
25384
+ "packages/core/src/store/worktree-build-guard.ts"() {
25385
+ "use strict";
25386
+ init_src();
25387
+ init_errors2();
25388
+ init_project_scope();
25389
+ ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV = "CLEO_ALLOW_WORKTREE_BUILD_MIGRATIONS";
25390
+ TEST_SANDBOX_MARKER = ".cleo-test-sandbox";
25391
+ E_WORKTREE_BUILD_SCHEMA = "E_WORKTREE_BUILD_SCHEMA";
25392
+ overrides = null;
25393
+ decisions = /* @__PURE__ */ new Map();
25394
+ WorktreeBuildSchemaError = class extends CleoError {
25395
+ constructor(message) {
25396
+ super(8 /* CONFIG_ERROR */, `${E_WORKTREE_BUILD_SCHEMA}: ${message}`, {
25397
+ fix: `Use the released \`cleo\` for this store, run the build against a store inside its own worktree, or set ${ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV}=1 to accept the schema change.`
25398
+ });
25399
+ }
25400
+ };
25401
+ guards = /* @__PURE__ */ new WeakMap();
25402
+ UNKNOWN_ATTACH_REFUSAL = "a store was ATTACHed by a bound, computed or URI filename, so this build cannot tell whose store it is; schema changes on unmapped schemas are refused until the guard is refreshed";
25403
+ }
25404
+ });
25405
+
25078
25406
  // packages/core/src/store/migration-manager.ts
25079
- import { copyFileSync, existsSync as existsSync4 } from "node:fs";
25080
- import { dirname as dirname3, join as join5 } from "node:path";
25407
+ import { copyFileSync, existsSync as existsSync5 } from "node:fs";
25408
+ import { dirname as dirname4, join as join6 } from "node:path";
25081
25409
  function stripSqlComments(sql29) {
25082
25410
  return sql29.replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
25083
25411
  }
@@ -25116,10 +25444,10 @@ function computeEliminatedTables(migrations) {
25116
25444
  return eliminated;
25117
25445
  }
25118
25446
  function resolveConsolidationCutoverPrefix(migrationsFolder) {
25119
- const parent = dirname3(migrationsFolder);
25447
+ const parent = dirname4(migrationsFolder);
25120
25448
  for (const setName of ["drizzle-cleo-project", "drizzle-cleo-global"]) {
25121
- const folder = join5(parent, setName);
25122
- if (!existsSync4(folder)) continue;
25449
+ const folder = join6(parent, setName);
25450
+ if (!existsSync5(folder)) continue;
25123
25451
  try {
25124
25452
  const consolidation = readMigrationFiles({ migrationsFolder: folder }).find(
25125
25453
  (m) => /-consolidation-cleo-/.test(m.name ?? "")
@@ -25143,7 +25471,7 @@ function tableExists(nativeDb, tableName) {
25143
25471
  }
25144
25472
  function createSafetyBackup(dbPath) {
25145
25473
  const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
25146
- if (!existsSync4(backupPath)) {
25474
+ if (!existsSync5(backupPath)) {
25147
25475
  try {
25148
25476
  copyFileSync(dbPath, backupPath);
25149
25477
  } catch {
@@ -25261,6 +25589,16 @@ function readSiblingMigrationHashes(siblingFolder) {
25261
25589
  return /* @__PURE__ */ new Set();
25262
25590
  }
25263
25591
  }
25592
+ function readSiblingNewestMillis(siblingFolder) {
25593
+ try {
25594
+ return Math.max(
25595
+ 0,
25596
+ ...readMigrationFiles({ migrationsFolder: siblingFolder }).map((m) => m.folderMillis)
25597
+ );
25598
+ } catch {
25599
+ return 0;
25600
+ }
25601
+ }
25264
25602
  function ensureJournalHashUnique(nativeDb) {
25265
25603
  if (!tableExists(nativeDb, "__drizzle_migrations")) return;
25266
25604
  try {
@@ -25309,6 +25647,7 @@ function upgradeSharedJournalFormat(nativeDb, lineageFolders) {
25309
25647
  return { named, unnamed: rows.length - named };
25310
25648
  }
25311
25649
  function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsystem, siblingMigrationsFolders = []) {
25650
+ assertNoPendingMigrationsForWorktreeBuild(nativeDb, readMigrationFiles({ migrationsFolder }));
25312
25651
  const eliminatedTables = computeEliminatedTables(readMigrationFiles({ migrationsFolder }));
25313
25652
  const cutoverPrefix = resolveConsolidationCutoverPrefix(migrationsFolder);
25314
25653
  if (siblingMigrationsFolders.length > 0)
@@ -25340,8 +25679,15 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25340
25679
  knownHashes.add(m);
25341
25680
  }
25342
25681
  }
25343
- const dbEntries = nativeDb.prepare('SELECT id, hash FROM "__drizzle_migrations"').all();
25344
- const orphanedEntries = dbEntries.filter((e) => !knownHashes.has(e.hash));
25682
+ const newestKnownMillis = Math.max(
25683
+ 0,
25684
+ ...localMigrations.map((m) => m.folderMillis),
25685
+ ...siblingMigrationsFolders.filter((folder) => folder !== migrationsFolder).map(readSiblingNewestMillis)
25686
+ );
25687
+ const dbEntries = nativeDb.prepare('SELECT id, hash, created_at FROM "__drizzle_migrations"').all();
25688
+ const orphanedEntries = dbEntries.filter(
25689
+ (e) => !knownHashes.has(e.hash) && !(Number(e.created_at) > newestKnownMillis)
25690
+ );
25345
25691
  const hasOrphanedEntries = orphanedEntries.length > 0;
25346
25692
  if (hasOrphanedEntries) {
25347
25693
  const dbHashes = new Set(dbEntries.map((e) => e.hash));
@@ -25583,6 +25929,8 @@ function sanitizeMigrationStatements(migrations) {
25583
25929
  }
25584
25930
  function migrateSanitized(db, config2) {
25585
25931
  const raw = readMigrationFiles(config2);
25932
+ const client = db.$client;
25933
+ if (client) assertNoPendingMigrationsForWorktreeBuild(client, raw);
25586
25934
  const sanitized = sanitizeMigrationStatements(raw);
25587
25935
  migrateSync(sanitized, db._.session, config2);
25588
25936
  }
@@ -25646,6 +25994,7 @@ var init_migration_manager = __esm({
25646
25994
  init_sqlite_core();
25647
25995
  init_logger2();
25648
25996
  init_with_retry();
25997
+ init_worktree_build_guard();
25649
25998
  MAX_MIGRATION_RETRIES = 5;
25650
25999
  MIGRATION_RETRY_BASE_DELAY_MS = 100;
25651
26000
  MIGRATION_RETRY_MAX_DELAY_MS = 2e3;
@@ -25655,13 +26004,13 @@ var init_migration_manager = __esm({
25655
26004
  });
25656
26005
 
25657
26006
  // packages/core/src/store/relocated-store-guard.ts
25658
- import { existsSync as existsSync5, realpathSync as realpathSync3 } from "node:fs";
25659
- import { createRequire } from "node:module";
25660
- import { basename as basename3, dirname as dirname4 } from "node:path";
26007
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
26008
+ import { createRequire as createRequire2 } from "node:module";
26009
+ import { basename as basename3, dirname as dirname5 } from "node:path";
25661
26010
  import { readDeclaredProjectIdentity as readDeclaredProjectIdentity2, readPortableProjectId } from "@cleocode/paths";
25662
26011
  function real2(p) {
25663
26012
  try {
25664
- return realpathSync3(p);
26013
+ return realpathSync4(p);
25665
26014
  } catch {
25666
26015
  return p;
25667
26016
  }
@@ -25678,7 +26027,7 @@ function liveElsewhere(globalDbPath, projectId, root) {
25678
26027
  "SELECT project_path AS projectPath FROM nexus_project_registry WHERE project_id = ?"
25679
26028
  ).get(projectId);
25680
26029
  const live = row?.projectPath;
25681
- if (!live || paths.has(live) || !existsSync5(live)) return null;
26030
+ if (!live || paths.has(live) || !existsSync6(live)) return null;
25682
26031
  if (!isStrictlyInsideDir(root, live)) return null;
25683
26032
  return readDeclaredProjectIdentity2(live)?.projectId === projectId ? live : null;
25684
26033
  } catch {
@@ -25692,14 +26041,14 @@ function detectRelocatedRoot(root, globalDbPath) {
25692
26041
  if (tombstone)
25693
26042
  return { projectId: tombstone.projectId, movedTo: tombstone.movedTo, via: "tombstone" };
25694
26043
  const declared = readPortableProjectId(root);
25695
- if (declared.status !== "valid" || !existsSync5(globalDbPath)) return null;
26044
+ if (declared.status !== "valid" || !existsSync6(globalDbPath)) return null;
25696
26045
  const movedTo = liveElsewhere(globalDbPath, declared.projectId, root);
25697
26046
  return movedTo ? { projectId: declared.projectId, movedTo, via: "registry" } : null;
25698
26047
  }
25699
26048
  function assertStoreNotRelocated(dbPath, globalDbPath) {
25700
- if (basename3(dbPath) !== "cleo.db" || basename3(dirname4(dbPath)) !== ".cleo") return;
25701
- if (existsSync5(dbPath) || globalDbPath === dbPath) return;
25702
- const root = dirname4(dirname4(dbPath));
26049
+ if (basename3(dbPath) !== "cleo.db" || basename3(dirname5(dbPath)) !== ".cleo") return;
26050
+ if (existsSync6(dbPath) || globalDbPath === dbPath) return;
26051
+ const root = dirname5(dirname5(dbPath));
25703
26052
  if (_adopted.has(root)) return;
25704
26053
  const moved = detectRelocatedRoot(root, globalDbPath);
25705
26054
  if (moved) throw projectMovedError(root, moved, void 0, moved.via);
@@ -25709,17 +26058,17 @@ var init_relocated_store_guard = __esm({
25709
26058
  "packages/core/src/store/relocated-store-guard.ts"() {
25710
26059
  "use strict";
25711
26060
  init_project_tombstone();
25712
- _require = createRequire(import.meta.url);
26061
+ _require = createRequire2(import.meta.url);
25713
26062
  _adopted = /* @__PURE__ */ new Set();
25714
26063
  }
25715
26064
  });
25716
26065
 
25717
26066
  // packages/core/src/store/resolve-migrations-folder.ts
25718
- import { createRequire as createRequire2 } from "node:module";
25719
- import { dirname as dirname5, join as join6 } from "node:path";
25720
- import { fileURLToPath } from "node:url";
26067
+ import { createRequire as createRequire3 } from "node:module";
26068
+ import { dirname as dirname6, join as join7 } from "node:path";
26069
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
25721
26070
  function coreRootFromEntry(entryPath) {
25722
- return dirname5(dirname5(entryPath));
26071
+ return dirname6(dirname6(entryPath));
25723
26072
  }
25724
26073
  function resolveConsolidatedJournalSiblings(ownSetName) {
25725
26074
  return CONSOLIDATED_JOURNAL_LINEAGES.filter((name15) => name15 !== ownSetName).map(
@@ -25729,14 +26078,14 @@ function resolveConsolidatedJournalSiblings(ownSetName) {
25729
26078
  function resolveCorePackageMigrationsFolder(setName) {
25730
26079
  try {
25731
26080
  const resolved = import.meta.resolve("@cleocode/core", import.meta.url);
25732
- const entryPath = fileURLToPath(resolved);
25733
- return join6(coreRootFromEntry(entryPath), "migrations", setName);
26081
+ const entryPath = fileURLToPath2(resolved);
26082
+ return join7(coreRootFromEntry(entryPath), "migrations", setName);
25734
26083
  } catch {
25735
26084
  }
25736
- const _require7 = createRequire2(import.meta.url);
26085
+ const _require7 = createRequire3(import.meta.url);
25737
26086
  try {
25738
26087
  const entryPath = _require7.resolve("@cleocode/core");
25739
- return join6(coreRootFromEntry(entryPath), "migrations", setName);
26088
+ return join7(coreRootFromEntry(entryPath), "migrations", setName);
25740
26089
  } catch (err) {
25741
26090
  throw new Error(
25742
26091
  `resolveCorePackageMigrationsFolder("${setName}"): cannot locate @cleocode/core from "${import.meta.url}". Ensure @cleocode/core is installed (workspace or npm). Original error: ${err.message}`
@@ -25832,11 +26181,11 @@ var init_sqlite_pragmas = __esm({
25832
26181
  });
25833
26182
 
25834
26183
  // packages/core/src/store/worktree-isolation-guard.ts
25835
- import { basename as basename4, dirname as dirname6, join as join7 } from "node:path";
26184
+ import { basename as basename4, dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
25836
26185
  function assertStorePathIsNotWorktreeResident(role, dbPath) {
25837
- const cleoDir = dirname6(dbPath);
26186
+ const cleoDir = dirname7(dbPath);
25838
26187
  if (basename4(cleoDir) !== ".cleo") return;
25839
- const projectRoot = dirname6(cleoDir);
26188
+ const projectRoot = dirname7(cleoDir);
25840
26189
  if (!isGitLinkedCheckout(projectRoot)) return;
25841
26190
  if (process.env["CLEO_ALLOW_WORKTREE_DB_CREATE"] === "1") {
25842
26191
  process.stderr.write(
@@ -25845,9 +26194,10 @@ function assertStorePathIsNotWorktreeResident(role, dbPath) {
25845
26194
  );
25846
26195
  return;
25847
26196
  }
26197
+ const owner = describeWorktreeOwner(projectRoot);
25848
26198
  throw new CleoError(
25849
26199
  8 /* CONFIG_ERROR */,
25850
- `E_WT_DB_ISOLATION_VIOLATION: refusing to open '${role}' DB at ${dbPath} \u2014 parent ${projectRoot} is a git worktree (gitlink). DBs must open against the canonical project root.`,
26200
+ `E_WT_DB_ISOLATION_VIOLATION: refusing to open '${role}' DB at ${dbPath} \u2014 parent ${projectRoot} is a git worktree (gitlink); ${owner}. DBs must open against the canonical project root.`,
25851
26201
  {
25852
26202
  fix: `Run from the canonical project root, or make sure the worktree's main repository is an initialised CLEO project so it resolves there. Inspect stranded worktree stores with \`cleo doctor worktree-stores\`. Emergency override (audited): CLEO_ALLOW_WORKTREE_DB_CREATE=1.`
25853
26203
  }
@@ -25860,7 +26210,7 @@ function assertDbPathIsNotWorktreeResident(role, cwd) {
25860
26210
  } catch {
25861
26211
  return;
25862
26212
  }
25863
- assertStorePathIsNotWorktreeResident(role, join7(cleoDir, PROJECT_STORE_FILENAME2));
26213
+ assertStorePathIsNotWorktreeResident(role, join8(cleoDir, PROJECT_STORE_FILENAME2));
25864
26214
  }
25865
26215
  var PROJECT_STORE_FILENAME2;
25866
26216
  var init_worktree_isolation_guard = __esm({
@@ -25880,10 +26230,10 @@ __export(sqlite_native_exports, {
25880
26230
  getDbSyncConstructor: () => getDbSyncConstructor,
25881
26231
  openNativeDatabase: () => openNativeDatabase
25882
26232
  });
25883
- import { realpathSync as realpathSync4 } from "node:fs";
25884
- import { createRequire as createRequire3 } from "node:module";
26233
+ import { realpathSync as realpathSync5 } from "node:fs";
26234
+ import { createRequire as createRequire4 } from "node:module";
25885
26235
  import { tmpdir as tmpdir2 } from "node:os";
25886
- import { delimiter, dirname as dirname7, isAbsolute as isAbsolute3, join as join8, resolve as resolve2, sep as sep2 } from "node:path";
26236
+ import { delimiter, dirname as dirname8, isAbsolute as isAbsolute4, join as join9, resolve as resolve4, sep as sep3 } from "node:path";
25887
26237
  function getDbSyncConstructor() {
25888
26238
  if (_ctor === null) {
25889
26239
  const mod = _require2("node:sqlite");
@@ -25892,19 +26242,19 @@ function getDbSyncConstructor() {
25892
26242
  return _ctor;
25893
26243
  }
25894
26244
  function resolveAbsoluteSafe(p) {
25895
- const abs = isAbsolute3(p) ? p : resolve2(p);
26245
+ const abs = isAbsolute4(p) ? p : resolve4(p);
25896
26246
  try {
25897
- return realpathSync4(abs);
26247
+ return realpathSync5(abs);
25898
26248
  } catch {
25899
26249
  const missingParts = [];
25900
26250
  let cursor = abs;
25901
26251
  while (true) {
25902
- const parent = dirname7(cursor);
26252
+ const parent = dirname8(cursor);
25903
26253
  if (parent === cursor) return abs;
25904
- missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep2) ? 0 : 1)));
26254
+ missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep3) ? 0 : 1)));
25905
26255
  cursor = parent;
25906
26256
  try {
25907
- return join8(realpathSync4(cursor), ...missingParts);
26257
+ return join9(realpathSync5(cursor), ...missingParts);
25908
26258
  } catch {
25909
26259
  }
25910
26260
  }
@@ -25912,7 +26262,7 @@ function resolveAbsoluteSafe(p) {
25912
26262
  }
25913
26263
  function isPathUnder(child, parent) {
25914
26264
  if (child === parent) return true;
25915
- const withSep = parent.endsWith(sep2) ? parent : parent + sep2;
26265
+ const withSep = parent.endsWith(sep3) ? parent : parent + sep3;
25916
26266
  return child.startsWith(withSep);
25917
26267
  }
25918
26268
  function assertVitestSafePath(path) {
@@ -25935,6 +26285,7 @@ function openNativeDatabase(path, options) {
25935
26285
  assertVitestSafePath(path);
25936
26286
  const DatabaseSyncCtor = getDbSyncConstructor();
25937
26287
  const db = new DatabaseSyncCtor(path, {
26288
+ // schema-guard-exempt: the native chokepoint; every writable caller installs the guard
25938
26289
  enableForeignKeyConstraints: true,
25939
26290
  readOnly: options?.readonly ?? false,
25940
26291
  // Default handle-open lock timeout mirrors the SSoT busy_timeout
@@ -25986,7 +26337,7 @@ var init_sqlite_native = __esm({
25986
26337
  "packages/core/src/store/sqlite-native.ts"() {
25987
26338
  "use strict";
25988
26339
  init_sqlite_pragmas();
25989
- _require2 = createRequire3(import.meta.url);
26340
+ _require2 = createRequire4(import.meta.url);
25990
26341
  _ctor = null;
25991
26342
  }
25992
26343
  });
@@ -26060,7 +26411,7 @@ var init_writer_lease_schema = __esm({
26060
26411
  // packages/core/src/store/writer-lease.ts
26061
26412
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
26062
26413
  import { randomUUID } from "node:crypto";
26063
- import { realpathSync as realpathSync5, statSync as statSync2 } from "node:fs";
26414
+ import { realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
26064
26415
  import { resolve as resolvePath } from "node:path";
26065
26416
  function log() {
26066
26417
  if (_log === null) _log = getLogger("writer-lease");
@@ -26150,7 +26501,7 @@ function resolveDbIdentity(db) {
26150
26501
  return identity;
26151
26502
  }
26152
26503
  function sleepAsync(ms) {
26153
- return new Promise((resolve15) => setTimeout(resolve15, Math.max(0, Math.round(ms))));
26504
+ return new Promise((resolve17) => setTimeout(resolve17, Math.max(0, Math.round(ms))));
26154
26505
  }
26155
26506
  function isPidAlive(pid) {
26156
26507
  try {
@@ -26489,7 +26840,7 @@ function assertColdOpenFile(frame) {
26489
26840
  async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
26490
26841
  opts.execution?.assertActive();
26491
26842
  const captured = opts.requiredIdentity;
26492
- const path = realpathSync5(captured.dbPath);
26843
+ const path = realpathSync6(captured.dbPath);
26493
26844
  const identity = statSync2(path, { bigint: true });
26494
26845
  if (captured.scope !== scope || captured.fileDevice !== String(identity.dev) || captured.fileInode !== String(identity.ino)) {
26495
26846
  throw new LeaseUnavailableError(
@@ -26522,6 +26873,7 @@ async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
26522
26873
  }
26523
26874
  const remaining = opts.execution ? Math.max(1, opts.execution.deadlineAt - Date.now()) : ACQUIRE_DEADLINE_MS;
26524
26875
  const owned = openNativeDatabase(path, { timeout: Math.min(ACQUIRE_DEADLINE_MS, remaining) });
26876
+ installSchemaWriteGuard(owned);
26525
26877
  try {
26526
26878
  opts.execution?.assertActive();
26527
26879
  const afterOpen = statSync2(path, { bigint: true });
@@ -26715,6 +27067,7 @@ var init_writer_lease = __esm({
26715
27067
  init_background_ops();
26716
27068
  init_dual_scope_db();
26717
27069
  init_sqlite_native();
27070
+ init_worktree_build_guard();
26718
27071
  init_writer_lease_schema();
26719
27072
  DEFAULT_TTL_MS = 3e4;
26720
27073
  DEFAULT_PRIORITY = 100;
@@ -27257,10 +27610,10 @@ var init_monitor = __esm({
27257
27610
 
27258
27611
  // packages/core/src/resources/supervisor-admit.ts
27259
27612
  import { connect } from "node:net";
27260
- import { join as join9 } from "node:path";
27613
+ import { join as join10 } from "node:path";
27261
27614
  import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
27262
27615
  function resolveSupervisorSocketPath() {
27263
- return process.env.CLEO_SUPERVISOR_SOCKET ?? join9(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
27616
+ return process.env.CLEO_SUPERVISOR_SOCKET ?? join10(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
27264
27617
  }
27265
27618
  async function sendResourceAdmit(socketPath, cls, holderId, budget) {
27266
27619
  const result = await sendLeaseRequest(
@@ -27283,7 +27636,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
27283
27636
  return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
27284
27637
  }
27285
27638
  function sendLeaseRequest(socketPath, request, expectedKind) {
27286
- return new Promise((resolve15) => {
27639
+ return new Promise((resolve17) => {
27287
27640
  const id = `ra-${process.pid}-${request.kind}`;
27288
27641
  const envelope = LeaseIpcRequestEnvelopeSchema.parse({
27289
27642
  protocol_version: LEASE_IPC_PROTOCOL_VERSION,
@@ -27301,7 +27654,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
27301
27654
  settled = true;
27302
27655
  socket.removeAllListeners();
27303
27656
  socket.destroy();
27304
- resolve15(value);
27657
+ resolve17(value);
27305
27658
  };
27306
27659
  const degrade = (reason) => done({ unavailable: true, reason });
27307
27660
  socket.setTimeout(REQUEST_TIMEOUT_MS);
@@ -27372,9 +27725,9 @@ __export(governor_exports, {
27372
27725
  resolveGovernorMode: () => resolveGovernorMode,
27373
27726
  slotFileCount: () => slotFileCount
27374
27727
  });
27375
- import { existsSync as existsSync6, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
27728
+ import { existsSync as existsSync7, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
27376
27729
  import { availableParallelism, totalmem } from "node:os";
27377
- import { join as join10 } from "node:path";
27730
+ import { join as join11 } from "node:path";
27378
27731
  import lockfile from "proper-lockfile";
27379
27732
  function log2() {
27380
27733
  if (_log2 === null) _log2 = getLogger("resource-governor");
@@ -27443,14 +27796,14 @@ function clamp(lo, v, hi) {
27443
27796
  return Math.max(lo, Math.min(v, hi));
27444
27797
  }
27445
27798
  function governorSlotDir(cls) {
27446
- return join10(getCleoHome(), "locks", `resource-${cls}`);
27799
+ return join11(getCleoHome(), "locks", `resource-${cls}`);
27447
27800
  }
27448
27801
  function ensureSlotFiles(dir, count) {
27449
- if (!existsSync6(dir)) mkdirSync(dir, { recursive: true });
27802
+ if (!existsSync7(dir)) mkdirSync(dir, { recursive: true });
27450
27803
  const paths = [];
27451
27804
  for (let i = 0; i < count; i++) {
27452
- const p = join10(dir, `slot-${i}.lock`);
27453
- if (!existsSync6(p)) writeFileSync3(p, "", { flag: "a" });
27805
+ const p = join11(dir, `slot-${i}.lock`);
27806
+ if (!existsSync7(p)) writeFileSync3(p, "", { flag: "a" });
27454
27807
  paths.push(p);
27455
27808
  }
27456
27809
  return paths;
@@ -27490,7 +27843,7 @@ function shuffledIndices(n) {
27490
27843
  }
27491
27844
  async function countHeldSlots(cls, budget) {
27492
27845
  const dir = governorSlotDir(cls);
27493
- if (!existsSync6(dir)) return 0;
27846
+ if (!existsSync7(dir)) return 0;
27494
27847
  const slots = ensureSlotFiles(dir, budget);
27495
27848
  let held = 0;
27496
27849
  for (const path of slots) {
@@ -27505,7 +27858,7 @@ async function countHeldSlots(cls, budget) {
27505
27858
  }
27506
27859
  function slotFileCount(cls) {
27507
27860
  const dir = governorSlotDir(cls);
27508
- if (!existsSync6(dir)) return 0;
27861
+ if (!existsSync7(dir)) return 0;
27509
27862
  return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
27510
27863
  }
27511
27864
  var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
@@ -27705,11 +28058,11 @@ var init_lock = __esm({
27705
28058
 
27706
28059
  // packages/core/src/store/atomic.ts
27707
28060
  import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
27708
- import { dirname as dirname8 } from "node:path";
28061
+ import { dirname as dirname9 } from "node:path";
27709
28062
  import writeFileAtomic from "write-file-atomic";
27710
28063
  async function atomicWrite(filePath, data, options) {
27711
28064
  try {
27712
- await mkdir(dirname8(filePath), { recursive: true });
28065
+ await mkdir(dirname9(filePath), { recursive: true });
27713
28066
  await writeFileAtomic(filePath, data, {
27714
28067
  encoding: options?.encoding ?? "utf8",
27715
28068
  mode: options?.mode
@@ -27742,7 +28095,7 @@ var init_atomic = __esm({
27742
28095
 
27743
28096
  // packages/core/src/store/backup.ts
27744
28097
  import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
27745
- import { basename as basename5, join as join11 } from "node:path";
28098
+ import { basename as basename5, dirname as dirname10, join as join12 } from "node:path";
27746
28099
  async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
27747
28100
  try {
27748
28101
  await mkdir2(backupDir, { recursive: true });
@@ -27753,14 +28106,14 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
27753
28106
  throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
27754
28107
  }
27755
28108
  for (let i = maxBackups; i >= 1; i--) {
27756
- const current = join11(backupDir, `${fileName}.${i}`);
28109
+ const current = join12(backupDir, `${fileName}.${i}`);
27757
28110
  if (i === maxBackups) {
27758
28111
  try {
27759
28112
  await unlink2(current);
27760
28113
  } catch {
27761
28114
  }
27762
28115
  } else {
27763
- const next = join11(backupDir, `${fileName}.${i + 1}`);
28116
+ const next = join12(backupDir, `${fileName}.${i + 1}`);
27764
28117
  try {
27765
28118
  await stat2(current);
27766
28119
  await fsRename(current, next);
@@ -27768,7 +28121,7 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
27768
28121
  }
27769
28122
  }
27770
28123
  }
27771
- const backupPath = join11(backupDir, `${fileName}.1`);
28124
+ const backupPath = join12(backupDir, `${fileName}.1`);
27772
28125
  await copyFile(filePath, backupPath);
27773
28126
  return backupPath;
27774
28127
  } catch (err) {
@@ -27782,6 +28135,7 @@ var init_backup = __esm({
27782
28135
  "use strict";
27783
28136
  init_src();
27784
28137
  init_errors2();
28138
+ init_worktree_isolation_guard();
27785
28139
  DEFAULT_MAX_BACKUPS = 5;
27786
28140
  }
27787
28141
  });
@@ -28066,7 +28420,7 @@ __export(identity_exports, {
28066
28420
  import { execFile } from "node:child_process";
28067
28421
  import { createHash as createHash2 } from "node:crypto";
28068
28422
  import { readFile as readFile3 } from "node:fs/promises";
28069
- import { join as join12, resolve as resolve3 } from "node:path";
28423
+ import { join as join13, resolve as resolve5 } from "node:path";
28070
28424
  import { promisify } from "node:util";
28071
28425
  import { legacyProjectId } from "@cleocode/paths";
28072
28426
  import { legacyProjectId as legacyProjectId2 } from "@cleocode/paths";
@@ -28074,14 +28428,14 @@ async function findGitRoot(fromPath, execution) {
28074
28428
  execution?.assertActive();
28075
28429
  try {
28076
28430
  const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
28077
- cwd: resolve3(fromPath),
28431
+ cwd: resolve5(fromPath),
28078
28432
  signal: execution?.signal,
28079
28433
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
28080
28434
  killSignal: "SIGKILL",
28081
28435
  maxBuffer: 64 * 1024
28082
28436
  });
28083
28437
  execution?.assertActive();
28084
- return resolve3(stdout.trim());
28438
+ return resolve5(stdout.trim());
28085
28439
  } catch {
28086
28440
  execution?.assertActive();
28087
28441
  return null;
@@ -28091,7 +28445,7 @@ async function findGitRemoteUrl(fromPath, execution) {
28091
28445
  execution?.assertActive();
28092
28446
  try {
28093
28447
  const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
28094
- cwd: resolve3(fromPath),
28448
+ cwd: resolve5(fromPath),
28095
28449
  signal: execution?.signal,
28096
28450
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
28097
28451
  killSignal: "SIGKILL",
@@ -28121,7 +28475,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
28121
28475
  try {
28122
28476
  const args = ["--no-replace-objects", "rev-list", "--max-parents=0", "HEAD"];
28123
28477
  const { stdout } = await execFileAsync("git", args, {
28124
- cwd: resolve3(fromPath),
28478
+ cwd: resolve5(fromPath),
28125
28479
  signal: execution?.signal,
28126
28480
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
28127
28481
  killSignal: "SIGKILL",
@@ -28144,7 +28498,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
28144
28498
  async function readProjectInfoName(repoRoot, execution) {
28145
28499
  execution?.assertActive();
28146
28500
  try {
28147
- const raw = await readFile3(join12(repoRoot, ".cleo", "project-info.json"), {
28501
+ const raw = await readFile3(join13(repoRoot, ".cleo", "project-info.json"), {
28148
28502
  encoding: "utf8",
28149
28503
  signal: execution?.signal
28150
28504
  });
@@ -28159,7 +28513,7 @@ async function readProjectInfoName(repoRoot, execution) {
28159
28513
  }
28160
28514
  async function projectPathFingerprint(repoPath, execution) {
28161
28515
  execution?.assertActive();
28162
- const realRepoPath = resolve3(repoPath);
28516
+ const realRepoPath = resolve5(repoPath);
28163
28517
  const results = await Promise.allSettled([
28164
28518
  findGitRoot(realRepoPath, execution),
28165
28519
  findGitRemoteUrl(realRepoPath, execution)
@@ -28183,9 +28537,9 @@ async function projectPathFingerprint(repoPath, execution) {
28183
28537
  }
28184
28538
  function computeLegacyAliases(repoPath, additionalPaths) {
28185
28539
  const aliases = /* @__PURE__ */ new Set();
28186
- aliases.add(legacyProjectId(resolve3(repoPath)));
28540
+ aliases.add(legacyProjectId(resolve5(repoPath)));
28187
28541
  for (const p of additionalPaths ?? []) {
28188
- aliases.add(legacyProjectId(resolve3(p)));
28542
+ aliases.add(legacyProjectId(resolve5(p)));
28189
28543
  }
28190
28544
  return [...aliases];
28191
28545
  }
@@ -28219,17 +28573,17 @@ var init_project_identity = __esm({
28219
28573
  });
28220
28574
 
28221
28575
  // packages/core/src/scaffold/ensure-config.ts
28222
- import { existsSync as existsSync7, readFileSync as readFileSync3 } from "node:fs";
28223
- import { basename as basename6, dirname as dirname9, join as join13, resolve as resolve4 } from "node:path";
28224
- import { fileURLToPath as fileURLToPath2 } from "node:url";
28576
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
28577
+ import { basename as basename6, dirname as dirname11, join as join14, resolve as resolve6 } from "node:path";
28578
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
28225
28579
  function getPackageRoot() {
28226
- const thisFile = fileURLToPath2(import.meta.url);
28227
- return resolve4(dirname9(thisFile), "..", "..");
28580
+ const thisFile = fileURLToPath3(import.meta.url);
28581
+ return resolve6(dirname11(thisFile), "..", "..");
28228
28582
  }
28229
28583
  function getCleoVersion() {
28230
28584
  try {
28231
- const pkgPath = join13(getPackageRoot(), "package.json");
28232
- const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
28585
+ const pkgPath = join14(getPackageRoot(), "package.json");
28586
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
28233
28587
  return pkg.version ?? "0.0.0";
28234
28588
  } catch {
28235
28589
  return "0.0.0";
@@ -28588,25 +28942,25 @@ var init_recovery = __esm({
28588
28942
  // packages/core/src/store/exodus/archive.ts
28589
28943
  import {
28590
28944
  copyFileSync as copyFileSync2,
28591
- existsSync as existsSync8,
28945
+ existsSync as existsSync9,
28592
28946
  mkdirSync as mkdirSync2,
28593
- readFileSync as readFileSync4,
28947
+ readFileSync as readFileSync5,
28594
28948
  renameSync as renameSync3,
28595
28949
  unlinkSync,
28596
28950
  writeFileSync as writeFileSync4
28597
28951
  } from "node:fs";
28598
- import { basename as basename7, dirname as dirname10, join as join14, resolve as resolve5 } from "node:path";
28952
+ import { basename as basename7, dirname as dirname12, join as join15, resolve as resolve7 } from "node:path";
28599
28953
  import { z as z26 } from "zod";
28600
28954
  function scopeBaseDir(scope, cwd, targetDbPath) {
28601
- if (targetDbPath !== void 0) return dirname10(targetDbPath);
28955
+ if (targetDbPath !== void 0) return dirname12(targetDbPath);
28602
28956
  return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
28603
28957
  }
28604
28958
  function exodusArchiveDir(scope, cwd, targetDbPath) {
28605
- return join14(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
28959
+ return join15(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
28606
28960
  }
28607
28961
  function exodusMarkerPath(scope, cwd, targetDbPath) {
28608
28962
  const marker16 = targetDbPath !== void 0 && basename7(targetDbPath) !== "cleo.db" ? `${basename7(targetDbPath)}.${MARKER_FILENAME_BY_SCOPE[scope]}` : MARKER_FILENAME_BY_SCOPE[scope];
28609
- return join14(scopeBaseDir(scope, cwd, targetDbPath), marker16);
28963
+ return join15(scopeBaseDir(scope, cwd, targetDbPath), marker16);
28610
28964
  }
28611
28965
  function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
28612
28966
  let markerPath;
@@ -28616,13 +28970,13 @@ function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
28616
28970
  if (targetDbPath) throw error48;
28617
28971
  return false;
28618
28972
  }
28619
- if (!existsSync8(markerPath)) return false;
28620
- const marker16 = markerIdentity.parse(JSON.parse(readFileSync4(markerPath, "utf8")));
28973
+ if (!existsSync9(markerPath)) return false;
28974
+ const marker16 = markerIdentity.parse(JSON.parse(readFileSync5(markerPath, "utf8")));
28621
28975
  if (nativeDb && (!marker16.databaseIdentity || !hasExodusDatabaseIdentity(nativeDb, marker16.databaseIdentity)))
28622
28976
  throw new Error(
28623
28977
  "Exodus completion marker does not certify this database generation; assessment required"
28624
28978
  );
28625
- return marker16.scope === scope && (!targetDbPath || !marker16.targetDbPath || resolve5(marker16.targetDbPath) === resolve5(targetDbPath));
28979
+ return marker16.scope === scope && (!targetDbPath || !marker16.targetDbPath || resolve7(marker16.targetDbPath) === resolve7(targetDbPath));
28626
28980
  }
28627
28981
  function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, databaseIdentity) {
28628
28982
  const markerPath = exodusMarkerPath(scope, cwd, targetDbPath);
@@ -28634,7 +28988,7 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
28634
28988
  cleoVersion: getCleoVersion(),
28635
28989
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
28636
28990
  archivedSources: [...archivedSources],
28637
- targetDbPath: resolve5(targetDbPath ?? join14(baseDir, "cleo.db")),
28991
+ targetDbPath: resolve7(targetDbPath ?? join15(baseDir, "cleo.db")),
28638
28992
  ...databaseIdentity ? { databaseIdentity } : {}
28639
28993
  };
28640
28994
  const tmpPath = `${markerPath}.tmp`;
@@ -28645,10 +28999,10 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
28645
28999
  }
28646
29000
  function moveFileInto(srcPath, destDir) {
28647
29001
  mkdirSync2(destDir, { recursive: true });
28648
- let dest = join14(destDir, basename7(srcPath));
28649
- if (existsSync8(dest)) {
29002
+ let dest = join15(destDir, basename7(srcPath));
29003
+ if (existsSync9(dest)) {
28650
29004
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
28651
- dest = join14(destDir, `${basename7(srcPath)}.${stamp}`);
29005
+ dest = join15(destDir, `${basename7(srcPath)}.${stamp}`);
28652
29006
  }
28653
29007
  try {
28654
29008
  renameSync3(srcPath, dest);
@@ -28659,14 +29013,14 @@ function moveFileInto(srcPath, destDir) {
28659
29013
  return dest;
28660
29014
  }
28661
29015
  function archiveSourceDb(source, cwd, targetDbPath) {
28662
- if (!existsSync8(source.path)) {
29016
+ if (!existsSync9(source.path)) {
28663
29017
  return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
28664
29018
  }
28665
29019
  const destDir = exodusArchiveDir(source.targetScope, cwd, targetDbPath);
28666
29020
  const archivedTo = moveFileInto(source.path, destDir);
28667
29021
  for (const suffix of SIDECAR_SUFFIXES) {
28668
29022
  const sidecar = `${source.path}${suffix}`;
28669
- if (existsSync8(sidecar)) {
29023
+ if (existsSync9(sidecar)) {
28670
29024
  try {
28671
29025
  moveFileInto(sidecar, destDir);
28672
29026
  } catch (err) {
@@ -28714,7 +29068,7 @@ function detectStrandedResidue(sources, cwd) {
28714
29068
  const stranded = [];
28715
29069
  for (const source of sources) {
28716
29070
  if (!markedScopes.has(source.targetScope)) continue;
28717
- if (existsSync8(source.path)) {
29071
+ if (existsSync9(source.path)) {
28718
29072
  stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
28719
29073
  }
28720
29074
  }
@@ -28779,7 +29133,7 @@ __export(open_cleo_db_exports, {
28779
29133
  openCleoDbSnapshot: () => openCleoDbSnapshot,
28780
29134
  validateProjectIdConsistency: () => validateProjectIdConsistency
28781
29135
  });
28782
- import { createRequire as createRequire4 } from "node:module";
29136
+ import { createRequire as createRequire5 } from "node:module";
28783
29137
  function unwrapNativeSqliteDb(db) {
28784
29138
  if (db && typeof db === "object" && "$client" in db) {
28785
29139
  return db.$client ?? db;
@@ -28843,9 +29197,10 @@ async function openCleoDb(role, cwd) {
28843
29197
  }
28844
29198
  function openCleoDbSnapshot(path, options = {}) {
28845
29199
  const { readOnly = true, applyPragmas = true } = options;
28846
- const _require7 = createRequire4(import.meta.url);
29200
+ const _require7 = createRequire5(import.meta.url);
28847
29201
  const { DatabaseSync: DatabaseSyncCtor } = _require7("node:sqlite");
28848
29202
  const db = new DatabaseSyncCtor(path, { readOnly });
29203
+ if (!readOnly) installSchemaWriteGuard(db);
28849
29204
  if (applyPragmas) {
28850
29205
  applyPerfPragmas(db, { enableWal: !readOnly });
28851
29206
  }
@@ -28873,6 +29228,7 @@ var init_open_cleo_db = __esm({
28873
29228
  init_project_info();
28874
29229
  init_dual_scope_db();
28875
29230
  init_sqlite_pragmas();
29231
+ init_worktree_build_guard();
28876
29232
  init_worktree_isolation_guard();
28877
29233
  PROJECT_ID_TRACKING_ROLES = /* @__PURE__ */ new Set(["global"]);
28878
29234
  }
@@ -29212,7 +29568,7 @@ var init_table_name_map = __esm({
29212
29568
  });
29213
29569
 
29214
29570
  // packages/core/src/store/exodus/count-parity.ts
29215
- import { existsSync as existsSync9 } from "node:fs";
29571
+ import { existsSync as existsSync10 } from "node:fs";
29216
29572
  function listTables(db) {
29217
29573
  return db.prepare(
29218
29574
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
@@ -29233,14 +29589,14 @@ function rowCount(db, tableName) {
29233
29589
  function computeCountParity(sources, projectDbPath, globalDbPath) {
29234
29590
  const entries = [];
29235
29591
  let skipped = 0;
29236
- if (!existsSync9(projectDbPath) || !existsSync9(globalDbPath)) {
29592
+ if (!existsSync10(projectDbPath) || !existsSync10(globalDbPath)) {
29237
29593
  return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
29238
29594
  }
29239
29595
  const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
29240
29596
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
29241
29597
  try {
29242
29598
  for (const src of sources) {
29243
- if (!existsSync9(src.path)) continue;
29599
+ if (!existsSync10(src.path)) continue;
29244
29600
  const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
29245
29601
  try {
29246
29602
  for (const legacyTable of listTables(srcSnap.db)) {
@@ -29298,8 +29654,8 @@ var init_count_parity = __esm({
29298
29654
  });
29299
29655
 
29300
29656
  // packages/core/src/store/exodus/plan.ts
29301
- import { existsSync as existsSync10, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
29302
- import { join as join15 } from "node:path";
29657
+ import { existsSync as existsSync11, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
29658
+ import { join as join16 } from "node:path";
29303
29659
  function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
29304
29660
  return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
29305
29661
  }
@@ -29310,33 +29666,33 @@ function buildSourceDescriptors(cwd) {
29310
29666
  // Project-tier — go into consolidated project-scope cleo.db
29311
29667
  {
29312
29668
  name: "tasks",
29313
- path: join15(cleoDir, "tasks.db"),
29669
+ path: join16(cleoDir, "tasks.db"),
29314
29670
  targetScope: "project"
29315
29671
  },
29316
29672
  {
29317
29673
  name: "brain (project)",
29318
- path: join15(cleoDir, "brain.db"),
29674
+ path: join16(cleoDir, "brain.db"),
29319
29675
  targetScope: "project"
29320
29676
  },
29321
29677
  {
29322
29678
  name: "conduit",
29323
- path: join15(cleoDir, "conduit.db"),
29679
+ path: join16(cleoDir, "conduit.db"),
29324
29680
  targetScope: "project"
29325
29681
  },
29326
29682
  // Global-tier — go into consolidated global-scope cleo.db
29327
29683
  {
29328
29684
  name: "nexus",
29329
- path: join15(cleoHome, "nexus.db"),
29685
+ path: join16(cleoHome, "nexus.db"),
29330
29686
  targetScope: "global"
29331
29687
  },
29332
29688
  {
29333
29689
  name: "signaldock",
29334
- path: join15(cleoHome, "signaldock.db"),
29690
+ path: join16(cleoHome, "signaldock.db"),
29335
29691
  targetScope: "global"
29336
29692
  },
29337
29693
  {
29338
29694
  name: "skills",
29339
- path: join15(cleoHome, "skills.db"),
29695
+ path: join16(cleoHome, "skills.db"),
29340
29696
  targetScope: "global"
29341
29697
  }
29342
29698
  ];
@@ -29365,7 +29721,7 @@ function findExistingStaging(cleoDir) {
29365
29721
  const entries = readdirSync3(cleoDir, { withFileTypes: true });
29366
29722
  const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
29367
29723
  if (stagingDirs.length > 0) {
29368
- return join15(cleoDir, stagingDirs[0]);
29724
+ return join16(cleoDir, stagingDirs[0]);
29369
29725
  }
29370
29726
  } catch {
29371
29727
  }
@@ -29381,7 +29737,7 @@ function buildExodusPlan(cwd) {
29381
29737
  const availableBytes = getAvailableBytes(cleoDir);
29382
29738
  const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
29383
29739
  const existingStaging = findExistingStaging(cleoDir);
29384
- const stagingDir = existingStaging ?? join15(cleoDir, deriveStagingDirName());
29740
+ const stagingDir = existingStaging ?? join16(cleoDir, deriveStagingDirName());
29385
29741
  const resumeFromStaging = existingStaging !== null;
29386
29742
  const projectDbPath = resolveDualScopeDbPath("project", cwd);
29387
29743
  const globalDbPath = resolveDualScopeDbPath("global");
@@ -29400,7 +29756,7 @@ function buildExodusPlan(cwd) {
29400
29756
  };
29401
29757
  }
29402
29758
  function sourcesPresent(sources) {
29403
- return sources.some((s) => existsSync10(s.path));
29759
+ return sources.some((s) => existsSync11(s.path));
29404
29760
  }
29405
29761
  var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
29406
29762
  var init_plan2 = __esm({
@@ -29414,18 +29770,18 @@ var init_plan2 = __esm({
29414
29770
  });
29415
29771
 
29416
29772
  // packages/core/src/store/exodus/health.ts
29417
- import { existsSync as existsSync11, statSync as statSync4 } from "node:fs";
29773
+ import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
29418
29774
  function buildExodusHealth(cwd) {
29419
29775
  const plan = buildExodusPlan(cwd);
29420
- const anyLegacyPresent = plan.sources.some((s) => existsSync11(s.path));
29776
+ const anyLegacyPresent = plan.sources.some((s) => existsSync12(s.path));
29421
29777
  const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
29422
29778
  const consolidatedExistsByScope = {
29423
- project: existsSync11(plan.projectDbPath),
29424
- global: existsSync11(plan.globalDbPath)
29779
+ project: existsSync12(plan.projectDbPath),
29780
+ global: existsSync12(plan.globalDbPath)
29425
29781
  };
29426
29782
  const buildScope = (scope) => {
29427
29783
  const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
29428
- const present = existsSync11(s.path);
29784
+ const present = existsSync12(s.path);
29429
29785
  let bytes = 0;
29430
29786
  if (present) {
29431
29787
  try {
@@ -29777,8 +30133,8 @@ var init_types = __esm({
29777
30133
  });
29778
30134
 
29779
30135
  // packages/core/src/store/backup-sidecar.ts
29780
- import { existsSync as existsSync12, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
29781
- import { join as join16 } from "node:path";
30136
+ import { existsSync as existsSync13, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
30137
+ import { join as join17 } from "node:path";
29782
30138
  function formatBackupTimestamp(d) {
29783
30139
  const pad = (n, len = 2) => String(n).padStart(len, "0");
29784
30140
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
@@ -29789,8 +30145,8 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29789
30145
  const ownedPattern = new RegExp(`\\.${escapedType}-`);
29790
30146
  const files = readdirSync4(backupDir).filter((f) => !f.endsWith(".meta.json") && !f.endsWith(".tmp") && ownedPattern.test(f)).map((f) => ({
29791
30147
  name: f,
29792
- path: join16(backupDir, f),
29793
- mtimeMs: statSync5(join16(backupDir, f)).mtimeMs
30148
+ path: join17(backupDir, f),
30149
+ mtimeMs: statSync5(join17(backupDir, f)).mtimeMs
29794
30150
  })).sort((a, b) => a.mtimeMs - b.mtimeMs);
29795
30151
  while (files.length > maxSnapshots) {
29796
30152
  const oldest = files.shift();
@@ -29798,7 +30154,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29798
30154
  try {
29799
30155
  unlinkSync2(oldest.path);
29800
30156
  const metaPath = `${oldest.path}.meta.json`;
29801
- if (existsSync12(metaPath)) unlinkSync2(metaPath);
30157
+ if (existsSync13(metaPath)) unlinkSync2(metaPath);
29802
30158
  } catch {
29803
30159
  }
29804
30160
  }
@@ -29806,7 +30162,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29806
30162
  }
29807
30163
  }
29808
30164
  function writeBackupSidecar(backupDir, sidecar) {
29809
- const dest = join16(backupDir, `${sidecar.backupId}.meta.json`);
30165
+ const dest = join17(backupDir, `${sidecar.backupId}.meta.json`);
29810
30166
  const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
29811
30167
  writeFileSync5(tmp, JSON.stringify(sidecar, null, 2));
29812
30168
  renameSync4(tmp, dest);
@@ -29818,23 +30174,23 @@ var init_backup_sidecar = __esm({
29818
30174
  });
29819
30175
 
29820
30176
  // packages/core/src/store/pre-repair-snapshot.ts
29821
- import { existsSync as existsSync13, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
29822
- import { dirname as dirname11, join as join17 } from "node:path";
30177
+ import { existsSync as existsSync14, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
30178
+ import { dirname as dirname13, join as join18 } from "node:path";
29823
30179
  function writePreRepairSnapshot(nativeDb, dbPath, label) {
29824
30180
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
29825
- const backupDir = join17(dirname11(dbPath), "backups");
30181
+ const backupDir = join18(dirname13(dbPath), "backups");
29826
30182
  mkdirSync3(backupDir, { recursive: true });
29827
- const snapshotPath = join17(backupDir, `cleo-pre-${label}-${stamp}.db`);
30183
+ const snapshotPath = join18(backupDir, `cleo-pre-${label}-${stamp}.db`);
29828
30184
  nativeDb.exec(`VACUUM INTO '${snapshotPath.replace(/'/g, "''")}'`);
29829
30185
  return snapshotPath;
29830
30186
  }
29831
30187
  function existingAncestor(path) {
29832
30188
  let p = path;
29833
- while (!existsSync13(p) && dirname11(p) !== p) p = dirname11(p);
30189
+ while (!existsSync14(p) && dirname13(p) !== p) p = dirname13(p);
29834
30190
  return p;
29835
30191
  }
29836
30192
  function planMigrationSnapshot(nativeDb, dbPath) {
29837
- const backupDir = join17(dirname11(dbPath), "backups", "sqlite");
30193
+ const backupDir = join18(dirname13(dbPath), "backups", "sqlite");
29838
30194
  const pragma = (name15) => Number(nativeDb.prepare(`PRAGMA main.${name15}`).get()[name15] ?? 0);
29839
30195
  const liveBytes = (pragma("page_count") - pragma("freelist_count")) * pragma("page_size");
29840
30196
  let availableBytes = null;
@@ -29846,13 +30202,13 @@ function planMigrationSnapshot(nativeDb, dbPath) {
29846
30202
  }
29847
30203
  const base = `migration-${formatBackupTimestamp(/* @__PURE__ */ new Date())}`;
29848
30204
  let backupId = base;
29849
- for (let n = 2; existsSync13(join17(backupDir, `${backupId}.meta.json`)); n++) {
30205
+ for (let n = 2; existsSync14(join18(backupDir, `${backupId}.meta.json`)); n++) {
29850
30206
  backupId = `${base}-${n}`;
29851
30207
  }
29852
30208
  return {
29853
30209
  backupDir,
29854
30210
  backupId,
29855
- snapshotPath: join17(backupDir, `cleo.db.${backupId}`),
30211
+ snapshotPath: join18(backupDir, `cleo.db.${backupId}`),
29856
30212
  requiredBytes: liveBytes + SNAPSHOT_HEADROOM_BYTES,
29857
30213
  availableBytes
29858
30214
  };
@@ -30092,7 +30448,7 @@ var init_legacy_tasks_lineage = __esm({
30092
30448
 
30093
30449
  // packages/core/src/store/ports/domain-binding.ts
30094
30450
  import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
30095
- import { resolve as resolve6 } from "node:path";
30451
+ import { resolve as resolve8 } from "node:path";
30096
30452
  function getCleoRuntime() {
30097
30453
  if (!_runtime) {
30098
30454
  _runtime = createCleoRuntime();
@@ -30160,6 +30516,8 @@ async function bindAgainst(key, store, establish) {
30160
30516
  () => establish(native, store)
30161
30517
  );
30162
30518
  return { store, native, db };
30519
+ } catch (error48) {
30520
+ throw explainSchemaWriteDenial(native, error48);
30163
30521
  } finally {
30164
30522
  membership.active = false;
30165
30523
  }
@@ -30209,7 +30567,7 @@ async function bindLive(scope, key, dbPath, openStore, establish) {
30209
30567
  );
30210
30568
  }
30211
30569
  async function bindProjectDomain(domain2, cwd, establish) {
30212
- const dbPath = resolve6(resolveDualScopeDbPath("project", cwd));
30570
+ const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
30213
30571
  const row = await bindLive(
30214
30572
  "project",
30215
30573
  bindingKey("project", dbPath, domain2),
@@ -30220,7 +30578,7 @@ async function bindProjectDomain(domain2, cwd, establish) {
30220
30578
  return row;
30221
30579
  }
30222
30580
  async function bindGlobalDomain(domain2, establish, cwd) {
30223
- const dbPath = resolve6(resolveDualScopeDbPath("global"));
30581
+ const dbPath = resolve8(resolveDualScopeDbPath("global"));
30224
30582
  const row = await bindLive(
30225
30583
  "global",
30226
30584
  bindingKey("global", dbPath, domain2),
@@ -30231,7 +30589,7 @@ async function bindGlobalDomain(domain2, establish, cwd) {
30231
30589
  return row;
30232
30590
  }
30233
30591
  async function bindGlobalDomainAtPath(domain2, dbPath, establish) {
30234
- const normalized = resolve6(dbPath);
30592
+ const normalized = resolve8(dbPath);
30235
30593
  const row = await bindLive(
30236
30594
  "global",
30237
30595
  bindingKey("global", normalized, domain2),
@@ -30242,7 +30600,7 @@ async function bindGlobalDomainAtPath(domain2, dbPath, establish) {
30242
30600
  return row;
30243
30601
  }
30244
30602
  function peekDomainAtPath(scope, dbPath, domain2) {
30245
- const row = _bindings.get(bindingKey(scope, resolve6(dbPath), domain2));
30603
+ const row = _bindings.get(bindingKey(scope, resolve8(dbPath), domain2));
30246
30604
  if (!row?.native.isOpen) return null;
30247
30605
  return row;
30248
30606
  }
@@ -30251,12 +30609,12 @@ function releaseDomainBindings(filter2) {
30251
30609
  _bindings.clear();
30252
30610
  return;
30253
30611
  }
30254
- const wantPath = filter2.dbPath === void 0 ? void 0 : resolve6(filter2.dbPath);
30612
+ const wantPath = filter2.dbPath === void 0 ? void 0 : resolve8(filter2.dbPath);
30255
30613
  for (const key of [..._bindings.keys()]) {
30256
- const sep5 = key.indexOf("::");
30614
+ const sep6 = key.indexOf("::");
30257
30615
  const lastSep = key.lastIndexOf("::");
30258
- const scope = key.slice(0, sep5);
30259
- const dbPath = key.slice(sep5 + 2, lastSep);
30616
+ const scope = key.slice(0, sep6);
30617
+ const dbPath = key.slice(sep6 + 2, lastSep);
30260
30618
  const domain2 = key.slice(lastSep + 2);
30261
30619
  if (filter2.scope !== void 0 && scope !== filter2.scope) continue;
30262
30620
  if (wantPath !== void 0 && dbPath !== wantPath) continue;
@@ -30271,7 +30629,7 @@ function boundProjectNative(domain2, cwd) {
30271
30629
  return peekProjectDomain(domain2, cwd)?.native ?? null;
30272
30630
  }
30273
30631
  function peekProjectDomain(domain2, cwd) {
30274
- const dbPath = resolve6(resolveDualScopeDbPath("project", cwd));
30632
+ const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
30275
30633
  const row = _bindings.get(bindingKey("project", dbPath, domain2));
30276
30634
  if (row?.native.isOpen) return row;
30277
30635
  if (cwd !== void 0) return null;
@@ -30286,7 +30644,7 @@ function peekProjectDomain(domain2, cwd) {
30286
30644
  return sole ?? null;
30287
30645
  }
30288
30646
  function peekGlobalDomain(domain2) {
30289
- const dbPath = resolve6(resolveDualScopeDbPath("global"));
30647
+ const dbPath = resolve8(resolveDualScopeDbPath("global"));
30290
30648
  const row = _bindings.get(bindingKey("global", dbPath, domain2));
30291
30649
  if (!row || !row.native.isOpen) return null;
30292
30650
  return row;
@@ -30297,6 +30655,7 @@ var init_domain_binding = __esm({
30297
30655
  "use strict";
30298
30656
  init_project_scope();
30299
30657
  init_dual_scope_db();
30658
+ init_worktree_build_guard();
30300
30659
  _runtime = null;
30301
30660
  _bindings = /* @__PURE__ */ new Map();
30302
30661
  _inflight = /* @__PURE__ */ new Map();
@@ -30307,9 +30666,9 @@ var init_domain_binding = __esm({
30307
30666
 
30308
30667
  // packages/core/src/telemetry/sqlite.ts
30309
30668
  import { mkdirSync as mkdirSync4 } from "node:fs";
30310
- import { dirname as dirname12, join as join18 } from "node:path";
30669
+ import { dirname as dirname14, join as join19 } from "node:path";
30311
30670
  function getTelemetryDbPath() {
30312
- return join18(getCleoHome(), DB_FILENAME);
30671
+ return join19(getCleoHome(), DB_FILENAME);
30313
30672
  }
30314
30673
  function resolveTelemetryMigrationsFolder() {
30315
30674
  return resolveCorePackageMigrationsFolder("drizzle-telemetry");
@@ -30357,8 +30716,9 @@ async function getTelemetryDb() {
30357
30716
  _initPromise = (async () => {
30358
30717
  const dbPath = requestedPath;
30359
30718
  _dbPath = dbPath;
30360
- mkdirSync4(dirname12(dbPath), { recursive: true });
30719
+ mkdirSync4(dirname14(dbPath), { recursive: true });
30361
30720
  const nativeDb = openNativeDatabase(dbPath);
30721
+ installSchemaWriteGuard(nativeDb);
30362
30722
  _nativeDb = nativeDb;
30363
30723
  const db = drizzle({ client: nativeDb });
30364
30724
  runTelemetryMigrations(nativeDb, db);
@@ -30379,6 +30739,7 @@ var init_sqlite2 = __esm({
30379
30739
  init_migration_manager();
30380
30740
  init_resolve_migrations_folder();
30381
30741
  init_sqlite3();
30742
+ init_worktree_build_guard();
30382
30743
  DB_FILENAME = "telemetry.db";
30383
30744
  TELEMETRY_SCHEMA_VERSION = "1.0.0";
30384
30745
  _db = null;
@@ -30389,11 +30750,11 @@ var init_sqlite2 = __esm({
30389
30750
  });
30390
30751
 
30391
30752
  // packages/core/src/store/agent-registry-store.ts
30392
- import { existsSync as existsSync14 } from "node:fs";
30393
- import { join as join19 } from "node:path";
30753
+ import { existsSync as existsSync15 } from "node:fs";
30754
+ import { join as join20 } from "node:path";
30394
30755
  function getGlobalAgentRegistryDbPath() {
30395
30756
  const cleoHome = getCleoHome();
30396
- const dbPath = join19(cleoHome, "cleo.db");
30757
+ const dbPath = join20(cleoHome, "cleo.db");
30397
30758
  if (!dbPath.startsWith(cleoHome)) {
30398
30759
  throw new Error(
30399
30760
  `BUG: getGlobalAgentRegistryDbPath() resolved to "${dbPath}" which is NOT under getCleoHome() ("${cleoHome}"). The Agent Registry is global-only per ADR-037. This indicates a code path that bypasses path resolution \u2014 fix the caller, do not suppress this error.`
@@ -30460,7 +30821,7 @@ function establishAgentRegistrySchema(native) {
30460
30821
  }
30461
30822
  async function ensureGlobalAgentRegistryDb() {
30462
30823
  const dbPath = getGlobalAgentRegistryDbPath();
30463
- const alreadyExists = existsSync14(dbPath);
30824
+ const alreadyExists = existsSync15(dbPath);
30464
30825
  let created = false;
30465
30826
  const { native: nativeDb } = await bindGlobalDomainAtPath(
30466
30827
  AGENT_REGISTRY_DOMAIN,
@@ -30505,8 +30866,8 @@ var init_agent_registry_store = __esm({
30505
30866
  });
30506
30867
 
30507
30868
  // packages/core/src/store/conduit-sqlite.ts
30508
- import { existsSync as existsSync15 } from "node:fs";
30509
- import { createRequire as createRequire5 } from "node:module";
30869
+ import { existsSync as existsSync16 } from "node:fs";
30870
+ import { createRequire as createRequire6 } from "node:module";
30510
30871
  function _getDrizzle() {
30511
30872
  if (_drizzle === null) {
30512
30873
  const mod = _require3("drizzle-orm/node-sqlite");
@@ -30534,7 +30895,7 @@ function runConduitMigrations(nativeDb) {
30534
30895
  }
30535
30896
  async function ensureConduitDb(projectRoot) {
30536
30897
  const dbPath = getConduitDbPath(projectRoot);
30537
- const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync15(dbPath);
30898
+ const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync16(dbPath);
30538
30899
  await bindConduitDomain(projectRoot);
30539
30900
  return { action: alreadyExists ? "exists" : "created", path: dbPath };
30540
30901
  }
@@ -30560,7 +30921,8 @@ var init_conduit_sqlite = __esm({
30560
30921
  init_domain_binding();
30561
30922
  init_resolve_migrations_folder();
30562
30923
  init_sqlite_pragmas();
30563
- _require3 = createRequire5(import.meta.url);
30924
+ init_worktree_build_guard();
30925
+ _require3 = createRequire6(import.meta.url);
30564
30926
  ({ DatabaseSync: DatabaseSync2 } = _require3("node:sqlite"));
30565
30927
  _drizzle = null;
30566
30928
  CONDUIT_SCHEMA_VERSION = "2026.4.23";
@@ -32434,216 +32796,6 @@ var init_memory_schema = __esm({
32434
32796
  }
32435
32797
  });
32436
32798
 
32437
- // packages/core/src/store/snapshot-gate.ts
32438
- import { join as join20 } from "node:path";
32439
- function readGateState(db) {
32440
- const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
32441
- const state = { generation: 0, prefixes: {} };
32442
- if (!row) return state;
32443
- try {
32444
- const parsed = JSON.parse(row.value);
32445
- if (parsed === null || typeof parsed !== "object") return state;
32446
- if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
32447
- state.generation = parsed.generation;
32448
- }
32449
- for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
32450
- if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
32451
- state.prefixes[prefix] = {
32452
- generation: e.generation,
32453
- startedAt: e.startedAt,
32454
- completedAt: e.completedAt
32455
- };
32456
- }
32457
- }
32458
- } catch {
32459
- }
32460
- return state;
32461
- }
32462
- function writeGateState(db, state) {
32463
- db.prepare(
32464
- "INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
32465
- ).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
32466
- }
32467
- function tryReadGateState(db) {
32468
- if (!db) return null;
32469
- try {
32470
- return readGateState(db);
32471
- } catch {
32472
- return null;
32473
- }
32474
- }
32475
- function needsSnapshot(entry, mode, nowMs, seenGeneration) {
32476
- if (!entry) return true;
32477
- if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
32478
- const elapsed = nowMs - entry.startedAt;
32479
- return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
32480
- }
32481
- async function runGatedSnapshot(opts, snapshot) {
32482
- const now = opts.now ?? Date.now;
32483
- const mode = opts.mode ?? "routine";
32484
- const db = opts.stateDb;
32485
- const none = (skipped, error48) => ({
32486
- snapshotted: [],
32487
- linked: [],
32488
- absent: [],
32489
- failed: [],
32490
- skipped,
32491
- ...error48 !== void 0 && { error: error48 }
32492
- });
32493
- const entryState = tryReadGateState(db);
32494
- const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
32495
- if (mode === "routine") {
32496
- if (!entryState) return none("state-unavailable");
32497
- const nowMs = now();
32498
- if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
32499
- return none("debounced");
32500
- }
32501
- }
32502
- const lockPath2 = join20(opts.backupDir, GATE_LOCK_BASENAME);
32503
- let release;
32504
- try {
32505
- release = await acquireLock(lockPath2, {
32506
- retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
32507
- stale: SNAPSHOT_LOCK_STALE_MS,
32508
- // A compromised lock (e.g. the backup dir was removed) must not throw
32509
- // from a timer and crash the host process.
32510
- onCompromised: () => {
32511
- }
32512
- });
32513
- } catch {
32514
- if (mode === "routine") return none("in-flight");
32515
- return none(
32516
- "lock-timeout",
32517
- `Snapshot lock ${lockPath2}.lock is still held after waiting. Another snapshot is running, or a crashed process left the lock (it expires after ${SNAPSHOT_LOCK_STALE_MS / 6e4} minutes). Remove it if no snapshot is running.`
32518
- );
32519
- }
32520
- try {
32521
- try {
32522
- opts.onLockAcquired?.();
32523
- } catch {
32524
- }
32525
- const state = tryReadGateState(db);
32526
- if (!state && mode === "routine") return none("state-unavailable");
32527
- const startMs = now();
32528
- const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
32529
- (p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
32530
- );
32531
- if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
32532
- const generation = (state?.generation ?? 0) + 1;
32533
- let claimed = false;
32534
- if (db && state) {
32535
- try {
32536
- writeGateState(db, { ...state, generation });
32537
- claimed = true;
32538
- } catch {
32539
- }
32540
- }
32541
- const snapshotted = [];
32542
- const linked = [];
32543
- const absent = [];
32544
- const failed = [];
32545
- for (const prefix of admitted) {
32546
- try {
32547
- const outcome = await snapshot(prefix);
32548
- if (outcome === "absent") absent.push(prefix);
32549
- else {
32550
- snapshotted.push(prefix);
32551
- if (outcome === "linked") linked.push(prefix);
32552
- }
32553
- } catch {
32554
- failed.push(prefix);
32555
- }
32556
- }
32557
- const satisfied = [...snapshotted, ...absent];
32558
- if (db && claimed && satisfied.length > 0) {
32559
- try {
32560
- const latest = readGateState(db);
32561
- const completedAt = now();
32562
- latest.generation = Math.max(latest.generation, generation);
32563
- for (const p of satisfied) {
32564
- latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
32565
- }
32566
- writeGateState(db, latest);
32567
- } catch {
32568
- }
32569
- }
32570
- return { snapshotted, linked, absent, failed, skipped: null };
32571
- } finally {
32572
- await release().catch(() => {
32573
- });
32574
- }
32575
- }
32576
- function isValidStamp(ymd, hms) {
32577
- const y = Number(ymd.slice(0, 4));
32578
- const mo = Number(ymd.slice(4, 6));
32579
- const d = Number(ymd.slice(6, 8));
32580
- const h = Number(hms.slice(0, 2));
32581
- const mi = Number(hms.slice(2, 4));
32582
- const se = Number(hms.slice(4, 6));
32583
- if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
32584
- const probe = new Date(Date.UTC(y, mo - 1, d));
32585
- return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
32586
- }
32587
- function selectSnapshotsToKeep(names, ctx = {}) {
32588
- const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
32589
- const keep = /* @__PURE__ */ new Set();
32590
- const stamped = [];
32591
- for (const name15 of names) {
32592
- const m = STAMP_PATTERN.exec(name15);
32593
- const ymd = m?.[1];
32594
- const hms = m?.[2];
32595
- if (!ymd || !hms || !isValidStamp(ymd, hms)) {
32596
- keep.add(name15);
32597
- continue;
32598
- }
32599
- const stamp = `${ymd}-${hms}`;
32600
- if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
32601
- keep.add(name15);
32602
- continue;
32603
- }
32604
- stamped.push({ name: name15, stamp });
32605
- }
32606
- if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
32607
- stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
32608
- for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
32609
- const keepNewestPerBucket = (bucketOf, slots) => {
32610
- const seen = /* @__PURE__ */ new Set();
32611
- for (const s of stamped) {
32612
- const bucket = bucketOf(s.stamp);
32613
- if (seen.has(bucket)) continue;
32614
- if (seen.size >= slots) break;
32615
- seen.add(bucket);
32616
- keep.add(s.name);
32617
- }
32618
- };
32619
- keepNewestPerBucket(
32620
- (stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
32621
- policy.quarterHourly
32622
- );
32623
- keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
32624
- keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
32625
- return keep;
32626
- }
32627
- var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
32628
- var init_snapshot_gate = __esm({
32629
- "packages/core/src/store/snapshot-gate.ts"() {
32630
- "use strict";
32631
- init_lock();
32632
- SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
32633
- SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
32634
- SNAPSHOT_LOCK_WAIT_RETRIES = 90;
32635
- SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
32636
- GATE_LOCK_BASENAME = ".snapshot-gate";
32637
- DEFAULT_SNAPSHOT_RETENTION = {
32638
- latest: 1,
32639
- quarterHourly: 3,
32640
- hourly: 3,
32641
- daily: 3
32642
- };
32643
- STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
32644
- }
32645
- });
32646
-
32647
32799
  // packages/core/src/store/twin-collapse.ts
32648
32800
  import { createHash as createHash3 } from "node:crypto";
32649
32801
  function hasMainTable(db, name15) {
@@ -32720,6 +32872,22 @@ function mergeSchemaMetaValue(key, bare, twin) {
32720
32872
  const field = SCHEMA_META_COUNTER_FIELDS[key];
32721
32873
  return field === void 0 ? bare : withMaxCounter(bare, twin, field);
32722
32874
  }
32875
+ function mirrorCounterToBare(db, key) {
32876
+ if (SCHEMA_META_COUNTER_FIELDS[key] === void 0) return;
32877
+ if (!hasMainTable(db, "schema_meta")) return;
32878
+ const twin = readKv(db, "tasks_schema_meta", key);
32879
+ if (twin === void 0) return;
32880
+ const bare = readKv(db, "schema_meta", key);
32881
+ const next = bare === void 0 ? twin : mergeSchemaMetaValue(key, bare, twin);
32882
+ if (next === null || next === bare) return;
32883
+ writeKv(db, "schema_meta", key, next);
32884
+ }
32885
+ function bareCounterOf(db, key) {
32886
+ const name15 = SCHEMA_META_COUNTER_FIELDS[key];
32887
+ if (name15 === void 0 || !hasMainTable(db, "schema_meta")) return 0;
32888
+ const bare = readKv(db, "schema_meta", key);
32889
+ return (bare === void 0 ? void 0 : counterOf(bare, name15)) ?? 0;
32890
+ }
32723
32891
  function kvRows(db, table, schema = "main") {
32724
32892
  const rows = db.prepare(`SELECT key, value FROM ${schema}.${table}`).all();
32725
32893
  return new Map(rows.map((r) => [r.key, r.value]));
@@ -32852,6 +33020,39 @@ function applyStickyRows(db, schema, plan) {
32852
33020
  }
32853
33021
  return { inserted, replaced: 0, deleted };
32854
33022
  }
33023
+ function tagsOf(tagsJson) {
33024
+ if (!tagsJson) return [];
33025
+ try {
33026
+ const parsed = JSON.parse(tagsJson);
33027
+ if (!Array.isArray(parsed)) return [];
33028
+ return [...new Set(parsed.filter((t) => typeof t === "string" && t.length > 0))];
33029
+ } catch {
33030
+ return [];
33031
+ }
33032
+ }
33033
+ function syncStickyJunction(db, schema) {
33034
+ const notes = db.prepare("SELECT id, tags_json FROM main.brain_sticky_notes").all();
33035
+ const have = /* @__PURE__ */ new Map();
33036
+ for (const r of db.prepare(`SELECT sticky_id, tag FROM ${schema}.brain_sticky_tags`).all()) {
33037
+ const set2 = have.get(r.sticky_id) ?? /* @__PURE__ */ new Set();
33038
+ set2.add(r.tag);
33039
+ have.set(r.sticky_id, set2);
33040
+ }
33041
+ const insert = db.prepare(
33042
+ `INSERT OR IGNORE INTO ${schema}.brain_sticky_tags (sticky_id, tag) VALUES (?, ?)`
33043
+ );
33044
+ const del = db.prepare(`DELETE FROM ${schema}.brain_sticky_tags WHERE sticky_id = ? AND tag = ?`);
33045
+ let inserted = 0;
33046
+ let deleted = 0;
33047
+ for (const note of notes) {
33048
+ const want = new Set(tagsOf(note.tags_json));
33049
+ const current = have.get(note.id) ?? /* @__PURE__ */ new Set();
33050
+ for (const tag of want)
33051
+ if (!current.has(tag)) inserted += Number(insert.run(note.id, tag).changes);
33052
+ for (const tag of current) if (!want.has(tag)) deleted += Number(del.run(note.id, tag).changes);
33053
+ }
33054
+ return { inserted, deleted };
33055
+ }
32855
33056
  function twinCollapseFailureOf(db) {
32856
33057
  return degraded.get(db);
32857
33058
  }
@@ -33061,7 +33262,7 @@ function collapseTwinTables(nativeDb, dbPath, options = {}) {
33061
33262
  }
33062
33263
  return inOrder();
33063
33264
  }
33064
- var log6, TWIN_COLLAPSE_MARKER_PREFIX, TWIN_COLLAPSE_FAILURE_PREFIX, SCHEMA_META_COUNTER_FIELDS, SCHEMA_META_NEVER_DELETED, MAX_CONFLICTS, sha, ABSENT, hashMap, emptyPlan, SCHEMA_META, hashSets, EMPTY_SET, STICKY_TAGS, PAIRS, degraded, SHADOW_WRITE_REFUSED, SHADOW_WRITE_OPS;
33265
+ var log6, TWIN_COLLAPSE_MARKER_PREFIX, TWIN_COLLAPSE_FAILURE_PREFIX, SNAPSHOT_GATE_KEY, SCHEMA_META_COUNTER_FIELDS, SCHEMA_META_NEVER_DELETED, MAX_CONFLICTS, sha, ABSENT, hashMap, emptyPlan, SCHEMA_META, hashSets, EMPTY_SET, STICKY_TAGS, PAIRS, degraded, SHADOW_WRITE_REFUSED, SHADOW_WRITE_OPS;
33065
33266
  var init_twin_collapse = __esm({
33066
33267
  "packages/core/src/store/twin-collapse.ts"() {
33067
33268
  "use strict";
@@ -33069,18 +33270,18 @@ var init_twin_collapse = __esm({
33069
33270
  init_errors2();
33070
33271
  init_logger2();
33071
33272
  init_pre_repair_snapshot();
33072
- init_snapshot_gate();
33073
33273
  log6 = getLogger("twin-collapse");
33074
33274
  TWIN_COLLAPSE_MARKER_PREFIX = "twin_collapse:";
33075
33275
  TWIN_COLLAPSE_FAILURE_PREFIX = "twin_collapse_failed:";
33276
+ SNAPSHOT_GATE_KEY = "sqlite_snapshot_gate";
33076
33277
  SCHEMA_META_COUNTER_FIELDS = {
33077
33278
  task_id_sequence: "counter",
33078
- [SNAPSHOT_GATE_META_KEY]: "generation",
33279
+ [SNAPSHOT_GATE_KEY]: "generation",
33079
33280
  file_meta: "generation"
33080
33281
  };
33081
33282
  SCHEMA_META_NEVER_DELETED = /* @__PURE__ */ new Set([
33082
33283
  "task_id_sequence",
33083
- SNAPSHOT_GATE_META_KEY
33284
+ SNAPSHOT_GATE_KEY
33084
33285
  ]);
33085
33286
  MAX_CONFLICTS = 50;
33086
33287
  sha = (value) => createHash3("sha256").update(value).digest("hex");
@@ -33145,7 +33346,12 @@ var init_twin_collapse = __esm({
33145
33346
  throw new Error(
33146
33347
  `sticky_tags collapse did not verify: ${missing} missing, ${lingering} not removed`
33147
33348
  );
33148
- return counts;
33349
+ const synced = syncStickyJunction(db, "main");
33350
+ return {
33351
+ inserted: counts.inserted + synced.inserted,
33352
+ replaced: 0,
33353
+ deleted: counts.deleted + synced.deleted
33354
+ };
33149
33355
  },
33150
33356
  shadow(db, plan) {
33151
33357
  db.exec(
@@ -33156,6 +33362,7 @@ var init_twin_collapse = __esm({
33156
33362
  "INSERT INTO temp.brain_sticky_tags (sticky_id, tag) SELECT sticky_id, tag FROM main.brain_sticky_tags"
33157
33363
  );
33158
33364
  applyStickyRows(db, "temp", plan);
33365
+ syncStickyJunction(db, "temp");
33159
33366
  }
33160
33367
  };
33161
33368
  PAIRS = [SCHEMA_META, STICKY_TAGS];
@@ -33187,7 +33394,7 @@ __export(config_exports, {
33187
33394
  parseConfigValue: () => parseConfigValue,
33188
33395
  setConfigValue: () => setConfigValue
33189
33396
  });
33190
- import { existsSync as existsSync16 } from "node:fs";
33397
+ import { existsSync as existsSync17 } from "node:fs";
33191
33398
  function getNestedValue(obj, path) {
33192
33399
  const parts = path.split(".");
33193
33400
  let current = obj;
@@ -33309,7 +33516,7 @@ function parseConfigValue(value) {
33309
33516
  }
33310
33517
  async function setConfigValue(key, value, cwd, opts) {
33311
33518
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
33312
- if (!existsSync16(configPath)) {
33519
+ if (!existsSync17(configPath)) {
33313
33520
  await atomicWriteJson(configPath, {});
33314
33521
  }
33315
33522
  const config2 = await readJson(configPath) ?? {};
@@ -33321,7 +33528,7 @@ async function setConfigValue(key, value, cwd, opts) {
33321
33528
  async function applyStrictnessPreset(preset, cwd, opts) {
33322
33529
  const definition = STRICTNESS_PRESETS[preset];
33323
33530
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
33324
- if (!existsSync16(configPath)) {
33531
+ if (!existsSync17(configPath)) {
33325
33532
  await atomicWriteJson(configPath, {});
33326
33533
  }
33327
33534
  const config2 = await readJson(configPath) ?? {};
@@ -33898,6 +34105,7 @@ var init_cross_db_cleanup = __esm({
33898
34105
  "use strict";
33899
34106
  init_memory_sqlite();
33900
34107
  init_memory_schema();
34108
+ init_worktree_build_guard();
33901
34109
  }
33902
34110
  });
33903
34111
 
@@ -38590,7 +38798,7 @@ __export(sqlite_data_accessor_exports, {
38590
38798
  setMetaValue: () => setMetaValue
38591
38799
  });
38592
38800
  import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
38593
- import { resolve as resolve7 } from "node:path";
38801
+ import { resolve as resolve9 } from "node:path";
38594
38802
  import {
38595
38803
  and as and5,
38596
38804
  eq as eq6,
@@ -38630,9 +38838,12 @@ async function writeMetaValue(cwd, key, value) {
38630
38838
  target: tasksSchemaMeta.key,
38631
38839
  set: { value: json2 }
38632
38840
  }).run();
38841
+ const native = getNativeTasksDb(cwd);
38842
+ if (native) mirrorCounterToBare(native, key);
38633
38843
  }
38634
38844
  function advanceTaskIdSequence(nativeDb, floor) {
38635
38845
  assertTwinCollapseWritable(nativeDb);
38846
+ const lowest = Math.max(floor, bareCounterOf(nativeDb, "task_id_sequence"));
38636
38847
  nativeDb.prepare(`
38637
38848
  UPDATE tasks_schema_meta
38638
38849
  SET value = json_set(value,
@@ -38641,7 +38852,8 @@ function advanceTaskIdSequence(nativeDb, floor) {
38641
38852
  '$.checksum', 'alloc-' || strftime('%s','now')
38642
38853
  )
38643
38854
  WHERE key = 'task_id_sequence'
38644
- `).run(floor, floor);
38855
+ `).run(lowest, lowest);
38856
+ mirrorCounterToBare(nativeDb, "task_id_sequence");
38645
38857
  const row = nativeDb.prepare(`
38646
38858
  SELECT json_extract(value, '$.counter') AS counter
38647
38859
  FROM tasks_schema_meta WHERE key = 'task_id_sequence'
@@ -38695,7 +38907,7 @@ function bindTaskAccessorScope(accessor, scope) {
38695
38907
  }
38696
38908
  async function createSqliteDataAccessor(cwd) {
38697
38909
  const scope = captureProjectScope(
38698
- resolve7(cwd ?? getProjectRoot()),
38910
+ resolve9(cwd ?? getProjectRoot()),
38699
38911
  worktreeScope.getStore()
38700
38912
  );
38701
38913
  return worktreeScope.run(
@@ -38810,7 +39022,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38810
39022
  actor: entry.actor ?? "system",
38811
39023
  detailsJson: entry.details ? JSON.stringify(entry.details) : "{}",
38812
39024
  beforeJson: entry.before ? JSON.stringify(entry.before) : null,
38813
- afterJson: entry.after ? JSON.stringify(entry.after) : null
39025
+ afterJson: entry.after ? JSON.stringify(entry.after) : null,
39026
+ // T12693: the session a ranking change ran in.
39027
+ sessionId: typeof entry.sessionId === "string" ? entry.sessionId : null
38814
39028
  }).run()
38815
39029
  );
38816
39030
  });
@@ -38818,6 +39032,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38818
39032
  async queryAuditLog(query) {
38819
39033
  const db = await getDb(cwd);
38820
39034
  const conditions = [];
39035
+ if (query.ids && query.ids.length > 0) {
39036
+ conditions.push(inArray4(tasksAuditLog.id, [...query.ids]));
39037
+ }
38821
39038
  if (query.taskIds && query.taskIds.length > 0) {
38822
39039
  conditions.push(inArray4(tasksAuditLog.taskId, [...query.taskIds]));
38823
39040
  }
@@ -38836,7 +39053,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38836
39053
  actor: tasksAuditLog.actor,
38837
39054
  detailsJson: tasksAuditLog.detailsJson,
38838
39055
  beforeJson: tasksAuditLog.beforeJson,
38839
- afterJson: tasksAuditLog.afterJson
39056
+ afterJson: tasksAuditLog.afterJson,
39057
+ sessionId: tasksAuditLog.sessionId
38840
39058
  }).from(tasksAuditLog).where(conditions.length > 0 ? and5(...conditions) : void 0).orderBy(sql26`${tasksAuditLog.timestamp} DESC`).limit(limit).all();
38841
39059
  return rows.map((row) => ({
38842
39060
  id: row.id,
@@ -38846,7 +39064,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38846
39064
  actor: row.actor,
38847
39065
  detailsJson: row.detailsJson ?? null,
38848
39066
  beforeJson: row.beforeJson ?? null,
38849
- afterJson: row.afterJson ?? null
39067
+ afterJson: row.afterJson ?? null,
39068
+ sessionId: row.sessionId ?? null
38850
39069
  }));
38851
39070
  },
38852
39071
  // ---- Fine-grained task operations (T5034) ----
@@ -39684,7 +39903,7 @@ var init_sqlite_data_accessor = __esm({
39684
39903
  });
39685
39904
 
39686
39905
  // packages/core/src/sequence/index.ts
39687
- import { existsSync as existsSync17, readFileSync as readFileSync5, renameSync as renameSync5 } from "node:fs";
39906
+ import { existsSync as existsSync18, readFileSync as readFileSync6, renameSync as renameSync5 } from "node:fs";
39688
39907
  import { join as join21 } from "node:path";
39689
39908
  function getLegacySequenceJsonPath(cwd) {
39690
39909
  return join21(resolveOrCwd(cwd), ".cleo", ".sequence.json");
@@ -39701,19 +39920,19 @@ function isSeedSequence(value) {
39701
39920
  return value.counter === 0 && value.lastId === "T000" && value.checksum === "seed";
39702
39921
  }
39703
39922
  function readLegacySequenceFile(path) {
39704
- if (!existsSync17(path)) return null;
39923
+ if (!existsSync18(path)) return null;
39705
39924
  try {
39706
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
39925
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
39707
39926
  return isValidSequenceState(parsed) ? parsed : null;
39708
39927
  } catch {
39709
39928
  return null;
39710
39929
  }
39711
39930
  }
39712
39931
  function renameLegacyFile(path) {
39713
- if (!existsSync17(path)) return;
39932
+ if (!existsSync18(path)) return;
39714
39933
  const migratedPath = `${path}.migrated`;
39715
39934
  try {
39716
- if (!existsSync17(migratedPath)) {
39935
+ if (!existsSync18(migratedPath)) {
39717
39936
  renameSync5(path, migratedPath);
39718
39937
  return;
39719
39938
  }
@@ -39879,12 +40098,12 @@ var init_checkpoint_git_dir = __esm({
39879
40098
 
39880
40099
  // packages/core/src/store/git-checkpoint.ts
39881
40100
  import { execFile as execFile2 } from "node:child_process";
39882
- import { existsSync as existsSync18 } from "node:fs";
40101
+ import { existsSync as existsSync19 } from "node:fs";
39883
40102
  import { readFile as readFile4, writeFile } from "node:fs/promises";
39884
- import { join as join23, resolve as resolve8 } from "node:path";
40103
+ import { join as join23, resolve as resolve10 } from "node:path";
39885
40104
  import { promisify as promisify2 } from "node:util";
39886
40105
  function makeCleoGitEnv(cleoDir) {
39887
- const abs = resolve8(cleoDir);
40106
+ const abs = resolve10(cleoDir);
39888
40107
  return {
39889
40108
  ...process.env,
39890
40109
  GIT_DIR: checkpointGitDir(abs),
@@ -39894,7 +40113,7 @@ function makeCleoGitEnv(cleoDir) {
39894
40113
  async function cleoGitCommand(args, cleoDir) {
39895
40114
  try {
39896
40115
  const result = await execFileAsync2("git", args, {
39897
- cwd: resolve8(cleoDir),
40116
+ cwd: resolve10(cleoDir),
39898
40117
  // absolute cwd so relative paths in args resolve correctly
39899
40118
  env: makeCleoGitEnv(cleoDir),
39900
40119
  timeout: 1e4
@@ -39905,7 +40124,7 @@ async function cleoGitCommand(args, cleoDir) {
39905
40124
  }
39906
40125
  }
39907
40126
  function isCleoGitInitialized(cleoDir) {
39908
- return existsSync18(join23(checkpointGitDir(cleoDir), "HEAD"));
40127
+ return existsSync19(join23(checkpointGitDir(cleoDir), "HEAD"));
39909
40128
  }
39910
40129
  async function loadStateFileAllowlist(cwd) {
39911
40130
  try {
@@ -39949,14 +40168,14 @@ async function isCleoGitRepo(cleoDir) {
39949
40168
  return result.success && (result.stdout === "true" || isCleoGitInitialized(cleoDir));
39950
40169
  }
39951
40170
  function isMergeInProgress(cleoDir) {
39952
- return existsSync18(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
40171
+ return existsSync19(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
39953
40172
  }
39954
40173
  async function isDetachedHead(cleoDir) {
39955
40174
  const result = await cleoGitCommand(["symbolic-ref", "HEAD"], cleoDir);
39956
40175
  return !result.success;
39957
40176
  }
39958
40177
  function isRebaseInProgress(cleoDir) {
39959
- return existsSync18(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync18(join23(checkpointGitDir(cleoDir), "rebase-apply"));
40178
+ return existsSync19(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync19(join23(checkpointGitDir(cleoDir), "rebase-apply"));
39960
40179
  }
39961
40180
  async function recordCheckpointTime(cleoDir) {
39962
40181
  try {
@@ -39980,7 +40199,7 @@ async function getChangedStateFiles(cleoDir, cwd) {
39980
40199
  const allStateFiles = await getAllStateFiles(cwd);
39981
40200
  for (const stateFile of allStateFiles) {
39982
40201
  const fullPath = join23(cleoDir, stateFile);
39983
- if (!existsSync18(fullPath)) continue;
40202
+ if (!existsSync19(fullPath)) continue;
39984
40203
  const diffResult = await cleoGitCommand(["diff", "--quiet", "--", stateFile], cleoDir);
39985
40204
  const cachedResult = await cleoGitCommand(
39986
40205
  ["diff", "--cached", "--quiet", "--", stateFile],
@@ -40007,7 +40226,7 @@ async function shouldCheckpoint(options) {
40007
40226
  const config2 = await loadCheckpointConfig(cwd);
40008
40227
  if (!config2.enabled) return false;
40009
40228
  const cleoDir = getCleoDir(cwd);
40010
- if (!existsSync18(cleoDir)) return false;
40229
+ if (!existsSync19(cleoDir)) return false;
40011
40230
  if (!isCleoGitInitialized(cleoDir)) return false;
40012
40231
  if (!await isCleoGitRepo(cleoDir)) return false;
40013
40232
  if (isMergeInProgress(cleoDir)) return false;
@@ -40080,6 +40299,218 @@ var init_git_checkpoint = __esm({
40080
40299
  }
40081
40300
  });
40082
40301
 
40302
+ // packages/core/src/store/snapshot-gate.ts
40303
+ import { join as join24 } from "node:path";
40304
+ function readGateState(db) {
40305
+ const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
40306
+ const state = { generation: 0, prefixes: {} };
40307
+ if (!row) return state;
40308
+ try {
40309
+ const parsed = JSON.parse(row.value);
40310
+ if (parsed === null || typeof parsed !== "object") return state;
40311
+ if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
40312
+ state.generation = parsed.generation;
40313
+ }
40314
+ for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
40315
+ if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
40316
+ state.prefixes[prefix] = {
40317
+ generation: e.generation,
40318
+ startedAt: e.startedAt,
40319
+ completedAt: e.completedAt
40320
+ };
40321
+ }
40322
+ }
40323
+ } catch {
40324
+ }
40325
+ return state;
40326
+ }
40327
+ function writeGateState(db, state) {
40328
+ db.prepare(
40329
+ "INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
40330
+ ).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
40331
+ mirrorCounterToBare(db, SNAPSHOT_GATE_META_KEY);
40332
+ }
40333
+ function tryReadGateState(db) {
40334
+ if (!db) return null;
40335
+ try {
40336
+ return readGateState(db);
40337
+ } catch {
40338
+ return null;
40339
+ }
40340
+ }
40341
+ function needsSnapshot(entry, mode, nowMs, seenGeneration) {
40342
+ if (!entry) return true;
40343
+ if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
40344
+ const elapsed = nowMs - entry.startedAt;
40345
+ return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
40346
+ }
40347
+ async function runGatedSnapshot(opts, snapshot) {
40348
+ const now = opts.now ?? Date.now;
40349
+ const mode = opts.mode ?? "routine";
40350
+ const db = opts.stateDb;
40351
+ const none = (skipped, error48) => ({
40352
+ snapshotted: [],
40353
+ linked: [],
40354
+ absent: [],
40355
+ failed: [],
40356
+ skipped,
40357
+ ...error48 !== void 0 && { error: error48 }
40358
+ });
40359
+ const entryState = tryReadGateState(db);
40360
+ const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
40361
+ if (mode === "routine") {
40362
+ if (!entryState) return none("state-unavailable");
40363
+ const nowMs = now();
40364
+ if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
40365
+ return none("debounced");
40366
+ }
40367
+ }
40368
+ const lockPath2 = join24(opts.backupDir, GATE_LOCK_BASENAME);
40369
+ let release;
40370
+ try {
40371
+ release = await acquireLock(lockPath2, {
40372
+ retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
40373
+ stale: SNAPSHOT_LOCK_STALE_MS,
40374
+ // A compromised lock (e.g. the backup dir was removed) must not throw
40375
+ // from a timer and crash the host process.
40376
+ onCompromised: () => {
40377
+ }
40378
+ });
40379
+ } catch {
40380
+ if (mode === "routine") return none("in-flight");
40381
+ return none(
40382
+ "lock-timeout",
40383
+ `Snapshot lock ${lockPath2}.lock is still held after waiting. Another snapshot is running, or a crashed process left the lock (it expires after ${SNAPSHOT_LOCK_STALE_MS / 6e4} minutes). Remove it if no snapshot is running.`
40384
+ );
40385
+ }
40386
+ try {
40387
+ try {
40388
+ opts.onLockAcquired?.();
40389
+ } catch {
40390
+ }
40391
+ const state = tryReadGateState(db);
40392
+ if (!state && mode === "routine") return none("state-unavailable");
40393
+ const startMs = now();
40394
+ const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
40395
+ (p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
40396
+ );
40397
+ if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
40398
+ const generation = (state?.generation ?? 0) + 1;
40399
+ let claimed = false;
40400
+ if (db && state) {
40401
+ try {
40402
+ writeGateState(db, { ...state, generation });
40403
+ claimed = true;
40404
+ } catch {
40405
+ }
40406
+ }
40407
+ const snapshotted = [];
40408
+ const linked = [];
40409
+ const absent = [];
40410
+ const failed = [];
40411
+ for (const prefix of admitted) {
40412
+ try {
40413
+ const outcome = await snapshot(prefix);
40414
+ if (outcome === "absent") absent.push(prefix);
40415
+ else {
40416
+ snapshotted.push(prefix);
40417
+ if (outcome === "linked") linked.push(prefix);
40418
+ }
40419
+ } catch {
40420
+ failed.push(prefix);
40421
+ }
40422
+ }
40423
+ const satisfied = [...snapshotted, ...absent];
40424
+ if (db && claimed && satisfied.length > 0) {
40425
+ try {
40426
+ const latest = readGateState(db);
40427
+ const completedAt = now();
40428
+ latest.generation = Math.max(latest.generation, generation);
40429
+ for (const p of satisfied) {
40430
+ latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
40431
+ }
40432
+ writeGateState(db, latest);
40433
+ } catch {
40434
+ }
40435
+ }
40436
+ return { snapshotted, linked, absent, failed, skipped: null };
40437
+ } finally {
40438
+ await release().catch(() => {
40439
+ });
40440
+ }
40441
+ }
40442
+ function isValidStamp(ymd, hms) {
40443
+ const y = Number(ymd.slice(0, 4));
40444
+ const mo = Number(ymd.slice(4, 6));
40445
+ const d = Number(ymd.slice(6, 8));
40446
+ const h = Number(hms.slice(0, 2));
40447
+ const mi = Number(hms.slice(2, 4));
40448
+ const se = Number(hms.slice(4, 6));
40449
+ if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
40450
+ const probe = new Date(Date.UTC(y, mo - 1, d));
40451
+ return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
40452
+ }
40453
+ function selectSnapshotsToKeep(names, ctx = {}) {
40454
+ const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
40455
+ const keep = /* @__PURE__ */ new Set();
40456
+ const stamped = [];
40457
+ for (const name15 of names) {
40458
+ const m = STAMP_PATTERN.exec(name15);
40459
+ const ymd = m?.[1];
40460
+ const hms = m?.[2];
40461
+ if (!ymd || !hms || !isValidStamp(ymd, hms)) {
40462
+ keep.add(name15);
40463
+ continue;
40464
+ }
40465
+ const stamp = `${ymd}-${hms}`;
40466
+ if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
40467
+ keep.add(name15);
40468
+ continue;
40469
+ }
40470
+ stamped.push({ name: name15, stamp });
40471
+ }
40472
+ if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
40473
+ stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
40474
+ for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
40475
+ const keepNewestPerBucket = (bucketOf, slots) => {
40476
+ const seen = /* @__PURE__ */ new Set();
40477
+ for (const s of stamped) {
40478
+ const bucket = bucketOf(s.stamp);
40479
+ if (seen.has(bucket)) continue;
40480
+ if (seen.size >= slots) break;
40481
+ seen.add(bucket);
40482
+ keep.add(s.name);
40483
+ }
40484
+ };
40485
+ keepNewestPerBucket(
40486
+ (stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
40487
+ policy.quarterHourly
40488
+ );
40489
+ keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
40490
+ keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
40491
+ return keep;
40492
+ }
40493
+ var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
40494
+ var init_snapshot_gate = __esm({
40495
+ "packages/core/src/store/snapshot-gate.ts"() {
40496
+ "use strict";
40497
+ init_lock();
40498
+ init_twin_collapse();
40499
+ SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
40500
+ SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
40501
+ SNAPSHOT_LOCK_WAIT_RETRIES = 90;
40502
+ SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
40503
+ GATE_LOCK_BASENAME = ".snapshot-gate";
40504
+ DEFAULT_SNAPSHOT_RETENTION = {
40505
+ latest: 1,
40506
+ quarterHourly: 3,
40507
+ hourly: 3,
40508
+ daily: 3
40509
+ };
40510
+ STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
40511
+ }
40512
+ });
40513
+
40083
40514
  // packages/core/src/store/data-safety-central.ts
40084
40515
  import { eq as eq7 } from "drizzle-orm";
40085
40516
  function inSafetyScope(cwd, operation) {
@@ -40490,7 +40921,7 @@ __export(data_accessor_exports, {
40490
40921
  getAccessorDb: () => getAccessorDb,
40491
40922
  getTaskAccessor: () => getTaskAccessor
40492
40923
  });
40493
- import { resolve as resolve9 } from "node:path";
40924
+ import { resolve as resolve11 } from "node:path";
40494
40925
  function assertTestEnv(dbPath) {
40495
40926
  const testMode = process.env["CLEO_TEST_MODE"];
40496
40927
  if (testMode !== "1") return;
@@ -40511,7 +40942,7 @@ function assertTestEnv(dbPath) {
40511
40942
  }
40512
40943
  }
40513
40944
  async function createDataAccessor(cwd) {
40514
- const root = resolve9(cwd ?? getProjectRoot());
40945
+ const root = resolve11(cwd ?? getProjectRoot());
40515
40946
  const inherited = worktreeScope.getStore();
40516
40947
  const captured = inherited ? { ...inherited } : void 0;
40517
40948
  captured?.execution?.assertActive();
@@ -40555,7 +40986,7 @@ __export(memory_sqlite_exports, {
40555
40986
  resetBrainDbState: () => resetBrainDbState,
40556
40987
  resolveBrainMigrationsFolder: () => resolveBrainMigrationsFolder
40557
40988
  });
40558
- import { createRequire as createRequire6 } from "node:module";
40989
+ import { createRequire as createRequire7 } from "node:module";
40559
40990
  function _getDrizzle2() {
40560
40991
  if (_drizzle2 === null) {
40561
40992
  const mod = _require4("drizzle-orm/node-sqlite");
@@ -40692,7 +41123,7 @@ var init_memory_sqlite = __esm({
40692
41123
  init_resolve_migrations_folder();
40693
41124
  init_memory_schema();
40694
41125
  init_twin_collapse();
40695
- _require4 = createRequire6(import.meta.url);
41126
+ _require4 = createRequire7(import.meta.url);
40696
41127
  _drizzle2 = null;
40697
41128
  BRAIN_SCHEMA_VERSION = "1.0.0";
40698
41129
  CONSOLIDATED_BRAIN_TABLES = [
@@ -40880,11 +41311,11 @@ var init_skills_schema = __esm({
40880
41311
  });
40881
41312
 
40882
41313
  // packages/core/src/store/skills-db.ts
40883
- import { join as join24 } from "node:path";
41314
+ import { join as join25 } from "node:path";
40884
41315
  import { and as and6, eq as eq8 } from "drizzle-orm";
40885
41316
  function getDefaultSkillsDbPath() {
40886
41317
  const cleoHome = getCleoHome();
40887
- const dbPath = join24(cleoHome, "cleo.db");
41318
+ const dbPath = join25(cleoHome, "cleo.db");
40888
41319
  if (!dbPath.startsWith(cleoHome)) {
40889
41320
  throw new Error(
40890
41321
  `BUG: getDefaultSkillsDbPath() resolved to "${dbPath}" which is NOT under getCleoHome() ("${cleoHome}"). The skills registry is global-only per SG-CLEO-SKILLS-architecture-v3.md \xA74. Fix the caller, do not suppress.`
@@ -40932,19 +41363,19 @@ import {
40932
41363
  chmodSync,
40933
41364
  closeSync,
40934
41365
  copyFileSync as copyFileSync3,
40935
- existsSync as existsSync19,
41366
+ existsSync as existsSync20,
40936
41367
  fsyncSync,
40937
41368
  linkSync,
40938
41369
  mkdirSync as mkdirSync5,
40939
41370
  openSync,
40940
41371
  readdirSync as readdirSync5,
40941
- realpathSync as realpathSync6,
41372
+ realpathSync as realpathSync7,
40942
41373
  renameSync as renameSync6,
40943
41374
  rmSync,
40944
41375
  statSync as statSync6,
40945
41376
  unlinkSync as unlinkSync3
40946
41377
  } from "node:fs";
40947
- import { dirname as dirname13, join as join25, sep as sep3 } from "node:path";
41378
+ import { dirname as dirname15, join as join26, sep as sep4 } from "node:path";
40948
41379
  function resolveInventoryPath(entry, cwd) {
40949
41380
  try {
40950
41381
  if (entry.tier === "global") {
@@ -40980,8 +41411,8 @@ async function openAgentRegistryDbForSnapshot() {
40980
41411
  }
40981
41412
  async function openTelemetryDbForSnapshot() {
40982
41413
  try {
40983
- const path = join25(getCleoHome(), "telemetry.db");
40984
- if (!existsSync19(path)) return null;
41414
+ const path = join26(getCleoHome(), "telemetry.db");
41415
+ if (!existsSync20(path)) return null;
40985
41416
  } catch {
40986
41417
  return null;
40987
41418
  }
@@ -41093,7 +41524,7 @@ function rotateSnapshots(backupDir, prefix, justWritten) {
41093
41524
  for (const name15 of names) {
41094
41525
  if (keep.has(name15)) continue;
41095
41526
  try {
41096
- unlinkSync3(join25(backupDir, name15));
41527
+ unlinkSync3(join26(backupDir, name15));
41097
41528
  } catch {
41098
41529
  }
41099
41530
  }
@@ -41115,7 +41546,7 @@ async function snapshotProjectTargetsGated(targets, opts) {
41115
41546
  let backupDir;
41116
41547
  try {
41117
41548
  const cleoDir = getCleoDir(cwd);
41118
- backupDir = join25(cleoDir, "backups", "sqlite");
41549
+ backupDir = join26(cleoDir, "backups", "sqlite");
41119
41550
  mkdirSync5(backupDir, { recursive: true });
41120
41551
  } catch {
41121
41552
  return null;
@@ -41147,7 +41578,7 @@ function sourceFileOf(db) {
41147
41578
  const location = db.location();
41148
41579
  if (!location) return null;
41149
41580
  try {
41150
- return realpathSync6(location);
41581
+ return realpathSync7(location);
41151
41582
  } catch {
41152
41583
  return location;
41153
41584
  }
@@ -41158,10 +41589,10 @@ function hasLocation(db) {
41158
41589
  function assertOwnedByProject(source, prefix, cwd) {
41159
41590
  let cleoDir = getCleoDir(cwd);
41160
41591
  try {
41161
- cleoDir = realpathSync6(cleoDir);
41592
+ cleoDir = realpathSync7(cleoDir);
41162
41593
  } catch {
41163
41594
  }
41164
- if (!source.startsWith(cleoDir + sep3)) {
41595
+ if (!source.startsWith(cleoDir + sep4)) {
41165
41596
  throw new Error(
41166
41597
  `refusing to snapshot ${prefix}: its database ${source} is not inside ${cleoDir}`
41167
41598
  );
@@ -41190,7 +41621,7 @@ function commitSnapshotFile(tmp, dest) {
41190
41621
  }
41191
41622
  renameSync6(tmp, dest);
41192
41623
  try {
41193
- const dirFd = openSync(dirname13(dest), "r");
41624
+ const dirFd = openSync(dirname15(dest), "r");
41194
41625
  try {
41195
41626
  fsyncSync(dirFd);
41196
41627
  } finally {
@@ -41213,7 +41644,7 @@ function removeDeadTempSnapshots(backupDir) {
41213
41644
  const m = TEMP_SNAPSHOT_RE.exec(name15);
41214
41645
  if (!m) continue;
41215
41646
  const pid = Number(m[1]);
41216
- const path = join25(backupDir, name15);
41647
+ const path = join26(backupDir, name15);
41217
41648
  const stale = pid !== process.pid && (!isPidAlive2(pid) || Date.now() - statSync6(path).mtimeMs > TEMP_SNAPSHOT_MAX_AGE_MS);
41218
41649
  if (stale) rmSync(path, { force: true });
41219
41650
  }
@@ -41223,7 +41654,7 @@ function removeDeadTempSnapshots(backupDir) {
41223
41654
  async function freeSnapshotName(backupDir, prefix) {
41224
41655
  for (let attempt = 0; attempt < SNAPSHOT_NAME_ATTEMPTS; attempt++) {
41225
41656
  const name15 = `${prefix}-${formatTimestamp(/* @__PURE__ */ new Date())}.db`;
41226
- if (!existsSync19(join25(backupDir, name15))) return name15;
41657
+ if (!existsSync20(join26(backupDir, name15))) return name15;
41227
41658
  await new Promise((r) => setTimeout(r, 1e3 - Date.now() % 1e3 + 5));
41228
41659
  }
41229
41660
  throw new Error(`no free snapshot filename for ${prefix} in ${backupDir}`);
@@ -41251,7 +41682,7 @@ async function snapshotOne(target, backupDir, writtenBySource, cwd) {
41251
41682
  if (opened && target.closeDb) target.closeDb(opened);
41252
41683
  throw err;
41253
41684
  }
41254
- const dest = join25(backupDir, destName);
41685
+ const dest = join26(backupDir, destName);
41255
41686
  removeDeadTempSnapshots(backupDir);
41256
41687
  const existing = source !== null ? writtenBySource.get(source) : void 0;
41257
41688
  if (existing !== void 0) {
@@ -41305,13 +41736,13 @@ async function vacuumIntoBackup(opts = {}) {
41305
41736
  function listSqliteBackupsForPrefix(prefix, cwd) {
41306
41737
  try {
41307
41738
  const cleoDir = getCleoDir(cwd);
41308
- const backupDir = join25(cleoDir, "backups", "sqlite");
41309
- if (!existsSync19(backupDir)) return [];
41739
+ const backupDir = join26(cleoDir, "backups", "sqlite");
41740
+ if (!existsSync20(backupDir)) return [];
41310
41741
  const pattern = snapshotPattern(prefix);
41311
41742
  return readdirSync5(backupDir).filter((f) => pattern.test(f)).map((f) => ({
41312
41743
  name: f,
41313
- path: join25(backupDir, f),
41314
- mtimeMs: statSync6(join25(backupDir, f)).mtimeMs
41744
+ path: join26(backupDir, f),
41745
+ mtimeMs: statSync6(join26(backupDir, f)).mtimeMs
41315
41746
  })).sort((a, b) => b.mtimeMs - a.mtimeMs);
41316
41747
  } catch {
41317
41748
  return [];
@@ -41381,15 +41812,16 @@ __export(sqlite_exports, {
41381
41812
  resetDbState: () => resetDbState,
41382
41813
  resolveMigrationsFolder: () => resolveMigrationsFolder,
41383
41814
  schema: () => tasks_schema_exports,
41384
- seedTasksMeta: () => seedTasksMeta
41815
+ seedTasksMeta: () => seedTasksMeta,
41816
+ worktreeRecoveryRefusal: () => worktreeRecoveryRefusal
41385
41817
  });
41386
- import { copyFileSync as copyFileSync4, existsSync as existsSync20, realpathSync as realpathSync7, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
41387
- import { createRequire as createRequire7 } from "node:module";
41388
- import { basename as basename8, dirname as dirname14, resolve as resolve10 } from "node:path";
41818
+ import { copyFileSync as copyFileSync4, existsSync as existsSync21, realpathSync as realpathSync8, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
41819
+ import { createRequire as createRequire8 } from "node:module";
41820
+ import { basename as basename8, dirname as dirname16, resolve as resolve12 } from "node:path";
41389
41821
  import { eq as eq9 } from "drizzle-orm";
41390
41822
  function _getDrizzle3() {
41391
41823
  if (_drizzle3 === null) {
41392
- const _require7 = createRequire7(import.meta.url);
41824
+ const _require7 = createRequire8(import.meta.url);
41393
41825
  const mod = _require7("drizzle-orm/node-sqlite");
41394
41826
  _drizzle3 = mod.drizzle;
41395
41827
  }
@@ -41425,13 +41857,19 @@ function countBackupTasks(backupDb) {
41425
41857
  return 0;
41426
41858
  }
41427
41859
  function isSameDirectory(a, b) {
41428
- if (resolve10(a) === resolve10(b)) return true;
41860
+ if (resolve12(a) === resolve12(b)) return true;
41429
41861
  try {
41430
- return realpathSync7(a) === realpathSync7(b);
41862
+ return realpathSync8(a) === realpathSync8(b);
41431
41863
  } catch {
41432
41864
  return false;
41433
41865
  }
41434
41866
  }
41867
+ function worktreeRecoveryRefusal(dbPath) {
41868
+ const storeCleoDir = dirname16(dbPath);
41869
+ const root = dirname16(storeCleoDir);
41870
+ if (basename8(storeCleoDir) !== ".cleo" || !isGitLinkedCheckout(root)) return null;
41871
+ return `Auto-recovery refused: ${dbPath} lives inside the git worktree ${root}; ${describeWorktreeOwner(root)}. A worktree uses its owning project's store and never receives a restored copy (T12460, T12677).`;
41872
+ }
41435
41873
  async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41436
41874
  const { openNativeDatabase: openNativeDatabase2 } = await Promise.resolve().then(() => (init_sqlite_native(), sqlite_native_exports));
41437
41875
  const log15 = getLogger("sqlite");
@@ -41440,12 +41878,10 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41440
41878
  const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks_tasks").get();
41441
41879
  const taskCount = countResult?.cnt ?? 0;
41442
41880
  if (taskCount > 0) return false;
41443
- const storeCleoDir = dirname14(dbPath);
41444
- if (basename8(storeCleoDir) === ".cleo" && isGitLinkedCheckout(dirname14(storeCleoDir))) {
41445
- log15.warn(
41446
- { dbPath },
41447
- "Auto-recovery refused: the empty store lives inside a git worktree (T12460). Worktrees must resolve the parent project store."
41448
- );
41881
+ const storeCleoDir = dirname16(dbPath);
41882
+ const worktreeRefusal = worktreeRecoveryRefusal(dbPath);
41883
+ if (worktreeRefusal !== null) {
41884
+ log15.warn({ dbPath }, worktreeRefusal);
41449
41885
  return false;
41450
41886
  }
41451
41887
  const backups = listSqliteBackups(cwd);
@@ -41453,7 +41889,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41453
41889
  return false;
41454
41890
  }
41455
41891
  const newestBackup = backups[0];
41456
- const backupCleoDir = dirname14(dirname14(dirname14(newestBackup.path)));
41892
+ const backupCleoDir = dirname16(dirname16(dirname16(newestBackup.path)));
41457
41893
  if (!isSameDirectory(backupCleoDir, storeCleoDir)) {
41458
41894
  log15.warn(
41459
41895
  { dbPath, backupPath: newestBackup.path },
@@ -41575,6 +42011,7 @@ function runMigrations(nativeDb, db, dbPath) {
41575
42011
  try {
41576
42012
  migrateWithRetry(db, migrationsFolder, nativeDb, "tasks", "sqlite");
41577
42013
  } catch (error48) {
42014
+ if (isWorktreeBuildSchemaError(error48)) throw error48;
41578
42015
  if (isSqliteBusy(error48) || !tableExists(nativeDb, "tasks_tasks")) throw error48;
41579
42016
  try {
41580
42017
  rebuildLegacyTasksLineage(
@@ -41616,7 +42053,7 @@ async function getSchemaVersion(cwd) {
41616
42053
  return result[0]?.value ?? null;
41617
42054
  }
41618
42055
  function dbExists(cwd) {
41619
- return existsSync20(resolveDualScopeDbPath("project", cwd));
42056
+ return existsSync21(resolveDualScopeDbPath("project", cwd));
41620
42057
  }
41621
42058
  function getNativeDb(cwd) {
41622
42059
  return boundProjectNative("tasks", cwd);
@@ -41652,6 +42089,7 @@ var init_sqlite3 = __esm({
41652
42089
  init_resolve_migrations_folder();
41653
42090
  init_sqlite_backup();
41654
42091
  init_twin_collapse();
42092
+ init_worktree_build_guard();
41655
42093
  init_worktree_isolation_guard();
41656
42094
  init_sqlite_native();
41657
42095
  init_tasks_schema();
@@ -41680,15 +42118,15 @@ var init_sqlite3 = __esm({
41680
42118
  // packages/core/src/store/exodus/migrate.ts
41681
42119
  import {
41682
42120
  copyFileSync as copyFileSync5,
41683
- existsSync as existsSync21,
42121
+ existsSync as existsSync22,
41684
42122
  mkdirSync as mkdirSync6,
41685
- readFileSync as readFileSync6,
42123
+ readFileSync as readFileSync7,
41686
42124
  renameSync as renameSync8,
41687
42125
  statSync as statSync7,
41688
42126
  unlinkSync as unlinkSync5,
41689
42127
  writeFileSync as writeFileSync6
41690
42128
  } from "node:fs";
41691
- import { join as join26 } from "node:path";
42129
+ import { join as join27 } from "node:path";
41692
42130
  function getSqliteVersion(db) {
41693
42131
  try {
41694
42132
  const row = db.prepare("SELECT sqlite_version() AS v").get();
@@ -41719,24 +42157,24 @@ function restoreGrandfatheredGuards(db, suspended) {
41719
42157
  }
41720
42158
  }
41721
42159
  function writeJournal(stagingDir, journal) {
41722
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
42160
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
41723
42161
  const tmpPath = `${journalPath}.tmp`;
41724
42162
  writeFileSync6(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
41725
42163
  renameSync8(tmpPath, journalPath);
41726
42164
  }
41727
42165
  function readJournal(stagingDir) {
41728
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
41729
- if (!existsSync21(journalPath)) return null;
42166
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
42167
+ if (!existsSync22(journalPath)) return null;
41730
42168
  try {
41731
- return JSON.parse(readFileSync6(journalPath, "utf8"));
42169
+ return JSON.parse(readFileSync7(journalPath, "utf8"));
41732
42170
  } catch {
41733
42171
  return null;
41734
42172
  }
41735
42173
  }
41736
42174
  function clearExodusJournal(stagingDir) {
41737
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
42175
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
41738
42176
  try {
41739
- if (!existsSync21(journalPath)) return false;
42177
+ if (!existsSync22(journalPath)) return false;
41740
42178
  unlinkSync5(journalPath);
41741
42179
  log10.info(
41742
42180
  { stagingDir },
@@ -42032,7 +42470,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
42032
42470
  mkdirSync6(stagingDir, { recursive: true });
42033
42471
  let sqliteVersion = "unknown";
42034
42472
  for (const src of sources) {
42035
- if (existsSync21(src.path)) {
42473
+ if (existsSync22(src.path)) {
42036
42474
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
42037
42475
  sqliteVersion = getSqliteVersion(snap.db);
42038
42476
  snap.close();
@@ -42062,15 +42500,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
42062
42500
  let reseedProject = null;
42063
42501
  try {
42064
42502
  for (const src of sources) {
42065
- if (!existsSync21(src.path)) continue;
42066
- const backupDest = join26(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
42503
+ if (!existsSync22(src.path)) continue;
42504
+ const backupDest = join27(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
42067
42505
  const srcBytes = safeStatBytes(src.path);
42068
42506
  const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
42069
42507
  if (skipStagingCopy) {
42070
42508
  onProgress?.(
42071
42509
  `Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
42072
42510
  );
42073
- } else if (!existsSync21(backupDest)) {
42511
+ } else if (!existsSync22(backupDest)) {
42074
42512
  onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
42075
42513
  copyFileSync5(src.path, backupDest);
42076
42514
  backupPaths.push(backupDest);
@@ -42103,8 +42541,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
42103
42541
  }
42104
42542
  prepareExodusRecovery(projectNative, stagingDir);
42105
42543
  if (globalNative !== null) prepareExodusRecovery(globalNative, stagingDir);
42106
- const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync21(s.path));
42107
- const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync21(s.path));
42544
+ const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
42545
+ const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync22(s.path));
42108
42546
  if (globalNative === null && globalSources.length > 0)
42109
42547
  throw new Error("A projectOnly exodus run was given global-scope sources");
42110
42548
  await migrateScope(
@@ -42412,9 +42850,9 @@ __export(reconcile_exports, {
42412
42850
  reconcileSupersededStores: () => reconcileSupersededStores,
42413
42851
  unmigratedBareSources: () => unmigratedBareSources
42414
42852
  });
42415
- import { copyFileSync as copyFileSync6, existsSync as existsSync22, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
42853
+ import { copyFileSync as copyFileSync6, existsSync as existsSync23, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
42416
42854
  import { tmpdir as tmpdir3 } from "node:os";
42417
- import { basename as basename9, join as join27 } from "node:path";
42855
+ import { basename as basename9, join as join28 } from "node:path";
42418
42856
  function ident2(name15) {
42419
42857
  return `"${name15.replace(/"/g, '""')}"`;
42420
42858
  }
@@ -42483,7 +42921,7 @@ function assessSupersededProjectStores(liveStorePath, sources, resolveTarget = r
42483
42921
  }
42484
42922
  function legacySourcesHoldRows(sources) {
42485
42923
  for (const src of sources) {
42486
- if (!existsSync22(src.path)) continue;
42924
+ if (!existsSync23(src.path)) continue;
42487
42925
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
42488
42926
  try {
42489
42927
  for (const table of orderTablesForCopy(snap.db)) {
@@ -42514,8 +42952,8 @@ async function bareTaskCoreSource(liveStorePath, resolveTarget, outDir) {
42514
42952
  live.close();
42515
42953
  }
42516
42954
  if (tables.length === 0) return null;
42517
- const seedPath = await buildFreshProjectStore(join27(outDir, "fresh-project-seed.db"));
42518
- const path = join27(outDir, "cleo-bare-task-core.db");
42955
+ const seedPath = await buildFreshProjectStore(join28(outDir, "fresh-project-seed.db"));
42956
+ const path = join28(outDir, "cleo-bare-task-core.db");
42519
42957
  const snap = openCleoDbSnapshot(path, { readOnly: false });
42520
42958
  let kept = 0;
42521
42959
  try {
@@ -42563,7 +43001,7 @@ async function buildFreshProjectStore(path) {
42563
43001
  }
42564
43002
  function snapshotFresherBareRows(barePath, legacyTasksPath, stagingDir) {
42565
43003
  if (legacyTasksPath === void 0) return null;
42566
- const path = join27(stagingDir, "cleo-bare-task-core-fresher.db");
43004
+ const path = join28(stagingDir, "cleo-bare-task-core-fresher.db");
42567
43005
  const snap = openCleoDbSnapshot(barePath, { readOnly: true });
42568
43006
  try {
42569
43007
  snap.db.exec(`VACUUM INTO '${path.replace(/'/g, "''")}'`);
@@ -42714,7 +43152,7 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
42714
43152
  const additive = options.additive === true;
42715
43153
  const plan = buildExodusPlan(projectRoot);
42716
43154
  const resolveTarget = await buildRuntimeTargetResolver();
42717
- const scratch = mkdtempSync(join27(tmpdir3(), "cleo-reconcile-"));
43155
+ const scratch = mkdtempSync(join28(tmpdir3(), "cleo-reconcile-"));
42718
43156
  try {
42719
43157
  return await reconcileWithScratch(
42720
43158
  projectRoot,
@@ -42730,8 +43168,8 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
42730
43168
  }
42731
43169
  }
42732
43170
  async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath, plan, resolveTarget, scratch) {
42733
- const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
42734
- const bare = !additive && existsSync22(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
43171
+ const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync23(s.path));
43172
+ const bare = !additive && existsSync23(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
42735
43173
  const copyResolver = additive ? (sourceName, legacyTable) => {
42736
43174
  const r = resolveTarget(sourceName, legacyTable);
42737
43175
  return r.kind !== "skip" && isLiveAuthoritative(sourceName, legacyTable, r.targetName) ? { kind: "skip", reason: "additive: live-authoritative task graph" } : r;
@@ -42750,7 +43188,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42750
43188
  stagingDir: null,
42751
43189
  receiptPath: null
42752
43190
  };
42753
- if (sources.length === 0 || !existsSync22(liveStorePath)) {
43191
+ if (sources.length === 0 || !existsSync23(liveStorePath)) {
42754
43192
  return {
42755
43193
  ...base,
42756
43194
  outcome: "nothing-to-reconcile",
@@ -42790,11 +43228,11 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42790
43228
  };
42791
43229
  }
42792
43230
  const iso = (/* @__PURE__ */ new Date()).toISOString().replace(/[:]/g, "").replace(/\..+Z$/, "Z");
42793
- const stagingDir = join27(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
43231
+ const stagingDir = join28(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
42794
43232
  mkdirSync7(stagingDir, { recursive: true });
42795
43233
  const copySources = sources.map((s) => {
42796
43234
  if (s !== bare) return s;
42797
- const kept = join27(stagingDir, basename9(s.path));
43235
+ const kept = join28(stagingDir, basename9(s.path));
42798
43236
  copyFileSync6(s.path, kept);
42799
43237
  return { ...s, path: kept };
42800
43238
  });
@@ -42814,7 +43252,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42814
43252
  const result = await withLock(
42815
43253
  `${liveStorePath}.exodus-on-open.lock`,
42816
43254
  async () => {
42817
- const liveBefore = join27(scratch, "live-before.db");
43255
+ const liveBefore = join28(scratch, "live-before.db");
42818
43256
  snapshotLive(liveStorePath, liveBefore);
42819
43257
  const migrated = await runExodusMigrate(reconcilePlan, false, (msg) => log11.debug(msg), {
42820
43258
  projectOnly: true,
@@ -42864,7 +43302,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42864
43302
  },
42865
43303
  { stale: 6e5, retries: 30 }
42866
43304
  );
42867
- const receiptPath = join27(stagingDir, RECEIPT_FILENAME);
43305
+ const receiptPath = join28(stagingDir, RECEIPT_FILENAME);
42868
43306
  const receipt2 = { ...result, receiptPath };
42869
43307
  writeFileSync7(receiptPath, `${JSON.stringify(receipt2, null, 2)}
42870
43308
  `, "utf8");
@@ -42941,20 +43379,20 @@ var init_seal = __esm({
42941
43379
  });
42942
43380
 
42943
43381
  // packages/core/src/store/exodus/status.ts
42944
- import { existsSync as existsSync23, readdirSync as readdirSync6, readFileSync as readFileSync7, statSync as statSync8 } from "node:fs";
42945
- import { join as join28 } from "node:path";
43382
+ import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync8, statSync as statSync8 } from "node:fs";
43383
+ import { join as join29 } from "node:path";
42946
43384
  function readJournal2(stagingDir) {
42947
- const p = join28(stagingDir, JOURNAL_FILENAME2);
42948
- if (!existsSync23(p)) return null;
43385
+ const p = join29(stagingDir, JOURNAL_FILENAME2);
43386
+ if (!existsSync24(p)) return null;
42949
43387
  try {
42950
- return JSON.parse(readFileSync7(p, "utf8"));
43388
+ return JSON.parse(readFileSync8(p, "utf8"));
42951
43389
  } catch {
42952
43390
  return null;
42953
43391
  }
42954
43392
  }
42955
43393
  function findStagingDirs(cleoDir) {
42956
43394
  try {
42957
- return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join28(cleoDir, e.name)).sort().reverse();
43395
+ return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join29(cleoDir, e.name)).sort().reverse();
42958
43396
  } catch {
42959
43397
  return [];
42960
43398
  }
@@ -42977,15 +43415,15 @@ function runExodusStatus(cwd) {
42977
43415
  const sourcesInfo = plan.sources.map((s) => ({
42978
43416
  name: s.name,
42979
43417
  path: s.path,
42980
- exists: existsSync23(s.path),
43418
+ exists: existsSync24(s.path),
42981
43419
  bytes: safeBytes(s.path)
42982
43420
  }));
42983
43421
  return {
42984
43422
  hasStaging: latestStaging !== null,
42985
43423
  stagingDir: latestStaging,
42986
43424
  journal,
42987
- projectDbExists: existsSync23(projectDbPath),
42988
- globalDbExists: existsSync23(globalDbPath),
43425
+ projectDbExists: existsSync24(projectDbPath),
43426
+ globalDbExists: existsSync24(globalDbPath),
42989
43427
  sourcesPresent: sourcesInfo.some((s) => s.exists),
42990
43428
  sources: sourcesInfo
42991
43429
  };
@@ -43002,8 +43440,8 @@ var init_status = __esm({
43002
43440
  });
43003
43441
 
43004
43442
  // packages/core/src/store/exodus/verify-migration.ts
43005
- import { existsSync as existsSync24 } from "node:fs";
43006
- import { createRequire as createRequire8 } from "node:module";
43443
+ import { existsSync as existsSync25 } from "node:fs";
43444
+ import { createRequire as createRequire9 } from "node:module";
43007
43445
  function orderByClause(db, tableName) {
43008
43446
  try {
43009
43447
  const pragma = db.prepare(`PRAGMA table_info("${tableName}")`).all();
@@ -43267,7 +43705,7 @@ function orphanAlreadyInSource(targetDb, fk, sources, resolveTarget = resolveCon
43267
43705
  const anyFeeder = (targetTable, probe) => {
43268
43706
  for (const feeder of feedersOf(targetTable)) {
43269
43707
  const src = sources.find((s) => s.name === feeder.sourceName);
43270
- if (src === void 0 || !existsSync24(src.path)) continue;
43708
+ if (src === void 0 || !existsSync25(src.path)) continue;
43271
43709
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
43272
43710
  try {
43273
43711
  if (!tableExists3(snap.db, feeder.legacyTable)) continue;
@@ -43322,7 +43760,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43322
43760
  const preExistingForeignKeyViolations = [];
43323
43761
  const failureLines = [];
43324
43762
  const sourceOrphanSigs = /* @__PURE__ */ new Set();
43325
- if (!existsSync24(projectDbPath)) {
43763
+ if (!existsSync25(projectDbPath)) {
43326
43764
  return {
43327
43765
  ok: false,
43328
43766
  tables: [],
@@ -43333,7 +43771,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43333
43771
  error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
43334
43772
  };
43335
43773
  }
43336
- if (!existsSync24(globalDbPath)) {
43774
+ if (!existsSync25(globalDbPath)) {
43337
43775
  return {
43338
43776
  ok: false,
43339
43777
  tables: [],
@@ -43348,7 +43786,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43348
43786
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
43349
43787
  try {
43350
43788
  for (const src of sources) {
43351
- if (!existsSync24(src.path)) {
43789
+ if (!existsSync25(src.path)) {
43352
43790
  onProgress?.(`Skipping ${src.name} (not present)`);
43353
43791
  continue;
43354
43792
  }
@@ -43543,7 +43981,7 @@ var init_verify_migration = __esm({
43543
43981
  init_column_transforms();
43544
43982
  init_table_name_map();
43545
43983
  log13 = getLogger("verify-migration");
43546
- _require5 = createRequire8(import.meta.url);
43984
+ _require5 = createRequire9(import.meta.url);
43547
43985
  CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
43548
43986
  }
43549
43987
  });
@@ -43639,11 +44077,11 @@ __export(on_open_exports, {
43639
44077
  maybeRunExodusOnOpen: () => maybeRunExodusOnOpen,
43640
44078
  withExodusOnOpenSuppressed: () => withExodusOnOpenSuppressed
43641
44079
  });
43642
- import { existsSync as existsSync25, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
44080
+ import { existsSync as existsSync26, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
43643
44081
  import { tmpdir as tmpdir4 } from "node:os";
43644
- import { join as join29, resolve as resolve11 } from "node:path";
44082
+ import { join as join30, resolve as resolve13 } from "node:path";
43645
44083
  async function withExodusOnOpenSuppressed(dbPath, fn) {
43646
- const key = resolve11(dbPath);
44084
+ const key = resolve13(dbPath);
43647
44085
  _reconcileInProgress.set(key, (_reconcileInProgress.get(key) ?? 0) + 1);
43648
44086
  try {
43649
44087
  return await fn();
@@ -43681,7 +44119,7 @@ function remedyFor(scope) {
43681
44119
  }
43682
44120
  async function strandedLegacySources(scope, cwd) {
43683
44121
  const { buildExodusPlan: buildExodusPlan2, legacySourcesHoldRows: legacySourcesHoldRows2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
43684
- return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync25(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
44122
+ return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync26(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
43685
44123
  }
43686
44124
  async function rollbackBothScopes(plan) {
43687
44125
  const { getDualScopeNativeDb: getDualScopeNativeDb2, openDualScopeDbAtPath: openDualScopeDbAtPath2 } = await Promise.resolve().then(() => (init_dual_scope_db(), dual_scope_db_exports));
@@ -43759,7 +44197,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43759
44197
  if (_exodusInProgress) {
43760
44198
  return { outcome: "skipped", reason: "re-entrant open during active migration" };
43761
44199
  }
43762
- if (_reconcileInProgress.has(resolve11(dbPath))) {
44200
+ if (_reconcileInProgress.has(resolve13(dbPath))) {
43763
44201
  return {
43764
44202
  outcome: "skipped",
43765
44203
  reason: "an explicit superseded-store reconcile of this store is in progress"
@@ -43792,14 +44230,14 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43792
44230
  const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
43793
44231
  const plan = buildExodusPlan2(cwd);
43794
44232
  const plannedTarget = scope === "project" ? plan.projectDbPath : plan.globalDbPath;
43795
- if (resolve11(plannedTarget) !== resolve11(dbPath)) {
44233
+ if (resolve13(plannedTarget) !== resolve13(dbPath)) {
43796
44234
  return {
43797
44235
  outcome: "aborted",
43798
44236
  reason: `migration plan target ${plannedTarget} does not match opened database ${dbPath}; no migration applied`
43799
44237
  };
43800
44238
  }
43801
44239
  const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
43802
- if (!scopeSources.some((s) => existsSync25(s.path))) {
44240
+ if (!scopeSources.some((s) => existsSync26(s.path))) {
43803
44241
  return {
43804
44242
  outcome: "skipped",
43805
44243
  reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
@@ -43816,12 +44254,12 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43816
44254
  {
43817
44255
  scope,
43818
44256
  dbPath,
43819
- sources: plan.sources.filter((s) => existsSync25(s.path)).map((s) => s.name)
44257
+ sources: plan.sources.filter((s) => existsSync26(s.path)).map((s) => s.name)
43820
44258
  },
43821
44259
  "exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
43822
44260
  );
43823
44261
  _exodusInProgress = true;
43824
- const bareScratch = mkdtempSync2(join29(tmpdir4(), "cleo-exodus-bare-"));
44262
+ const bareScratch = mkdtempSync2(join30(tmpdir4(), "cleo-exodus-bare-"));
43825
44263
  try {
43826
44264
  const { buildRuntimeTargetResolver: buildRuntimeTargetResolver2 } = await Promise.resolve().then(() => (init_runtime_targets(), runtime_targets_exports));
43827
44265
  const resolveTarget = await buildRuntimeTargetResolver2();
@@ -43829,7 +44267,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43829
44267
  const bare = scope === "project" ? await unmigratedBareSources2(
43830
44268
  dbPath,
43831
44269
  resolveTarget,
43832
- plan.sources.find((s) => s.name === "tasks" && existsSync25(s.path))?.path,
44270
+ plan.sources.find((s) => s.name === "tasks" && existsSync26(s.path))?.path,
43833
44271
  bareScratch
43834
44272
  ) : { first: [], last: [] };
43835
44273
  const migratePlan = { ...plan, sources: [...bare.first, ...plan.sources, ...bare.last] };
@@ -43893,7 +44331,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43893
44331
  "exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
43894
44332
  );
43895
44333
  try {
43896
- const consumed = plan.sources.filter((s) => existsSync25(s.path));
44334
+ const consumed = plan.sources.filter((s) => existsSync26(s.path));
43897
44335
  const identities = await sealTargets(plan, consumed);
43898
44336
  const archiveResult = archiveMigratedSources(consumed, cwd, plan, identities);
43899
44337
  log14.info(
@@ -43968,9 +44406,9 @@ __export(dual_scope_db_exports, {
43968
44406
  upsertIdempotent: () => upsertIdempotent,
43969
44407
  withStoreSchemaOwnership: () => withStoreSchemaOwnership
43970
44408
  });
43971
- import { existsSync as existsSync26, mkdirSync as mkdirSync8 } from "node:fs";
43972
- import { createRequire as createRequire9 } from "node:module";
43973
- import { dirname as dirname15, join as join30, resolve as resolve12 } from "node:path";
44409
+ import { existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
44410
+ import { createRequire as createRequire10 } from "node:module";
44411
+ import { dirname as dirname17, join as join31, resolve as resolve14 } from "node:path";
43974
44412
  function getDualScopeNativeDb(handle) {
43975
44413
  const db = handle.db;
43976
44414
  if ("$client" in db && db.$client instanceof getDatabaseSyncCtor()) return db.$client;
@@ -43992,9 +44430,9 @@ function cacheKey(scope, dbPath) {
43992
44430
  }
43993
44431
  function resolveDualScopeDbPath(scope, cwd, capturedGlobalHome) {
43994
44432
  if (scope === "project") {
43995
- return join30(resolveCleoDir(cwd), "cleo.db");
44433
+ return join31(resolveCleoDir(cwd), "cleo.db");
43996
44434
  }
43997
- return join30(capturedGlobalHome ?? getCleoHome(), "cleo.db");
44435
+ return join31(capturedGlobalHome ?? getCleoHome(), "cleo.db");
43998
44436
  }
43999
44437
  function migrationsSetName(scope) {
44000
44438
  return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
@@ -44044,8 +44482,8 @@ async function openDualScopeDb(scope, cwd, options) {
44044
44482
  async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
44045
44483
  execution?.assertActive();
44046
44484
  log15.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
44047
- const dir = dirname15(dbPath);
44048
- if (!existsSync26(dir)) {
44485
+ const dir = dirname17(dbPath);
44486
+ if (!existsSync27(dir)) {
44049
44487
  mkdirSync8(dir, { recursive: true });
44050
44488
  }
44051
44489
  execution?.assertActive();
@@ -44053,6 +44491,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
44053
44491
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
44054
44492
  try {
44055
44493
  applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
44494
+ installSchemaWriteGuard(nativeDb);
44056
44495
  const drizzle2 = getDrizzle();
44057
44496
  const db = drizzle2({ client: nativeDb });
44058
44497
  const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
@@ -44101,11 +44540,12 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
44101
44540
  execution?.assertActive();
44102
44541
  return handle;
44103
44542
  } catch (err) {
44543
+ const explained = explainSchemaWriteDenial(nativeDb, err);
44104
44544
  try {
44105
44545
  nativeDb.close();
44106
44546
  } catch {
44107
44547
  }
44108
- throw err;
44548
+ throw explained;
44109
44549
  }
44110
44550
  }
44111
44551
  async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
@@ -44126,7 +44566,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44126
44566
  );
44127
44567
  }
44128
44568
  const dedicated = options?.dedicated === true;
44129
- const normalizedPath = resolve12(dbPath);
44569
+ const normalizedPath = resolve14(dbPath);
44130
44570
  const key = cacheKey(scope, normalizedPath);
44131
44571
  if (!dedicated) {
44132
44572
  const existing = _cache.get(key);
@@ -44163,8 +44603,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44163
44603
  }
44164
44604
  let initResolve = null;
44165
44605
  let initReject = null;
44166
- const initPromise = new Promise((resolve15, reject) => {
44167
- initResolve = resolve15;
44606
+ const initPromise = new Promise((resolve17, reject) => {
44607
+ initResolve = resolve17;
44168
44608
  initReject = reject;
44169
44609
  });
44170
44610
  _cache.set(key, {
@@ -44185,8 +44625,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44185
44625
  try {
44186
44626
  execution?.assertActive();
44187
44627
  log15.debug({ scope, dbPath: normalizedPath }, "opening dual-scope cleo.db");
44188
- const dir = dirname15(normalizedPath);
44189
- if (!existsSync26(dir)) {
44628
+ const dir = dirname17(normalizedPath);
44629
+ if (!existsSync27(dir)) {
44190
44630
  mkdirSync8(dir, { recursive: true });
44191
44631
  }
44192
44632
  execution?.assertActive();
@@ -44194,6 +44634,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44194
44634
  const nativeDb = new DatabaseSyncCtor(normalizedPath, { allowExtension: true });
44195
44635
  openingNative = nativeDb;
44196
44636
  applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
44637
+ installSchemaWriteGuard(nativeDb);
44197
44638
  const drizzle2 = getDrizzle();
44198
44639
  const db = drizzle2({ client: nativeDb });
44199
44640
  const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
@@ -44324,12 +44765,13 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44324
44765
  execution?.assertActive();
44325
44766
  initResolve(finalHandle);
44326
44767
  } catch (err) {
44768
+ const explained = openingNative ? explainSchemaWriteDenial(openingNative, err) : err;
44327
44769
  try {
44328
44770
  if (!published && openingNative?.isOpen) openingNative.close();
44329
44771
  } catch (closeError) {
44330
44772
  log15.warn({ closeError }, "failed to close unpublished database initializer");
44331
44773
  }
44332
- initReject(err);
44774
+ initReject(explained);
44333
44775
  }
44334
44776
  })();
44335
44777
  return initPromise;
@@ -44402,6 +44844,7 @@ var init_dual_scope_db = __esm({
44402
44844
  init_relocated_store_guard();
44403
44845
  init_resolve_migrations_folder();
44404
44846
  init_sqlite_pragmas();
44847
+ init_worktree_build_guard();
44405
44848
  init_worktree_isolation_guard();
44406
44849
  init_writer_lease();
44407
44850
  ExodusAbortWriteUnsafeError = class extends Error {
@@ -44424,7 +44867,7 @@ var init_dual_scope_db = __esm({
44424
44867
  }
44425
44868
  };
44426
44869
  _cache = /* @__PURE__ */ new Map();
44427
- _require6 = createRequire9(import.meta.url);
44870
+ _require6 = createRequire10(import.meta.url);
44428
44871
  _drizzle4 = null;
44429
44872
  _DatabaseSyncCtor = null;
44430
44873
  EntryCancelledError = class extends Error {
@@ -44455,7 +44898,7 @@ var init_dual_scope_db = __esm({
44455
44898
  }
44456
44899
  /** @inheritdoc */
44457
44900
  async openProject(dbPath, options) {
44458
- const normalized = resolve12(dbPath);
44901
+ const normalized = resolve14(dbPath);
44459
44902
  if (options?.dedicated) {
44460
44903
  const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
44461
44904
  dedicated: true
@@ -44467,7 +44910,7 @@ var init_dual_scope_db = __esm({
44467
44910
  /** @inheritdoc */
44468
44911
  async openGlobal(options) {
44469
44912
  const dbPath = resolveDualScopeDbPath("global");
44470
- const normalized = resolve12(dbPath);
44913
+ const normalized = resolve14(dbPath);
44471
44914
  if (options?.dedicated) {
44472
44915
  const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
44473
44916
  dedicated: true
@@ -44478,7 +44921,7 @@ var init_dual_scope_db = __esm({
44478
44921
  }
44479
44922
  /** @inheritdoc */
44480
44923
  async openGlobalAt(dbPath, options) {
44481
- const normalized = resolve12(dbPath);
44924
+ const normalized = resolve14(dbPath);
44482
44925
  if (options?.dedicated) {
44483
44926
  const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
44484
44927
  dedicated: true
@@ -44489,7 +44932,7 @@ var init_dual_scope_db = __esm({
44489
44932
  }
44490
44933
  /** @inheritdoc */
44491
44934
  closeProject(dbPath) {
44492
- const normalized = resolve12(dbPath);
44935
+ const normalized = resolve14(dbPath);
44493
44936
  this.closeEntry("project", normalized);
44494
44937
  }
44495
44938
  /** @inheritdoc */
@@ -44526,8 +44969,8 @@ var init_dual_scope_db = __esm({
44526
44969
  const entryId = ++this._nextId;
44527
44970
  let initResolve;
44528
44971
  let initReject;
44529
- const initPromise = new Promise((resolve15, reject) => {
44530
- initResolve = resolve15;
44972
+ const initPromise = new Promise((resolve17, reject) => {
44973
+ initResolve = resolve17;
44531
44974
  initReject = reject;
44532
44975
  });
44533
44976
  this._registry.set(key, { id: entryId, store: null, initPromise });
@@ -45320,8 +45763,8 @@ __export(nexus_sqlite_exports, {
45320
45763
  resetNexusDbState: () => resetNexusDbState,
45321
45764
  resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
45322
45765
  });
45323
- import { copyFileSync as copyFileSync7, existsSync as existsSync27 } from "node:fs";
45324
- import { join as join31 } from "node:path";
45766
+ import { copyFileSync as copyFileSync7, existsSync as existsSync28 } from "node:fs";
45767
+ import { join as join32 } from "node:path";
45325
45768
  function getNexusDbPath(cwd) {
45326
45769
  return resolveDualScopeDbPath("project", cwd);
45327
45770
  }
@@ -45357,12 +45800,13 @@ function ensureGlobalRegistryAttached(nativeDb) {
45357
45800
  }
45358
45801
  }
45359
45802
  nativeDb.exec(`ATTACH DATABASE '${escaped}' AS ${NEXUS_GLOBAL_ATTACH_ALIAS}`);
45803
+ refreshSchemaWriteGuard(nativeDb);
45360
45804
  }
45361
45805
  function resolveNexusMigrationsFolder() {
45362
45806
  return resolveCorePackageMigrationsFolder("drizzle-nexus");
45363
45807
  }
45364
45808
  function getNestedNexusSentinelPath() {
45365
- return join31(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
45809
+ return join32(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
45366
45810
  }
45367
45811
  function detectAndWarnOnNestedNexus() {
45368
45812
  let nestedPath;
@@ -45371,7 +45815,7 @@ function detectAndWarnOnNestedNexus() {
45371
45815
  } catch {
45372
45816
  return false;
45373
45817
  }
45374
- if (!existsSync27(nestedPath)) return false;
45818
+ if (!existsSync28(nestedPath)) return false;
45375
45819
  if (_warnedNestedPaths.has(nestedPath)) return false;
45376
45820
  _warnedNestedPaths.add(nestedPath);
45377
45821
  const canonicalPath = getNexusDbPath();
@@ -45530,7 +45974,7 @@ function runNexusMigrations(nativeDb, db, dbPath) {
45530
45974
  const migrationsFolder = resolveNexusMigrationsFolder();
45531
45975
  if (tableExists4(nativeDb, "nexus_nodes")) {
45532
45976
  const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
45533
- if (!existsSync27(backupPath)) {
45977
+ if (!existsSync28(backupPath)) {
45534
45978
  try {
45535
45979
  copyFileSync7(dbPath, backupPath);
45536
45980
  } catch {
@@ -45625,6 +46069,7 @@ var init_nexus_sqlite = __esm({
45625
46069
  init_resolve_migrations_folder();
45626
46070
  init_nexus_schema();
45627
46071
  init_with_retry();
46072
+ init_worktree_build_guard();
45628
46073
  NEXUS_SCHEMA_VERSION = "1.0.0";
45629
46074
  NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
45630
46075
  NESTED_NEXUS_SENTINEL = "nexus.db";
@@ -45659,15 +46104,15 @@ var init_legacy_alias = __esm({
45659
46104
 
45660
46105
  // packages/core/src/llm/stable-device-id.ts
45661
46106
  import { randomUUID as randomUUID3 } from "node:crypto";
45662
- import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync8, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
45663
- import { dirname as dirname16 } from "node:path";
46107
+ import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
46108
+ import { dirname as dirname18 } from "node:path";
45664
46109
  import { resolveStableDeviceIdPath } from "@cleocode/paths";
45665
46110
  function getStableDeviceId() {
45666
46111
  if (_cachedDeviceId !== null) return _cachedDeviceId;
45667
46112
  const path = resolveStableDeviceIdPath();
45668
- if (existsSync28(path)) {
46113
+ if (existsSync29(path)) {
45669
46114
  try {
45670
- const raw = readFileSync8(path, "utf-8").trim();
46115
+ const raw = readFileSync9(path, "utf-8").trim();
45671
46116
  if (raw.length > 0) {
45672
46117
  _cachedDeviceId = raw;
45673
46118
  return raw;
@@ -45677,8 +46122,8 @@ function getStableDeviceId() {
45677
46122
  }
45678
46123
  const fresh = randomUUID3();
45679
46124
  try {
45680
- const dir = dirname16(path);
45681
- if (!existsSync28(dir)) {
46125
+ const dir = dirname18(path);
46126
+ if (!existsSync29(dir)) {
45682
46127
  mkdirSync9(dir, { recursive: true });
45683
46128
  }
45684
46129
  const tmpPath = `${path}.tmp.${process.pid}`;
@@ -45715,8 +46160,8 @@ var init_registry_roots = __esm({
45715
46160
  // packages/core/src/nexus/projects-scan.ts
45716
46161
  async function withinBudget(promise2, ms) {
45717
46162
  let timer;
45718
- const expiry = new Promise((resolve15) => {
45719
- timer = setTimeout(() => resolve15("timeout"), ms);
46163
+ const expiry = new Promise((resolve17) => {
46164
+ timer = setTimeout(() => resolve17("timeout"), ms);
45720
46165
  timer.unref();
45721
46166
  });
45722
46167
  try {
@@ -45754,9 +46199,9 @@ __export(path_map_exports, {
45754
46199
  supersededRegistryPath: () => supersededRegistryPath,
45755
46200
  touchProjectLocation: () => touchProjectLocation
45756
46201
  });
45757
- import { existsSync as existsSync29, lstatSync, readdirSync as readdirSync7 } from "node:fs";
46202
+ import { existsSync as existsSync30, lstatSync, readdirSync as readdirSync7 } from "node:fs";
45758
46203
  import { lstat, readdir as readdir2 } from "node:fs/promises";
45759
- import { isAbsolute as isAbsolute4, join as join32, relative as relative2, sep as sep4 } from "node:path";
46204
+ import { isAbsolute as isAbsolute5, join as join33, relative as relative3, sep as sep5 } from "node:path";
45760
46205
  import { canonicalizePath as canonicalizePath3, readDeclaredProjectIdentity as readDeclaredProjectIdentity3 } from "@cleocode/paths";
45761
46206
  import { and as and7, desc as desc3, eq as eq11, inArray as inArray5, ne as ne3 } from "drizzle-orm";
45762
46207
  function holdingKey(projectId, path) {
@@ -45772,7 +46217,7 @@ function isSupersededRegistryPath(projectPath) {
45772
46217
  return projectPath.startsWith(SUPERSEDED_PATH_PREFIX);
45773
46218
  }
45774
46219
  function projectHolding(path, projectId) {
45775
- const cleoDir = join32(path, ".cleo");
46220
+ const cleoDir = join33(path, ".cleo");
45776
46221
  try {
45777
46222
  lstatSync(cleoDir);
45778
46223
  readdirSync7(cleoDir);
@@ -45784,7 +46229,7 @@ function projectHolding(path, projectId) {
45784
46229
  return declared === null || declared.projectId === projectId ? "yes" : "no";
45785
46230
  }
45786
46231
  async function probeProjectHolding(path, projectId, timeoutMs) {
45787
- const cleoDir = join32(path, ".cleo");
46232
+ const cleoDir = join33(path, ".cleo");
45788
46233
  const probe = async () => {
45789
46234
  try {
45790
46235
  await lstat(cleoDir);
@@ -45802,8 +46247,8 @@ async function probeProjectHolding(path, projectId, timeoutMs) {
45802
46247
  return declared === null || declared.projectId === projectId ? "yes" : "no";
45803
46248
  }
45804
46249
  function isStrictlyInside(outer, inner) {
45805
- const rel = relative2(canonicalizePath3(outer), canonicalizePath3(inner));
45806
- return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep4}`) && !isAbsolute4(rel);
46250
+ const rel = relative3(canonicalizePath3(outer), canonicalizePath3(inner));
46251
+ return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep5}`) && !isAbsolute5(rel);
45807
46252
  }
45808
46253
  function locationKey(projectId, deviceId, path) {
45809
46254
  return and7(
@@ -45965,7 +46410,7 @@ function hasOtherLiveLocation(db, record2, deviceId) {
45965
46410
  ne3(projectLocations.path, record2.projectPath)
45966
46411
  )
45967
46412
  ).all().some(
45968
- (location) => isStrictlyInside(record2.projectPath, location.path) && existsSync29(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record2.projectId
46413
+ (location) => isStrictlyInside(record2.projectPath, location.path) && existsSync30(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record2.projectId
45969
46414
  );
45970
46415
  }
45971
46416
  function demoteProjectLocation(db, record2, state) {
@@ -46016,7 +46461,7 @@ function rehomeDisplacedRows(db, projectId, projectPath, deviceId, probed) {
46016
46461
  ).orderBy(desc3(projectLocations.lastSeen)).all();
46017
46462
  const present = (path) => {
46018
46463
  const holding = probed?.get(holdingKey(row.projectId, path));
46019
- return holding === void 0 ? existsSync29(path) : holding === "yes";
46464
+ return holding === void 0 ? existsSync30(path) : holding === "yes";
46020
46465
  };
46021
46466
  const home = candidates.find(
46022
46467
  (c) => present(c.path) && db.select({ projectId: projectRegistry.projectId }).from(projectRegistry).where(eq11(projectRegistry.projectPath, c.path)).all().length === 0
@@ -46045,7 +46490,7 @@ async function listProjectCheckouts(projectId, opts = {}) {
46045
46490
  projectHash: generateProjectHash(row.path),
46046
46491
  firstSeen: row.firstSeen,
46047
46492
  lastSeen: row.lastSeen,
46048
- exists: local && existsSync29(row.path),
46493
+ exists: local && existsSync30(row.path),
46049
46494
  deviceId: local ? deviceId : row.deviceId,
46050
46495
  state: row.state
46051
46496
  });
@@ -46074,13 +46519,13 @@ __export(checkout_nonce_exports, {
46074
46519
  readCheckoutNonce: () => readCheckoutNonce
46075
46520
  });
46076
46521
  import { randomBytes as randomBytes2 } from "node:crypto";
46077
- import { existsSync as existsSync30, readFileSync as readFileSync9, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
46078
- import { join as join33 } from "node:path";
46522
+ import { existsSync as existsSync31, readFileSync as readFileSync10, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
46523
+ import { join as join34 } from "node:path";
46079
46524
  function readInfo(projectRoot) {
46080
- const path = join33(projectRoot, ".cleo", "project-info.json");
46081
- if (!existsSync30(path)) return null;
46525
+ const path = join34(projectRoot, ".cleo", "project-info.json");
46526
+ if (!existsSync31(path)) return null;
46082
46527
  try {
46083
- const parsed = JSON.parse(readFileSync9(path, "utf-8"));
46528
+ const parsed = JSON.parse(readFileSync10(path, "utf-8"));
46084
46529
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
46085
46530
  } catch {
46086
46531
  return null;
@@ -46096,7 +46541,7 @@ function ensureCheckoutNonce(projectRoot) {
46096
46541
  const info = readInfo(projectRoot);
46097
46542
  if (!info) return null;
46098
46543
  const nonce = randomBytes2(16).toString("hex");
46099
- const path = join33(projectRoot, ".cleo", "project-info.json");
46544
+ const path = join34(projectRoot, ".cleo", "project-info.json");
46100
46545
  const temp = `${path}.${randomBytes2(6).toString("hex")}.tmp`;
46101
46546
  writeFileSync9(temp, `${JSON.stringify({ ...info, [CHECKOUT_NONCE_FIELD]: nonce }, null, 2)}
46102
46547
  `);
@@ -46171,10 +46616,10 @@ __export(paths_exports, {
46171
46616
  validateProjectRoot: () => validateProjectRoot,
46172
46617
  worktreeScope: () => worktreeScope
46173
46618
  });
46174
- import { existsSync as existsSync31, readFileSync as readFileSync10, statSync as statSync9 } from "node:fs";
46175
- import { createRequire as createRequire10 } from "node:module";
46619
+ import { existsSync as existsSync32, readFileSync as readFileSync11, statSync as statSync9 } from "node:fs";
46620
+ import { createRequire as createRequire11 } from "node:module";
46176
46621
  import { homedir as homedir2 } from "node:os";
46177
- import { basename as basename10, dirname as dirname17, join as join34, resolve as resolve13 } from "node:path";
46622
+ import { basename as basename10, dirname as dirname19, join as join35, resolve as resolve15 } from "node:path";
46178
46623
  import {
46179
46624
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
46180
46625
  getCleoTemplatesTildePath as _getCleoTemplatesTildePath,
@@ -46184,7 +46629,7 @@ import {
46184
46629
  resolveCanonicalCleoDir as _resolveCanonicalCleoDir
46185
46630
  } from "@cleocode/paths";
46186
46631
  function _getDatabaseSyncCtor() {
46187
- const _require7 = createRequire10(import.meta.url);
46632
+ const _require7 = createRequire11(import.meta.url);
46188
46633
  const mod = _require7("node:sqlite");
46189
46634
  return mod.DatabaseSync;
46190
46635
  }
@@ -46196,20 +46641,20 @@ function runWithWorktreeScopeFromEnv(fn) {
46196
46641
  }
46197
46642
  function isProjectInitialized(projectRoot) {
46198
46643
  const root = projectRoot ?? getProjectRoot();
46199
- const cleoDir = join34(root, ".cleo");
46200
- return existsSync31(cleoDir) && existsSync31(join34(cleoDir, "tasks.db"));
46644
+ const cleoDir = join35(root, ".cleo");
46645
+ return existsSync32(cleoDir) && existsSync32(join35(cleoDir, "tasks.db"));
46201
46646
  }
46202
46647
  function getCleoHome() {
46203
46648
  return getPlatformPaths().data;
46204
46649
  }
46205
46650
  function getCleoTemplatesDir() {
46206
- return join34(getCleoHome(), "templates");
46651
+ return join35(getCleoHome(), "templates");
46207
46652
  }
46208
46653
  function getCleoSchemasDir() {
46209
- return join34(getCleoHome(), "schemas");
46654
+ return join35(getCleoHome(), "schemas");
46210
46655
  }
46211
46656
  function getCleoDocsDir() {
46212
- return join34(getCleoHome(), "docs");
46657
+ return join35(getCleoHome(), "docs");
46213
46658
  }
46214
46659
  function getCleoDir(cwd) {
46215
46660
  if (cwd) {
@@ -46258,24 +46703,24 @@ function getCleoDirAbsolute(cwd, opts) {
46258
46703
  try {
46259
46704
  const projectRoot = getProjectRoot(cwd);
46260
46705
  const canonical = _resolveCanonicalCleoDir(project.projectId);
46261
- if (canonical !== null && canonical === resolve13(projectRoot, cleoDir)) {
46706
+ if (canonical !== null && canonical === resolve15(projectRoot, cleoDir)) {
46262
46707
  return canonical;
46263
46708
  }
46264
- return resolve13(projectRoot, cleoDir);
46709
+ return resolve15(projectRoot, cleoDir);
46265
46710
  } catch {
46266
- return resolve13(project.projectRoot, cleoDir);
46711
+ return resolve15(project.projectRoot, cleoDir);
46267
46712
  }
46268
46713
  }
46269
46714
  try {
46270
- return resolve13(getProjectRoot(cwd), cleoDir);
46715
+ return resolve15(getProjectRoot(cwd), cleoDir);
46271
46716
  } catch (err) {
46272
46717
  if (opts?.bootstrap) {
46273
- return resolve13(cwd ?? process.cwd(), cleoDir);
46718
+ return resolve15(cwd ?? process.cwd(), cleoDir);
46274
46719
  }
46275
46720
  if (_cwdHasGitAncestor(cwd)) {
46276
46721
  throw err;
46277
46722
  }
46278
- return resolve13(cwd ?? process.cwd(), cleoDir);
46723
+ return resolve15(cwd ?? process.cwd(), cleoDir);
46279
46724
  }
46280
46725
  }
46281
46726
  function resolveCanonicalCleoDir(projectId) {
@@ -46302,9 +46747,9 @@ function resolveCanonicalCleoDir(projectId) {
46302
46747
  function _resolveProjectByCwdFromNexus(cwd) {
46303
46748
  try {
46304
46749
  const cleoHome = getCleoHome();
46305
- const globalDbPath = join34(cleoHome, "cleo.db");
46306
- if (!existsSync31(globalDbPath)) return null;
46307
- const start = resolve13(cwd ?? process.cwd());
46750
+ const globalDbPath = join35(cleoHome, "cleo.db");
46751
+ if (!existsSync32(globalDbPath)) return null;
46752
+ const start = resolve15(cwd ?? process.cwd());
46308
46753
  let current = start;
46309
46754
  const DatabaseSync3 = _getDatabaseSyncCtor();
46310
46755
  const db = new DatabaseSync3(globalDbPath, { readOnly: true });
@@ -46317,7 +46762,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
46317
46762
  if (row && typeof row.project_id === "string" && row.project_id.length > 0) {
46318
46763
  return row.project_id;
46319
46764
  }
46320
- const parent = dirname17(current);
46765
+ const parent = dirname19(current);
46321
46766
  if (parent === current) break;
46322
46767
  current = parent;
46323
46768
  }
@@ -46337,18 +46782,18 @@ function _cleoDirEnvOverride() {
46337
46782
  }
46338
46783
  function _findCleoDirRoot(cwd) {
46339
46784
  const homeRoot = homedir2();
46340
- let current = resolve13(cwd ?? process.cwd());
46785
+ let current = resolve15(cwd ?? process.cwd());
46341
46786
  while (true) {
46342
46787
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
46343
46788
  if (!isDangerousRoot) {
46344
46789
  try {
46345
- if (statSync9(join34(current, ".cleo")).isDirectory()) {
46790
+ if (statSync9(join35(current, ".cleo")).isDirectory()) {
46346
46791
  return current;
46347
46792
  }
46348
46793
  } catch {
46349
46794
  }
46350
46795
  }
46351
- const parent = dirname17(current);
46796
+ const parent = dirname19(current);
46352
46797
  if (parent === current) break;
46353
46798
  current = parent;
46354
46799
  }
@@ -46367,7 +46812,7 @@ function resolveProjectByCwd(cwd) {
46367
46812
  if (pathsResult !== null) {
46368
46813
  return pathsResult.projectId;
46369
46814
  }
46370
- const start = resolve13(from ?? process.cwd());
46815
+ const start = resolve15(from ?? process.cwd());
46371
46816
  let current = start;
46372
46817
  while (true) {
46373
46818
  const mainRepo = _resolveMainRepoFromGitlink(current);
@@ -46378,7 +46823,7 @@ function resolveProjectByCwd(cwd) {
46378
46823
  }
46379
46824
  break;
46380
46825
  }
46381
- const parent = dirname17(current);
46826
+ const parent = dirname19(current);
46382
46827
  if (parent === current) break;
46383
46828
  current = parent;
46384
46829
  }
@@ -46397,7 +46842,7 @@ function resolveProjectByCwd(cwd) {
46397
46842
  function resolveCleoDir(cwd) {
46398
46843
  const scope = worktreeScope.getStore();
46399
46844
  if (scope !== void 0) {
46400
- return join34(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
46845
+ return join35(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
46401
46846
  }
46402
46847
  const override = _cleoDirEnvOverride();
46403
46848
  if (override !== null) {
@@ -46405,16 +46850,16 @@ function resolveCleoDir(cwd) {
46405
46850
  }
46406
46851
  const root = _findCleoDirRoot(cwd);
46407
46852
  if (root !== null) {
46408
- return join34(resolveStoreOwnerRoot(root), ".cleo");
46853
+ return join35(resolveStoreOwnerRoot(root), ".cleo");
46409
46854
  }
46410
- const start = resolve13(cwd ?? process.cwd());
46855
+ const start = resolve15(cwd ?? process.cwd());
46411
46856
  let current = start;
46412
46857
  while (true) {
46413
46858
  const mainRepo = _resolveMainRepoFromGitlink(current);
46414
46859
  if (mainRepo !== null) {
46415
- return join34(mainRepo, ".cleo");
46860
+ return join35(mainRepo, ".cleo");
46416
46861
  }
46417
- const parent = dirname17(current);
46862
+ const parent = dirname19(current);
46418
46863
  if (parent === current) {
46419
46864
  break;
46420
46865
  }
@@ -46453,25 +46898,25 @@ function _resolveCleoDir(cwd) {
46453
46898
  const project = _pathsResolveProjectByCwd(cwd);
46454
46899
  if (project !== null) {
46455
46900
  try {
46456
- return resolve13(getProjectRoot(cwd), cleoDir);
46901
+ return resolve15(getProjectRoot(cwd), cleoDir);
46457
46902
  } catch {
46458
- return resolve13(project.projectRoot, cleoDir);
46903
+ return resolve15(project.projectRoot, cleoDir);
46459
46904
  }
46460
46905
  }
46461
46906
  return getCleoDirAbsolute(cwd);
46462
46907
  }
46463
46908
  function _cwdHasGitAncestor(cwd) {
46464
- const start = resolve13(cwd ?? process.cwd());
46909
+ const start = resolve15(cwd ?? process.cwd());
46465
46910
  let current = start;
46466
46911
  while (true) {
46467
- const gitMarker = join34(current, ".git");
46912
+ const gitMarker = join35(current, ".git");
46468
46913
  try {
46469
- if (existsSync31(gitMarker)) {
46914
+ if (existsSync32(gitMarker)) {
46470
46915
  return true;
46471
46916
  }
46472
46917
  } catch {
46473
46918
  }
46474
- const parent = dirname17(current);
46919
+ const parent = dirname19(current);
46475
46920
  if (parent === current) return false;
46476
46921
  current = parent;
46477
46922
  }
@@ -46498,55 +46943,55 @@ function resolveProjectPath(relativePath, cwd) {
46498
46943
  return relativePath;
46499
46944
  }
46500
46945
  if (relativePath.startsWith("~/") || relativePath.startsWith("~\\") || relativePath === "~") {
46501
- return resolve13(homedir2(), relativePath.slice(2));
46946
+ return resolve15(homedir2(), relativePath.slice(2));
46502
46947
  }
46503
- return resolve13(getProjectRoot(cwd), relativePath);
46948
+ return resolve15(getProjectRoot(cwd), relativePath);
46504
46949
  }
46505
46950
  function getTaskPath(cwd) {
46506
- return join34(_resolveCleoDir(cwd), "tasks.db");
46951
+ return join35(_resolveCleoDir(cwd), "tasks.db");
46507
46952
  }
46508
46953
  function getConfigPath(cwd) {
46509
- return join34(_resolveCleoDir(cwd), "config.json");
46954
+ return join35(_resolveCleoDir(cwd), "config.json");
46510
46955
  }
46511
46956
  function getSessionsPath(cwd) {
46512
- return join34(_resolveCleoDir(cwd), "sessions.json");
46957
+ return join35(_resolveCleoDir(cwd), "sessions.json");
46513
46958
  }
46514
46959
  function getArchivePath(cwd) {
46515
- return join34(_resolveCleoDir(cwd), "tasks-archive.json");
46960
+ return join35(_resolveCleoDir(cwd), "tasks-archive.json");
46516
46961
  }
46517
46962
  function getLogPath(cwd) {
46518
- return join34(_resolveCleoDir(cwd), "logs", "cleo.log");
46963
+ return join35(_resolveCleoDir(cwd), "logs", "cleo.log");
46519
46964
  }
46520
46965
  function getBackupDir(cwd) {
46521
- return join34(_resolveCleoDir(cwd), "backups", "operational");
46966
+ return join35(_resolveCleoDir(cwd), "backups", "operational");
46522
46967
  }
46523
46968
  function getGlobalConfigPath() {
46524
- return join34(getCleoHome(), "config.json");
46969
+ return join35(getCleoHome(), "config.json");
46525
46970
  }
46526
46971
  function getCleoGlobalRecipesDir() {
46527
- return join34(getCleoHome(), "global-recipes");
46972
+ return join35(getCleoHome(), "global-recipes");
46528
46973
  }
46529
46974
  function getCleoGlobalJustfilePath() {
46530
- return join34(getCleoGlobalRecipesDir(), "justfile");
46975
+ return join35(getCleoGlobalRecipesDir(), "justfile");
46531
46976
  }
46532
46977
  function getCleoPiExtensionsDir() {
46533
- return join34(getCleoHome(), "pi-extensions");
46978
+ return join35(getCleoHome(), "pi-extensions");
46534
46979
  }
46535
46980
  function getCleoCantWorkflowsDir() {
46536
- return join34(getCleoHome(), "cant-workflows");
46981
+ return join35(getCleoHome(), "cant-workflows");
46537
46982
  }
46538
46983
  function getCleoGlobalAgentsDir() {
46539
- return join34(getCleoHome(), "agents");
46984
+ return join35(getCleoHome(), "agents");
46540
46985
  }
46541
46986
  function getCleoGlobalCantAgentsDir() {
46542
- return join34(getCleoHome(), "cant", "agents");
46987
+ return join35(getCleoHome(), "cant", "agents");
46543
46988
  }
46544
46989
  function getAgentOutputsDir(cwd) {
46545
46990
  const projectRoot = getProjectRoot(cwd);
46546
- const configPath = join34(projectRoot, ".cleo", "config.json");
46547
- if (existsSync31(configPath)) {
46991
+ const configPath = join35(projectRoot, ".cleo", "config.json");
46992
+ if (existsSync32(configPath)) {
46548
46993
  try {
46549
- const config2 = JSON.parse(readFileSync10(configPath, "utf-8"));
46994
+ const config2 = JSON.parse(readFileSync11(configPath, "utf-8"));
46550
46995
  if (typeof config2.agentOutputs === "object" && config2.agentOutputs?.directory) {
46551
46996
  return config2.agentOutputs.directory;
46552
46997
  }
@@ -46569,17 +47014,17 @@ function getAgentOutputsAbsolute(cwd) {
46569
47014
  if (isAbsolutePath2(dir)) {
46570
47015
  return dir;
46571
47016
  }
46572
- return resolve13(getProjectRoot(cwd), dir);
47017
+ return resolve15(getProjectRoot(cwd), dir);
46573
47018
  }
46574
47019
  function getManifestPath(cwd) {
46575
47020
  const outputDir = getAgentOutputsDir(cwd);
46576
47021
  const projectRoot = getProjectRoot(cwd);
46577
- const configPath = join34(projectRoot, ".cleo", "config.json");
47022
+ const configPath = join35(projectRoot, ".cleo", "config.json");
46578
47023
  const legacyFileName = ["MANIFEST", "jsonl"].join(".");
46579
47024
  let manifestFile = legacyFileName;
46580
- if (existsSync31(configPath)) {
47025
+ if (existsSync32(configPath)) {
46581
47026
  try {
46582
- const config2 = JSON.parse(readFileSync10(configPath, "utf-8"));
47027
+ const config2 = JSON.parse(readFileSync11(configPath, "utf-8"));
46583
47028
  const customFile = config2.agentOutputs?.manifestFile ?? config2.research?.manifestFile;
46584
47029
  if (customFile) {
46585
47030
  manifestFile = customFile;
@@ -46587,12 +47032,12 @@ function getManifestPath(cwd) {
46587
47032
  } catch {
46588
47033
  }
46589
47034
  }
46590
- return resolve13(projectRoot, outputDir, manifestFile);
47035
+ return resolve15(projectRoot, outputDir, manifestFile);
46591
47036
  }
46592
47037
  function getManifestArchivePath(cwd) {
46593
47038
  const outputDir = getAgentOutputsDir(cwd);
46594
47039
  const projectRoot = getProjectRoot(cwd);
46595
- return resolve13(projectRoot, outputDir, "MANIFEST.archive.jsonl");
47040
+ return resolve15(projectRoot, outputDir, "MANIFEST.archive.jsonl");
46596
47041
  }
46597
47042
  function isAbsolutePath2(path) {
46598
47043
  return _isAbsolutePath(path);
@@ -46616,24 +47061,24 @@ function getCanonicalTemplatesTildePath() {
46616
47061
  return _getCanonicalTemplatesTildePath();
46617
47062
  }
46618
47063
  function getAgentsHome() {
46619
- return process.env["AGENTS_HOME"] ?? join34(homedir2(), ".agents");
47064
+ return process.env["AGENTS_HOME"] ?? join35(homedir2(), ".agents");
46620
47065
  }
46621
47066
  function getClaudeAgentsDir() {
46622
- const claudeDir = process.env["CLAUDE_HOME"] ?? join34(homedir2(), ".claude");
46623
- return join34(claudeDir, "agents");
47067
+ const claudeDir = process.env["CLAUDE_HOME"] ?? join35(homedir2(), ".claude");
47068
+ return join35(claudeDir, "agents");
46624
47069
  }
46625
47070
  function getClaudeMemDbPath() {
46626
- return process.env["CLAUDE_MEM_DB"] ?? join34(homedir2(), ".claude-mem", "claude-mem.db");
47071
+ return process.env["CLAUDE_MEM_DB"] ?? join35(homedir2(), ".claude-mem", "claude-mem.db");
46627
47072
  }
46628
47073
  function resolveWorktreeRouting(cwdOverride) {
46629
- const cwd = resolve13(cwdOverride ?? process.cwd());
47074
+ const cwd = resolve15(cwdOverride ?? process.cwd());
46630
47075
  const home = homedir2();
46631
47076
  let worktreePath;
46632
47077
  let current = cwd;
46633
47078
  while (current !== home && current !== "/" && current !== "") {
46634
- const gitPath = join34(current, ".git");
47079
+ const gitPath = join35(current, ".git");
46635
47080
  try {
46636
- if (existsSync31(gitPath)) {
47081
+ if (existsSync32(gitPath)) {
46637
47082
  const stat3 = statSync9(gitPath);
46638
47083
  if (stat3.isFile()) {
46639
47084
  worktreePath = current;
@@ -46645,7 +47090,7 @@ function resolveWorktreeRouting(cwdOverride) {
46645
47090
  }
46646
47091
  } catch {
46647
47092
  }
46648
- const parent = dirname17(current);
47093
+ const parent = dirname19(current);
46649
47094
  if (parent === current) break;
46650
47095
  current = parent;
46651
47096
  }
@@ -46662,17 +47107,17 @@ function resolveWorktreeRouting(cwdOverride) {
46662
47107
  }
46663
47108
  function resolveWorktreeFilePath(filePath, routing) {
46664
47109
  if (!routing.isWorktree || routing.worktreePath === void 0) {
46665
- return resolve13(filePath);
47110
+ return resolve15(filePath);
46666
47111
  }
46667
- return resolve13(routing.cwd, filePath);
47112
+ return resolve15(routing.cwd, filePath);
46668
47113
  }
46669
47114
  function detectStrayCleoDb(routing) {
46670
47115
  if (!routing.isWorktree || routing.worktreePath === void 0) {
46671
47116
  return void 0;
46672
47117
  }
46673
- const tasksDbPath = join34(routing.worktreePath, ".cleo", "tasks.db");
47118
+ const tasksDbPath = join35(routing.worktreePath, ".cleo", "tasks.db");
46674
47119
  try {
46675
- if (existsSync31(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
47120
+ if (existsSync32(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
46676
47121
  return tasksDbPath;
46677
47122
  }
46678
47123
  } catch {
@@ -46682,7 +47127,7 @@ function detectStrayCleoDb(routing) {
46682
47127
  async function resolveProjectById(projectId) {
46683
47128
  try {
46684
47129
  const { getNexusDb: getNexusDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
46685
- if (!existsSync31(getNexusRegistryDbPath2())) return null;
47130
+ if (!existsSync32(getNexusRegistryDbPath2())) return null;
46686
47131
  const { eq: eq12 } = await import("drizzle-orm");
46687
47132
  const { projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
46688
47133
  const db = await getNexusDb2();
@@ -46717,9 +47162,9 @@ function _rowToRegistryEntry(row) {
46717
47162
  };
46718
47163
  }
46719
47164
  function _readProjectNameFromInfo(projectRoot) {
46720
- const infoPath = join34(projectRoot, ".cleo", "project-info.json");
46721
- if (!existsSync31(infoPath)) return void 0;
46722
- const raw = readFileSync10(infoPath, "utf-8");
47165
+ const infoPath = join35(projectRoot, ".cleo", "project-info.json");
47166
+ if (!existsSync32(infoPath)) return void 0;
47167
+ const raw = readFileSync11(infoPath, "utf-8");
46723
47168
  const data = JSON.parse(raw);
46724
47169
  return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
46725
47170
  }
@@ -46770,7 +47215,7 @@ async function recordProjectEncounter(cwd) {
46770
47215
  if (!shouldAutoRegisterProject(project.projectRoot, cleoHome)) return "ephemeral";
46771
47216
  const checkout = captureProjectScope(project.projectRoot, worktreeScope.getStore()).worktreeRoot;
46772
47217
  const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
46773
- if (existsSync31(getNexusRegistryDbPath2(cleoHome))) {
47218
+ if (existsSync32(getNexusRegistryDbPath2(cleoHome))) {
46774
47219
  const { and: and8, eq: eq12 } = await import("drizzle-orm");
46775
47220
  const { projectLocations: projectLocations2, projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
46776
47221
  const { currentDeviceId: currentDeviceId2 } = await Promise.resolve().then(() => (init_path_map(), path_map_exports));
@@ -46947,42 +47392,42 @@ var init_paths = __esm({
46947
47392
  // packages/core/src/store/file-utils.ts
46948
47393
  import { randomBytes as randomBytes3 } from "node:crypto";
46949
47394
  import {
46950
- existsSync as existsSync32,
47395
+ existsSync as existsSync33,
46951
47396
  mkdirSync as mkdirSync10,
46952
47397
  readdirSync as readdirSync8,
46953
- readFileSync as readFileSync11,
47398
+ readFileSync as readFileSync12,
46954
47399
  renameSync as renameSync11,
46955
47400
  unlinkSync as unlinkSync6,
46956
47401
  writeFileSync as writeFileSync10
46957
47402
  } from "node:fs";
46958
- import { basename as basename11, dirname as dirname18, join as join35 } from "node:path";
47403
+ import { basename as basename11, dirname as dirname20, join as join36 } from "node:path";
46959
47404
  import * as lockfile3 from "proper-lockfile";
46960
47405
  function rotateBackup(filePath, mode) {
46961
- const dir = dirname18(filePath);
47406
+ const dir = dirname20(filePath);
46962
47407
  const name15 = basename11(filePath);
46963
- const backupDir = join35(dir, ".backups");
47408
+ const backupDir = join36(dir, ".backups");
46964
47409
  const dirMode = typeof mode === "number" ? modeToDirMode(mode) : void 0;
46965
- if (!existsSync32(backupDir)) {
47410
+ if (!existsSync33(backupDir)) {
46966
47411
  mkdirSync10(backupDir, { recursive: true, mode: dirMode });
46967
47412
  }
46968
47413
  for (let i = MAX_BACKUPS; i >= 1; i--) {
46969
- const current = join35(backupDir, `${name15}.${i}`);
47414
+ const current = join36(backupDir, `${name15}.${i}`);
46970
47415
  if (i === MAX_BACKUPS) {
46971
47416
  try {
46972
47417
  unlinkSync6(current);
46973
47418
  } catch {
46974
47419
  }
46975
47420
  } else {
46976
- const next = join35(backupDir, `${name15}.${i + 1}`);
47421
+ const next = join36(backupDir, `${name15}.${i + 1}`);
46977
47422
  try {
46978
- if (existsSync32(current)) renameSync11(current, next);
47423
+ if (existsSync33(current)) renameSync11(current, next);
46979
47424
  } catch {
46980
47425
  }
46981
47426
  }
46982
47427
  }
46983
47428
  try {
46984
- const content = readFileSync11(filePath, "utf-8");
46985
- const backupPath = join35(backupDir, `${name15}.1`);
47429
+ const content = readFileSync12(filePath, "utf-8");
47430
+ const backupPath = join36(backupDir, `${name15}.1`);
46986
47431
  if (typeof mode === "number") {
46987
47432
  writeFileSync10(backupPath, content, { encoding: "utf-8", mode });
46988
47433
  } else {
@@ -47002,8 +47447,8 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
47002
47447
  const opts = typeof optsOrIndent === "number" ? { indent: optsOrIndent } : optsOrIndent;
47003
47448
  const indent = opts.indent ?? 2;
47004
47449
  const mode = opts.mode;
47005
- const dir = dirname18(filePath);
47006
- const tempPath = join35(dir, `.${basename11(filePath)}.${randomBytes3(6).toString("hex")}.tmp`);
47450
+ const dir = dirname20(filePath);
47451
+ const tempPath = join36(dir, `.${basename11(filePath)}.${randomBytes3(6).toString("hex")}.tmp`);
47007
47452
  const content = JSON.stringify(data, null, indent) + "\n";
47008
47453
  if (typeof mode === "number") {
47009
47454
  writeFileSync10(tempPath, content, { encoding: "utf-8", mode });
@@ -47011,7 +47456,7 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
47011
47456
  writeFileSync10(tempPath, content, "utf-8");
47012
47457
  }
47013
47458
  try {
47014
- if (existsSync32(filePath)) {
47459
+ if (existsSync33(filePath)) {
47015
47460
  rotateBackup(filePath, mode);
47016
47461
  }
47017
47462
  renameSync11(tempPath, filePath);
@@ -47025,7 +47470,7 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
47025
47470
  }
47026
47471
  function readJsonFile(filePath) {
47027
47472
  try {
47028
- const content = readFileSync11(filePath, "utf-8");
47473
+ const content = readFileSync12(filePath, "utf-8");
47029
47474
  return JSON.parse(content);
47030
47475
  } catch (error48) {
47031
47476
  if (error48.code === "ENOENT") {
@@ -47035,12 +47480,12 @@ function readJsonFile(filePath) {
47035
47480
  }
47036
47481
  }
47037
47482
  async function withLock2(filePath, transform2, opts = {}) {
47038
- const dir = dirname18(filePath);
47483
+ const dir = dirname20(filePath);
47039
47484
  const dirMode = typeof opts.mode === "number" ? modeToDirMode(opts.mode) : void 0;
47040
- if (!existsSync32(dir)) {
47485
+ if (!existsSync33(dir)) {
47041
47486
  mkdirSync10(dir, { recursive: true, mode: dirMode });
47042
47487
  }
47043
- if (!existsSync32(filePath)) {
47488
+ if (!existsSync33(filePath)) {
47044
47489
  if (typeof opts.mode === "number") {
47045
47490
  writeFileSync10(filePath, "", { encoding: "utf-8", mode: opts.mode });
47046
47491
  } else {
@@ -47061,11 +47506,11 @@ async function withLock2(filePath, transform2, opts = {}) {
47061
47506
  }
47062
47507
  }
47063
47508
  async function withFileLock(filePath, operation) {
47064
- const dir = dirname18(filePath);
47065
- if (!existsSync32(dir)) {
47509
+ const dir = dirname20(filePath);
47510
+ if (!existsSync33(dir)) {
47066
47511
  mkdirSync10(dir, { recursive: true });
47067
47512
  }
47068
- if (!existsSync32(filePath)) {
47513
+ if (!existsSync33(filePath)) {
47069
47514
  writeFileSync10(filePath, "", "utf-8");
47070
47515
  }
47071
47516
  let release;
@@ -47099,10 +47544,10 @@ var init_file_utils = __esm({
47099
47544
 
47100
47545
  // packages/core/src/llm/credential-removal.ts
47101
47546
  import { unlinkSync as unlinkSync7 } from "node:fs";
47102
- import { join as join36 } from "node:path";
47547
+ import { join as join37 } from "node:path";
47103
47548
  import { getCleoHome as getCleoHome4 } from "@cleocode/paths";
47104
47549
  function suppressionStatePath() {
47105
- return join36(getCleoHome4(), SUPPRESSION_FILENAME);
47550
+ return join37(getCleoHome4(), SUPPRESSION_FILENAME);
47106
47551
  }
47107
47552
  function readSuppressionFile() {
47108
47553
  const data = readJsonFile(suppressionStatePath());
@@ -47206,7 +47651,7 @@ var init_credential_removal = __esm({
47206
47651
  sourceId: "cleo-pkce",
47207
47652
  description: "Delete CLEO-issued PKCE token at <CLEO_HOME>/anthropic-oauth.json",
47208
47653
  async remove() {
47209
- const path = join36(getCleoHome4(), "anthropic-oauth.json");
47654
+ const path = join37(getCleoHome4(), "anthropic-oauth.json");
47210
47655
  const cleaned = [];
47211
47656
  try {
47212
47657
  unlinkSync7(path);
@@ -47264,12 +47709,12 @@ var init_credential_removal = __esm({
47264
47709
  });
47265
47710
 
47266
47711
  // packages/core/src/llm/credential-seeders/claude-code-seeder.ts
47267
- import { readFileSync as readFileSync12 } from "node:fs";
47712
+ import { readFileSync as readFileSync13 } from "node:fs";
47268
47713
  import { homedir as homedir3 } from "node:os";
47269
- import { join as join37 } from "node:path";
47714
+ import { join as join38 } from "node:path";
47270
47715
  function defaultReadCredentialFile() {
47271
47716
  try {
47272
- return readFileSync12(join37(homedir3(), ".claude", ".credentials.json"), "utf-8");
47717
+ return readFileSync13(join38(homedir3(), ".claude", ".credentials.json"), "utf-8");
47273
47718
  } catch {
47274
47719
  return null;
47275
47720
  }
@@ -47363,14 +47808,14 @@ var init_claude_code_seeder = __esm({
47363
47808
  });
47364
47809
 
47365
47810
  // packages/core/src/llm/credential-seeders/cleo-pkce-seeder.ts
47366
- import { readFileSync as readFileSync13 } from "node:fs";
47367
- import { join as join38 } from "node:path";
47811
+ import { readFileSync as readFileSync14 } from "node:fs";
47812
+ import { join as join39 } from "node:path";
47368
47813
  function defaultCleoPkcePath() {
47369
- return join38(getCleoHome(), "anthropic-oauth.json");
47814
+ return join39(getCleoHome(), "anthropic-oauth.json");
47370
47815
  }
47371
47816
  function defaultReadCredentialFile2() {
47372
47817
  try {
47373
- return readFileSync13(defaultCleoPkcePath(), "utf-8");
47818
+ return readFileSync14(defaultCleoPkcePath(), "utf-8");
47374
47819
  } catch {
47375
47820
  return null;
47376
47821
  }
@@ -47437,13 +47882,13 @@ var init_cleo_pkce_seeder = __esm({
47437
47882
  });
47438
47883
 
47439
47884
  // packages/core/src/llm/credential-seeders/codex-cli-seeder.ts
47440
- import { existsSync as existsSync33, readFileSync as readFileSync14 } from "node:fs";
47885
+ import { existsSync as existsSync34, readFileSync as readFileSync15 } from "node:fs";
47441
47886
  import { homedir as homedir4 } from "node:os";
47442
- import { join as join39 } from "node:path";
47887
+ import { join as join40 } from "node:path";
47443
47888
  function getCodexAuthPath() {
47444
47889
  const codexHome = (process.env["CODEX_HOME"] ?? "").trim();
47445
- const root = codexHome || join39(homedir4(), ".codex");
47446
- return join39(root, "auth.json");
47890
+ const root = codexHome || join40(homedir4(), ".codex");
47891
+ return join40(root, "auth.json");
47447
47892
  }
47448
47893
  var CodexCliSeeder, codexCliSeeder;
47449
47894
  var init_codex_cli_seeder = __esm({
@@ -47462,12 +47907,12 @@ var init_codex_cli_seeder = __esm({
47462
47907
  */
47463
47908
  async seed() {
47464
47909
  const authPath = getCodexAuthPath();
47465
- if (!existsSync33(authPath)) {
47910
+ if (!existsSync34(authPath)) {
47466
47911
  return { entries: [] };
47467
47912
  }
47468
47913
  let raw;
47469
47914
  try {
47470
- raw = readFileSync14(authPath, "utf-8");
47915
+ raw = readFileSync15(authPath, "utf-8");
47471
47916
  } catch (err) {
47472
47917
  return {
47473
47918
  entries: [],
@@ -47657,11 +48102,11 @@ var init_google_pkce = __esm({
47657
48102
  });
47658
48103
 
47659
48104
  // packages/core/src/llm/credential-seeders/gemini-cli-seeder.ts
47660
- import { existsSync as existsSync34, readFileSync as readFileSync15 } from "node:fs";
47661
- import { join as join40 } from "node:path";
48105
+ import { existsSync as existsSync35, readFileSync as readFileSync16 } from "node:fs";
48106
+ import { join as join41 } from "node:path";
47662
48107
  import { getCleoHome as getCleoHome5 } from "@cleocode/paths";
47663
48108
  function getGoogleOauthPath() {
47664
- return join40(getCleoHome5(), "google_oauth.json");
48109
+ return join41(getCleoHome5(), "google_oauth.json");
47665
48110
  }
47666
48111
  function parseGoogleOauthFile(raw) {
47667
48112
  let json2;
@@ -47706,12 +48151,12 @@ var init_gemini_cli_seeder = __esm({
47706
48151
  */
47707
48152
  async seed() {
47708
48153
  const path = getGoogleOauthPath();
47709
- if (!existsSync34(path)) {
48154
+ if (!existsSync35(path)) {
47710
48155
  return { entries: [] };
47711
48156
  }
47712
48157
  let raw;
47713
48158
  try {
47714
- raw = readFileSync15(path, "utf-8");
48159
+ raw = readFileSync16(path, "utf-8");
47715
48160
  } catch (err) {
47716
48161
  return {
47717
48162
  entries: [],
@@ -47931,23 +48376,23 @@ var init_credential_seeders = __esm({
47931
48376
 
47932
48377
  // packages/core/src/llm/global-config-migration.ts
47933
48378
  import {
47934
- existsSync as existsSync35,
48379
+ existsSync as existsSync36,
47935
48380
  mkdirSync as mkdirSync11,
47936
- readFileSync as readFileSync16,
48381
+ readFileSync as readFileSync17,
47937
48382
  renameSync as renameSync12,
47938
48383
  unlinkSync as unlinkSync8,
47939
48384
  writeFileSync as writeFileSync11
47940
48385
  } from "node:fs";
47941
- import { join as join41 } from "node:path";
48386
+ import { join as join42 } from "node:path";
47942
48387
  import { getCleoHome as getCleoHome6, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
47943
48388
  function configDirGlobalConfigPath() {
47944
- return join41(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
48389
+ return join42(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
47945
48390
  }
47946
48391
  function legacyGlobalConfigPath() {
47947
- return join41(getCleoHome6(), GLOBAL_CONFIG_FILENAME);
48392
+ return join42(getCleoHome6(), GLOBAL_CONFIG_FILENAME);
47948
48393
  }
47949
48394
  function migrationMarkerPath() {
47950
- return join41(getCleoHome6(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
48395
+ return join42(getCleoHome6(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
47951
48396
  }
47952
48397
  function tempTargetPath() {
47953
48398
  return `${configDirGlobalConfigPath()}.tmp`;
@@ -47957,17 +48402,17 @@ function migrateGlobalConfigToConfigDir() {
47957
48402
  const source = legacyGlobalConfigPath();
47958
48403
  const target = configDirGlobalConfigPath();
47959
48404
  const marker16 = migrationMarkerPath();
47960
- if (existsSync35(marker16)) return false;
47961
- if (!existsSync35(source)) {
48405
+ if (existsSync36(marker16)) return false;
48406
+ if (!existsSync36(source)) {
47962
48407
  stampMarker(marker16);
47963
48408
  return false;
47964
48409
  }
47965
- if (existsSync35(target)) {
48410
+ if (existsSync36(target)) {
47966
48411
  backupSourceQuiet(source);
47967
48412
  stampMarker(marker16);
47968
48413
  return false;
47969
48414
  }
47970
- const raw = readFileSync16(source, "utf-8");
48415
+ const raw = readFileSync17(source, "utf-8");
47971
48416
  try {
47972
48417
  JSON.parse(raw);
47973
48418
  } catch (err) {
@@ -47995,7 +48440,7 @@ function migrateGlobalConfigToConfigDir() {
47995
48440
  } catch (err) {
47996
48441
  try {
47997
48442
  const temp = tempTargetPath();
47998
- if (existsSync35(temp)) unlinkSync8(temp);
48443
+ if (existsSync36(temp)) unlinkSync8(temp);
47999
48444
  } catch {
48000
48445
  }
48001
48446
  console.error(
@@ -48006,7 +48451,7 @@ function migrateGlobalConfigToConfigDir() {
48006
48451
  }
48007
48452
  function stampMarker(markerPath) {
48008
48453
  try {
48009
- mkdirSync11(join41(getCleoHome6(), MIGRATIONS_SUBDIR), { recursive: true });
48454
+ mkdirSync11(join42(getCleoHome6(), MIGRATIONS_SUBDIR), { recursive: true });
48010
48455
  writeFileSync11(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
48011
48456
  `, { mode: 420 });
48012
48457
  } catch {
@@ -48015,7 +48460,7 @@ function stampMarker(markerPath) {
48015
48460
  function backupSourceQuiet(source) {
48016
48461
  try {
48017
48462
  const backup = `${source}${BACKUP_SUFFIX}`;
48018
- if (existsSync35(backup)) return;
48463
+ if (existsSync36(backup)) return;
48019
48464
  renameSync12(source, backup);
48020
48465
  } catch {
48021
48466
  }
@@ -48038,15 +48483,15 @@ var init_global_config_migration = __esm({
48038
48483
  });
48039
48484
 
48040
48485
  // packages/core/src/llm/legacy-flat-key-import.ts
48041
- import { existsSync as existsSync36, readFileSync as readFileSync17, renameSync as renameSync13, writeFileSync as writeFileSync12 } from "node:fs";
48042
- import { join as join42 } from "node:path";
48486
+ import { existsSync as existsSync37, readFileSync as readFileSync18, renameSync as renameSync13, writeFileSync as writeFileSync12 } from "node:fs";
48487
+ import { join as join43 } from "node:path";
48043
48488
  import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
48044
48489
  function migrationPaths() {
48045
48490
  const home = getCleoHome7();
48046
48491
  return {
48047
- flatPath: join42(home, "anthropic-key"),
48048
- bakPath: join42(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
48049
- markerPath: join42(home, LEGACY_FLAT_KEY_MARKER)
48492
+ flatPath: join43(home, "anthropic-key"),
48493
+ bakPath: join43(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
48494
+ markerPath: join43(home, LEGACY_FLAT_KEY_MARKER)
48050
48495
  };
48051
48496
  }
48052
48497
  function writeMarker(markerPath) {
@@ -48067,8 +48512,8 @@ function writeMarker(markerPath) {
48067
48512
  }
48068
48513
  function readFlatKey(flatPath) {
48069
48514
  try {
48070
- if (!existsSync36(flatPath)) return null;
48071
- const raw = readFileSync17(flatPath, "utf-8").trim();
48515
+ if (!existsSync37(flatPath)) return null;
48516
+ const raw = readFileSync18(flatPath, "utf-8").trim();
48072
48517
  return raw || null;
48073
48518
  } catch (err) {
48074
48519
  logger.warn(
@@ -48080,7 +48525,7 @@ function readFlatKey(flatPath) {
48080
48525
  }
48081
48526
  async function importLegacyFlatAnthropicKey() {
48082
48527
  const { flatPath, bakPath, markerPath } = migrationPaths();
48083
- if (existsSync36(markerPath)) {
48528
+ if (existsSync37(markerPath)) {
48084
48529
  return { status: "marker-present", flatPath, bakPath: null, markerPath };
48085
48530
  }
48086
48531
  let existing = null;
@@ -48097,7 +48542,7 @@ async function importLegacyFlatAnthropicKey() {
48097
48542
  writeMarker(markerPath);
48098
48543
  return { status: "already-imported", flatPath, bakPath: null, markerPath };
48099
48544
  }
48100
- if (!existsSync36(flatPath)) {
48545
+ if (!existsSync37(flatPath)) {
48101
48546
  writeMarker(markerPath);
48102
48547
  return { status: "no-flat-file", flatPath, bakPath: null, markerPath };
48103
48548
  }
@@ -48174,15 +48619,15 @@ __export(credentials_exports, {
48174
48619
  resolveProviderStatus: () => resolveProviderStatus,
48175
48620
  storeAnthropicApiKey: () => storeAnthropicApiKey
48176
48621
  });
48177
- import { existsSync as existsSync37, mkdirSync as mkdirSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "node:fs";
48178
- import { join as join43 } from "node:path";
48622
+ import { existsSync as existsSync38, mkdirSync as mkdirSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync13 } from "node:fs";
48623
+ import { join as join44 } from "node:path";
48179
48624
  import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
48180
48625
  function globalConfigPath() {
48181
48626
  return configDirGlobalConfigPath();
48182
48627
  }
48183
48628
  function projectConfigPath(projectRoot) {
48184
48629
  const cleoDir = process.env["CLEO_DIR"] ?? ".cleo";
48185
- return join43(projectRoot, cleoDir, "config.json");
48630
+ return join44(projectRoot, cleoDir, "config.json");
48186
48631
  }
48187
48632
  function readGlobalProviderKey(provider) {
48188
48633
  ensureGlobalConfigMigrated();
@@ -48192,9 +48637,9 @@ function readGlobalProviderKey(provider) {
48192
48637
  }
48193
48638
  function readFlatAnthropicKey() {
48194
48639
  try {
48195
- const keyFile = join43(getCleoHome8(), "anthropic-key");
48196
- if (!existsSync37(keyFile)) return null;
48197
- const stored = readFileSync18(keyFile, "utf-8").trim();
48640
+ const keyFile = join44(getCleoHome8(), "anthropic-key");
48641
+ if (!existsSync38(keyFile)) return null;
48642
+ const stored = readFileSync19(keyFile, "utf-8").trim();
48198
48643
  return stored || null;
48199
48644
  } catch {
48200
48645
  return null;
@@ -48202,8 +48647,8 @@ function readFlatAnthropicKey() {
48202
48647
  }
48203
48648
  function readProviderKeyFromConfig(configFile, provider) {
48204
48649
  try {
48205
- if (!existsSync37(configFile)) return null;
48206
- const raw = readFileSync18(configFile, "utf-8");
48650
+ if (!existsSync38(configFile)) return null;
48651
+ const raw = readFileSync19(configFile, "utf-8");
48207
48652
  const config2 = JSON.parse(raw);
48208
48653
  const llm = config2["llm"];
48209
48654
  if (!llm || typeof llm !== "object") return null;
@@ -48375,10 +48820,10 @@ function resolveProviderStatus(provider) {
48375
48820
  }
48376
48821
  function storeAnthropicApiKey(apiKey) {
48377
48822
  const dir = getCleoHome8();
48378
- if (!existsSync37(dir)) {
48823
+ if (!existsSync38(dir)) {
48379
48824
  mkdirSync12(dir, { recursive: true });
48380
48825
  }
48381
- const keyFile = join43(dir, "anthropic-key");
48826
+ const keyFile = join44(dir, "anthropic-key");
48382
48827
  writeFileSync13(keyFile, apiKey.trim(), { mode: 384 });
48383
48828
  }
48384
48829
  function clearAnthropicKeyCache() {
@@ -48443,16 +48888,16 @@ __export(credentials_store_exports, {
48443
48888
  pickCredentialForProviderSync: () => pickCredentialForProviderSync,
48444
48889
  removeCredential: () => removeCredential
48445
48890
  });
48446
- import { chmodSync as chmodSync2, existsSync as existsSync38, mkdirSync as mkdirSync13, readFileSync as readFileSync19, statSync as statSync10, writeFileSync as writeFileSync14 } from "node:fs";
48447
- import { dirname as dirname19, join as join44 } from "node:path";
48891
+ import { chmodSync as chmodSync2, existsSync as existsSync39, mkdirSync as mkdirSync13, readFileSync as readFileSync20, statSync as statSync10, writeFileSync as writeFileSync14 } from "node:fs";
48892
+ import { dirname as dirname21, join as join45 } from "node:path";
48448
48893
  import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
48449
48894
  function credentialsStorePath() {
48450
- return join44(getCleoHome9(), "llm-credentials.json");
48895
+ return join45(getCleoHome9(), "llm-credentials.json");
48451
48896
  }
48452
48897
  function ensureFileInitialized(path) {
48453
- if (existsSync38(path)) return;
48454
- const dir = dirname19(path);
48455
- if (!existsSync38(dir)) {
48898
+ if (existsSync39(path)) return;
48899
+ const dir = dirname21(path);
48900
+ if (!existsSync39(dir)) {
48456
48901
  mkdirSync13(dir, { recursive: true, mode: 448 });
48457
48902
  } else {
48458
48903
  try {
@@ -48496,7 +48941,7 @@ function readStoreSync() {
48496
48941
  const path = credentialsStorePath();
48497
48942
  let raw;
48498
48943
  try {
48499
- raw = readFileSync19(path, "utf-8");
48944
+ raw = readFileSync20(path, "utf-8");
48500
48945
  } catch {
48501
48946
  return emptyStore();
48502
48947
  }
@@ -49085,13 +49530,13 @@ var init_xai = __esm({
49085
49530
 
49086
49531
  // packages/core/src/llm/provider-registry/loader.ts
49087
49532
  import { readdirSync as readdirSync9, statSync as statSync11 } from "node:fs";
49088
- import { join as join45 } from "node:path";
49533
+ import { join as join46 } from "node:path";
49089
49534
  import { pathToFileURL } from "node:url";
49090
49535
  function isPluginFile(filename) {
49091
49536
  return PLUGIN_EXTENSIONS.some((ext) => filename.endsWith(ext));
49092
49537
  }
49093
49538
  function getPluginDir() {
49094
- return join45(getCleoHome(), "plugins", "model-providers");
49539
+ return join46(getCleoHome(), "plugins", "model-providers");
49095
49540
  }
49096
49541
  async function loadOnePlugin(absPath, api) {
49097
49542
  let mod;
@@ -49139,13 +49584,13 @@ async function scanAndLoadPlugins(pluginDir, api) {
49139
49584
  }
49140
49585
  const pluginFiles = entries.filter((name15) => !name15.startsWith(".") && isPluginFile(name15)).filter((name15) => {
49141
49586
  try {
49142
- return statSync11(join45(pluginDir, name15)).isFile();
49587
+ return statSync11(join46(pluginDir, name15)).isFile();
49143
49588
  } catch {
49144
49589
  return false;
49145
49590
  }
49146
49591
  }).sort();
49147
49592
  for (const filename of pluginFiles) {
49148
- await loadOnePlugin(join45(pluginDir, filename), api);
49593
+ await loadOnePlugin(join46(pluginDir, filename), api);
49149
49594
  }
49150
49595
  }
49151
49596
  async function runDiscovery(registerProvider2, builtins) {
@@ -49248,15 +49693,15 @@ var init_provider_registry = __esm({
49248
49693
  });
49249
49694
 
49250
49695
  // packages/core/src/llm/rate-limit-guard.ts
49251
- import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync9 } from "node:fs";
49252
- import { join as join46 } from "node:path";
49696
+ import { existsSync as existsSync40, mkdirSync as mkdirSync14, unlinkSync as unlinkSync9 } from "node:fs";
49697
+ import { join as join47 } from "node:path";
49253
49698
  import { getCleoHome as getCleoHome10 } from "@cleocode/paths";
49254
49699
  function sanitize(value) {
49255
49700
  return value.replace(/[^a-zA-Z0-9_-]/g, "_");
49256
49701
  }
49257
49702
  function rateLimitStatePath(provider, label) {
49258
- const dir = join46(getCleoHome10(), "rate-limit-state");
49259
- return join46(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
49703
+ const dir = join47(getCleoHome10(), "rate-limit-state");
49704
+ return join47(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
49260
49705
  }
49261
49706
  function parseResetFromHeaders(headers) {
49262
49707
  const get = (k) => {
@@ -49303,8 +49748,8 @@ async function recordRateLimit(provider, label, opts) {
49303
49748
  source = "default";
49304
49749
  }
49305
49750
  const filePath = rateLimitStatePath(provider, label);
49306
- const dir = join46(getCleoHome10(), "rate-limit-state");
49307
- if (!existsSync39(dir)) {
49751
+ const dir = join47(getCleoHome10(), "rate-limit-state");
49752
+ if (!existsSync40(dir)) {
49308
49753
  mkdirSync14(dir, { recursive: true });
49309
49754
  }
49310
49755
  const state = { resetAt, recordedAt: now, source };
@@ -50205,31 +50650,31 @@ var init_error_classifier = __esm({
50205
50650
 
50206
50651
  // packages/core/src/llm/catalog-cache.ts
50207
50652
  import {
50208
- existsSync as existsSync40,
50653
+ existsSync as existsSync41,
50209
50654
  mkdirSync as mkdirSync15,
50210
50655
  readdirSync as readdirSync10,
50211
- readFileSync as readFileSync20,
50656
+ readFileSync as readFileSync21,
50212
50657
  statSync as statSync12,
50213
50658
  symlinkSync,
50214
50659
  unlinkSync as unlinkSync10,
50215
50660
  writeFileSync as writeFileSync15
50216
50661
  } from "node:fs";
50217
- import { join as join47 } from "node:path";
50662
+ import { join as join48 } from "node:path";
50218
50663
  import { getCleoHome as getCleoHome11 } from "@cleocode/paths";
50219
50664
  function getCatalogDir() {
50220
50665
  if (process.env["CLEO_DATA_DIR"]) {
50221
- return join47(process.env["CLEO_DATA_DIR"], "llm-catalog");
50666
+ return join48(process.env["CLEO_DATA_DIR"], "llm-catalog");
50222
50667
  }
50223
- return join47(getCleoHome11(), "llm-catalog");
50668
+ return join48(getCleoHome11(), "llm-catalog");
50224
50669
  }
50225
50670
  function findLatestCacheFile(dir) {
50226
- if (!existsSync40(dir)) return null;
50227
- const files = readdirSync10(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync12(join47(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
50228
- return files.length > 0 ? join47(dir, files[0].name) : null;
50671
+ if (!existsSync41(dir)) return null;
50672
+ const files = readdirSync10(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync12(join48(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
50673
+ return files.length > 0 ? join48(dir, files[0].name) : null;
50229
50674
  }
50230
50675
  function readCacheFile(filePath) {
50231
50676
  try {
50232
- const raw = readFileSync20(filePath, "utf-8");
50677
+ const raw = readFileSync21(filePath, "utf-8");
50233
50678
  return JSON.parse(raw);
50234
50679
  } catch {
50235
50680
  return null;
@@ -50242,16 +50687,16 @@ var init_catalog_cache = __esm({
50242
50687
  });
50243
50688
 
50244
50689
  // packages/core/src/llm/model-metadata.ts
50245
- import { readFileSync as readFileSync21 } from "node:fs";
50246
- import { dirname as dirname20, join as join48 } from "node:path";
50247
- import { fileURLToPath as fileURLToPath3 } from "node:url";
50690
+ import { readFileSync as readFileSync22 } from "node:fs";
50691
+ import { dirname as dirname22, join as join49 } from "node:path";
50692
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
50248
50693
  function getCuratedTable() {
50249
50694
  if (_curated !== void 0) {
50250
50695
  return _curated;
50251
50696
  }
50252
- const thisDir = dirname20(fileURLToPath3(import.meta.url));
50253
- const jsonPath = join48(thisDir, "curated-models.json");
50254
- const raw = JSON.parse(readFileSync21(jsonPath, "utf-8"));
50697
+ const thisDir = dirname22(fileURLToPath4(import.meta.url));
50698
+ const jsonPath = join49(thisDir, "curated-models.json");
50699
+ const raw = JSON.parse(readFileSync22(jsonPath, "utf-8"));
50255
50700
  _curated = raw.models;
50256
50701
  return _curated;
50257
50702
  }
@@ -50336,7 +50781,7 @@ function storedToResolved(stored) {
50336
50781
  };
50337
50782
  }
50338
50783
  function sleep3(ms) {
50339
- return new Promise((resolve15) => setTimeout(resolve15, ms));
50784
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
50340
50785
  }
50341
50786
  function backoffMs(policy, attempt) {
50342
50787
  const base = policy.baseDelayMs * 2 ** attempt;
@@ -54278,7 +54723,7 @@ function normalizeOllamaToolCall(tc) {
54278
54723
  };
54279
54724
  }
54280
54725
  function sleep4(ms) {
54281
- return new Promise((resolve15) => setTimeout(resolve15, ms));
54726
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
54282
54727
  }
54283
54728
  var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
54284
54729
  var init_ollama2 = __esm({
@@ -74792,7 +75237,7 @@ function createProviderToolFactoryWithOutputSchema({
74792
75237
  supportsDeferredResults
74793
75238
  });
74794
75239
  }
74795
- async function resolve14(value) {
75240
+ async function resolve16(value) {
74796
75241
  if (typeof value === "function") {
74797
75242
  value = value();
74798
75243
  }
@@ -78826,14 +79271,14 @@ var init_dist4 = __esm({
78826
79271
  headers
78827
79272
  }) {
78828
79273
  return combineHeaders(
78829
- await resolve14(this.config.headers),
79274
+ await resolve16(this.config.headers),
78830
79275
  headers,
78831
79276
  betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {}
78832
79277
  );
78833
79278
  }
78834
79279
  async getBetasFromHeaders(requestHeaders) {
78835
79280
  var _a17, _b16;
78836
- const configHeaders = await resolve14(this.config.headers);
79281
+ const configHeaders = await resolve16(this.config.headers);
78837
79282
  const configBetaHeader = (_a17 = configHeaders["anthropic-beta"]) != null ? _a17 : "";
78838
79283
  const requestBetaHeader = (_b16 = requestHeaders == null ? void 0 : requestHeaders["anthropic-beta"]) != null ? _b16 : "";
78839
79284
  return new Set(