@cleocode/core 2026.5.134 → 2026.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (557) hide show
  1. package/binaries/README.md +49 -27
  2. package/dist/agents/{agent-registry.d.ts → agent-capacity-tracker.d.ts} +2 -2
  3. package/dist/agents/agent-capacity-tracker.d.ts.map +1 -0
  4. package/dist/agents/{agent-registry.js → agent-capacity-tracker.js} +2 -2
  5. package/dist/agents/agent-capacity-tracker.js.map +1 -0
  6. package/dist/agents/index.d.ts +1 -1
  7. package/dist/agents/index.d.ts.map +1 -1
  8. package/dist/agents/index.js +4 -2
  9. package/dist/agents/index.js.map +1 -1
  10. package/dist/agents/seed-install.d.ts +1 -1
  11. package/dist/agents/seed-install.d.ts.map +1 -1
  12. package/dist/agents/seed-install.js +42 -36
  13. package/dist/agents/seed-install.js.map +1 -1
  14. package/dist/caamp-export.d.ts +18 -0
  15. package/dist/caamp-export.d.ts.map +1 -0
  16. package/dist/caamp-export.js +18 -0
  17. package/dist/caamp-export.js.map +1 -0
  18. package/dist/conduit/http-transport.d.ts +7 -13
  19. package/dist/conduit/http-transport.d.ts.map +1 -1
  20. package/dist/conduit/http-transport.js +12 -59
  21. package/dist/conduit/http-transport.js.map +1 -1
  22. package/dist/conduit/local-transport.d.ts +1 -1
  23. package/dist/conduit/local-transport.d.ts.map +1 -1
  24. package/dist/conduit/local-transport.js +69 -43
  25. package/dist/conduit/local-transport.js.map +1 -1
  26. package/dist/dispatch/mutate-projection.d.ts.map +1 -1
  27. package/dist/dispatch/mutate-projection.js +11 -0
  28. package/dist/dispatch/mutate-projection.js.map +1 -1
  29. package/dist/docs/docs-read-model.d.ts +7 -0
  30. package/dist/docs/docs-read-model.d.ts.map +1 -1
  31. package/dist/docs/docs-read-model.js +5 -0
  32. package/dist/docs/docs-read-model.js.map +1 -1
  33. package/dist/docs/export-document.js +40526 -281
  34. package/dist/docs/export-document.js.map +6 -1
  35. package/dist/docs/supersede.d.ts.map +1 -1
  36. package/dist/docs/supersede.js +12 -7
  37. package/dist/docs/supersede.js.map +1 -1
  38. package/dist/doctor/db-substrate.d.ts.map +1 -1
  39. package/dist/doctor/db-substrate.js +10 -9
  40. package/dist/doctor/db-substrate.js.map +1 -1
  41. package/dist/git-shim-export.d.ts +18 -0
  42. package/dist/git-shim-export.d.ts.map +1 -0
  43. package/dist/git-shim-export.js +18 -0
  44. package/dist/git-shim-export.js.map +1 -0
  45. package/dist/hooks/payload-schemas.d.ts +2 -2
  46. package/dist/init.d.ts.map +1 -1
  47. package/dist/init.js +39 -32
  48. package/dist/init.js.map +1 -1
  49. package/dist/internal.d.ts +11 -3
  50. package/dist/internal.d.ts.map +1 -1
  51. package/dist/internal.js +14 -5
  52. package/dist/internal.js.map +1 -1
  53. package/dist/lafs-export.d.ts +18 -0
  54. package/dist/lafs-export.d.ts.map +1 -0
  55. package/dist/lafs-export.js +18 -0
  56. package/dist/lafs-export.js.map +1 -0
  57. package/dist/lifecycle/effective-stage.js +1 -1
  58. package/dist/lifecycle/index.js +1 -1
  59. package/dist/lifecycle/index.js.map +1 -1
  60. package/dist/lifecycle/rollup.js +1 -1
  61. package/dist/llm/credential-pool.d.ts +17 -0
  62. package/dist/llm/credential-pool.d.ts.map +1 -1
  63. package/dist/llm/credential-pool.js +40 -1
  64. package/dist/llm/credential-pool.js.map +1 -1
  65. package/dist/llm/plugin-facade.d.ts.map +1 -1
  66. package/dist/llm/plugin-facade.js +43392 -354
  67. package/dist/llm/plugin-facade.js.map +6 -1
  68. package/dist/llm/role-executor.d.ts +8 -0
  69. package/dist/llm/role-executor.d.ts.map +1 -1
  70. package/dist/llm/role-executor.js +96 -4
  71. package/dist/llm/role-executor.js.map +1 -1
  72. package/dist/llm/role-resolver.d.ts.map +1 -1
  73. package/dist/llm/role-resolver.js +56 -1
  74. package/dist/llm/role-resolver.js.map +1 -1
  75. package/dist/llm/transports/codex-oauth-headers.d.ts +51 -0
  76. package/dist/llm/transports/codex-oauth-headers.d.ts.map +1 -0
  77. package/dist/llm/transports/codex-oauth-headers.js +89 -0
  78. package/dist/llm/transports/codex-oauth-headers.js.map +1 -0
  79. package/dist/memory/claude-mem-migration.d.ts.map +1 -1
  80. package/dist/memory/claude-mem-migration.js +1 -3
  81. package/dist/memory/claude-mem-migration.js.map +1 -1
  82. package/dist/memory/decisions.d.ts.map +1 -1
  83. package/dist/memory/decisions.js +77 -23
  84. package/dist/memory/decisions.js.map +1 -1
  85. package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
  86. package/dist/memory/graph-memory-bridge.js +12 -6
  87. package/dist/memory/graph-memory-bridge.js.map +1 -1
  88. package/dist/memory/learnings.d.ts +2 -2
  89. package/dist/memory/nexus-plasticity.d.ts +21 -9
  90. package/dist/memory/nexus-plasticity.d.ts.map +1 -1
  91. package/dist/memory/nexus-plasticity.js +44 -22
  92. package/dist/memory/nexus-plasticity.js.map +1 -1
  93. package/dist/memory/patterns.d.ts +2 -2
  94. package/dist/memory/redaction.d.ts +19 -3
  95. package/dist/memory/redaction.d.ts.map +1 -1
  96. package/dist/memory/redaction.js +64 -129
  97. package/dist/memory/redaction.js.map +6 -1
  98. package/dist/metrics/token-service.d.ts +8 -2
  99. package/dist/metrics/token-service.d.ts.map +1 -1
  100. package/dist/metrics/token-service.js +1 -1
  101. package/dist/metrics/token-service.js.map +1 -1
  102. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  103. package/dist/nexus/analyze-orchestrator.js +6 -8
  104. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  105. package/dist/nexus/api-extractors/http-extractor.d.ts.map +1 -1
  106. package/dist/nexus/api-extractors/http-extractor.js +3 -3
  107. package/dist/nexus/api-extractors/http-extractor.js.map +1 -1
  108. package/dist/nexus/clusters.d.ts.map +1 -1
  109. package/dist/nexus/clusters.js +3 -2
  110. package/dist/nexus/clusters.js.map +1 -1
  111. package/dist/nexus/context.d.ts.map +1 -1
  112. package/dist/nexus/context.js +10 -16
  113. package/dist/nexus/context.js.map +1 -1
  114. package/dist/nexus/diff.d.ts.map +1 -1
  115. package/dist/nexus/diff.js +6 -4
  116. package/dist/nexus/diff.js.map +1 -1
  117. package/dist/nexus/export.d.ts.map +1 -1
  118. package/dist/nexus/export.js +7 -4
  119. package/dist/nexus/export.js.map +1 -1
  120. package/dist/nexus/flows.d.ts.map +1 -1
  121. package/dist/nexus/flows.js +3 -1
  122. package/dist/nexus/flows.js.map +1 -1
  123. package/dist/nexus/impact.d.ts +1 -1
  124. package/dist/nexus/impact.d.ts.map +1 -1
  125. package/dist/nexus/impact.js +31 -17
  126. package/dist/nexus/impact.js.map +1 -1
  127. package/dist/nexus/living-brain.d.ts.map +1 -1
  128. package/dist/nexus/living-brain.js +27 -15
  129. package/dist/nexus/living-brain.js.map +1 -1
  130. package/dist/nexus/nexus-bridge.d.ts.map +1 -1
  131. package/dist/nexus/nexus-bridge.js +28 -29
  132. package/dist/nexus/nexus-bridge.js.map +1 -1
  133. package/dist/nexus/plasticity-queries.d.ts +4 -2
  134. package/dist/nexus/plasticity-queries.d.ts.map +1 -1
  135. package/dist/nexus/plasticity-queries.js +27 -15
  136. package/dist/nexus/plasticity-queries.js.map +1 -1
  137. package/dist/nexus/query.d.ts.map +1 -1
  138. package/dist/nexus/query.js +6 -2
  139. package/dist/nexus/query.js.map +1 -1
  140. package/dist/nexus/registry.d.ts.map +1 -1
  141. package/dist/nexus/registry.js +65 -30
  142. package/dist/nexus/registry.js.map +1 -1
  143. package/dist/nexus/route-analysis.d.ts +3 -2
  144. package/dist/nexus/route-analysis.d.ts.map +1 -1
  145. package/dist/nexus/route-analysis.js +11 -10
  146. package/dist/nexus/route-analysis.js.map +1 -1
  147. package/dist/nexus/sigil.d.ts.map +1 -1
  148. package/dist/nexus/sigil.js +60 -13
  149. package/dist/nexus/sigil.js.map +1 -1
  150. package/dist/nexus/user-profile.d.ts +2 -1
  151. package/dist/nexus/user-profile.d.ts.map +1 -1
  152. package/dist/nexus/user-profile.js +8 -4
  153. package/dist/nexus/user-profile.js.map +1 -1
  154. package/dist/orchestrate/index.d.ts +1 -1
  155. package/dist/orchestrate/index.d.ts.map +1 -1
  156. package/dist/orchestrate/index.js +1 -1
  157. package/dist/orchestrate/index.js.map +1 -1
  158. package/dist/orchestrate/plan.d.ts +3 -3
  159. package/dist/orchestrate/plan.d.ts.map +1 -1
  160. package/dist/orchestrate/plan.js +7 -7
  161. package/dist/orchestrate/plan.js.map +1 -1
  162. package/dist/orchestrate/spawn-ops.js +2 -2
  163. package/dist/orchestrate/spawn-ops.js.map +1 -1
  164. package/dist/orchestration/classify.d.ts +2 -2
  165. package/dist/orchestration/classify.js +3 -3
  166. package/dist/orchestration/classify.js.map +1 -1
  167. package/dist/orchestration/validate-spawn.d.ts.map +1 -1
  168. package/dist/orchestration/validate-spawn.js +5 -5
  169. package/dist/orchestration/validate-spawn.js.map +1 -1
  170. package/dist/paths-export.d.ts +18 -0
  171. package/dist/paths-export.d.ts.map +1 -0
  172. package/dist/paths-export.js +18 -0
  173. package/dist/paths-export.js.map +1 -0
  174. package/dist/paths.d.ts.map +1 -1
  175. package/dist/paths.js +24 -11
  176. package/dist/paths.js.map +1 -1
  177. package/dist/playbooks/index.d.ts +1 -0
  178. package/dist/playbooks/index.d.ts.map +1 -1
  179. package/dist/playbooks/index.js +4 -0
  180. package/dist/playbooks/index.js.map +1 -1
  181. package/dist/playbooks/skill-node-executor.d.ts +155 -0
  182. package/dist/playbooks/skill-node-executor.d.ts.map +1 -0
  183. package/dist/playbooks/skill-node-executor.js +156 -0
  184. package/dist/playbooks/skill-node-executor.js.map +1 -0
  185. package/dist/repair.d.ts +3 -7
  186. package/dist/repair.d.ts.map +1 -1
  187. package/dist/repair.js +5 -43
  188. package/dist/repair.js.map +1 -1
  189. package/dist/sagas/migrate-containment.js +7 -7
  190. package/dist/sagas/migrate-containment.js.map +1 -1
  191. package/dist/scaffold/ensure-dirs.d.ts +8 -2
  192. package/dist/scaffold/ensure-dirs.d.ts.map +1 -1
  193. package/dist/scaffold/ensure-dirs.js +24 -11
  194. package/dist/scaffold/ensure-dirs.js.map +1 -1
  195. package/dist/scaffold/project-detection.d.ts +5 -1
  196. package/dist/scaffold/project-detection.d.ts.map +1 -1
  197. package/dist/scaffold/project-detection.js +9 -5
  198. package/dist/scaffold/project-detection.js.map +1 -1
  199. package/dist/sentient/hygiene-scan.js +6 -6
  200. package/dist/sentient/hygiene-scan.js.map +1 -1
  201. package/dist/sentient/proposal-dedup.js +2 -2
  202. package/dist/sentient/proposal-rate-limiter.js +1 -1
  203. package/dist/sentient/propose-tick.js +5 -5
  204. package/dist/sentient/propose-tick.js.map +1 -1
  205. package/dist/sentient/stage-drift-tick.js +3 -3
  206. package/dist/sentient/stage-drift-tick.js.map +1 -1
  207. package/dist/sequence/index.d.ts.map +1 -1
  208. package/dist/sequence/index.js +6 -2
  209. package/dist/sequence/index.js.map +1 -1
  210. package/dist/sessions/briefing.d.ts.map +1 -1
  211. package/dist/sessions/briefing.js +18 -4
  212. package/dist/sessions/briefing.js.map +1 -1
  213. package/dist/setup/sections/verification.js +2 -2
  214. package/dist/setup/sections/verification.js.map +1 -1
  215. package/dist/shutdown.d.ts +91 -0
  216. package/dist/shutdown.d.ts.map +1 -0
  217. package/dist/shutdown.js +120 -0
  218. package/dist/shutdown.js.map +1 -0
  219. package/dist/skills/index.d.ts +2 -0
  220. package/dist/skills/index.d.ts.map +1 -1
  221. package/dist/skills/index.js +1 -0
  222. package/dist/skills/index.js.map +1 -1
  223. package/dist/skills/skill-executor-adapter.d.ts +136 -0
  224. package/dist/skills/skill-executor-adapter.d.ts.map +1 -0
  225. package/dist/skills/skill-executor-adapter.js +137 -0
  226. package/dist/skills/skill-executor-adapter.js.map +1 -0
  227. package/dist/skills/usage-recorder.d.ts.map +1 -1
  228. package/dist/skills/usage-recorder.js +30 -0
  229. package/dist/skills/usage-recorder.js.map +1 -1
  230. package/dist/skills-export.d.ts +23 -0
  231. package/dist/skills-export.d.ts.map +1 -0
  232. package/dist/skills-export.js +23 -0
  233. package/dist/skills-export.js.map +1 -0
  234. package/dist/stats/index.d.ts.map +1 -1
  235. package/dist/stats/index.js +8 -3
  236. package/dist/stats/index.js.map +1 -1
  237. package/dist/store/agent-doctor.d.ts +3 -3
  238. package/dist/store/agent-doctor.d.ts.map +1 -1
  239. package/dist/store/agent-doctor.js +18 -13
  240. package/dist/store/agent-doctor.js.map +1 -1
  241. package/dist/store/agent-install.d.ts +6 -5
  242. package/dist/store/agent-install.d.ts.map +1 -1
  243. package/dist/store/agent-install.js +20 -16
  244. package/dist/store/agent-install.js.map +1 -1
  245. package/dist/store/agent-registry-accessor.d.ts +66 -28
  246. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  247. package/dist/store/agent-registry-accessor.js +248 -167
  248. package/dist/store/agent-registry-accessor.js.map +1 -1
  249. package/dist/store/agent-registry-store.d.ts +242 -0
  250. package/dist/store/agent-registry-store.d.ts.map +1 -0
  251. package/dist/store/agent-registry-store.js +501 -0
  252. package/dist/store/agent-registry-store.js.map +1 -0
  253. package/dist/store/agent-resolver.d.ts +8 -8
  254. package/dist/store/agent-resolver.d.ts.map +1 -1
  255. package/dist/store/agent-resolver.js +19 -17
  256. package/dist/store/agent-resolver.js.map +1 -1
  257. package/dist/store/backup-pack.d.ts.map +1 -1
  258. package/dist/store/backup-pack.js +24 -8
  259. package/dist/store/backup-pack.js.map +1 -1
  260. package/dist/store/conduit-sqlite.d.ts +181 -74
  261. package/dist/store/conduit-sqlite.d.ts.map +1 -1
  262. package/dist/store/conduit-sqlite.js +307 -528
  263. package/dist/store/conduit-sqlite.js.map +1 -1
  264. package/dist/store/cross-db-cleanup.d.ts +5 -5
  265. package/dist/store/cross-db-cleanup.d.ts.map +1 -1
  266. package/dist/store/cross-db-cleanup.js +12 -10
  267. package/dist/store/cross-db-cleanup.js.map +1 -1
  268. package/dist/store/data-accessor.d.ts +4 -4
  269. package/dist/store/data-accessor.js +5 -5
  270. package/dist/store/data-accessor.js.map +1 -1
  271. package/dist/store/data-safety-central.d.ts +83 -1
  272. package/dist/store/data-safety-central.d.ts.map +1 -1
  273. package/dist/store/data-safety-central.js +257 -0
  274. package/dist/store/data-safety-central.js.map +1 -1
  275. package/dist/store/db-helpers.d.ts +8 -2
  276. package/dist/store/db-helpers.d.ts.map +1 -1
  277. package/dist/store/db-helpers.js +6 -2
  278. package/dist/store/db-helpers.js.map +1 -1
  279. package/dist/store/dual-scope-db.d.ts +46 -4
  280. package/dist/store/dual-scope-db.d.ts.map +1 -1
  281. package/dist/store/dual-scope-db.js +103 -9
  282. package/dist/store/dual-scope-db.js.map +1 -1
  283. package/dist/store/exodus/__fixtures__/representative-fixture.d.ts +116 -0
  284. package/dist/store/exodus/__fixtures__/representative-fixture.d.ts.map +1 -0
  285. package/dist/store/exodus/__fixtures__/representative-fixture.js +274 -0
  286. package/dist/store/exodus/__fixtures__/representative-fixture.js.map +1 -0
  287. package/dist/store/exodus/index.d.ts +3 -1
  288. package/dist/store/exodus/index.d.ts.map +1 -1
  289. package/dist/store/exodus/index.js +3 -1
  290. package/dist/store/exodus/index.js.map +1 -1
  291. package/dist/store/exodus/migrate.d.ts +120 -1
  292. package/dist/store/exodus/migrate.d.ts.map +1 -1
  293. package/dist/store/exodus/migrate.js +923 -119
  294. package/dist/store/exodus/migrate.js.map +1 -1
  295. package/dist/store/exodus/on-open.d.ts +189 -0
  296. package/dist/store/exodus/on-open.d.ts.map +1 -0
  297. package/dist/store/exodus/on-open.js +464 -0
  298. package/dist/store/exodus/on-open.js.map +1 -0
  299. package/dist/store/exodus/table-name-map.d.ts +173 -0
  300. package/dist/store/exodus/table-name-map.d.ts.map +1 -0
  301. package/dist/store/exodus/table-name-map.js +660 -0
  302. package/dist/store/exodus/table-name-map.js.map +1 -0
  303. package/dist/store/exodus/verify-migration.d.ts +72 -0
  304. package/dist/store/exodus/verify-migration.d.ts.map +1 -0
  305. package/dist/store/exodus/verify-migration.js +678 -0
  306. package/dist/store/exodus/verify-migration.js.map +1 -0
  307. package/dist/store/exodus/verify.d.ts +32 -8
  308. package/dist/store/exodus/verify.d.ts.map +1 -1
  309. package/dist/store/exodus/verify.js +48 -142
  310. package/dist/store/exodus/verify.js.map +1 -1
  311. package/dist/store/index.d.ts +2 -3
  312. package/dist/store/index.d.ts.map +1 -1
  313. package/dist/store/index.js +2 -3
  314. package/dist/store/index.js.map +1 -1
  315. package/dist/store/memory-accessor.d.ts +31 -0
  316. package/dist/store/memory-accessor.d.ts.map +1 -1
  317. package/dist/store/memory-accessor.js +38 -0
  318. package/dist/store/memory-accessor.js.map +1 -1
  319. package/dist/store/memory-sqlite.d.ts +86 -13
  320. package/dist/store/memory-sqlite.d.ts.map +1 -1
  321. package/dist/store/memory-sqlite.js +326 -528
  322. package/dist/store/memory-sqlite.js.map +1 -1
  323. package/dist/store/migrate-signaldock-to-conduit.d.ts +1 -1
  324. package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -1
  325. package/dist/store/migrate-signaldock-to-conduit.js +126 -35
  326. package/dist/store/migrate-signaldock-to-conduit.js.map +1 -1
  327. package/dist/store/migration-manager.d.ts +49 -0
  328. package/dist/store/migration-manager.d.ts.map +1 -1
  329. package/dist/store/migration-manager.js +167 -67
  330. package/dist/store/migration-manager.js.map +1 -1
  331. package/dist/store/migration-sqlite.d.ts +1 -1
  332. package/dist/store/migration-sqlite.d.ts.map +1 -1
  333. package/dist/store/migration-sqlite.js +32 -3
  334. package/dist/store/migration-sqlite.js.map +1 -1
  335. package/dist/store/nexus-sqlite.d.ts +152 -29
  336. package/dist/store/nexus-sqlite.d.ts.map +1 -1
  337. package/dist/store/nexus-sqlite.js +496 -177
  338. package/dist/store/nexus-sqlite.js.map +1 -1
  339. package/dist/store/nexus-validation-schemas.d.ts +32 -32
  340. package/dist/store/open-cleo-db.d.ts +37 -40
  341. package/dist/store/open-cleo-db.d.ts.map +1 -1
  342. package/dist/store/open-cleo-db.js +76 -153
  343. package/dist/store/open-cleo-db.js.map +1 -1
  344. package/dist/store/role-accessors-impl.d.ts +4 -4
  345. package/dist/store/role-accessors-impl.d.ts.map +1 -1
  346. package/dist/store/role-accessors-impl.js +18 -15
  347. package/dist/store/role-accessors-impl.js.map +1 -1
  348. package/dist/store/schema/{signaldock-schema.d.ts → agent-registry-schema.d.ts} +15 -5
  349. package/dist/store/schema/agent-registry-schema.d.ts.map +1 -0
  350. package/dist/store/schema/{signaldock-schema.js → agent-registry-schema.js} +15 -5
  351. package/dist/store/schema/agent-registry-schema.js.map +1 -0
  352. package/dist/store/schema/agent-schema.d.ts +1 -1
  353. package/dist/store/schema/agent-schema.js +4 -4
  354. package/dist/store/schema/agent-schema.js.map +1 -1
  355. package/dist/store/schema/attachments.d.ts +1 -1
  356. package/dist/store/schema/audit.d.ts +15 -5
  357. package/dist/store/schema/audit.d.ts.map +1 -1
  358. package/dist/store/schema/audit.js +12 -2
  359. package/dist/store/schema/audit.js.map +1 -1
  360. package/dist/store/schema/background-jobs.d.ts +1 -1
  361. package/dist/store/schema/cleo-global/{signaldock.d.ts → agent-registry.d.ts} +277 -271
  362. package/dist/store/schema/cleo-global/agent-registry.d.ts.map +1 -0
  363. package/dist/store/schema/cleo-global/{signaldock.js → agent-registry.js} +136 -125
  364. package/dist/store/schema/cleo-global/agent-registry.js.map +1 -0
  365. package/dist/store/schema/cleo-global/index.d.ts +29 -22
  366. package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
  367. package/dist/store/schema/cleo-global/index.js +29 -22
  368. package/dist/store/schema/cleo-global/index.js.map +1 -1
  369. package/dist/store/schema/cleo-global/nexus.d.ts +36 -1034
  370. package/dist/store/schema/cleo-global/nexus.d.ts.map +1 -1
  371. package/dist/store/schema/cleo-global/nexus.js +32 -337
  372. package/dist/store/schema/cleo-global/nexus.js.map +1 -1
  373. package/dist/store/schema/cleo-global/skills.d.ts +16 -0
  374. package/dist/store/schema/cleo-global/skills.d.ts.map +1 -1
  375. package/dist/store/schema/cleo-global/skills.js +11 -0
  376. package/dist/store/schema/cleo-global/skills.js.map +1 -1
  377. package/dist/store/schema/{cleo-project → cleo-global}/telemetry.d.ts +33 -17
  378. package/dist/store/schema/cleo-global/telemetry.d.ts.map +1 -0
  379. package/dist/store/schema/{cleo-project → cleo-global}/telemetry.js +30 -18
  380. package/dist/store/schema/cleo-global/telemetry.js.map +1 -0
  381. package/dist/store/schema/cleo-project/audit.d.ts +8 -8
  382. package/dist/store/schema/cleo-project/audit.d.ts.map +1 -1
  383. package/dist/store/schema/cleo-project/audit.js +2 -6
  384. package/dist/store/schema/cleo-project/audit.js.map +1 -1
  385. package/dist/store/schema/cleo-project/docs.d.ts +1 -1
  386. package/dist/store/schema/cleo-project/index.d.ts +29 -12
  387. package/dist/store/schema/cleo-project/index.d.ts.map +1 -1
  388. package/dist/store/schema/cleo-project/index.js +29 -12
  389. package/dist/store/schema/cleo-project/index.js.map +1 -1
  390. package/dist/store/schema/cleo-project/lifecycle.d.ts +2 -2
  391. package/dist/store/schema/cleo-project/nexus-graph.d.ts +1067 -0
  392. package/dist/store/schema/cleo-project/nexus-graph.d.ts.map +1 -0
  393. package/dist/store/schema/cleo-project/nexus-graph.js +407 -0
  394. package/dist/store/schema/cleo-project/nexus-graph.js.map +1 -0
  395. package/dist/store/schema/cleo-project/provenance-orphans.d.ts +385 -0
  396. package/dist/store/schema/cleo-project/provenance-orphans.d.ts.map +1 -0
  397. package/dist/store/schema/cleo-project/provenance-orphans.js +142 -0
  398. package/dist/store/schema/cleo-project/provenance-orphans.js.map +1 -0
  399. package/dist/store/schema/cleo-project/provenance-rest.d.ts +1 -1
  400. package/dist/store/schema/cleo-project/runtime.d.ts +1 -1
  401. package/dist/store/schema/cleo-project/tasks-core-batch2.d.ts +1 -1
  402. package/dist/store/schema/cleo-project/tasks-core.d.ts +3 -3
  403. package/dist/store/schema/cleo-shared/brain.d.ts +711 -494
  404. package/dist/store/schema/cleo-shared/brain.d.ts.map +1 -1
  405. package/dist/store/schema/cleo-shared/brain.js +215 -134
  406. package/dist/store/schema/cleo-shared/brain.js.map +1 -1
  407. package/dist/store/schema/conduit-schema.d.ts +63 -51
  408. package/dist/store/schema/conduit-schema.d.ts.map +1 -1
  409. package/dist/store/schema/conduit-schema.js +23 -11
  410. package/dist/store/schema/conduit-schema.js.map +1 -1
  411. package/dist/store/schema/goal.d.ts +3 -2
  412. package/dist/store/schema/goal.d.ts.map +1 -1
  413. package/dist/store/schema/goal.js +3 -2
  414. package/dist/store/schema/goal.js.map +1 -1
  415. package/dist/store/schema/index.d.ts +1 -0
  416. package/dist/store/schema/index.d.ts.map +1 -1
  417. package/dist/store/schema/index.js +1 -0
  418. package/dist/store/schema/index.js.map +1 -1
  419. package/dist/store/schema/lifecycle.d.ts +2 -2
  420. package/dist/store/schema/memory-schema.d.ts +2 -2
  421. package/dist/store/schema/nexus-schema.d.ts +174 -115
  422. package/dist/store/schema/nexus-schema.d.ts.map +1 -1
  423. package/dist/store/schema/nexus-schema.js +175 -55
  424. package/dist/store/schema/nexus-schema.js.map +1 -1
  425. package/dist/store/schema/provenance/releases.d.ts +1 -1
  426. package/dist/store/schema/schema-utils.d.ts +78 -0
  427. package/dist/store/schema/schema-utils.d.ts.map +1 -0
  428. package/dist/store/schema/schema-utils.js +49 -0
  429. package/dist/store/schema/schema-utils.js.map +1 -0
  430. package/dist/store/schema/skills-schema.d.ts +81 -44
  431. package/dist/store/schema/skills-schema.d.ts.map +1 -1
  432. package/dist/store/schema/skills-schema.js +49 -16
  433. package/dist/store/schema/skills-schema.js.map +1 -1
  434. package/dist/store/schema/tasks.d.ts +3 -3
  435. package/dist/store/skills-db.d.ts +90 -50
  436. package/dist/store/skills-db.d.ts.map +1 -1
  437. package/dist/store/skills-db.js +132 -146
  438. package/dist/store/skills-db.js.map +1 -1
  439. package/dist/store/sqlite-backup.d.ts +2 -2
  440. package/dist/store/sqlite-backup.d.ts.map +1 -1
  441. package/dist/store/sqlite-backup.js +11 -10
  442. package/dist/store/sqlite-backup.js.map +1 -1
  443. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  444. package/dist/store/sqlite-data-accessor.js +25 -18
  445. package/dist/store/sqlite-data-accessor.js.map +1 -1
  446. package/dist/store/sqlite.d.ts +72 -12
  447. package/dist/store/sqlite.d.ts.map +1 -1
  448. package/dist/store/sqlite.js +153 -89
  449. package/dist/store/sqlite.js.map +1 -1
  450. package/dist/store/tasks-schema.d.ts +4 -0
  451. package/dist/store/tasks-schema.d.ts.map +1 -1
  452. package/dist/store/tasks-schema.js +60 -0
  453. package/dist/store/tasks-schema.js.map +1 -1
  454. package/dist/store/tasks-sqlite.d.ts +2 -2
  455. package/dist/store/tasks-sqlite.d.ts.map +1 -1
  456. package/dist/store/tasks-sqlite.js +10 -5
  457. package/dist/store/tasks-sqlite.js.map +1 -1
  458. package/dist/store/umbrella-data-accessor.d.ts +17 -6
  459. package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
  460. package/dist/store/umbrella-data-accessor.js +8 -8
  461. package/dist/store/umbrella-data-accessor.js.map +1 -1
  462. package/dist/store/validation-schemas.d.ts +241 -208
  463. package/dist/store/validation-schemas.d.ts.map +1 -1
  464. package/dist/system/health.d.ts.map +1 -1
  465. package/dist/system/health.js +11 -6
  466. package/dist/system/health.js.map +1 -1
  467. package/dist/system/project-health.d.ts.map +1 -1
  468. package/dist/system/project-health.js +58 -12
  469. package/dist/system/project-health.js.map +1 -1
  470. package/dist/tasks/add.d.ts +8 -0
  471. package/dist/tasks/add.d.ts.map +1 -1
  472. package/dist/tasks/add.js +101 -0
  473. package/dist/tasks/add.js.map +1 -1
  474. package/dist/tasks/cancelled-child-waiver-audit.d.ts +47 -0
  475. package/dist/tasks/cancelled-child-waiver-audit.d.ts.map +1 -0
  476. package/dist/tasks/cancelled-child-waiver-audit.js +34 -0
  477. package/dist/tasks/cancelled-child-waiver-audit.js.map +1 -0
  478. package/dist/tasks/complete.d.ts +22 -2
  479. package/dist/tasks/complete.d.ts.map +1 -1
  480. package/dist/tasks/complete.js +71 -6
  481. package/dist/tasks/complete.js.map +1 -1
  482. package/dist/tasks/compute-task-view.js +1 -1
  483. package/dist/tasks/session-scope.d.ts +5 -0
  484. package/dist/tasks/session-scope.d.ts.map +1 -1
  485. package/dist/tasks/session-scope.js +4 -0
  486. package/dist/tasks/session-scope.js.map +1 -1
  487. package/dist/tools/guard.d.ts +71 -1
  488. package/dist/tools/guard.d.ts.map +1 -1
  489. package/dist/tools/guard.js +73 -1
  490. package/dist/tools/guard.js.map +1 -1
  491. package/dist/tools/index.d.ts +21 -0
  492. package/dist/tools/index.d.ts.map +1 -1
  493. package/dist/tools/index.js +25 -0
  494. package/dist/tools/index.js.map +1 -1
  495. package/dist/upgrade.d.ts.map +1 -1
  496. package/dist/upgrade.js +22 -13
  497. package/dist/upgrade.js.map +1 -1
  498. package/dist/workgraph/containment.js +18 -18
  499. package/dist/workgraph/relations.js +2 -2
  500. package/dist/worktree/list.d.ts +1 -1
  501. package/dist/worktree/list.d.ts.map +1 -1
  502. package/dist/worktree/list.js +19 -21
  503. package/dist/worktree/list.js.map +1 -1
  504. package/dist/worktree-export.d.ts +18 -0
  505. package/dist/worktree-export.d.ts.map +1 -0
  506. package/dist/worktree-export.js +18 -0
  507. package/dist/worktree-export.js.map +1 -0
  508. package/migrations/drizzle-agent-registry/20260412000000_initial-global-agent-registry/migration.sql +29 -0
  509. package/migrations/drizzle-brain/20260601000001_t11522-brain-task-observations/migration.sql +28 -0
  510. package/migrations/drizzle-brain/20260601000002_t11522-inline-only-brain-tables/migration.sql +75 -0
  511. package/migrations/drizzle-cleo-global/20260531000001_t11363-consolidation-cleo-global/migration.sql +49 -144
  512. package/migrations/drizzle-cleo-global/20260531000001_t11363-consolidation-cleo-global/snapshot.json +8 -8
  513. package/migrations/drizzle-cleo-global/20260531000002_t11546-brain-usage-log/migration.sql +16 -0
  514. package/migrations/drizzle-cleo-global/20260601000001_t11544-skills-usage-project-id/migration.sql +12 -0
  515. package/migrations/drizzle-cleo-global/20260602000001_t11622-agent-registry-rename/migration.sql +80 -0
  516. package/migrations/drizzle-cleo-project/20260531000001_t11363-consolidation-cleo-project/migration.sql +26 -167
  517. package/migrations/drizzle-cleo-project/20260531000001_t11363-consolidation-cleo-project/snapshot.json +8 -8
  518. package/migrations/drizzle-cleo-project/20260531000002_t11546-brain-usage-log/migration.sql +21 -0
  519. package/migrations/drizzle-cleo-project/20260601000001_t11549-agent-credentials-brain-release-links/migration.sql +49 -0
  520. package/migrations/drizzle-cleo-project/20260601000002_t11538-project-nexus-graph/migration.sql +140 -0
  521. package/migrations/drizzle-cleo-project/20260602000002_t11649-token-usage-transport-mcp/migration.sql +146 -0
  522. package/migrations/drizzle-conduit/20260601000003_t11523-conduit-inline-schema/migration.sql +82 -0
  523. package/migrations/drizzle-nexus/20260421200001_t1165-baseline-reset/migration.sql +26 -8
  524. package/migrations/drizzle-nexus/20260601000001_t11545-nexus-relation-weights-partition/migration.sql +97 -0
  525. package/package.json +45 -13
  526. package/scripts/install-supervisor-binary.mjs +50 -201
  527. package/scripts/napi-binary-picker.mjs +267 -0
  528. package/dist/agents/agent-registry.d.ts.map +0 -1
  529. package/dist/agents/agent-registry.js.map +0 -1
  530. package/dist/store/data-safety.d.ts +0 -92
  531. package/dist/store/data-safety.d.ts.map +0 -1
  532. package/dist/store/data-safety.js +0 -274
  533. package/dist/store/data-safety.js.map +0 -1
  534. package/dist/store/schema/cleo-global/signaldock.d.ts.map +0 -1
  535. package/dist/store/schema/cleo-global/signaldock.js.map +0 -1
  536. package/dist/store/schema/cleo-project/telemetry.d.ts.map +0 -1
  537. package/dist/store/schema/cleo-project/telemetry.js.map +0 -1
  538. package/dist/store/schema/signaldock-schema.d.ts.map +0 -1
  539. package/dist/store/schema/signaldock-schema.js.map +0 -1
  540. package/dist/store/signaldock-sqlite.d.ts +0 -173
  541. package/dist/store/signaldock-sqlite.d.ts.map +0 -1
  542. package/dist/store/signaldock-sqlite.js +0 -445
  543. package/dist/store/signaldock-sqlite.js.map +0 -1
  544. package/migrations/drizzle-nexus/20260318205558_initial/migration.sql +0 -46
  545. package/migrations/drizzle-nexus/20260412000001_t529-nexus-graph-tables/migration.sql +0 -49
  546. package/migrations/drizzle-nexus/20260415000001_t622-project-registry-paths/migration.sql +0 -12
  547. package/migrations/drizzle-nexus/20260419000001_t998-nexus-plasticity/migration.sql +0 -13
  548. package/migrations/drizzle-nexus/20260423052640_t1077-add-user-profile-table/migration.sql +0 -16
  549. package/migrations/drizzle-nexus/20260423052640_t1077-add-user-profile-table/snapshot.json +0 -1531
  550. package/migrations/drizzle-nexus/20260424140538_t1148-add-sigils-table/migration.sql +0 -13
  551. package/migrations/drizzle-nexus/20260424140538_t1148-add-sigils-table/snapshot.json +0 -1652
  552. package/migrations/drizzle-nexus/20260504000001_t1839-fts5-nexus-symbols/migration.sql +0 -68
  553. package/migrations/drizzle-nexus/20260507135519_t9163-nexus-is-external/migration.sql +0 -20
  554. package/migrations/drizzle-nexus/20260507135519_t9163-nexus-is-external/snapshot.json +0 -1652
  555. package/migrations/drizzle-nexus/20260526222449_t11025-project-id-aliases/migration.sql +0 -16
  556. package/migrations/drizzle-signaldock/20260412000000_initial-global-signaldock/migration.sql +0 -209
  557. package/migrations/drizzle-signaldock/20260412000000_initial-global-signaldock/snapshot.json +0 -2060
@@ -1,50 +1,125 @@
1
1
  /**
2
- * SQLite store for conduit.db project-tier messaging and agent-ref database.
3
- *
4
- * Creates and manages .cleo/conduit.db using node:sqlite directly.
5
- *
6
- * Schema definitions live in `conduit-schema.ts` (Drizzle ORM table objects).
7
- * On open, the legacy DDL bootstrap (`applyConduitSchema`, retained as a
8
- * `CREATE TABLE IF NOT EXISTS` fallback that also handles the FTS5 virtual
9
- * table + triggers which Drizzle cannot model) creates any missing tables,
10
- * then the canonical `migration-manager.ts` runner reconciles the Drizzle
11
- * journal and applies any pending migrations from
12
- * `packages/core/migrations/drizzle-conduit/`. This brings conduit.db into
13
- * the same SSoT pattern as tasks/brain/nexus/signaldock/telemetry.
2
+ * SQLite store for the project-scope CONDUIT domain agent-to-agent messaging,
3
+ * delivery queue, attachments, A2A topics, and per-project agent refs.
4
+ *
5
+ * ## E6-L3 — thin-facade migration (T11523)
6
+ *
7
+ * `ensureConduitDb()` is now a thin facade that delegates the database open to
8
+ * {@link openDualScopeDb}('project', cwd) the canonical dual-scope chokepoint
9
+ * introduced by E3/E4 (T11512/T11517) and already adopted by the tasks domain
10
+ * (E6-L1, T11521) and brain domain (E6-L2, T11522). This ensures:
11
+ *
12
+ * - Every conduit-domain open flows through the single pragma SSoT (ADR-068/069).
13
+ * - The conduit tables now live inside the consolidated project `cleo.db` NOT a
14
+ * separate `conduit.db` file — co-existing with `tasks_*` / `brain_*` / etc.
15
+ * - DB Open Guard Gate 3 (`scripts/lint-no-direct-db-open.mjs`) stays green: the
16
+ * only native open is inside `dual-scope-db.ts`.
17
+ *
18
+ * ## COMPLETE-CUTOVER to prefixed `conduit_*` tables (T11578 · AC4)
19
+ *
20
+ * The conduit runtime READ + WRITE path now targets the PREFIXED consolidated
21
+ * tables (`conduit_conversations`, `conduit_messages`, `conduit_topics`, …) that
22
+ * the consolidated cleo-project migration creates — NOT the legacy BARE tables
23
+ * (`conversations`, `messages`, …). The schema barrel imported below is therefore
24
+ * `schema/cleo-project/conduit.ts` (the prefixed target shape, TEXT ISO-8601
25
+ * timestamps + CHECK constraints), replacing the legacy `schema/conduit-schema.ts`
26
+ * bare shape. The drizzle journal `runConduitMigrations` reconciles now only needs
27
+ * the FTS5 quartet that the consolidated migration omits (drizzle-orm sqlite-core
28
+ * does not model FTS5 virtual tables).
29
+ *
30
+ * ## Inline DDL → forward migration (T11523 → T11578)
31
+ *
32
+ * The legacy 16-table inline `CONDUIT_SCHEMA_SQL` blob was first converted to a
33
+ * forward Drizzle migration under
34
+ * `migrations/drizzle-conduit/20260601000003_t11523-conduit-inline-schema`
35
+ * (T11523, bare runtime shape). The AC4 cutover (T11578) rewrote that migration to
36
+ * carry ONLY the `conduit_messages_fts` FTS5 virtual table + its 3 sync triggers
37
+ * (`conduit_messages_ai/ad/au`) + the two legacy `_conduit_meta` /
38
+ * `_conduit_migrations` health-probe tables. The 14 prefixed `conduit_*` tables
39
+ * are owned by the consolidated cleo-project migration (single SSoT) — this
40
+ * migration no longer creates them.
41
+ *
42
+ * ## Single physical shape (consolidated owns the tables)
43
+ *
44
+ * After AC4 the runtime writes the SAME prefixed `conduit_*` tables the
45
+ * consolidated schema (`cleo-project/conduit.ts`) declares — there is no longer a
46
+ * disjoint bare runtime shape. The exodus migration (T11248 / T11553) still
47
+ * renames any LEGACY bare data (`messages` → `conduit_messages`) from a
48
+ * pre-cutover DB into those same prefixed tables; the FTS index is rebuilt
49
+ * post-migration from `conduit_messages` (exodus skips `*_fts` tables).
14
50
  *
15
51
  * Architecture (ADR-037):
16
- * conduit.db — project-scoped (this module) — messaging, delivery, attachments,
52
+ * conduit (this module) — project-scoped — messaging, delivery, attachments,
17
53
  * project_agent_refs
18
54
  * signaldock.db — global-scoped (T346) — agents, capabilities, cloud-sync tables
19
55
  *
20
56
  * @task T344
21
57
  * @task T1407
58
+ * @task T11523 - E6-L3: route ensureConduitDb through openDualScopeDb (SG-DB-SUBSTRATE-V2)
22
59
  * @epic T310
23
- * @why ADR-037 splits single signaldock.db into project-tier conduit.db
60
+ * @epic T11249
61
+ * @why ADR-037 splits single signaldock.db into project-tier conduit
24
62
  * (this module) and global-tier signaldock.db (T346). T1407 unifies
25
- * conduit.db under the canonical Drizzle migration runner.
26
- * @what Path helper, database initializer, Drizzle migration runner wiring,
27
- * legacy schema applier (bootstrap + FTS5 fallback), health check,
28
- * and native DB accessor.
63
+ * conduit under the canonical Drizzle migration runner; T11523 routes it
64
+ * through the consolidated `cleo.db` dual-scope chokepoint.
65
+ * @what Path helper, database initializer (dual-scope facade), Drizzle migration
66
+ * runner wiring, health check, native DB accessor, and project_agent_refs
67
+ * CRUD accessors.
29
68
  */
30
- import { existsSync, mkdirSync } from 'node:fs';
69
+ import { existsSync } from 'node:fs';
31
70
  import { createRequire } from 'node:module';
32
- import { dirname, join } from 'node:path';
33
- import { drizzle } from 'drizzle-orm/node-sqlite';
71
+ // E6-L3 (T11523): dual-scope chokepoint the conduit domain now opens the
72
+ // consolidated project `cleo.db` through here. openDualScopeDb manages the
73
+ // DatabaseSync lifecycle, pragmas, and consolidated migrations. We extract the
74
+ // native handle and re-wrap it with the legacy conduit-schema drizzle instance so
75
+ // existing callers compile and run without change.
76
+ import { openDualScopeDb, resolveDualScopeDbPath } from './dual-scope-db.js';
34
77
  import { migrateSanitized, reconcileJournal } from './migration-manager.js';
35
78
  import { resolveCorePackageMigrationsFolder } from './resolve-migrations-folder.js';
36
- import * as conduitSchema from './schema/conduit-schema.js';
37
- import { applyPerfPragmas, optimizeBeforeClose } from './sqlite-pragmas.js';
79
+ import * as conduitSchema from './schema/cleo-project/conduit.js';
80
+ import { applyPerfPragmas } from './sqlite-pragmas.js';
38
81
  const _require = createRequire(import.meta.url);
39
82
  const { DatabaseSync } = _require('node:sqlite');
40
- /** Database file name within .cleo/ directory. */
83
+ /**
84
+ * Cached `drizzle` factory from `drizzle-orm/node-sqlite`, loaded on first use.
85
+ *
86
+ * Loaded via `createRequire` rather than a top-level import so that importing
87
+ * `conduit-sqlite.ts` does not eagerly pull in `node:sqlite` (which the drizzle
88
+ * driver statically imports). Memoized after the first call. Mirrors the
89
+ * `_getDrizzle` lazy pattern in sqlite.ts / memory-sqlite.ts (T11280/T11521/T11522).
90
+ *
91
+ * @internal
92
+ * @task T11523
93
+ */
94
+ let _drizzle = null;
95
+ /**
96
+ * Returns the `drizzle` factory, loading `drizzle-orm/node-sqlite` on first call.
97
+ *
98
+ * @internal
99
+ * @task T11523
100
+ */
101
+ function _getDrizzle() {
102
+ if (_drizzle === null) {
103
+ const mod = _require('drizzle-orm/node-sqlite');
104
+ _drizzle = mod.drizzle;
105
+ }
106
+ return _drizzle;
107
+ }
108
+ /**
109
+ * Legacy database file name. Retained as an export for backwards compatibility
110
+ * with callers that still reference the constant; the conduit domain now lives
111
+ * inside the consolidated project `cleo.db` (E6-L3, T11523).
112
+ *
113
+ * @deprecated The conduit domain no longer has a standalone `conduit.db` file —
114
+ * it is served from the project `cleo.db`. Use {@link getConduitDbPath}.
115
+ */
41
116
  export const CONDUIT_DB_FILENAME = 'conduit.db';
42
117
  /**
43
- * Schema version for conduit.db.
118
+ * Schema version for the conduit domain.
44
119
  *
45
- * Bumped only when the Drizzle schema changes. T1407 refactor preserved the
46
- * 2026.4.23 schema verbatim (DDL representation only no semantic changes),
47
- * so the version remains pinned at the post-T1252 A2A topics value.
120
+ * Bumped only when the conduit Drizzle schema changes. Pinned at the post-T1252
121
+ * A2A topics value; retained for backwards compatibility with pre-T1407 health
122
+ * checks that read `_conduit_meta.schema_version`.
48
123
  */
49
124
  export const CONDUIT_SCHEMA_VERSION = '2026.4.23';
50
125
  // ---------------------------------------------------------------------------
@@ -52,526 +127,200 @@ export const CONDUIT_SCHEMA_VERSION = '2026.4.23';
52
127
  // ---------------------------------------------------------------------------
53
128
  let _conduitNativeDb = null;
54
129
  let _conduitDbPath = null;
55
- // ---------------------------------------------------------------------------
56
- // DDL
57
- // ---------------------------------------------------------------------------
58
- /**
59
- * Full conduit.db schema SQL.
60
- *
61
- * All tables use CREATE TABLE IF NOT EXISTS / CREATE INDEX IF NOT EXISTS /
62
- * CREATE TRIGGER IF NOT EXISTS for idempotency. Carried over verbatim from
63
- * the project-local tables in signaldock-sqlite.ts (migration
64
- * `2026-03-28-000000_initial` + subsequent migrations), minus the global-
65
- * identity tables (agents, capabilities, skills, agent_capabilities,
66
- * agent_skills, agent_connections, users, organization, accounts, sessions,
67
- * verifications, claim_codes, org_agent_keys) which move to global-tier
68
- * signaldock.db (T346).
69
- *
70
- * Additional new table: project_agent_refs (ADR-037 §3, Q6=A).
71
- *
72
- * NOTE: The `connections` table from the original migration is a cross-agent
73
- * social graph that references `agents(id)` — it is a global-identity
74
- * concern and stays with signaldock.db (T346). It is NOT included here.
75
- */
76
- const CONDUIT_SCHEMA_SQL = `
77
- -- -------------------------------------------------------------------------
78
- -- Project-scoped conversations (LocalTransport DM threads).
79
- -- -------------------------------------------------------------------------
80
- CREATE TABLE IF NOT EXISTS conversations (
81
- id TEXT PRIMARY KEY,
82
- participants TEXT NOT NULL,
83
- visibility TEXT NOT NULL DEFAULT 'private',
84
- message_count INTEGER NOT NULL DEFAULT 0,
85
- last_message_at INTEGER,
86
- created_at INTEGER NOT NULL,
87
- updated_at INTEGER NOT NULL
88
- );
89
-
90
- -- -------------------------------------------------------------------------
91
- -- Project-scoped agent-to-agent messages (LocalTransport content).
92
- -- -------------------------------------------------------------------------
93
- CREATE TABLE IF NOT EXISTS messages (
94
- id TEXT PRIMARY KEY,
95
- conversation_id TEXT NOT NULL REFERENCES conversations(id),
96
- from_agent_id TEXT NOT NULL,
97
- to_agent_id TEXT NOT NULL,
98
- content TEXT NOT NULL,
99
- content_type TEXT NOT NULL DEFAULT 'text',
100
- status TEXT NOT NULL DEFAULT 'pending',
101
- attachments TEXT NOT NULL DEFAULT '[]',
102
- group_id TEXT,
103
- metadata TEXT DEFAULT '{}',
104
- reply_to TEXT,
105
- created_at INTEGER NOT NULL,
106
- delivered_at INTEGER,
107
- read_at INTEGER
108
- );
109
- CREATE INDEX IF NOT EXISTS messages_conversation_idx ON messages(conversation_id);
110
- CREATE INDEX IF NOT EXISTS messages_from_agent_idx ON messages(from_agent_id);
111
- CREATE INDEX IF NOT EXISTS messages_to_agent_idx ON messages(to_agent_id);
112
- CREATE INDEX IF NOT EXISTS messages_created_at_idx ON messages(created_at);
113
- CREATE INDEX IF NOT EXISTS idx_messages_group_id ON messages(group_id) WHERE group_id IS NOT NULL;
114
- CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to) WHERE reply_to IS NOT NULL;
115
-
116
- -- -------------------------------------------------------------------------
117
- -- FTS5 virtual table for full-text search on message content.
118
- -- NOTE: Must be migrated using VACUUM INTO, not DDL-only copy, to preserve
119
- -- triggers. The INSERT INTO messages_fts(messages_fts) VALUES('rebuild')
120
- -- is idempotent — safe to run on every open.
121
- -- -------------------------------------------------------------------------
122
- CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts
123
- USING fts5(content, from_agent_id, content='messages', content_rowid='rowid');
124
- INSERT INTO messages_fts(messages_fts) VALUES('rebuild');
125
- CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN
126
- INSERT INTO messages_fts(rowid, content, from_agent_id)
127
- VALUES (new.rowid, new.content, new.from_agent_id);
128
- END;
129
- CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN
130
- INSERT INTO messages_fts(messages_fts, rowid, content, from_agent_id)
131
- VALUES('delete', old.rowid, old.content, old.from_agent_id);
132
- END;
133
- CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN
134
- INSERT INTO messages_fts(messages_fts, rowid, content, from_agent_id)
135
- VALUES('delete', old.rowid, old.content, old.from_agent_id);
136
- INSERT INTO messages_fts(rowid, content, from_agent_id)
137
- VALUES (new.rowid, new.content, new.from_agent_id);
138
- END;
139
-
140
- -- -------------------------------------------------------------------------
141
- -- Async delivery queue for deferred message dispatch.
142
- -- -------------------------------------------------------------------------
143
- CREATE TABLE IF NOT EXISTS delivery_jobs (
144
- id TEXT PRIMARY KEY,
145
- message_id TEXT NOT NULL,
146
- payload TEXT NOT NULL,
147
- status TEXT NOT NULL DEFAULT 'pending',
148
- attempts INTEGER NOT NULL DEFAULT 0,
149
- max_attempts INTEGER NOT NULL DEFAULT 6,
150
- next_attempt_at INTEGER NOT NULL,
151
- last_error TEXT,
152
- created_at INTEGER NOT NULL,
153
- updated_at INTEGER NOT NULL
154
- );
155
- CREATE INDEX IF NOT EXISTS idx_delivery_jobs_status ON delivery_jobs(status, next_attempt_at);
156
-
157
- -- -------------------------------------------------------------------------
158
- -- Dead-letter queue for messages that exceeded max delivery attempts.
159
- -- -------------------------------------------------------------------------
160
- CREATE TABLE IF NOT EXISTS dead_letters (
161
- id TEXT PRIMARY KEY,
162
- message_id TEXT NOT NULL,
163
- job_id TEXT NOT NULL,
164
- reason TEXT NOT NULL,
165
- attempts INTEGER NOT NULL,
166
- created_at INTEGER NOT NULL
167
- );
168
- CREATE INDEX IF NOT EXISTS idx_dead_letters_message ON dead_letters(message_id);
169
-
170
- -- -------------------------------------------------------------------------
171
- -- Pinned messages within a conversation.
172
- -- -------------------------------------------------------------------------
173
- CREATE TABLE IF NOT EXISTS message_pins (
174
- id TEXT PRIMARY KEY,
175
- message_id TEXT NOT NULL,
176
- conversation_id TEXT NOT NULL,
177
- pinned_by TEXT NOT NULL,
178
- note TEXT,
179
- created_at INTEGER NOT NULL,
180
- UNIQUE(message_id, pinned_by)
181
- );
182
- CREATE INDEX IF NOT EXISTS idx_pins_conversation ON message_pins(conversation_id);
183
- CREATE INDEX IF NOT EXISTS idx_pins_agent ON message_pins(pinned_by);
184
-
185
- -- -------------------------------------------------------------------------
186
- -- File/blob attachments associated with messages.
187
- -- -------------------------------------------------------------------------
188
- CREATE TABLE IF NOT EXISTS attachments (
189
- slug TEXT PRIMARY KEY,
190
- conversation_id TEXT NOT NULL,
191
- from_agent_id TEXT NOT NULL,
192
- content BLOB NOT NULL,
193
- original_size INTEGER NOT NULL,
194
- compressed_size INTEGER NOT NULL,
195
- content_hash TEXT NOT NULL,
196
- format TEXT NOT NULL DEFAULT 'text',
197
- title TEXT,
198
- tokens INTEGER NOT NULL DEFAULT 0,
199
- expires_at INTEGER NOT NULL DEFAULT 0,
200
- storage_key TEXT,
201
- mode TEXT NOT NULL DEFAULT 'draft',
202
- version_count INTEGER NOT NULL DEFAULT 1,
203
- current_version INTEGER NOT NULL DEFAULT 1,
204
- created_at INTEGER NOT NULL
205
- );
206
- CREATE INDEX IF NOT EXISTS attachments_conversation_idx ON attachments(conversation_id);
207
- CREATE INDEX IF NOT EXISTS attachments_agent_idx ON attachments(from_agent_id);
208
-
209
- -- -------------------------------------------------------------------------
210
- -- Version history for attachments (collaborative editing).
211
- -- -------------------------------------------------------------------------
212
- CREATE TABLE IF NOT EXISTS attachment_versions (
213
- id TEXT PRIMARY KEY,
214
- slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
215
- version_number INTEGER NOT NULL,
216
- author_agent_id TEXT NOT NULL,
217
- change_type TEXT NOT NULL DEFAULT 'patch',
218
- patch_text TEXT,
219
- storage_key TEXT NOT NULL,
220
- content_hash TEXT NOT NULL,
221
- original_size INTEGER NOT NULL,
222
- compressed_size INTEGER NOT NULL,
223
- tokens INTEGER NOT NULL,
224
- change_summary TEXT,
225
- sections_modified TEXT NOT NULL DEFAULT '[]',
226
- tokens_added INTEGER NOT NULL DEFAULT 0,
227
- tokens_removed INTEGER NOT NULL DEFAULT 0,
228
- created_at INTEGER NOT NULL,
229
- UNIQUE(slug, version_number)
230
- );
231
- CREATE INDEX IF NOT EXISTS idx_attachment_versions_slug ON attachment_versions(slug);
232
- CREATE INDEX IF NOT EXISTS idx_attachment_versions_author ON attachment_versions(author_agent_id);
233
-
234
- -- -------------------------------------------------------------------------
235
- -- Approval records for attachment content review.
236
- -- -------------------------------------------------------------------------
237
- CREATE TABLE IF NOT EXISTS attachment_approvals (
238
- id TEXT PRIMARY KEY,
239
- slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
240
- reviewer_agent_id TEXT NOT NULL,
241
- status TEXT NOT NULL DEFAULT 'pending',
242
- comment TEXT,
243
- version_reviewed INTEGER NOT NULL,
244
- created_at INTEGER NOT NULL,
245
- updated_at INTEGER NOT NULL,
246
- UNIQUE(slug, reviewer_agent_id)
247
- );
248
- CREATE INDEX IF NOT EXISTS idx_attachment_approvals_slug ON attachment_approvals(slug);
249
-
250
- -- -------------------------------------------------------------------------
251
- -- Contributor statistics per attachment (who edited, how much).
252
- -- -------------------------------------------------------------------------
253
- CREATE TABLE IF NOT EXISTS attachment_contributors (
254
- slug TEXT NOT NULL REFERENCES attachments(slug) ON DELETE CASCADE,
255
- agent_id TEXT NOT NULL,
256
- version_count INTEGER NOT NULL DEFAULT 0,
257
- total_tokens_added INTEGER NOT NULL DEFAULT 0,
258
- total_tokens_removed INTEGER NOT NULL DEFAULT 0,
259
- first_contribution_at INTEGER NOT NULL,
260
- last_contribution_at INTEGER NOT NULL,
261
- PRIMARY KEY (slug, agent_id)
262
- );
263
-
264
- -- -------------------------------------------------------------------------
265
- -- NEW: Per-project agent reference overrides (ADR-037 §3, Q6=A).
266
- -- agent_id is a SOFT FK to global signaldock.db:agents.agent_id.
267
- -- Cross-DB FK enforcement is not possible in SQLite; the accessor layer
268
- -- (T355) validates on every cross-DB join.
269
- -- -------------------------------------------------------------------------
270
- CREATE TABLE IF NOT EXISTS project_agent_refs (
271
- agent_id TEXT PRIMARY KEY,
272
- attached_at TEXT NOT NULL,
273
- role TEXT,
274
- capabilities_override TEXT,
275
- last_used_at TEXT,
276
- enabled INTEGER NOT NULL DEFAULT 1
277
- );
278
- -- Partial index: covers the dominant query path (list enabled agents).
279
- CREATE INDEX IF NOT EXISTS idx_project_agent_refs_enabled
280
- ON project_agent_refs(enabled) WHERE enabled = 1;
281
-
282
- -- -------------------------------------------------------------------------
283
- -- A2A Topics (T1252 — Wave 9 Agent-to-Agent coordination pub-sub).
284
- -- Topics are named channels that agents can publish to / subscribe from.
285
- -- Topic names follow "<epicId>.<waveId>" or "<epicId>.coordination".
286
- -- -------------------------------------------------------------------------
287
- CREATE TABLE IF NOT EXISTS topics (
288
- id TEXT PRIMARY KEY,
289
- name TEXT NOT NULL UNIQUE,
290
- epic_id TEXT NOT NULL,
291
- wave_id INTEGER,
292
- created_by TEXT NOT NULL,
293
- created_at INTEGER NOT NULL
294
- );
295
- CREATE INDEX IF NOT EXISTS idx_topics_epic ON topics(epic_id);
296
-
297
- -- -------------------------------------------------------------------------
298
- -- A2A Topic subscriptions — links an agent_id to a topic_id.
299
- -- Created by subscribeTopic(); removed by unsubscribeTopic().
300
- -- -------------------------------------------------------------------------
301
- CREATE TABLE IF NOT EXISTS topic_subscriptions (
302
- topic_id TEXT NOT NULL REFERENCES topics(id) ON DELETE CASCADE,
303
- agent_id TEXT NOT NULL,
304
- subscribed_at INTEGER NOT NULL,
305
- PRIMARY KEY (topic_id, agent_id)
306
- );
307
- CREATE INDEX IF NOT EXISTS idx_topic_subscriptions_agent ON topic_subscriptions(agent_id);
308
-
309
- -- -------------------------------------------------------------------------
310
- -- A2A Topic messages — broadcast messages published to a topic.
311
- -- payload is stored as JSON text.
312
- -- -------------------------------------------------------------------------
313
- CREATE TABLE IF NOT EXISTS topic_messages (
314
- id TEXT PRIMARY KEY,
315
- topic_id TEXT NOT NULL REFERENCES topics(id) ON DELETE CASCADE,
316
- from_agent_id TEXT NOT NULL,
317
- kind TEXT NOT NULL DEFAULT 'message',
318
- content TEXT NOT NULL,
319
- payload TEXT,
320
- created_at INTEGER NOT NULL
321
- );
322
- CREATE INDEX IF NOT EXISTS idx_topic_messages_topic_created ON topic_messages(topic_id, created_at);
323
-
324
- -- -------------------------------------------------------------------------
325
- -- A2A Topic message ACKs — per-subscriber delivery tracking.
326
- -- -------------------------------------------------------------------------
327
- CREATE TABLE IF NOT EXISTS topic_message_acks (
328
- message_id TEXT NOT NULL REFERENCES topic_messages(id) ON DELETE CASCADE,
329
- subscriber_agent_id TEXT NOT NULL,
330
- delivered_at INTEGER,
331
- read_at INTEGER,
332
- PRIMARY KEY (message_id, subscriber_agent_id)
333
- );
334
-
335
- -- -------------------------------------------------------------------------
336
- -- Schema tracking tables (mirrors _signaldock_meta / _signaldock_migrations).
337
- -- -------------------------------------------------------------------------
338
- CREATE TABLE IF NOT EXISTS _conduit_meta (
339
- key TEXT PRIMARY KEY,
340
- value TEXT NOT NULL,
341
- updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
342
- );
343
- CREATE TABLE IF NOT EXISTS _conduit_migrations (
344
- name TEXT PRIMARY KEY,
345
- applied_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
346
- );
347
- `;
130
+ /** Guard against concurrent initialization (async dual-scope open). */
131
+ let _initPromise = null;
348
132
  // ---------------------------------------------------------------------------
349
133
  // Public API
350
134
  // ---------------------------------------------------------------------------
351
135
  /**
352
- * Returns the project-tier conduit.db path.
136
+ * Returns the project-scope conduit database path.
137
+ *
138
+ * ## E6-L3 (T11523)
353
139
  *
354
- * Always resolves to `<projectRoot>/.cleo/conduit.db`. The caller is
355
- * responsible for supplying the absolute project root (e.g. via
356
- * `getProjectRoot()` from `../paths.js`).
140
+ * After the dual-scope migration, `ensureConduitDb()` opens the consolidated
141
+ * project `cleo.db` via {@link openDualScopeDb} not the legacy standalone
142
+ * `conduit.db`. This function therefore returns the dual-scope `cleo.db` path so
143
+ * that callers checking for the file `ensureConduitDb()` created (existence /
144
+ * backup / health probes) point at the correct file.
145
+ *
146
+ * The supplied `projectRoot` is passed through as the `cwd` for the SSoT
147
+ * resolver, which walks up to find the `.cleo/` directory.
357
148
  *
358
149
  * @task T344
150
+ * @task T11523
359
151
  * @epic T310
360
152
  * @param projectRoot - Absolute path to the project root directory.
361
- * @returns Absolute path to `<projectRoot>/.cleo/conduit.db`.
153
+ * @returns Absolute path to the project `cleo.db`.
362
154
  */
363
155
  export function getConduitDbPath(projectRoot) {
364
- return join(projectRoot, '.cleo', CONDUIT_DB_FILENAME);
156
+ return resolveDualScopeDbPath('project', projectRoot);
365
157
  }
366
158
  /**
367
- * Applies the conduit.db schema idempotently using CREATE TABLE IF NOT EXISTS.
368
- *
369
- * Used as a bootstrap path for fresh conduit.db files BEFORE the Drizzle
370
- * migration runner takes over. The DDL is `CREATE TABLE IF NOT EXISTS` /
371
- * `CREATE INDEX IF NOT EXISTS` / `CREATE TRIGGER IF NOT EXISTS` /
372
- * `CREATE VIRTUAL TABLE IF NOT EXISTS` for full idempotency, so calling this
373
- * on an already-populated DB is a no-op.
374
- *
375
- * Two reasons this raw-SQL applier is retained alongside the Drizzle
376
- * runner (T1407):
377
- *
378
- * 1. **FTS5 + triggers** — drizzle-orm sqlite-core does not model FTS5
379
- * virtual tables or AFTER INSERT/DELETE/UPDATE triggers. The
380
- * `messages_fts` virtual table and its 3 triggers can only live in
381
- * raw SQL. They MUST be present after init for full-text message
382
- * search to work.
383
- *
384
- * 2. **Comment-only baseline migration** — the Drizzle baseline marker at
385
- * `packages/core/migrations/drizzle-conduit/20260425000000_initial-conduit/migration.sql`
386
- * is intentionally comment-only (T1165 Hybrid Path A+ pattern) so that
387
- * existing conduit.db files in the wild detect the schema via
388
- * `reconcileJournal()` and mark the baseline applied without re-running
389
- * DDL. Fresh DBs therefore need a separate bootstrap path — that is
390
- * this function.
391
- *
392
- * Exposed for the migration executor (T358) which needs to apply the schema
393
- * to a newly created conduit.db during the signaldock.db → conduit.db
394
- * migration. Also called internally by `ensureConduitDb` on every open.
159
+ * Resolve the absolute path to the drizzle-conduit migrations folder inside
160
+ * `@cleocode/core`, using ESM-native module resolution (T1177 pattern).
395
161
  *
396
- * @task T344
397
162
  * @task T1407
398
163
  * @epic T310
399
- * @param db - An open node:sqlite DatabaseSync instance.
400
164
  */
401
- export function applyConduitSchema(db) {
402
- db.exec(CONDUIT_SCHEMA_SQL);
165
+ export function resolveConduitMigrationsFolder() {
166
+ return resolveCorePackageMigrationsFolder('drizzle-conduit');
403
167
  }
404
168
  /**
405
- * Resolve the absolute path to the drizzle-conduit migrations folder inside
406
- * `@cleocode/core`, using ESM-native module resolution (T1177 pattern).
169
+ * Apply the conduit-domain schema to an arbitrary open `DatabaseSync` handle by
170
+ * running the `drizzle-conduit` migration set against it.
171
+ *
172
+ * ## E6-L3 (T11523)
173
+ *
174
+ * Previously this executed the inline `CONDUIT_SCHEMA_SQL` blob directly. That
175
+ * blob has been moved into the forward migration
176
+ * `20260601000003_t11523-conduit-inline-schema`, so this helper now reconciles
177
+ * the journal and runs the conduit migrations — the same path `ensureConduitDb`
178
+ * uses internally. It remains exported for the signaldock→conduit migration
179
+ * executor (T358) and characterization tests that need to seed the conduit schema
180
+ * onto a caller-owned handle.
407
181
  *
182
+ * Idempotent: every migration statement uses `IF NOT EXISTS`, so applying it onto
183
+ * an already-populated DB is a no-op (the journal reconciler marks it applied).
184
+ *
185
+ * @task T344
408
186
  * @task T1407
187
+ * @task T11523
409
188
  * @epic T310
189
+ * @param db - An open node:sqlite DatabaseSync instance.
410
190
  */
411
- export function resolveConduitMigrationsFolder() {
412
- return resolveCorePackageMigrationsFolder('drizzle-conduit');
191
+ export function applyConduitSchema(db) {
192
+ runConduitMigrations(db);
413
193
  }
414
194
  /**
415
- * Run Drizzle migrations to reconcile and update conduit.db.
195
+ * Run Drizzle migrations to reconcile and update the conduit schema on the given
196
+ * native handle.
416
197
  *
417
198
  * Uses `reconcileJournal()` + `migrateSanitized()` from migration-manager.ts —
418
199
  * the canonical SSoT for SQLite migration semantics shared with tasks/brain/
419
- * nexus/signaldock/telemetry.
420
- *
421
- * Reconciliation handles:
422
- * - Scenario 1: existing DB with schema present but no `__drizzle_migrations`
423
- * table bootstrap baseline as applied.
424
- * - Scenario 3: comment-only baseline marker on a populated DB marked
425
- * applied immediately without running DDL.
426
- * - Scenario 4: backfill `name` on null journal entries (Drizzle v1 beta).
427
- *
428
- * The existence sentinel is `conversations` the first table created by
429
- * `applyConduitSchema()` (always present on any conduit.db that has been
430
- * through a successful init).
200
+ * nexus/signaldock/telemetry. The conduit `__drizzle_migrations` journal lives in
201
+ * the same `cleo.db` as the consolidated cleo-project journal; the hashes are
202
+ * disjoint, so the conduit migrations reconcile/apply independently.
203
+ *
204
+ * The existence sentinel is `_conduit_meta` (T11578 · AC4) — a table the conduit
205
+ * forward migration ITSELF creates, NOT one the consolidated migration owns. This
206
+ * is critical: `reconcileJournal` Scenario 2 (orphan deletion) is gated on the
207
+ * sentinel already existing. The consolidated cleo-project migration runs FIRST
208
+ * (via `openDualScopeDb`) and writes its OWN entries into the SHARED
209
+ * `__drizzle_migrations` journal; if the sentinel were a consolidated-owned table
210
+ * (e.g. `conduit_messages`) it would already exist on the first conduit open, so
211
+ * Scenario 2 would fire, see the consolidated entries as "orphans" (absent from
212
+ * the conduit folder), and DELETE them — corrupting the consolidated journal and
213
+ * forcing a destructive re-run on the next open (`table … already exists`).
214
+ * Pinning the sentinel to a conduit-migration-created table keeps Scenario 2
215
+ * dormant until the conduit set is journaled, exactly as the pre-cutover bare
216
+ * `conversations` sentinel did.
431
217
  *
432
218
  * @task T1407
219
+ * @task T11523
220
+ * @task T11578
433
221
  * @epic T310
434
222
  */
435
223
  function runConduitMigrations(nativeDb) {
436
224
  const migrationsFolder = resolveConduitMigrationsFolder();
437
- // Reconcile the Drizzle journal first so existing DBs don't try to re-run
438
- // the comment-only baseline marker (Scenario 3 marks it applied immediately
439
- // when the schema already matches).
440
- reconcileJournal(nativeDb, migrationsFolder, 'conversations', 'conduit');
441
- const db = drizzle({ client: nativeDb, schema: conduitSchema });
225
+ // Reconcile the Drizzle journal first so existing DBs don't try to re-run the
226
+ // comment-only baseline marker (Scenario 3 marks it applied immediately when
227
+ // the schema already matches). Sentinel = `_conduit_meta` (created by the
228
+ // conduit migration itself — see the doc note above on why it must NOT be a
229
+ // consolidated-owned table).
230
+ reconcileJournal(nativeDb, migrationsFolder, '_conduit_meta', 'conduit');
231
+ const db = _getDrizzle()({ client: nativeDb, schema: conduitSchema });
442
232
  migrateSanitized(db, { migrationsFolder });
443
233
  }
444
234
  /**
445
- * Opens or creates conduit.db for the given project root.
446
- *
447
- * On first call for a given projectRoot:
448
- * 1. Creates `<projectRoot>/.cleo/` directory if missing.
449
- * 2. Opens (or creates) the SQLite file.
450
- * 3. Sets WAL mode and enables foreign keys.
451
- * 4. Bootstraps schema via `applyConduitSchema` (idempotent CREATE
452
- * TABLE/INDEX/TRIGGER/VIRTUAL TABLE IF NOT EXISTS the only path
453
- * that creates the FTS5 virtual table + triggers Drizzle cannot
454
- * model).
455
- * 5. Runs Drizzle migration reconciliation + apply pending migrations
456
- * via `runConduitMigrations()` (canonical migration-manager.ts SSoT).
457
- * 6. Records `schema_version` in `_conduit_meta` (legacy, retained for
458
- * backwards compatibility with pre-T1407 health checks).
459
- * 7. Stores the open handle in the module singleton.
235
+ * Initialize the project-scope CONDUIT domain SQLite database (lazy, singleton).
236
+ *
237
+ * ## E6-L3 façade (T11523)
238
+ *
239
+ * Delegates the physical DB open to {@link openDualScopeDb}('project', cwd) the
240
+ * canonical dual-scope chokepoint. openDualScopeDb applies the pragma SSoT,
241
+ * creates the directory, runs the consolidated cleo-project migrations (which
242
+ * create the prefixed `conduit_*` tables), and manages the singleton cache. We
243
+ * extract its native handle (`$client`) and run the `drizzle-conduit` migration on
244
+ * it to (idempotently) create the `conduit_messages_fts` FTS5 quartet that the
245
+ * consolidated migration omits. After the AC4 cutover (T11578) the LocalTransport +
246
+ * accessor writers query the SAME prefixed `conduit_*` tables the exodus
247
+ * migration (T11248 / T11553) renames any pre-cutover BARE data into them.
460
248
  *
461
249
  * On subsequent calls the existing singleton is returned immediately if the
462
- * resolved path matches; otherwise the previous handle is closed and a new
463
- * one is opened (test-isolation safety).
250
+ * resolved path matches AND the shared handle is still live (liveness guard);
251
+ * otherwise it re-derives from the live dual-scope cache.
464
252
  *
465
- * Caller MUST call `closeConduitDb()` when done to release the handle.
253
+ * Uses a promise guard so concurrent callers wait for the same initialization to
254
+ * complete (the dual-scope open is async).
466
255
  *
467
256
  * @task T344
468
257
  * @task T1407
258
+ * @task T11523
469
259
  * @epic T310
470
260
  * @param projectRoot - Absolute path to the project root directory.
471
261
  * @returns Object with `action` (`'created'` | `'exists'`) and `path`.
472
262
  */
473
- /**
474
- * Read the `schema_version` row from `_conduit_meta` if it exists.
475
- *
476
- * Used by {@link ensureConduitDb} as a fast-path sentinel: when the value
477
- * matches {@link CONDUIT_SCHEMA_VERSION} we know the DB is fully bootstrapped
478
- * and migrated to the in-process code version, so we can skip the full
479
- * `applyConduitSchema()` + `runConduitMigrations()` pipeline on every CLI
480
- * invocation (T9027 — epic T9026, CLI startup tax reduction).
481
- *
482
- * Defensive: returns `null` if the meta table is missing (pre-T1407 layout)
483
- * or the row is absent. Any throw is swallowed — a sentinel miss simply
484
- * forces the fall-through full-init path which is always safe.
485
- *
486
- * @param db - An open conduit.db handle (post-pragmas).
487
- * @returns The schema_version string, or `null` if absent / unreadable.
488
- * @task T9027
489
- * @epic T9026
490
- */
491
- function readSchemaVersionSentinel(db) {
492
- try {
493
- const row = db.prepare("SELECT value FROM _conduit_meta WHERE key = 'schema_version'").get();
494
- return row?.value ?? null;
495
- }
496
- catch {
497
- return null;
498
- }
499
- }
500
- export function ensureConduitDb(projectRoot) {
263
+ export async function ensureConduitDb(projectRoot) {
501
264
  const dbPath = getConduitDbPath(projectRoot);
502
- // If singleton already open at the same path, skip re-initialization.
265
+ // Liveness guard (T11523): the conduit domain SHARES the consolidated cleo.db
266
+ // handle with the tasks + brain domains. Another domain may have closed +
267
+ // re-opened the shared `DatabaseSync` (e.g. its reset / auto-recovery path)
268
+ // while our conduit singleton still references the now-closed handle. Detect a
269
+ // stale (closed) handle, or a singleton bound to a different path, and drop it
270
+ // so we re-derive from the live openDualScopeDb cache below.
271
+ if (_conduitNativeDb && (!_conduitNativeDb.isOpen || _conduitDbPath !== dbPath)) {
272
+ resetConduitDbState();
273
+ }
274
+ // If singleton already open at the same path and live, skip re-initialization.
503
275
  if (_conduitNativeDb && _conduitDbPath === dbPath) {
504
276
  return { action: 'exists', path: dbPath };
505
277
  }
506
- // Close any stale singleton pointing at a different path (e.g. between tests).
507
- if (_conduitNativeDb) {
508
- closeConduitDb();
509
- }
510
- const alreadyExists = existsSync(dbPath);
511
- // Ensure parent .cleo/ directory exists.
512
- mkdirSync(dirname(dbPath), { recursive: true });
513
- const db = new DatabaseSync(dbPath);
514
- // Canonical CLEO pragma set (WAL, busy_timeout, synchronous=NORMAL, FK on,
515
- // 64MB cache, 256MB mmap, MEMORY temp store, wal_autocheckpoint).
516
- applyPerfPragmas(db);
517
- // Check whether the schema sentinel table already exists before applying DDL.
518
- const hasSchema = (() => {
519
- try {
520
- const result = db
521
- .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='conversations'")
522
- .get();
523
- return !!result;
524
- }
525
- catch {
526
- return false;
278
+ // If already initializing, wait for the in-flight init.
279
+ if (_initPromise)
280
+ return _initPromise;
281
+ _initPromise = (async () => {
282
+ const alreadyExists = existsSync(dbPath);
283
+ // ── Dual-scope chokepoint delegation (T11523 · E6-L3) ──────────────────
284
+ // openDualScopeDb applies the pragma SSoT, creates the directory, runs the
285
+ // consolidated cleo-project migrations (which create the `conduit_*` tables),
286
+ // and manages the singleton cache. We extract its native handle so we can run
287
+ // the legacy `drizzle-conduit` migrations for caller compatibility.
288
+ const dualHandle = await openDualScopeDb('project', projectRoot);
289
+ // Extract the underlying DatabaseSync. Drizzle exposes it via `$client`.
290
+ const nativeDb = dualHandle.db.$client ?? null;
291
+ if (!nativeDb) {
292
+ throw new Error('E6-L3: openDualScopeDb returned a handle without $client — ' +
293
+ 'cannot extract DatabaseSync for legacy conduit-schema wrapping.');
527
294
  }
528
- })();
529
- // T9027 Schema-version sentinel fast path (epic T9026, CLI startup tax).
530
- //
531
- // If the DB already has the conduit schema applied AND its
532
- // `_conduit_meta.schema_version` row exactly equals the in-process
533
- // `CONDUIT_SCHEMA_VERSION` constant, we know:
534
- // 1. All DDL is already in place (CREATE TABLE IF NOT EXISTS would no-op).
535
- // 2. All Drizzle migrations up to this version have already been replayed
536
- // (the meta row is only written at the tail of a successful ensure()).
537
- //
538
- // In that case skip applyConduitSchema() and runConduitMigrations() entirely
539
- // both perform non-trivial work (DDL string parse for the former, journal
540
- // SELECT + reconciler for the latter) on every CLI invocation. Pragmas are
541
- // already applied above.
542
- //
543
- // Fall-through (sentinel missing, stale, or mismatched) preserves the full
544
- // bootstrap + migration replay path so fresh DBs and version bumps work.
545
- if (alreadyExists && hasSchema && readSchemaVersionSentinel(db) === CONDUIT_SCHEMA_VERSION) {
546
- _conduitNativeDb = db;
295
+ // Establish the FTS5 index over the consolidated `conduit_messages` table.
296
+ // The consolidated migrations already created the prefixed `conduit_*` tables;
297
+ // running the `drizzle-conduit` set adds the `conduit_messages_fts` virtual
298
+ // table + its 3 sync triggers (drizzle-orm cannot model FTS5, so the
299
+ // consolidated migration omits them). Idempotent: a no-op once the FTS index
300
+ // already exists (T11578 · AC4).
301
+ runConduitMigrations(nativeDb);
302
+ // Record schema version in the legacy `_conduit_meta` table for backwards-
303
+ // compatible health-check consumers (checkConduitDbHealth and any external
304
+ // tooling that grepped the meta table prior to T1407). The Drizzle journal
305
+ // (`__drizzle_migrations`) is the canonical migration source-of-truth.
306
+ nativeDb.exec(`INSERT OR REPLACE INTO _conduit_meta (key, value, updated_at)
307
+ VALUES ('schema_version', '${CONDUIT_SCHEMA_VERSION}', strftime('%s', 'now'))`);
308
+ _conduitNativeDb = nativeDb;
547
309
  _conduitDbPath = dbPath;
548
- return { action: 'exists', path: dbPath };
310
+ return { action: alreadyExists ? 'exists' : 'created', path: dbPath };
311
+ })();
312
+ try {
313
+ return await _initPromise;
314
+ }
315
+ finally {
316
+ _initPromise = null;
549
317
  }
550
- // Bootstrap schema (idempotent — all statements use IF NOT EXISTS). For fresh
551
- // DBs this creates every conduit table, the FTS5 virtual table, and its 3
552
- // triggers. For populated DBs this is a no-op.
553
- applyConduitSchema(db);
554
- // Run Drizzle migration reconciliation + apply any pending migrations
555
- // (T1407 unification — canonical migration-manager.ts runner).
556
- runConduitMigrations(db);
557
- // Record schema version in the legacy `_conduit_meta` table for backwards-
558
- // compatible health-check consumers (checkConduitDbHealth and any external
559
- // tooling that grepped the meta table prior to T1407). The Drizzle journal
560
- // (`__drizzle_migrations`) is now the canonical migration source-of-truth.
561
- db.exec(`INSERT OR REPLACE INTO _conduit_meta (key, value, updated_at)
562
- VALUES ('schema_version', '${CONDUIT_SCHEMA_VERSION}', strftime('%s', 'now'))`);
563
- _conduitNativeDb = db;
564
- _conduitDbPath = dbPath;
565
- return {
566
- action: alreadyExists && hasSchema ? 'exists' : 'created',
567
- path: dbPath,
568
- };
569
318
  }
570
319
  /**
571
- * Returns the live node:sqlite DatabaseSync handle for conduit.db.
320
+ * Returns the live node:sqlite DatabaseSync handle for the conduit domain.
572
321
  *
573
- * Returns `null` if `ensureConduitDb` has not been called yet for this
574
- * process, or if `closeConduitDb` has been called since the last open.
322
+ * Returns `null` if `ensureConduitDb` has not been called yet for this process,
323
+ * or if the shared handle has been closed since the last open.
575
324
  *
576
325
  * @task T344
577
326
  * @epic T310
@@ -581,29 +330,47 @@ export function getConduitNativeDb() {
581
330
  return _conduitNativeDb;
582
331
  }
583
332
  /**
584
- * Closes the conduit.db connection and resets the module singleton.
333
+ * Close the conduit-domain database connection and reset the module singleton.
334
+ *
335
+ * ## E6-L3 (T11523)
585
336
  *
586
- * Safe to call multiple times. No-op if the database is already closed.
337
+ * The conduit domain now SHARES the consolidated project `cleo.db` handle with
338
+ * the tasks + brain domains (all open it via {@link openDualScopeDb}, same cache
339
+ * key). This function therefore must NOT close the underlying `DatabaseSync` nor
340
+ * evict the dual-scope cache — doing so would break in-flight tasks/brain-domain
341
+ * queries with "database is not open". It only drops the conduit-domain singleton
342
+ * references; the shared handle's lifecycle is owned by `openDualScopeDb` and torn
343
+ * down by a coordinated reset (`closeAllDatabases` → `_resetDualScopeDbCache`).
344
+ *
345
+ * Safe to call multiple times.
587
346
  *
588
347
  * @task T344
348
+ * @task T11523
589
349
  * @epic T310
590
350
  */
591
351
  export function closeConduitDb() {
592
- if (_conduitNativeDb) {
593
- try {
594
- if (_conduitNativeDb.isOpen) {
595
- // PRAGMA optimize before close so the next process inherits up-to-date
596
- // table statistics for query planning (SQLite-recommended pattern).
597
- optimizeBeforeClose(_conduitNativeDb);
598
- _conduitNativeDb.close();
599
- }
600
- }
601
- catch {
602
- // Ignore close errorsthe handle is being discarded regardless.
603
- }
604
- _conduitNativeDb = null;
605
- }
352
+ // Drop only the conduit singleton references. Do NOT close `_conduitNativeDb`
353
+ // — it is the shared dual-scope handle, possibly still in use by tasks/brain.
354
+ _conduitNativeDb = null;
355
+ _conduitDbPath = null;
356
+ _initPromise = null;
357
+ }
358
+ /**
359
+ * Reset conduit-domain singleton state without saving.
360
+ *
361
+ * Used during tests or when the shared database handle is recreated. Drops only
362
+ * the conduit-domain singleton references does NOT close the shared dual-scope
363
+ * `cleo.db` handle nor evict the dual-scope cache (that handle is shared with the
364
+ * tasks + brain domains). Mirrors {@link closeConduitDb}. Safe to call multiple
365
+ * times.
366
+ *
367
+ * @task T11523
368
+ * @epic T310
369
+ */
370
+ export function resetConduitDbState() {
371
+ _conduitNativeDb = null;
606
372
  _conduitDbPath = null;
373
+ _initPromise = null;
607
374
  }
608
375
  // ---------------------------------------------------------------------------
609
376
  // project_agent_refs CRUD accessors (T353)
@@ -613,7 +380,7 @@ export function closeConduitDb() {
613
380
  * re-enables it (update attached_at timestamp). If a row exists with enabled=1,
614
381
  * no-op. Inserts a new row otherwise.
615
382
  *
616
- * @param db - conduit.db handle (from ensureConduitDb).
383
+ * @param db - conduit handle (from ensureConduitDb).
617
384
  * @param agentId - Global signaldock.db:agents.id (soft FK, not validated here).
618
385
  * @param opts - Optional role and capabilities override.
619
386
  * @task T353
@@ -621,11 +388,11 @@ export function closeConduitDb() {
621
388
  */
622
389
  export function attachAgentToProject(db, agentId, opts) {
623
390
  const now = new Date().toISOString();
624
- db.prepare(`INSERT INTO project_agent_refs (agent_id, attached_at, role, capabilities_override, last_used_at, enabled)
391
+ db.prepare(`INSERT INTO conduit_project_agent_refs (agent_id, attached_at, role, capabilities_override, last_used_at, enabled)
625
392
  VALUES (?, ?, ?, ?, NULL, 1)
626
393
  ON CONFLICT(agent_id) DO UPDATE SET
627
394
  enabled = 1,
628
- attached_at = CASE WHEN project_agent_refs.enabled = 0 THEN excluded.attached_at ELSE project_agent_refs.attached_at END,
395
+ attached_at = CASE WHEN conduit_project_agent_refs.enabled = 0 THEN excluded.attached_at ELSE conduit_project_agent_refs.attached_at END,
629
396
  role = excluded.role,
630
397
  capabilities_override = excluded.capabilities_override`).run(agentId, now, opts?.role ?? null, opts?.capabilitiesOverride ?? null);
631
398
  }
@@ -633,19 +400,19 @@ export function attachAgentToProject(db, agentId, opts) {
633
400
  * Detaches an agent from the current project by setting enabled=0.
634
401
  * Does NOT delete the row (preserves attachment history for audit).
635
402
  *
636
- * @param db - conduit.db handle (from ensureConduitDb).
403
+ * @param db - conduit handle (from ensureConduitDb).
637
404
  * @param agentId - Agent ID to detach.
638
405
  * @task T353
639
406
  * @epic T310
640
407
  */
641
408
  export function detachAgentFromProject(db, agentId) {
642
- db.prepare(`UPDATE project_agent_refs SET enabled = 0 WHERE agent_id = ?`).run(agentId);
409
+ db.prepare(`UPDATE conduit_project_agent_refs SET enabled = 0 WHERE agent_id = ?`).run(agentId);
643
410
  }
644
411
  /**
645
412
  * Lists project_agent_refs rows. By default returns only enabled=1 rows.
646
413
  * Pass enabledOnly=false to return all rows regardless of enabled state.
647
414
  *
648
- * @param db - conduit.db handle (from ensureConduitDb).
415
+ * @param db - conduit handle (from ensureConduitDb).
649
416
  * @param opts - Filter options. Defaults to `{ enabledOnly: true }`.
650
417
  * @returns Array of ProjectAgentRef rows ordered by attached_at DESC.
651
418
  * @task T353
@@ -655,10 +422,10 @@ export function listProjectAgentRefs(db, opts) {
655
422
  const enabledOnly = opts?.enabledOnly ?? true;
656
423
  const sql = enabledOnly
657
424
  ? `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
658
- FROM project_agent_refs WHERE enabled = 1
425
+ FROM conduit_project_agent_refs WHERE enabled = 1
659
426
  ORDER BY attached_at DESC`
660
427
  : `SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
661
- FROM project_agent_refs
428
+ FROM conduit_project_agent_refs
662
429
  ORDER BY attached_at DESC`;
663
430
  const rows = db.prepare(sql).all();
664
431
  return rows.map((r) => ({
@@ -673,7 +440,7 @@ export function listProjectAgentRefs(db, opts) {
673
440
  /**
674
441
  * Returns a single project_agent_refs row by agentId, or null if not found.
675
442
  *
676
- * @param db - conduit.db handle (from ensureConduitDb).
443
+ * @param db - conduit handle (from ensureConduitDb).
677
444
  * @param agentId - Agent ID to look up.
678
445
  * @returns The ProjectAgentRef row, or null if the agent is not attached.
679
446
  * @task T353
@@ -682,7 +449,7 @@ export function listProjectAgentRefs(db, opts) {
682
449
  export function getProjectAgentRef(db, agentId) {
683
450
  const row = db
684
451
  .prepare(`SELECT agent_id, attached_at, role, capabilities_override, last_used_at, enabled
685
- FROM project_agent_refs WHERE agent_id = ?`)
452
+ FROM conduit_project_agent_refs WHERE agent_id = ?`)
686
453
  .get(agentId);
687
454
  if (!row)
688
455
  return null;
@@ -699,25 +466,30 @@ export function getProjectAgentRef(db, agentId) {
699
466
  * Updates the last_used_at timestamp for an agent to now.
700
467
  * No-op if the agent_id does not exist in project_agent_refs.
701
468
  *
702
- * @param db - conduit.db handle (from ensureConduitDb).
469
+ * @param db - conduit handle (from ensureConduitDb).
703
470
  * @param agentId - Agent ID to update.
704
471
  * @task T353
705
472
  * @epic T310
706
473
  */
707
474
  export function updateProjectAgentLastUsed(db, agentId) {
708
- db.prepare(`UPDATE project_agent_refs SET last_used_at = ? WHERE agent_id = ?`).run(new Date().toISOString(), agentId);
475
+ db.prepare(`UPDATE conduit_project_agent_refs SET last_used_at = ? WHERE agent_id = ?`).run(new Date().toISOString(), agentId);
709
476
  }
710
477
  /**
711
- * Checks conduit.db health — table count, WAL mode, schema version, and
478
+ * Checks conduit-domain health — table count, WAL mode, schema version, and
712
479
  * foreign keys status.
713
480
  *
714
- * Used by `cleo doctor` to verify conduit.db integrity. Does NOT require
715
- * `ensureConduitDb` to have been called; opens and closes the DB internally.
481
+ * ## E6-L3 (T11523)
482
+ *
483
+ * The conduit domain now lives in the consolidated project `cleo.db`. This probe
484
+ * opens that file (read-only inspection of pragma + sqlite_master state) — it does
485
+ * NOT require `ensureConduitDb` to have been called and opens/closes its own
486
+ * short-lived connection. Used by `cleo doctor` to verify conduit integrity.
716
487
  *
717
488
  * @task T344
489
+ * @task T11523
718
490
  * @epic T310
719
491
  * @param projectRoot - Absolute path to the project root directory.
720
- * @returns Health report object. `exists: false` when conduit.db is absent.
492
+ * @returns Health report object. `exists: false` when the DB is absent.
721
493
  */
722
494
  export function checkConduitDbHealth(projectRoot) {
723
495
  const dbPath = getConduitDbPath(projectRoot);
@@ -767,17 +539,24 @@ export function checkConduitDbHealth(projectRoot) {
767
539
  }
768
540
  }
769
541
  /**
770
- * Open a fresh (non-singleton) conduit.db connection with pragmas applied.
542
+ * Open a fresh (non-singleton) connection to the conduit-domain DB with pragmas
543
+ * applied.
544
+ *
545
+ * ## E6-L3 (T11523)
771
546
  *
772
- * Unlike `ensureConduitDb`, this creates an independent connection that the
773
- * caller owns and must close. Intended for callers that manage connection
774
- * lifecycle explicitly (e.g. LocalTransport connect/disconnect cycle).
547
+ * The conduit domain now lives in the consolidated project `cleo.db`. This opens
548
+ * an independent connection to that file (WAL mode permits concurrent
549
+ * connections) that the caller owns and must close. Intended for callers that
550
+ * manage connection lifecycle explicitly (e.g. LocalTransport connect/disconnect
551
+ * cycle). The caller is responsible for ensuring `ensureConduitDb` has run first
552
+ * so the bare conduit tables exist.
775
553
  *
776
554
  * Applies the pragma SSoT from `specs/sqlite-pragmas.json` (T9047, T9189).
777
555
  *
778
- * @param projectRoot - Project root for resolving conduit.db path.
556
+ * @param projectRoot - Project root for resolving the conduit DB path.
779
557
  * @returns An open DatabaseSync connection (caller must close).
780
558
  * @task T9189
559
+ * @task T11523
781
560
  */
782
561
  export function openFreshConduitDb(projectRoot) {
783
562
  const dbPath = getConduitDbPath(projectRoot);