@cleocode/core 2026.3.74 → 2026.4.0

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 (428) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/agent-schema.d.ts.map +1 -1
  3. package/dist/agents/retry.js +26 -21
  4. package/dist/agents/retry.js.map +1 -1
  5. package/dist/cant/approval.d.ts +110 -0
  6. package/dist/cant/approval.d.ts.map +1 -0
  7. package/dist/cant/approval.js +185 -0
  8. package/dist/cant/approval.js.map +1 -0
  9. package/dist/cant/context-builder.d.ts +79 -0
  10. package/dist/cant/context-builder.d.ts.map +1 -0
  11. package/dist/cant/context-builder.js +117 -0
  12. package/dist/cant/context-builder.js.map +1 -0
  13. package/dist/cant/discretion.d.ts +95 -0
  14. package/dist/cant/discretion.d.ts.map +1 -0
  15. package/dist/cant/discretion.js +116 -0
  16. package/dist/cant/discretion.js.map +1 -0
  17. package/dist/cant/index.d.ts +25 -0
  18. package/dist/cant/index.d.ts.map +1 -0
  19. package/dist/cant/index.js +23 -0
  20. package/dist/cant/index.js.map +1 -0
  21. package/dist/cant/parallel-runner.d.ts +38 -0
  22. package/dist/cant/parallel-runner.d.ts.map +1 -0
  23. package/dist/cant/parallel-runner.js +173 -0
  24. package/dist/cant/parallel-runner.js.map +1 -0
  25. package/dist/cant/types.d.ts +127 -0
  26. package/dist/cant/types.d.ts.map +1 -0
  27. package/dist/cant/types.js +11 -0
  28. package/dist/cant/types.js.map +1 -0
  29. package/dist/cant/workflow-executor.d.ts +105 -0
  30. package/dist/cant/workflow-executor.d.ts.map +1 -0
  31. package/dist/cant/workflow-executor.js +440 -0
  32. package/dist/cant/workflow-executor.js.map +1 -0
  33. package/dist/cleo.js +21 -1
  34. package/dist/cleo.js.map +1 -1
  35. package/dist/code/index.d.ts +10 -0
  36. package/dist/code/index.d.ts.map +1 -0
  37. package/dist/code/outline.d.ts +51 -0
  38. package/dist/code/outline.d.ts.map +1 -0
  39. package/dist/code/parser.d.ts +30 -0
  40. package/dist/code/parser.d.ts.map +1 -0
  41. package/dist/code/search.d.ts +42 -0
  42. package/dist/code/search.d.ts.map +1 -0
  43. package/dist/code/unfold.d.ts +44 -0
  44. package/dist/code/unfold.d.ts.map +1 -0
  45. package/dist/conduit/conduit-client.d.ts +35 -0
  46. package/dist/conduit/conduit-client.d.ts.map +1 -0
  47. package/dist/conduit/conduit-client.js +94 -0
  48. package/dist/conduit/conduit-client.js.map +1 -0
  49. package/dist/conduit/factory.d.ts +15 -0
  50. package/dist/conduit/factory.d.ts.map +1 -0
  51. package/dist/conduit/factory.js +35 -0
  52. package/dist/conduit/factory.js.map +1 -0
  53. package/dist/conduit/http-transport.d.ts +44 -0
  54. package/dist/conduit/http-transport.d.ts.map +1 -0
  55. package/dist/conduit/http-transport.js +165 -0
  56. package/dist/conduit/http-transport.js.map +1 -0
  57. package/dist/conduit/index.d.ts +15 -0
  58. package/dist/conduit/index.d.ts.map +1 -0
  59. package/dist/conduit/index.js +12 -0
  60. package/dist/conduit/index.js.map +1 -0
  61. package/dist/conduit/local-transport.d.ts +91 -0
  62. package/dist/conduit/local-transport.d.ts.map +1 -0
  63. package/dist/conduit/sse-transport.d.ts +68 -0
  64. package/dist/conduit/sse-transport.d.ts.map +1 -0
  65. package/dist/config.js +4 -3
  66. package/dist/config.js.map +1 -1
  67. package/dist/crypto/credentials.d.ts +40 -0
  68. package/dist/crypto/credentials.d.ts.map +1 -0
  69. package/dist/crypto/credentials.js +144 -0
  70. package/dist/crypto/credentials.js.map +1 -0
  71. package/dist/engine-result.d.ts +1 -1
  72. package/dist/engine-result.d.ts.map +1 -1
  73. package/dist/error-catalog.d.ts +1 -1
  74. package/dist/error-catalog.d.ts.map +1 -1
  75. package/dist/error-registry.d.ts +1 -1
  76. package/dist/error-registry.d.ts.map +1 -1
  77. package/dist/errors.d.ts +1 -1
  78. package/dist/errors.d.ts.map +1 -1
  79. package/dist/hooks/handlers/agent-hooks.d.ts.map +1 -1
  80. package/dist/hooks/handlers/agent-hooks.js +106 -0
  81. package/dist/hooks/handlers/agent-hooks.js.map +1 -0
  82. package/dist/hooks/handlers/context-hooks.d.ts.map +1 -1
  83. package/dist/hooks/handlers/context-hooks.js +111 -0
  84. package/dist/hooks/handlers/context-hooks.js.map +1 -0
  85. package/dist/hooks/handlers/error-hooks.d.ts +14 -5
  86. package/dist/hooks/handlers/error-hooks.d.ts.map +1 -1
  87. package/dist/hooks/handlers/error-hooks.js +15 -6
  88. package/dist/hooks/handlers/error-hooks.js.map +1 -1
  89. package/dist/hooks/handlers/file-hooks.d.ts.map +1 -1
  90. package/dist/hooks/handlers/file-hooks.js +35 -11
  91. package/dist/hooks/handlers/file-hooks.js.map +1 -1
  92. package/dist/hooks/handlers/handler-helpers.d.ts +41 -0
  93. package/dist/hooks/handlers/handler-helpers.d.ts.map +1 -0
  94. package/dist/hooks/handlers/handler-helpers.js +61 -0
  95. package/dist/hooks/handlers/handler-helpers.js.map +1 -0
  96. package/dist/hooks/handlers/index.js +10 -1
  97. package/dist/hooks/handlers/index.js.map +1 -1
  98. package/dist/hooks/handlers/mcp-hooks.d.ts.map +1 -1
  99. package/dist/hooks/handlers/mcp-hooks.js +88 -21
  100. package/dist/hooks/handlers/mcp-hooks.js.map +1 -1
  101. package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
  102. package/dist/hooks/handlers/session-hooks.js +5 -10
  103. package/dist/hooks/handlers/session-hooks.js.map +1 -1
  104. package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
  105. package/dist/hooks/handlers/task-hooks.js +5 -10
  106. package/dist/hooks/handlers/task-hooks.js.map +1 -1
  107. package/dist/hooks/handlers/work-capture-hooks.d.ts.map +1 -1
  108. package/dist/hooks/handlers/work-capture-hooks.js +165 -0
  109. package/dist/hooks/handlers/work-capture-hooks.js.map +1 -0
  110. package/dist/hooks/payload-schemas.js +83 -26
  111. package/dist/hooks/payload-schemas.js.map +1 -1
  112. package/dist/hooks/provider-hooks.js +37 -5
  113. package/dist/hooks/provider-hooks.js.map +1 -1
  114. package/dist/hooks/registry.js +76 -23
  115. package/dist/hooks/registry.js.map +1 -1
  116. package/dist/hooks/types.js +17 -13
  117. package/dist/hooks/types.js.map +1 -1
  118. package/dist/index.d.ts +4 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +6452 -3371
  121. package/dist/index.js.map +4 -4
  122. package/dist/init.d.ts.map +1 -1
  123. package/dist/init.js +12 -0
  124. package/dist/init.js.map +1 -1
  125. package/dist/internal.d.ts +11 -1
  126. package/dist/internal.d.ts.map +1 -1
  127. package/dist/internal.js +10 -0
  128. package/dist/internal.js.map +1 -1
  129. package/dist/lib/index.d.ts +1 -0
  130. package/dist/lib/index.d.ts.map +1 -1
  131. package/dist/lib/tree-sitter-languages.d.ts +29 -0
  132. package/dist/lib/tree-sitter-languages.d.ts.map +1 -0
  133. package/dist/memory/brain-links.d.ts.map +1 -1
  134. package/dist/memory/brain-maintenance.d.ts +13 -0
  135. package/dist/memory/brain-maintenance.d.ts.map +1 -1
  136. package/dist/memory/brain-retrieval.d.ts +3 -0
  137. package/dist/memory/brain-retrieval.d.ts.map +1 -1
  138. package/dist/memory/brain-retrieval.js +5 -0
  139. package/dist/memory/brain-retrieval.js.map +1 -1
  140. package/dist/memory/decisions.d.ts.map +1 -1
  141. package/dist/mvi-helpers.d.ts +52 -0
  142. package/dist/mvi-helpers.d.ts.map +1 -0
  143. package/dist/mvi-helpers.js +74 -0
  144. package/dist/mvi-helpers.js.map +1 -0
  145. package/dist/nexus/index.js +2 -0
  146. package/dist/nexus/index.js.map +1 -1
  147. package/dist/nexus/workspace.d.ts.map +1 -1
  148. package/dist/nexus/workspace.js +355 -0
  149. package/dist/nexus/workspace.js.map +1 -0
  150. package/dist/orchestration/hierarchy.d.ts +32 -0
  151. package/dist/orchestration/hierarchy.d.ts.map +1 -0
  152. package/dist/orchestration/index.d.ts +1 -0
  153. package/dist/orchestration/index.d.ts.map +1 -1
  154. package/dist/output.d.ts +2 -2
  155. package/dist/output.d.ts.map +1 -1
  156. package/dist/output.js +40 -8
  157. package/dist/output.js.map +1 -1
  158. package/dist/pagination.d.ts +1 -1
  159. package/dist/pagination.d.ts.map +1 -1
  160. package/dist/sessions/find.d.ts +3 -0
  161. package/dist/sessions/find.d.ts.map +1 -1
  162. package/dist/sessions/find.js +3 -1
  163. package/dist/sessions/find.js.map +1 -1
  164. package/dist/sessions/index.d.ts.map +1 -1
  165. package/dist/sessions/index.js +11 -4
  166. package/dist/sessions/index.js.map +1 -1
  167. package/dist/sessions/snapshot.js +213 -0
  168. package/dist/sessions/snapshot.js.map +1 -0
  169. package/dist/store/agent-registry-accessor.d.ts +31 -0
  170. package/dist/store/agent-registry-accessor.d.ts.map +1 -0
  171. package/dist/store/agent-registry-accessor.js +169 -0
  172. package/dist/store/agent-registry-accessor.js.map +1 -0
  173. package/dist/store/converters.d.ts.map +1 -1
  174. package/dist/store/converters.js +2 -0
  175. package/dist/store/converters.js.map +1 -1
  176. package/dist/store/cross-db-cleanup.d.ts +34 -0
  177. package/dist/store/cross-db-cleanup.d.ts.map +1 -1
  178. package/dist/store/db-helpers.d.ts.map +1 -1
  179. package/dist/store/db-helpers.js +1 -0
  180. package/dist/store/db-helpers.js.map +1 -1
  181. package/dist/store/json.js +2 -2
  182. package/dist/store/safety-data-accessor.d.ts +7 -0
  183. package/dist/store/safety-data-accessor.d.ts.map +1 -1
  184. package/dist/store/safety-data-accessor.js +14 -0
  185. package/dist/store/safety-data-accessor.js.map +1 -1
  186. package/dist/store/signaldock-sqlite.d.ts +48 -0
  187. package/dist/store/signaldock-sqlite.d.ts.map +1 -0
  188. package/dist/store/signaldock-sqlite.js +178 -0
  189. package/dist/store/signaldock-sqlite.js.map +1 -0
  190. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  191. package/dist/store/sqlite-data-accessor.js +50 -0
  192. package/dist/store/sqlite-data-accessor.js.map +1 -1
  193. package/dist/store/sqlite.d.ts.map +1 -1
  194. package/dist/store/sqlite.js +30 -1
  195. package/dist/store/sqlite.js.map +1 -1
  196. package/dist/store/task-store.d.ts.map +1 -1
  197. package/dist/store/task-store.js +2 -0
  198. package/dist/store/task-store.js.map +1 -1
  199. package/dist/store/tasks-schema.d.ts +16 -0
  200. package/dist/store/tasks-schema.d.ts.map +1 -1
  201. package/dist/store/tasks-schema.js +33 -0
  202. package/dist/store/tasks-schema.js.map +1 -1
  203. package/dist/store/validation-schemas.d.ts +32 -0
  204. package/dist/store/validation-schemas.d.ts.map +1 -1
  205. package/dist/system/health.d.ts +1 -1
  206. package/dist/system/health.d.ts.map +1 -1
  207. package/dist/system/health.js +35 -0
  208. package/dist/system/health.js.map +1 -1
  209. package/dist/task-work/index.d.ts.map +1 -1
  210. package/dist/task-work/index.js +8 -4
  211. package/dist/task-work/index.js.map +1 -1
  212. package/dist/tasks/complete.js +5 -2
  213. package/dist/tasks/complete.js.map +1 -1
  214. package/dist/tasks/find.d.ts +3 -0
  215. package/dist/tasks/find.d.ts.map +1 -1
  216. package/dist/tasks/find.js +7 -1
  217. package/dist/tasks/find.js.map +1 -1
  218. package/dist/tasks/list.d.ts +5 -2
  219. package/dist/tasks/list.d.ts.map +1 -1
  220. package/dist/tasks/list.js +9 -2
  221. package/dist/tasks/list.js.map +1 -1
  222. package/dist/tasks/show.d.ts +3 -0
  223. package/dist/tasks/show.d.ts.map +1 -1
  224. package/dist/tasks/show.js +2 -0
  225. package/dist/tasks/show.js.map +1 -1
  226. package/dist/upgrade.d.ts.map +1 -1
  227. package/dist/upgrade.js +15 -0
  228. package/dist/upgrade.js.map +1 -1
  229. package/migrations/drizzle-tasks/20260324000000_assignee-column/migration.sql +6 -0
  230. package/migrations/drizzle-tasks/20260324000000_assignee-column/snapshot.json +9 -0
  231. package/migrations/drizzle-tasks/20260327000000_agent-credentials/migration.sql +23 -0
  232. package/package.json +17 -7
  233. package/src/__tests__/cli-parity.test.js +11 -1
  234. package/src/__tests__/cli-parity.test.js.map +1 -1
  235. package/src/__tests__/cli-parity.test.ts +17 -1
  236. package/src/__tests__/human-output.test.js +11 -1
  237. package/src/__tests__/human-output.test.js.map +1 -1
  238. package/src/__tests__/human-output.test.ts +18 -1
  239. package/src/__tests__/injection-chain.test.js +3 -2
  240. package/src/__tests__/injection-chain.test.js.map +1 -1
  241. package/src/__tests__/injection-mvi-tiers.test.d.ts +2 -2
  242. package/src/__tests__/injection-mvi-tiers.test.js +15 -15
  243. package/src/__tests__/injection-mvi-tiers.test.js.map +1 -1
  244. package/src/__tests__/lafs-conformance.test.d.ts +1 -1
  245. package/src/__tests__/lafs-conformance.test.js +2 -2
  246. package/src/__tests__/sharing.test.js +19 -0
  247. package/src/__tests__/sharing.test.js.map +1 -1
  248. package/src/agents/__tests__/agent-registry.test.d.ts +12 -0
  249. package/src/agents/__tests__/agent-registry.test.d.ts.map +1 -0
  250. package/src/agents/__tests__/agent-registry.test.js +262 -0
  251. package/src/agents/__tests__/agent-registry.test.js.map +1 -0
  252. package/src/agents/__tests__/execution-learning.test.d.ts +14 -0
  253. package/src/agents/__tests__/execution-learning.test.d.ts.map +1 -0
  254. package/src/agents/__tests__/execution-learning.test.js +533 -0
  255. package/src/agents/__tests__/execution-learning.test.js.map +1 -0
  256. package/src/agents/__tests__/health-monitor.test.d.ts +10 -0
  257. package/src/agents/__tests__/health-monitor.test.d.ts.map +1 -0
  258. package/src/agents/__tests__/health-monitor.test.js +259 -0
  259. package/src/agents/__tests__/health-monitor.test.js.map +1 -0
  260. package/src/agents/__tests__/registry.test.js +27 -2
  261. package/src/agents/__tests__/registry.test.js.map +1 -1
  262. package/src/agents/agent-schema.ts +2 -5
  263. package/src/cant/__tests__/cant-agent-parse.test.ts +94 -0
  264. package/src/cant/approval.ts +218 -0
  265. package/src/cant/context-builder.ts +135 -0
  266. package/src/cant/discretion.ts +149 -0
  267. package/src/cant/index.ts +58 -0
  268. package/src/cant/parallel-runner.ts +205 -0
  269. package/src/cant/types.ts +158 -0
  270. package/src/cant/workflow-executor.ts +618 -0
  271. package/src/code/index.ts +10 -0
  272. package/src/code/outline.ts +214 -0
  273. package/src/code/parser.ts +299 -0
  274. package/src/code/search.ts +173 -0
  275. package/src/code/unfold.ts +204 -0
  276. package/src/conduit/__tests__/dual-api-e2e.test.ts +212 -0
  277. package/src/conduit/__tests__/local-credential-flow.test.ts +230 -0
  278. package/src/conduit/__tests__/local-transport.test.ts +320 -0
  279. package/src/conduit/__tests__/sse-transport.test.ts +344 -0
  280. package/src/conduit/conduit-client.ts +123 -0
  281. package/src/conduit/factory.ts +49 -0
  282. package/src/conduit/http-transport.ts +201 -0
  283. package/src/conduit/index.ts +15 -0
  284. package/src/conduit/local-transport.ts +309 -0
  285. package/src/conduit/sse-transport.ts +382 -0
  286. package/src/crypto/credentials.ts +166 -0
  287. package/src/engine-result.ts +1 -1
  288. package/src/error-catalog.ts +1 -1
  289. package/src/error-registry.ts +1 -1
  290. package/src/errors.ts +1 -1
  291. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts +13 -0
  292. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.d.ts.map +1 -0
  293. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js +501 -0
  294. package/src/hooks/handlers/__tests__/hook-automation-e2e.test.js.map +1 -0
  295. package/src/hooks/handlers/agent-hooks.ts +1 -30
  296. package/src/hooks/handlers/context-hooks.ts +1 -30
  297. package/src/hooks/handlers/error-hooks.ts +14 -5
  298. package/src/hooks/handlers/file-hooks.ts +1 -6
  299. package/src/hooks/handlers/handler-helpers.ts +62 -0
  300. package/src/hooks/handlers/mcp-hooks.ts +2 -14
  301. package/src/hooks/handlers/session-hooks.ts +1 -6
  302. package/src/hooks/handlers/task-hooks.ts +1 -6
  303. package/src/hooks/handlers/work-capture-hooks.ts +1 -10
  304. package/src/index.ts +12 -1
  305. package/src/init.ts +12 -0
  306. package/src/intelligence/__tests__/adaptive-validation.test.d.ts +11 -0
  307. package/src/intelligence/__tests__/adaptive-validation.test.d.ts.map +1 -0
  308. package/src/intelligence/__tests__/adaptive-validation.test.js +517 -0
  309. package/src/intelligence/__tests__/adaptive-validation.test.js.map +1 -0
  310. package/src/intelligence/__tests__/impact.test.d.ts +1 -0
  311. package/src/intelligence/__tests__/impact.test.d.ts.map +1 -1
  312. package/src/intelligence/__tests__/impact.test.js +132 -1
  313. package/src/intelligence/__tests__/impact.test.js.map +1 -1
  314. package/src/internal.ts +22 -0
  315. package/src/lib/__tests__/retry.test.d.ts +7 -0
  316. package/src/lib/__tests__/retry.test.d.ts.map +1 -0
  317. package/src/lib/__tests__/retry.test.js +225 -0
  318. package/src/lib/__tests__/retry.test.js.map +1 -0
  319. package/src/lib/index.ts +8 -0
  320. package/src/lib/tree-sitter-languages.ts +88 -0
  321. package/src/lifecycle/__tests__/chain-store.test.js +6 -0
  322. package/src/lifecycle/__tests__/chain-store.test.js.map +1 -1
  323. package/src/lifecycle/__tests__/tessera-engine.test.js +52 -0
  324. package/src/lifecycle/__tests__/tessera-engine.test.js.map +1 -1
  325. package/src/memory/__tests__/brain-automation.test.d.ts +11 -0
  326. package/src/memory/__tests__/brain-automation.test.d.ts.map +1 -0
  327. package/src/memory/__tests__/brain-automation.test.js +730 -0
  328. package/src/memory/__tests__/brain-automation.test.js.map +1 -0
  329. package/src/memory/__tests__/brain-links.test.ts +14 -0
  330. package/src/memory/__tests__/brain-retrieval.test.ts +10 -0
  331. package/src/memory/__tests__/session-memory.test.ts +17 -0
  332. package/src/memory/brain-links.ts +17 -0
  333. package/src/memory/brain-maintenance.ts +33 -1
  334. package/src/memory/brain-retrieval.ts +27 -2
  335. package/src/memory/decisions.ts +18 -2
  336. package/src/mvi-helpers.ts +81 -0
  337. package/src/nexus/workspace.ts +19 -7
  338. package/src/orchestration/hierarchy.ts +202 -0
  339. package/src/orchestration/index.ts +1 -0
  340. package/src/output.ts +43 -10
  341. package/src/pagination.ts +1 -1
  342. package/src/sessions/__tests__/session-edge-cases.test.js +20 -1
  343. package/src/sessions/__tests__/session-edge-cases.test.js.map +1 -1
  344. package/src/sessions/__tests__/session-find.test.js +1 -1
  345. package/src/sessions/__tests__/session-find.test.js.map +1 -1
  346. package/src/sessions/__tests__/session-find.test.ts +1 -1
  347. package/src/sessions/find.ts +6 -1
  348. package/src/sessions/index.ts +9 -0
  349. package/src/store/__tests__/migration-safety.test.js +3 -0
  350. package/src/store/__tests__/migration-safety.test.js.map +1 -1
  351. package/src/store/__tests__/session-store.test.js +128 -1
  352. package/src/store/__tests__/session-store.test.js.map +1 -1
  353. package/src/store/__tests__/task-store.test.js +18 -1
  354. package/src/store/__tests__/task-store.test.js.map +1 -1
  355. package/src/store/__tests__/test-db-helper.d.ts.map +1 -1
  356. package/src/store/__tests__/test-db-helper.js +12 -0
  357. package/src/store/__tests__/test-db-helper.js.map +1 -1
  358. package/src/store/agent-registry-accessor.ts +375 -0
  359. package/src/store/converters.ts +2 -0
  360. package/src/store/cross-db-cleanup.ts +175 -1
  361. package/src/store/db-helpers.ts +1 -0
  362. package/src/store/safety-data-accessor.ts +23 -0
  363. package/src/store/signaldock-sqlite.ts +429 -0
  364. package/src/store/sqlite-data-accessor.ts +72 -0
  365. package/src/store/sqlite.ts +4 -1
  366. package/src/store/task-store.ts +9 -1
  367. package/src/store/tasks-schema.ts +7 -0
  368. package/src/system/__tests__/health.test.ts +2 -2
  369. package/src/system/health.ts +54 -2
  370. package/src/task-work/index.ts +5 -0
  371. package/src/tasks/__tests__/add.test.js +19 -1
  372. package/src/tasks/__tests__/add.test.js.map +1 -1
  373. package/src/tasks/__tests__/assignee.test.d.ts +14 -0
  374. package/src/tasks/__tests__/assignee.test.d.ts.map +1 -0
  375. package/src/tasks/__tests__/assignee.test.js +125 -0
  376. package/src/tasks/__tests__/assignee.test.js.map +1 -0
  377. package/src/tasks/__tests__/assignee.test.ts +162 -0
  378. package/src/tasks/__tests__/complete-unblocks.test.js +13 -1
  379. package/src/tasks/__tests__/complete-unblocks.test.js.map +1 -1
  380. package/src/tasks/__tests__/complete.test.js +28 -7
  381. package/src/tasks/__tests__/complete.test.js.map +1 -1
  382. package/src/tasks/__tests__/epic-enforcement.test.d.ts +15 -0
  383. package/src/tasks/__tests__/epic-enforcement.test.d.ts.map +1 -0
  384. package/src/tasks/__tests__/epic-enforcement.test.js +669 -0
  385. package/src/tasks/__tests__/epic-enforcement.test.js.map +1 -0
  386. package/src/tasks/__tests__/hierarchy-policy.test.js +5 -0
  387. package/src/tasks/__tests__/hierarchy-policy.test.js.map +1 -1
  388. package/src/tasks/__tests__/minimal-test.test.d.ts +2 -0
  389. package/src/tasks/__tests__/minimal-test.test.d.ts.map +1 -0
  390. package/src/tasks/__tests__/minimal-test.test.js +25 -0
  391. package/src/tasks/__tests__/minimal-test.test.js.map +1 -0
  392. package/src/tasks/__tests__/pipeline-stage.test.d.ts +14 -0
  393. package/src/tasks/__tests__/pipeline-stage.test.d.ts.map +1 -0
  394. package/src/tasks/__tests__/pipeline-stage.test.js +277 -0
  395. package/src/tasks/__tests__/pipeline-stage.test.js.map +1 -0
  396. package/src/tasks/__tests__/update.test.js +43 -6
  397. package/src/tasks/__tests__/update.test.js.map +1 -1
  398. package/src/tasks/find.ts +11 -1
  399. package/src/tasks/list.ts +14 -3
  400. package/src/tasks/show.ts +6 -0
  401. package/src/upgrade.ts +16 -0
  402. package/dist/tasks/reparent.d.ts +0 -38
  403. package/dist/tasks/reparent.d.ts.map +0 -1
  404. package/dist/ui/injection-legacy.d.ts +0 -26
  405. package/dist/ui/injection-legacy.d.ts.map +0 -1
  406. package/dist/ui/injection-legacy.js +0 -42
  407. package/dist/ui/injection-legacy.js.map +0 -1
  408. package/src/signaldock/__tests__/claude-code-transport.test.d.ts +0 -7
  409. package/src/signaldock/__tests__/claude-code-transport.test.d.ts.map +0 -1
  410. package/src/signaldock/__tests__/claude-code-transport.test.js +0 -147
  411. package/src/signaldock/__tests__/claude-code-transport.test.js.map +0 -1
  412. package/src/signaldock/__tests__/claude-code-transport.test.ts +0 -180
  413. package/src/signaldock/__tests__/factory.test.d.ts +0 -7
  414. package/src/signaldock/__tests__/factory.test.d.ts.map +0 -1
  415. package/src/signaldock/__tests__/factory.test.js +0 -55
  416. package/src/signaldock/__tests__/factory.test.js.map +0 -1
  417. package/src/signaldock/__tests__/factory.test.ts +0 -61
  418. package/src/signaldock/__tests__/signaldock-transport.test.d.ts +0 -9
  419. package/src/signaldock/__tests__/signaldock-transport.test.d.ts.map +0 -1
  420. package/src/signaldock/__tests__/signaldock-transport.test.js +0 -321
  421. package/src/signaldock/__tests__/signaldock-transport.test.js.map +0 -1
  422. package/src/signaldock/__tests__/signaldock-transport.test.ts +0 -421
  423. package/src/signaldock/claude-code-transport.ts +0 -137
  424. package/src/signaldock/factory.ts +0 -39
  425. package/src/signaldock/index.ts +0 -28
  426. package/src/signaldock/signaldock-transport.ts +0 -194
  427. package/src/signaldock/transport.ts +0 -78
  428. package/src/signaldock/types.ts +0 -100
@@ -0,0 +1,382 @@
1
+ /**
2
+ * SseTransport — Server-Sent Events transport with HTTP polling fallback.
3
+ *
4
+ * Receives messages in real-time via SSE from the SignalDock v2 API.
5
+ * Sends messages and acks via HTTP POST (SSE is receive-only).
6
+ * Falls back to HTTP polling when SSE is unavailable or disconnects.
7
+ *
8
+ * @see docs/specs/SIGNALDOCK-UNIFIED-AGENT-REGISTRY.md Section 4.4
9
+ * @task T216
10
+ */
11
+
12
+ import type { ConduitMessage, Transport, TransportConnectConfig } from '@cleocode/contracts';
13
+
14
+ /** Maximum reconnect attempts before permanent HTTP fallback. */
15
+ const MAX_RECONNECT_ATTEMPTS = 3;
16
+
17
+ /** Maximum reconnect delay in milliseconds. */
18
+ const MAX_RECONNECT_DELAY_MS = 30_000;
19
+
20
+ /** SSE transport mode. */
21
+ type SseMode = 'sse' | 'http-fallback';
22
+
23
+ /** Internal connection state. */
24
+ interface SseTransportState {
25
+ agentId: string;
26
+ apiKey: string;
27
+ apiBaseUrl: string;
28
+ sseEndpoint: string;
29
+ eventSource: EventSource | null;
30
+ mode: SseMode;
31
+ messageBuffer: ConduitMessage[];
32
+ subscribers: Set<(message: ConduitMessage) => void>;
33
+ reconnectAttempts: number;
34
+ reconnectTimer: ReturnType<typeof setTimeout> | null;
35
+ connected: boolean;
36
+ }
37
+
38
+ /** SseTransport — real-time SSE with HTTP polling fallback. */
39
+ export class SseTransport implements Transport {
40
+ readonly name = 'sse';
41
+ private state: SseTransportState | null = null;
42
+
43
+ /**
44
+ * Connect to the SSE endpoint for real-time message delivery.
45
+ *
46
+ * If SSE connection fails, falls back to HTTP polling mode.
47
+ * Auth is conveyed via query parameter (SSE doesn't support custom headers).
48
+ */
49
+ async connect(config: TransportConnectConfig): Promise<void> {
50
+ if (this.state?.connected) {
51
+ throw new Error('SseTransport already connected. Disconnect first.');
52
+ }
53
+
54
+ const sseEndpoint = config.sseEndpoint;
55
+ if (!sseEndpoint && !config.apiBaseUrl) {
56
+ throw new Error('SseTransport requires sseEndpoint or apiBaseUrl in config.');
57
+ }
58
+
59
+ const endpoint = sseEndpoint ?? `${config.apiBaseUrl}/messages/stream`;
60
+
61
+ this.state = {
62
+ agentId: config.agentId,
63
+ apiKey: config.apiKey,
64
+ apiBaseUrl: config.apiBaseUrl,
65
+ sseEndpoint: endpoint,
66
+ eventSource: null,
67
+ mode: 'sse',
68
+ messageBuffer: [],
69
+ subscribers: new Set(),
70
+ reconnectAttempts: 0,
71
+ reconnectTimer: null,
72
+ connected: false,
73
+ };
74
+
75
+ try {
76
+ await this.connectSse();
77
+ } catch {
78
+ // SSE failed — fall back to HTTP polling
79
+ this.state.mode = 'http-fallback';
80
+ this.state.connected = true;
81
+ }
82
+ }
83
+
84
+ /** Disconnect the transport, closing SSE and clearing all state. */
85
+ async disconnect(): Promise<void> {
86
+ if (!this.state) return;
87
+
88
+ if (this.state.eventSource) {
89
+ this.state.eventSource.close();
90
+ }
91
+ if (this.state.reconnectTimer) {
92
+ clearTimeout(this.state.reconnectTimer);
93
+ }
94
+ this.state.messageBuffer = [];
95
+ this.state.connected = false;
96
+ this.state = null;
97
+ }
98
+
99
+ /**
100
+ * Send a message via HTTP POST.
101
+ *
102
+ * SSE is receive-only — all sends go through HTTP regardless of SSE state.
103
+ */
104
+ async push(
105
+ to: string,
106
+ content: string,
107
+ options?: { conversationId?: string; replyTo?: string },
108
+ ): Promise<{ messageId: string }> {
109
+ this.ensureConnected();
110
+
111
+ const body: Record<string, string> = { content, toAgentId: to };
112
+ let path = '/messages';
113
+
114
+ if (options?.conversationId) {
115
+ path = `/conversations/${options.conversationId}/messages`;
116
+ if (options.replyTo) {
117
+ body['replyTo'] = options.replyTo;
118
+ }
119
+ }
120
+
121
+ const response = await this.httpFetch(path, {
122
+ method: 'POST',
123
+ body: JSON.stringify(body),
124
+ });
125
+
126
+ if (!response.ok) {
127
+ const text = await response.text().catch(() => '');
128
+ throw new Error(`SseTransport push failed: ${response.status} ${text}`);
129
+ }
130
+
131
+ const data = (await response.json()) as {
132
+ data?: { message?: { id?: string }; id?: string };
133
+ };
134
+ return { messageId: data.data?.message?.id ?? data.data?.id ?? 'unknown' };
135
+ }
136
+
137
+ /**
138
+ * Poll for messages.
139
+ *
140
+ * In SSE mode: drains the internal message buffer (no HTTP request).
141
+ * In HTTP fallback mode: fetches via GET /messages/peek.
142
+ */
143
+ async poll(options?: { limit?: number; since?: string }): Promise<ConduitMessage[]> {
144
+ this.ensureConnected();
145
+
146
+ if (this.state!.mode === 'sse' && this.state!.eventSource) {
147
+ // Drain buffer — messages arrived via SSE push
148
+ let messages = this.state!.messageBuffer.splice(0);
149
+
150
+ if (options?.since) {
151
+ messages = messages.filter((m) => m.timestamp > options.since!);
152
+ }
153
+ if (options?.limit && messages.length > options.limit) {
154
+ // Put excess back in buffer
155
+ const excess = messages.splice(options.limit);
156
+ this.state!.messageBuffer.unshift(...excess);
157
+ }
158
+ return messages;
159
+ }
160
+
161
+ // HTTP fallback mode
162
+ return this.httpPoll(options);
163
+ }
164
+
165
+ /** Acknowledge messages via HTTP POST. */
166
+ async ack(messageIds: string[]): Promise<void> {
167
+ this.ensureConnected();
168
+ if (messageIds.length === 0) return;
169
+
170
+ await this.httpFetch('/messages/ack', {
171
+ method: 'POST',
172
+ body: JSON.stringify({ messageIds }),
173
+ });
174
+ }
175
+
176
+ /**
177
+ * Subscribe to real-time messages.
178
+ *
179
+ * In SSE mode, messages are pushed to the handler as they arrive.
180
+ * In HTTP fallback mode, polls on an interval.
181
+ */
182
+ subscribe(handler: (message: ConduitMessage) => void): () => void {
183
+ this.ensureConnected();
184
+
185
+ this.state!.subscribers.add(handler);
186
+
187
+ // Start HTTP polling interval only if in fallback mode
188
+ const interval =
189
+ this.state!.mode === 'http-fallback'
190
+ ? setInterval(async () => {
191
+ if (this.state?.mode === 'http-fallback') {
192
+ const messages = await this.httpPoll({ limit: 20 });
193
+ for (const msg of messages) handler(msg);
194
+ if (messages.length > 0) {
195
+ await this.ack(messages.map((m) => m.id));
196
+ }
197
+ }
198
+ }, 5000)
199
+ : null;
200
+
201
+ return () => {
202
+ if (interval) clearInterval(interval);
203
+ if (this.state) {
204
+ this.state.subscribers.delete(handler);
205
+ }
206
+ };
207
+ }
208
+
209
+ // --------------------------------------------------------------------------
210
+ // SSE connection management
211
+ // --------------------------------------------------------------------------
212
+
213
+ /** Establish SSE connection. Resolves when open, rejects on error. */
214
+ private connectSse(): Promise<void> {
215
+ return new Promise<void>((resolve, reject) => {
216
+ if (!this.state) {
217
+ reject(new Error('No state'));
218
+ return;
219
+ }
220
+
221
+ // SSE doesn't support custom headers — auth via query param
222
+ const url = `${this.state.sseEndpoint}?token=${encodeURIComponent(this.state.apiKey)}&agent_id=${encodeURIComponent(this.state.agentId)}`;
223
+
224
+ const es = new EventSource(url);
225
+ this.state.eventSource = es;
226
+
227
+ const timeout = setTimeout(() => {
228
+ es.close();
229
+ reject(new Error('SSE connection timeout'));
230
+ }, 10_000);
231
+
232
+ es.addEventListener('open', () => {
233
+ clearTimeout(timeout);
234
+ this.state!.connected = true;
235
+ this.state!.reconnectAttempts = 0;
236
+ resolve();
237
+ });
238
+
239
+ es.addEventListener('message', (event: MessageEvent) => {
240
+ this.handleSseMessage(event);
241
+ });
242
+
243
+ es.addEventListener('error', () => {
244
+ clearTimeout(timeout);
245
+ if (!this.state!.connected) {
246
+ // Initial connection failed
247
+ es.close();
248
+ reject(new Error('SSE connection failed'));
249
+ } else {
250
+ // Connection dropped — attempt reconnect
251
+ this.handleSseDisconnect();
252
+ }
253
+ });
254
+ });
255
+ }
256
+
257
+ /** Handle an incoming SSE message event. */
258
+ private handleSseMessage(event: MessageEvent): void {
259
+ if (!this.state) return;
260
+
261
+ try {
262
+ const data = JSON.parse(event.data as string) as {
263
+ id?: string;
264
+ from_agent_id?: string;
265
+ from?: string;
266
+ content?: string;
267
+ conversation_id?: string;
268
+ threadId?: string;
269
+ created_at?: string;
270
+ timestamp?: string;
271
+ type?: string;
272
+ };
273
+
274
+ // Skip heartbeat events
275
+ if (data.type === 'heartbeat' || data.type === 'ping') return;
276
+
277
+ // Skip self-sent messages
278
+ const from = data.from_agent_id ?? data.from ?? 'unknown';
279
+ if (from === this.state.agentId) return;
280
+
281
+ const message: ConduitMessage = {
282
+ id: data.id ?? `sse-${Date.now()}`,
283
+ from,
284
+ content: data.content ?? '',
285
+ threadId: data.conversation_id ?? data.threadId,
286
+ timestamp: data.created_at ?? data.timestamp ?? new Date().toISOString(),
287
+ };
288
+
289
+ this.state.messageBuffer.push(message);
290
+ for (const h of this.state.subscribers) {
291
+ try {
292
+ h(message);
293
+ } catch {
294
+ /* subscriber error must not crash transport */
295
+ }
296
+ }
297
+ } catch {
298
+ // Malformed SSE data — skip silently
299
+ }
300
+ }
301
+
302
+ /** Handle SSE connection drop — attempt reconnect with backoff. */
303
+ private handleSseDisconnect(): void {
304
+ if (!this.state) return;
305
+
306
+ this.state.eventSource?.close();
307
+ this.state.eventSource = null;
308
+ this.state.reconnectAttempts++;
309
+
310
+ if (this.state.reconnectAttempts > MAX_RECONNECT_ATTEMPTS) {
311
+ // Switch to permanent HTTP fallback
312
+ this.state.mode = 'http-fallback';
313
+ return;
314
+ }
315
+
316
+ // Exponential backoff: 1s, 2s, 4s, ...
317
+ const delay = Math.min(1000 * 2 ** (this.state.reconnectAttempts - 1), MAX_RECONNECT_DELAY_MS);
318
+
319
+ this.state.reconnectTimer = setTimeout(() => {
320
+ void this.connectSse().catch(() => {
321
+ this.handleSseDisconnect();
322
+ });
323
+ }, delay);
324
+ }
325
+
326
+ // --------------------------------------------------------------------------
327
+ // HTTP helpers
328
+ // --------------------------------------------------------------------------
329
+
330
+ /** HTTP poll for messages (used in fallback mode). */
331
+ private async httpPoll(options?: { limit?: number; since?: string }): Promise<ConduitMessage[]> {
332
+ const params = new URLSearchParams();
333
+ params.set('mentioned', this.state!.agentId);
334
+ if (options?.limit) params.set('limit', String(options.limit));
335
+ if (options?.since) params.set('since', options.since);
336
+
337
+ const response = await this.httpFetch(`/messages/peek?${params}`, { method: 'GET' });
338
+ if (!response.ok) return [];
339
+
340
+ const data = (await response.json()) as {
341
+ data?: {
342
+ messages?: Array<{
343
+ id: string;
344
+ fromAgentId?: string;
345
+ content?: string;
346
+ conversationId?: string;
347
+ createdAt?: string;
348
+ }>;
349
+ };
350
+ };
351
+
352
+ return (data.data?.messages ?? []).map((m) => ({
353
+ id: m.id,
354
+ from: m.fromAgentId ?? 'unknown',
355
+ content: m.content ?? '',
356
+ threadId: m.conversationId,
357
+ timestamp: m.createdAt ?? new Date().toISOString(),
358
+ }));
359
+ }
360
+
361
+ /** Make an authenticated HTTP request to the API. */
362
+ private async httpFetch(path: string, init: RequestInit): Promise<Response> {
363
+ const url = `${this.state!.apiBaseUrl}${path}`;
364
+ return fetch(url, {
365
+ ...init,
366
+ headers: {
367
+ 'Content-Type': 'application/json',
368
+ Authorization: `Bearer ${this.state!.apiKey}`,
369
+ 'X-Agent-Id': this.state!.agentId,
370
+ ...(init.headers as Record<string, string>),
371
+ },
372
+ signal: init.signal ?? AbortSignal.timeout(10_000),
373
+ });
374
+ }
375
+
376
+ /** Throw if not connected. */
377
+ private ensureConnected(): void {
378
+ if (!this.state?.connected) {
379
+ throw new Error('SseTransport not connected. Call connect() first.');
380
+ }
381
+ }
382
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Credential encryption — AES-256-GCM with machine-bound key derivation.
3
+ *
4
+ * API keys (`sk_live_*`) are encrypted at rest in SQLite using AES-256-GCM.
5
+ * The encryption key is derived per-project from a machine-specific secret:
6
+ *
7
+ * machine-key (32 random bytes at ~/.local/share/cleo/machine-key)
8
+ * + project path
9
+ * = HMAC-SHA256(machine-key, project-path) → per-project AES key
10
+ *
11
+ * This means credentials are bound to BOTH the machine AND the project.
12
+ * Moving `.cleo/tasks.db` to another machine renders stored keys unreadable.
13
+ *
14
+ * @see docs/specs/SIGNALDOCK-UNIFIED-AGENT-REGISTRY.md Section 3.6
15
+ * @module crypto/credentials
16
+ */
17
+
18
+ import { createCipheriv, createDecipheriv, createHmac, randomBytes } from 'node:crypto';
19
+ import { chmod, mkdir, readFile, stat, writeFile } from 'node:fs/promises';
20
+ import { dirname, join } from 'node:path';
21
+
22
+ /** AES-256-GCM constants. */
23
+ const ALGORITHM = 'aes-256-gcm' as const;
24
+ const IV_LENGTH = 12;
25
+ const AUTH_TAG_LENGTH = 16;
26
+ const KEY_LENGTH = 32;
27
+ /** Version byte prefix for ciphertext format (F-006: enables future algorithm migration). */
28
+ const CIPHERTEXT_VERSION = 0x01;
29
+
30
+ /**
31
+ * Get the path to the machine key file.
32
+ * Uses XDG data dir: `~/.local/share/cleo/machine-key`
33
+ *
34
+ * @throws If HOME/USERPROFILE are unset (F-002: never fall back to /tmp).
35
+ */
36
+ function getMachineKeyPath(): string {
37
+ const home = process.env['HOME'] ?? process.env['USERPROFILE'];
38
+ if (!home) {
39
+ throw new Error(
40
+ 'Cannot determine home directory. Set HOME or USERPROFILE environment variable. ' +
41
+ 'Machine key cannot be stored securely without a persistent home directory.',
42
+ );
43
+ }
44
+ return join(home, '.local', 'share', 'cleo', 'machine-key');
45
+ }
46
+
47
+ /**
48
+ * Read or auto-generate the machine key (32 random bytes).
49
+ * Sets file permissions to 0600 (owner read/write only).
50
+ *
51
+ * @throws If the machine key exists but has wrong permissions (not 0600).
52
+ */
53
+ async function getMachineKey(): Promise<Buffer> {
54
+ const keyPath = getMachineKeyPath();
55
+
56
+ try {
57
+ // Check existing key
58
+ const stats = await stat(keyPath);
59
+ const mode = stats.mode & 0o777;
60
+ if (mode !== 0o600) {
61
+ throw new Error(
62
+ `Machine key has unsafe permissions (${mode.toString(8)}). Expected 0600. ` +
63
+ `Fix with: chmod 600 ${keyPath}`,
64
+ );
65
+ }
66
+ const key = await readFile(keyPath);
67
+ // F-004: validate key length
68
+ if (key.length !== KEY_LENGTH) {
69
+ throw new Error(
70
+ `Machine key has invalid length (${key.length} bytes, expected ${KEY_LENGTH}). ` +
71
+ `Delete ${keyPath} and re-register agents to generate a new key.`,
72
+ );
73
+ }
74
+ return key;
75
+ } catch (err: unknown) {
76
+ if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') {
77
+ // Auto-generate on first use
78
+ const key = randomBytes(KEY_LENGTH);
79
+ await mkdir(dirname(keyPath), { recursive: true });
80
+ await writeFile(keyPath, key, { mode: 0o600 });
81
+ await chmod(keyPath, 0o600); // Ensure perms even on existing dirs
82
+ return key;
83
+ }
84
+ throw err;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Derive a per-project encryption key from the machine key.
90
+ * Uses HMAC-SHA256(machine-key, project-path) to produce a 32-byte AES key.
91
+ */
92
+ async function deriveProjectKey(projectPath: string): Promise<Buffer> {
93
+ const machineKey = await getMachineKey();
94
+ return createHmac('sha256', machineKey).update(projectPath).digest();
95
+ }
96
+
97
+ /**
98
+ * Encrypt a plaintext string using AES-256-GCM with a per-project key.
99
+ *
100
+ * Output format: base64(version + iv + ciphertext + authTag)
101
+ * - version: 1 byte (0x01 = AES-256-GCM)
102
+ * - iv: 12 bytes
103
+ * - ciphertext: variable length
104
+ * - authTag: 16 bytes
105
+ *
106
+ * @param plaintext - The string to encrypt (e.g. an API key).
107
+ * @param projectPath - Absolute path to the project directory (used for key derivation).
108
+ * @returns Base64-encoded ciphertext.
109
+ */
110
+ export async function encrypt(plaintext: string, projectPath: string): Promise<string> {
111
+ const key = await deriveProjectKey(projectPath);
112
+ const iv = randomBytes(IV_LENGTH);
113
+ const cipher = createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });
114
+
115
+ const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
116
+ const authTag = cipher.getAuthTag();
117
+
118
+ // Pack: version + iv + ciphertext + authTag (F-006: version byte for future migration)
119
+ const version = Buffer.from([CIPHERTEXT_VERSION]);
120
+ const packed = Buffer.concat([version, iv, encrypted, authTag]);
121
+ return packed.toString('base64');
122
+ }
123
+
124
+ /**
125
+ * Decrypt a base64-encoded ciphertext using AES-256-GCM with a per-project key.
126
+ *
127
+ * @param ciphertext - Base64-encoded string from `encrypt()`.
128
+ * @param projectPath - Absolute path to the project directory (must match the one used for encryption).
129
+ * @returns The original plaintext string.
130
+ * @throws If decryption fails (wrong key, corrupted data, or machine key mismatch).
131
+ */
132
+ export async function decrypt(ciphertext: string, projectPath: string): Promise<string> {
133
+ const key = await deriveProjectKey(projectPath);
134
+ const packed = Buffer.from(ciphertext, 'base64');
135
+
136
+ if (packed.length < 1 + IV_LENGTH + AUTH_TAG_LENGTH) {
137
+ throw new Error('Cannot decrypt credentials: ciphertext too short');
138
+ }
139
+
140
+ // F-006: check version byte
141
+ const version = packed[0];
142
+ if (version !== CIPHERTEXT_VERSION) {
143
+ throw new Error(
144
+ `Unknown ciphertext version (${version}). Expected ${CIPHERTEXT_VERSION}. ` +
145
+ 'Re-register agents to re-encrypt with the current format.',
146
+ );
147
+ }
148
+
149
+ const iv = packed.subarray(1, 1 + IV_LENGTH);
150
+ const authTag = packed.subarray(packed.length - AUTH_TAG_LENGTH);
151
+ const encrypted = packed.subarray(1 + IV_LENGTH, packed.length - AUTH_TAG_LENGTH);
152
+
153
+ const decipher = createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });
154
+ decipher.setAuthTag(authTag);
155
+
156
+ try {
157
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
158
+ return decrypted.toString('utf8');
159
+ } catch {
160
+ throw new Error(
161
+ 'Cannot decrypt credentials. Machine key mismatch or corrupted data. ' +
162
+ 'If this database was moved from another machine, re-register agents: ' +
163
+ 'cleo agent register --id <id> --api-key <key>',
164
+ );
165
+ }
166
+ }
@@ -9,7 +9,7 @@
9
9
  * @epic T5701
10
10
  */
11
11
 
12
- import type { LAFSPage } from '@cleocode/lafs-protocol';
12
+ import type { LAFSPage } from '@cleocode/lafs';
13
13
 
14
14
  /**
15
15
  * Canonical EngineResult type used by all engines and core engine-compat modules.
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { ExitCode } from '@cleocode/contracts';
13
- import type { LAFSErrorCategory } from '@cleocode/lafs-protocol';
13
+ import type { LAFSErrorCategory } from '@cleocode/lafs';
14
14
 
15
15
  /**
16
16
  * A single entry in the unified error catalog.
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { ExitCode } from '@cleocode/contracts';
16
- import type { LAFSErrorCategory } from '@cleocode/lafs-protocol';
16
+ import type { LAFSErrorCategory } from '@cleocode/lafs';
17
17
 
18
18
  /**
19
19
  * Entry in the CLEO-to-LAFS error registry.
package/src/errors.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { ExitCode, getExitCodeName, isRecoverableCode } from '@cleocode/contracts';
11
- import type { LAFSError, LAFSErrorCategory } from '@cleocode/lafs-protocol';
11
+ import type { LAFSError, LAFSErrorCategory } from '@cleocode/lafs';
12
12
  import { getErrorDefinition } from './error-catalog.js';
13
13
 
14
14
  /**
@@ -0,0 +1,13 @@
1
+ /**
2
+ * E2E integration tests: hook automation fires across lifecycle events
3
+ *
4
+ * Verifies that brain automation hooks actually dispatch and call observeBrain
5
+ * with the correct payloads for all lifecycle event types. Tests use mock
6
+ * adapters and direct handler invocation to exercise the full handler logic
7
+ * without requiring a real SQLite database.
8
+ *
9
+ * @task T168
10
+ * @epic T134
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=hook-automation-e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-automation-e2e.test.d.ts","sourceRoot":"","sources":["hook-automation-e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}