@namzu/sdk 0.1.8 → 0.3.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 (626) hide show
  1. package/CHANGELOG.md +69 -2
  2. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  3. package/dist/agents/ReactiveAgent.js +5 -2
  4. package/dist/agents/ReactiveAgent.js.map +1 -1
  5. package/dist/agents/RouterAgent.d.ts.map +1 -1
  6. package/dist/agents/RouterAgent.js +3 -0
  7. package/dist/agents/RouterAgent.js.map +1 -1
  8. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  9. package/dist/agents/SupervisorAgent.js +21 -5
  10. package/dist/agents/SupervisorAgent.js.map +1 -1
  11. package/dist/bridge/a2a/index.d.ts +1 -1
  12. package/dist/bridge/a2a/index.d.ts.map +1 -1
  13. package/dist/bridge/a2a/index.js +1 -1
  14. package/dist/bridge/a2a/index.js.map +1 -1
  15. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  16. package/dist/bridge/a2a/mapper.js +6 -0
  17. package/dist/bridge/a2a/mapper.js.map +1 -1
  18. package/dist/bridge/a2a/message.d.ts +0 -2
  19. package/dist/bridge/a2a/message.d.ts.map +1 -1
  20. package/dist/bridge/a2a/message.js +0 -26
  21. package/dist/bridge/a2a/message.js.map +1 -1
  22. package/dist/bridge/a2a/task.d.ts +5 -4
  23. package/dist/bridge/a2a/task.d.ts.map +1 -1
  24. package/dist/bridge/a2a/task.js +4 -4
  25. package/dist/bridge/a2a/task.js.map +1 -1
  26. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  27. package/dist/bridge/sse/mapper.js +6 -0
  28. package/dist/bridge/sse/mapper.js.map +1 -1
  29. package/dist/constants/a2a/index.d.ts +2 -2
  30. package/dist/constants/a2a/index.d.ts.map +1 -1
  31. package/dist/constants/a2a/index.js.map +1 -1
  32. package/dist/contracts/api.d.ts +14 -27
  33. package/dist/contracts/api.d.ts.map +1 -1
  34. package/dist/contracts/ids.d.ts +1 -1
  35. package/dist/contracts/ids.d.ts.map +1 -1
  36. package/dist/contracts/index.d.ts +3 -3
  37. package/dist/contracts/index.d.ts.map +1 -1
  38. package/dist/contracts/index.js +1 -1
  39. package/dist/contracts/index.js.map +1 -1
  40. package/dist/contracts/schemas.d.ts +1 -31
  41. package/dist/contracts/schemas.d.ts.map +1 -1
  42. package/dist/contracts/schemas.js +1 -7
  43. package/dist/contracts/schemas.js.map +1 -1
  44. package/dist/gateway/local.d.ts.map +1 -1
  45. package/dist/gateway/local.js +6 -0
  46. package/dist/gateway/local.js.map +1 -1
  47. package/dist/index.d.ts +6 -3
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +6 -3
  50. package/dist/index.js.map +1 -1
  51. package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
  52. package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
  53. package/dist/manager/agent/__tests__/lifecycle.test.js +316 -0
  54. package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
  55. package/dist/manager/agent/lifecycle.d.ts +67 -3
  56. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  57. package/dist/manager/agent/lifecycle.js +375 -14
  58. package/dist/manager/agent/lifecycle.js.map +1 -1
  59. package/dist/manager/index.d.ts +2 -0
  60. package/dist/manager/index.d.ts.map +1 -1
  61. package/dist/manager/index.js +1 -0
  62. package/dist/manager/index.js.map +1 -1
  63. package/dist/manager/run/persistence.d.ts +10 -1
  64. package/dist/manager/run/persistence.d.ts.map +1 -1
  65. package/dist/manager/run/persistence.js +20 -0
  66. package/dist/manager/run/persistence.js.map +1 -1
  67. package/dist/manager/thread/__tests__/lifecycle.test.d.ts +2 -0
  68. package/dist/manager/thread/__tests__/lifecycle.test.d.ts.map +1 -0
  69. package/dist/manager/thread/__tests__/lifecycle.test.js +216 -0
  70. package/dist/manager/thread/__tests__/lifecycle.test.js.map +1 -0
  71. package/dist/manager/thread/lifecycle.d.ts +105 -0
  72. package/dist/manager/thread/lifecycle.d.ts.map +1 -0
  73. package/dist/manager/thread/lifecycle.js +186 -0
  74. package/dist/manager/thread/lifecycle.js.map +1 -0
  75. package/dist/rag/retriever.js +2 -2
  76. package/dist/run/reporter.d.ts.map +1 -1
  77. package/dist/run/reporter.js +25 -0
  78. package/dist/run/reporter.js.map +1 -1
  79. package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
  80. package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
  81. package/dist/runtime/query/__tests__/context.test.js +85 -0
  82. package/dist/runtime/query/__tests__/context.test.js.map +1 -0
  83. package/dist/runtime/query/context-cache.d.ts +3 -3
  84. package/dist/runtime/query/context-cache.d.ts.map +1 -1
  85. package/dist/runtime/query/context-cache.js +2 -2
  86. package/dist/runtime/query/context-cache.js.map +1 -1
  87. package/dist/runtime/query/context.d.ts +45 -1
  88. package/dist/runtime/query/context.d.ts.map +1 -1
  89. package/dist/runtime/query/context.js +50 -8
  90. package/dist/runtime/query/context.js.map +1 -1
  91. package/dist/runtime/query/events.d.ts.map +1 -1
  92. package/dist/runtime/query/events.js +8 -0
  93. package/dist/runtime/query/events.js.map +1 -1
  94. package/dist/runtime/query/index.d.ts +22 -1
  95. package/dist/runtime/query/index.d.ts.map +1 -1
  96. package/dist/runtime/query/index.js +11 -0
  97. package/dist/runtime/query/index.js.map +1 -1
  98. package/dist/session/__tests__/integration/_fixtures.d.ts +122 -0
  99. package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
  100. package/dist/session/__tests__/integration/_fixtures.js +215 -0
  101. package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
  102. package/dist/session/__tests__/integration/archive-gate.test.d.ts +15 -0
  103. package/dist/session/__tests__/integration/archive-gate.test.d.ts.map +1 -0
  104. package/dist/session/__tests__/integration/archive-gate.test.js +214 -0
  105. package/dist/session/__tests__/integration/archive-gate.test.js.map +1 -0
  106. package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
  107. package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
  108. package/dist/session/__tests__/integration/capacity-caps.test.js +123 -0
  109. package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
  110. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
  111. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
  112. package/dist/session/__tests__/integration/e2e-spawn.test.js +238 -0
  113. package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
  114. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
  115. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
  116. package/dist/session/__tests__/integration/event-stream-ordering.test.js +330 -0
  117. package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
  118. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
  119. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
  120. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +182 -0
  121. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
  122. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
  123. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
  124. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +156 -0
  125. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
  126. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
  127. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
  128. package/dist/session/__tests__/integration/handoff-single-e2e.test.js +179 -0
  129. package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
  130. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
  131. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
  132. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +158 -0
  133. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
  134. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
  135. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
  136. package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
  137. package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
  138. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
  139. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
  140. package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
  141. package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
  142. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
  143. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
  144. package/dist/session/__tests__/integration/prev-artifact-dag.test.js +242 -0
  145. package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
  146. package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
  147. package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
  148. package/dist/session/__tests__/integration/retention-archive.test.js +187 -0
  149. package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
  150. package/dist/session/__tests__/integration/spawn-rollback.test.d.ts +26 -0
  151. package/dist/session/__tests__/integration/spawn-rollback.test.d.ts.map +1 -0
  152. package/dist/session/__tests__/integration/spawn-rollback.test.js +236 -0
  153. package/dist/session/__tests__/integration/spawn-rollback.test.js.map +1 -0
  154. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
  155. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
  156. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +201 -0
  157. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
  158. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
  159. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
  160. package/dist/session/__tests__/integration/tenant-isolation.test.js +189 -0
  161. package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
  162. package/dist/session/errors.d.ts +139 -0
  163. package/dist/session/errors.d.ts.map +1 -0
  164. package/dist/session/errors.js +107 -0
  165. package/dist/session/errors.js.map +1 -0
  166. package/dist/session/events/index.d.ts +4 -0
  167. package/dist/session/events/index.d.ts.map +1 -0
  168. package/dist/session/events/index.js +8 -0
  169. package/dist/session/events/index.js.map +1 -0
  170. package/dist/session/events/schema-version.d.ts +13 -0
  171. package/dist/session/events/schema-version.d.ts.map +1 -0
  172. package/dist/session/events/schema-version.js +12 -0
  173. package/dist/session/events/schema-version.js.map +1 -0
  174. package/dist/session/events/types.d.ts +64 -0
  175. package/dist/session/events/types.d.ts.map +1 -0
  176. package/dist/session/events/types.js +2 -0
  177. package/dist/session/events/types.js.map +1 -0
  178. package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
  179. package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
  180. package/dist/session/handoff/__tests__/broadcast.test.js +261 -0
  181. package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
  182. package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
  183. package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
  184. package/dist/session/handoff/__tests__/capacity.test.js +103 -0
  185. package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
  186. package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
  187. package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
  188. package/dist/session/handoff/__tests__/single.test.js +239 -0
  189. package/dist/session/handoff/__tests__/single.test.js.map +1 -0
  190. package/dist/session/handoff/assignment.d.ts +71 -0
  191. package/dist/session/handoff/assignment.d.ts.map +1 -0
  192. package/dist/session/handoff/assignment.js +11 -0
  193. package/dist/session/handoff/assignment.js.map +1 -0
  194. package/dist/session/handoff/broadcast.d.ts +54 -0
  195. package/dist/session/handoff/broadcast.d.ts.map +1 -0
  196. package/dist/session/handoff/broadcast.js +311 -0
  197. package/dist/session/handoff/broadcast.js.map +1 -0
  198. package/dist/session/handoff/capacity.d.ts +66 -0
  199. package/dist/session/handoff/capacity.d.ts.map +1 -0
  200. package/dist/session/handoff/capacity.js +60 -0
  201. package/dist/session/handoff/capacity.js.map +1 -0
  202. package/dist/session/handoff/events.d.ts +66 -0
  203. package/dist/session/handoff/events.d.ts.map +1 -0
  204. package/dist/session/handoff/events.js +13 -0
  205. package/dist/session/handoff/events.js.map +1 -0
  206. package/dist/session/handoff/index.d.ts +12 -0
  207. package/dist/session/handoff/index.d.ts.map +1 -0
  208. package/dist/session/handoff/index.js +9 -0
  209. package/dist/session/handoff/index.js.map +1 -0
  210. package/dist/session/handoff/single.d.ts +69 -0
  211. package/dist/session/handoff/single.d.ts.map +1 -0
  212. package/dist/session/handoff/single.js +229 -0
  213. package/dist/session/handoff/single.js.map +1 -0
  214. package/dist/session/handoff/version.d.ts +52 -0
  215. package/dist/session/handoff/version.d.ts.map +1 -0
  216. package/dist/session/handoff/version.js +36 -0
  217. package/dist/session/handoff/version.js.map +1 -0
  218. package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
  219. package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
  220. package/dist/session/hierarchy/__tests__/session.test.js +69 -0
  221. package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
  222. package/dist/session/hierarchy/actor.d.ts +26 -0
  223. package/dist/session/hierarchy/actor.d.ts.map +1 -0
  224. package/dist/session/hierarchy/actor.js +2 -0
  225. package/dist/session/hierarchy/actor.js.map +1 -0
  226. package/dist/session/hierarchy/index.d.ts +9 -0
  227. package/dist/session/hierarchy/index.d.ts.map +1 -0
  228. package/dist/session/hierarchy/index.js +4 -0
  229. package/dist/session/hierarchy/index.js.map +1 -0
  230. package/dist/session/hierarchy/lineage.d.ts +15 -0
  231. package/dist/session/hierarchy/lineage.d.ts.map +1 -0
  232. package/dist/session/hierarchy/lineage.js +2 -0
  233. package/dist/session/hierarchy/lineage.js.map +1 -0
  234. package/dist/session/hierarchy/project.d.ts +40 -0
  235. package/dist/session/hierarchy/project.d.ts.map +1 -0
  236. package/dist/session/hierarchy/project.js +2 -0
  237. package/dist/session/hierarchy/project.js.map +1 -0
  238. package/dist/session/hierarchy/session.d.ts +71 -0
  239. package/dist/session/hierarchy/session.d.ts.map +1 -0
  240. package/dist/session/hierarchy/session.js +51 -0
  241. package/dist/session/hierarchy/session.js.map +1 -0
  242. package/dist/session/hierarchy/sub-session.d.ts +76 -0
  243. package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
  244. package/dist/session/hierarchy/sub-session.js +2 -0
  245. package/dist/session/hierarchy/sub-session.js.map +1 -0
  246. package/dist/session/hierarchy/tenant.d.ts +13 -0
  247. package/dist/session/hierarchy/tenant.d.ts.map +1 -0
  248. package/dist/session/hierarchy/tenant.js +2 -0
  249. package/dist/session/hierarchy/tenant.js.map +1 -0
  250. package/dist/session/hierarchy/thread.d.ts +54 -0
  251. package/dist/session/hierarchy/thread.d.ts.map +1 -0
  252. package/dist/session/hierarchy/thread.js +2 -0
  253. package/dist/session/hierarchy/thread.js.map +1 -0
  254. package/dist/session/index.d.ts +10 -0
  255. package/dist/session/index.d.ts.map +1 -0
  256. package/dist/session/index.js +15 -0
  257. package/dist/session/index.js.map +1 -0
  258. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
  259. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
  260. package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
  261. package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
  262. package/dist/session/intervention/index.d.ts +3 -0
  263. package/dist/session/intervention/index.d.ts.map +1 -0
  264. package/dist/session/intervention/index.js +8 -0
  265. package/dist/session/intervention/index.js.map +1 -0
  266. package/dist/session/intervention/prev-artifact.d.ts +103 -0
  267. package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
  268. package/dist/session/intervention/prev-artifact.js +112 -0
  269. package/dist/session/intervention/prev-artifact.js.map +1 -0
  270. package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
  271. package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
  272. package/dist/session/migration/__tests__/filesystem.test.js +188 -0
  273. package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
  274. package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
  275. package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
  276. package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
  277. package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
  278. package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
  279. package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
  280. package/dist/session/migration/__tests__/marker.test.js +75 -0
  281. package/dist/session/migration/__tests__/marker.test.js.map +1 -0
  282. package/dist/session/migration/errors.d.ts +26 -0
  283. package/dist/session/migration/errors.d.ts.map +1 -0
  284. package/dist/session/migration/errors.js +22 -0
  285. package/dist/session/migration/errors.js.map +1 -0
  286. package/dist/session/migration/filesystem.d.ts +94 -0
  287. package/dist/session/migration/filesystem.d.ts.map +1 -0
  288. package/dist/session/migration/filesystem.js +319 -0
  289. package/dist/session/migration/filesystem.js.map +1 -0
  290. package/dist/session/migration/id-prefix.d.ts +93 -0
  291. package/dist/session/migration/id-prefix.d.ts.map +1 -0
  292. package/dist/session/migration/id-prefix.js +111 -0
  293. package/dist/session/migration/id-prefix.js.map +1 -0
  294. package/dist/session/migration/index.d.ts +8 -0
  295. package/dist/session/migration/index.d.ts.map +1 -0
  296. package/dist/session/migration/index.js +8 -0
  297. package/dist/session/migration/index.js.map +1 -0
  298. package/dist/session/migration/marker.d.ts +57 -0
  299. package/dist/session/migration/marker.d.ts.map +1 -0
  300. package/dist/session/migration/marker.js +111 -0
  301. package/dist/session/migration/marker.js.map +1 -0
  302. package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
  303. package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
  304. package/dist/session/retention/__tests__/archive.test.js +253 -0
  305. package/dist/session/retention/__tests__/archive.test.js.map +1 -0
  306. package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
  307. package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
  308. package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
  309. package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
  310. package/dist/session/retention/archive-backend-ref.d.ts +18 -0
  311. package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
  312. package/dist/session/retention/archive-backend-ref.js +2 -0
  313. package/dist/session/retention/archive-backend-ref.js.map +1 -0
  314. package/dist/session/retention/archive.d.ts +130 -0
  315. package/dist/session/retention/archive.d.ts.map +1 -0
  316. package/dist/session/retention/archive.js +203 -0
  317. package/dist/session/retention/archive.js.map +1 -0
  318. package/dist/session/retention/backend.d.ts +101 -0
  319. package/dist/session/retention/backend.d.ts.map +1 -0
  320. package/dist/session/retention/backend.js +15 -0
  321. package/dist/session/retention/backend.js.map +1 -0
  322. package/dist/session/retention/disk-backend.d.ts +59 -0
  323. package/dist/session/retention/disk-backend.d.ts.map +1 -0
  324. package/dist/session/retention/disk-backend.js +236 -0
  325. package/dist/session/retention/disk-backend.js.map +1 -0
  326. package/dist/session/retention/index.d.ts +9 -0
  327. package/dist/session/retention/index.d.ts.map +1 -0
  328. package/dist/session/retention/index.js +6 -0
  329. package/dist/session/retention/index.js.map +1 -0
  330. package/dist/session/retention/policy.d.ts +49 -0
  331. package/dist/session/retention/policy.d.ts.map +1 -0
  332. package/dist/session/retention/policy.js +21 -0
  333. package/dist/session/retention/policy.js.map +1 -0
  334. package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
  335. package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
  336. package/dist/session/summary/__tests__/materialize.test.js +270 -0
  337. package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
  338. package/dist/session/summary/deliverable.d.ts +74 -0
  339. package/dist/session/summary/deliverable.d.ts.map +1 -0
  340. package/dist/session/summary/deliverable.js +20 -0
  341. package/dist/session/summary/deliverable.js.map +1 -0
  342. package/dist/session/summary/index.d.ts +6 -0
  343. package/dist/session/summary/index.d.ts.map +1 -0
  344. package/dist/session/summary/index.js +9 -0
  345. package/dist/session/summary/index.js.map +1 -0
  346. package/dist/session/summary/materialize.d.ts +82 -0
  347. package/dist/session/summary/materialize.d.ts.map +1 -0
  348. package/dist/session/summary/materialize.js +117 -0
  349. package/dist/session/summary/materialize.js.map +1 -0
  350. package/dist/session/summary/ref.d.ts +91 -0
  351. package/dist/session/summary/ref.d.ts.map +1 -0
  352. package/dist/session/summary/ref.js +51 -0
  353. package/dist/session/summary/ref.js.map +1 -0
  354. package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
  355. package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
  356. package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
  357. package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
  358. package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
  359. package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
  360. package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
  361. package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
  362. package/dist/session/workspace/driver.d.ts +55 -0
  363. package/dist/session/workspace/driver.d.ts.map +1 -0
  364. package/dist/session/workspace/driver.js +12 -0
  365. package/dist/session/workspace/driver.js.map +1 -0
  366. package/dist/session/workspace/git-worktree.d.ts +65 -0
  367. package/dist/session/workspace/git-worktree.d.ts.map +1 -0
  368. package/dist/session/workspace/git-worktree.js +156 -0
  369. package/dist/session/workspace/git-worktree.js.map +1 -0
  370. package/dist/session/workspace/index.d.ts +8 -0
  371. package/dist/session/workspace/index.d.ts.map +1 -0
  372. package/dist/session/workspace/index.js +7 -0
  373. package/dist/session/workspace/index.js.map +1 -0
  374. package/dist/session/workspace/path-builder.d.ts +50 -0
  375. package/dist/session/workspace/path-builder.d.ts.map +1 -0
  376. package/dist/session/workspace/path-builder.js +50 -0
  377. package/dist/session/workspace/path-builder.js.map +1 -0
  378. package/dist/session/workspace/ref.d.ts +46 -0
  379. package/dist/session/workspace/ref.d.ts.map +1 -0
  380. package/dist/session/workspace/ref.js +11 -0
  381. package/dist/session/workspace/ref.js.map +1 -0
  382. package/dist/session/workspace/registry.d.ts +26 -0
  383. package/dist/session/workspace/registry.d.ts.map +1 -0
  384. package/dist/session/workspace/registry.js +35 -0
  385. package/dist/session/workspace/registry.js.map +1 -0
  386. package/dist/store/index.d.ts +0 -2
  387. package/dist/store/index.d.ts.map +1 -1
  388. package/dist/store/index.js +0 -1
  389. package/dist/store/index.js.map +1 -1
  390. package/dist/store/session/__tests__/disk.test.d.ts +2 -0
  391. package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
  392. package/dist/store/session/__tests__/disk.test.js +267 -0
  393. package/dist/store/session/__tests__/disk.test.js.map +1 -0
  394. package/dist/store/session/__tests__/memory.test.d.ts +2 -0
  395. package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
  396. package/dist/store/session/__tests__/memory.test.js +258 -0
  397. package/dist/store/session/__tests__/memory.test.js.map +1 -0
  398. package/dist/store/session/disk.d.ts +86 -0
  399. package/dist/store/session/disk.d.ts.map +1 -0
  400. package/dist/store/session/disk.js +818 -0
  401. package/dist/store/session/disk.js.map +1 -0
  402. package/dist/store/session/index.d.ts +7 -0
  403. package/dist/store/session/index.d.ts.map +1 -0
  404. package/dist/store/session/index.js +10 -0
  405. package/dist/store/session/index.js.map +1 -0
  406. package/dist/store/session/linkage.d.ts +38 -0
  407. package/dist/store/session/linkage.d.ts.map +1 -0
  408. package/dist/store/session/linkage.js +64 -0
  409. package/dist/store/session/linkage.js.map +1 -0
  410. package/dist/store/session/memory.d.ts +49 -0
  411. package/dist/store/session/memory.d.ts.map +1 -0
  412. package/dist/store/session/memory.js +335 -0
  413. package/dist/store/session/memory.js.map +1 -0
  414. package/dist/store/session/messages.d.ts +20 -0
  415. package/dist/store/session/messages.d.ts.map +1 -0
  416. package/dist/store/session/messages.js +12 -0
  417. package/dist/store/session/messages.js.map +1 -0
  418. package/dist/store/thread/disk.d.ts +41 -0
  419. package/dist/store/thread/disk.d.ts.map +1 -0
  420. package/dist/store/thread/disk.js +229 -0
  421. package/dist/store/thread/disk.js.map +1 -0
  422. package/dist/store/thread/index.d.ts +4 -0
  423. package/dist/store/thread/index.d.ts.map +1 -0
  424. package/dist/store/thread/index.js +6 -0
  425. package/dist/store/thread/index.js.map +1 -0
  426. package/dist/store/thread/memory.d.ts +23 -0
  427. package/dist/store/thread/memory.d.ts.map +1 -0
  428. package/dist/store/thread/memory.js +90 -0
  429. package/dist/store/thread/memory.js.map +1 -0
  430. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
  431. package/dist/types/agent/base.d.ts +24 -1
  432. package/dist/types/agent/base.d.ts.map +1 -1
  433. package/dist/types/agent/factory.d.ts +8 -2
  434. package/dist/types/agent/factory.d.ts.map +1 -1
  435. package/dist/types/agent/task.d.ts +57 -2
  436. package/dist/types/agent/task.d.ts.map +1 -1
  437. package/dist/types/agent/task.js.map +1 -1
  438. package/dist/types/ids/index.d.ts +22 -3
  439. package/dist/types/ids/index.d.ts.map +1 -1
  440. package/dist/types/ids/index.js +8 -1
  441. package/dist/types/ids/index.js.map +1 -1
  442. package/dist/types/invocation/__tests__/state.test.js +36 -29
  443. package/dist/types/invocation/__tests__/state.test.js.map +1 -1
  444. package/dist/types/invocation/index.d.ts +20 -4
  445. package/dist/types/invocation/index.d.ts.map +1 -1
  446. package/dist/types/invocation/index.js +10 -7
  447. package/dist/types/invocation/index.js.map +1 -1
  448. package/dist/types/rag/retrieval.d.ts +4 -3
  449. package/dist/types/rag/retrieval.d.ts.map +1 -1
  450. package/dist/types/run/config.d.ts +12 -1
  451. package/dist/types/run/config.d.ts.map +1 -1
  452. package/dist/types/run/events.d.ts +26 -1
  453. package/dist/types/run/events.d.ts.map +1 -1
  454. package/dist/types/run/index.d.ts.map +1 -1
  455. package/dist/types/run/index.js +8 -0
  456. package/dist/types/run/index.js.map +1 -1
  457. package/dist/types/run/metadata.d.ts +12 -2
  458. package/dist/types/run/metadata.d.ts.map +1 -1
  459. package/dist/types/run/status.d.ts +26 -0
  460. package/dist/types/run/status.d.ts.map +1 -0
  461. package/dist/types/run/status.js +2 -0
  462. package/dist/types/run/status.js.map +1 -0
  463. package/dist/types/session/ids.d.ts +9 -0
  464. package/dist/types/session/ids.d.ts.map +1 -0
  465. package/dist/types/session/ids.js +9 -0
  466. package/dist/types/session/ids.js.map +1 -0
  467. package/dist/types/session/index.d.ts +3 -0
  468. package/dist/types/session/index.d.ts.map +1 -0
  469. package/dist/types/session/index.js +5 -0
  470. package/dist/types/session/index.js.map +1 -0
  471. package/dist/types/session/store.d.ts +210 -0
  472. package/dist/types/session/store.d.ts.map +1 -0
  473. package/dist/types/session/store.js +9 -0
  474. package/dist/types/session/store.js.map +1 -0
  475. package/dist/types/thread/index.d.ts +2 -0
  476. package/dist/types/thread/index.d.ts.map +1 -0
  477. package/dist/types/thread/index.js +5 -0
  478. package/dist/types/thread/index.js.map +1 -0
  479. package/dist/types/thread/store.d.ts +86 -0
  480. package/dist/types/thread/store.d.ts.map +1 -0
  481. package/dist/types/thread/store.js +22 -0
  482. package/dist/types/thread/store.js.map +1 -0
  483. package/dist/utils/id.d.ts +8 -2
  484. package/dist/utils/id.d.ts.map +1 -1
  485. package/dist/utils/id.js +22 -4
  486. package/dist/utils/id.js.map +1 -1
  487. package/package.json +6 -11
  488. package/src/agents/ReactiveAgent.ts +7 -2
  489. package/src/agents/RouterAgent.ts +5 -0
  490. package/src/agents/SupervisorAgent.ts +29 -6
  491. package/src/bridge/a2a/index.ts +0 -1
  492. package/src/bridge/a2a/mapper.ts +7 -0
  493. package/src/bridge/a2a/message.ts +0 -32
  494. package/src/bridge/a2a/task.ts +9 -8
  495. package/src/bridge/sse/mapper.ts +8 -1
  496. package/src/constants/a2a/index.ts +2 -2
  497. package/src/contracts/api.ts +14 -30
  498. package/src/contracts/ids.ts +1 -1
  499. package/src/contracts/index.ts +3 -7
  500. package/src/contracts/schemas.ts +1 -8
  501. package/src/gateway/local.ts +6 -0
  502. package/src/index.ts +14 -4
  503. package/src/manager/agent/__tests__/lifecycle.test.ts +473 -0
  504. package/src/manager/agent/lifecycle.ts +515 -21
  505. package/src/manager/index.ts +3 -0
  506. package/src/manager/run/persistence.ts +26 -1
  507. package/src/manager/thread/__tests__/lifecycle.test.ts +286 -0
  508. package/src/manager/thread/lifecycle.ts +217 -0
  509. package/src/rag/retriever.ts +2 -2
  510. package/src/run/reporter.ts +28 -0
  511. package/src/runtime/query/__tests__/context.test.ts +102 -0
  512. package/src/runtime/query/context-cache.ts +4 -4
  513. package/src/runtime/query/context.ts +98 -9
  514. package/src/runtime/query/events.ts +8 -0
  515. package/src/runtime/query/index.ts +38 -1
  516. package/src/session/__tests__/integration/_fixtures.ts +310 -0
  517. package/src/session/__tests__/integration/archive-gate.test.ts +288 -0
  518. package/src/session/__tests__/integration/capacity-caps.test.ts +171 -0
  519. package/src/session/__tests__/integration/e2e-spawn.test.ts +296 -0
  520. package/src/session/__tests__/integration/event-stream-ordering.test.ts +410 -0
  521. package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +271 -0
  522. package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +214 -0
  523. package/src/session/__tests__/integration/handoff-single-e2e.test.ts +251 -0
  524. package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +240 -0
  525. package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
  526. package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
  527. package/src/session/__tests__/integration/prev-artifact-dag.test.ts +325 -0
  528. package/src/session/__tests__/integration/retention-archive.test.ts +233 -0
  529. package/src/session/__tests__/integration/spawn-rollback.test.ts +313 -0
  530. package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +239 -0
  531. package/src/session/__tests__/integration/tenant-isolation.test.ts +292 -0
  532. package/src/session/errors.ts +159 -0
  533. package/src/session/events/index.ts +16 -0
  534. package/src/session/events/schema-version.ts +13 -0
  535. package/src/session/events/types.ts +71 -0
  536. package/src/session/handoff/__tests__/broadcast.test.ts +378 -0
  537. package/src/session/handoff/__tests__/capacity.test.ts +129 -0
  538. package/src/session/handoff/__tests__/single.test.ts +333 -0
  539. package/src/session/handoff/assignment.ts +74 -0
  540. package/src/session/handoff/broadcast.ts +406 -0
  541. package/src/session/handoff/capacity.ts +121 -0
  542. package/src/session/handoff/events.ts +72 -0
  543. package/src/session/handoff/index.ts +29 -0
  544. package/src/session/handoff/single.ts +310 -0
  545. package/src/session/handoff/version.ts +59 -0
  546. package/src/session/hierarchy/__tests__/session.test.ts +100 -0
  547. package/src/session/hierarchy/actor.ts +17 -0
  548. package/src/session/hierarchy/index.ts +18 -0
  549. package/src/session/hierarchy/lineage.ts +15 -0
  550. package/src/session/hierarchy/project.ts +41 -0
  551. package/src/session/hierarchy/session.ts +109 -0
  552. package/src/session/hierarchy/sub-session.ts +92 -0
  553. package/src/session/hierarchy/tenant.ts +13 -0
  554. package/src/session/hierarchy/thread.ts +55 -0
  555. package/src/session/index.ts +15 -0
  556. package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
  557. package/src/session/intervention/index.ts +16 -0
  558. package/src/session/intervention/prev-artifact.ts +180 -0
  559. package/src/session/migration/__tests__/filesystem.test.ts +263 -0
  560. package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
  561. package/src/session/migration/__tests__/marker.test.ts +84 -0
  562. package/src/session/migration/errors.ts +23 -0
  563. package/src/session/migration/filesystem.ts +401 -0
  564. package/src/session/migration/id-prefix.ts +141 -0
  565. package/src/session/migration/index.ts +38 -0
  566. package/src/session/migration/marker.ts +131 -0
  567. package/src/session/retention/__tests__/archive.test.ts +318 -0
  568. package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
  569. package/src/session/retention/archive-backend-ref.ts +17 -0
  570. package/src/session/retention/archive.ts +281 -0
  571. package/src/session/retention/backend.ts +107 -0
  572. package/src/session/retention/disk-backend.ts +304 -0
  573. package/src/session/retention/index.ts +16 -0
  574. package/src/session/retention/policy.ts +53 -0
  575. package/src/session/summary/__tests__/materialize.test.ts +343 -0
  576. package/src/session/summary/deliverable.ts +84 -0
  577. package/src/session/summary/index.ts +31 -0
  578. package/src/session/summary/materialize.ts +169 -0
  579. package/src/session/summary/ref.ts +104 -0
  580. package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
  581. package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
  582. package/src/session/workspace/driver.ts +60 -0
  583. package/src/session/workspace/git-worktree.ts +209 -0
  584. package/src/session/workspace/index.ts +25 -0
  585. package/src/session/workspace/path-builder.ts +71 -0
  586. package/src/session/workspace/ref.ts +50 -0
  587. package/src/session/workspace/registry.ts +42 -0
  588. package/src/store/index.ts +0 -3
  589. package/src/store/session/__tests__/disk.test.ts +397 -0
  590. package/src/store/session/__tests__/memory.test.ts +402 -0
  591. package/src/store/session/disk.ts +976 -0
  592. package/src/store/session/index.ts +13 -0
  593. package/src/store/session/linkage.ts +80 -0
  594. package/src/store/session/memory.ts +412 -0
  595. package/src/store/session/messages.ts +21 -0
  596. package/src/store/thread/disk.ts +261 -0
  597. package/src/store/thread/index.ts +7 -0
  598. package/src/store/thread/memory.ts +104 -0
  599. package/src/types/agent/base.ts +27 -1
  600. package/src/types/agent/factory.ts +8 -3
  601. package/src/types/agent/task.ts +66 -2
  602. package/src/types/ids/index.ts +34 -3
  603. package/src/types/invocation/__tests__/state.test.ts +37 -29
  604. package/src/types/invocation/index.ts +26 -10
  605. package/src/types/rag/retrieval.ts +4 -3
  606. package/src/types/run/config.ts +13 -1
  607. package/src/types/run/events.ts +36 -1
  608. package/src/types/run/index.ts +8 -0
  609. package/src/types/run/metadata.ts +12 -2
  610. package/src/types/run/status.ts +33 -0
  611. package/src/types/session/ids.ts +23 -0
  612. package/src/types/session/index.ts +27 -0
  613. package/src/types/session/store.ts +252 -0
  614. package/src/types/thread/index.ts +5 -0
  615. package/src/types/thread/store.ts +92 -0
  616. package/src/utils/id.ts +34 -4
  617. package/dist/store/conversation/memory.d.ts +0 -21
  618. package/dist/store/conversation/memory.d.ts.map +0 -1
  619. package/dist/store/conversation/memory.js +0 -86
  620. package/dist/store/conversation/memory.js.map +0 -1
  621. package/dist/types/conversation/index.d.ts +0 -7
  622. package/dist/types/conversation/index.d.ts.map +0 -1
  623. package/dist/types/conversation/index.js +0 -2
  624. package/dist/types/conversation/index.js.map +0 -1
  625. package/src/store/conversation/memory.ts +0 -121
  626. package/src/types/conversation/index.ts +0 -8
@@ -0,0 +1,16 @@
1
+ // Sub-barrel for session-hierarchy run-event surface.
2
+ // Convention #4: concrete types live in sibling files; re-export them here.
3
+ //
4
+ // Phase 2 scope is limited to the sub-session lifecycle variants that are
5
+ // spliced into `RunEvent`. A dedicated `SessionHierarchyEvent` top-level
6
+ // union lands in a later phase (see session-hierarchy.md §10.2).
7
+
8
+ export { RUN_EVENT_SCHEMA_VERSION } from './schema-version.js'
9
+ export type { RunEventSchemaVersion } from './schema-version.js'
10
+
11
+ export type {
12
+ SubsessionSpawnedEvent,
13
+ SubsessionMessagedEvent,
14
+ SubsessionIdledEvent,
15
+ SubsessionLifecycleEvent,
16
+ } from './types.js'
@@ -0,0 +1,13 @@
1
+ /**
2
+ * RunEvent envelope schema version. Bumped on breaking envelope change.
3
+ *
4
+ * - v1: pre-0.2.0 (implicit; untagged events are treated as v1 by consumers).
5
+ * - v2: 0.2.0+ — adds `schemaVersion`, `lineage`, and sub-session lifecycle
6
+ * events.
7
+ *
8
+ * See session-hierarchy.md §10.1 (Event-schema evolution contract) and
9
+ * §13.3.2 (`schemaVersion` back-compat).
10
+ */
11
+ export const RUN_EVENT_SCHEMA_VERSION = 2 as const
12
+
13
+ export type RunEventSchemaVersion = typeof RUN_EVENT_SCHEMA_VERSION
@@ -0,0 +1,71 @@
1
+ import type { MessageId, RunId, SessionId } from '../../types/ids/index.js'
2
+ import type { SubSessionId } from '../../types/session/ids.js'
3
+ import type { ActorRef } from '../hierarchy/actor.js'
4
+ import type { Lineage } from '../hierarchy/lineage.js'
5
+ import type { RunEventSchemaVersion } from './schema-version.js'
6
+
7
+ /**
8
+ * Sub-session lifecycle events that splice into {@link RunEvent}.
9
+ *
10
+ * See session-hierarchy.md §10.4 (Parent-Child Linkage). These cover the
11
+ * in-flight visibility gap that the terminal-only `SessionSummaryRef` does
12
+ * not address. Every sub-session emission carries the full {@link Lineage}
13
+ * chain — consumers can reconstruct the delegation tree without walking the
14
+ * store (§10.4 invariant).
15
+ *
16
+ * Note: these events are spliced into the `RunEvent` union in
17
+ * `types/run/events.ts` rather than kept as a separate top-level union.
18
+ * A dedicated `SessionHierarchyEvent` top-level type lands in Phase 3+.
19
+ */
20
+
21
+ /**
22
+ * Emitted when the kernel creates a new sub-session. Precedes the child
23
+ * session's `run_started`. See §10.4 / §10.5 example stream.
24
+ */
25
+ export interface SubsessionSpawnedEvent {
26
+ type: 'subsession_spawned'
27
+ runId: RunId
28
+ subSessionId: SubSessionId
29
+ parentSessionId: SessionId
30
+ spawnedBy: ActorRef
31
+ lineage: Lineage
32
+ schemaVersion: RunEventSchemaVersion
33
+ at: Date
34
+ }
35
+
36
+ /**
37
+ * Emitted each time the child session's Run appends a message. Gives parents
38
+ * and platform consumers in-flight visibility without requiring a drill into
39
+ * the child transcript. See §10.4.
40
+ */
41
+ export interface SubsessionMessagedEvent {
42
+ type: 'subsession_messaged'
43
+ runId: RunId
44
+ subSessionId: SubSessionId
45
+ parentSessionId: SessionId
46
+ messageId: MessageId
47
+ lineage: Lineage
48
+ schemaVersion: RunEventSchemaVersion
49
+ at: Date
50
+ }
51
+
52
+ /**
53
+ * Emitted when the child session transitions to `idle` (terminal persistent
54
+ * state per §5.3 — sub-sessions never close). A separate
55
+ * `sub_session.summarized` event carries the `SessionSummaryRef` (§8); this
56
+ * event only reports the lifecycle transition.
57
+ */
58
+ export interface SubsessionIdledEvent {
59
+ type: 'subsession_idled'
60
+ runId: RunId
61
+ subSessionId: SubSessionId
62
+ parentSessionId: SessionId
63
+ lineage: Lineage
64
+ schemaVersion: RunEventSchemaVersion
65
+ at: Date
66
+ }
67
+
68
+ export type SubsessionLifecycleEvent =
69
+ | SubsessionSpawnedEvent
70
+ | SubsessionMessagedEvent
71
+ | SubsessionIdledEvent
@@ -0,0 +1,378 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { ThreadManager } from '../../../manager/thread/lifecycle.js'
3
+ import type { ActorRef } from '../../../session/hierarchy/actor.js'
4
+ import {
5
+ type ExecFile,
6
+ type ExecFileResult,
7
+ GitWorktreeDriver,
8
+ } from '../../../session/workspace/git-worktree.js'
9
+ import { WorkspaceBackendRegistry } from '../../../session/workspace/registry.js'
10
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
11
+ import { InMemoryThreadStore } from '../../../store/thread/memory.js'
12
+ import type { SessionId, TenantId, UserId } from '../../../types/ids/index.js'
13
+ import type { ProjectId } from '../../../types/session/ids.js'
14
+ import { generateHandoffId } from '../../../utils/id.js'
15
+ import type { HandoffAssignment } from '../assignment.js'
16
+ import { type BroadcastHandoffDeps, executeBroadcastHandoff } from '../broadcast.js'
17
+ import { DefaultCapacityValidator } from '../capacity.js'
18
+ import type {
19
+ HandoffBroadcastRollbackEvent,
20
+ HandoffCommittedEvent,
21
+ HandoffEventSink,
22
+ HandoffLockedEvent,
23
+ HandoffUnlockedEvent,
24
+ } from '../events.js'
25
+ import { HandoffVersionConflict } from '../version.js'
26
+
27
+ const tenant = 'tnt_alpha' as TenantId
28
+
29
+ function stubLogger() {
30
+ return {
31
+ debug: vi.fn(),
32
+ info: vi.fn(),
33
+ warn: vi.fn(),
34
+ error: vi.fn(),
35
+ child() {
36
+ return stubLogger()
37
+ },
38
+ }
39
+ }
40
+
41
+ function okExec(stdout = '', stderr = ''): ExecFileResult {
42
+ return { stdout, stderr }
43
+ }
44
+
45
+ function user(userId: string): ActorRef {
46
+ return { kind: 'user', userId: userId as UserId, tenantId: tenant }
47
+ }
48
+
49
+ interface MockedHandoffEventSink extends HandoffEventSink {
50
+ onLocked: ReturnType<typeof vi.fn<(ev: HandoffLockedEvent) => void>>
51
+ onUnlocked: ReturnType<typeof vi.fn<(ev: HandoffUnlockedEvent) => void>>
52
+ onCommitted: ReturnType<typeof vi.fn<(ev: HandoffCommittedEvent) => void>>
53
+ onBroadcastRollback: ReturnType<typeof vi.fn<(ev: HandoffBroadcastRollbackEvent) => void>>
54
+ }
55
+
56
+ interface DepsBundle {
57
+ deps: BroadcastHandoffDeps
58
+ events: MockedHandoffEventSink
59
+ }
60
+
61
+ function buildDeps(
62
+ store: InMemorySessionStore,
63
+ threadStore: InMemoryThreadStore,
64
+ execOverride?: ExecFile,
65
+ ): DepsBundle {
66
+ const exec: ExecFile = execOverride ? execOverride : async (_file, _args) => okExec()
67
+ const driver = new GitWorktreeDriver({
68
+ repoRoot: '/repo',
69
+ logger: stubLogger(),
70
+ execFile: exec,
71
+ })
72
+ const registry = new WorkspaceBackendRegistry()
73
+ registry.register(driver)
74
+
75
+ const events: MockedHandoffEventSink = {
76
+ onLocked: vi.fn<(ev: HandoffLockedEvent) => void>(),
77
+ onUnlocked: vi.fn<(ev: HandoffUnlockedEvent) => void>(),
78
+ onCommitted: vi.fn<(ev: HandoffCommittedEvent) => void>(),
79
+ onBroadcastRollback: vi.fn<(ev: HandoffBroadcastRollbackEvent) => void>(),
80
+ }
81
+
82
+ const threadManager = new ThreadManager({ threadStore, sessionStore: store })
83
+ return {
84
+ deps: {
85
+ store,
86
+ workspaceRegistry: registry,
87
+ capacity: new DefaultCapacityValidator(store),
88
+ events,
89
+ threadManager,
90
+ },
91
+ events,
92
+ }
93
+ }
94
+
95
+ async function seedIdle(store: InMemorySessionStore, threadStore: InMemoryThreadStore) {
96
+ const project = await store.createProject({ tenantId: tenant, name: 'p' }, tenant)
97
+ const thread = await threadStore.createThread(
98
+ { projectId: project.id, title: 'handoff-broadcast-test' },
99
+ tenant,
100
+ )
101
+ const session = await store.createSession(
102
+ { threadId: thread.id, projectId: project.id, currentActor: user('usr_source') },
103
+ tenant,
104
+ )
105
+ return { project, thread, session }
106
+ }
107
+
108
+ function buildAssignments(
109
+ sourceSessionId: SessionId,
110
+ projectId: ProjectId,
111
+ threadId: Awaited<ReturnType<InMemoryThreadStore['createThread']>>['id'],
112
+ expectedOwnerVersion: number,
113
+ recipients: ActorRef[],
114
+ broadcastId = 'bc_1',
115
+ ): HandoffAssignment[] {
116
+ return recipients.map((recipientActor) => ({
117
+ id: generateHandoffId(),
118
+ mode: 'broadcast' as const,
119
+ sourceSessionId,
120
+ tenantId: tenant,
121
+ threadId,
122
+ projectId,
123
+ sourceActor: user('usr_source'),
124
+ recipientActor,
125
+ expectedOwnerVersion,
126
+ broadcastId,
127
+ createdAt: new Date('2026-02-01'),
128
+ }))
129
+ }
130
+
131
+ describe('executeBroadcastHandoff', () => {
132
+ let store: InMemorySessionStore
133
+ let threadStore: InMemoryThreadStore
134
+
135
+ beforeEach(() => {
136
+ store = new InMemorySessionStore()
137
+ threadStore = new InMemoryThreadStore()
138
+ })
139
+
140
+ it('happy path: 3 recipients → source ends in awaiting_merge with 3 new children', async () => {
141
+ const { project, thread, session } = await seedIdle(store, threadStore)
142
+ const { deps, events } = buildDeps(store, threadStore)
143
+
144
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
145
+ user('usr_bob'),
146
+ user('usr_carol'),
147
+ user('usr_dan'),
148
+ ])
149
+
150
+ const outcomes = await executeBroadcastHandoff(deps, assignments, tenant)
151
+ expect(outcomes).toHaveLength(3)
152
+ expect(new Set(outcomes.map((o) => o.newSessionId)).size).toBe(3)
153
+ expect(outcomes.every((o) => o.committedOwnerVersion === 1)).toBe(true)
154
+
155
+ const reloaded = await store.getSession(session.id, tenant)
156
+ expect(reloaded?.status).toBe('awaiting_merge')
157
+ expect(reloaded?.ownerVersion).toBe(1)
158
+
159
+ const children = await store.getChildren(session.id, tenant)
160
+ expect(children).toHaveLength(3)
161
+
162
+ expect(events.onLocked).toHaveBeenCalledTimes(1)
163
+ expect(events.onCommitted).toHaveBeenCalledTimes(1)
164
+ expect(events.onBroadcastRollback).not.toHaveBeenCalled()
165
+ })
166
+
167
+ it('rollback on mid-fan-out failure (2nd recipient worktree add fails): source reverts, rollback emits accurate partialState', async () => {
168
+ const { project, thread, session } = await seedIdle(store, threadStore)
169
+
170
+ let addCount = 0
171
+ const exec: ExecFile = async (_file, args) => {
172
+ if (args.includes('add')) {
173
+ addCount += 1
174
+ if (addCount === 2) throw new Error('simulated mid-fanout failure')
175
+ }
176
+ return okExec()
177
+ }
178
+ const { deps, events } = buildDeps(store, threadStore, exec)
179
+
180
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
181
+ user('usr_b'),
182
+ user('usr_c'),
183
+ user('usr_d'),
184
+ ])
185
+
186
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
187
+ /Workspace backend git-worktree failed on create/,
188
+ )
189
+
190
+ const reloaded = await store.getSession(session.id, tenant)
191
+ expect(reloaded?.status).toBe('idle')
192
+ expect(reloaded?.ownerVersion).toBe(0)
193
+
194
+ // The first recipient got through all three sub-ops; the second failed
195
+ // during worktree provisioning. partialState reports:
196
+ // worktreesProvisioned: 1 (the first recipient's)
197
+ // subsessionsCreated: 1 (the first recipient's)
198
+ // assignmentsWritten: 1 (the first recipient's)
199
+ expect(events.onBroadcastRollback).toHaveBeenCalledTimes(1)
200
+ const rollbackCall = events.onBroadcastRollback.mock.calls[0]?.[0]
201
+ expect(rollbackCall).toBeDefined()
202
+ expect(rollbackCall?.partialState.worktreesProvisioned).toBe(1)
203
+ expect(rollbackCall?.partialState.subsessionsCreated).toBe(1)
204
+ expect(rollbackCall?.partialState.assignmentsWritten).toBe(1)
205
+ expect(rollbackCall?.broadcastId).toBe('bc_1')
206
+
207
+ // Phase 8: rollback now fully deletes partial records rather than
208
+ // flipping them to 'archived'. The source session has no children and
209
+ // no orphan child sessions remain under the project.
210
+ const children = await store.getChildren(session.id, tenant)
211
+ expect(children).toHaveLength(0)
212
+ })
213
+
214
+ it('rollback performs full cleanup via deleteSubSession/deleteSession (no status-flip stopgap)', async () => {
215
+ const { project, thread, session } = await seedIdle(store, threadStore)
216
+
217
+ let addCount = 0
218
+ const exec: ExecFile = async (_file, args) => {
219
+ if (args.includes('add')) {
220
+ addCount += 1
221
+ if (addCount === 2) throw new Error('simulated failure')
222
+ }
223
+ return okExec()
224
+ }
225
+ const { deps } = buildDeps(store, threadStore, exec)
226
+
227
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
228
+ user('usr_b'),
229
+ user('usr_c'),
230
+ ])
231
+
232
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow()
233
+
234
+ // No sub-session record remains.
235
+ const children = await store.getChildren(session.id, tenant)
236
+ expect(children).toHaveLength(0)
237
+
238
+ // Source is back to idle with its original ownerVersion (unchanged because
239
+ // the CAS commit never landed).
240
+ const reloaded = await store.getSession(session.id, tenant)
241
+ expect(reloaded?.status).toBe('idle')
242
+ expect(reloaded?.ownerVersion).toBe(0)
243
+ })
244
+
245
+ it('rollback idempotency: worktree dispose throwing during rollback does not bubble a secondary failure', async () => {
246
+ const { project, thread, session } = await seedIdle(store, threadStore)
247
+
248
+ let addCount = 0
249
+ let removeCount = 0
250
+ const exec: ExecFile = async (_file, args) => {
251
+ if (args.includes('add')) {
252
+ addCount += 1
253
+ if (addCount === 2) throw new Error('primary: mid-fanout add failure')
254
+ }
255
+ if (args.includes('remove')) {
256
+ removeCount += 1
257
+ // Throw an unclassified error so the regex in dispose does NOT treat
258
+ // it as idempotent success — exercises the outer try/catch in the
259
+ // rollback loop.
260
+ throw new Error('secondary rollback dispose failure (unexpected)')
261
+ }
262
+ return okExec()
263
+ }
264
+ const { deps, events } = buildDeps(store, threadStore, exec)
265
+
266
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
267
+ user('usr_b'),
268
+ user('usr_c'),
269
+ ])
270
+
271
+ // Outer failure is the PRIMARY one — the secondary dispose failure is
272
+ // swallowed. Primary wraps in WorkspaceBackendError (create op).
273
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
274
+ /Workspace backend git-worktree failed on create/,
275
+ )
276
+
277
+ expect(removeCount).toBeGreaterThanOrEqual(1)
278
+ expect(events.onBroadcastRollback).toHaveBeenCalledTimes(1)
279
+
280
+ // Source is idle (rollback succeeded at the store layer even if dispose
281
+ // partially failed).
282
+ const reloaded = await store.getSession(session.id, tenant)
283
+ expect(reloaded?.status).toBe('idle')
284
+ })
285
+
286
+ it('dedupe: two assignments targeting same recipient → rejected pre-lock (no side effects)', async () => {
287
+ const { project, thread, session } = await seedIdle(store, threadStore)
288
+ const { deps, events } = buildDeps(store, threadStore)
289
+
290
+ const bob = user('usr_bob')
291
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [
292
+ bob,
293
+ bob,
294
+ user('usr_dan'),
295
+ ])
296
+
297
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
298
+ /duplicate recipient/,
299
+ )
300
+
301
+ // Source never locked — no events fired.
302
+ expect(events.onLocked).not.toHaveBeenCalled()
303
+ expect(events.onCommitted).not.toHaveBeenCalled()
304
+ expect(events.onBroadcastRollback).not.toHaveBeenCalled()
305
+ const reloaded = await store.getSession(session.id, tenant)
306
+ expect(reloaded?.status).toBe('idle')
307
+ })
308
+
309
+ it('width cap: 9 recipients exceeds default maxWidth=8 → rejected before source lock', async () => {
310
+ const { project, thread, session } = await seedIdle(store, threadStore)
311
+ const { deps, events } = buildDeps(store, threadStore)
312
+
313
+ const recipients = Array.from({ length: 9 }, (_, i) => user(`usr_${i}`))
314
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, recipients)
315
+
316
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
317
+ /Delegation capacity exceeded/,
318
+ )
319
+ expect(events.onLocked).not.toHaveBeenCalled()
320
+ expect(events.onBroadcastRollback).not.toHaveBeenCalled()
321
+
322
+ const reloaded = await store.getSession(session.id, tenant)
323
+ expect(reloaded?.status).toBe('idle')
324
+ })
325
+
326
+ it('concurrent broadcast on same source: second attempt rejected with HandoffVersionConflict', async () => {
327
+ const { project, thread, session } = await seedIdle(store, threadStore)
328
+ const { deps } = buildDeps(store, threadStore)
329
+
330
+ const firstAssignments = buildAssignments(
331
+ session.id,
332
+ project.id,
333
+ thread.id,
334
+ 0,
335
+ [user('usr_b'), user('usr_c')],
336
+ 'bc_1',
337
+ )
338
+ await executeBroadcastHandoff(deps, firstAssignments, tenant)
339
+
340
+ // Second broadcast still has expectedOwnerVersion = 0 but source is now 1.
341
+ // It should also observe source.status === 'awaiting_merge' (non-idle) —
342
+ // that rejects with HandoffLockRejected BEFORE the CAS check fires. To
343
+ // exercise the CAS path, reset source to `idle` (simulating all recipients
344
+ // completing) and THEN attempt the second handoff with stale expected=0.
345
+ const reloaded = await store.getSession(session.id, tenant)
346
+ if (!reloaded) throw new Error('source missing')
347
+ await store.updateSession({ ...reloaded, status: 'idle' }, tenant)
348
+
349
+ const second = buildAssignments(
350
+ session.id,
351
+ project.id,
352
+ thread.id,
353
+ 0, // stale — actual is 1
354
+ [user('usr_d'), user('usr_e')],
355
+ 'bc_2',
356
+ )
357
+ await expect(executeBroadcastHandoff(deps, second, tenant)).rejects.toBeInstanceOf(
358
+ HandoffVersionConflict,
359
+ )
360
+ })
361
+
362
+ it('empty assignments → throws a descriptive error', async () => {
363
+ const { deps } = buildDeps(store, threadStore)
364
+ await expect(executeBroadcastHandoff(deps, [], tenant)).rejects.toThrow(
365
+ /assignments must not be empty/,
366
+ )
367
+ })
368
+
369
+ it('single-row broadcast → rejected (caller must use executeSingleHandoff)', async () => {
370
+ const { project, thread, session } = await seedIdle(store, threadStore)
371
+ const { deps } = buildDeps(store, threadStore)
372
+ const assignments = buildAssignments(session.id, project.id, thread.id, 0, [user('usr_b')])
373
+
374
+ await expect(executeBroadcastHandoff(deps, assignments, tenant)).rejects.toThrow(
375
+ /single-recipient handoffs must use executeSingleHandoff/,
376
+ )
377
+ })
378
+ })
@@ -0,0 +1,129 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { ActorRef } from '../../../session/hierarchy/actor.js'
3
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
4
+ import { InMemoryThreadStore } from '../../../store/thread/memory.js'
5
+ import type { AgentId, SessionId, TenantId, UserId } from '../../../types/ids/index.js'
6
+ import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
7
+ import { DefaultCapacityValidator, DelegationCapacityExceeded } from '../capacity.js'
8
+
9
+ const tenant = 'tnt_alpha' as TenantId
10
+
11
+ function user(): ActorRef {
12
+ return { kind: 'user', userId: 'usr_a' as UserId, tenantId: tenant }
13
+ }
14
+
15
+ function agent(): ActorRef {
16
+ return { kind: 'agent', agentId: 'agt_a' as AgentId, tenantId: tenant }
17
+ }
18
+
19
+ async function seedProject(store: InMemorySessionStore) {
20
+ const project = await store.createProject({ tenantId: tenant, name: 'p' }, tenant)
21
+ const threadStore = new InMemoryThreadStore()
22
+ const thread = await threadStore.createThread({ projectId: project.id, title: 'default' }, tenant)
23
+ const root = await store.createSession(
24
+ { threadId: thread.id, projectId: project.id, currentActor: user() },
25
+ tenant,
26
+ )
27
+ return { project, thread, root }
28
+ }
29
+
30
+ async function spawnChild(
31
+ store: InMemorySessionStore,
32
+ parentId: SessionId,
33
+ projectId: ProjectId,
34
+ threadId: ThreadId,
35
+ ): Promise<{ childId: SessionId }> {
36
+ const child = await store.createSession({ threadId, projectId, currentActor: user() }, tenant)
37
+ await store.createSubSession(
38
+ {
39
+ parentSessionId: parentId,
40
+ childSessionId: child.id,
41
+ kind: 'agent_spawn',
42
+ spawnedBy: agent(),
43
+ },
44
+ tenant,
45
+ )
46
+ return { childId: child.id }
47
+ }
48
+
49
+ describe('DefaultCapacityValidator', () => {
50
+ it('depth: root session validates against limit 4 (new child would be depth 1) — passes', async () => {
51
+ const store = new InMemorySessionStore()
52
+ const { root } = await seedProject(store)
53
+ const validator = new DefaultCapacityValidator(store)
54
+
55
+ await expect(validator.validateDepth(root.id, 4, tenant)).resolves.toBeUndefined()
56
+ })
57
+
58
+ it('depth: chain of 4 (root→c1→c2→c3→c4) allows a 5th (depth 5) to pass when limit = 5', async () => {
59
+ const store = new InMemorySessionStore()
60
+ const { project, thread, root } = await seedProject(store)
61
+ const c1 = await spawnChild(store, root.id, project.id, thread.id)
62
+ const c2 = await spawnChild(store, c1.childId, project.id, thread.id)
63
+ const c3 = await spawnChild(store, c2.childId, project.id, thread.id)
64
+ const c4 = await spawnChild(store, c3.childId, project.id, thread.id)
65
+
66
+ const validator = new DefaultCapacityValidator(store)
67
+ // Ancestry of c4: root→c1→c2→c3→c4 = length 5. Spawning under c4 = depth 5.
68
+ await expect(validator.validateDepth(c4.childId, 5, tenant)).resolves.toBeUndefined()
69
+ })
70
+
71
+ it('depth: over-limit throws DelegationCapacityExceeded with dimension=depth', async () => {
72
+ const store = new InMemorySessionStore()
73
+ const { project, thread, root } = await seedProject(store)
74
+ const c1 = await spawnChild(store, root.id, project.id, thread.id)
75
+ const c2 = await spawnChild(store, c1.childId, project.id, thread.id)
76
+ const c3 = await spawnChild(store, c2.childId, project.id, thread.id)
77
+ const c4 = await spawnChild(store, c3.childId, project.id, thread.id)
78
+
79
+ const validator = new DefaultCapacityValidator(store)
80
+ try {
81
+ // Ancestry of c4 has length 5; limit=4 means depth 5 > 4 → reject.
82
+ await validator.validateDepth(c4.childId, 4, tenant)
83
+ expect.fail('expected DelegationCapacityExceeded')
84
+ } catch (err) {
85
+ expect(err).toBeInstanceOf(DelegationCapacityExceeded)
86
+ const e = err as DelegationCapacityExceeded
87
+ expect(e.details.dimension).toBe('depth')
88
+ expect(e.details.limit).toBe(4)
89
+ expect(e.details.current).toBe(5)
90
+ }
91
+ })
92
+
93
+ it('width: empty parent with 4 pending children passes limit=8', async () => {
94
+ const store = new InMemorySessionStore()
95
+ const { root } = await seedProject(store)
96
+ const validator = new DefaultCapacityValidator(store)
97
+
98
+ await expect(validator.validateWidth(root.id, 4, 8, tenant)).resolves.toBeUndefined()
99
+ })
100
+
101
+ it('width: existing 5 + pending 3 = 8 passes exactly at the limit', async () => {
102
+ const store = new InMemorySessionStore()
103
+ const { project, thread, root } = await seedProject(store)
104
+ for (let i = 0; i < 5; i++) {
105
+ await spawnChild(store, root.id, project.id, thread.id)
106
+ }
107
+ const validator = new DefaultCapacityValidator(store)
108
+ await expect(validator.validateWidth(root.id, 3, 8, tenant)).resolves.toBeUndefined()
109
+ })
110
+
111
+ it('width: existing 6 + pending 3 = 9 exceeds 8, throws dimension=width', async () => {
112
+ const store = new InMemorySessionStore()
113
+ const { project, thread, root } = await seedProject(store)
114
+ for (let i = 0; i < 6; i++) {
115
+ await spawnChild(store, root.id, project.id, thread.id)
116
+ }
117
+ const validator = new DefaultCapacityValidator(store)
118
+ try {
119
+ await validator.validateWidth(root.id, 3, 8, tenant)
120
+ expect.fail('expected DelegationCapacityExceeded')
121
+ } catch (err) {
122
+ expect(err).toBeInstanceOf(DelegationCapacityExceeded)
123
+ const e = err as DelegationCapacityExceeded
124
+ expect(e.details.dimension).toBe('width')
125
+ expect(e.details.current).toBe(9)
126
+ expect(e.details.limit).toBe(8)
127
+ }
128
+ })
129
+ })