@cleocode/core 2026.3.76 → 2026.4.2

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 (473) hide show
  1. package/dist/agents/agent-schema.d.ts.map +1 -1
  2. package/dist/audit.d.ts +1 -1
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/bootstrap.d.ts +2 -2
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/caamp/adapter.d.ts +6 -49
  7. package/dist/caamp/adapter.d.ts.map +1 -1
  8. package/dist/caamp/index.d.ts +2 -2
  9. package/dist/caamp/index.d.ts.map +1 -1
  10. package/dist/code/index.d.ts +10 -0
  11. package/dist/code/index.d.ts.map +1 -0
  12. package/dist/code/outline.d.ts +51 -0
  13. package/dist/code/outline.d.ts.map +1 -0
  14. package/dist/code/parser.d.ts +32 -0
  15. package/dist/code/parser.d.ts.map +1 -0
  16. package/dist/code/search.d.ts +42 -0
  17. package/dist/code/search.d.ts.map +1 -0
  18. package/dist/code/unfold.d.ts +44 -0
  19. package/dist/code/unfold.d.ts.map +1 -0
  20. package/dist/compliance/protocol-enforcement.d.ts +1 -1
  21. package/dist/compliance/protocol-rules.d.ts +1 -1
  22. package/dist/compliance/protocol-types.d.ts +2 -3
  23. package/dist/compliance/protocol-types.d.ts.map +1 -1
  24. package/dist/conduit/conduit-client.d.ts +14 -0
  25. package/dist/conduit/conduit-client.d.ts.map +1 -1
  26. package/dist/conduit/factory.d.ts +11 -1
  27. package/dist/conduit/factory.d.ts.map +1 -1
  28. package/dist/conduit/http-transport.d.ts +17 -5
  29. package/dist/conduit/http-transport.d.ts.map +1 -1
  30. package/dist/conduit/index.d.ts +5 -2
  31. package/dist/conduit/index.d.ts.map +1 -1
  32. package/dist/conduit/local-transport.d.ts +91 -0
  33. package/dist/conduit/local-transport.d.ts.map +1 -0
  34. package/dist/conduit/sse-transport.d.ts +68 -0
  35. package/dist/conduit/sse-transport.d.ts.map +1 -0
  36. package/dist/crypto/credentials.d.ts.map +1 -1
  37. package/dist/error-catalog.d.ts +3 -3
  38. package/dist/error-catalog.d.ts.map +1 -1
  39. package/dist/errors.d.ts +1 -1
  40. package/dist/hooks/handlers/index.d.ts +2 -2
  41. package/dist/hooks/handlers/index.d.ts.map +1 -1
  42. package/dist/hooks/handlers/notification-hooks.d.ts +31 -0
  43. package/dist/hooks/handlers/notification-hooks.d.ts.map +1 -0
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +4646 -3476
  47. package/dist/index.js.map +4 -4
  48. package/dist/init.d.ts +6 -6
  49. package/dist/init.d.ts.map +1 -1
  50. package/dist/injection.d.ts.map +1 -1
  51. package/dist/internal.d.ts +7 -5
  52. package/dist/internal.d.ts.map +1 -1
  53. package/dist/lib/index.d.ts +1 -0
  54. package/dist/lib/index.d.ts.map +1 -1
  55. package/dist/lib/tree-sitter-languages.d.ts +29 -0
  56. package/dist/lib/tree-sitter-languages.d.ts.map +1 -0
  57. package/dist/logger.d.ts +3 -3
  58. package/dist/memory/brain-links.d.ts.map +1 -1
  59. package/dist/memory/brain-maintenance.d.ts +13 -0
  60. package/dist/memory/brain-maintenance.d.ts.map +1 -1
  61. package/dist/memory/brain-retrieval.d.ts +1 -1
  62. package/dist/memory/brain-retrieval.d.ts.map +1 -1
  63. package/dist/memory/decisions.d.ts.map +1 -1
  64. package/dist/memory/engine-compat.d.ts +392 -25
  65. package/dist/memory/engine-compat.d.ts.map +1 -1
  66. package/dist/memory/index.d.ts +416 -3
  67. package/dist/memory/index.d.ts.map +1 -1
  68. package/dist/metrics/token-service.d.ts +3 -3
  69. package/dist/metrics/token-service.d.ts.map +1 -1
  70. package/dist/orchestration/hierarchy.d.ts +32 -0
  71. package/dist/orchestration/hierarchy.d.ts.map +1 -0
  72. package/dist/orchestration/index.d.ts +1 -0
  73. package/dist/orchestration/index.d.ts.map +1 -1
  74. package/dist/paths.d.ts +335 -2
  75. package/dist/paths.d.ts.map +1 -1
  76. package/dist/routing/capability-matrix.d.ts +3 -3
  77. package/dist/routing/capability-matrix.d.ts.map +1 -1
  78. package/dist/scaffold.d.ts +422 -11
  79. package/dist/scaffold.d.ts.map +1 -1
  80. package/dist/security/input-sanitization.d.ts +2 -2
  81. package/dist/skills/dynamic-skill-generator.d.ts +3 -2
  82. package/dist/skills/dynamic-skill-generator.d.ts.map +1 -1
  83. package/dist/skills/routing-table.d.ts +4 -4
  84. package/dist/skills/routing-table.d.ts.map +1 -1
  85. package/dist/store/agent-registry-accessor.d.ts +10 -433
  86. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  87. package/dist/store/cross-db-cleanup.d.ts +34 -0
  88. package/dist/store/cross-db-cleanup.d.ts.map +1 -1
  89. package/dist/store/provider.d.ts +1 -1
  90. package/dist/store/signaldock-sqlite.d.ts.map +1 -1
  91. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  92. package/dist/store/sqlite.d.ts +1 -1
  93. package/dist/store/task-store.d.ts.map +1 -1
  94. package/dist/store/tasks-schema.d.ts +4 -228
  95. package/dist/store/tasks-schema.d.ts.map +1 -1
  96. package/dist/store/validation-schemas.d.ts +4 -5
  97. package/dist/store/validation-schemas.d.ts.map +1 -1
  98. package/dist/system/archive-analytics.d.ts +1 -1
  99. package/dist/system/health.d.ts +2 -2
  100. package/dist/system/health.d.ts.map +1 -1
  101. package/dist/system/runtime.d.ts +2 -1
  102. package/dist/system/runtime.d.ts.map +1 -1
  103. package/dist/tasks/list.d.ts +1 -1
  104. package/dist/tasks/list.d.ts.map +1 -1
  105. package/dist/tasks/task-ops.d.ts +415 -3
  106. package/dist/tasks/task-ops.d.ts.map +1 -1
  107. package/dist/templates/parser.d.ts +1 -1
  108. package/dist/ui/index.d.ts +1 -1
  109. package/dist/upgrade.d.ts +1 -1
  110. package/dist/upgrade.d.ts.map +1 -1
  111. package/dist/validation/operation-gate-validators.d.ts +1 -1
  112. package/dist/validation/operation-verification-gates.d.ts +3 -3
  113. package/dist/validation/param-utils.d.ts +6 -5
  114. package/dist/validation/param-utils.d.ts.map +1 -1
  115. package/dist/validation/validate-ops.d.ts +1 -1
  116. package/dist/validation/validate-ops.d.ts.map +1 -1
  117. package/package.json +19 -7
  118. package/src/__tests__/caamp-skill-install.test.js +0 -15
  119. package/src/__tests__/caamp-skill-install.test.js.map +1 -1
  120. package/src/__tests__/caamp-skill-install.test.ts +0 -16
  121. package/src/__tests__/injection-mvi-tiers.test.js +7 -7
  122. package/src/__tests__/injection-mvi-tiers.test.js.map +1 -1
  123. package/src/__tests__/injection-mvi-tiers.test.ts +55 -103
  124. package/src/agents/agent-schema.ts +2 -5
  125. package/src/audit.ts +2 -2
  126. package/src/bootstrap.ts +5 -39
  127. package/src/caamp/adapter.ts +3 -219
  128. package/src/caamp/index.ts +1 -13
  129. package/src/cant/__tests__/cant-agent-parse.test.d.ts.map +1 -0
  130. package/src/cant/__tests__/cant-agent-parse.test.js +77 -0
  131. package/src/cant/__tests__/cant-agent-parse.test.js.map +1 -0
  132. package/src/code/index.ts +10 -0
  133. package/src/code/outline.ts +214 -0
  134. package/src/code/parser.ts +331 -0
  135. package/src/code/search.ts +173 -0
  136. package/src/code/unfold.ts +204 -0
  137. package/src/codebase-map/analyzers/architecture.ts +2 -2
  138. package/src/compliance/protocol-enforcement.ts +1 -1
  139. package/src/compliance/protocol-rules.ts +1 -1
  140. package/src/compliance/protocol-types.ts +2 -3
  141. package/src/conduit/__tests__/dual-api-e2e.test.d.ts.map +1 -0
  142. package/src/conduit/__tests__/dual-api-e2e.test.js +178 -0
  143. package/src/conduit/__tests__/dual-api-e2e.test.js.map +1 -0
  144. package/src/conduit/__tests__/dual-api-e2e.test.ts +212 -0
  145. package/src/conduit/__tests__/local-credential-flow.test.d.ts.map +1 -0
  146. package/src/conduit/__tests__/local-credential-flow.test.js +185 -0
  147. package/src/conduit/__tests__/local-credential-flow.test.js.map +1 -0
  148. package/src/conduit/__tests__/local-credential-flow.test.ts +230 -0
  149. package/src/conduit/__tests__/local-transport.test.d.ts.map +1 -0
  150. package/src/conduit/__tests__/local-transport.test.js +404 -0
  151. package/src/conduit/__tests__/local-transport.test.js.map +1 -0
  152. package/src/conduit/__tests__/local-transport.test.ts +509 -0
  153. package/src/conduit/__tests__/sse-transport.test.d.ts.map +1 -0
  154. package/src/conduit/__tests__/sse-transport.test.js +291 -0
  155. package/src/conduit/__tests__/sse-transport.test.js.map +1 -0
  156. package/src/conduit/__tests__/sse-transport.test.ts +344 -0
  157. package/src/conduit/conduit-client.ts +14 -0
  158. package/src/conduit/factory.ts +29 -8
  159. package/src/conduit/http-transport.ts +78 -16
  160. package/src/conduit/index.ts +5 -2
  161. package/src/conduit/local-transport.ts +309 -0
  162. package/src/conduit/sse-transport.ts +382 -0
  163. package/src/crypto/credentials.ts +59 -13
  164. package/src/error-catalog.ts +3 -3
  165. package/src/errors.ts +1 -1
  166. package/src/hooks/__tests__/provider-hooks.test.js +4 -4
  167. package/src/hooks/__tests__/provider-hooks.test.js.map +1 -1
  168. package/src/hooks/__tests__/provider-hooks.test.ts +4 -4
  169. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js +2 -2
  170. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js.map +1 -1
  171. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.ts +6 -4
  172. package/src/hooks/handlers/index.ts +2 -6
  173. package/src/hooks/handlers/notification-hooks.ts +65 -0
  174. package/src/index.ts +2 -1
  175. package/src/init.ts +14 -54
  176. package/src/injection.ts +4 -3
  177. package/src/internal.ts +7 -5
  178. package/src/lib/index.ts +8 -0
  179. package/src/lib/tree-sitter-languages.ts +88 -0
  180. package/src/logger.ts +5 -5
  181. package/src/memory/__tests__/brain-links.test.js +13 -0
  182. package/src/memory/__tests__/brain-links.test.js.map +1 -1
  183. package/src/memory/__tests__/brain-links.test.ts +14 -0
  184. package/src/memory/__tests__/brain-retrieval.test.js +9 -0
  185. package/src/memory/__tests__/brain-retrieval.test.js.map +1 -1
  186. package/src/memory/__tests__/brain-retrieval.test.ts +10 -0
  187. package/src/memory/__tests__/session-memory.test.js +16 -0
  188. package/src/memory/__tests__/session-memory.test.js.map +1 -1
  189. package/src/memory/__tests__/session-memory.test.ts +17 -0
  190. package/src/memory/brain-links.ts +17 -0
  191. package/src/memory/brain-maintenance.ts +33 -1
  192. package/src/memory/brain-retrieval.ts +19 -3
  193. package/src/memory/decisions.ts +18 -2
  194. package/src/memory/engine-compat.ts +392 -25
  195. package/src/memory/index.ts +417 -4
  196. package/src/metrics/token-service.ts +4 -4
  197. package/src/migration/index.ts +1 -1
  198. package/src/orchestration/hierarchy.ts +202 -0
  199. package/src/orchestration/index.ts +1 -0
  200. package/src/paths.ts +340 -5
  201. package/src/routing/capability-matrix.ts +49 -49
  202. package/src/scaffold.ts +428 -70
  203. package/src/security/input-sanitization.ts +4 -4
  204. package/src/sessions/__tests__/session-grade.integration.test.js +9 -9
  205. package/src/sessions/__tests__/session-grade.integration.test.ts +9 -9
  206. package/src/sessions/__tests__/session-grade.test.js +10 -10
  207. package/src/sessions/__tests__/session-grade.test.js.map +1 -1
  208. package/src/sessions/__tests__/session-grade.test.ts +10 -10
  209. package/src/sessions/session-grade.ts +4 -4
  210. package/src/skills/__tests__/dynamic-skill-generator.test.js +24 -26
  211. package/src/skills/__tests__/dynamic-skill-generator.test.js.map +1 -1
  212. package/src/skills/__tests__/dynamic-skill-generator.test.ts +24 -26
  213. package/src/skills/__tests__/routing-table.test.js +22 -22
  214. package/src/skills/__tests__/routing-table.test.js.map +1 -1
  215. package/src/skills/__tests__/routing-table.test.ts +23 -23
  216. package/src/skills/dynamic-skill-generator.ts +13 -24
  217. package/src/skills/routing-table.ts +4 -4
  218. package/src/store/__tests__/data-safety-central.test.js +8 -0
  219. package/src/store/__tests__/data-safety-central.test.js.map +1 -1
  220. package/src/store/__tests__/data-safety-central.test.ts +8 -0
  221. package/src/store/__tests__/safety-accessor.test.js +8 -0
  222. package/src/store/__tests__/safety-accessor.test.js.map +1 -1
  223. package/src/store/__tests__/safety-accessor.test.ts +8 -0
  224. package/src/store/agent-registry-accessor.ts +284 -108
  225. package/src/store/cross-db-cleanup.ts +175 -1
  226. package/src/store/provider.ts +2 -2
  227. package/src/store/signaldock-sqlite.ts +262 -60
  228. package/src/store/sqlite-data-accessor.ts +3 -0
  229. package/src/store/sqlite.ts +2 -2
  230. package/src/store/task-store.ts +8 -1
  231. package/src/store/tasks-schema.ts +5 -40
  232. package/src/system/__tests__/health.test.js +2 -2
  233. package/src/system/__tests__/health.test.js.map +1 -1
  234. package/src/system/__tests__/health.test.ts +2 -2
  235. package/src/system/archive-analytics.ts +1 -1
  236. package/src/system/health.ts +43 -19
  237. package/src/system/inject-generate.ts +20 -20
  238. package/src/system/runtime.ts +5 -4
  239. package/src/tasks/atomicity.ts +1 -1
  240. package/src/tasks/list.ts +1 -1
  241. package/src/tasks/task-ops.ts +415 -3
  242. package/src/templates/parser.ts +1 -1
  243. package/src/ui/index.ts +4 -4
  244. package/src/upgrade.ts +3 -14
  245. package/src/validation/operation-gate-validators.ts +1 -1
  246. package/src/validation/operation-verification-gates.ts +3 -3
  247. package/src/validation/param-utils.ts +11 -10
  248. package/src/validation/validate-ops.ts +6 -6
  249. package/templates/CLEO-INJECTION.md +38 -110
  250. package/dist/hooks/handlers/mcp-hooks.d.ts +0 -48
  251. package/dist/hooks/handlers/mcp-hooks.d.ts.map +0 -1
  252. package/dist/mcp/index.d.ts +0 -42
  253. package/dist/mcp/index.d.ts.map +0 -1
  254. package/src/__tests__/audit-prune.test.d.ts +0 -2
  255. package/src/__tests__/caamp-skill-install.test.d.ts +0 -14
  256. package/src/__tests__/cli-mcp-parity.integration.test.d.ts +0 -34
  257. package/src/__tests__/cli-mcp-parity.integration.test.d.ts.map +0 -1
  258. package/src/__tests__/cli-mcp-parity.integration.test.js +0 -898
  259. package/src/__tests__/cli-mcp-parity.integration.test.js.map +0 -1
  260. package/src/__tests__/cli-parity.test.d.ts +0 -9
  261. package/src/__tests__/config.test.d.ts +0 -7
  262. package/src/__tests__/core-parity.test.d.ts +0 -17
  263. package/src/__tests__/error-catalog.test.d.ts +0 -2
  264. package/src/__tests__/golden-parity.test.d.ts +0 -12
  265. package/src/__tests__/hooks.test.d.ts +0 -5
  266. package/src/__tests__/human-output.test.d.ts +0 -12
  267. package/src/__tests__/index-api-compat.test.d.ts +0 -2
  268. package/src/__tests__/init-e2e.test.d.ts +0 -12
  269. package/src/__tests__/injection-chain.test.d.ts +0 -18
  270. package/src/__tests__/injection-mvi-tiers.test.d.ts +0 -14
  271. package/src/__tests__/injection-shared.test.d.ts +0 -10
  272. package/src/__tests__/lafs-conformance.test.d.ts +0 -18
  273. package/src/__tests__/logger.test.d.ts +0 -2
  274. package/src/__tests__/mcp-install-verify.test.d.ts +0 -13
  275. package/src/__tests__/mcp-install-verify.test.d.ts.map +0 -1
  276. package/src/__tests__/mcp-install-verify.test.js +0 -177
  277. package/src/__tests__/mcp-install-verify.test.js.map +0 -1
  278. package/src/__tests__/mcp-install-verify.test.ts +0 -217
  279. package/src/__tests__/paths.test.d.ts +0 -7
  280. package/src/__tests__/project-info.test.d.ts +0 -2
  281. package/src/__tests__/rcsd-pipeline-e2e.test.d.ts +0 -14
  282. package/src/__tests__/remote.test.d.ts +0 -6
  283. package/src/__tests__/scaffold.test.d.ts +0 -6
  284. package/src/__tests__/schema-management.test.d.ts +0 -5
  285. package/src/__tests__/schema.test.d.ts +0 -2
  286. package/src/__tests__/sharing.test.d.ts +0 -6
  287. package/src/__tests__/snapshot.test.d.ts +0 -6
  288. package/src/__tests__/upgrade.test.d.ts +0 -7
  289. package/src/adapters/__tests__/discovery.test.d.ts +0 -6
  290. package/src/adapters/__tests__/manager.test.d.ts +0 -6
  291. package/src/agents/__tests__/agent-registry.test.d.ts +0 -12
  292. package/src/agents/__tests__/capacity.test.d.ts +0 -7
  293. package/src/agents/__tests__/execution-learning.test.d.ts +0 -14
  294. package/src/agents/__tests__/health-monitor.test.d.ts +0 -10
  295. package/src/agents/__tests__/registry.test.d.ts +0 -8
  296. package/src/agents/__tests__/retry.test.d.ts +0 -7
  297. package/src/compliance/__tests__/sync.test.d.ts +0 -5
  298. package/src/hooks/__tests__/provider-hooks.test.d.ts +0 -2
  299. package/src/hooks/__tests__/registry.test.d.ts +0 -2
  300. package/src/hooks/handlers/__tests__/error-hooks.test.d.ts +0 -2
  301. package/src/hooks/handlers/__tests__/file-hooks.test.d.ts +0 -2
  302. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts +0 -13
  303. package/src/hooks/handlers/__tests__/mcp-hooks.test.d.ts +0 -2
  304. package/src/hooks/handlers/__tests__/mcp-hooks.test.d.ts.map +0 -1
  305. package/src/hooks/handlers/__tests__/mcp-hooks.test.js +0 -119
  306. package/src/hooks/handlers/__tests__/mcp-hooks.test.js.map +0 -1
  307. package/src/hooks/handlers/__tests__/mcp-hooks.test.ts +0 -150
  308. package/src/hooks/handlers/__tests__/session-hooks.test.d.ts +0 -2
  309. package/src/hooks/handlers/__tests__/task-hooks.test.d.ts +0 -2
  310. package/src/hooks/handlers/mcp-hooks.ts +0 -162
  311. package/src/intelligence/__tests__/adaptive-validation.test.d.ts +0 -11
  312. package/src/intelligence/__tests__/impact.test.d.ts +0 -16
  313. package/src/intelligence/__tests__/patterns.test.d.ts +0 -8
  314. package/src/intelligence/__tests__/prediction.test.d.ts +0 -8
  315. package/src/lib/__tests__/retry.test.d.ts +0 -7
  316. package/src/lifecycle/__tests__/chain-store.test.d.ts +0 -10
  317. package/src/lifecycle/__tests__/consolidate-rcasd.test.d.ts +0 -7
  318. package/src/lifecycle/__tests__/default-chain.test.d.ts +0 -7
  319. package/src/lifecycle/__tests__/frontmatter.test.d.ts +0 -7
  320. package/src/lifecycle/__tests__/lifecycle.test.d.ts +0 -7
  321. package/src/lifecycle/__tests__/pipeline.integration.test.d.ts +0 -19
  322. package/src/lifecycle/__tests__/rcasd-paths.test.d.ts +0 -7
  323. package/src/lifecycle/__tests__/resume-schema-contract.test.d.ts +0 -16
  324. package/src/lifecycle/__tests__/stage-record-provenance.integration.test.d.ts +0 -7
  325. package/src/lifecycle/__tests__/tessera-engine.test.d.ts +0 -10
  326. package/src/mcp/index.ts +0 -163
  327. package/src/memory/__tests__/auto-extract.test.d.ts +0 -7
  328. package/src/memory/__tests__/brain-automation.test.d.ts +0 -11
  329. package/src/memory/__tests__/brain-embedding.test.d.ts +0 -2
  330. package/src/memory/__tests__/brain-links.test.d.ts +0 -8
  331. package/src/memory/__tests__/brain-migration.test.d.ts +0 -8
  332. package/src/memory/__tests__/brain-retrieval.test.d.ts +0 -10
  333. package/src/memory/__tests__/brain-search.test.d.ts +0 -8
  334. package/src/memory/__tests__/claude-mem-migration.test.d.ts +0 -12
  335. package/src/memory/__tests__/decisions.test.d.ts +0 -8
  336. package/src/memory/__tests__/engine-compat.test.d.ts +0 -12
  337. package/src/memory/__tests__/memory-bridge.test.d.ts +0 -10
  338. package/src/memory/__tests__/pipeline-manifest-sqlite.test.d.ts +0 -13
  339. package/src/memory/__tests__/session-memory.test.d.ts +0 -9
  340. package/src/metrics/__tests__/model-provider-registry.test.d.ts +0 -2
  341. package/src/metrics/__tests__/provider-detection.test.d.ts +0 -2
  342. package/src/migration/__tests__/checksum.test.d.ts +0 -8
  343. package/src/migration/__tests__/logger.test.d.ts +0 -5
  344. package/src/migration/__tests__/migration-failure.integration.test.d.ts +0 -15
  345. package/src/migration/__tests__/migration.test.d.ts +0 -13
  346. package/src/migration/__tests__/state.test.d.ts +0 -8
  347. package/src/migration/__tests__/validate.test.d.ts +0 -8
  348. package/src/nexus/__tests__/deps.test.d.ts +0 -7
  349. package/src/nexus/__tests__/nexus-e2e.test.d.ts +0 -12
  350. package/src/nexus/__tests__/permissions.test.d.ts +0 -7
  351. package/src/nexus/__tests__/query.test.d.ts +0 -7
  352. package/src/nexus/__tests__/reconcile.test.d.ts +0 -7
  353. package/src/nexus/__tests__/registry.test.d.ts +0 -7
  354. package/src/nexus/__tests__/transfer.test.d.ts +0 -8
  355. package/src/observability/__tests__/index.test.d.ts +0 -7
  356. package/src/observability/__tests__/log-filter.test.d.ts +0 -7
  357. package/src/observability/__tests__/log-parser.test.d.ts +0 -7
  358. package/src/observability/__tests__/log-reader.test.d.ts +0 -7
  359. package/src/orchestration/__tests__/autonomous-spec.test.d.ts +0 -9
  360. package/src/orchestration/__tests__/orchestration.test.d.ts +0 -7
  361. package/src/orchestration/__tests__/protocol-validators.test.d.ts +0 -9
  362. package/src/phases/__tests__/deps.test.d.ts +0 -7
  363. package/src/phases/__tests__/phases.test.d.ts +0 -7
  364. package/src/release/__tests__/artifacts.test.d.ts +0 -7
  365. package/src/release/__tests__/cancel-release.test.d.ts +0 -10
  366. package/src/release/__tests__/changelog-writer.test.d.ts +0 -6
  367. package/src/release/__tests__/push-policy.test.d.ts +0 -14
  368. package/src/release/__tests__/release.test.d.ts +0 -11
  369. package/src/sequence/__tests__/allocate.test.d.ts +0 -6
  370. package/src/sessions/__tests__/briefing-blocked.test.d.ts +0 -6
  371. package/src/sessions/__tests__/briefing.test.d.ts +0 -11
  372. package/src/sessions/__tests__/handoff-integration.test.d.ts +0 -8
  373. package/src/sessions/__tests__/handoff.test.d.ts +0 -11
  374. package/src/sessions/__tests__/index.test.d.ts +0 -2
  375. package/src/sessions/__tests__/session-cleanup.test.d.ts +0 -7
  376. package/src/sessions/__tests__/session-edge-cases.test.d.ts +0 -9
  377. package/src/sessions/__tests__/session-find.test.d.ts +0 -9
  378. package/src/sessions/__tests__/session-grade.integration.test.d.ts +0 -11
  379. package/src/sessions/__tests__/session-grade.test.d.ts +0 -6
  380. package/src/sessions/__tests__/session-memory-bridge.test.d.ts +0 -2
  381. package/src/sessions/__tests__/sessions.test.d.ts +0 -7
  382. package/src/skills/__tests__/discovery.test.d.ts +0 -6
  383. package/src/skills/__tests__/dispatch.test.d.ts +0 -6
  384. package/src/skills/__tests__/dynamic-skill-generator.test.d.ts +0 -2
  385. package/src/skills/__tests__/manifests.test.d.ts +0 -6
  386. package/src/skills/__tests__/precedence.test.d.ts +0 -6
  387. package/src/skills/__tests__/routing-table.test.d.ts +0 -2
  388. package/src/skills/__tests__/skill-paths.test.d.ts +0 -7
  389. package/src/skills/__tests__/test-utility.test.d.ts +0 -7
  390. package/src/skills/__tests__/token.test.d.ts +0 -6
  391. package/src/skills/__tests__/validation.test.d.ts +0 -6
  392. package/src/skills/__tests__/version.test.d.ts +0 -5
  393. package/src/skills/injection/__tests__/subagent.test.d.ts +0 -2
  394. package/src/skills/orchestrator/__tests__/spawn-tier.test.d.ts +0 -2
  395. package/src/spawn/__tests__/adapter-registry.test.d.ts +0 -2
  396. package/src/stats/__tests__/stats.test.d.ts +0 -7
  397. package/src/sticky/__tests__/purge.test.d.ts +0 -9
  398. package/src/store/__tests__/atomic.test.d.ts +0 -7
  399. package/src/store/__tests__/backup.test.d.ts +0 -7
  400. package/src/store/__tests__/brain-accessor-pageindex.test.d.ts +0 -12
  401. package/src/store/__tests__/brain-accessor.test.d.ts +0 -10
  402. package/src/store/__tests__/brain-pageindex.test.d.ts +0 -11
  403. package/src/store/__tests__/brain-schema.test.d.ts +0 -11
  404. package/src/store/__tests__/brain-vec.test.d.ts +0 -11
  405. package/src/store/__tests__/collision-detection.test.d.ts +0 -11
  406. package/src/store/__tests__/data-safety-central.test.d.ts +0 -20
  407. package/src/store/__tests__/db-helpers.test.d.ts +0 -7
  408. package/src/store/__tests__/e2e-safety-integration.test.d.ts +0 -13
  409. package/src/store/__tests__/git-checkpoint.test.d.ts +0 -7
  410. package/src/store/__tests__/idempotent-migration.test.d.ts +0 -5
  411. package/src/store/__tests__/import-logging.test.d.ts +0 -7
  412. package/src/store/__tests__/import-sort.test.d.ts +0 -7
  413. package/src/store/__tests__/json.test.d.ts +0 -7
  414. package/src/store/__tests__/lifecycle-schema-parity.test.d.ts +0 -2
  415. package/src/store/__tests__/migration-integration.test.d.ts +0 -15
  416. package/src/store/__tests__/migration-retry.test.d.ts +0 -10
  417. package/src/store/__tests__/migration-safety.test.d.ts +0 -21
  418. package/src/store/__tests__/migration-sqlite.test.d.ts +0 -11
  419. package/src/store/__tests__/performance-safety.test.d.ts +0 -17
  420. package/src/store/__tests__/project-detect.test.d.ts +0 -6
  421. package/src/store/__tests__/project-registry.test.d.ts +0 -7
  422. package/src/store/__tests__/provider.test.d.ts +0 -9
  423. package/src/store/__tests__/relations.test.d.ts +0 -9
  424. package/src/store/__tests__/safety-accessor.test.d.ts +0 -18
  425. package/src/store/__tests__/sequence-validation.test.d.ts +0 -11
  426. package/src/store/__tests__/session-store.test.d.ts +0 -11
  427. package/src/store/__tests__/sqlite-backup.test.d.ts +0 -14
  428. package/src/store/__tests__/sqlite.test.d.ts +0 -11
  429. package/src/store/__tests__/task-store.test.d.ts +0 -11
  430. package/src/store/__tests__/test-db-helper.d.ts +0 -61
  431. package/src/store/__tests__/write-verification.test.d.ts +0 -11
  432. package/src/system/__tests__/cleanup.test.d.ts +0 -2
  433. package/src/system/__tests__/health.test.d.ts +0 -2
  434. package/src/task-work/__tests__/start-deps.test.d.ts +0 -6
  435. package/src/tasks/__tests__/add.test.d.ts +0 -7
  436. package/src/tasks/__tests__/archive.test.d.ts +0 -7
  437. package/src/tasks/__tests__/assignee.test.d.ts +0 -14
  438. package/src/tasks/__tests__/atomicity.test.d.ts +0 -6
  439. package/src/tasks/__tests__/cancel-ops.test.d.ts +0 -7
  440. package/src/tasks/__tests__/complete-unblocks.test.d.ts +0 -6
  441. package/src/tasks/__tests__/complete.test.d.ts +0 -7
  442. package/src/tasks/__tests__/delete.test.d.ts +0 -7
  443. package/src/tasks/__tests__/dependency-check.test.d.ts +0 -7
  444. package/src/tasks/__tests__/deps-ready.test.d.ts +0 -6
  445. package/src/tasks/__tests__/epic-enforcement.test.d.ts +0 -15
  446. package/src/tasks/__tests__/find.test.d.ts +0 -7
  447. package/src/tasks/__tests__/graph-ops.test.d.ts +0 -7
  448. package/src/tasks/__tests__/hierarchy-policy.test.d.ts +0 -6
  449. package/src/tasks/__tests__/hierarchy.test.d.ts +0 -7
  450. package/src/tasks/__tests__/id-generator.test.d.ts +0 -2
  451. package/src/tasks/__tests__/labels.test.d.ts +0 -7
  452. package/src/tasks/__tests__/list.test.d.ts +0 -7
  453. package/src/tasks/__tests__/minimal-test.test.d.ts +0 -2
  454. package/src/tasks/__tests__/phase-tracking.test.d.ts +0 -7
  455. package/src/tasks/__tests__/pipeline-stage.test.d.ts +0 -14
  456. package/src/tasks/__tests__/plan-priority.test.d.ts +0 -10
  457. package/src/tasks/__tests__/priority-normalization.test.d.ts +0 -7
  458. package/src/tasks/__tests__/relates.test.d.ts +0 -9
  459. package/src/tasks/__tests__/show-deps.test.d.ts +0 -6
  460. package/src/tasks/__tests__/show.test.d.ts +0 -7
  461. package/src/tasks/__tests__/staleness.test.d.ts +0 -7
  462. package/src/tasks/__tests__/task-ops-depends.test.d.ts +0 -6
  463. package/src/tasks/__tests__/update.test.d.ts +0 -7
  464. package/src/validation/__tests__/chain-validation.test.d.ts +0 -7
  465. package/src/validation/__tests__/compliance.test.d.ts +0 -7
  466. package/src/validation/__tests__/docs-sync.test.d.ts +0 -7
  467. package/src/validation/__tests__/doctor-gitignore.test.d.ts +0 -7
  468. package/src/validation/__tests__/doctor-injection.test.d.ts +0 -11
  469. package/src/validation/__tests__/doctor.test.d.ts +0 -7
  470. package/src/validation/__tests__/engine.test.d.ts +0 -7
  471. package/src/validation/__tests__/manifest.test.d.ts +0 -7
  472. package/src/validation/__tests__/protocol-common.test.d.ts +0 -7
  473. package/src/validation/__tests__/verification.test.d.ts +0 -7
@@ -1,85 +1,194 @@
1
1
  /**
2
- * Agent Registry Accessor — CRUD operations for agent credentials in SQLite.
2
+ * Agent Registry Accessor — CRUD operations for agent data in signaldock.db.
3
+ *
4
+ * signaldock.db is the SSoT for ALL agent data: identity, credentials,
5
+ * capabilities, skills, transport config. No agent data lives in tasks.db.
3
6
  *
4
- * Implements the `AgentRegistryAPI` contract from `@cleocode/contracts`.
5
7
  * API keys are encrypted at rest using the crypto/credentials module.
6
8
  *
7
- * @see docs/specs/SIGNALDOCK-UNIFIED-AGENT-REGISTRY.md Section 3
8
- * @task T175
9
+ * @see docs/specs/DATABASE-ARCHITECTURE.md
10
+ * @task T234
9
11
  */
10
12
 
13
+ import { createRequire } from 'node:module';
14
+ import type { DatabaseSync } from 'node:sqlite';
11
15
  import type {
12
16
  AgentCredential,
13
17
  AgentListFilter,
14
18
  AgentRegistryAPI,
15
19
  TransportConfig,
16
20
  } from '@cleocode/contracts';
17
- import { desc, eq } from 'drizzle-orm';
18
- import type { NodeSQLiteDatabase } from 'drizzle-orm/node-sqlite';
19
- import { createInsertSchema, createSelectSchema } from 'drizzle-orm/zod';
20
21
  import { decrypt, encrypt } from '../crypto/credentials.js';
21
- import * as schema from './tasks-schema.js';
22
-
23
- const { agentCredentials } = schema;
22
+ import { ensureSignaldockDb, getSignaldockDbPath } from './signaldock-sqlite.js';
24
23
 
25
- /** Typed database instance — preserves end-to-end type safety with the full schema. */
26
- type TypedDb = NodeSQLiteDatabase<typeof schema>;
24
+ const _require = createRequire(import.meta.url);
25
+ const { DatabaseSync: DatabaseSyncClass } = _require('node:sqlite') as {
26
+ DatabaseSync: new (...args: ConstructorParameters<typeof DatabaseSync>) => DatabaseSync;
27
+ };
27
28
 
28
- /** Zod validation schemas for agent credentials (drizzle-orm/zod). */
29
- export const agentCredentialInsertSchema = createInsertSchema(agentCredentials);
30
- export const agentCredentialSelectSchema = createSelectSchema(agentCredentials);
29
+ /** Raw row shape from signaldock.db agents table. */
30
+ interface AgentDbRow {
31
+ id: string;
32
+ agent_id: string;
33
+ name: string;
34
+ description: string | null;
35
+ class: string;
36
+ privacy_tier: string;
37
+ capabilities: string;
38
+ skills: string;
39
+ transport_type: string;
40
+ api_key_encrypted: string | null;
41
+ api_base_url: string;
42
+ classification: string | null;
43
+ transport_config: string;
44
+ is_active: number;
45
+ last_used_at: number | null;
46
+ created_at: number;
47
+ updated_at: number;
48
+ }
31
49
 
32
- /** Convert a database row to an AgentCredential, decrypting the API key. */
33
- async function rowToCredential(
34
- row: typeof agentCredentials.$inferSelect,
35
- projectPath: string,
36
- ): Promise<AgentCredential> {
37
- const apiKey = await decrypt(row.apiKeyEncrypted, projectPath);
50
+ /** Convert a signaldock.db row to an AgentCredential, decrypting the API key. */
51
+ async function rowToCredential(row: AgentDbRow, projectPath: string): Promise<AgentCredential> {
52
+ const apiKey = row.api_key_encrypted ? await decrypt(row.api_key_encrypted, projectPath) : '';
38
53
  return {
39
- agentId: row.agentId,
40
- displayName: row.displayName,
54
+ agentId: row.agent_id,
55
+ displayName: row.name,
41
56
  apiKey,
42
- apiBaseUrl: row.apiBaseUrl,
57
+ apiBaseUrl: row.api_base_url,
43
58
  classification: row.classification ?? undefined,
44
- privacyTier: row.privacyTier as AgentCredential['privacyTier'],
59
+ privacyTier: row.privacy_tier as AgentCredential['privacyTier'],
45
60
  capabilities: JSON.parse(row.capabilities) as string[],
46
61
  skills: JSON.parse(row.skills) as string[],
47
- transportConfig: JSON.parse(row.transportConfig) as TransportConfig,
48
- isActive: row.isActive,
49
- lastUsedAt: row.lastUsedAt ? new Date(row.lastUsedAt).toISOString() : undefined,
50
- createdAt: new Date(row.createdAt).toISOString(),
51
- updatedAt: new Date(row.updatedAt).toISOString(),
62
+ transportType: (row.transport_type ?? 'http') as AgentCredential['transportType'],
63
+ transportConfig: JSON.parse(row.transport_config) as TransportConfig,
64
+ isActive: row.is_active === 1,
65
+ lastUsedAt: row.last_used_at ? new Date(row.last_used_at * 1000).toISOString() : undefined,
66
+ createdAt: new Date(row.created_at * 1000).toISOString(),
67
+ updatedAt: new Date(row.updated_at * 1000).toISOString(),
52
68
  };
53
69
  }
54
70
 
55
- /** SQLite implementation of the AgentRegistryAPI. */
71
+ /** Open signaldock.db for read/write operations. Caller must close. */
72
+ function openDb(projectPath: string): DatabaseSync {
73
+ const dbPath = getSignaldockDbPath(projectPath);
74
+ const db = new DatabaseSyncClass(dbPath);
75
+ db.exec('PRAGMA foreign_keys = ON');
76
+ db.exec('PRAGMA journal_mode = WAL');
77
+ return db;
78
+ }
79
+
80
+ /**
81
+ * Sync capabilities/skills to junction tables in signaldock.db.
82
+ * Junction tables are the SSoT — JSON columns are materialized cache.
83
+ */
84
+ function syncJunctionTables(
85
+ db: DatabaseSync,
86
+ agentUuid: string,
87
+ capabilities: string[],
88
+ skills: string[],
89
+ ): void {
90
+ db.prepare('DELETE FROM agent_capabilities WHERE agent_id = ?').run(agentUuid);
91
+ db.prepare('DELETE FROM agent_skills WHERE agent_id = ?').run(agentUuid);
92
+ for (const cap of capabilities) {
93
+ const capRow = db.prepare('SELECT id FROM capabilities WHERE slug = ?').get(cap) as
94
+ | { id: string }
95
+ | undefined;
96
+ if (capRow) {
97
+ db.prepare(
98
+ 'INSERT OR IGNORE INTO agent_capabilities (agent_id, capability_id) VALUES (?, ?)',
99
+ ).run(agentUuid, capRow.id);
100
+ }
101
+ }
102
+ for (const skill of skills) {
103
+ const skillRow = db.prepare('SELECT id FROM skills WHERE slug = ?').get(skill) as
104
+ | { id: string }
105
+ | undefined;
106
+ if (skillRow) {
107
+ db.prepare('INSERT OR IGNORE INTO agent_skills (agent_id, skill_id) VALUES (?, ?)').run(
108
+ agentUuid,
109
+ skillRow.id,
110
+ );
111
+ }
112
+ }
113
+ }
114
+
115
+ /** signaldock.db implementation of the AgentRegistryAPI. */
56
116
  export class AgentRegistryAccessor implements AgentRegistryAPI {
57
- constructor(
58
- private db: TypedDb,
59
- private projectPath: string,
60
- ) {}
117
+ constructor(private projectPath: string) {}
118
+
119
+ /** Ensure signaldock.db exists with full schema before any operation. */
120
+ private async ensureDb(): Promise<void> {
121
+ await ensureSignaldockDb(this.projectPath);
122
+ }
61
123
 
62
124
  async register(
63
125
  credential: Omit<AgentCredential, 'createdAt' | 'updatedAt'>,
64
126
  ): Promise<AgentCredential> {
65
- const now = Date.now();
66
- const apiKeyEncrypted = await encrypt(credential.apiKey, this.projectPath);
67
-
68
- await this.db.insert(agentCredentials).values({
69
- agentId: credential.agentId,
70
- displayName: credential.displayName,
71
- apiKeyEncrypted,
72
- apiBaseUrl: credential.apiBaseUrl,
73
- classification: credential.classification ?? null,
74
- privacyTier: credential.privacyTier,
75
- capabilities: JSON.stringify(credential.capabilities),
76
- skills: JSON.stringify(credential.skills),
77
- transportConfig: JSON.stringify(credential.transportConfig),
78
- isActive: credential.isActive,
79
- lastUsedAt: credential.lastUsedAt ? new Date(credential.lastUsedAt).getTime() : null,
80
- createdAt: now,
81
- updatedAt: now,
82
- });
127
+ await this.ensureDb();
128
+ const nowTs = Math.floor(Date.now() / 1000);
129
+ const apiKeyEncrypted = credential.apiKey
130
+ ? await encrypt(credential.apiKey, this.projectPath)
131
+ : null;
132
+
133
+ const db = openDb(this.projectPath);
134
+ try {
135
+ const existing = db
136
+ .prepare('SELECT id FROM agents WHERE agent_id = ?')
137
+ .get(credential.agentId) as { id: string } | undefined;
138
+
139
+ if (!existing) {
140
+ const id = crypto.randomUUID();
141
+ db.prepare(
142
+ `INSERT INTO agents (id, agent_id, name, class, privacy_tier, capabilities, skills,
143
+ transport_type, api_key_encrypted, api_base_url, classification, transport_config,
144
+ is_active, last_used_at, status, created_at, updated_at)
145
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'online', ?, ?)`,
146
+ ).run(
147
+ id,
148
+ credential.agentId,
149
+ credential.displayName,
150
+ credential.classification ?? 'custom',
151
+ credential.privacyTier,
152
+ JSON.stringify(credential.capabilities),
153
+ JSON.stringify(credential.skills),
154
+ credential.transportType ?? 'http',
155
+ apiKeyEncrypted,
156
+ credential.apiBaseUrl,
157
+ credential.classification ?? null,
158
+ JSON.stringify(credential.transportConfig),
159
+ credential.isActive ? 1 : 0,
160
+ credential.lastUsedAt
161
+ ? Math.floor(new Date(credential.lastUsedAt).getTime() / 1000)
162
+ : null,
163
+ nowTs,
164
+ nowTs,
165
+ );
166
+ syncJunctionTables(db, id, credential.capabilities, credential.skills);
167
+ } else {
168
+ db.prepare(
169
+ `UPDATE agents SET name = ?, class = ?, privacy_tier = ?, capabilities = ?, skills = ?,
170
+ transport_type = ?, api_key_encrypted = ?, api_base_url = ?, classification = ?,
171
+ transport_config = ?, is_active = ?, updated_at = ? WHERE agent_id = ?`,
172
+ ).run(
173
+ credential.displayName,
174
+ credential.classification ?? 'custom',
175
+ credential.privacyTier,
176
+ JSON.stringify(credential.capabilities),
177
+ JSON.stringify(credential.skills),
178
+ credential.transportType ?? 'http',
179
+ apiKeyEncrypted,
180
+ credential.apiBaseUrl,
181
+ credential.classification ?? null,
182
+ JSON.stringify(credential.transportConfig),
183
+ credential.isActive ? 1 : 0,
184
+ nowTs,
185
+ credential.agentId,
186
+ );
187
+ syncJunctionTables(db, existing.id, credential.capabilities, credential.skills);
188
+ }
189
+ } finally {
190
+ db.close();
191
+ }
83
192
 
84
193
  const result = await this.get(credential.agentId);
85
194
  if (!result) throw new Error(`Failed to register agent: ${credential.agentId}`);
@@ -87,54 +196,110 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
87
196
  }
88
197
 
89
198
  async get(agentId: string): Promise<AgentCredential | null> {
90
- const rows = await this.db
91
- .select()
92
- .from(agentCredentials)
93
- .where(eq(agentCredentials.agentId, agentId));
94
-
95
- if (rows.length === 0) return null;
96
- return rowToCredential(rows[0]!, this.projectPath);
199
+ await this.ensureDb();
200
+ const db = openDb(this.projectPath);
201
+ try {
202
+ const row = db.prepare('SELECT * FROM agents WHERE agent_id = ?').get(agentId) as
203
+ | AgentDbRow
204
+ | undefined;
205
+ if (!row) return null;
206
+ return rowToCredential(row, this.projectPath);
207
+ } finally {
208
+ db.close();
209
+ }
97
210
  }
98
211
 
99
212
  async list(filter?: AgentListFilter): Promise<AgentCredential[]> {
100
- const query =
101
- filter?.active !== undefined
102
- ? this.db
103
- .select()
104
- .from(agentCredentials)
105
- .where(eq(agentCredentials.isActive, filter.active))
106
- : this.db.select().from(agentCredentials);
107
-
108
- const rows = await query;
109
- return Promise.all(rows.map((row) => rowToCredential(row, this.projectPath)));
213
+ await this.ensureDb();
214
+ const db = openDb(this.projectPath);
215
+ try {
216
+ const rows =
217
+ filter?.active !== undefined
218
+ ? (db
219
+ .prepare('SELECT * FROM agents WHERE is_active = ?')
220
+ .all(filter.active ? 1 : 0) as unknown as AgentDbRow[])
221
+ : (db.prepare('SELECT * FROM agents').all() as unknown as AgentDbRow[]);
222
+ return Promise.all(rows.map((row) => rowToCredential(row, this.projectPath)));
223
+ } finally {
224
+ db.close();
225
+ }
110
226
  }
111
227
 
112
228
  async update(
113
229
  agentId: string,
114
230
  updates: Partial<Omit<AgentCredential, 'agentId' | 'createdAt'>>,
115
231
  ): Promise<AgentCredential> {
116
- // C2 fix: pre-flight check — fail fast if agent doesn't exist
117
232
  const existing = await this.get(agentId);
118
233
  if (!existing) throw new Error(`Agent not found: ${agentId}`);
119
234
 
120
- const now = Date.now();
121
- const values: Record<string, unknown> = { updatedAt: now };
122
-
123
- if (updates.displayName !== undefined) values['displayName'] = updates.displayName;
124
- if (updates.apiBaseUrl !== undefined) values['apiBaseUrl'] = updates.apiBaseUrl;
125
- if (updates.classification !== undefined) values['classification'] = updates.classification;
126
- if (updates.privacyTier !== undefined) values['privacyTier'] = updates.privacyTier;
127
- if (updates.capabilities !== undefined)
128
- values['capabilities'] = JSON.stringify(updates.capabilities);
129
- if (updates.skills !== undefined) values['skills'] = JSON.stringify(updates.skills);
130
- if (updates.transportConfig !== undefined)
131
- values['transportConfig'] = JSON.stringify(updates.transportConfig);
132
- if (updates.isActive !== undefined) values['isActive'] = updates.isActive;
133
- if (updates.apiKey !== undefined) {
134
- values['apiKeyEncrypted'] = await encrypt(updates.apiKey, this.projectPath);
135
- }
235
+ const nowTs = Math.floor(Date.now() / 1000);
236
+ const db = openDb(this.projectPath);
237
+ try {
238
+ const sets: string[] = ['updated_at = ?'];
239
+ const params: unknown[] = [nowTs];
136
240
 
137
- await this.db.update(agentCredentials).set(values).where(eq(agentCredentials.agentId, agentId));
241
+ if (updates.displayName !== undefined) {
242
+ sets.push('name = ?');
243
+ params.push(updates.displayName);
244
+ }
245
+ if (updates.apiBaseUrl !== undefined) {
246
+ sets.push('api_base_url = ?');
247
+ params.push(updates.apiBaseUrl);
248
+ }
249
+ if (updates.classification !== undefined) {
250
+ sets.push('classification = ?');
251
+ params.push(updates.classification);
252
+ }
253
+ if (updates.privacyTier !== undefined) {
254
+ sets.push('privacy_tier = ?');
255
+ params.push(updates.privacyTier);
256
+ }
257
+ if (updates.capabilities !== undefined) {
258
+ sets.push('capabilities = ?');
259
+ params.push(JSON.stringify(updates.capabilities));
260
+ }
261
+ if (updates.skills !== undefined) {
262
+ sets.push('skills = ?');
263
+ params.push(JSON.stringify(updates.skills));
264
+ }
265
+ if (updates.transportType !== undefined) {
266
+ sets.push('transport_type = ?');
267
+ params.push(updates.transportType);
268
+ }
269
+ if (updates.transportConfig !== undefined) {
270
+ sets.push('transport_config = ?');
271
+ params.push(JSON.stringify(updates.transportConfig));
272
+ }
273
+ if (updates.isActive !== undefined) {
274
+ sets.push('is_active = ?');
275
+ params.push(updates.isActive ? 1 : 0);
276
+ }
277
+ if (updates.apiKey !== undefined) {
278
+ const encrypted = await encrypt(updates.apiKey, this.projectPath);
279
+ sets.push('api_key_encrypted = ?');
280
+ params.push(encrypted);
281
+ }
282
+
283
+ params.push(agentId);
284
+ db.prepare(`UPDATE agents SET ${sets.join(', ')} WHERE agent_id = ?`).run(
285
+ ...(params as Array<string | number | null>),
286
+ );
287
+
288
+ // Sync junction tables if capabilities or skills changed
289
+ if (updates.capabilities !== undefined || updates.skills !== undefined) {
290
+ const agentRow = db.prepare('SELECT id FROM agents WHERE agent_id = ?').get(agentId) as {
291
+ id: string;
292
+ };
293
+ syncJunctionTables(
294
+ db,
295
+ agentRow.id,
296
+ updates.capabilities ?? existing.capabilities,
297
+ updates.skills ?? existing.skills,
298
+ );
299
+ }
300
+ } finally {
301
+ db.close();
302
+ }
138
303
 
139
304
  const result = await this.get(agentId);
140
305
  if (!result) throw new Error(`Agent not found after update: ${agentId}`);
@@ -142,18 +307,21 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
142
307
  }
143
308
 
144
309
  async remove(agentId: string): Promise<void> {
145
- // H2 fix: pre-flight check — throw if agent doesn't exist
146
310
  const existing = await this.get(agentId);
147
311
  if (!existing) throw new Error(`Agent not found: ${agentId}`);
148
312
 
149
- await this.db.delete(agentCredentials).where(eq(agentCredentials.agentId, agentId));
313
+ const db = openDb(this.projectPath);
314
+ try {
315
+ db.prepare('DELETE FROM agents WHERE agent_id = ?').run(agentId);
316
+ } finally {
317
+ db.close();
318
+ }
150
319
  }
151
320
 
152
321
  async rotateKey(agentId: string): Promise<{ agentId: string; newApiKey: string }> {
153
322
  const credential = await this.get(agentId);
154
323
  if (!credential) throw new Error(`Agent not found: ${agentId}`);
155
324
 
156
- // Call cloud API to rotate key
157
325
  const response = await fetch(`${credential.apiBaseUrl}/agents/${agentId}/rotate-key`, {
158
326
  method: 'POST',
159
327
  headers: {
@@ -170,30 +338,38 @@ export class AgentRegistryAccessor implements AgentRegistryAPI {
170
338
  const newApiKey = data.data?.apiKey;
171
339
  if (!newApiKey) throw new Error('Cloud API did not return a new API key');
172
340
 
173
- // Re-encrypt and store locally
174
341
  await this.update(agentId, { apiKey: newApiKey });
175
-
176
- // C1 fix: return only agentId, not plaintext key — callers use get() to retrieve
177
342
  return { agentId, newApiKey: `${newApiKey.substring(0, 8)}...rotated` };
178
343
  }
179
344
 
180
345
  async getActive(): Promise<AgentCredential | null> {
181
- // H3 fix: secondary orderBy(createdAt desc) for deterministic tie-breaking
182
- const rows = await this.db
183
- .select()
184
- .from(agentCredentials)
185
- .where(eq(agentCredentials.isActive, true))
186
- .orderBy(desc(agentCredentials.lastUsedAt), desc(agentCredentials.createdAt))
187
- .limit(1);
188
-
189
- if (rows.length === 0) return null;
190
- return rowToCredential(rows[0]!, this.projectPath);
346
+ await this.ensureDb();
347
+ const db = openDb(this.projectPath);
348
+ try {
349
+ const row = db
350
+ .prepare(
351
+ 'SELECT * FROM agents WHERE is_active = 1 ORDER BY last_used_at DESC, created_at DESC LIMIT 1',
352
+ )
353
+ .get() as AgentDbRow | undefined;
354
+ if (!row) return null;
355
+ return rowToCredential(row, this.projectPath);
356
+ } finally {
357
+ db.close();
358
+ }
191
359
  }
192
360
 
193
361
  async markUsed(agentId: string): Promise<void> {
194
- await this.db
195
- .update(agentCredentials)
196
- .set({ lastUsedAt: Date.now(), updatedAt: Date.now() })
197
- .where(eq(agentCredentials.agentId, agentId));
362
+ await this.ensureDb();
363
+ const nowTs = Math.floor(Date.now() / 1000);
364
+ const db = openDb(this.projectPath);
365
+ try {
366
+ db.prepare('UPDATE agents SET last_used_at = ?, updated_at = ? WHERE agent_id = ?').run(
367
+ nowTs,
368
+ nowTs,
369
+ agentId,
370
+ );
371
+ } finally {
372
+ db.close();
373
+ }
198
374
  }
199
375
  }
@@ -11,7 +11,7 @@
11
11
  * @epic T029
12
12
  */
13
13
 
14
- import { eq, or } from 'drizzle-orm';
14
+ import { and, eq, isNotNull, or } from 'drizzle-orm';
15
15
  import * as brainSchema from './brain-schema.js';
16
16
  import { getBrainDb } from './brain-sqlite.js';
17
17
 
@@ -177,6 +177,142 @@ export async function taskExistsInTasksDb(
177
177
  * if (await sessionExistsInTasksDb('ses_abc', db)) { /* safe to reference *\/ }
178
178
  * ```
179
179
  */
180
+ /**
181
+ * Reconcile orphaned cross-DB references in brain.db.
182
+ *
183
+ * Scans brain.db for references to tasks/sessions that no longer exist in
184
+ * tasks.db and cleans them up:
185
+ * - brain_decisions with stale context_task_id or context_epic_id → nullify
186
+ * - brain_observations with stale source_session_id → nullify
187
+ * - brain_memory_links with stale task_id → delete row
188
+ *
189
+ * This is the background reconciliation pass mentioned in the module doc.
190
+ * Safe to run at any frequency — idempotent.
191
+ *
192
+ * @param cwd - Optional working directory
193
+ * @returns Counts of orphaned references cleaned up
194
+ */
195
+ export async function reconcileOrphanedRefs(cwd?: string): Promise<{
196
+ decisionsFixed: number;
197
+ observationsFixed: number;
198
+ linksRemoved: number;
199
+ }> {
200
+ let brainDb: Awaited<ReturnType<typeof getBrainDb>> | null = null;
201
+ const result = { decisionsFixed: 0, observationsFixed: 0, linksRemoved: 0 };
202
+
203
+ try {
204
+ brainDb = await getBrainDb(cwd);
205
+ } catch {
206
+ return result;
207
+ }
208
+
209
+ const { getDb } = await import('./sqlite.js');
210
+ let tasksDb: Awaited<ReturnType<typeof getDb>>;
211
+ try {
212
+ tasksDb = await getDb(cwd);
213
+ } catch {
214
+ return result;
215
+ }
216
+
217
+ try {
218
+ // 1. Find decisions with stale context_task_id
219
+ const decisionsWithTaskRef = await brainDb
220
+ .select({
221
+ id: brainSchema.brainDecisions.id,
222
+ contextTaskId: brainSchema.brainDecisions.contextTaskId,
223
+ contextEpicId: brainSchema.brainDecisions.contextEpicId,
224
+ })
225
+ .from(brainSchema.brainDecisions)
226
+ .where(
227
+ or(
228
+ isNotNull(brainSchema.brainDecisions.contextTaskId),
229
+ isNotNull(brainSchema.brainDecisions.contextEpicId),
230
+ ),
231
+ )
232
+ .all();
233
+
234
+ for (const d of decisionsWithTaskRef) {
235
+ if (d.contextTaskId) {
236
+ const exists = await taskExistsInTasksDb(d.contextTaskId, tasksDb);
237
+ if (!exists) {
238
+ await brainDb
239
+ .update(brainSchema.brainDecisions)
240
+ .set({ contextTaskId: null })
241
+ .where(eq(brainSchema.brainDecisions.id, d.id));
242
+ result.decisionsFixed++;
243
+ }
244
+ }
245
+ if (d.contextEpicId) {
246
+ const exists = await taskExistsInTasksDb(d.contextEpicId, tasksDb);
247
+ if (!exists) {
248
+ await brainDb
249
+ .update(brainSchema.brainDecisions)
250
+ .set({ contextEpicId: null })
251
+ .where(eq(brainSchema.brainDecisions.id, d.id));
252
+ result.decisionsFixed++;
253
+ }
254
+ }
255
+ }
256
+
257
+ // 2. Find observations with stale source_session_id
258
+ const obsWithSessionRef = await brainDb
259
+ .select({
260
+ id: brainSchema.brainObservations.id,
261
+ sourceSessionId: brainSchema.brainObservations.sourceSessionId,
262
+ })
263
+ .from(brainSchema.brainObservations)
264
+ .where(isNotNull(brainSchema.brainObservations.sourceSessionId))
265
+ .all();
266
+
267
+ for (const o of obsWithSessionRef) {
268
+ {
269
+ const exists = o.sourceSessionId
270
+ ? await sessionExistsInTasksDb(o.sourceSessionId, tasksDb)
271
+ : false;
272
+ if (!exists) {
273
+ await brainDb
274
+ .update(brainSchema.brainObservations)
275
+ .set({ sourceSessionId: null })
276
+ .where(eq(brainSchema.brainObservations.id, o.id));
277
+ result.observationsFixed++;
278
+ }
279
+ }
280
+ }
281
+
282
+ // 3. Find memory links with stale task_id
283
+ const allLinks = await brainDb
284
+ .select({
285
+ memoryType: brainSchema.brainMemoryLinks.memoryType,
286
+ memoryId: brainSchema.brainMemoryLinks.memoryId,
287
+ taskId: brainSchema.brainMemoryLinks.taskId,
288
+ linkType: brainSchema.brainMemoryLinks.linkType,
289
+ })
290
+ .from(brainSchema.brainMemoryLinks)
291
+ .all();
292
+
293
+ for (const link of allLinks) {
294
+ const exists = await taskExistsInTasksDb(link.taskId, tasksDb);
295
+ if (!exists) {
296
+ await brainDb
297
+ .delete(brainSchema.brainMemoryLinks)
298
+ .where(
299
+ and(
300
+ eq(brainSchema.brainMemoryLinks.memoryType, link.memoryType),
301
+ eq(brainSchema.brainMemoryLinks.memoryId, link.memoryId),
302
+ eq(brainSchema.brainMemoryLinks.taskId, link.taskId),
303
+ eq(brainSchema.brainMemoryLinks.linkType, link.linkType),
304
+ ),
305
+ );
306
+ result.linksRemoved++;
307
+ }
308
+ }
309
+ } catch {
310
+ // Non-fatal best-effort reconciliation
311
+ }
312
+
313
+ return result;
314
+ }
315
+
180
316
  export async function sessionExistsInTasksDb(
181
317
  sessionId: string,
182
318
  tasksDb: Awaited<ReturnType<typeof import('./sqlite.js').getDb>>,
@@ -190,3 +326,41 @@ export async function sessionExistsInTasksDb(
190
326
  .all();
191
327
  return result.length > 0;
192
328
  }
329
+
330
+ /**
331
+ * Verify an agent exists in signaldock.db before creating cross-DB references.
332
+ * Returns true if the agent_id exists in signaldock.db agents table.
333
+ *
334
+ * Provides write-guard for agent_instances and agent_error_log in tasks.db
335
+ * that reference agents whose identity lives in signaldock.db.
336
+ *
337
+ * @param agentId - Agent slug (e.g. 'cleo-db-lead') to verify
338
+ * @param cwd - Optional working directory
339
+ * @returns True if the agent exists in signaldock.db
340
+ *
341
+ * @task T238
342
+ */
343
+ export async function agentExistsInSignaldockDb(agentId: string, cwd?: string): Promise<boolean> {
344
+ try {
345
+ const { getSignaldockDbPath } = await import('./signaldock-sqlite.js');
346
+ const { existsSync } = await import('node:fs');
347
+ const dbPath = getSignaldockDbPath(cwd);
348
+ if (!existsSync(dbPath)) return false;
349
+
350
+ const { createRequire } = await import('node:module');
351
+ const _require = createRequire(import.meta.url);
352
+ const { DatabaseSync } = _require('node:sqlite') as typeof import('node:sqlite');
353
+ const db = new DatabaseSync(dbPath);
354
+ try {
355
+ const row = db.prepare('SELECT id FROM agents WHERE agent_id = ?').get(agentId) as
356
+ | { id: string }
357
+ | undefined;
358
+ return !!row;
359
+ } finally {
360
+ db.close();
361
+ }
362
+ } catch {
363
+ // signaldock.db may not exist yet — non-fatal
364
+ return false;
365
+ }
366
+ }
@@ -2,7 +2,7 @@
2
2
  * Store provider abstraction layer.
3
3
  *
4
4
  * Defines the StoreProvider interface backed by SQLite (ADR-006).
5
- * CLI and MCP engine use StoreProvider for all data access.
5
+ * CLI and dispatch engine use StoreProvider for all data access.
6
6
  *
7
7
  * @epic T4454
8
8
  * @task W1-T6
@@ -104,7 +104,7 @@ export interface StoreProvider {
104
104
 
105
105
  // ---- High-level domain operations ----
106
106
  // These wrap core business logic (validation, ID generation, logging, etc.)
107
- // and are the primary API for CLI commands and MCP engine.
107
+ // and are the primary API for CLI commands and dispatch engine.
108
108
  // @task T4656
109
109
  // @epic T4654
110
110