@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"],
@@ -3086,12 +3086,21 @@ var init_operations_registry = __esm({
3086
3086
  gateway: "query",
3087
3087
  domain: "tasks",
3088
3088
  operation: "history",
3089
- description: "Show task work history (time tracked per task)",
3089
+ description: "Show task work history; with taskId, the task audit trail; with ranking, who changed its priority/severity/kind/depends and why (T12693)",
3090
3090
  tier: 1,
3091
3091
  idempotent: true,
3092
3092
  sessionRequired: false,
3093
3093
  requiredParams: [],
3094
- params: []
3094
+ params: [
3095
+ { name: "taskId", type: "string", required: false, description: "Task to show history for" },
3096
+ { name: "limit", type: "number", required: false, description: "Maximum entries" },
3097
+ {
3098
+ name: "ranking",
3099
+ type: "boolean",
3100
+ required: false,
3101
+ description: "Only ranking-input changes (actor, session, reason, before/after)"
3102
+ }
3103
+ ]
3095
3104
  },
3096
3105
  {
3097
3106
  gateway: "query",
@@ -5586,6 +5595,32 @@ var init_operations_registry = __esm({
5586
5595
  ],
5587
5596
  outputSchema: OUTPUT_CONTRACTS["tasks.assignee"]
5588
5597
  },
5598
+ {
5599
+ gateway: "mutate",
5600
+ domain: "tasks",
5601
+ operation: "ranking.revert",
5602
+ description: "tasks.ranking.revert (mutate) \u2014 undo one recorded ranking change (priority/severity/kind/depends) as a new audited change (T12693, D11161)",
5603
+ tier: 1,
5604
+ idempotent: false,
5605
+ sessionRequired: false,
5606
+ requiredParams: ["entryId"],
5607
+ params: [
5608
+ {
5609
+ name: "entryId",
5610
+ type: "string",
5611
+ required: true,
5612
+ description: "ranking_changed audit row id (cleo history ranking <taskId>)",
5613
+ cli: { positional: true }
5614
+ },
5615
+ { name: "reason", type: "string", required: false, description: "Why it is reverted" },
5616
+ {
5617
+ name: "force",
5618
+ type: "boolean",
5619
+ required: false,
5620
+ description: "Revert even though a field changed again since"
5621
+ }
5622
+ ]
5623
+ },
5589
5624
  {
5590
5625
  gateway: "mutate",
5591
5626
  domain: "tasks",
@@ -10509,7 +10544,7 @@ var init_operations_registry = __esm({
10509
10544
  type: "string",
10510
10545
  required: false,
10511
10546
  enum: DOCS_LIFECYCLE_STATUSES,
10512
- description: `Override the new lifecycle status. Defaults to "draft" on every update. Valid: ${DOCS_LIFECYCLE_STATUSES.join("|")}.`
10547
+ 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("|")}.`
10513
10548
  },
10514
10549
  {
10515
10550
  name: "dryRun",
@@ -12996,11 +13031,13 @@ var init_evidence_atom_schema = __esm({
12996
13031
  });
12997
13032
  prAtomSchema = z10.object({
12998
13033
  kind: z10.literal("pr"),
12999
- prNumber: z10.number().int().positive("pr atom requires a positive integer PR number")
13034
+ prNumber: z10.number().int().positive("pr atom requires a positive integer PR number"),
13035
+ componentPrNumber: z10.number().int().positive().optional()
13000
13036
  });
13001
13037
  ciAtomSchema = z10.object({
13002
13038
  kind: z10.literal("ci"),
13003
- prNumber: z10.number().int().positive("ci atom requires a positive integer PR number")
13039
+ prNumber: z10.number().int().positive("ci atom requires a positive integer PR number"),
13040
+ componentPrNumber: z10.number().int().positive().optional()
13004
13041
  });
13005
13042
  locDropAtomSchema = z10.object({
13006
13043
  kind: z10.literal("loc-drop"),
@@ -13051,7 +13088,10 @@ var init_evidence_atom_schema = __esm({
13051
13088
  ["commit", "note"],
13052
13089
  ["decision", "files"],
13053
13090
  ["decision", "note"],
13054
- ["pr", "files"]
13091
+ ["pr", "files"],
13092
+ // T12689: a deletion-only PR (no bytes to hash). Contextual validation
13093
+ // accepts this only when every change the PR made is a deletion.
13094
+ ["pr", "note"]
13055
13095
  ]
13056
13096
  },
13057
13097
  testsPassed: { oneOf: [["test-run"], ["tool"], ["ci"]] },
@@ -16953,7 +16993,7 @@ var init_collection_keys = __esm({
16953
16993
 
16954
16994
  // packages/contracts/src/decide.ts
16955
16995
  import { z as z24 } from "zod";
16956
- 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;
16996
+ 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;
16957
16997
  var init_decide = __esm({
16958
16998
  "packages/contracts/src/decide.ts"() {
16959
16999
  "use strict";
@@ -16977,6 +17017,7 @@ var init_decide = __esm({
16977
17017
  /** Maximum number of levels on a `score` question's scale. */
16978
17018
  maxScoreLevels: 10
16979
17019
  };
17020
+ DECISION_PROVIDER_KINDS = ["layahost", "jev"];
16980
17021
  decisionQuestionTypeSchema = z24.enum(DECISION_QUESTION_TYPES);
16981
17022
  decisionOutcomeSourceSchema = z24.enum(DECISION_OUTCOME_SOURCES);
16982
17023
  decisionInstructionsSchema = z24.union([z24.string(), z24.record(z24.string(), z24.json())]);
@@ -17014,6 +17055,8 @@ var init_decide = __esm({
17014
17055
  ]);
17015
17056
  decisionRequestSchema = z24.object({
17016
17057
  model: z24.string().min(1).optional(),
17058
+ lang: z24.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$/).optional(),
17059
+ cache: z24.boolean().optional(),
17017
17060
  state: decisionStateSchema,
17018
17061
  questions: z24.record(z24.string().min(1), decisionQuestionSchema).refine(
17019
17062
  (questions) => {
@@ -17054,14 +17097,26 @@ var init_decide = __esm({
17054
17097
  requestId: z24.string().min(1).optional(),
17055
17098
  latencyMs: z24.number().nonnegative(),
17056
17099
  costUsd: z24.number().nonnegative().optional(),
17100
+ costMicros: z24.number().int().nonnegative().optional(),
17101
+ balanceMicros: z24.number().int().optional(),
17102
+ checkpoint: z24.string().min(1).optional(),
17057
17103
  inputTokens: z24.number().int().nonnegative().optional()
17058
17104
  });
17105
+ decisionProviderKindSchema = z24.enum(DECISION_PROVIDER_KINDS);
17059
17106
  decisionProviderConfigSchema = z24.object({
17060
- baseUrl: z24.url()
17107
+ baseUrl: z24.url(),
17108
+ provider: decisionProviderKindSchema.optional()
17061
17109
  });
17062
17110
  }
17063
17111
  });
17064
17112
 
17113
+ // packages/contracts/src/decide-sites.ts
17114
+ var init_decide_sites = __esm({
17115
+ "packages/contracts/src/decide-sites.ts"() {
17116
+ "use strict";
17117
+ }
17118
+ });
17119
+
17065
17120
  // packages/contracts/src/task-id.ts
17066
17121
  var init_task_id = __esm({
17067
17122
  "packages/contracts/src/task-id.ts"() {
@@ -17143,6 +17198,7 @@ var init_src = __esm({
17143
17198
  init_caamp_markers();
17144
17199
  init_collection_keys();
17145
17200
  init_decide();
17201
+ init_decide_sites();
17146
17202
  init_task_id();
17147
17203
  }
17148
17204
  });
@@ -18640,6 +18696,37 @@ function linkedWorktreeMainRoot(dir) {
18640
18696
  if (basename2(commonDir) === ".git") return dirname2(commonDir);
18641
18697
  return readCoreWorktree(commonDir);
18642
18698
  }
18699
+ function describeWorktreeOwner(dir) {
18700
+ const mainRoot = linkedWorktreeMainRoot(dir);
18701
+ if (mainRoot === null) {
18702
+ const bare = bareRepositoryOfWorktree(dir);
18703
+ 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`;
18704
+ }
18705
+ let projectId = null;
18706
+ try {
18707
+ const parsed = JSON.parse(
18708
+ readFileSync2(join3(mainRoot, ".cleo", "project-info.json"), "utf-8")
18709
+ );
18710
+ if (typeof parsed === "object" && parsed !== null && "projectId" in parsed) {
18711
+ const value = parsed.projectId;
18712
+ if (typeof value === "string" && value !== "") projectId = value;
18713
+ }
18714
+ } catch {
18715
+ }
18716
+ return projectId === null ? `owning repository ${mainRoot} (not an initialised CLEO project)` : `owning project ${mainRoot} (projectId ${projectId})`;
18717
+ }
18718
+ function bareRepositoryOfWorktree(dir) {
18719
+ const gitdir = readGitlinkTarget(dir);
18720
+ if (!gitdir || basename2(dirname2(gitdir)) !== "worktrees") return null;
18721
+ const commonDir = dirname2(dirname2(gitdir));
18722
+ try {
18723
+ const config = readFileSync2(join3(commonDir, "config"), "utf-8");
18724
+ const core = /^\[core\][^[]*/m.exec(config)?.[0] ?? "";
18725
+ return /^\s*bare\s*=\s*true\s*$/im.test(core) ? commonDir : null;
18726
+ } catch {
18727
+ return null;
18728
+ }
18729
+ }
18643
18730
  function readCoreWorktree(gitDir) {
18644
18731
  try {
18645
18732
  const config = readFileSync2(join3(gitDir, "config"), "utf-8");
@@ -19089,13 +19176,13 @@ function captureWriteFence(input) {
19089
19176
  return writeFence;
19090
19177
  }
19091
19178
  function observeOperation(context, work) {
19092
- return new Promise((resolve14) => {
19179
+ return new Promise((resolve16) => {
19093
19180
  let observed = false;
19094
19181
  const finish = (result) => {
19095
19182
  if (observed) return;
19096
19183
  observed = true;
19097
19184
  context.signal.removeEventListener("abort", abort);
19098
- resolve14(result);
19185
+ resolve16(result);
19099
19186
  };
19100
19187
  const abort = () => {
19101
19188
  const reason = context.signal.reason;
@@ -19729,7 +19816,7 @@ var init_sql = __esm({
19729
19816
  return new SQL([new StringChunk(str)]);
19730
19817
  }
19731
19818
  _sql.raw = raw;
19732
- function join35(chunks, separator) {
19819
+ function join36(chunks, separator) {
19733
19820
  const result = [];
19734
19821
  for (const [i, chunk] of chunks.entries()) {
19735
19822
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -19737,7 +19824,7 @@ var init_sql = __esm({
19737
19824
  }
19738
19825
  return new SQL(result);
19739
19826
  }
19740
- _sql.join = join35;
19827
+ _sql.join = join36;
19741
19828
  function identifier2(value) {
19742
19829
  return new Name(value);
19743
19830
  }
@@ -21752,7 +21839,7 @@ var init_select = __esm({
21752
21839
  const baseTableName = this.tableName;
21753
21840
  const tableName = getTableLikeName(table);
21754
21841
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
21755
- if (typeof tableName === "string" && this.config.joins?.some((join35) => join35.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21842
+ if (typeof tableName === "string" && this.config.joins?.some((join36) => join36.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21756
21843
  if (!this.isPartialSelect) {
21757
21844
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
21758
21845
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -23349,7 +23436,7 @@ var init_dialect = __esm({
23349
23436
  if (!joins2) return;
23350
23437
  const withEntries = Object.entries(joins2).filter(([_, v]) => v);
23351
23438
  if (!withEntries.length) return;
23352
- return sql.join(withEntries.map(([k, join35]) => {
23439
+ return sql.join(withEntries.map(([k, join36]) => {
23353
23440
  const relation = tableConfig.relations[k];
23354
23441
  const isSingle2 = is(relation, One);
23355
23442
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -23360,7 +23447,7 @@ var init_dialect = __esm({
23360
23447
  table: targetTable,
23361
23448
  mode: isSingle2 ? "first" : "many",
23362
23449
  schema,
23363
- queryConfig: join35,
23450
+ queryConfig: join36,
23364
23451
  tableConfig: schema[relation.targetTableName],
23365
23452
  relationWhere: filter,
23366
23453
  isNested: true,
@@ -23374,7 +23461,7 @@ var init_dialect = __esm({
23374
23461
  key: k,
23375
23462
  selection: innerQuery.selection,
23376
23463
  isArray: !isSingle2,
23377
- isOptional: (relation.optional ?? false) || join35 !== true && !!join35.where
23464
+ isOptional: (relation.optional ?? false) || join36 !== true && !!join36.where
23378
23465
  });
23379
23466
  const jsonColumns = sql.join(innerQuery.selection.map((s) => {
23380
23467
  return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb2}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
@@ -23796,7 +23883,7 @@ var init_update = __esm({
23796
23883
  createJoin(joinType) {
23797
23884
  return ((table, on) => {
23798
23885
  const tableName = getTableLikeName(table);
23799
- if (typeof tableName === "string" && this.config.joins.some((join35) => join35.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
23886
+ if (typeof tableName === "string" && this.config.joins.some((join36) => join36.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
23800
23887
  if (typeof on === "function") {
23801
23888
  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;
23802
23889
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -24952,7 +25039,7 @@ async function withWriteRetry(fn, opts = {}) {
24952
25039
  throw contentionErr;
24953
25040
  }
24954
25041
  function sleep(ms) {
24955
- return new Promise((resolve14) => setTimeout(resolve14, ms));
25042
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
24956
25043
  }
24957
25044
  var DEFAULT_MAX_ATTEMPTS, DEFAULT_BASE_DELAY_MS, DEFAULT_JITTER_MS;
24958
25045
  var init_with_retry = __esm({
@@ -24964,9 +25051,250 @@ var init_with_retry = __esm({
24964
25051
  }
24965
25052
  });
24966
25053
 
25054
+ // packages/core/src/store/worktree-build-guard.ts
25055
+ import { existsSync as existsSync4, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "node:fs";
25056
+ import { createRequire } from "node:module";
25057
+ import { dirname as dirname3, isAbsolute as isAbsolute3, join as join5, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
25058
+ import { fileURLToPath } from "node:url";
25059
+ function realOrResolved(path2) {
25060
+ try {
25061
+ return realpathSync3(path2);
25062
+ } catch {
25063
+ return resolve2(path2);
25064
+ }
25065
+ }
25066
+ function isWithin(root, path2) {
25067
+ const local = relative2(root, path2);
25068
+ return local === "" || !isAbsolute3(local) && local !== ".." && !local.startsWith(`..${sep2}`);
25069
+ }
25070
+ function insideGitCheckout(dir) {
25071
+ let current = dir;
25072
+ for (; ; ) {
25073
+ if (existsSync4(join5(current, ".git"))) return true;
25074
+ const parent = dirname3(current);
25075
+ if (parent === current) return false;
25076
+ current = parent;
25077
+ }
25078
+ }
25079
+ function insideTestSandbox(path2) {
25080
+ let dir = dirname3(path2);
25081
+ for (; ; ) {
25082
+ if (existsSync4(join5(dir, TEST_SANDBOX_MARKER))) return !insideGitCheckout(dir);
25083
+ const parent = dirname3(dir);
25084
+ if (parent === dir) return false;
25085
+ dir = parent;
25086
+ }
25087
+ }
25088
+ function linkedWorktreeRootOf(path2) {
25089
+ let dir = realOrResolved(path2);
25090
+ for (; ; ) {
25091
+ if (isGitLinkedCheckout(dir)) return dir;
25092
+ if (existsSync4(join5(dir, ".git"))) return null;
25093
+ const parent = dirname3(dir);
25094
+ if (parent === dir) return null;
25095
+ dir = parent;
25096
+ }
25097
+ }
25098
+ function readBuildProvenance(codePath) {
25099
+ let dir = dirname3(codePath);
25100
+ for (; ; ) {
25101
+ const stamp = join5(dir, "build-provenance.json");
25102
+ if (existsSync4(stamp)) {
25103
+ try {
25104
+ const parsed = JSON.parse(readFileSync3(stamp, "utf8"));
25105
+ if (typeof parsed === "object" && parsed !== null && "linkedWorktree" in parsed) {
25106
+ const value = parsed.linkedWorktree;
25107
+ if (value === null || typeof value === "string") return { linkedWorktree: value };
25108
+ }
25109
+ } catch {
25110
+ }
25111
+ return null;
25112
+ }
25113
+ if (existsSync4(join5(dir, "package.json"))) return null;
25114
+ const parent = dirname3(dir);
25115
+ if (parent === dir) return null;
25116
+ dir = parent;
25117
+ }
25118
+ }
25119
+ function devBuildWorktree(options = {}) {
25120
+ const codePath = options.codePath ?? overrides?.codePath ?? fileURLToPath(import.meta.url);
25121
+ const provenance = options.provenance !== void 0 ? options.provenance : overrides?.provenance !== void 0 ? overrides.provenance : readBuildProvenance(codePath);
25122
+ if (provenance) return provenance.linkedWorktree;
25123
+ if (codePath.split(/[\\/]/).includes("node_modules")) return null;
25124
+ return linkedWorktreeRootOf(codePath);
25125
+ }
25126
+ function schemaWriteRefusal(dbPath, options = {}) {
25127
+ const env = options.env ?? overrides?.env ?? process.env;
25128
+ const buildWorktree = devBuildWorktree(options);
25129
+ if (buildWorktree === null) return null;
25130
+ const store = realOrResolved(dbPath);
25131
+ if (isWithin(realOrResolved(buildWorktree), store)) return null;
25132
+ if (env["VITEST"]) return null;
25133
+ const honourTestSandbox = options.honourTestSandbox ?? overrides?.honourTestSandbox ?? true;
25134
+ if (honourTestSandbox && insideTestSandbox(store)) return null;
25135
+ if (env[ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV] === "1") return null;
25136
+ 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).`;
25137
+ }
25138
+ function decisionFor(dbPath) {
25139
+ const key = realOrResolved(dbPath);
25140
+ if (!decisions.has(key)) decisions.set(key, schemaWriteRefusal(key));
25141
+ return decisions.get(key) ?? null;
25142
+ }
25143
+ function isWorktreeBuildSchemaError(error) {
25144
+ return error instanceof Error && error.message.includes(E_WORKTREE_BUILD_SCHEMA);
25145
+ }
25146
+ function codes() {
25147
+ if (authorizerCodes) return authorizerCodes;
25148
+ const sqlite = createRequire(import.meta.url)("node:sqlite").constants;
25149
+ authorizerCodes = {
25150
+ sqlite,
25151
+ creates: /* @__PURE__ */ new Map([
25152
+ [sqlite.SQLITE_CREATE_TABLE, "table"],
25153
+ [sqlite.SQLITE_CREATE_VTABLE, "table"],
25154
+ [sqlite.SQLITE_CREATE_INDEX, "index"],
25155
+ [sqlite.SQLITE_CREATE_TRIGGER, "trigger"],
25156
+ [sqlite.SQLITE_CREATE_VIEW, "view"]
25157
+ ]),
25158
+ changes: /* @__PURE__ */ new Set([
25159
+ sqlite.SQLITE_ALTER_TABLE,
25160
+ sqlite.SQLITE_DROP_TABLE,
25161
+ sqlite.SQLITE_DROP_INDEX,
25162
+ sqlite.SQLITE_DROP_TRIGGER,
25163
+ sqlite.SQLITE_DROP_VIEW,
25164
+ sqlite.SQLITE_DROP_VTABLE
25165
+ ])
25166
+ };
25167
+ return authorizerCodes;
25168
+ }
25169
+ function attachRefusal(name2) {
25170
+ if (name2 === "" || name2 === ":memory:") return null;
25171
+ if (typeof name2 !== "string" || /^file:/i.test(name2) || name2.includes("?")) {
25172
+ return UNKNOWN_ATTACH_REFUSAL;
25173
+ }
25174
+ return decisionFor(name2);
25175
+ }
25176
+ function readSchemas(nativeDb) {
25177
+ const schemas = /* @__PURE__ */ new Map();
25178
+ const list = nativeDb.prepare("PRAGMA database_list").all();
25179
+ for (const { name: name2, file } of list) {
25180
+ if (name2 === "temp") continue;
25181
+ const rows = nativeDb.prepare(`SELECT type, name FROM "${name2.replaceAll('"', '""')}".sqlite_master`).all();
25182
+ schemas.set(name2.toLowerCase(), {
25183
+ refusal: file ? decisionFor(file) : null,
25184
+ // '' = in-memory
25185
+ objects: new Set(rows.map((r) => `${r.type}:${r.name}`))
25186
+ });
25187
+ }
25188
+ return schemas;
25189
+ }
25190
+ function guardActive() {
25191
+ const env = overrides?.env ?? process.env;
25192
+ if (env["VITEST"]) return false;
25193
+ if (overrides) return devBuildWorktree() !== null;
25194
+ if (processBuildWorktree === void 0) processBuildWorktree = devBuildWorktree();
25195
+ return processBuildWorktree !== null;
25196
+ }
25197
+ function installSchemaWriteGuard(nativeDb) {
25198
+ if (!guardActive()) return false;
25199
+ const location = nativeDb.location();
25200
+ const mainRefusal = location ? decisionFor(location) : null;
25201
+ if (typeof nativeDb.setAuthorizer !== "function") {
25202
+ if (mainRefusal) throw new WorktreeBuildSchemaError(mainRefusal);
25203
+ return false;
25204
+ }
25205
+ const state = {
25206
+ schemas: readSchemas(nativeDb),
25207
+ unmappedAttachRefusal: null,
25208
+ stale: false,
25209
+ lastDenied: null
25210
+ };
25211
+ guards.set(nativeDb, state);
25212
+ const { sqlite, creates, changes } = codes();
25213
+ nativeDb.setAuthorizer((action, arg1, arg2, dbName) => {
25214
+ if (action === sqlite.SQLITE_ATTACH) {
25215
+ const refusal2 = attachRefusal(arg1);
25216
+ if (refusal2 && !state.unmappedAttachRefusal) state.unmappedAttachRefusal = refusal2;
25217
+ return sqlite.SQLITE_OK;
25218
+ }
25219
+ if (action === sqlite.SQLITE_DETACH) {
25220
+ state.stale = true;
25221
+ return sqlite.SQLITE_OK;
25222
+ }
25223
+ const createType = creates.get(action);
25224
+ if (createType === void 0 && !changes.has(action)) return sqlite.SQLITE_OK;
25225
+ const schema = ((action === sqlite.SQLITE_ALTER_TABLE ? arg1 : dbName) ?? "main").toLowerCase();
25226
+ if (schema === "temp") return sqlite.SQLITE_OK;
25227
+ const mapped = state.schemas.get(schema);
25228
+ const policy = state.stale ? void 0 : mapped;
25229
+ const refusal = policy ? policy.refusal : (mapped?.refusal ?? null) || state.unmappedAttachRefusal;
25230
+ if (refusal === null) return sqlite.SQLITE_OK;
25231
+ if (createType !== void 0 && policy?.objects.has(`${createType}:${arg1}`)) {
25232
+ return sqlite.SQLITE_OK;
25233
+ }
25234
+ state.lastDenied = {
25235
+ what: createType !== void 0 ? `CREATE ${createType} ${schema}.${arg1}` : `schema change on ${schema}.${(action === sqlite.SQLITE_ALTER_TABLE ? arg2 : arg1) ?? ""}`,
25236
+ refusal
25237
+ };
25238
+ return sqlite.SQLITE_DENY;
25239
+ });
25240
+ return mainRefusal !== null;
25241
+ }
25242
+ function refreshSchemaWriteGuard(nativeDb) {
25243
+ const state = guards.get(nativeDb);
25244
+ if (!state) return;
25245
+ state.schemas = readSchemas(nativeDb);
25246
+ state.unmappedAttachRefusal = null;
25247
+ state.stale = false;
25248
+ }
25249
+ function explainSchemaWriteDenial(nativeDb, error) {
25250
+ if (!(error instanceof Error) || !/not authorized/i.test(error.message)) return error;
25251
+ const denied = guards.get(nativeDb)?.lastDenied;
25252
+ if (!denied) return error;
25253
+ return new WorktreeBuildSchemaError(`${denied.refusal} Denied: ${denied.what}.`);
25254
+ }
25255
+ function pendingMigrations(nativeDb, migrations) {
25256
+ const hasJournal = nativeDb.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = '__drizzle_migrations'").get();
25257
+ const applied = hasJournal ? new Set(
25258
+ nativeDb.prepare('SELECT hash FROM main."__drizzle_migrations"').all().map((row) => row.hash)
25259
+ ) : /* @__PURE__ */ new Set();
25260
+ return migrations.filter((m) => !applied.has(m.hash)).map((m) => m.name ?? m.hash);
25261
+ }
25262
+ function assertNoPendingMigrationsForWorktreeBuild(nativeDb, migrations) {
25263
+ const dbPath = nativeDb.location();
25264
+ if (!dbPath) return;
25265
+ const refusal = decisionFor(dbPath);
25266
+ if (refusal === null) return;
25267
+ const pending = pendingMigrations(nativeDb, migrations);
25268
+ if (pending.length === 0) return;
25269
+ throw new WorktreeBuildSchemaError(`${refusal} Pending migrations: ${pending.join(", ")}.`);
25270
+ }
25271
+ var ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV, TEST_SANDBOX_MARKER, E_WORKTREE_BUILD_SCHEMA, overrides, decisions, WorktreeBuildSchemaError, authorizerCodes, guards, UNKNOWN_ATTACH_REFUSAL, processBuildWorktree;
25272
+ var init_worktree_build_guard = __esm({
25273
+ "packages/core/src/store/worktree-build-guard.ts"() {
25274
+ "use strict";
25275
+ init_src();
25276
+ init_errors2();
25277
+ init_project_scope();
25278
+ ALLOW_WORKTREE_BUILD_MIGRATIONS_ENV = "CLEO_ALLOW_WORKTREE_BUILD_MIGRATIONS";
25279
+ TEST_SANDBOX_MARKER = ".cleo-test-sandbox";
25280
+ E_WORKTREE_BUILD_SCHEMA = "E_WORKTREE_BUILD_SCHEMA";
25281
+ overrides = null;
25282
+ decisions = /* @__PURE__ */ new Map();
25283
+ WorktreeBuildSchemaError = class extends CleoError {
25284
+ constructor(message) {
25285
+ super(8 /* CONFIG_ERROR */, `${E_WORKTREE_BUILD_SCHEMA}: ${message}`, {
25286
+ 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.`
25287
+ });
25288
+ }
25289
+ };
25290
+ guards = /* @__PURE__ */ new WeakMap();
25291
+ 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";
25292
+ }
25293
+ });
25294
+
24967
25295
  // packages/core/src/store/migration-manager.ts
24968
- import { copyFileSync, existsSync as existsSync4 } from "node:fs";
24969
- import { dirname as dirname3, join as join5 } from "node:path";
25296
+ import { copyFileSync, existsSync as existsSync5 } from "node:fs";
25297
+ import { dirname as dirname4, join as join6 } from "node:path";
24970
25298
  function stripSqlComments(sql32) {
24971
25299
  return sql32.replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
24972
25300
  }
@@ -25005,10 +25333,10 @@ function computeEliminatedTables(migrations) {
25005
25333
  return eliminated;
25006
25334
  }
25007
25335
  function resolveConsolidationCutoverPrefix(migrationsFolder) {
25008
- const parent = dirname3(migrationsFolder);
25336
+ const parent = dirname4(migrationsFolder);
25009
25337
  for (const setName of ["drizzle-cleo-project", "drizzle-cleo-global"]) {
25010
- const folder = join5(parent, setName);
25011
- if (!existsSync4(folder)) continue;
25338
+ const folder = join6(parent, setName);
25339
+ if (!existsSync5(folder)) continue;
25012
25340
  try {
25013
25341
  const consolidation = readMigrationFiles({ migrationsFolder: folder }).find(
25014
25342
  (m) => /-consolidation-cleo-/.test(m.name ?? "")
@@ -25032,7 +25360,7 @@ function tableExists(nativeDb, tableName) {
25032
25360
  }
25033
25361
  function createSafetyBackup(dbPath) {
25034
25362
  const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
25035
- if (!existsSync4(backupPath)) {
25363
+ if (!existsSync5(backupPath)) {
25036
25364
  try {
25037
25365
  copyFileSync(dbPath, backupPath);
25038
25366
  } catch {
@@ -25150,6 +25478,16 @@ function readSiblingMigrationHashes(siblingFolder) {
25150
25478
  return /* @__PURE__ */ new Set();
25151
25479
  }
25152
25480
  }
25481
+ function readSiblingNewestMillis(siblingFolder) {
25482
+ try {
25483
+ return Math.max(
25484
+ 0,
25485
+ ...readMigrationFiles({ migrationsFolder: siblingFolder }).map((m) => m.folderMillis)
25486
+ );
25487
+ } catch {
25488
+ return 0;
25489
+ }
25490
+ }
25153
25491
  function ensureJournalHashUnique(nativeDb) {
25154
25492
  if (!tableExists(nativeDb, "__drizzle_migrations")) return;
25155
25493
  try {
@@ -25198,6 +25536,7 @@ function upgradeSharedJournalFormat(nativeDb, lineageFolders) {
25198
25536
  return { named, unnamed: rows.length - named };
25199
25537
  }
25200
25538
  function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsystem, siblingMigrationsFolders = []) {
25539
+ assertNoPendingMigrationsForWorktreeBuild(nativeDb, readMigrationFiles({ migrationsFolder }));
25201
25540
  const eliminatedTables = computeEliminatedTables(readMigrationFiles({ migrationsFolder }));
25202
25541
  const cutoverPrefix = resolveConsolidationCutoverPrefix(migrationsFolder);
25203
25542
  if (siblingMigrationsFolders.length > 0)
@@ -25229,8 +25568,15 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25229
25568
  knownHashes.add(m);
25230
25569
  }
25231
25570
  }
25232
- const dbEntries = nativeDb.prepare('SELECT id, hash FROM "__drizzle_migrations"').all();
25233
- const orphanedEntries = dbEntries.filter((e) => !knownHashes.has(e.hash));
25571
+ const newestKnownMillis = Math.max(
25572
+ 0,
25573
+ ...localMigrations.map((m) => m.folderMillis),
25574
+ ...siblingMigrationsFolders.filter((folder) => folder !== migrationsFolder).map(readSiblingNewestMillis)
25575
+ );
25576
+ const dbEntries = nativeDb.prepare('SELECT id, hash, created_at FROM "__drizzle_migrations"').all();
25577
+ const orphanedEntries = dbEntries.filter(
25578
+ (e) => !knownHashes.has(e.hash) && !(Number(e.created_at) > newestKnownMillis)
25579
+ );
25234
25580
  const hasOrphanedEntries = orphanedEntries.length > 0;
25235
25581
  if (hasOrphanedEntries) {
25236
25582
  const dbHashes = new Set(dbEntries.map((e) => e.hash));
@@ -25472,6 +25818,8 @@ function sanitizeMigrationStatements(migrations) {
25472
25818
  }
25473
25819
  function migrateSanitized(db, config) {
25474
25820
  const raw = readMigrationFiles(config);
25821
+ const client = db.$client;
25822
+ if (client) assertNoPendingMigrationsForWorktreeBuild(client, raw);
25475
25823
  const sanitized = sanitizeMigrationStatements(raw);
25476
25824
  migrateSync(sanitized, db._.session, config);
25477
25825
  }
@@ -25535,6 +25883,7 @@ var init_migration_manager = __esm({
25535
25883
  init_sqlite_core();
25536
25884
  init_logger2();
25537
25885
  init_with_retry();
25886
+ init_worktree_build_guard();
25538
25887
  MAX_MIGRATION_RETRIES = 5;
25539
25888
  MIGRATION_RETRY_BASE_DELAY_MS = 100;
25540
25889
  MIGRATION_RETRY_MAX_DELAY_MS = 2e3;
@@ -25544,13 +25893,13 @@ var init_migration_manager = __esm({
25544
25893
  });
25545
25894
 
25546
25895
  // packages/core/src/store/relocated-store-guard.ts
25547
- import { existsSync as existsSync5, realpathSync as realpathSync3 } from "node:fs";
25548
- import { createRequire } from "node:module";
25549
- import { basename as basename3, dirname as dirname4 } from "node:path";
25896
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
25897
+ import { createRequire as createRequire2 } from "node:module";
25898
+ import { basename as basename3, dirname as dirname5 } from "node:path";
25550
25899
  import { readDeclaredProjectIdentity as readDeclaredProjectIdentity2, readPortableProjectId } from "@cleocode/paths";
25551
25900
  function real2(p) {
25552
25901
  try {
25553
- return realpathSync3(p);
25902
+ return realpathSync4(p);
25554
25903
  } catch {
25555
25904
  return p;
25556
25905
  }
@@ -25567,7 +25916,7 @@ function liveElsewhere(globalDbPath, projectId, root) {
25567
25916
  "SELECT project_path AS projectPath FROM nexus_project_registry WHERE project_id = ?"
25568
25917
  ).get(projectId);
25569
25918
  const live = row?.projectPath;
25570
- if (!live || paths.has(live) || !existsSync5(live)) return null;
25919
+ if (!live || paths.has(live) || !existsSync6(live)) return null;
25571
25920
  if (!isStrictlyInsideDir(root, live)) return null;
25572
25921
  return readDeclaredProjectIdentity2(live)?.projectId === projectId ? live : null;
25573
25922
  } catch {
@@ -25581,14 +25930,14 @@ function detectRelocatedRoot(root, globalDbPath) {
25581
25930
  if (tombstone)
25582
25931
  return { projectId: tombstone.projectId, movedTo: tombstone.movedTo, via: "tombstone" };
25583
25932
  const declared = readPortableProjectId(root);
25584
- if (declared.status !== "valid" || !existsSync5(globalDbPath)) return null;
25933
+ if (declared.status !== "valid" || !existsSync6(globalDbPath)) return null;
25585
25934
  const movedTo = liveElsewhere(globalDbPath, declared.projectId, root);
25586
25935
  return movedTo ? { projectId: declared.projectId, movedTo, via: "registry" } : null;
25587
25936
  }
25588
25937
  function assertStoreNotRelocated(dbPath, globalDbPath) {
25589
- if (basename3(dbPath) !== "cleo.db" || basename3(dirname4(dbPath)) !== ".cleo") return;
25590
- if (existsSync5(dbPath) || globalDbPath === dbPath) return;
25591
- const root = dirname4(dirname4(dbPath));
25938
+ if (basename3(dbPath) !== "cleo.db" || basename3(dirname5(dbPath)) !== ".cleo") return;
25939
+ if (existsSync6(dbPath) || globalDbPath === dbPath) return;
25940
+ const root = dirname5(dirname5(dbPath));
25592
25941
  if (_adopted.has(root)) return;
25593
25942
  const moved = detectRelocatedRoot(root, globalDbPath);
25594
25943
  if (moved) throw projectMovedError(root, moved, void 0, moved.via);
@@ -25598,17 +25947,17 @@ var init_relocated_store_guard = __esm({
25598
25947
  "packages/core/src/store/relocated-store-guard.ts"() {
25599
25948
  "use strict";
25600
25949
  init_project_tombstone();
25601
- _require = createRequire(import.meta.url);
25950
+ _require = createRequire2(import.meta.url);
25602
25951
  _adopted = /* @__PURE__ */ new Set();
25603
25952
  }
25604
25953
  });
25605
25954
 
25606
25955
  // packages/core/src/store/resolve-migrations-folder.ts
25607
- import { createRequire as createRequire2 } from "node:module";
25608
- import { dirname as dirname5, join as join6 } from "node:path";
25609
- import { fileURLToPath } from "node:url";
25956
+ import { createRequire as createRequire3 } from "node:module";
25957
+ import { dirname as dirname6, join as join7 } from "node:path";
25958
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
25610
25959
  function coreRootFromEntry(entryPath) {
25611
- return dirname5(dirname5(entryPath));
25960
+ return dirname6(dirname6(entryPath));
25612
25961
  }
25613
25962
  function resolveConsolidatedJournalSiblings(ownSetName) {
25614
25963
  return CONSOLIDATED_JOURNAL_LINEAGES.filter((name2) => name2 !== ownSetName).map(
@@ -25618,14 +25967,14 @@ function resolveConsolidatedJournalSiblings(ownSetName) {
25618
25967
  function resolveCorePackageMigrationsFolder(setName) {
25619
25968
  try {
25620
25969
  const resolved = import.meta.resolve("@cleocode/core", import.meta.url);
25621
- const entryPath = fileURLToPath(resolved);
25622
- return join6(coreRootFromEntry(entryPath), "migrations", setName);
25970
+ const entryPath = fileURLToPath2(resolved);
25971
+ return join7(coreRootFromEntry(entryPath), "migrations", setName);
25623
25972
  } catch {
25624
25973
  }
25625
- const _require7 = createRequire2(import.meta.url);
25974
+ const _require7 = createRequire3(import.meta.url);
25626
25975
  try {
25627
25976
  const entryPath = _require7.resolve("@cleocode/core");
25628
- return join6(coreRootFromEntry(entryPath), "migrations", setName);
25977
+ return join7(coreRootFromEntry(entryPath), "migrations", setName);
25629
25978
  } catch (err) {
25630
25979
  throw new Error(
25631
25980
  `resolveCorePackageMigrationsFolder("${setName}"): cannot locate @cleocode/core from "${import.meta.url}". Ensure @cleocode/core is installed (workspace or npm). Original error: ${err.message}`
@@ -25735,11 +26084,11 @@ var init_sqlite_pragmas = __esm({
25735
26084
  });
25736
26085
 
25737
26086
  // packages/core/src/store/worktree-isolation-guard.ts
25738
- import { basename as basename4, dirname as dirname6, join as join7 } from "node:path";
26087
+ import { basename as basename4, dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
25739
26088
  function assertStorePathIsNotWorktreeResident(role, dbPath) {
25740
- const cleoDir = dirname6(dbPath);
26089
+ const cleoDir = dirname7(dbPath);
25741
26090
  if (basename4(cleoDir) !== ".cleo") return;
25742
- const projectRoot = dirname6(cleoDir);
26091
+ const projectRoot = dirname7(cleoDir);
25743
26092
  if (!isGitLinkedCheckout(projectRoot)) return;
25744
26093
  if (process.env["CLEO_ALLOW_WORKTREE_DB_CREATE"] === "1") {
25745
26094
  process.stderr.write(
@@ -25748,9 +26097,10 @@ function assertStorePathIsNotWorktreeResident(role, dbPath) {
25748
26097
  );
25749
26098
  return;
25750
26099
  }
26100
+ const owner = describeWorktreeOwner(projectRoot);
25751
26101
  throw new CleoError(
25752
26102
  8 /* CONFIG_ERROR */,
25753
- `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.`,
26103
+ `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.`,
25754
26104
  {
25755
26105
  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.`
25756
26106
  }
@@ -25763,7 +26113,7 @@ function assertDbPathIsNotWorktreeResident(role, cwd) {
25763
26113
  } catch {
25764
26114
  return;
25765
26115
  }
25766
- assertStorePathIsNotWorktreeResident(role, join7(cleoDir, PROJECT_STORE_FILENAME2));
26116
+ assertStorePathIsNotWorktreeResident(role, join8(cleoDir, PROJECT_STORE_FILENAME2));
25767
26117
  }
25768
26118
  var PROJECT_STORE_FILENAME2;
25769
26119
  var init_worktree_isolation_guard = __esm({
@@ -25783,10 +26133,10 @@ __export(sqlite_native_exports, {
25783
26133
  getDbSyncConstructor: () => getDbSyncConstructor,
25784
26134
  openNativeDatabase: () => openNativeDatabase
25785
26135
  });
25786
- import { realpathSync as realpathSync4 } from "node:fs";
25787
- import { createRequire as createRequire3 } from "node:module";
26136
+ import { realpathSync as realpathSync5 } from "node:fs";
26137
+ import { createRequire as createRequire4 } from "node:module";
25788
26138
  import { tmpdir as tmpdir2 } from "node:os";
25789
- import { delimiter, dirname as dirname7, isAbsolute as isAbsolute3, join as join8, resolve as resolve2, sep as sep2 } from "node:path";
26139
+ import { delimiter, dirname as dirname8, isAbsolute as isAbsolute4, join as join9, resolve as resolve4, sep as sep3 } from "node:path";
25790
26140
  function getDbSyncConstructor() {
25791
26141
  if (_ctor === null) {
25792
26142
  const mod = _require2("node:sqlite");
@@ -25795,19 +26145,19 @@ function getDbSyncConstructor() {
25795
26145
  return _ctor;
25796
26146
  }
25797
26147
  function resolveAbsoluteSafe(p) {
25798
- const abs = isAbsolute3(p) ? p : resolve2(p);
26148
+ const abs = isAbsolute4(p) ? p : resolve4(p);
25799
26149
  try {
25800
- return realpathSync4(abs);
26150
+ return realpathSync5(abs);
25801
26151
  } catch {
25802
26152
  const missingParts = [];
25803
26153
  let cursor = abs;
25804
26154
  while (true) {
25805
- const parent = dirname7(cursor);
26155
+ const parent = dirname8(cursor);
25806
26156
  if (parent === cursor) return abs;
25807
- missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep2) ? 0 : 1)));
26157
+ missingParts.unshift(cursor.slice(parent.length + (parent.endsWith(sep3) ? 0 : 1)));
25808
26158
  cursor = parent;
25809
26159
  try {
25810
- return join8(realpathSync4(cursor), ...missingParts);
26160
+ return join9(realpathSync5(cursor), ...missingParts);
25811
26161
  } catch {
25812
26162
  }
25813
26163
  }
@@ -25815,7 +26165,7 @@ function resolveAbsoluteSafe(p) {
25815
26165
  }
25816
26166
  function isPathUnder(child, parent) {
25817
26167
  if (child === parent) return true;
25818
- const withSep = parent.endsWith(sep2) ? parent : parent + sep2;
26168
+ const withSep = parent.endsWith(sep3) ? parent : parent + sep3;
25819
26169
  return child.startsWith(withSep);
25820
26170
  }
25821
26171
  function assertVitestSafePath(path2) {
@@ -25838,6 +26188,7 @@ function openNativeDatabase(path2, options) {
25838
26188
  assertVitestSafePath(path2);
25839
26189
  const DatabaseSyncCtor = getDbSyncConstructor();
25840
26190
  const db = new DatabaseSyncCtor(path2, {
26191
+ // schema-guard-exempt: the native chokepoint; every writable caller installs the guard
25841
26192
  enableForeignKeyConstraints: true,
25842
26193
  readOnly: options?.readonly ?? false,
25843
26194
  // Default handle-open lock timeout mirrors the SSoT busy_timeout
@@ -25889,7 +26240,7 @@ var init_sqlite_native = __esm({
25889
26240
  "packages/core/src/store/sqlite-native.ts"() {
25890
26241
  "use strict";
25891
26242
  init_sqlite_pragmas();
25892
- _require2 = createRequire3(import.meta.url);
26243
+ _require2 = createRequire4(import.meta.url);
25893
26244
  _ctor = null;
25894
26245
  }
25895
26246
  });
@@ -25963,7 +26314,7 @@ var init_writer_lease_schema = __esm({
25963
26314
  // packages/core/src/store/writer-lease.ts
25964
26315
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
25965
26316
  import { randomUUID } from "node:crypto";
25966
- import { realpathSync as realpathSync5, statSync as statSync2 } from "node:fs";
26317
+ import { realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
25967
26318
  import { resolve as resolvePath } from "node:path";
25968
26319
  function log() {
25969
26320
  if (_log === null) _log = getLogger("writer-lease");
@@ -26053,7 +26404,7 @@ function resolveDbIdentity(db) {
26053
26404
  return identity;
26054
26405
  }
26055
26406
  function sleepAsync(ms) {
26056
- return new Promise((resolve14) => setTimeout(resolve14, Math.max(0, Math.round(ms))));
26407
+ return new Promise((resolve16) => setTimeout(resolve16, Math.max(0, Math.round(ms))));
26057
26408
  }
26058
26409
  function isPidAlive(pid) {
26059
26410
  try {
@@ -26392,7 +26743,7 @@ function assertColdOpenFile(frame) {
26392
26743
  async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
26393
26744
  opts.execution?.assertActive();
26394
26745
  const captured = opts.requiredIdentity;
26395
- const path2 = realpathSync5(captured.dbPath);
26746
+ const path2 = realpathSync6(captured.dbPath);
26396
26747
  const identity = statSync2(path2, { bigint: true });
26397
26748
  if (captured.scope !== scope || captured.fileDevice !== String(identity.dev) || captured.fileInode !== String(identity.ino)) {
26398
26749
  throw new LeaseUnavailableError(
@@ -26425,6 +26776,7 @@ async function withRequiredColdOpenLease(scope, nativeDb, fn, opts) {
26425
26776
  }
26426
26777
  const remaining = opts.execution ? Math.max(1, opts.execution.deadlineAt - Date.now()) : ACQUIRE_DEADLINE_MS;
26427
26778
  const owned = openNativeDatabase(path2, { timeout: Math.min(ACQUIRE_DEADLINE_MS, remaining) });
26779
+ installSchemaWriteGuard(owned);
26428
26780
  try {
26429
26781
  opts.execution?.assertActive();
26430
26782
  const afterOpen = statSync2(path2, { bigint: true });
@@ -26618,6 +26970,7 @@ var init_writer_lease = __esm({
26618
26970
  init_background_ops();
26619
26971
  init_dual_scope_db();
26620
26972
  init_sqlite_native();
26973
+ init_worktree_build_guard();
26621
26974
  init_writer_lease_schema();
26622
26975
  DEFAULT_TTL_MS = 3e4;
26623
26976
  DEFAULT_PRIORITY = 100;
@@ -27160,10 +27513,10 @@ var init_monitor = __esm({
27160
27513
 
27161
27514
  // packages/core/src/resources/supervisor-admit.ts
27162
27515
  import { connect } from "node:net";
27163
- import { join as join9 } from "node:path";
27516
+ import { join as join10 } from "node:path";
27164
27517
  import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
27165
27518
  function resolveSupervisorSocketPath() {
27166
- return process.env.CLEO_SUPERVISOR_SOCKET ?? join9(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
27519
+ return process.env.CLEO_SUPERVISOR_SOCKET ?? join10(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
27167
27520
  }
27168
27521
  async function sendResourceAdmit(socketPath, cls, holderId, budget) {
27169
27522
  const result = await sendLeaseRequest(
@@ -27186,7 +27539,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
27186
27539
  return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
27187
27540
  }
27188
27541
  function sendLeaseRequest(socketPath, request, expectedKind) {
27189
- return new Promise((resolve14) => {
27542
+ return new Promise((resolve16) => {
27190
27543
  const id = `ra-${process.pid}-${request.kind}`;
27191
27544
  const envelope = LeaseIpcRequestEnvelopeSchema.parse({
27192
27545
  protocol_version: LEASE_IPC_PROTOCOL_VERSION,
@@ -27204,7 +27557,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
27204
27557
  settled = true;
27205
27558
  socket.removeAllListeners();
27206
27559
  socket.destroy();
27207
- resolve14(value);
27560
+ resolve16(value);
27208
27561
  };
27209
27562
  const degrade = (reason) => done({ unavailable: true, reason });
27210
27563
  socket.setTimeout(REQUEST_TIMEOUT_MS);
@@ -27275,9 +27628,9 @@ __export(governor_exports, {
27275
27628
  resolveGovernorMode: () => resolveGovernorMode,
27276
27629
  slotFileCount: () => slotFileCount
27277
27630
  });
27278
- import { existsSync as existsSync6, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
27631
+ import { existsSync as existsSync7, mkdirSync, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
27279
27632
  import { availableParallelism, totalmem } from "node:os";
27280
- import { join as join10 } from "node:path";
27633
+ import { join as join11 } from "node:path";
27281
27634
  import lockfile from "proper-lockfile";
27282
27635
  function log2() {
27283
27636
  if (_log2 === null) _log2 = getLogger("resource-governor");
@@ -27346,14 +27699,14 @@ function clamp(lo, v, hi) {
27346
27699
  return Math.max(lo, Math.min(v, hi));
27347
27700
  }
27348
27701
  function governorSlotDir(cls) {
27349
- return join10(getCleoHome(), "locks", `resource-${cls}`);
27702
+ return join11(getCleoHome(), "locks", `resource-${cls}`);
27350
27703
  }
27351
27704
  function ensureSlotFiles(dir, count) {
27352
- if (!existsSync6(dir)) mkdirSync(dir, { recursive: true });
27705
+ if (!existsSync7(dir)) mkdirSync(dir, { recursive: true });
27353
27706
  const paths = [];
27354
27707
  for (let i = 0; i < count; i++) {
27355
- const p = join10(dir, `slot-${i}.lock`);
27356
- if (!existsSync6(p)) writeFileSync3(p, "", { flag: "a" });
27708
+ const p = join11(dir, `slot-${i}.lock`);
27709
+ if (!existsSync7(p)) writeFileSync3(p, "", { flag: "a" });
27357
27710
  paths.push(p);
27358
27711
  }
27359
27712
  return paths;
@@ -27393,7 +27746,7 @@ function shuffledIndices(n) {
27393
27746
  }
27394
27747
  async function countHeldSlots(cls, budget) {
27395
27748
  const dir = governorSlotDir(cls);
27396
- if (!existsSync6(dir)) return 0;
27749
+ if (!existsSync7(dir)) return 0;
27397
27750
  const slots = ensureSlotFiles(dir, budget);
27398
27751
  let held = 0;
27399
27752
  for (const path2 of slots) {
@@ -27408,7 +27761,7 @@ async function countHeldSlots(cls, budget) {
27408
27761
  }
27409
27762
  function slotFileCount(cls) {
27410
27763
  const dir = governorSlotDir(cls);
27411
- if (!existsSync6(dir)) return 0;
27764
+ if (!existsSync7(dir)) return 0;
27412
27765
  return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
27413
27766
  }
27414
27767
  var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
@@ -27608,11 +27961,11 @@ var init_lock = __esm({
27608
27961
 
27609
27962
  // packages/core/src/store/atomic.ts
27610
27963
  import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
27611
- import { dirname as dirname8 } from "node:path";
27964
+ import { dirname as dirname9 } from "node:path";
27612
27965
  import writeFileAtomic from "write-file-atomic";
27613
27966
  async function atomicWrite(filePath, data, options) {
27614
27967
  try {
27615
- await mkdir(dirname8(filePath), { recursive: true });
27968
+ await mkdir(dirname9(filePath), { recursive: true });
27616
27969
  await writeFileAtomic(filePath, data, {
27617
27970
  encoding: options?.encoding ?? "utf8",
27618
27971
  mode: options?.mode
@@ -27645,7 +27998,7 @@ var init_atomic = __esm({
27645
27998
 
27646
27999
  // packages/core/src/store/backup.ts
27647
28000
  import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
27648
- import { basename as basename5, join as join11 } from "node:path";
28001
+ import { basename as basename5, dirname as dirname10, join as join12 } from "node:path";
27649
28002
  async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
27650
28003
  try {
27651
28004
  await mkdir2(backupDir, { recursive: true });
@@ -27656,14 +28009,14 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
27656
28009
  throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
27657
28010
  }
27658
28011
  for (let i = maxBackups; i >= 1; i--) {
27659
- const current = join11(backupDir, `${fileName}.${i}`);
28012
+ const current = join12(backupDir, `${fileName}.${i}`);
27660
28013
  if (i === maxBackups) {
27661
28014
  try {
27662
28015
  await unlink2(current);
27663
28016
  } catch {
27664
28017
  }
27665
28018
  } else {
27666
- const next = join11(backupDir, `${fileName}.${i + 1}`);
28019
+ const next = join12(backupDir, `${fileName}.${i + 1}`);
27667
28020
  try {
27668
28021
  await stat2(current);
27669
28022
  await fsRename(current, next);
@@ -27671,7 +28024,7 @@ async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUP
27671
28024
  }
27672
28025
  }
27673
28026
  }
27674
- const backupPath = join11(backupDir, `${fileName}.1`);
28027
+ const backupPath = join12(backupDir, `${fileName}.1`);
27675
28028
  await copyFile(filePath, backupPath);
27676
28029
  return backupPath;
27677
28030
  } catch (err) {
@@ -27685,6 +28038,7 @@ var init_backup = __esm({
27685
28038
  "use strict";
27686
28039
  init_src();
27687
28040
  init_errors2();
28041
+ init_worktree_isolation_guard();
27688
28042
  DEFAULT_MAX_BACKUPS = 5;
27689
28043
  }
27690
28044
  });
@@ -27969,7 +28323,7 @@ __export(identity_exports, {
27969
28323
  import { execFile } from "node:child_process";
27970
28324
  import { createHash as createHash2 } from "node:crypto";
27971
28325
  import { readFile as readFile3 } from "node:fs/promises";
27972
- import { join as join12, resolve as resolve3 } from "node:path";
28326
+ import { join as join13, resolve as resolve5 } from "node:path";
27973
28327
  import { promisify } from "node:util";
27974
28328
  import { legacyProjectId } from "@cleocode/paths";
27975
28329
  import { legacyProjectId as legacyProjectId2 } from "@cleocode/paths";
@@ -27977,14 +28331,14 @@ async function findGitRoot(fromPath, execution) {
27977
28331
  execution?.assertActive();
27978
28332
  try {
27979
28333
  const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
27980
- cwd: resolve3(fromPath),
28334
+ cwd: resolve5(fromPath),
27981
28335
  signal: execution?.signal,
27982
28336
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
27983
28337
  killSignal: "SIGKILL",
27984
28338
  maxBuffer: 64 * 1024
27985
28339
  });
27986
28340
  execution?.assertActive();
27987
- return resolve3(stdout.trim());
28341
+ return resolve5(stdout.trim());
27988
28342
  } catch {
27989
28343
  execution?.assertActive();
27990
28344
  return null;
@@ -27994,7 +28348,7 @@ async function findGitRemoteUrl(fromPath, execution) {
27994
28348
  execution?.assertActive();
27995
28349
  try {
27996
28350
  const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
27997
- cwd: resolve3(fromPath),
28351
+ cwd: resolve5(fromPath),
27998
28352
  signal: execution?.signal,
27999
28353
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
28000
28354
  killSignal: "SIGKILL",
@@ -28024,7 +28378,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
28024
28378
  try {
28025
28379
  const args = ["--no-replace-objects", "rev-list", "--max-parents=0", "HEAD"];
28026
28380
  const { stdout } = await execFileAsync("git", args, {
28027
- cwd: resolve3(fromPath),
28381
+ cwd: resolve5(fromPath),
28028
28382
  signal: execution?.signal,
28029
28383
  timeout: execution ? Math.max(1, execution.remainingMs()) : void 0,
28030
28384
  killSignal: "SIGKILL",
@@ -28047,7 +28401,7 @@ async function collectCheckoutEvidence(fromPath, execution) {
28047
28401
  async function readProjectInfoName(repoRoot, execution) {
28048
28402
  execution?.assertActive();
28049
28403
  try {
28050
- const raw = await readFile3(join12(repoRoot, ".cleo", "project-info.json"), {
28404
+ const raw = await readFile3(join13(repoRoot, ".cleo", "project-info.json"), {
28051
28405
  encoding: "utf8",
28052
28406
  signal: execution?.signal
28053
28407
  });
@@ -28062,7 +28416,7 @@ async function readProjectInfoName(repoRoot, execution) {
28062
28416
  }
28063
28417
  async function projectPathFingerprint(repoPath, execution) {
28064
28418
  execution?.assertActive();
28065
- const realRepoPath = resolve3(repoPath);
28419
+ const realRepoPath = resolve5(repoPath);
28066
28420
  const results = await Promise.allSettled([
28067
28421
  findGitRoot(realRepoPath, execution),
28068
28422
  findGitRemoteUrl(realRepoPath, execution)
@@ -28086,9 +28440,9 @@ async function projectPathFingerprint(repoPath, execution) {
28086
28440
  }
28087
28441
  function computeLegacyAliases(repoPath, additionalPaths) {
28088
28442
  const aliases = /* @__PURE__ */ new Set();
28089
- aliases.add(legacyProjectId(resolve3(repoPath)));
28443
+ aliases.add(legacyProjectId(resolve5(repoPath)));
28090
28444
  for (const p of additionalPaths ?? []) {
28091
- aliases.add(legacyProjectId(resolve3(p)));
28445
+ aliases.add(legacyProjectId(resolve5(p)));
28092
28446
  }
28093
28447
  return [...aliases];
28094
28448
  }
@@ -28122,17 +28476,17 @@ var init_project_identity = __esm({
28122
28476
  });
28123
28477
 
28124
28478
  // packages/core/src/scaffold/ensure-config.ts
28125
- import { existsSync as existsSync7, readFileSync as readFileSync3 } from "node:fs";
28126
- import { basename as basename6, dirname as dirname9, join as join13, resolve as resolve4 } from "node:path";
28127
- import { fileURLToPath as fileURLToPath2 } from "node:url";
28479
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
28480
+ import { basename as basename6, dirname as dirname11, join as join14, resolve as resolve6 } from "node:path";
28481
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
28128
28482
  function getPackageRoot() {
28129
- const thisFile = fileURLToPath2(import.meta.url);
28130
- return resolve4(dirname9(thisFile), "..", "..");
28483
+ const thisFile = fileURLToPath3(import.meta.url);
28484
+ return resolve6(dirname11(thisFile), "..", "..");
28131
28485
  }
28132
28486
  function getCleoVersion() {
28133
28487
  try {
28134
- const pkgPath = join13(getPackageRoot(), "package.json");
28135
- const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
28488
+ const pkgPath = join14(getPackageRoot(), "package.json");
28489
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
28136
28490
  return pkg.version ?? "0.0.0";
28137
28491
  } catch {
28138
28492
  return "0.0.0";
@@ -28491,25 +28845,25 @@ var init_recovery = __esm({
28491
28845
  // packages/core/src/store/exodus/archive.ts
28492
28846
  import {
28493
28847
  copyFileSync as copyFileSync2,
28494
- existsSync as existsSync8,
28848
+ existsSync as existsSync9,
28495
28849
  mkdirSync as mkdirSync2,
28496
- readFileSync as readFileSync4,
28850
+ readFileSync as readFileSync5,
28497
28851
  renameSync as renameSync3,
28498
28852
  unlinkSync,
28499
28853
  writeFileSync as writeFileSync4
28500
28854
  } from "node:fs";
28501
- import { basename as basename7, dirname as dirname10, join as join14, resolve as resolve5 } from "node:path";
28855
+ import { basename as basename7, dirname as dirname12, join as join15, resolve as resolve7 } from "node:path";
28502
28856
  import { z as z26 } from "zod";
28503
28857
  function scopeBaseDir(scope, cwd, targetDbPath) {
28504
- if (targetDbPath !== void 0) return dirname10(targetDbPath);
28858
+ if (targetDbPath !== void 0) return dirname12(targetDbPath);
28505
28859
  return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
28506
28860
  }
28507
28861
  function exodusArchiveDir(scope, cwd, targetDbPath) {
28508
- return join14(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
28862
+ return join15(scopeBaseDir(scope, cwd, targetDbPath), ARCHIVE_DIR_NAME);
28509
28863
  }
28510
28864
  function exodusMarkerPath(scope, cwd, targetDbPath) {
28511
28865
  const marker = targetDbPath !== void 0 && basename7(targetDbPath) !== "cleo.db" ? `${basename7(targetDbPath)}.${MARKER_FILENAME_BY_SCOPE[scope]}` : MARKER_FILENAME_BY_SCOPE[scope];
28512
- return join14(scopeBaseDir(scope, cwd, targetDbPath), marker);
28866
+ return join15(scopeBaseDir(scope, cwd, targetDbPath), marker);
28513
28867
  }
28514
28868
  function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
28515
28869
  let markerPath;
@@ -28519,13 +28873,13 @@ function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
28519
28873
  if (targetDbPath) throw error;
28520
28874
  return false;
28521
28875
  }
28522
- if (!existsSync8(markerPath)) return false;
28523
- const marker = markerIdentity.parse(JSON.parse(readFileSync4(markerPath, "utf8")));
28876
+ if (!existsSync9(markerPath)) return false;
28877
+ const marker = markerIdentity.parse(JSON.parse(readFileSync5(markerPath, "utf8")));
28524
28878
  if (nativeDb && (!marker.databaseIdentity || !hasExodusDatabaseIdentity(nativeDb, marker.databaseIdentity)))
28525
28879
  throw new Error(
28526
28880
  "Exodus completion marker does not certify this database generation; assessment required"
28527
28881
  );
28528
- return marker.scope === scope && (!targetDbPath || !marker.targetDbPath || resolve5(marker.targetDbPath) === resolve5(targetDbPath));
28882
+ return marker.scope === scope && (!targetDbPath || !marker.targetDbPath || resolve7(marker.targetDbPath) === resolve7(targetDbPath));
28529
28883
  }
28530
28884
  function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, databaseIdentity) {
28531
28885
  const markerPath = exodusMarkerPath(scope, cwd, targetDbPath);
@@ -28537,7 +28891,7 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
28537
28891
  cleoVersion: getCleoVersion(),
28538
28892
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
28539
28893
  archivedSources: [...archivedSources],
28540
- targetDbPath: resolve5(targetDbPath ?? join14(baseDir, "cleo.db")),
28894
+ targetDbPath: resolve7(targetDbPath ?? join15(baseDir, "cleo.db")),
28541
28895
  ...databaseIdentity ? { databaseIdentity } : {}
28542
28896
  };
28543
28897
  const tmpPath = `${markerPath}.tmp`;
@@ -28548,10 +28902,10 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
28548
28902
  }
28549
28903
  function moveFileInto(srcPath, destDir) {
28550
28904
  mkdirSync2(destDir, { recursive: true });
28551
- let dest = join14(destDir, basename7(srcPath));
28552
- if (existsSync8(dest)) {
28905
+ let dest = join15(destDir, basename7(srcPath));
28906
+ if (existsSync9(dest)) {
28553
28907
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
28554
- dest = join14(destDir, `${basename7(srcPath)}.${stamp}`);
28908
+ dest = join15(destDir, `${basename7(srcPath)}.${stamp}`);
28555
28909
  }
28556
28910
  try {
28557
28911
  renameSync3(srcPath, dest);
@@ -28562,14 +28916,14 @@ function moveFileInto(srcPath, destDir) {
28562
28916
  return dest;
28563
28917
  }
28564
28918
  function archiveSourceDb(source, cwd, targetDbPath) {
28565
- if (!existsSync8(source.path)) {
28919
+ if (!existsSync9(source.path)) {
28566
28920
  return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
28567
28921
  }
28568
28922
  const destDir = exodusArchiveDir(source.targetScope, cwd, targetDbPath);
28569
28923
  const archivedTo = moveFileInto(source.path, destDir);
28570
28924
  for (const suffix of SIDECAR_SUFFIXES) {
28571
28925
  const sidecar = `${source.path}${suffix}`;
28572
- if (existsSync8(sidecar)) {
28926
+ if (existsSync9(sidecar)) {
28573
28927
  try {
28574
28928
  moveFileInto(sidecar, destDir);
28575
28929
  } catch (err) {
@@ -28617,7 +28971,7 @@ function detectStrandedResidue(sources, cwd) {
28617
28971
  const stranded = [];
28618
28972
  for (const source of sources) {
28619
28973
  if (!markedScopes.has(source.targetScope)) continue;
28620
- if (existsSync8(source.path)) {
28974
+ if (existsSync9(source.path)) {
28621
28975
  stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
28622
28976
  }
28623
28977
  }
@@ -28682,7 +29036,7 @@ __export(open_cleo_db_exports, {
28682
29036
  openCleoDbSnapshot: () => openCleoDbSnapshot,
28683
29037
  validateProjectIdConsistency: () => validateProjectIdConsistency
28684
29038
  });
28685
- import { createRequire as createRequire4 } from "node:module";
29039
+ import { createRequire as createRequire5 } from "node:module";
28686
29040
  function unwrapNativeSqliteDb(db) {
28687
29041
  if (db && typeof db === "object" && "$client" in db) {
28688
29042
  return db.$client ?? db;
@@ -28746,9 +29100,10 @@ async function openCleoDb(role, cwd) {
28746
29100
  }
28747
29101
  function openCleoDbSnapshot(path2, options = {}) {
28748
29102
  const { readOnly = true, applyPragmas = true } = options;
28749
- const _require7 = createRequire4(import.meta.url);
29103
+ const _require7 = createRequire5(import.meta.url);
28750
29104
  const { DatabaseSync: DatabaseSyncCtor } = _require7("node:sqlite");
28751
29105
  const db = new DatabaseSyncCtor(path2, { readOnly });
29106
+ if (!readOnly) installSchemaWriteGuard(db);
28752
29107
  if (applyPragmas) {
28753
29108
  applyPerfPragmas(db, { enableWal: !readOnly });
28754
29109
  }
@@ -28776,6 +29131,7 @@ var init_open_cleo_db = __esm({
28776
29131
  init_project_info();
28777
29132
  init_dual_scope_db();
28778
29133
  init_sqlite_pragmas();
29134
+ init_worktree_build_guard();
28779
29135
  init_worktree_isolation_guard();
28780
29136
  PROJECT_ID_TRACKING_ROLES = /* @__PURE__ */ new Set(["global"]);
28781
29137
  }
@@ -29115,7 +29471,7 @@ var init_table_name_map = __esm({
29115
29471
  });
29116
29472
 
29117
29473
  // packages/core/src/store/exodus/count-parity.ts
29118
- import { existsSync as existsSync9 } from "node:fs";
29474
+ import { existsSync as existsSync10 } from "node:fs";
29119
29475
  function listTables(db) {
29120
29476
  return db.prepare(
29121
29477
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
@@ -29136,14 +29492,14 @@ function rowCount(db, tableName) {
29136
29492
  function computeCountParity(sources, projectDbPath, globalDbPath) {
29137
29493
  const entries = [];
29138
29494
  let skipped = 0;
29139
- if (!existsSync9(projectDbPath) || !existsSync9(globalDbPath)) {
29495
+ if (!existsSync10(projectDbPath) || !existsSync10(globalDbPath)) {
29140
29496
  return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
29141
29497
  }
29142
29498
  const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
29143
29499
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
29144
29500
  try {
29145
29501
  for (const src of sources) {
29146
- if (!existsSync9(src.path)) continue;
29502
+ if (!existsSync10(src.path)) continue;
29147
29503
  const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
29148
29504
  try {
29149
29505
  for (const legacyTable of listTables(srcSnap.db)) {
@@ -29201,8 +29557,8 @@ var init_count_parity = __esm({
29201
29557
  });
29202
29558
 
29203
29559
  // packages/core/src/store/exodus/plan.ts
29204
- import { existsSync as existsSync10, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
29205
- import { join as join15 } from "node:path";
29560
+ import { existsSync as existsSync11, readdirSync as readdirSync3, statfsSync, statSync as statSync3 } from "node:fs";
29561
+ import { join as join16 } from "node:path";
29206
29562
  function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
29207
29563
  return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
29208
29564
  }
@@ -29213,33 +29569,33 @@ function buildSourceDescriptors(cwd) {
29213
29569
  // Project-tier — go into consolidated project-scope cleo.db
29214
29570
  {
29215
29571
  name: "tasks",
29216
- path: join15(cleoDir, "tasks.db"),
29572
+ path: join16(cleoDir, "tasks.db"),
29217
29573
  targetScope: "project"
29218
29574
  },
29219
29575
  {
29220
29576
  name: "brain (project)",
29221
- path: join15(cleoDir, "brain.db"),
29577
+ path: join16(cleoDir, "brain.db"),
29222
29578
  targetScope: "project"
29223
29579
  },
29224
29580
  {
29225
29581
  name: "conduit",
29226
- path: join15(cleoDir, "conduit.db"),
29582
+ path: join16(cleoDir, "conduit.db"),
29227
29583
  targetScope: "project"
29228
29584
  },
29229
29585
  // Global-tier — go into consolidated global-scope cleo.db
29230
29586
  {
29231
29587
  name: "nexus",
29232
- path: join15(cleoHome, "nexus.db"),
29588
+ path: join16(cleoHome, "nexus.db"),
29233
29589
  targetScope: "global"
29234
29590
  },
29235
29591
  {
29236
29592
  name: "signaldock",
29237
- path: join15(cleoHome, "signaldock.db"),
29593
+ path: join16(cleoHome, "signaldock.db"),
29238
29594
  targetScope: "global"
29239
29595
  },
29240
29596
  {
29241
29597
  name: "skills",
29242
- path: join15(cleoHome, "skills.db"),
29598
+ path: join16(cleoHome, "skills.db"),
29243
29599
  targetScope: "global"
29244
29600
  }
29245
29601
  ];
@@ -29268,7 +29624,7 @@ function findExistingStaging(cleoDir) {
29268
29624
  const entries = readdirSync3(cleoDir, { withFileTypes: true });
29269
29625
  const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
29270
29626
  if (stagingDirs.length > 0) {
29271
- return join15(cleoDir, stagingDirs[0]);
29627
+ return join16(cleoDir, stagingDirs[0]);
29272
29628
  }
29273
29629
  } catch {
29274
29630
  }
@@ -29284,7 +29640,7 @@ function buildExodusPlan(cwd) {
29284
29640
  const availableBytes = getAvailableBytes(cleoDir);
29285
29641
  const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
29286
29642
  const existingStaging = findExistingStaging(cleoDir);
29287
- const stagingDir = existingStaging ?? join15(cleoDir, deriveStagingDirName());
29643
+ const stagingDir = existingStaging ?? join16(cleoDir, deriveStagingDirName());
29288
29644
  const resumeFromStaging = existingStaging !== null;
29289
29645
  const projectDbPath = resolveDualScopeDbPath("project", cwd);
29290
29646
  const globalDbPath = resolveDualScopeDbPath("global");
@@ -29303,7 +29659,7 @@ function buildExodusPlan(cwd) {
29303
29659
  };
29304
29660
  }
29305
29661
  function sourcesPresent(sources) {
29306
- return sources.some((s) => existsSync10(s.path));
29662
+ return sources.some((s) => existsSync11(s.path));
29307
29663
  }
29308
29664
  var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
29309
29665
  var init_plan2 = __esm({
@@ -29317,18 +29673,18 @@ var init_plan2 = __esm({
29317
29673
  });
29318
29674
 
29319
29675
  // packages/core/src/store/exodus/health.ts
29320
- import { existsSync as existsSync11, statSync as statSync4 } from "node:fs";
29676
+ import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
29321
29677
  function buildExodusHealth(cwd) {
29322
29678
  const plan = buildExodusPlan(cwd);
29323
- const anyLegacyPresent = plan.sources.some((s) => existsSync11(s.path));
29679
+ const anyLegacyPresent = plan.sources.some((s) => existsSync12(s.path));
29324
29680
  const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
29325
29681
  const consolidatedExistsByScope = {
29326
- project: existsSync11(plan.projectDbPath),
29327
- global: existsSync11(plan.globalDbPath)
29682
+ project: existsSync12(plan.projectDbPath),
29683
+ global: existsSync12(plan.globalDbPath)
29328
29684
  };
29329
29685
  const buildScope = (scope) => {
29330
29686
  const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
29331
- const present = existsSync11(s.path);
29687
+ const present = existsSync12(s.path);
29332
29688
  let bytes = 0;
29333
29689
  if (present) {
29334
29690
  try {
@@ -29680,8 +30036,8 @@ var init_types = __esm({
29680
30036
  });
29681
30037
 
29682
30038
  // packages/core/src/store/backup-sidecar.ts
29683
- import { existsSync as existsSync12, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
29684
- import { join as join16 } from "node:path";
30039
+ import { existsSync as existsSync13, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
30040
+ import { join as join17 } from "node:path";
29685
30041
  function formatBackupTimestamp(d) {
29686
30042
  const pad = (n, len = 2) => String(n).padStart(len, "0");
29687
30043
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
@@ -29692,8 +30048,8 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29692
30048
  const ownedPattern = new RegExp(`\\.${escapedType}-`);
29693
30049
  const files = readdirSync4(backupDir).filter((f) => !f.endsWith(".meta.json") && !f.endsWith(".tmp") && ownedPattern.test(f)).map((f) => ({
29694
30050
  name: f,
29695
- path: join16(backupDir, f),
29696
- mtimeMs: statSync5(join16(backupDir, f)).mtimeMs
30051
+ path: join17(backupDir, f),
30052
+ mtimeMs: statSync5(join17(backupDir, f)).mtimeMs
29697
30053
  })).sort((a, b) => a.mtimeMs - b.mtimeMs);
29698
30054
  while (files.length > maxSnapshots) {
29699
30055
  const oldest = files.shift();
@@ -29701,7 +30057,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29701
30057
  try {
29702
30058
  unlinkSync2(oldest.path);
29703
30059
  const metaPath = `${oldest.path}.meta.json`;
29704
- if (existsSync12(metaPath)) unlinkSync2(metaPath);
30060
+ if (existsSync13(metaPath)) unlinkSync2(metaPath);
29705
30061
  } catch {
29706
30062
  }
29707
30063
  }
@@ -29709,7 +30065,7 @@ function rotateBackupDir(backupDir, maxSnapshots, backupType) {
29709
30065
  }
29710
30066
  }
29711
30067
  function writeBackupSidecar(backupDir, sidecar) {
29712
- const dest = join16(backupDir, `${sidecar.backupId}.meta.json`);
30068
+ const dest = join17(backupDir, `${sidecar.backupId}.meta.json`);
29713
30069
  const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
29714
30070
  writeFileSync5(tmp, JSON.stringify(sidecar, null, 2));
29715
30071
  renameSync4(tmp, dest);
@@ -29721,23 +30077,23 @@ var init_backup_sidecar = __esm({
29721
30077
  });
29722
30078
 
29723
30079
  // packages/core/src/store/pre-repair-snapshot.ts
29724
- import { existsSync as existsSync13, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
29725
- import { dirname as dirname11, join as join17 } from "node:path";
30080
+ import { existsSync as existsSync14, mkdirSync as mkdirSync3, statfsSync as statfsSync2 } from "node:fs";
30081
+ import { dirname as dirname13, join as join18 } from "node:path";
29726
30082
  function writePreRepairSnapshot(nativeDb, dbPath, label) {
29727
30083
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
29728
- const backupDir = join17(dirname11(dbPath), "backups");
30084
+ const backupDir = join18(dirname13(dbPath), "backups");
29729
30085
  mkdirSync3(backupDir, { recursive: true });
29730
- const snapshotPath = join17(backupDir, `cleo-pre-${label}-${stamp}.db`);
30086
+ const snapshotPath = join18(backupDir, `cleo-pre-${label}-${stamp}.db`);
29731
30087
  nativeDb.exec(`VACUUM INTO '${snapshotPath.replace(/'/g, "''")}'`);
29732
30088
  return snapshotPath;
29733
30089
  }
29734
30090
  function existingAncestor(path2) {
29735
30091
  let p = path2;
29736
- while (!existsSync13(p) && dirname11(p) !== p) p = dirname11(p);
30092
+ while (!existsSync14(p) && dirname13(p) !== p) p = dirname13(p);
29737
30093
  return p;
29738
30094
  }
29739
30095
  function planMigrationSnapshot(nativeDb, dbPath) {
29740
- const backupDir = join17(dirname11(dbPath), "backups", "sqlite");
30096
+ const backupDir = join18(dirname13(dbPath), "backups", "sqlite");
29741
30097
  const pragma = (name2) => Number(nativeDb.prepare(`PRAGMA main.${name2}`).get()[name2] ?? 0);
29742
30098
  const liveBytes = (pragma("page_count") - pragma("freelist_count")) * pragma("page_size");
29743
30099
  let availableBytes = null;
@@ -29749,13 +30105,13 @@ function planMigrationSnapshot(nativeDb, dbPath) {
29749
30105
  }
29750
30106
  const base = `migration-${formatBackupTimestamp(/* @__PURE__ */ new Date())}`;
29751
30107
  let backupId = base;
29752
- for (let n = 2; existsSync13(join17(backupDir, `${backupId}.meta.json`)); n++) {
30108
+ for (let n = 2; existsSync14(join18(backupDir, `${backupId}.meta.json`)); n++) {
29753
30109
  backupId = `${base}-${n}`;
29754
30110
  }
29755
30111
  return {
29756
30112
  backupDir,
29757
30113
  backupId,
29758
- snapshotPath: join17(backupDir, `cleo.db.${backupId}`),
30114
+ snapshotPath: join18(backupDir, `cleo.db.${backupId}`),
29759
30115
  requiredBytes: liveBytes + SNAPSHOT_HEADROOM_BYTES,
29760
30116
  availableBytes
29761
30117
  };
@@ -29995,7 +30351,7 @@ var init_legacy_tasks_lineage = __esm({
29995
30351
 
29996
30352
  // packages/core/src/store/ports/domain-binding.ts
29997
30353
  import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
29998
- import { resolve as resolve6 } from "node:path";
30354
+ import { resolve as resolve8 } from "node:path";
29999
30355
  function getCleoRuntime() {
30000
30356
  if (!_runtime) {
30001
30357
  _runtime = createCleoRuntime();
@@ -30063,6 +30419,8 @@ async function bindAgainst(key, store, establish) {
30063
30419
  () => establish(native, store)
30064
30420
  );
30065
30421
  return { store, native, db };
30422
+ } catch (error) {
30423
+ throw explainSchemaWriteDenial(native, error);
30066
30424
  } finally {
30067
30425
  membership.active = false;
30068
30426
  }
@@ -30112,7 +30470,7 @@ async function bindLive(scope, key, dbPath, openStore, establish) {
30112
30470
  );
30113
30471
  }
30114
30472
  async function bindProjectDomain(domain, cwd, establish) {
30115
- const dbPath = resolve6(resolveDualScopeDbPath("project", cwd));
30473
+ const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
30116
30474
  const row = await bindLive(
30117
30475
  "project",
30118
30476
  bindingKey("project", dbPath, domain),
@@ -30123,7 +30481,7 @@ async function bindProjectDomain(domain, cwd, establish) {
30123
30481
  return row;
30124
30482
  }
30125
30483
  async function bindGlobalDomain(domain, establish, cwd) {
30126
- const dbPath = resolve6(resolveDualScopeDbPath("global"));
30484
+ const dbPath = resolve8(resolveDualScopeDbPath("global"));
30127
30485
  const row = await bindLive(
30128
30486
  "global",
30129
30487
  bindingKey("global", dbPath, domain),
@@ -30134,7 +30492,7 @@ async function bindGlobalDomain(domain, establish, cwd) {
30134
30492
  return row;
30135
30493
  }
30136
30494
  async function bindGlobalDomainAtPath(domain, dbPath, establish) {
30137
- const normalized = resolve6(dbPath);
30495
+ const normalized = resolve8(dbPath);
30138
30496
  const row = await bindLive(
30139
30497
  "global",
30140
30498
  bindingKey("global", normalized, domain),
@@ -30145,7 +30503,7 @@ async function bindGlobalDomainAtPath(domain, dbPath, establish) {
30145
30503
  return row;
30146
30504
  }
30147
30505
  function peekDomainAtPath(scope, dbPath, domain) {
30148
- const row = _bindings.get(bindingKey(scope, resolve6(dbPath), domain));
30506
+ const row = _bindings.get(bindingKey(scope, resolve8(dbPath), domain));
30149
30507
  if (!row?.native.isOpen) return null;
30150
30508
  return row;
30151
30509
  }
@@ -30154,12 +30512,12 @@ function releaseDomainBindings(filter) {
30154
30512
  _bindings.clear();
30155
30513
  return;
30156
30514
  }
30157
- const wantPath = filter.dbPath === void 0 ? void 0 : resolve6(filter.dbPath);
30515
+ const wantPath = filter.dbPath === void 0 ? void 0 : resolve8(filter.dbPath);
30158
30516
  for (const key of [..._bindings.keys()]) {
30159
- const sep5 = key.indexOf("::");
30517
+ const sep6 = key.indexOf("::");
30160
30518
  const lastSep = key.lastIndexOf("::");
30161
- const scope = key.slice(0, sep5);
30162
- const dbPath = key.slice(sep5 + 2, lastSep);
30519
+ const scope = key.slice(0, sep6);
30520
+ const dbPath = key.slice(sep6 + 2, lastSep);
30163
30521
  const domain = key.slice(lastSep + 2);
30164
30522
  if (filter.scope !== void 0 && scope !== filter.scope) continue;
30165
30523
  if (wantPath !== void 0 && dbPath !== wantPath) continue;
@@ -30174,7 +30532,7 @@ function boundProjectNative(domain, cwd) {
30174
30532
  return peekProjectDomain(domain, cwd)?.native ?? null;
30175
30533
  }
30176
30534
  function peekProjectDomain(domain, cwd) {
30177
- const dbPath = resolve6(resolveDualScopeDbPath("project", cwd));
30535
+ const dbPath = resolve8(resolveDualScopeDbPath("project", cwd));
30178
30536
  const row = _bindings.get(bindingKey("project", dbPath, domain));
30179
30537
  if (row?.native.isOpen) return row;
30180
30538
  if (cwd !== void 0) return null;
@@ -30189,7 +30547,7 @@ function peekProjectDomain(domain, cwd) {
30189
30547
  return sole ?? null;
30190
30548
  }
30191
30549
  function peekGlobalDomain(domain) {
30192
- const dbPath = resolve6(resolveDualScopeDbPath("global"));
30550
+ const dbPath = resolve8(resolveDualScopeDbPath("global"));
30193
30551
  const row = _bindings.get(bindingKey("global", dbPath, domain));
30194
30552
  if (!row || !row.native.isOpen) return null;
30195
30553
  return row;
@@ -30200,6 +30558,7 @@ var init_domain_binding = __esm({
30200
30558
  "use strict";
30201
30559
  init_project_scope();
30202
30560
  init_dual_scope_db();
30561
+ init_worktree_build_guard();
30203
30562
  _runtime = null;
30204
30563
  _bindings = /* @__PURE__ */ new Map();
30205
30564
  _inflight = /* @__PURE__ */ new Map();
@@ -30210,9 +30569,9 @@ var init_domain_binding = __esm({
30210
30569
 
30211
30570
  // packages/core/src/telemetry/sqlite.ts
30212
30571
  import { mkdirSync as mkdirSync4 } from "node:fs";
30213
- import { dirname as dirname12, join as join18 } from "node:path";
30572
+ import { dirname as dirname14, join as join19 } from "node:path";
30214
30573
  function getTelemetryDbPath() {
30215
- return join18(getCleoHome(), DB_FILENAME);
30574
+ return join19(getCleoHome(), DB_FILENAME);
30216
30575
  }
30217
30576
  function resolveTelemetryMigrationsFolder() {
30218
30577
  return resolveCorePackageMigrationsFolder("drizzle-telemetry");
@@ -30260,8 +30619,9 @@ async function getTelemetryDb() {
30260
30619
  _initPromise = (async () => {
30261
30620
  const dbPath = requestedPath;
30262
30621
  _dbPath = dbPath;
30263
- mkdirSync4(dirname12(dbPath), { recursive: true });
30622
+ mkdirSync4(dirname14(dbPath), { recursive: true });
30264
30623
  const nativeDb = openNativeDatabase(dbPath);
30624
+ installSchemaWriteGuard(nativeDb);
30265
30625
  _nativeDb = nativeDb;
30266
30626
  const db = drizzle({ client: nativeDb });
30267
30627
  runTelemetryMigrations(nativeDb, db);
@@ -30282,6 +30642,7 @@ var init_sqlite2 = __esm({
30282
30642
  init_migration_manager();
30283
30643
  init_resolve_migrations_folder();
30284
30644
  init_sqlite3();
30645
+ init_worktree_build_guard();
30285
30646
  DB_FILENAME = "telemetry.db";
30286
30647
  TELEMETRY_SCHEMA_VERSION = "1.0.0";
30287
30648
  _db = null;
@@ -30292,11 +30653,11 @@ var init_sqlite2 = __esm({
30292
30653
  });
30293
30654
 
30294
30655
  // packages/core/src/store/agent-registry-store.ts
30295
- import { existsSync as existsSync14 } from "node:fs";
30296
- import { join as join19 } from "node:path";
30656
+ import { existsSync as existsSync15 } from "node:fs";
30657
+ import { join as join20 } from "node:path";
30297
30658
  function getGlobalAgentRegistryDbPath() {
30298
30659
  const cleoHome = getCleoHome();
30299
- const dbPath = join19(cleoHome, "cleo.db");
30660
+ const dbPath = join20(cleoHome, "cleo.db");
30300
30661
  if (!dbPath.startsWith(cleoHome)) {
30301
30662
  throw new Error(
30302
30663
  `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.`
@@ -30363,7 +30724,7 @@ function establishAgentRegistrySchema(native) {
30363
30724
  }
30364
30725
  async function ensureGlobalAgentRegistryDb() {
30365
30726
  const dbPath = getGlobalAgentRegistryDbPath();
30366
- const alreadyExists = existsSync14(dbPath);
30727
+ const alreadyExists = existsSync15(dbPath);
30367
30728
  let created = false;
30368
30729
  const { native: nativeDb } = await bindGlobalDomainAtPath(
30369
30730
  AGENT_REGISTRY_DOMAIN,
@@ -30408,8 +30769,8 @@ var init_agent_registry_store = __esm({
30408
30769
  });
30409
30770
 
30410
30771
  // packages/core/src/store/conduit-sqlite.ts
30411
- import { existsSync as existsSync15 } from "node:fs";
30412
- import { createRequire as createRequire5 } from "node:module";
30772
+ import { existsSync as existsSync16 } from "node:fs";
30773
+ import { createRequire as createRequire6 } from "node:module";
30413
30774
  function _getDrizzle() {
30414
30775
  if (_drizzle === null) {
30415
30776
  const mod = _require3("drizzle-orm/node-sqlite");
@@ -30437,7 +30798,7 @@ function runConduitMigrations(nativeDb) {
30437
30798
  }
30438
30799
  async function ensureConduitDb(projectRoot) {
30439
30800
  const dbPath = getConduitDbPath(projectRoot);
30440
- const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync15(dbPath);
30801
+ const alreadyExists = peekProjectDomain("conduit", projectRoot) !== null || existsSync16(dbPath);
30441
30802
  await bindConduitDomain(projectRoot);
30442
30803
  return { action: alreadyExists ? "exists" : "created", path: dbPath };
30443
30804
  }
@@ -30463,7 +30824,8 @@ var init_conduit_sqlite = __esm({
30463
30824
  init_domain_binding();
30464
30825
  init_resolve_migrations_folder();
30465
30826
  init_sqlite_pragmas();
30466
- _require3 = createRequire5(import.meta.url);
30827
+ init_worktree_build_guard();
30828
+ _require3 = createRequire6(import.meta.url);
30467
30829
  ({ DatabaseSync: DatabaseSync2 } = _require3("node:sqlite"));
30468
30830
  _drizzle = null;
30469
30831
  CONDUIT_SCHEMA_VERSION = "2026.4.23";
@@ -32337,216 +32699,6 @@ var init_memory_schema = __esm({
32337
32699
  }
32338
32700
  });
32339
32701
 
32340
- // packages/core/src/store/snapshot-gate.ts
32341
- import { join as join20 } from "node:path";
32342
- function readGateState(db) {
32343
- const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
32344
- const state = { generation: 0, prefixes: {} };
32345
- if (!row) return state;
32346
- try {
32347
- const parsed = JSON.parse(row.value);
32348
- if (parsed === null || typeof parsed !== "object") return state;
32349
- if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
32350
- state.generation = parsed.generation;
32351
- }
32352
- for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
32353
- if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
32354
- state.prefixes[prefix] = {
32355
- generation: e.generation,
32356
- startedAt: e.startedAt,
32357
- completedAt: e.completedAt
32358
- };
32359
- }
32360
- }
32361
- } catch {
32362
- }
32363
- return state;
32364
- }
32365
- function writeGateState(db, state) {
32366
- db.prepare(
32367
- "INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
32368
- ).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
32369
- }
32370
- function tryReadGateState(db) {
32371
- if (!db) return null;
32372
- try {
32373
- return readGateState(db);
32374
- } catch {
32375
- return null;
32376
- }
32377
- }
32378
- function needsSnapshot(entry, mode, nowMs, seenGeneration) {
32379
- if (!entry) return true;
32380
- if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
32381
- const elapsed = nowMs - entry.startedAt;
32382
- return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
32383
- }
32384
- async function runGatedSnapshot(opts, snapshot) {
32385
- const now = opts.now ?? Date.now;
32386
- const mode = opts.mode ?? "routine";
32387
- const db = opts.stateDb;
32388
- const none = (skipped, error) => ({
32389
- snapshotted: [],
32390
- linked: [],
32391
- absent: [],
32392
- failed: [],
32393
- skipped,
32394
- ...error !== void 0 && { error }
32395
- });
32396
- const entryState = tryReadGateState(db);
32397
- const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
32398
- if (mode === "routine") {
32399
- if (!entryState) return none("state-unavailable");
32400
- const nowMs = now();
32401
- if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
32402
- return none("debounced");
32403
- }
32404
- }
32405
- const lockPath2 = join20(opts.backupDir, GATE_LOCK_BASENAME);
32406
- let release;
32407
- try {
32408
- release = await acquireLock(lockPath2, {
32409
- retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
32410
- stale: SNAPSHOT_LOCK_STALE_MS,
32411
- // A compromised lock (e.g. the backup dir was removed) must not throw
32412
- // from a timer and crash the host process.
32413
- onCompromised: () => {
32414
- }
32415
- });
32416
- } catch {
32417
- if (mode === "routine") return none("in-flight");
32418
- return none(
32419
- "lock-timeout",
32420
- `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.`
32421
- );
32422
- }
32423
- try {
32424
- try {
32425
- opts.onLockAcquired?.();
32426
- } catch {
32427
- }
32428
- const state = tryReadGateState(db);
32429
- if (!state && mode === "routine") return none("state-unavailable");
32430
- const startMs = now();
32431
- const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
32432
- (p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
32433
- );
32434
- if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
32435
- const generation = (state?.generation ?? 0) + 1;
32436
- let claimed = false;
32437
- if (db && state) {
32438
- try {
32439
- writeGateState(db, { ...state, generation });
32440
- claimed = true;
32441
- } catch {
32442
- }
32443
- }
32444
- const snapshotted = [];
32445
- const linked = [];
32446
- const absent = [];
32447
- const failed = [];
32448
- for (const prefix of admitted) {
32449
- try {
32450
- const outcome = await snapshot(prefix);
32451
- if (outcome === "absent") absent.push(prefix);
32452
- else {
32453
- snapshotted.push(prefix);
32454
- if (outcome === "linked") linked.push(prefix);
32455
- }
32456
- } catch {
32457
- failed.push(prefix);
32458
- }
32459
- }
32460
- const satisfied = [...snapshotted, ...absent];
32461
- if (db && claimed && satisfied.length > 0) {
32462
- try {
32463
- const latest = readGateState(db);
32464
- const completedAt = now();
32465
- latest.generation = Math.max(latest.generation, generation);
32466
- for (const p of satisfied) {
32467
- latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
32468
- }
32469
- writeGateState(db, latest);
32470
- } catch {
32471
- }
32472
- }
32473
- return { snapshotted, linked, absent, failed, skipped: null };
32474
- } finally {
32475
- await release().catch(() => {
32476
- });
32477
- }
32478
- }
32479
- function isValidStamp(ymd, hms) {
32480
- const y = Number(ymd.slice(0, 4));
32481
- const mo = Number(ymd.slice(4, 6));
32482
- const d = Number(ymd.slice(6, 8));
32483
- const h = Number(hms.slice(0, 2));
32484
- const mi = Number(hms.slice(2, 4));
32485
- const se = Number(hms.slice(4, 6));
32486
- if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
32487
- const probe = new Date(Date.UTC(y, mo - 1, d));
32488
- return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
32489
- }
32490
- function selectSnapshotsToKeep(names, ctx = {}) {
32491
- const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
32492
- const keep = /* @__PURE__ */ new Set();
32493
- const stamped = [];
32494
- for (const name2 of names) {
32495
- const m = STAMP_PATTERN.exec(name2);
32496
- const ymd = m?.[1];
32497
- const hms = m?.[2];
32498
- if (!ymd || !hms || !isValidStamp(ymd, hms)) {
32499
- keep.add(name2);
32500
- continue;
32501
- }
32502
- const stamp = `${ymd}-${hms}`;
32503
- if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
32504
- keep.add(name2);
32505
- continue;
32506
- }
32507
- stamped.push({ name: name2, stamp });
32508
- }
32509
- if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
32510
- stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
32511
- for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
32512
- const keepNewestPerBucket = (bucketOf, slots) => {
32513
- const seen = /* @__PURE__ */ new Set();
32514
- for (const s of stamped) {
32515
- const bucket = bucketOf(s.stamp);
32516
- if (seen.has(bucket)) continue;
32517
- if (seen.size >= slots) break;
32518
- seen.add(bucket);
32519
- keep.add(s.name);
32520
- }
32521
- };
32522
- keepNewestPerBucket(
32523
- (stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
32524
- policy.quarterHourly
32525
- );
32526
- keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
32527
- keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
32528
- return keep;
32529
- }
32530
- var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
32531
- var init_snapshot_gate = __esm({
32532
- "packages/core/src/store/snapshot-gate.ts"() {
32533
- "use strict";
32534
- init_lock();
32535
- SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
32536
- SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
32537
- SNAPSHOT_LOCK_WAIT_RETRIES = 90;
32538
- SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
32539
- GATE_LOCK_BASENAME = ".snapshot-gate";
32540
- DEFAULT_SNAPSHOT_RETENTION = {
32541
- latest: 1,
32542
- quarterHourly: 3,
32543
- hourly: 3,
32544
- daily: 3
32545
- };
32546
- STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
32547
- }
32548
- });
32549
-
32550
32702
  // packages/core/src/store/twin-collapse.ts
32551
32703
  import { createHash as createHash3 } from "node:crypto";
32552
32704
  function hasMainTable(db, name2) {
@@ -32623,6 +32775,22 @@ function mergeSchemaMetaValue(key, bare, twin) {
32623
32775
  const field = SCHEMA_META_COUNTER_FIELDS[key];
32624
32776
  return field === void 0 ? bare : withMaxCounter(bare, twin, field);
32625
32777
  }
32778
+ function mirrorCounterToBare(db, key) {
32779
+ if (SCHEMA_META_COUNTER_FIELDS[key] === void 0) return;
32780
+ if (!hasMainTable(db, "schema_meta")) return;
32781
+ const twin = readKv(db, "tasks_schema_meta", key);
32782
+ if (twin === void 0) return;
32783
+ const bare = readKv(db, "schema_meta", key);
32784
+ const next = bare === void 0 ? twin : mergeSchemaMetaValue(key, bare, twin);
32785
+ if (next === null || next === bare) return;
32786
+ writeKv(db, "schema_meta", key, next);
32787
+ }
32788
+ function bareCounterOf(db, key) {
32789
+ const name2 = SCHEMA_META_COUNTER_FIELDS[key];
32790
+ if (name2 === void 0 || !hasMainTable(db, "schema_meta")) return 0;
32791
+ const bare = readKv(db, "schema_meta", key);
32792
+ return (bare === void 0 ? void 0 : counterOf(bare, name2)) ?? 0;
32793
+ }
32626
32794
  function kvRows(db, table, schema = "main") {
32627
32795
  const rows = db.prepare(`SELECT key, value FROM ${schema}.${table}`).all();
32628
32796
  return new Map(rows.map((r) => [r.key, r.value]));
@@ -32755,6 +32923,39 @@ function applyStickyRows(db, schema, plan) {
32755
32923
  }
32756
32924
  return { inserted, replaced: 0, deleted };
32757
32925
  }
32926
+ function tagsOf(tagsJson) {
32927
+ if (!tagsJson) return [];
32928
+ try {
32929
+ const parsed = JSON.parse(tagsJson);
32930
+ if (!Array.isArray(parsed)) return [];
32931
+ return [...new Set(parsed.filter((t) => typeof t === "string" && t.length > 0))];
32932
+ } catch {
32933
+ return [];
32934
+ }
32935
+ }
32936
+ function syncStickyJunction(db, schema) {
32937
+ const notes = db.prepare("SELECT id, tags_json FROM main.brain_sticky_notes").all();
32938
+ const have = /* @__PURE__ */ new Map();
32939
+ for (const r of db.prepare(`SELECT sticky_id, tag FROM ${schema}.brain_sticky_tags`).all()) {
32940
+ const set = have.get(r.sticky_id) ?? /* @__PURE__ */ new Set();
32941
+ set.add(r.tag);
32942
+ have.set(r.sticky_id, set);
32943
+ }
32944
+ const insert = db.prepare(
32945
+ `INSERT OR IGNORE INTO ${schema}.brain_sticky_tags (sticky_id, tag) VALUES (?, ?)`
32946
+ );
32947
+ const del = db.prepare(`DELETE FROM ${schema}.brain_sticky_tags WHERE sticky_id = ? AND tag = ?`);
32948
+ let inserted = 0;
32949
+ let deleted = 0;
32950
+ for (const note of notes) {
32951
+ const want = new Set(tagsOf(note.tags_json));
32952
+ const current = have.get(note.id) ?? /* @__PURE__ */ new Set();
32953
+ for (const tag of want)
32954
+ if (!current.has(tag)) inserted += Number(insert.run(note.id, tag).changes);
32955
+ for (const tag of current) if (!want.has(tag)) deleted += Number(del.run(note.id, tag).changes);
32956
+ }
32957
+ return { inserted, deleted };
32958
+ }
32758
32959
  function twinCollapseFailureOf(db) {
32759
32960
  return degraded.get(db);
32760
32961
  }
@@ -32964,7 +33165,7 @@ function collapseTwinTables(nativeDb, dbPath, options = {}) {
32964
33165
  }
32965
33166
  return inOrder();
32966
33167
  }
32967
- 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;
33168
+ 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;
32968
33169
  var init_twin_collapse = __esm({
32969
33170
  "packages/core/src/store/twin-collapse.ts"() {
32970
33171
  "use strict";
@@ -32972,18 +33173,18 @@ var init_twin_collapse = __esm({
32972
33173
  init_errors2();
32973
33174
  init_logger2();
32974
33175
  init_pre_repair_snapshot();
32975
- init_snapshot_gate();
32976
33176
  log6 = getLogger("twin-collapse");
32977
33177
  TWIN_COLLAPSE_MARKER_PREFIX = "twin_collapse:";
32978
33178
  TWIN_COLLAPSE_FAILURE_PREFIX = "twin_collapse_failed:";
33179
+ SNAPSHOT_GATE_KEY = "sqlite_snapshot_gate";
32979
33180
  SCHEMA_META_COUNTER_FIELDS = {
32980
33181
  task_id_sequence: "counter",
32981
- [SNAPSHOT_GATE_META_KEY]: "generation",
33182
+ [SNAPSHOT_GATE_KEY]: "generation",
32982
33183
  file_meta: "generation"
32983
33184
  };
32984
33185
  SCHEMA_META_NEVER_DELETED = /* @__PURE__ */ new Set([
32985
33186
  "task_id_sequence",
32986
- SNAPSHOT_GATE_META_KEY
33187
+ SNAPSHOT_GATE_KEY
32987
33188
  ]);
32988
33189
  MAX_CONFLICTS = 50;
32989
33190
  sha = (value) => createHash3("sha256").update(value).digest("hex");
@@ -33048,7 +33249,12 @@ var init_twin_collapse = __esm({
33048
33249
  throw new Error(
33049
33250
  `sticky_tags collapse did not verify: ${missing} missing, ${lingering} not removed`
33050
33251
  );
33051
- return counts;
33252
+ const synced = syncStickyJunction(db, "main");
33253
+ return {
33254
+ inserted: counts.inserted + synced.inserted,
33255
+ replaced: 0,
33256
+ deleted: counts.deleted + synced.deleted
33257
+ };
33052
33258
  },
33053
33259
  shadow(db, plan) {
33054
33260
  db.exec(
@@ -33059,6 +33265,7 @@ var init_twin_collapse = __esm({
33059
33265
  "INSERT INTO temp.brain_sticky_tags (sticky_id, tag) SELECT sticky_id, tag FROM main.brain_sticky_tags"
33060
33266
  );
33061
33267
  applyStickyRows(db, "temp", plan);
33268
+ syncStickyJunction(db, "temp");
33062
33269
  }
33063
33270
  };
33064
33271
  PAIRS = [SCHEMA_META, STICKY_TAGS];
@@ -33090,7 +33297,7 @@ __export(config_exports, {
33090
33297
  parseConfigValue: () => parseConfigValue,
33091
33298
  setConfigValue: () => setConfigValue
33092
33299
  });
33093
- import { existsSync as existsSync16 } from "node:fs";
33300
+ import { existsSync as existsSync17 } from "node:fs";
33094
33301
  function getNestedValue(obj, path2) {
33095
33302
  const parts = path2.split(".");
33096
33303
  let current = obj;
@@ -33212,7 +33419,7 @@ function parseConfigValue(value) {
33212
33419
  }
33213
33420
  async function setConfigValue(key, value, cwd, opts) {
33214
33421
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
33215
- if (!existsSync16(configPath)) {
33422
+ if (!existsSync17(configPath)) {
33216
33423
  await atomicWriteJson(configPath, {});
33217
33424
  }
33218
33425
  const config = await readJson(configPath) ?? {};
@@ -33224,7 +33431,7 @@ async function setConfigValue(key, value, cwd, opts) {
33224
33431
  async function applyStrictnessPreset(preset, cwd, opts) {
33225
33432
  const definition = STRICTNESS_PRESETS[preset];
33226
33433
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
33227
- if (!existsSync16(configPath)) {
33434
+ if (!existsSync17(configPath)) {
33228
33435
  await atomicWriteJson(configPath, {});
33229
33436
  }
33230
33437
  const config = await readJson(configPath) ?? {};
@@ -33801,6 +34008,7 @@ var init_cross_db_cleanup = __esm({
33801
34008
  "use strict";
33802
34009
  init_memory_sqlite();
33803
34010
  init_memory_schema();
34011
+ init_worktree_build_guard();
33804
34012
  }
33805
34013
  });
33806
34014
 
@@ -38493,7 +38701,7 @@ __export(sqlite_data_accessor_exports, {
38493
38701
  setMetaValue: () => setMetaValue
38494
38702
  });
38495
38703
  import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
38496
- import { resolve as resolve7 } from "node:path";
38704
+ import { resolve as resolve9 } from "node:path";
38497
38705
  import {
38498
38706
  and as and5,
38499
38707
  eq as eq6,
@@ -38533,9 +38741,12 @@ async function writeMetaValue(cwd, key, value) {
38533
38741
  target: tasksSchemaMeta.key,
38534
38742
  set: { value: json }
38535
38743
  }).run();
38744
+ const native = getNativeTasksDb(cwd);
38745
+ if (native) mirrorCounterToBare(native, key);
38536
38746
  }
38537
38747
  function advanceTaskIdSequence(nativeDb, floor) {
38538
38748
  assertTwinCollapseWritable(nativeDb);
38749
+ const lowest = Math.max(floor, bareCounterOf(nativeDb, "task_id_sequence"));
38539
38750
  nativeDb.prepare(`
38540
38751
  UPDATE tasks_schema_meta
38541
38752
  SET value = json_set(value,
@@ -38544,7 +38755,8 @@ function advanceTaskIdSequence(nativeDb, floor) {
38544
38755
  '$.checksum', 'alloc-' || strftime('%s','now')
38545
38756
  )
38546
38757
  WHERE key = 'task_id_sequence'
38547
- `).run(floor, floor);
38758
+ `).run(lowest, lowest);
38759
+ mirrorCounterToBare(nativeDb, "task_id_sequence");
38548
38760
  const row = nativeDb.prepare(`
38549
38761
  SELECT json_extract(value, '$.counter') AS counter
38550
38762
  FROM tasks_schema_meta WHERE key = 'task_id_sequence'
@@ -38598,7 +38810,7 @@ function bindTaskAccessorScope(accessor, scope) {
38598
38810
  }
38599
38811
  async function createSqliteDataAccessor(cwd) {
38600
38812
  const scope = captureProjectScope(
38601
- resolve7(cwd ?? getProjectRoot()),
38813
+ resolve9(cwd ?? getProjectRoot()),
38602
38814
  worktreeScope.getStore()
38603
38815
  );
38604
38816
  return worktreeScope.run(
@@ -38713,7 +38925,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38713
38925
  actor: entry.actor ?? "system",
38714
38926
  detailsJson: entry.details ? JSON.stringify(entry.details) : "{}",
38715
38927
  beforeJson: entry.before ? JSON.stringify(entry.before) : null,
38716
- afterJson: entry.after ? JSON.stringify(entry.after) : null
38928
+ afterJson: entry.after ? JSON.stringify(entry.after) : null,
38929
+ // T12693: the session a ranking change ran in.
38930
+ sessionId: typeof entry.sessionId === "string" ? entry.sessionId : null
38717
38931
  }).run()
38718
38932
  );
38719
38933
  });
@@ -38721,6 +38935,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38721
38935
  async queryAuditLog(query) {
38722
38936
  const db = await getDb(cwd);
38723
38937
  const conditions = [];
38938
+ if (query.ids && query.ids.length > 0) {
38939
+ conditions.push(inArray4(tasksAuditLog.id, [...query.ids]));
38940
+ }
38724
38941
  if (query.taskIds && query.taskIds.length > 0) {
38725
38942
  conditions.push(inArray4(tasksAuditLog.taskId, [...query.taskIds]));
38726
38943
  }
@@ -38739,7 +38956,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38739
38956
  actor: tasksAuditLog.actor,
38740
38957
  detailsJson: tasksAuditLog.detailsJson,
38741
38958
  beforeJson: tasksAuditLog.beforeJson,
38742
- afterJson: tasksAuditLog.afterJson
38959
+ afterJson: tasksAuditLog.afterJson,
38960
+ sessionId: tasksAuditLog.sessionId
38743
38961
  }).from(tasksAuditLog).where(conditions.length > 0 ? and5(...conditions) : void 0).orderBy(sql26`${tasksAuditLog.timestamp} DESC`).limit(limit).all();
38744
38962
  return rows.map((row) => ({
38745
38963
  id: row.id,
@@ -38749,7 +38967,8 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
38749
38967
  actor: row.actor,
38750
38968
  detailsJson: row.detailsJson ?? null,
38751
38969
  beforeJson: row.beforeJson ?? null,
38752
- afterJson: row.afterJson ?? null
38970
+ afterJson: row.afterJson ?? null,
38971
+ sessionId: row.sessionId ?? null
38753
38972
  }));
38754
38973
  },
38755
38974
  // ---- Fine-grained task operations (T5034) ----
@@ -39587,7 +39806,7 @@ var init_sqlite_data_accessor = __esm({
39587
39806
  });
39588
39807
 
39589
39808
  // packages/core/src/sequence/index.ts
39590
- import { existsSync as existsSync17, readFileSync as readFileSync5, renameSync as renameSync5 } from "node:fs";
39809
+ import { existsSync as existsSync18, readFileSync as readFileSync6, renameSync as renameSync5 } from "node:fs";
39591
39810
  import { join as join21 } from "node:path";
39592
39811
  function getLegacySequenceJsonPath(cwd) {
39593
39812
  return join21(resolveOrCwd(cwd), ".cleo", ".sequence.json");
@@ -39604,19 +39823,19 @@ function isSeedSequence(value) {
39604
39823
  return value.counter === 0 && value.lastId === "T000" && value.checksum === "seed";
39605
39824
  }
39606
39825
  function readLegacySequenceFile(path2) {
39607
- if (!existsSync17(path2)) return null;
39826
+ if (!existsSync18(path2)) return null;
39608
39827
  try {
39609
- const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
39828
+ const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
39610
39829
  return isValidSequenceState(parsed) ? parsed : null;
39611
39830
  } catch {
39612
39831
  return null;
39613
39832
  }
39614
39833
  }
39615
39834
  function renameLegacyFile(path2) {
39616
- if (!existsSync17(path2)) return;
39835
+ if (!existsSync18(path2)) return;
39617
39836
  const migratedPath = `${path2}.migrated`;
39618
39837
  try {
39619
- if (!existsSync17(migratedPath)) {
39838
+ if (!existsSync18(migratedPath)) {
39620
39839
  renameSync5(path2, migratedPath);
39621
39840
  return;
39622
39841
  }
@@ -39782,12 +40001,12 @@ var init_checkpoint_git_dir = __esm({
39782
40001
 
39783
40002
  // packages/core/src/store/git-checkpoint.ts
39784
40003
  import { execFile as execFile2 } from "node:child_process";
39785
- import { existsSync as existsSync18 } from "node:fs";
40004
+ import { existsSync as existsSync19 } from "node:fs";
39786
40005
  import { readFile as readFile4, writeFile } from "node:fs/promises";
39787
- import { join as join23, resolve as resolve8 } from "node:path";
40006
+ import { join as join23, resolve as resolve10 } from "node:path";
39788
40007
  import { promisify as promisify2 } from "node:util";
39789
40008
  function makeCleoGitEnv(cleoDir) {
39790
- const abs = resolve8(cleoDir);
40009
+ const abs = resolve10(cleoDir);
39791
40010
  return {
39792
40011
  ...process.env,
39793
40012
  GIT_DIR: checkpointGitDir(abs),
@@ -39797,7 +40016,7 @@ function makeCleoGitEnv(cleoDir) {
39797
40016
  async function cleoGitCommand(args, cleoDir) {
39798
40017
  try {
39799
40018
  const result = await execFileAsync2("git", args, {
39800
- cwd: resolve8(cleoDir),
40019
+ cwd: resolve10(cleoDir),
39801
40020
  // absolute cwd so relative paths in args resolve correctly
39802
40021
  env: makeCleoGitEnv(cleoDir),
39803
40022
  timeout: 1e4
@@ -39808,7 +40027,7 @@ async function cleoGitCommand(args, cleoDir) {
39808
40027
  }
39809
40028
  }
39810
40029
  function isCleoGitInitialized(cleoDir) {
39811
- return existsSync18(join23(checkpointGitDir(cleoDir), "HEAD"));
40030
+ return existsSync19(join23(checkpointGitDir(cleoDir), "HEAD"));
39812
40031
  }
39813
40032
  async function loadStateFileAllowlist(cwd) {
39814
40033
  try {
@@ -39852,14 +40071,14 @@ async function isCleoGitRepo(cleoDir) {
39852
40071
  return result.success && (result.stdout === "true" || isCleoGitInitialized(cleoDir));
39853
40072
  }
39854
40073
  function isMergeInProgress(cleoDir) {
39855
- return existsSync18(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
40074
+ return existsSync19(join23(checkpointGitDir(cleoDir), "MERGE_HEAD"));
39856
40075
  }
39857
40076
  async function isDetachedHead(cleoDir) {
39858
40077
  const result = await cleoGitCommand(["symbolic-ref", "HEAD"], cleoDir);
39859
40078
  return !result.success;
39860
40079
  }
39861
40080
  function isRebaseInProgress(cleoDir) {
39862
- return existsSync18(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync18(join23(checkpointGitDir(cleoDir), "rebase-apply"));
40081
+ return existsSync19(join23(checkpointGitDir(cleoDir), "rebase-merge")) || existsSync19(join23(checkpointGitDir(cleoDir), "rebase-apply"));
39863
40082
  }
39864
40083
  async function recordCheckpointTime(cleoDir) {
39865
40084
  try {
@@ -39883,7 +40102,7 @@ async function getChangedStateFiles(cleoDir, cwd) {
39883
40102
  const allStateFiles = await getAllStateFiles(cwd);
39884
40103
  for (const stateFile of allStateFiles) {
39885
40104
  const fullPath = join23(cleoDir, stateFile);
39886
- if (!existsSync18(fullPath)) continue;
40105
+ if (!existsSync19(fullPath)) continue;
39887
40106
  const diffResult = await cleoGitCommand(["diff", "--quiet", "--", stateFile], cleoDir);
39888
40107
  const cachedResult = await cleoGitCommand(
39889
40108
  ["diff", "--cached", "--quiet", "--", stateFile],
@@ -39910,7 +40129,7 @@ async function shouldCheckpoint(options) {
39910
40129
  const config = await loadCheckpointConfig(cwd);
39911
40130
  if (!config.enabled) return false;
39912
40131
  const cleoDir = getCleoDir(cwd);
39913
- if (!existsSync18(cleoDir)) return false;
40132
+ if (!existsSync19(cleoDir)) return false;
39914
40133
  if (!isCleoGitInitialized(cleoDir)) return false;
39915
40134
  if (!await isCleoGitRepo(cleoDir)) return false;
39916
40135
  if (isMergeInProgress(cleoDir)) return false;
@@ -39983,6 +40202,218 @@ var init_git_checkpoint = __esm({
39983
40202
  }
39984
40203
  });
39985
40204
 
40205
+ // packages/core/src/store/snapshot-gate.ts
40206
+ import { join as join24 } from "node:path";
40207
+ function readGateState(db) {
40208
+ const row = db.prepare("SELECT value FROM tasks_schema_meta WHERE key = ?").get(SNAPSHOT_GATE_META_KEY);
40209
+ const state = { generation: 0, prefixes: {} };
40210
+ if (!row) return state;
40211
+ try {
40212
+ const parsed = JSON.parse(row.value);
40213
+ if (parsed === null || typeof parsed !== "object") return state;
40214
+ if (typeof parsed.generation === "number" && Number.isSafeInteger(parsed.generation)) {
40215
+ state.generation = parsed.generation;
40216
+ }
40217
+ for (const [prefix, e] of Object.entries(parsed.prefixes ?? {})) {
40218
+ if (e && typeof e.generation === "number" && typeof e.startedAt === "number" && typeof e.completedAt === "number") {
40219
+ state.prefixes[prefix] = {
40220
+ generation: e.generation,
40221
+ startedAt: e.startedAt,
40222
+ completedAt: e.completedAt
40223
+ };
40224
+ }
40225
+ }
40226
+ } catch {
40227
+ }
40228
+ return state;
40229
+ }
40230
+ function writeGateState(db, state) {
40231
+ db.prepare(
40232
+ "INSERT INTO tasks_schema_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
40233
+ ).run(SNAPSHOT_GATE_META_KEY, JSON.stringify(state));
40234
+ mirrorCounterToBare(db, SNAPSHOT_GATE_META_KEY);
40235
+ }
40236
+ function tryReadGateState(db) {
40237
+ if (!db) return null;
40238
+ try {
40239
+ return readGateState(db);
40240
+ } catch {
40241
+ return null;
40242
+ }
40243
+ }
40244
+ function needsSnapshot(entry, mode, nowMs, seenGeneration) {
40245
+ if (!entry) return true;
40246
+ if (mode === "required") return seenGeneration === null || entry.generation <= seenGeneration;
40247
+ const elapsed = nowMs - entry.startedAt;
40248
+ return elapsed < 0 || elapsed >= SNAPSHOT_DEBOUNCE_MS;
40249
+ }
40250
+ async function runGatedSnapshot(opts, snapshot) {
40251
+ const now = opts.now ?? Date.now;
40252
+ const mode = opts.mode ?? "routine";
40253
+ const db = opts.stateDb;
40254
+ const none = (skipped, error) => ({
40255
+ snapshotted: [],
40256
+ linked: [],
40257
+ absent: [],
40258
+ failed: [],
40259
+ skipped,
40260
+ ...error !== void 0 && { error }
40261
+ });
40262
+ const entryState = tryReadGateState(db);
40263
+ const seenGeneration = mode === "required" ? opts.seenGeneration ?? entryState?.generation ?? null : null;
40264
+ if (mode === "routine") {
40265
+ if (!entryState) return none("state-unavailable");
40266
+ const nowMs = now();
40267
+ if (!opts.prefixes.some((p) => needsSnapshot(entryState.prefixes[p], mode, nowMs, null))) {
40268
+ return none("debounced");
40269
+ }
40270
+ }
40271
+ const lockPath2 = join24(opts.backupDir, GATE_LOCK_BASENAME);
40272
+ let release;
40273
+ try {
40274
+ release = await acquireLock(lockPath2, {
40275
+ retries: mode === "required" ? opts.lockWaitRetries ?? SNAPSHOT_LOCK_WAIT_RETRIES : 0,
40276
+ stale: SNAPSHOT_LOCK_STALE_MS,
40277
+ // A compromised lock (e.g. the backup dir was removed) must not throw
40278
+ // from a timer and crash the host process.
40279
+ onCompromised: () => {
40280
+ }
40281
+ });
40282
+ } catch {
40283
+ if (mode === "routine") return none("in-flight");
40284
+ return none(
40285
+ "lock-timeout",
40286
+ `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.`
40287
+ );
40288
+ }
40289
+ try {
40290
+ try {
40291
+ opts.onLockAcquired?.();
40292
+ } catch {
40293
+ }
40294
+ const state = tryReadGateState(db);
40295
+ if (!state && mode === "routine") return none("state-unavailable");
40296
+ const startMs = now();
40297
+ const admitted = mode === "required" && opts.alwaysSnapshot === true ? [...opts.prefixes] : opts.prefixes.filter(
40298
+ (p) => needsSnapshot(state?.prefixes[p], mode, startMs, seenGeneration)
40299
+ );
40300
+ if (admitted.length === 0) return none(mode === "routine" ? "debounced" : "covered");
40301
+ const generation = (state?.generation ?? 0) + 1;
40302
+ let claimed = false;
40303
+ if (db && state) {
40304
+ try {
40305
+ writeGateState(db, { ...state, generation });
40306
+ claimed = true;
40307
+ } catch {
40308
+ }
40309
+ }
40310
+ const snapshotted = [];
40311
+ const linked = [];
40312
+ const absent = [];
40313
+ const failed = [];
40314
+ for (const prefix of admitted) {
40315
+ try {
40316
+ const outcome = await snapshot(prefix);
40317
+ if (outcome === "absent") absent.push(prefix);
40318
+ else {
40319
+ snapshotted.push(prefix);
40320
+ if (outcome === "linked") linked.push(prefix);
40321
+ }
40322
+ } catch {
40323
+ failed.push(prefix);
40324
+ }
40325
+ }
40326
+ const satisfied = [...snapshotted, ...absent];
40327
+ if (db && claimed && satisfied.length > 0) {
40328
+ try {
40329
+ const latest = readGateState(db);
40330
+ const completedAt = now();
40331
+ latest.generation = Math.max(latest.generation, generation);
40332
+ for (const p of satisfied) {
40333
+ latest.prefixes[p] = { generation, startedAt: startMs, completedAt };
40334
+ }
40335
+ writeGateState(db, latest);
40336
+ } catch {
40337
+ }
40338
+ }
40339
+ return { snapshotted, linked, absent, failed, skipped: null };
40340
+ } finally {
40341
+ await release().catch(() => {
40342
+ });
40343
+ }
40344
+ }
40345
+ function isValidStamp(ymd, hms) {
40346
+ const y = Number(ymd.slice(0, 4));
40347
+ const mo = Number(ymd.slice(4, 6));
40348
+ const d = Number(ymd.slice(6, 8));
40349
+ const h = Number(hms.slice(0, 2));
40350
+ const mi = Number(hms.slice(2, 4));
40351
+ const se = Number(hms.slice(4, 6));
40352
+ if (mo < 1 || mo > 12 || d < 1 || h > 23 || mi > 59 || se > 59) return false;
40353
+ const probe = new Date(Date.UTC(y, mo - 1, d));
40354
+ return probe.getUTCFullYear() === y && probe.getUTCMonth() === mo - 1 && probe.getUTCDate() === d;
40355
+ }
40356
+ function selectSnapshotsToKeep(names, ctx = {}) {
40357
+ const policy = ctx.policy ?? DEFAULT_SNAPSHOT_RETENTION;
40358
+ const keep = /* @__PURE__ */ new Set();
40359
+ const stamped = [];
40360
+ for (const name2 of names) {
40361
+ const m = STAMP_PATTERN.exec(name2);
40362
+ const ymd = m?.[1];
40363
+ const hms = m?.[2];
40364
+ if (!ymd || !hms || !isValidStamp(ymd, hms)) {
40365
+ keep.add(name2);
40366
+ continue;
40367
+ }
40368
+ const stamp = `${ymd}-${hms}`;
40369
+ if (ctx.nowStamp !== void 0 && stamp > ctx.nowStamp) {
40370
+ keep.add(name2);
40371
+ continue;
40372
+ }
40373
+ stamped.push({ name: name2, stamp });
40374
+ }
40375
+ if (ctx.pinned !== void 0 && names.includes(ctx.pinned)) keep.add(ctx.pinned);
40376
+ stamped.sort((a, b) => a.stamp < b.stamp ? 1 : a.stamp > b.stamp ? -1 : 0);
40377
+ for (const s of stamped.slice(0, policy.latest)) keep.add(s.name);
40378
+ const keepNewestPerBucket = (bucketOf, slots) => {
40379
+ const seen = /* @__PURE__ */ new Set();
40380
+ for (const s of stamped) {
40381
+ const bucket = bucketOf(s.stamp);
40382
+ if (seen.has(bucket)) continue;
40383
+ if (seen.size >= slots) break;
40384
+ seen.add(bucket);
40385
+ keep.add(s.name);
40386
+ }
40387
+ };
40388
+ keepNewestPerBucket(
40389
+ (stamp) => `${stamp.slice(0, 11)}q${Math.floor(Number(stamp.slice(11, 13)) / 15)}`,
40390
+ policy.quarterHourly
40391
+ );
40392
+ keepNewestPerBucket((stamp) => stamp.slice(0, 11), policy.hourly);
40393
+ keepNewestPerBucket((stamp) => stamp.slice(0, 8), policy.daily);
40394
+ return keep;
40395
+ }
40396
+ var SNAPSHOT_DEBOUNCE_MS, SNAPSHOT_LOCK_STALE_MS, SNAPSHOT_LOCK_WAIT_RETRIES, SNAPSHOT_GATE_META_KEY, GATE_LOCK_BASENAME, DEFAULT_SNAPSHOT_RETENTION, STAMP_PATTERN;
40397
+ var init_snapshot_gate = __esm({
40398
+ "packages/core/src/store/snapshot-gate.ts"() {
40399
+ "use strict";
40400
+ init_lock();
40401
+ init_twin_collapse();
40402
+ SNAPSHOT_DEBOUNCE_MS = 5 * 6e4;
40403
+ SNAPSHOT_LOCK_STALE_MS = 10 * 6e4;
40404
+ SNAPSHOT_LOCK_WAIT_RETRIES = 90;
40405
+ SNAPSHOT_GATE_META_KEY = "sqlite_snapshot_gate";
40406
+ GATE_LOCK_BASENAME = ".snapshot-gate";
40407
+ DEFAULT_SNAPSHOT_RETENTION = {
40408
+ latest: 1,
40409
+ quarterHourly: 3,
40410
+ hourly: 3,
40411
+ daily: 3
40412
+ };
40413
+ STAMP_PATTERN = /-(\d{8})-(\d{6})\.db$/;
40414
+ }
40415
+ });
40416
+
39986
40417
  // packages/core/src/store/data-safety-central.ts
39987
40418
  import { eq as eq7 } from "drizzle-orm";
39988
40419
  function inSafetyScope(cwd, operation) {
@@ -40393,7 +40824,7 @@ __export(data_accessor_exports, {
40393
40824
  getAccessorDb: () => getAccessorDb,
40394
40825
  getTaskAccessor: () => getTaskAccessor
40395
40826
  });
40396
- import { resolve as resolve9 } from "node:path";
40827
+ import { resolve as resolve11 } from "node:path";
40397
40828
  function assertTestEnv(dbPath) {
40398
40829
  const testMode = process.env["CLEO_TEST_MODE"];
40399
40830
  if (testMode !== "1") return;
@@ -40414,7 +40845,7 @@ function assertTestEnv(dbPath) {
40414
40845
  }
40415
40846
  }
40416
40847
  async function createDataAccessor(cwd) {
40417
- const root = resolve9(cwd ?? getProjectRoot());
40848
+ const root = resolve11(cwd ?? getProjectRoot());
40418
40849
  const inherited = worktreeScope.getStore();
40419
40850
  const captured = inherited ? { ...inherited } : void 0;
40420
40851
  captured?.execution?.assertActive();
@@ -40458,7 +40889,7 @@ __export(memory_sqlite_exports, {
40458
40889
  resetBrainDbState: () => resetBrainDbState,
40459
40890
  resolveBrainMigrationsFolder: () => resolveBrainMigrationsFolder
40460
40891
  });
40461
- import { createRequire as createRequire6 } from "node:module";
40892
+ import { createRequire as createRequire7 } from "node:module";
40462
40893
  function _getDrizzle2() {
40463
40894
  if (_drizzle2 === null) {
40464
40895
  const mod = _require4("drizzle-orm/node-sqlite");
@@ -40595,7 +41026,7 @@ var init_memory_sqlite = __esm({
40595
41026
  init_resolve_migrations_folder();
40596
41027
  init_memory_schema();
40597
41028
  init_twin_collapse();
40598
- _require4 = createRequire6(import.meta.url);
41029
+ _require4 = createRequire7(import.meta.url);
40599
41030
  _drizzle2 = null;
40600
41031
  BRAIN_SCHEMA_VERSION = "1.0.0";
40601
41032
  CONSOLIDATED_BRAIN_TABLES = [
@@ -40783,11 +41214,11 @@ var init_skills_schema = __esm({
40783
41214
  });
40784
41215
 
40785
41216
  // packages/core/src/store/skills-db.ts
40786
- import { join as join24 } from "node:path";
41217
+ import { join as join25 } from "node:path";
40787
41218
  import { and as and6, eq as eq8 } from "drizzle-orm";
40788
41219
  function getDefaultSkillsDbPath() {
40789
41220
  const cleoHome = getCleoHome();
40790
- const dbPath = join24(cleoHome, "cleo.db");
41221
+ const dbPath = join25(cleoHome, "cleo.db");
40791
41222
  if (!dbPath.startsWith(cleoHome)) {
40792
41223
  throw new Error(
40793
41224
  `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.`
@@ -40835,19 +41266,19 @@ import {
40835
41266
  chmodSync,
40836
41267
  closeSync,
40837
41268
  copyFileSync as copyFileSync3,
40838
- existsSync as existsSync19,
41269
+ existsSync as existsSync20,
40839
41270
  fsyncSync,
40840
41271
  linkSync,
40841
41272
  mkdirSync as mkdirSync5,
40842
41273
  openSync,
40843
41274
  readdirSync as readdirSync5,
40844
- realpathSync as realpathSync6,
41275
+ realpathSync as realpathSync7,
40845
41276
  renameSync as renameSync6,
40846
41277
  rmSync,
40847
41278
  statSync as statSync6,
40848
41279
  unlinkSync as unlinkSync3
40849
41280
  } from "node:fs";
40850
- import { dirname as dirname13, join as join25, sep as sep3 } from "node:path";
41281
+ import { dirname as dirname15, join as join26, sep as sep4 } from "node:path";
40851
41282
  function resolveInventoryPath(entry, cwd) {
40852
41283
  try {
40853
41284
  if (entry.tier === "global") {
@@ -40883,8 +41314,8 @@ async function openAgentRegistryDbForSnapshot() {
40883
41314
  }
40884
41315
  async function openTelemetryDbForSnapshot() {
40885
41316
  try {
40886
- const path2 = join25(getCleoHome(), "telemetry.db");
40887
- if (!existsSync19(path2)) return null;
41317
+ const path2 = join26(getCleoHome(), "telemetry.db");
41318
+ if (!existsSync20(path2)) return null;
40888
41319
  } catch {
40889
41320
  return null;
40890
41321
  }
@@ -40996,7 +41427,7 @@ function rotateSnapshots(backupDir, prefix, justWritten) {
40996
41427
  for (const name2 of names) {
40997
41428
  if (keep.has(name2)) continue;
40998
41429
  try {
40999
- unlinkSync3(join25(backupDir, name2));
41430
+ unlinkSync3(join26(backupDir, name2));
41000
41431
  } catch {
41001
41432
  }
41002
41433
  }
@@ -41018,7 +41449,7 @@ async function snapshotProjectTargetsGated(targets, opts) {
41018
41449
  let backupDir;
41019
41450
  try {
41020
41451
  const cleoDir = getCleoDir(cwd);
41021
- backupDir = join25(cleoDir, "backups", "sqlite");
41452
+ backupDir = join26(cleoDir, "backups", "sqlite");
41022
41453
  mkdirSync5(backupDir, { recursive: true });
41023
41454
  } catch {
41024
41455
  return null;
@@ -41050,7 +41481,7 @@ function sourceFileOf(db) {
41050
41481
  const location = db.location();
41051
41482
  if (!location) return null;
41052
41483
  try {
41053
- return realpathSync6(location);
41484
+ return realpathSync7(location);
41054
41485
  } catch {
41055
41486
  return location;
41056
41487
  }
@@ -41061,10 +41492,10 @@ function hasLocation(db) {
41061
41492
  function assertOwnedByProject(source, prefix, cwd) {
41062
41493
  let cleoDir = getCleoDir(cwd);
41063
41494
  try {
41064
- cleoDir = realpathSync6(cleoDir);
41495
+ cleoDir = realpathSync7(cleoDir);
41065
41496
  } catch {
41066
41497
  }
41067
- if (!source.startsWith(cleoDir + sep3)) {
41498
+ if (!source.startsWith(cleoDir + sep4)) {
41068
41499
  throw new Error(
41069
41500
  `refusing to snapshot ${prefix}: its database ${source} is not inside ${cleoDir}`
41070
41501
  );
@@ -41093,7 +41524,7 @@ function commitSnapshotFile(tmp, dest) {
41093
41524
  }
41094
41525
  renameSync6(tmp, dest);
41095
41526
  try {
41096
- const dirFd = openSync(dirname13(dest), "r");
41527
+ const dirFd = openSync(dirname15(dest), "r");
41097
41528
  try {
41098
41529
  fsyncSync(dirFd);
41099
41530
  } finally {
@@ -41116,7 +41547,7 @@ function removeDeadTempSnapshots(backupDir) {
41116
41547
  const m = TEMP_SNAPSHOT_RE.exec(name2);
41117
41548
  if (!m) continue;
41118
41549
  const pid = Number(m[1]);
41119
- const path2 = join25(backupDir, name2);
41550
+ const path2 = join26(backupDir, name2);
41120
41551
  const stale = pid !== process.pid && (!isPidAlive2(pid) || Date.now() - statSync6(path2).mtimeMs > TEMP_SNAPSHOT_MAX_AGE_MS);
41121
41552
  if (stale) rmSync(path2, { force: true });
41122
41553
  }
@@ -41126,7 +41557,7 @@ function removeDeadTempSnapshots(backupDir) {
41126
41557
  async function freeSnapshotName(backupDir, prefix) {
41127
41558
  for (let attempt = 0; attempt < SNAPSHOT_NAME_ATTEMPTS; attempt++) {
41128
41559
  const name2 = `${prefix}-${formatTimestamp(/* @__PURE__ */ new Date())}.db`;
41129
- if (!existsSync19(join25(backupDir, name2))) return name2;
41560
+ if (!existsSync20(join26(backupDir, name2))) return name2;
41130
41561
  await new Promise((r) => setTimeout(r, 1e3 - Date.now() % 1e3 + 5));
41131
41562
  }
41132
41563
  throw new Error(`no free snapshot filename for ${prefix} in ${backupDir}`);
@@ -41154,7 +41585,7 @@ async function snapshotOne(target, backupDir, writtenBySource, cwd) {
41154
41585
  if (opened && target.closeDb) target.closeDb(opened);
41155
41586
  throw err;
41156
41587
  }
41157
- const dest = join25(backupDir, destName);
41588
+ const dest = join26(backupDir, destName);
41158
41589
  removeDeadTempSnapshots(backupDir);
41159
41590
  const existing = source !== null ? writtenBySource.get(source) : void 0;
41160
41591
  if (existing !== void 0) {
@@ -41208,13 +41639,13 @@ async function vacuumIntoBackup(opts = {}) {
41208
41639
  function listSqliteBackupsForPrefix(prefix, cwd) {
41209
41640
  try {
41210
41641
  const cleoDir = getCleoDir(cwd);
41211
- const backupDir = join25(cleoDir, "backups", "sqlite");
41212
- if (!existsSync19(backupDir)) return [];
41642
+ const backupDir = join26(cleoDir, "backups", "sqlite");
41643
+ if (!existsSync20(backupDir)) return [];
41213
41644
  const pattern = snapshotPattern(prefix);
41214
41645
  return readdirSync5(backupDir).filter((f) => pattern.test(f)).map((f) => ({
41215
41646
  name: f,
41216
- path: join25(backupDir, f),
41217
- mtimeMs: statSync6(join25(backupDir, f)).mtimeMs
41647
+ path: join26(backupDir, f),
41648
+ mtimeMs: statSync6(join26(backupDir, f)).mtimeMs
41218
41649
  })).sort((a, b) => b.mtimeMs - a.mtimeMs);
41219
41650
  } catch {
41220
41651
  return [];
@@ -41284,15 +41715,16 @@ __export(sqlite_exports, {
41284
41715
  resetDbState: () => resetDbState,
41285
41716
  resolveMigrationsFolder: () => resolveMigrationsFolder,
41286
41717
  schema: () => tasks_schema_exports,
41287
- seedTasksMeta: () => seedTasksMeta
41718
+ seedTasksMeta: () => seedTasksMeta,
41719
+ worktreeRecoveryRefusal: () => worktreeRecoveryRefusal
41288
41720
  });
41289
- import { copyFileSync as copyFileSync4, existsSync as existsSync20, realpathSync as realpathSync7, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
41290
- import { createRequire as createRequire7 } from "node:module";
41291
- import { basename as basename8, dirname as dirname14, resolve as resolve10 } from "node:path";
41721
+ import { copyFileSync as copyFileSync4, existsSync as existsSync21, realpathSync as realpathSync8, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
41722
+ import { createRequire as createRequire8 } from "node:module";
41723
+ import { basename as basename8, dirname as dirname16, resolve as resolve12 } from "node:path";
41292
41724
  import { eq as eq9 } from "drizzle-orm";
41293
41725
  function _getDrizzle3() {
41294
41726
  if (_drizzle3 === null) {
41295
- const _require7 = createRequire7(import.meta.url);
41727
+ const _require7 = createRequire8(import.meta.url);
41296
41728
  const mod = _require7("drizzle-orm/node-sqlite");
41297
41729
  _drizzle3 = mod.drizzle;
41298
41730
  }
@@ -41328,13 +41760,19 @@ function countBackupTasks(backupDb) {
41328
41760
  return 0;
41329
41761
  }
41330
41762
  function isSameDirectory(a, b) {
41331
- if (resolve10(a) === resolve10(b)) return true;
41763
+ if (resolve12(a) === resolve12(b)) return true;
41332
41764
  try {
41333
- return realpathSync7(a) === realpathSync7(b);
41765
+ return realpathSync8(a) === realpathSync8(b);
41334
41766
  } catch {
41335
41767
  return false;
41336
41768
  }
41337
41769
  }
41770
+ function worktreeRecoveryRefusal(dbPath) {
41771
+ const storeCleoDir = dirname16(dbPath);
41772
+ const root = dirname16(storeCleoDir);
41773
+ if (basename8(storeCleoDir) !== ".cleo" || !isGitLinkedCheckout(root)) return null;
41774
+ 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).`;
41775
+ }
41338
41776
  async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41339
41777
  const { openNativeDatabase: openNativeDatabase2 } = await Promise.resolve().then(() => (init_sqlite_native(), sqlite_native_exports));
41340
41778
  const log15 = getLogger("sqlite");
@@ -41343,12 +41781,10 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41343
41781
  const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks_tasks").get();
41344
41782
  const taskCount = countResult?.cnt ?? 0;
41345
41783
  if (taskCount > 0) return false;
41346
- const storeCleoDir = dirname14(dbPath);
41347
- if (basename8(storeCleoDir) === ".cleo" && isGitLinkedCheckout(dirname14(storeCleoDir))) {
41348
- log15.warn(
41349
- { dbPath },
41350
- "Auto-recovery refused: the empty store lives inside a git worktree (T12460). Worktrees must resolve the parent project store."
41351
- );
41784
+ const storeCleoDir = dirname16(dbPath);
41785
+ const worktreeRefusal = worktreeRecoveryRefusal(dbPath);
41786
+ if (worktreeRefusal !== null) {
41787
+ log15.warn({ dbPath }, worktreeRefusal);
41352
41788
  return false;
41353
41789
  }
41354
41790
  const backups = listSqliteBackups(cwd);
@@ -41356,7 +41792,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
41356
41792
  return false;
41357
41793
  }
41358
41794
  const newestBackup = backups[0];
41359
- const backupCleoDir = dirname14(dirname14(dirname14(newestBackup.path)));
41795
+ const backupCleoDir = dirname16(dirname16(dirname16(newestBackup.path)));
41360
41796
  if (!isSameDirectory(backupCleoDir, storeCleoDir)) {
41361
41797
  log15.warn(
41362
41798
  { dbPath, backupPath: newestBackup.path },
@@ -41478,6 +41914,7 @@ function runMigrations(nativeDb, db, dbPath) {
41478
41914
  try {
41479
41915
  migrateWithRetry(db, migrationsFolder, nativeDb, "tasks", "sqlite");
41480
41916
  } catch (error) {
41917
+ if (isWorktreeBuildSchemaError(error)) throw error;
41481
41918
  if (isSqliteBusy(error) || !tableExists(nativeDb, "tasks_tasks")) throw error;
41482
41919
  try {
41483
41920
  rebuildLegacyTasksLineage(
@@ -41519,7 +41956,7 @@ async function getSchemaVersion(cwd) {
41519
41956
  return result[0]?.value ?? null;
41520
41957
  }
41521
41958
  function dbExists(cwd) {
41522
- return existsSync20(resolveDualScopeDbPath("project", cwd));
41959
+ return existsSync21(resolveDualScopeDbPath("project", cwd));
41523
41960
  }
41524
41961
  function getNativeDb(cwd) {
41525
41962
  return boundProjectNative("tasks", cwd);
@@ -41555,6 +41992,7 @@ var init_sqlite3 = __esm({
41555
41992
  init_resolve_migrations_folder();
41556
41993
  init_sqlite_backup();
41557
41994
  init_twin_collapse();
41995
+ init_worktree_build_guard();
41558
41996
  init_worktree_isolation_guard();
41559
41997
  init_sqlite_native();
41560
41998
  init_tasks_schema();
@@ -41583,15 +42021,15 @@ var init_sqlite3 = __esm({
41583
42021
  // packages/core/src/store/exodus/migrate.ts
41584
42022
  import {
41585
42023
  copyFileSync as copyFileSync5,
41586
- existsSync as existsSync21,
42024
+ existsSync as existsSync22,
41587
42025
  mkdirSync as mkdirSync6,
41588
- readFileSync as readFileSync6,
42026
+ readFileSync as readFileSync7,
41589
42027
  renameSync as renameSync8,
41590
42028
  statSync as statSync7,
41591
42029
  unlinkSync as unlinkSync5,
41592
42030
  writeFileSync as writeFileSync6
41593
42031
  } from "node:fs";
41594
- import { join as join26 } from "node:path";
42032
+ import { join as join27 } from "node:path";
41595
42033
  function getSqliteVersion(db) {
41596
42034
  try {
41597
42035
  const row = db.prepare("SELECT sqlite_version() AS v").get();
@@ -41622,24 +42060,24 @@ function restoreGrandfatheredGuards(db, suspended) {
41622
42060
  }
41623
42061
  }
41624
42062
  function writeJournal(stagingDir, journal) {
41625
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
42063
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
41626
42064
  const tmpPath = `${journalPath}.tmp`;
41627
42065
  writeFileSync6(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
41628
42066
  renameSync8(tmpPath, journalPath);
41629
42067
  }
41630
42068
  function readJournal(stagingDir) {
41631
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
41632
- if (!existsSync21(journalPath)) return null;
42069
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
42070
+ if (!existsSync22(journalPath)) return null;
41633
42071
  try {
41634
- return JSON.parse(readFileSync6(journalPath, "utf8"));
42072
+ return JSON.parse(readFileSync7(journalPath, "utf8"));
41635
42073
  } catch {
41636
42074
  return null;
41637
42075
  }
41638
42076
  }
41639
42077
  function clearExodusJournal(stagingDir) {
41640
- const journalPath = join26(stagingDir, JOURNAL_FILENAME);
42078
+ const journalPath = join27(stagingDir, JOURNAL_FILENAME);
41641
42079
  try {
41642
- if (!existsSync21(journalPath)) return false;
42080
+ if (!existsSync22(journalPath)) return false;
41643
42081
  unlinkSync5(journalPath);
41644
42082
  log10.info(
41645
42083
  { stagingDir },
@@ -41935,7 +42373,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
41935
42373
  mkdirSync6(stagingDir, { recursive: true });
41936
42374
  let sqliteVersion = "unknown";
41937
42375
  for (const src of sources) {
41938
- if (existsSync21(src.path)) {
42376
+ if (existsSync22(src.path)) {
41939
42377
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
41940
42378
  sqliteVersion = getSqliteVersion(snap.db);
41941
42379
  snap.close();
@@ -41965,15 +42403,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
41965
42403
  let reseedProject = null;
41966
42404
  try {
41967
42405
  for (const src of sources) {
41968
- if (!existsSync21(src.path)) continue;
41969
- const backupDest = join26(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
42406
+ if (!existsSync22(src.path)) continue;
42407
+ const backupDest = join27(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
41970
42408
  const srcBytes = safeStatBytes(src.path);
41971
42409
  const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
41972
42410
  if (skipStagingCopy) {
41973
42411
  onProgress?.(
41974
42412
  `Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
41975
42413
  );
41976
- } else if (!existsSync21(backupDest)) {
42414
+ } else if (!existsSync22(backupDest)) {
41977
42415
  onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
41978
42416
  copyFileSync5(src.path, backupDest);
41979
42417
  backupPaths.push(backupDest);
@@ -42006,8 +42444,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
42006
42444
  }
42007
42445
  prepareExodusRecovery(projectNative, stagingDir);
42008
42446
  if (globalNative !== null) prepareExodusRecovery(globalNative, stagingDir);
42009
- const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync21(s.path));
42010
- const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync21(s.path));
42447
+ const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
42448
+ const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync22(s.path));
42011
42449
  if (globalNative === null && globalSources.length > 0)
42012
42450
  throw new Error("A projectOnly exodus run was given global-scope sources");
42013
42451
  await migrateScope(
@@ -42315,9 +42753,9 @@ __export(reconcile_exports, {
42315
42753
  reconcileSupersededStores: () => reconcileSupersededStores,
42316
42754
  unmigratedBareSources: () => unmigratedBareSources
42317
42755
  });
42318
- import { copyFileSync as copyFileSync6, existsSync as existsSync22, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
42756
+ import { copyFileSync as copyFileSync6, existsSync as existsSync23, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
42319
42757
  import { tmpdir as tmpdir3 } from "node:os";
42320
- import { basename as basename9, join as join27 } from "node:path";
42758
+ import { basename as basename9, join as join28 } from "node:path";
42321
42759
  function ident2(name2) {
42322
42760
  return `"${name2.replace(/"/g, '""')}"`;
42323
42761
  }
@@ -42386,7 +42824,7 @@ function assessSupersededProjectStores(liveStorePath, sources, resolveTarget = r
42386
42824
  }
42387
42825
  function legacySourcesHoldRows(sources) {
42388
42826
  for (const src of sources) {
42389
- if (!existsSync22(src.path)) continue;
42827
+ if (!existsSync23(src.path)) continue;
42390
42828
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
42391
42829
  try {
42392
42830
  for (const table of orderTablesForCopy(snap.db)) {
@@ -42417,8 +42855,8 @@ async function bareTaskCoreSource(liveStorePath, resolveTarget, outDir) {
42417
42855
  live.close();
42418
42856
  }
42419
42857
  if (tables.length === 0) return null;
42420
- const seedPath = await buildFreshProjectStore(join27(outDir, "fresh-project-seed.db"));
42421
- const path2 = join27(outDir, "cleo-bare-task-core.db");
42858
+ const seedPath = await buildFreshProjectStore(join28(outDir, "fresh-project-seed.db"));
42859
+ const path2 = join28(outDir, "cleo-bare-task-core.db");
42422
42860
  const snap = openCleoDbSnapshot(path2, { readOnly: false });
42423
42861
  let kept = 0;
42424
42862
  try {
@@ -42466,7 +42904,7 @@ async function buildFreshProjectStore(path2) {
42466
42904
  }
42467
42905
  function snapshotFresherBareRows(barePath, legacyTasksPath, stagingDir) {
42468
42906
  if (legacyTasksPath === void 0) return null;
42469
- const path2 = join27(stagingDir, "cleo-bare-task-core-fresher.db");
42907
+ const path2 = join28(stagingDir, "cleo-bare-task-core-fresher.db");
42470
42908
  const snap = openCleoDbSnapshot(barePath, { readOnly: true });
42471
42909
  try {
42472
42910
  snap.db.exec(`VACUUM INTO '${path2.replace(/'/g, "''")}'`);
@@ -42617,7 +43055,7 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
42617
43055
  const additive = options.additive === true;
42618
43056
  const plan = buildExodusPlan(projectRoot);
42619
43057
  const resolveTarget = await buildRuntimeTargetResolver();
42620
- const scratch = mkdtempSync(join27(tmpdir3(), "cleo-reconcile-"));
43058
+ const scratch = mkdtempSync(join28(tmpdir3(), "cleo-reconcile-"));
42621
43059
  try {
42622
43060
  return await reconcileWithScratch(
42623
43061
  projectRoot,
@@ -42633,8 +43071,8 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
42633
43071
  }
42634
43072
  }
42635
43073
  async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath, plan, resolveTarget, scratch) {
42636
- const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync22(s.path));
42637
- const bare = !additive && existsSync22(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
43074
+ const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync23(s.path));
43075
+ const bare = !additive && existsSync23(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
42638
43076
  const copyResolver = additive ? (sourceName, legacyTable) => {
42639
43077
  const r = resolveTarget(sourceName, legacyTable);
42640
43078
  return r.kind !== "skip" && isLiveAuthoritative(sourceName, legacyTable, r.targetName) ? { kind: "skip", reason: "additive: live-authoritative task graph" } : r;
@@ -42653,7 +43091,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42653
43091
  stagingDir: null,
42654
43092
  receiptPath: null
42655
43093
  };
42656
- if (sources.length === 0 || !existsSync22(liveStorePath)) {
43094
+ if (sources.length === 0 || !existsSync23(liveStorePath)) {
42657
43095
  return {
42658
43096
  ...base,
42659
43097
  outcome: "nothing-to-reconcile",
@@ -42693,11 +43131,11 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42693
43131
  };
42694
43132
  }
42695
43133
  const iso = (/* @__PURE__ */ new Date()).toISOString().replace(/[:]/g, "").replace(/\..+Z$/, "Z");
42696
- const stagingDir = join27(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
43134
+ const stagingDir = join28(resolveCleoDir(projectRoot), `${RECONCILE_DIR_PREFIX}${iso}`);
42697
43135
  mkdirSync7(stagingDir, { recursive: true });
42698
43136
  const copySources = sources.map((s) => {
42699
43137
  if (s !== bare) return s;
42700
- const kept = join27(stagingDir, basename9(s.path));
43138
+ const kept = join28(stagingDir, basename9(s.path));
42701
43139
  copyFileSync6(s.path, kept);
42702
43140
  return { ...s, path: kept };
42703
43141
  });
@@ -42717,7 +43155,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42717
43155
  const result = await withLock(
42718
43156
  `${liveStorePath}.exodus-on-open.lock`,
42719
43157
  async () => {
42720
- const liveBefore = join27(scratch, "live-before.db");
43158
+ const liveBefore = join28(scratch, "live-before.db");
42721
43159
  snapshotLive(liveStorePath, liveBefore);
42722
43160
  const migrated = await runExodusMigrate(reconcilePlan, false, (msg) => log11.debug(msg), {
42723
43161
  projectOnly: true,
@@ -42767,7 +43205,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
42767
43205
  },
42768
43206
  { stale: 6e5, retries: 30 }
42769
43207
  );
42770
- const receiptPath = join27(stagingDir, RECEIPT_FILENAME);
43208
+ const receiptPath = join28(stagingDir, RECEIPT_FILENAME);
42771
43209
  const receipt2 = { ...result, receiptPath };
42772
43210
  writeFileSync7(receiptPath, `${JSON.stringify(receipt2, null, 2)}
42773
43211
  `, "utf8");
@@ -42844,20 +43282,20 @@ var init_seal = __esm({
42844
43282
  });
42845
43283
 
42846
43284
  // packages/core/src/store/exodus/status.ts
42847
- import { existsSync as existsSync23, readdirSync as readdirSync6, readFileSync as readFileSync7, statSync as statSync8 } from "node:fs";
42848
- import { join as join28 } from "node:path";
43285
+ import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync8, statSync as statSync8 } from "node:fs";
43286
+ import { join as join29 } from "node:path";
42849
43287
  function readJournal2(stagingDir) {
42850
- const p = join28(stagingDir, JOURNAL_FILENAME2);
42851
- if (!existsSync23(p)) return null;
43288
+ const p = join29(stagingDir, JOURNAL_FILENAME2);
43289
+ if (!existsSync24(p)) return null;
42852
43290
  try {
42853
- return JSON.parse(readFileSync7(p, "utf8"));
43291
+ return JSON.parse(readFileSync8(p, "utf8"));
42854
43292
  } catch {
42855
43293
  return null;
42856
43294
  }
42857
43295
  }
42858
43296
  function findStagingDirs(cleoDir) {
42859
43297
  try {
42860
- return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join28(cleoDir, e.name)).sort().reverse();
43298
+ return readdirSync6(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join29(cleoDir, e.name)).sort().reverse();
42861
43299
  } catch {
42862
43300
  return [];
42863
43301
  }
@@ -42880,15 +43318,15 @@ function runExodusStatus(cwd) {
42880
43318
  const sourcesInfo = plan.sources.map((s) => ({
42881
43319
  name: s.name,
42882
43320
  path: s.path,
42883
- exists: existsSync23(s.path),
43321
+ exists: existsSync24(s.path),
42884
43322
  bytes: safeBytes(s.path)
42885
43323
  }));
42886
43324
  return {
42887
43325
  hasStaging: latestStaging !== null,
42888
43326
  stagingDir: latestStaging,
42889
43327
  journal,
42890
- projectDbExists: existsSync23(projectDbPath),
42891
- globalDbExists: existsSync23(globalDbPath),
43328
+ projectDbExists: existsSync24(projectDbPath),
43329
+ globalDbExists: existsSync24(globalDbPath),
42892
43330
  sourcesPresent: sourcesInfo.some((s) => s.exists),
42893
43331
  sources: sourcesInfo
42894
43332
  };
@@ -42905,8 +43343,8 @@ var init_status = __esm({
42905
43343
  });
42906
43344
 
42907
43345
  // packages/core/src/store/exodus/verify-migration.ts
42908
- import { existsSync as existsSync24 } from "node:fs";
42909
- import { createRequire as createRequire8 } from "node:module";
43346
+ import { existsSync as existsSync25 } from "node:fs";
43347
+ import { createRequire as createRequire9 } from "node:module";
42910
43348
  function orderByClause(db, tableName) {
42911
43349
  try {
42912
43350
  const pragma = db.prepare(`PRAGMA table_info("${tableName}")`).all();
@@ -43170,7 +43608,7 @@ function orphanAlreadyInSource(targetDb, fk, sources, resolveTarget = resolveCon
43170
43608
  const anyFeeder = (targetTable, probe) => {
43171
43609
  for (const feeder of feedersOf(targetTable)) {
43172
43610
  const src = sources.find((s) => s.name === feeder.sourceName);
43173
- if (src === void 0 || !existsSync24(src.path)) continue;
43611
+ if (src === void 0 || !existsSync25(src.path)) continue;
43174
43612
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
43175
43613
  try {
43176
43614
  if (!tableExists3(snap.db, feeder.legacyTable)) continue;
@@ -43225,7 +43663,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43225
43663
  const preExistingForeignKeyViolations = [];
43226
43664
  const failureLines = [];
43227
43665
  const sourceOrphanSigs = /* @__PURE__ */ new Set();
43228
- if (!existsSync24(projectDbPath)) {
43666
+ if (!existsSync25(projectDbPath)) {
43229
43667
  return {
43230
43668
  ok: false,
43231
43669
  tables: [],
@@ -43236,7 +43674,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43236
43674
  error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
43237
43675
  };
43238
43676
  }
43239
- if (!existsSync24(globalDbPath)) {
43677
+ if (!existsSync25(globalDbPath)) {
43240
43678
  return {
43241
43679
  ok: false,
43242
43680
  tables: [],
@@ -43251,7 +43689,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
43251
43689
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
43252
43690
  try {
43253
43691
  for (const src of sources) {
43254
- if (!existsSync24(src.path)) {
43692
+ if (!existsSync25(src.path)) {
43255
43693
  onProgress?.(`Skipping ${src.name} (not present)`);
43256
43694
  continue;
43257
43695
  }
@@ -43446,7 +43884,7 @@ var init_verify_migration = __esm({
43446
43884
  init_column_transforms();
43447
43885
  init_table_name_map();
43448
43886
  log13 = getLogger("verify-migration");
43449
- _require5 = createRequire8(import.meta.url);
43887
+ _require5 = createRequire9(import.meta.url);
43450
43888
  CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
43451
43889
  }
43452
43890
  });
@@ -43542,11 +43980,11 @@ __export(on_open_exports, {
43542
43980
  maybeRunExodusOnOpen: () => maybeRunExodusOnOpen,
43543
43981
  withExodusOnOpenSuppressed: () => withExodusOnOpenSuppressed
43544
43982
  });
43545
- import { existsSync as existsSync25, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
43983
+ import { existsSync as existsSync26, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
43546
43984
  import { tmpdir as tmpdir4 } from "node:os";
43547
- import { join as join29, resolve as resolve11 } from "node:path";
43985
+ import { join as join30, resolve as resolve13 } from "node:path";
43548
43986
  async function withExodusOnOpenSuppressed(dbPath, fn) {
43549
- const key = resolve11(dbPath);
43987
+ const key = resolve13(dbPath);
43550
43988
  _reconcileInProgress.set(key, (_reconcileInProgress.get(key) ?? 0) + 1);
43551
43989
  try {
43552
43990
  return await fn();
@@ -43584,7 +44022,7 @@ function remedyFor(scope) {
43584
44022
  }
43585
44023
  async function strandedLegacySources(scope, cwd) {
43586
44024
  const { buildExodusPlan: buildExodusPlan2, legacySourcesHoldRows: legacySourcesHoldRows2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
43587
- return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync25(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
44025
+ return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync26(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
43588
44026
  }
43589
44027
  async function rollbackBothScopes(plan) {
43590
44028
  const { getDualScopeNativeDb: getDualScopeNativeDb2, openDualScopeDbAtPath: openDualScopeDbAtPath2 } = await Promise.resolve().then(() => (init_dual_scope_db(), dual_scope_db_exports));
@@ -43662,7 +44100,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43662
44100
  if (_exodusInProgress) {
43663
44101
  return { outcome: "skipped", reason: "re-entrant open during active migration" };
43664
44102
  }
43665
- if (_reconcileInProgress.has(resolve11(dbPath))) {
44103
+ if (_reconcileInProgress.has(resolve13(dbPath))) {
43666
44104
  return {
43667
44105
  outcome: "skipped",
43668
44106
  reason: "an explicit superseded-store reconcile of this store is in progress"
@@ -43695,14 +44133,14 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43695
44133
  const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
43696
44134
  const plan = buildExodusPlan2(cwd);
43697
44135
  const plannedTarget = scope === "project" ? plan.projectDbPath : plan.globalDbPath;
43698
- if (resolve11(plannedTarget) !== resolve11(dbPath)) {
44136
+ if (resolve13(plannedTarget) !== resolve13(dbPath)) {
43699
44137
  return {
43700
44138
  outcome: "aborted",
43701
44139
  reason: `migration plan target ${plannedTarget} does not match opened database ${dbPath}; no migration applied`
43702
44140
  };
43703
44141
  }
43704
44142
  const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
43705
- if (!scopeSources.some((s) => existsSync25(s.path))) {
44143
+ if (!scopeSources.some((s) => existsSync26(s.path))) {
43706
44144
  return {
43707
44145
  outcome: "skipped",
43708
44146
  reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
@@ -43719,12 +44157,12 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43719
44157
  {
43720
44158
  scope,
43721
44159
  dbPath,
43722
- sources: plan.sources.filter((s) => existsSync25(s.path)).map((s) => s.name)
44160
+ sources: plan.sources.filter((s) => existsSync26(s.path)).map((s) => s.name)
43723
44161
  },
43724
44162
  "exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
43725
44163
  );
43726
44164
  _exodusInProgress = true;
43727
- const bareScratch = mkdtempSync2(join29(tmpdir4(), "cleo-exodus-bare-"));
44165
+ const bareScratch = mkdtempSync2(join30(tmpdir4(), "cleo-exodus-bare-"));
43728
44166
  try {
43729
44167
  const { buildRuntimeTargetResolver: buildRuntimeTargetResolver2 } = await Promise.resolve().then(() => (init_runtime_targets(), runtime_targets_exports));
43730
44168
  const resolveTarget = await buildRuntimeTargetResolver2();
@@ -43732,7 +44170,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43732
44170
  const bare = scope === "project" ? await unmigratedBareSources2(
43733
44171
  dbPath,
43734
44172
  resolveTarget,
43735
- plan.sources.find((s) => s.name === "tasks" && existsSync25(s.path))?.path,
44173
+ plan.sources.find((s) => s.name === "tasks" && existsSync26(s.path))?.path,
43736
44174
  bareScratch
43737
44175
  ) : { first: [], last: [] };
43738
44176
  const migratePlan = { ...plan, sources: [...bare.first, ...plan.sources, ...bare.last] };
@@ -43796,7 +44234,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
43796
44234
  "exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
43797
44235
  );
43798
44236
  try {
43799
- const consumed = plan.sources.filter((s) => existsSync25(s.path));
44237
+ const consumed = plan.sources.filter((s) => existsSync26(s.path));
43800
44238
  const identities = await sealTargets(plan, consumed);
43801
44239
  const archiveResult = archiveMigratedSources(consumed, cwd, plan, identities);
43802
44240
  log14.info(
@@ -43871,9 +44309,9 @@ __export(dual_scope_db_exports, {
43871
44309
  upsertIdempotent: () => upsertIdempotent,
43872
44310
  withStoreSchemaOwnership: () => withStoreSchemaOwnership
43873
44311
  });
43874
- import { existsSync as existsSync26, mkdirSync as mkdirSync8 } from "node:fs";
43875
- import { createRequire as createRequire9 } from "node:module";
43876
- import { dirname as dirname15, join as join30, resolve as resolve12 } from "node:path";
44312
+ import { existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
44313
+ import { createRequire as createRequire10 } from "node:module";
44314
+ import { dirname as dirname17, join as join31, resolve as resolve14 } from "node:path";
43877
44315
  function getDualScopeNativeDb(handle) {
43878
44316
  const db = handle.db;
43879
44317
  if ("$client" in db && db.$client instanceof getDatabaseSyncCtor()) return db.$client;
@@ -43895,9 +44333,9 @@ function cacheKey(scope, dbPath) {
43895
44333
  }
43896
44334
  function resolveDualScopeDbPath(scope, cwd, capturedGlobalHome) {
43897
44335
  if (scope === "project") {
43898
- return join30(resolveCleoDir(cwd), "cleo.db");
44336
+ return join31(resolveCleoDir(cwd), "cleo.db");
43899
44337
  }
43900
- return join30(capturedGlobalHome ?? getCleoHome(), "cleo.db");
44338
+ return join31(capturedGlobalHome ?? getCleoHome(), "cleo.db");
43901
44339
  }
43902
44340
  function migrationsSetName(scope) {
43903
44341
  return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
@@ -43947,8 +44385,8 @@ async function openDualScopeDb(scope, cwd, options) {
43947
44385
  async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
43948
44386
  execution?.assertActive();
43949
44387
  log15.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
43950
- const dir = dirname15(dbPath);
43951
- if (!existsSync26(dir)) {
44388
+ const dir = dirname17(dbPath);
44389
+ if (!existsSync27(dir)) {
43952
44390
  mkdirSync8(dir, { recursive: true });
43953
44391
  }
43954
44392
  execution?.assertActive();
@@ -43956,6 +44394,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
43956
44394
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
43957
44395
  try {
43958
44396
  applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
44397
+ installSchemaWriteGuard(nativeDb);
43959
44398
  const drizzle2 = getDrizzle();
43960
44399
  const db = drizzle2({ client: nativeDb });
43961
44400
  const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
@@ -44004,11 +44443,12 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
44004
44443
  execution?.assertActive();
44005
44444
  return handle;
44006
44445
  } catch (err) {
44446
+ const explained = explainSchemaWriteDenial(nativeDb, err);
44007
44447
  try {
44008
44448
  nativeDb.close();
44009
44449
  } catch {
44010
44450
  }
44011
- throw err;
44451
+ throw explained;
44012
44452
  }
44013
44453
  }
44014
44454
  async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
@@ -44029,7 +44469,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44029
44469
  );
44030
44470
  }
44031
44471
  const dedicated = options?.dedicated === true;
44032
- const normalizedPath = resolve12(dbPath);
44472
+ const normalizedPath = resolve14(dbPath);
44033
44473
  const key = cacheKey(scope, normalizedPath);
44034
44474
  if (!dedicated) {
44035
44475
  const existing = _cache.get(key);
@@ -44066,8 +44506,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44066
44506
  }
44067
44507
  let initResolve = null;
44068
44508
  let initReject = null;
44069
- const initPromise = new Promise((resolve14, reject) => {
44070
- initResolve = resolve14;
44509
+ const initPromise = new Promise((resolve16, reject) => {
44510
+ initResolve = resolve16;
44071
44511
  initReject = reject;
44072
44512
  });
44073
44513
  _cache.set(key, {
@@ -44088,8 +44528,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44088
44528
  try {
44089
44529
  execution?.assertActive();
44090
44530
  log15.debug({ scope, dbPath: normalizedPath }, "opening dual-scope cleo.db");
44091
- const dir = dirname15(normalizedPath);
44092
- if (!existsSync26(dir)) {
44531
+ const dir = dirname17(normalizedPath);
44532
+ if (!existsSync27(dir)) {
44093
44533
  mkdirSync8(dir, { recursive: true });
44094
44534
  }
44095
44535
  execution?.assertActive();
@@ -44097,6 +44537,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44097
44537
  const nativeDb = new DatabaseSyncCtor(normalizedPath, { allowExtension: true });
44098
44538
  openingNative = nativeDb;
44099
44539
  applyPerfPragmas(nativeDb, memoryBoundedPragmaOverrides());
44540
+ installSchemaWriteGuard(nativeDb);
44100
44541
  const drizzle2 = getDrizzle();
44101
44542
  const db = drizzle2({ client: nativeDb });
44102
44543
  const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
@@ -44227,12 +44668,13 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
44227
44668
  execution?.assertActive();
44228
44669
  initResolve(finalHandle);
44229
44670
  } catch (err) {
44671
+ const explained = openingNative ? explainSchemaWriteDenial(openingNative, err) : err;
44230
44672
  try {
44231
44673
  if (!published && openingNative?.isOpen) openingNative.close();
44232
44674
  } catch (closeError) {
44233
44675
  log15.warn({ closeError }, "failed to close unpublished database initializer");
44234
44676
  }
44235
- initReject(err);
44677
+ initReject(explained);
44236
44678
  }
44237
44679
  })();
44238
44680
  return initPromise;
@@ -44305,6 +44747,7 @@ var init_dual_scope_db = __esm({
44305
44747
  init_relocated_store_guard();
44306
44748
  init_resolve_migrations_folder();
44307
44749
  init_sqlite_pragmas();
44750
+ init_worktree_build_guard();
44308
44751
  init_worktree_isolation_guard();
44309
44752
  init_writer_lease();
44310
44753
  ExodusAbortWriteUnsafeError = class extends Error {
@@ -44327,7 +44770,7 @@ var init_dual_scope_db = __esm({
44327
44770
  }
44328
44771
  };
44329
44772
  _cache = /* @__PURE__ */ new Map();
44330
- _require6 = createRequire9(import.meta.url);
44773
+ _require6 = createRequire10(import.meta.url);
44331
44774
  _drizzle4 = null;
44332
44775
  _DatabaseSyncCtor = null;
44333
44776
  EntryCancelledError = class extends Error {
@@ -44358,7 +44801,7 @@ var init_dual_scope_db = __esm({
44358
44801
  }
44359
44802
  /** @inheritdoc */
44360
44803
  async openProject(dbPath, options) {
44361
- const normalized = resolve12(dbPath);
44804
+ const normalized = resolve14(dbPath);
44362
44805
  if (options?.dedicated) {
44363
44806
  const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
44364
44807
  dedicated: true
@@ -44370,7 +44813,7 @@ var init_dual_scope_db = __esm({
44370
44813
  /** @inheritdoc */
44371
44814
  async openGlobal(options) {
44372
44815
  const dbPath = resolveDualScopeDbPath("global");
44373
- const normalized = resolve12(dbPath);
44816
+ const normalized = resolve14(dbPath);
44374
44817
  if (options?.dedicated) {
44375
44818
  const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
44376
44819
  dedicated: true
@@ -44381,7 +44824,7 @@ var init_dual_scope_db = __esm({
44381
44824
  }
44382
44825
  /** @inheritdoc */
44383
44826
  async openGlobalAt(dbPath, options) {
44384
- const normalized = resolve12(dbPath);
44827
+ const normalized = resolve14(dbPath);
44385
44828
  if (options?.dedicated) {
44386
44829
  const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
44387
44830
  dedicated: true
@@ -44392,7 +44835,7 @@ var init_dual_scope_db = __esm({
44392
44835
  }
44393
44836
  /** @inheritdoc */
44394
44837
  closeProject(dbPath) {
44395
- const normalized = resolve12(dbPath);
44838
+ const normalized = resolve14(dbPath);
44396
44839
  this.closeEntry("project", normalized);
44397
44840
  }
44398
44841
  /** @inheritdoc */
@@ -44429,8 +44872,8 @@ var init_dual_scope_db = __esm({
44429
44872
  const entryId = ++this._nextId;
44430
44873
  let initResolve;
44431
44874
  let initReject;
44432
- const initPromise = new Promise((resolve14, reject) => {
44433
- initResolve = resolve14;
44875
+ const initPromise = new Promise((resolve16, reject) => {
44876
+ initResolve = resolve16;
44434
44877
  initReject = reject;
44435
44878
  });
44436
44879
  this._registry.set(key, { id: entryId, store: null, initPromise });
@@ -45223,8 +45666,8 @@ __export(nexus_sqlite_exports, {
45223
45666
  resetNexusDbState: () => resetNexusDbState,
45224
45667
  resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
45225
45668
  });
45226
- import { copyFileSync as copyFileSync7, existsSync as existsSync27 } from "node:fs";
45227
- import { join as join31 } from "node:path";
45669
+ import { copyFileSync as copyFileSync7, existsSync as existsSync28 } from "node:fs";
45670
+ import { join as join32 } from "node:path";
45228
45671
  function getNexusDbPath(cwd) {
45229
45672
  return resolveDualScopeDbPath("project", cwd);
45230
45673
  }
@@ -45260,12 +45703,13 @@ function ensureGlobalRegistryAttached(nativeDb) {
45260
45703
  }
45261
45704
  }
45262
45705
  nativeDb.exec(`ATTACH DATABASE '${escaped}' AS ${NEXUS_GLOBAL_ATTACH_ALIAS}`);
45706
+ refreshSchemaWriteGuard(nativeDb);
45263
45707
  }
45264
45708
  function resolveNexusMigrationsFolder() {
45265
45709
  return resolveCorePackageMigrationsFolder("drizzle-nexus");
45266
45710
  }
45267
45711
  function getNestedNexusSentinelPath() {
45268
- return join31(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
45712
+ return join32(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
45269
45713
  }
45270
45714
  function detectAndWarnOnNestedNexus() {
45271
45715
  let nestedPath;
@@ -45274,7 +45718,7 @@ function detectAndWarnOnNestedNexus() {
45274
45718
  } catch {
45275
45719
  return false;
45276
45720
  }
45277
- if (!existsSync27(nestedPath)) return false;
45721
+ if (!existsSync28(nestedPath)) return false;
45278
45722
  if (_warnedNestedPaths.has(nestedPath)) return false;
45279
45723
  _warnedNestedPaths.add(nestedPath);
45280
45724
  const canonicalPath = getNexusDbPath();
@@ -45433,7 +45877,7 @@ function runNexusMigrations(nativeDb, db, dbPath) {
45433
45877
  const migrationsFolder = resolveNexusMigrationsFolder();
45434
45878
  if (tableExists4(nativeDb, "nexus_nodes")) {
45435
45879
  const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
45436
- if (!existsSync27(backupPath)) {
45880
+ if (!existsSync28(backupPath)) {
45437
45881
  try {
45438
45882
  copyFileSync7(dbPath, backupPath);
45439
45883
  } catch {
@@ -45528,6 +45972,7 @@ var init_nexus_sqlite = __esm({
45528
45972
  init_resolve_migrations_folder();
45529
45973
  init_nexus_schema();
45530
45974
  init_with_retry();
45975
+ init_worktree_build_guard();
45531
45976
  NEXUS_SCHEMA_VERSION = "1.0.0";
45532
45977
  NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
45533
45978
  NESTED_NEXUS_SENTINEL = "nexus.db";
@@ -45562,15 +46007,15 @@ var init_legacy_alias = __esm({
45562
46007
 
45563
46008
  // packages/core/src/llm/stable-device-id.ts
45564
46009
  import { randomUUID as randomUUID3 } from "node:crypto";
45565
- import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync8, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
45566
- import { dirname as dirname16 } from "node:path";
46010
+ import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync9, writeFileSync as writeFileSync8 } from "node:fs";
46011
+ import { dirname as dirname18 } from "node:path";
45567
46012
  import { resolveStableDeviceIdPath } from "@cleocode/paths";
45568
46013
  function getStableDeviceId() {
45569
46014
  if (_cachedDeviceId !== null) return _cachedDeviceId;
45570
46015
  const path2 = resolveStableDeviceIdPath();
45571
- if (existsSync28(path2)) {
46016
+ if (existsSync29(path2)) {
45572
46017
  try {
45573
- const raw = readFileSync8(path2, "utf-8").trim();
46018
+ const raw = readFileSync9(path2, "utf-8").trim();
45574
46019
  if (raw.length > 0) {
45575
46020
  _cachedDeviceId = raw;
45576
46021
  return raw;
@@ -45580,8 +46025,8 @@ function getStableDeviceId() {
45580
46025
  }
45581
46026
  const fresh = randomUUID3();
45582
46027
  try {
45583
- const dir = dirname16(path2);
45584
- if (!existsSync28(dir)) {
46028
+ const dir = dirname18(path2);
46029
+ if (!existsSync29(dir)) {
45585
46030
  mkdirSync9(dir, { recursive: true });
45586
46031
  }
45587
46032
  const tmpPath = `${path2}.tmp.${process.pid}`;
@@ -45618,8 +46063,8 @@ var init_registry_roots = __esm({
45618
46063
  // packages/core/src/nexus/projects-scan.ts
45619
46064
  async function withinBudget(promise, ms) {
45620
46065
  let timer;
45621
- const expiry = new Promise((resolve14) => {
45622
- timer = setTimeout(() => resolve14("timeout"), ms);
46066
+ const expiry = new Promise((resolve16) => {
46067
+ timer = setTimeout(() => resolve16("timeout"), ms);
45623
46068
  timer.unref();
45624
46069
  });
45625
46070
  try {
@@ -45657,9 +46102,9 @@ __export(path_map_exports, {
45657
46102
  supersededRegistryPath: () => supersededRegistryPath,
45658
46103
  touchProjectLocation: () => touchProjectLocation
45659
46104
  });
45660
- import { existsSync as existsSync29, lstatSync, readdirSync as readdirSync7 } from "node:fs";
46105
+ import { existsSync as existsSync30, lstatSync, readdirSync as readdirSync7 } from "node:fs";
45661
46106
  import { lstat, readdir as readdir2 } from "node:fs/promises";
45662
- import { isAbsolute as isAbsolute4, join as join32, relative as relative2, sep as sep4 } from "node:path";
46107
+ import { isAbsolute as isAbsolute5, join as join33, relative as relative3, sep as sep5 } from "node:path";
45663
46108
  import { canonicalizePath as canonicalizePath3, readDeclaredProjectIdentity as readDeclaredProjectIdentity3 } from "@cleocode/paths";
45664
46109
  import { and as and7, desc as desc3, eq as eq11, inArray as inArray5, ne as ne3 } from "drizzle-orm";
45665
46110
  function holdingKey(projectId, path2) {
@@ -45675,7 +46120,7 @@ function isSupersededRegistryPath(projectPath) {
45675
46120
  return projectPath.startsWith(SUPERSEDED_PATH_PREFIX);
45676
46121
  }
45677
46122
  function projectHolding(path2, projectId) {
45678
- const cleoDir = join32(path2, ".cleo");
46123
+ const cleoDir = join33(path2, ".cleo");
45679
46124
  try {
45680
46125
  lstatSync(cleoDir);
45681
46126
  readdirSync7(cleoDir);
@@ -45687,7 +46132,7 @@ function projectHolding(path2, projectId) {
45687
46132
  return declared === null || declared.projectId === projectId ? "yes" : "no";
45688
46133
  }
45689
46134
  async function probeProjectHolding(path2, projectId, timeoutMs) {
45690
- const cleoDir = join32(path2, ".cleo");
46135
+ const cleoDir = join33(path2, ".cleo");
45691
46136
  const probe = async () => {
45692
46137
  try {
45693
46138
  await lstat(cleoDir);
@@ -45705,8 +46150,8 @@ async function probeProjectHolding(path2, projectId, timeoutMs) {
45705
46150
  return declared === null || declared.projectId === projectId ? "yes" : "no";
45706
46151
  }
45707
46152
  function isStrictlyInside(outer, inner) {
45708
- const rel = relative2(canonicalizePath3(outer), canonicalizePath3(inner));
45709
- return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep4}`) && !isAbsolute4(rel);
46153
+ const rel = relative3(canonicalizePath3(outer), canonicalizePath3(inner));
46154
+ return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep5}`) && !isAbsolute5(rel);
45710
46155
  }
45711
46156
  function locationKey(projectId, deviceId, path2) {
45712
46157
  return and7(
@@ -45868,7 +46313,7 @@ function hasOtherLiveLocation(db, record, deviceId) {
45868
46313
  ne3(projectLocations.path, record.projectPath)
45869
46314
  )
45870
46315
  ).all().some(
45871
- (location) => isStrictlyInside(record.projectPath, location.path) && existsSync29(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record.projectId
46316
+ (location) => isStrictlyInside(record.projectPath, location.path) && existsSync30(location.path) && readDeclaredProjectIdentity3(location.path)?.projectId === record.projectId
45872
46317
  );
45873
46318
  }
45874
46319
  function demoteProjectLocation(db, record, state) {
@@ -45919,7 +46364,7 @@ function rehomeDisplacedRows(db, projectId, projectPath, deviceId, probed) {
45919
46364
  ).orderBy(desc3(projectLocations.lastSeen)).all();
45920
46365
  const present = (path2) => {
45921
46366
  const holding = probed?.get(holdingKey(row.projectId, path2));
45922
- return holding === void 0 ? existsSync29(path2) : holding === "yes";
46367
+ return holding === void 0 ? existsSync30(path2) : holding === "yes";
45923
46368
  };
45924
46369
  const home = candidates.find(
45925
46370
  (c) => present(c.path) && db.select({ projectId: projectRegistry.projectId }).from(projectRegistry).where(eq11(projectRegistry.projectPath, c.path)).all().length === 0
@@ -45948,7 +46393,7 @@ async function listProjectCheckouts(projectId, opts = {}) {
45948
46393
  projectHash: generateProjectHash(row.path),
45949
46394
  firstSeen: row.firstSeen,
45950
46395
  lastSeen: row.lastSeen,
45951
- exists: local && existsSync29(row.path),
46396
+ exists: local && existsSync30(row.path),
45952
46397
  deviceId: local ? deviceId : row.deviceId,
45953
46398
  state: row.state
45954
46399
  });
@@ -45977,13 +46422,13 @@ __export(checkout_nonce_exports, {
45977
46422
  readCheckoutNonce: () => readCheckoutNonce
45978
46423
  });
45979
46424
  import { randomBytes as randomBytes2 } from "node:crypto";
45980
- import { existsSync as existsSync30, readFileSync as readFileSync9, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
45981
- import { join as join33 } from "node:path";
46425
+ import { existsSync as existsSync31, readFileSync as readFileSync10, renameSync as renameSync10, writeFileSync as writeFileSync9 } from "node:fs";
46426
+ import { join as join34 } from "node:path";
45982
46427
  function readInfo(projectRoot) {
45983
- const path2 = join33(projectRoot, ".cleo", "project-info.json");
45984
- if (!existsSync30(path2)) return null;
46428
+ const path2 = join34(projectRoot, ".cleo", "project-info.json");
46429
+ if (!existsSync31(path2)) return null;
45985
46430
  try {
45986
- const parsed = JSON.parse(readFileSync9(path2, "utf-8"));
46431
+ const parsed = JSON.parse(readFileSync10(path2, "utf-8"));
45987
46432
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
45988
46433
  } catch {
45989
46434
  return null;
@@ -45999,7 +46444,7 @@ function ensureCheckoutNonce(projectRoot) {
45999
46444
  const info = readInfo(projectRoot);
46000
46445
  if (!info) return null;
46001
46446
  const nonce = randomBytes2(16).toString("hex");
46002
- const path2 = join33(projectRoot, ".cleo", "project-info.json");
46447
+ const path2 = join34(projectRoot, ".cleo", "project-info.json");
46003
46448
  const temp = `${path2}.${randomBytes2(6).toString("hex")}.tmp`;
46004
46449
  writeFileSync9(temp, `${JSON.stringify({ ...info, [CHECKOUT_NONCE_FIELD]: nonce }, null, 2)}
46005
46450
  `);
@@ -46074,10 +46519,10 @@ __export(paths_exports, {
46074
46519
  validateProjectRoot: () => validateProjectRoot,
46075
46520
  worktreeScope: () => worktreeScope
46076
46521
  });
46077
- import { existsSync as existsSync31, readFileSync as readFileSync10, statSync as statSync9 } from "node:fs";
46078
- import { createRequire as createRequire10 } from "node:module";
46522
+ import { existsSync as existsSync32, readFileSync as readFileSync11, statSync as statSync9 } from "node:fs";
46523
+ import { createRequire as createRequire11 } from "node:module";
46079
46524
  import { homedir as homedir2 } from "node:os";
46080
- import { basename as basename10, dirname as dirname17, join as join34, resolve as resolve13 } from "node:path";
46525
+ import { basename as basename10, dirname as dirname19, join as join35, resolve as resolve15 } from "node:path";
46081
46526
  import {
46082
46527
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
46083
46528
  getCleoTemplatesTildePath as _getCleoTemplatesTildePath,
@@ -46087,7 +46532,7 @@ import {
46087
46532
  resolveCanonicalCleoDir as _resolveCanonicalCleoDir
46088
46533
  } from "@cleocode/paths";
46089
46534
  function _getDatabaseSyncCtor() {
46090
- const _require7 = createRequire10(import.meta.url);
46535
+ const _require7 = createRequire11(import.meta.url);
46091
46536
  const mod = _require7("node:sqlite");
46092
46537
  return mod.DatabaseSync;
46093
46538
  }
@@ -46099,20 +46544,20 @@ function runWithWorktreeScopeFromEnv(fn) {
46099
46544
  }
46100
46545
  function isProjectInitialized(projectRoot) {
46101
46546
  const root = projectRoot ?? getProjectRoot();
46102
- const cleoDir = join34(root, ".cleo");
46103
- return existsSync31(cleoDir) && existsSync31(join34(cleoDir, "tasks.db"));
46547
+ const cleoDir = join35(root, ".cleo");
46548
+ return existsSync32(cleoDir) && existsSync32(join35(cleoDir, "tasks.db"));
46104
46549
  }
46105
46550
  function getCleoHome() {
46106
46551
  return getPlatformPaths().data;
46107
46552
  }
46108
46553
  function getCleoTemplatesDir() {
46109
- return join34(getCleoHome(), "templates");
46554
+ return join35(getCleoHome(), "templates");
46110
46555
  }
46111
46556
  function getCleoSchemasDir() {
46112
- return join34(getCleoHome(), "schemas");
46557
+ return join35(getCleoHome(), "schemas");
46113
46558
  }
46114
46559
  function getCleoDocsDir() {
46115
- return join34(getCleoHome(), "docs");
46560
+ return join35(getCleoHome(), "docs");
46116
46561
  }
46117
46562
  function getCleoDir(cwd) {
46118
46563
  if (cwd) {
@@ -46161,24 +46606,24 @@ function getCleoDirAbsolute(cwd, opts) {
46161
46606
  try {
46162
46607
  const projectRoot = getProjectRoot(cwd);
46163
46608
  const canonical = _resolveCanonicalCleoDir(project.projectId);
46164
- if (canonical !== null && canonical === resolve13(projectRoot, cleoDir)) {
46609
+ if (canonical !== null && canonical === resolve15(projectRoot, cleoDir)) {
46165
46610
  return canonical;
46166
46611
  }
46167
- return resolve13(projectRoot, cleoDir);
46612
+ return resolve15(projectRoot, cleoDir);
46168
46613
  } catch {
46169
- return resolve13(project.projectRoot, cleoDir);
46614
+ return resolve15(project.projectRoot, cleoDir);
46170
46615
  }
46171
46616
  }
46172
46617
  try {
46173
- return resolve13(getProjectRoot(cwd), cleoDir);
46618
+ return resolve15(getProjectRoot(cwd), cleoDir);
46174
46619
  } catch (err) {
46175
46620
  if (opts?.bootstrap) {
46176
- return resolve13(cwd ?? process.cwd(), cleoDir);
46621
+ return resolve15(cwd ?? process.cwd(), cleoDir);
46177
46622
  }
46178
46623
  if (_cwdHasGitAncestor(cwd)) {
46179
46624
  throw err;
46180
46625
  }
46181
- return resolve13(cwd ?? process.cwd(), cleoDir);
46626
+ return resolve15(cwd ?? process.cwd(), cleoDir);
46182
46627
  }
46183
46628
  }
46184
46629
  function resolveCanonicalCleoDir(projectId) {
@@ -46205,9 +46650,9 @@ function resolveCanonicalCleoDir(projectId) {
46205
46650
  function _resolveProjectByCwdFromNexus(cwd) {
46206
46651
  try {
46207
46652
  const cleoHome = getCleoHome();
46208
- const globalDbPath = join34(cleoHome, "cleo.db");
46209
- if (!existsSync31(globalDbPath)) return null;
46210
- const start = resolve13(cwd ?? process.cwd());
46653
+ const globalDbPath = join35(cleoHome, "cleo.db");
46654
+ if (!existsSync32(globalDbPath)) return null;
46655
+ const start = resolve15(cwd ?? process.cwd());
46211
46656
  let current = start;
46212
46657
  const DatabaseSync3 = _getDatabaseSyncCtor();
46213
46658
  const db = new DatabaseSync3(globalDbPath, { readOnly: true });
@@ -46220,7 +46665,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
46220
46665
  if (row && typeof row.project_id === "string" && row.project_id.length > 0) {
46221
46666
  return row.project_id;
46222
46667
  }
46223
- const parent = dirname17(current);
46668
+ const parent = dirname19(current);
46224
46669
  if (parent === current) break;
46225
46670
  current = parent;
46226
46671
  }
@@ -46240,18 +46685,18 @@ function _cleoDirEnvOverride() {
46240
46685
  }
46241
46686
  function _findCleoDirRoot(cwd) {
46242
46687
  const homeRoot = homedir2();
46243
- let current = resolve13(cwd ?? process.cwd());
46688
+ let current = resolve15(cwd ?? process.cwd());
46244
46689
  while (true) {
46245
46690
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
46246
46691
  if (!isDangerousRoot) {
46247
46692
  try {
46248
- if (statSync9(join34(current, ".cleo")).isDirectory()) {
46693
+ if (statSync9(join35(current, ".cleo")).isDirectory()) {
46249
46694
  return current;
46250
46695
  }
46251
46696
  } catch {
46252
46697
  }
46253
46698
  }
46254
- const parent = dirname17(current);
46699
+ const parent = dirname19(current);
46255
46700
  if (parent === current) break;
46256
46701
  current = parent;
46257
46702
  }
@@ -46270,7 +46715,7 @@ function resolveProjectByCwd(cwd) {
46270
46715
  if (pathsResult !== null) {
46271
46716
  return pathsResult.projectId;
46272
46717
  }
46273
- const start = resolve13(from ?? process.cwd());
46718
+ const start = resolve15(from ?? process.cwd());
46274
46719
  let current = start;
46275
46720
  while (true) {
46276
46721
  const mainRepo = _resolveMainRepoFromGitlink(current);
@@ -46281,7 +46726,7 @@ function resolveProjectByCwd(cwd) {
46281
46726
  }
46282
46727
  break;
46283
46728
  }
46284
- const parent = dirname17(current);
46729
+ const parent = dirname19(current);
46285
46730
  if (parent === current) break;
46286
46731
  current = parent;
46287
46732
  }
@@ -46300,7 +46745,7 @@ function resolveProjectByCwd(cwd) {
46300
46745
  function resolveCleoDir(cwd) {
46301
46746
  const scope = worktreeScope.getStore();
46302
46747
  if (scope !== void 0) {
46303
- return join34(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
46748
+ return join35(resolveStoreOwnerRoot(scope.worktreeRoot), ".cleo");
46304
46749
  }
46305
46750
  const override = _cleoDirEnvOverride();
46306
46751
  if (override !== null) {
@@ -46308,16 +46753,16 @@ function resolveCleoDir(cwd) {
46308
46753
  }
46309
46754
  const root = _findCleoDirRoot(cwd);
46310
46755
  if (root !== null) {
46311
- return join34(resolveStoreOwnerRoot(root), ".cleo");
46756
+ return join35(resolveStoreOwnerRoot(root), ".cleo");
46312
46757
  }
46313
- const start = resolve13(cwd ?? process.cwd());
46758
+ const start = resolve15(cwd ?? process.cwd());
46314
46759
  let current = start;
46315
46760
  while (true) {
46316
46761
  const mainRepo = _resolveMainRepoFromGitlink(current);
46317
46762
  if (mainRepo !== null) {
46318
- return join34(mainRepo, ".cleo");
46763
+ return join35(mainRepo, ".cleo");
46319
46764
  }
46320
- const parent = dirname17(current);
46765
+ const parent = dirname19(current);
46321
46766
  if (parent === current) {
46322
46767
  break;
46323
46768
  }
@@ -46356,25 +46801,25 @@ function _resolveCleoDir(cwd) {
46356
46801
  const project = _pathsResolveProjectByCwd(cwd);
46357
46802
  if (project !== null) {
46358
46803
  try {
46359
- return resolve13(getProjectRoot(cwd), cleoDir);
46804
+ return resolve15(getProjectRoot(cwd), cleoDir);
46360
46805
  } catch {
46361
- return resolve13(project.projectRoot, cleoDir);
46806
+ return resolve15(project.projectRoot, cleoDir);
46362
46807
  }
46363
46808
  }
46364
46809
  return getCleoDirAbsolute(cwd);
46365
46810
  }
46366
46811
  function _cwdHasGitAncestor(cwd) {
46367
- const start = resolve13(cwd ?? process.cwd());
46812
+ const start = resolve15(cwd ?? process.cwd());
46368
46813
  let current = start;
46369
46814
  while (true) {
46370
- const gitMarker = join34(current, ".git");
46815
+ const gitMarker = join35(current, ".git");
46371
46816
  try {
46372
- if (existsSync31(gitMarker)) {
46817
+ if (existsSync32(gitMarker)) {
46373
46818
  return true;
46374
46819
  }
46375
46820
  } catch {
46376
46821
  }
46377
- const parent = dirname17(current);
46822
+ const parent = dirname19(current);
46378
46823
  if (parent === current) return false;
46379
46824
  current = parent;
46380
46825
  }
@@ -46401,55 +46846,55 @@ function resolveProjectPath(relativePath, cwd) {
46401
46846
  return relativePath;
46402
46847
  }
46403
46848
  if (relativePath.startsWith("~/") || relativePath.startsWith("~\\") || relativePath === "~") {
46404
- return resolve13(homedir2(), relativePath.slice(2));
46849
+ return resolve15(homedir2(), relativePath.slice(2));
46405
46850
  }
46406
- return resolve13(getProjectRoot(cwd), relativePath);
46851
+ return resolve15(getProjectRoot(cwd), relativePath);
46407
46852
  }
46408
46853
  function getTaskPath(cwd) {
46409
- return join34(_resolveCleoDir(cwd), "tasks.db");
46854
+ return join35(_resolveCleoDir(cwd), "tasks.db");
46410
46855
  }
46411
46856
  function getConfigPath(cwd) {
46412
- return join34(_resolveCleoDir(cwd), "config.json");
46857
+ return join35(_resolveCleoDir(cwd), "config.json");
46413
46858
  }
46414
46859
  function getSessionsPath(cwd) {
46415
- return join34(_resolveCleoDir(cwd), "sessions.json");
46860
+ return join35(_resolveCleoDir(cwd), "sessions.json");
46416
46861
  }
46417
46862
  function getArchivePath(cwd) {
46418
- return join34(_resolveCleoDir(cwd), "tasks-archive.json");
46863
+ return join35(_resolveCleoDir(cwd), "tasks-archive.json");
46419
46864
  }
46420
46865
  function getLogPath(cwd) {
46421
- return join34(_resolveCleoDir(cwd), "logs", "cleo.log");
46866
+ return join35(_resolveCleoDir(cwd), "logs", "cleo.log");
46422
46867
  }
46423
46868
  function getBackupDir(cwd) {
46424
- return join34(_resolveCleoDir(cwd), "backups", "operational");
46869
+ return join35(_resolveCleoDir(cwd), "backups", "operational");
46425
46870
  }
46426
46871
  function getGlobalConfigPath() {
46427
- return join34(getCleoHome(), "config.json");
46872
+ return join35(getCleoHome(), "config.json");
46428
46873
  }
46429
46874
  function getCleoGlobalRecipesDir() {
46430
- return join34(getCleoHome(), "global-recipes");
46875
+ return join35(getCleoHome(), "global-recipes");
46431
46876
  }
46432
46877
  function getCleoGlobalJustfilePath() {
46433
- return join34(getCleoGlobalRecipesDir(), "justfile");
46878
+ return join35(getCleoGlobalRecipesDir(), "justfile");
46434
46879
  }
46435
46880
  function getCleoPiExtensionsDir() {
46436
- return join34(getCleoHome(), "pi-extensions");
46881
+ return join35(getCleoHome(), "pi-extensions");
46437
46882
  }
46438
46883
  function getCleoCantWorkflowsDir() {
46439
- return join34(getCleoHome(), "cant-workflows");
46884
+ return join35(getCleoHome(), "cant-workflows");
46440
46885
  }
46441
46886
  function getCleoGlobalAgentsDir() {
46442
- return join34(getCleoHome(), "agents");
46887
+ return join35(getCleoHome(), "agents");
46443
46888
  }
46444
46889
  function getCleoGlobalCantAgentsDir() {
46445
- return join34(getCleoHome(), "cant", "agents");
46890
+ return join35(getCleoHome(), "cant", "agents");
46446
46891
  }
46447
46892
  function getAgentOutputsDir(cwd) {
46448
46893
  const projectRoot = getProjectRoot(cwd);
46449
- const configPath = join34(projectRoot, ".cleo", "config.json");
46450
- if (existsSync31(configPath)) {
46894
+ const configPath = join35(projectRoot, ".cleo", "config.json");
46895
+ if (existsSync32(configPath)) {
46451
46896
  try {
46452
- const config = JSON.parse(readFileSync10(configPath, "utf-8"));
46897
+ const config = JSON.parse(readFileSync11(configPath, "utf-8"));
46453
46898
  if (typeof config.agentOutputs === "object" && config.agentOutputs?.directory) {
46454
46899
  return config.agentOutputs.directory;
46455
46900
  }
@@ -46472,17 +46917,17 @@ function getAgentOutputsAbsolute(cwd) {
46472
46917
  if (isAbsolutePath2(dir)) {
46473
46918
  return dir;
46474
46919
  }
46475
- return resolve13(getProjectRoot(cwd), dir);
46920
+ return resolve15(getProjectRoot(cwd), dir);
46476
46921
  }
46477
46922
  function getManifestPath(cwd) {
46478
46923
  const outputDir = getAgentOutputsDir(cwd);
46479
46924
  const projectRoot = getProjectRoot(cwd);
46480
- const configPath = join34(projectRoot, ".cleo", "config.json");
46925
+ const configPath = join35(projectRoot, ".cleo", "config.json");
46481
46926
  const legacyFileName = ["MANIFEST", "jsonl"].join(".");
46482
46927
  let manifestFile = legacyFileName;
46483
- if (existsSync31(configPath)) {
46928
+ if (existsSync32(configPath)) {
46484
46929
  try {
46485
- const config = JSON.parse(readFileSync10(configPath, "utf-8"));
46930
+ const config = JSON.parse(readFileSync11(configPath, "utf-8"));
46486
46931
  const customFile = config.agentOutputs?.manifestFile ?? config.research?.manifestFile;
46487
46932
  if (customFile) {
46488
46933
  manifestFile = customFile;
@@ -46490,12 +46935,12 @@ function getManifestPath(cwd) {
46490
46935
  } catch {
46491
46936
  }
46492
46937
  }
46493
- return resolve13(projectRoot, outputDir, manifestFile);
46938
+ return resolve15(projectRoot, outputDir, manifestFile);
46494
46939
  }
46495
46940
  function getManifestArchivePath(cwd) {
46496
46941
  const outputDir = getAgentOutputsDir(cwd);
46497
46942
  const projectRoot = getProjectRoot(cwd);
46498
- return resolve13(projectRoot, outputDir, "MANIFEST.archive.jsonl");
46943
+ return resolve15(projectRoot, outputDir, "MANIFEST.archive.jsonl");
46499
46944
  }
46500
46945
  function isAbsolutePath2(path2) {
46501
46946
  return _isAbsolutePath(path2);
@@ -46519,24 +46964,24 @@ function getCanonicalTemplatesTildePath() {
46519
46964
  return _getCanonicalTemplatesTildePath();
46520
46965
  }
46521
46966
  function getAgentsHome() {
46522
- return process.env["AGENTS_HOME"] ?? join34(homedir2(), ".agents");
46967
+ return process.env["AGENTS_HOME"] ?? join35(homedir2(), ".agents");
46523
46968
  }
46524
46969
  function getClaudeAgentsDir() {
46525
- const claudeDir = process.env["CLAUDE_HOME"] ?? join34(homedir2(), ".claude");
46526
- return join34(claudeDir, "agents");
46970
+ const claudeDir = process.env["CLAUDE_HOME"] ?? join35(homedir2(), ".claude");
46971
+ return join35(claudeDir, "agents");
46527
46972
  }
46528
46973
  function getClaudeMemDbPath() {
46529
- return process.env["CLAUDE_MEM_DB"] ?? join34(homedir2(), ".claude-mem", "claude-mem.db");
46974
+ return process.env["CLAUDE_MEM_DB"] ?? join35(homedir2(), ".claude-mem", "claude-mem.db");
46530
46975
  }
46531
46976
  function resolveWorktreeRouting(cwdOverride) {
46532
- const cwd = resolve13(cwdOverride ?? process.cwd());
46977
+ const cwd = resolve15(cwdOverride ?? process.cwd());
46533
46978
  const home = homedir2();
46534
46979
  let worktreePath;
46535
46980
  let current = cwd;
46536
46981
  while (current !== home && current !== "/" && current !== "") {
46537
- const gitPath = join34(current, ".git");
46982
+ const gitPath = join35(current, ".git");
46538
46983
  try {
46539
- if (existsSync31(gitPath)) {
46984
+ if (existsSync32(gitPath)) {
46540
46985
  const stat3 = statSync9(gitPath);
46541
46986
  if (stat3.isFile()) {
46542
46987
  worktreePath = current;
@@ -46548,7 +46993,7 @@ function resolveWorktreeRouting(cwdOverride) {
46548
46993
  }
46549
46994
  } catch {
46550
46995
  }
46551
- const parent = dirname17(current);
46996
+ const parent = dirname19(current);
46552
46997
  if (parent === current) break;
46553
46998
  current = parent;
46554
46999
  }
@@ -46565,17 +47010,17 @@ function resolveWorktreeRouting(cwdOverride) {
46565
47010
  }
46566
47011
  function resolveWorktreeFilePath(filePath, routing) {
46567
47012
  if (!routing.isWorktree || routing.worktreePath === void 0) {
46568
- return resolve13(filePath);
47013
+ return resolve15(filePath);
46569
47014
  }
46570
- return resolve13(routing.cwd, filePath);
47015
+ return resolve15(routing.cwd, filePath);
46571
47016
  }
46572
47017
  function detectStrayCleoDb(routing) {
46573
47018
  if (!routing.isWorktree || routing.worktreePath === void 0) {
46574
47019
  return void 0;
46575
47020
  }
46576
- const tasksDbPath = join34(routing.worktreePath, ".cleo", "tasks.db");
47021
+ const tasksDbPath = join35(routing.worktreePath, ".cleo", "tasks.db");
46577
47022
  try {
46578
- if (existsSync31(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
47023
+ if (existsSync32(tasksDbPath) && statSync9(tasksDbPath).isFile()) {
46579
47024
  return tasksDbPath;
46580
47025
  }
46581
47026
  } catch {
@@ -46585,7 +47030,7 @@ function detectStrayCleoDb(routing) {
46585
47030
  async function resolveProjectById(projectId) {
46586
47031
  try {
46587
47032
  const { getNexusDb: getNexusDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
46588
- if (!existsSync31(getNexusRegistryDbPath2())) return null;
47033
+ if (!existsSync32(getNexusRegistryDbPath2())) return null;
46589
47034
  const { eq: eq14 } = await import("drizzle-orm");
46590
47035
  const { projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
46591
47036
  const db = await getNexusDb2();
@@ -46620,9 +47065,9 @@ function _rowToRegistryEntry(row) {
46620
47065
  };
46621
47066
  }
46622
47067
  function _readProjectNameFromInfo(projectRoot) {
46623
- const infoPath = join34(projectRoot, ".cleo", "project-info.json");
46624
- if (!existsSync31(infoPath)) return void 0;
46625
- const raw = readFileSync10(infoPath, "utf-8");
47068
+ const infoPath = join35(projectRoot, ".cleo", "project-info.json");
47069
+ if (!existsSync32(infoPath)) return void 0;
47070
+ const raw = readFileSync11(infoPath, "utf-8");
46626
47071
  const data = JSON.parse(raw);
46627
47072
  return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
46628
47073
  }
@@ -46673,7 +47118,7 @@ async function recordProjectEncounter(cwd) {
46673
47118
  if (!shouldAutoRegisterProject(project.projectRoot, cleoHome)) return "ephemeral";
46674
47119
  const checkout = captureProjectScope(project.projectRoot, worktreeScope.getStore()).worktreeRoot;
46675
47120
  const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
46676
- if (existsSync31(getNexusRegistryDbPath2(cleoHome))) {
47121
+ if (existsSync32(getNexusRegistryDbPath2(cleoHome))) {
46677
47122
  const { and: and10, eq: eq14 } = await import("drizzle-orm");
46678
47123
  const { projectLocations: projectLocations2, projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
46679
47124
  const { currentDeviceId: currentDeviceId2 } = await Promise.resolve().then(() => (init_path_map(), path_map_exports));