@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,310 @@
1
+ /**
2
+ * Single-recipient handoff flow — `idle → locked → CAS → commit | revert`.
3
+ *
4
+ * See session-hierarchy.md §6.1 (single-recipient flow) and §6.4 (concurrent
5
+ * CAS). Function-based per Convention #9 — dependencies arrive as an
6
+ * explicit `deps` envelope so tests can inject mocks and production code
7
+ * composes flows without a class hierarchy.
8
+ *
9
+ * Flow (pattern doc §5.1 + §6.1):
10
+ * 1. Load source session; verify tenant.
11
+ * 2. Check status (must be `idle`); no non-terminal Runs.
12
+ * 3. Validate capacity (depth + width).
13
+ * 4. Transition source `idle → locked` with CAS on `ownerVersion`.
14
+ * 5. Emit `onLocked`.
15
+ * 6. Spawn recipient sub-session + provision isolated workspace.
16
+ * 7. On any step 6 failure: compensating revert (`locked → idle`, version
17
+ * unchanged, dispose any partial worktree), emit `onUnlocked`, rethrow.
18
+ * 8. On success: commit `locked → idle` with updated `currentActor` +
19
+ * appended `previousActors` + bumped `ownerVersion`.
20
+ * 9. Emit `onCommitted` with the new version.
21
+ */
22
+
23
+ import type { ThreadManager } from '../../manager/thread/lifecycle.js'
24
+ import type { SessionId, TenantId } from '../../types/ids/index.js'
25
+ import type { SessionStore } from '../../types/session/store.js'
26
+ import { TenantIsolationError } from '../errors.js'
27
+ import type { Session } from '../hierarchy/session.js'
28
+ import type { WorkspaceBackendDriver } from '../workspace/driver.js'
29
+ import type { WorkspaceRef } from '../workspace/ref.js'
30
+ import type { WorkspaceBackendRegistry } from '../workspace/registry.js'
31
+ import type { HandoffAssignment, HandoffOutcome } from './assignment.js'
32
+ import type { CapacityValidator } from './capacity.js'
33
+ import type { HandoffEventSink } from './events.js'
34
+ import { HandoffLockRejected, HandoffVersionConflict } from './version.js'
35
+
36
+ /**
37
+ * Minimal surface the handoff flow queries for Run fan-in status. A Run is
38
+ * considered "blocking" if it is in any non-terminal status that prevents the
39
+ * source session from transitioning to `locked` (session-hierarchy.md §5.1).
40
+ *
41
+ * The flow injects the resolver so Phase 4 stays decoupled from Phase 6's
42
+ * Run persistence refactor. Production wires the real Run store; tests stub.
43
+ */
44
+ export interface RunStatusResolver {
45
+ /**
46
+ * Returns the reason the session has a non-terminal Run, or `null` when
47
+ * all Runs are terminal and the lock is allowed.
48
+ */
49
+ blockingRun(
50
+ sessionId: SessionId,
51
+ tenantId: TenantId,
52
+ ): Promise<{ reason: 'active_run' | 'pending_hitl' | 'pending_subsession' } | null>
53
+ }
54
+
55
+ /** Null resolver — treats every session as unblocked. Used by tests that do not exercise Run fan-in. */
56
+ export const NOOP_RUN_STATUS_RESOLVER: RunStatusResolver = {
57
+ async blockingRun(): Promise<null> {
58
+ return null
59
+ },
60
+ }
61
+
62
+ export interface SingleHandoffDeps {
63
+ store: SessionStore
64
+ workspaceRegistry: WorkspaceBackendRegistry
65
+ capacity: CapacityValidator
66
+ events: HandoffEventSink
67
+ runStatus?: RunStatusResolver
68
+ /**
69
+ * Gate the recipient-session creation on the Thread being `'open'`.
70
+ * Added in Phase 2.6 to mirror spawn — a handoff into an archived
71
+ * Thread would otherwise undermine `ThreadManager.archive`.
72
+ */
73
+ threadManager: ThreadManager
74
+ }
75
+
76
+ /**
77
+ * Executes a single-recipient handoff against `deps.store`. Throws
78
+ * {@link HandoffLockRejected}, {@link HandoffVersionConflict},
79
+ * {@link TenantIsolationError}, or {@link DelegationCapacityExceeded} on
80
+ * invariant violations. Workspace provisioning failures surface as
81
+ * {@link WorkspaceBackendError} after the compensating revert.
82
+ */
83
+ export async function executeSingleHandoff(
84
+ deps: SingleHandoffDeps,
85
+ assignment: HandoffAssignment,
86
+ tenantId: TenantId,
87
+ ): Promise<HandoffOutcome> {
88
+ if (assignment.tenantId !== tenantId) {
89
+ throw new TenantIsolationError({
90
+ requested: tenantId,
91
+ resource: `handoff-assignment(${assignment.id})`,
92
+ })
93
+ }
94
+
95
+ // Thread archive gate (Phase 2.6) — runs FIRST so an archived thread
96
+ // fails fastest with `ThreadClosedError` rather than a lock rejection or
97
+ // capacity error. Checked BEFORE the CAS lock so a denied handoff leaves
98
+ // the source session untouched.
99
+ await deps.threadManager.requireOpen(assignment.threadId, tenantId)
100
+
101
+ // 1. Load source session + tenant check.
102
+ const source = await deps.store.getSession(assignment.sourceSessionId, tenantId)
103
+ if (!source) {
104
+ throw new Error(`Source session ${assignment.sourceSessionId} not found`)
105
+ }
106
+ if (source.tenantId !== tenantId) {
107
+ throw new TenantIsolationError({
108
+ requested: tenantId,
109
+ resource: `session(${source.id})`,
110
+ })
111
+ }
112
+ if (source.threadId !== assignment.threadId) {
113
+ throw new Error(
114
+ `Assignment threadId ${assignment.threadId} does not match source session threadId ${source.threadId}`,
115
+ )
116
+ }
117
+ if (source.projectId !== assignment.projectId) {
118
+ throw new Error(
119
+ `Assignment projectId ${assignment.projectId} does not match source session projectId ${source.projectId}`,
120
+ )
121
+ }
122
+
123
+ // 2. Status check — only `idle` sessions may lock. `active`, `awaiting_hitl`,
124
+ // `awaiting_merge`, `locked`, `failed`, `archived` all reject.
125
+ if (source.status !== 'idle') {
126
+ throw new HandoffLockRejected({
127
+ sessionId: source.id,
128
+ reason: statusToLockReason(source.status),
129
+ })
130
+ }
131
+
132
+ // 3. Non-terminal Run fan-in (§5.1).
133
+ const runResolver = deps.runStatus ?? NOOP_RUN_STATUS_RESOLVER
134
+ const blocking = await runResolver.blockingRun(source.id, tenantId)
135
+ if (blocking) {
136
+ throw new HandoffLockRejected({
137
+ sessionId: source.id,
138
+ reason: blocking.reason,
139
+ })
140
+ }
141
+
142
+ // 4. Capacity — depth (new child depth = parent ancestry length + 1) and
143
+ // width (one new child under the source's *parent* would change — but
144
+ // single handoff does NOT create a child under the source; it transfers
145
+ // ownership of the same session. Width only applies to broadcast).
146
+ // For `single` we still validate depth to future-proof should the flow
147
+ // evolve into a branch variant.
148
+ const project = await deps.store.getProject(source.projectId, tenantId)
149
+ if (!project) {
150
+ throw new Error(`Project ${source.projectId} not found`)
151
+ }
152
+ await deps.capacity.validateDepth(source.id, project.config.maxDelegationDepth, tenantId)
153
+
154
+ // 5. CAS → `idle → locked`.
155
+ if (source.ownerVersion !== assignment.expectedOwnerVersion) {
156
+ throw new HandoffVersionConflict({
157
+ sessionId: source.id,
158
+ expected: assignment.expectedOwnerVersion,
159
+ actual: source.ownerVersion,
160
+ })
161
+ }
162
+
163
+ const locked: Session = {
164
+ ...source,
165
+ status: 'locked',
166
+ }
167
+ await deps.store.updateSession(locked, tenantId)
168
+ emit(deps.events.onLocked, { sessionId: source.id, at: new Date() })
169
+
170
+ // 6. Provision recipient resources. Track partial state for rollback.
171
+ let provisionedWorkspace: WorkspaceRef | null = null
172
+ let createdSessionId: SessionId | null = null
173
+ try {
174
+ const driver: WorkspaceBackendDriver = deps.workspaceRegistry.get('git-worktree')
175
+ provisionedWorkspace = await driver.create({ label: `handoff-${assignment.id}` })
176
+
177
+ const recipientSession = await deps.store.createSession(
178
+ {
179
+ threadId: source.threadId,
180
+ projectId: source.projectId,
181
+ currentActor: assignment.recipientActor,
182
+ },
183
+ tenantId,
184
+ )
185
+ createdSessionId = recipientSession.id
186
+
187
+ await deps.store.createSubSession(
188
+ {
189
+ parentSessionId: source.id,
190
+ childSessionId: recipientSession.id,
191
+ kind: 'user_handoff',
192
+ spawnedBy: assignment.sourceActor,
193
+ },
194
+ tenantId,
195
+ )
196
+
197
+ // 7. Commit source: `locked → idle` with appended actor + bumped version.
198
+ // The source transitions ownership to the recipient — the previous
199
+ // owner is permanently read-only (§6.1).
200
+ const committed: Session = {
201
+ ...source,
202
+ status: 'idle',
203
+ currentActor: assignment.recipientActor,
204
+ previousActors: source.currentActor
205
+ ? [...source.previousActors, source.currentActor]
206
+ : [...source.previousActors],
207
+ ownerVersion: source.ownerVersion + 1,
208
+ }
209
+ await deps.store.updateSession(committed, tenantId)
210
+
211
+ emit(deps.events.onCommitted, {
212
+ sessionId: source.id,
213
+ newVersion: committed.ownerVersion,
214
+ handoffIds: [assignment.id],
215
+ at: new Date(),
216
+ })
217
+
218
+ return {
219
+ assignmentId: assignment.id,
220
+ newSessionId: recipientSession.id,
221
+ workspaceId: provisionedWorkspace.id,
222
+ committedOwnerVersion: committed.ownerVersion,
223
+ }
224
+ } catch (failure) {
225
+ // Compensating revert — idempotent. Every step tolerates prior success.
226
+ await revertLock(deps, source, provisionedWorkspace, createdSessionId, tenantId)
227
+ throw failure
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Reverts a source session from `locked` back to `idle` preserving
233
+ * `ownerVersion`, disposes any provisioned worktree, and emits `onUnlocked`.
234
+ *
235
+ * **Idempotent.** Every sub-op tolerates being called against already-released
236
+ * state:
237
+ * - `updateSession` replays the same payload — last-write-wins (Phase 3
238
+ * store uses write-tmp-rename).
239
+ * - `dispose` on a missing worktree is a no-op by contract
240
+ * (`driver.ts#dispose` + `git-worktree.ts` regex for "not a working tree").
241
+ */
242
+ async function revertLock(
243
+ deps: SingleHandoffDeps,
244
+ source: Session,
245
+ workspace: WorkspaceRef | null,
246
+ createdSessionId: SessionId | null,
247
+ tenantId: TenantId,
248
+ ): Promise<void> {
249
+ const reverted: Session = { ...source, status: 'idle' }
250
+ try {
251
+ await deps.store.updateSession(reverted, tenantId)
252
+ } catch {
253
+ // Swallow — the flow is already unwinding a primary failure; surfacing
254
+ // secondary errors would mask root cause. Idempotent per Risk #3.
255
+ }
256
+
257
+ if (workspace) {
258
+ try {
259
+ const driver = deps.workspaceRegistry.get('git-worktree')
260
+ await driver.dispose(workspace)
261
+ } catch {
262
+ // Idempotent rollback per Risk #3 — dispose is already tolerant of
263
+ // missing worktrees, but we still guard the registry lookup path.
264
+ }
265
+ }
266
+
267
+ if (createdSessionId) {
268
+ // No `deleteSession` in the Phase 3 store surface — mark the partially
269
+ // created recipient session as `archived` so it is inert. A later phase
270
+ // introduces explicit deletion; until then this is the cleanest
271
+ // compensator that does not add surface area.
272
+ try {
273
+ const recipient = await deps.store.getSession(createdSessionId, tenantId)
274
+ if (recipient) {
275
+ await deps.store.updateSession({ ...recipient, status: 'archived' }, tenantId)
276
+ }
277
+ } catch {
278
+ // Same rationale as above.
279
+ }
280
+ }
281
+
282
+ emit(deps.events.onUnlocked, { sessionId: source.id, at: new Date() })
283
+ }
284
+
285
+ function statusToLockReason(
286
+ status: Session['status'],
287
+ ): 'active_run' | 'pending_hitl' | 'pending_subsession' {
288
+ switch (status) {
289
+ case 'active':
290
+ return 'active_run'
291
+ case 'awaiting_hitl':
292
+ return 'pending_hitl'
293
+ case 'awaiting_merge':
294
+ return 'pending_subsession'
295
+ case 'locked':
296
+ return 'active_run'
297
+ case 'failed':
298
+ return 'active_run'
299
+ case 'archived':
300
+ return 'active_run'
301
+ case 'idle':
302
+ // Unreachable — caller guards. Keep a sentinel value so exhaustiveness
303
+ // does not force an `assert never` export from this module.
304
+ return 'active_run'
305
+ }
306
+ }
307
+
308
+ function emit<T>(handler: ((ev: T) => void) | undefined, event: T): void {
309
+ if (handler) handler(event)
310
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Typed errors for the handoff state machine.
3
+ *
4
+ * See session-hierarchy.md §5.1 (illegal `active → locked` transition) and
5
+ * §6.4 (concurrent CAS). Both classes carry structured `details` so consumers
6
+ * can route without string parsing (Convention #5: deny-by-default, fail
7
+ * fast).
8
+ */
9
+
10
+ import type { RunId, SessionId } from '../../types/ids/index.js'
11
+
12
+ /**
13
+ * Raised when a handoff's CAS write finds {@link Session.ownerVersion} has
14
+ * advanced since the assignment was constructed — another actor committed
15
+ * first (session-hierarchy.md §6.4 concurrent CAS). The caller re-reads and
16
+ * decides whether to retry.
17
+ */
18
+ export class HandoffVersionConflict extends Error {
19
+ readonly details: {
20
+ sessionId: SessionId
21
+ expected: number
22
+ actual: number
23
+ }
24
+
25
+ constructor(details: { sessionId: SessionId; expected: number; actual: number }) {
26
+ super(
27
+ `Handoff version conflict on ${details.sessionId}: expected ${details.expected}, actual ${details.actual}`,
28
+ )
29
+ this.name = 'HandoffVersionConflict'
30
+ this.details = details
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Reasons a session cannot transition `* → locked` for handoff. See
36
+ * session-hierarchy.md §5.1 — lock entry requires an `idle` session with all
37
+ * runs terminal. The three reasons are the non-terminal Run statuses that
38
+ * fan in to a non-idle Session.
39
+ */
40
+ export type HandoffLockRejectedReason = 'active_run' | 'pending_hitl' | 'pending_subsession'
41
+
42
+ /**
43
+ * Raised when a handoff targets a session whose current Run is non-terminal.
44
+ * Callers must wait for the active Run to terminalize (or cancel it) before
45
+ * re-attempting the handoff (session-hierarchy.md §5.1).
46
+ */
47
+ export class HandoffLockRejected extends Error {
48
+ readonly details: {
49
+ sessionId: SessionId
50
+ reason: HandoffLockRejectedReason
51
+ runId?: RunId
52
+ }
53
+
54
+ constructor(details: { sessionId: SessionId; reason: HandoffLockRejectedReason; runId?: RunId }) {
55
+ super(`Handoff lock rejected on ${details.sessionId}: ${details.reason}`)
56
+ this.name = 'HandoffLockRejected'
57
+ this.details = details
58
+ }
59
+ }
@@ -0,0 +1,100 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { RunStatus } from '../../../types/run/status.js'
3
+ import type {
4
+ ProjectId,
5
+ SessionId,
6
+ TenantId,
7
+ ThreadId,
8
+ UserId,
9
+ } from '../../../types/session/ids.js'
10
+ import type { ActorRef } from '../actor.js'
11
+ import { type Session, type SessionStatus, deriveStatus } from '../session.js'
12
+
13
+ const tenant = 'tnt_a' as TenantId
14
+ const project = 'prj_a' as ProjectId
15
+ const thread = 'thd_a' as ThreadId
16
+
17
+ function user(): ActorRef {
18
+ return { kind: 'user', userId: 'usr_a' as UserId, tenantId: tenant }
19
+ }
20
+
21
+ function makeSession(status: SessionStatus): Session {
22
+ return {
23
+ id: 'ses_a' as SessionId,
24
+ threadId: thread,
25
+ projectId: project,
26
+ tenantId: tenant,
27
+ status,
28
+ currentActor: user(),
29
+ previousActors: [],
30
+ workspaceId: null,
31
+ ownerVersion: 0,
32
+ createdAt: new Date('2026-01-01'),
33
+ updatedAt: new Date('2026-01-01'),
34
+ }
35
+ }
36
+
37
+ function runs(...statuses: RunStatus[]): readonly { status: RunStatus }[] {
38
+ return statuses.map((status) => ({ status }))
39
+ }
40
+
41
+ describe('deriveStatus', () => {
42
+ it('empty run set → idle', () => {
43
+ expect(deriveStatus(makeSession('idle'), [])).toBe('idle')
44
+ })
45
+
46
+ it('all succeeded → idle', () => {
47
+ expect(deriveStatus(makeSession('idle'), runs('succeeded', 'succeeded'))).toBe('idle')
48
+ })
49
+
50
+ it('any running → active (overrides idle session status)', () => {
51
+ expect(deriveStatus(makeSession('idle'), runs('succeeded', 'running'))).toBe('active')
52
+ })
53
+
54
+ it('any awaiting_subsession → active (delegation-in-flight parent is active)', () => {
55
+ expect(deriveStatus(makeSession('idle'), runs('succeeded', 'awaiting_subsession'))).toBe(
56
+ 'active',
57
+ )
58
+ })
59
+
60
+ it('awaiting_subsession alone → active', () => {
61
+ expect(deriveStatus(makeSession('idle'), runs('awaiting_subsession'))).toBe('active')
62
+ })
63
+
64
+ it('any awaiting_hitl → awaiting_hitl', () => {
65
+ expect(deriveStatus(makeSession('idle'), runs('succeeded', 'awaiting_hitl'))).toBe(
66
+ 'awaiting_hitl',
67
+ )
68
+ })
69
+
70
+ it('any awaiting_hitl_resolution → awaiting_hitl (persisted HITL wait)', () => {
71
+ expect(deriveStatus(makeSession('idle'), runs('awaiting_hitl_resolution'))).toBe(
72
+ 'awaiting_hitl',
73
+ )
74
+ })
75
+
76
+ it('all failed → failed', () => {
77
+ expect(deriveStatus(makeSession('idle'), runs('failed', 'failed'))).toBe('failed')
78
+ })
79
+
80
+ it('cancelled + failed + succeeded mix → idle (cancellation is not terminal Session state)', () => {
81
+ expect(deriveStatus(makeSession('idle'), runs('succeeded', 'cancelled', 'failed'))).toBe('idle')
82
+ })
83
+
84
+ it('locked session-level state wins over derived (even with succeeded runs)', () => {
85
+ expect(deriveStatus(makeSession('locked'), runs('succeeded'))).toBe('locked')
86
+ })
87
+
88
+ it('awaiting_merge session-level state wins over derived', () => {
89
+ expect(deriveStatus(makeSession('awaiting_merge'), runs('succeeded'))).toBe('awaiting_merge')
90
+ })
91
+
92
+ it('archived session-level state wins over derived (retention tombstone)', () => {
93
+ expect(deriveStatus(makeSession('archived'), runs('succeeded'))).toBe('archived')
94
+ })
95
+
96
+ it('running takes precedence over HITL', () => {
97
+ // Two runs — one running, one HITL. Active is higher priority (§5.1).
98
+ expect(deriveStatus(makeSession('idle'), runs('running', 'awaiting_hitl'))).toBe('active')
99
+ })
100
+ })
@@ -0,0 +1,17 @@
1
+ import type { AgentId, TenantId, UserId } from '../../types/ids/index.js'
2
+
3
+ /**
4
+ * Discriminated union of actors that can own a {@link Session}.
5
+ *
6
+ * See session-hierarchy.md §4.3. The `parentActor` field on the agent variant
7
+ * pairs with {@link Lineage} (§10.4) — permission audit events walk this
8
+ * chain to attribute subagent actions back to the originating user. Renamed
9
+ * from `spawnedBy` during the 0.2.0 design phase (no shim kept).
10
+ */
11
+ export type ActorRef =
12
+ | { kind: 'user'; userId: UserId; tenantId: TenantId }
13
+ | { kind: 'agent'; agentId: AgentId; tenantId: TenantId; parentActor?: ActorRef }
14
+ | { kind: 'system'; role: SystemRoleId; tenantId: TenantId }
15
+
16
+ /** Branded id for the {@link ActorRef} `system` variant. */
17
+ export type SystemRoleId = `sys_${string}`
@@ -0,0 +1,18 @@
1
+ // Sub-barrel for the session-hierarchy entity model.
2
+ // Convention #4: concrete types live in sibling files; re-export them here.
3
+
4
+ export type { ActorRef, SystemRoleId } from './actor.js'
5
+ export type { Lineage } from './lineage.js'
6
+ export type { Tenant } from './tenant.js'
7
+ export type { Project, ProjectConfig } from './project.js'
8
+ export type { Thread, ThreadStatus } from './thread.js'
9
+ export type { Session, SessionStatus } from './session.js'
10
+ export { deriveStatus } from './session.js'
11
+ export type {
12
+ SubSession,
13
+ SubSessionStatus,
14
+ SubSessionKind,
15
+ FailureMode,
16
+ CompletionMode,
17
+ DeliverableRef,
18
+ } from './sub-session.js'
@@ -0,0 +1,15 @@
1
+ import type { SessionId } from '../../types/ids/index.js'
2
+
3
+ /**
4
+ * Parent/root linkage carried on every sub-session event.
5
+ *
6
+ * Per session-hierarchy.md §10.4 every `RunEvent` emitted from a sub-session
7
+ * carries a {@link Lineage} so consumers can reconstruct the delegation tree
8
+ * without walking the store. `depth` is 0 at the root session and grows by 1
9
+ * per delegation level.
10
+ */
11
+ export interface Lineage {
12
+ parentSessionId: SessionId
13
+ rootSessionId: SessionId
14
+ depth: number
15
+ }
@@ -0,0 +1,41 @@
1
+ import type { KnowledgeBaseRef, MemoryStoreRef, TenantId, VaultRef } from '../../types/ids/index.js'
2
+ import type { ProjectId } from '../../types/session/ids.js'
3
+ import type { RetentionPolicy } from '../retention/policy.js'
4
+
5
+ /**
6
+ * Per-project configuration. Defaults per session-hierarchy.md §3 / §4.2 /
7
+ * §8.2 are applied at instantiation time (not encoded here) so the type
8
+ * stays declarative:
9
+ * - maxDelegationDepth: 4
10
+ * - maxDelegationWidth: 8
11
+ * - maxInterventionDepth: 10
12
+ * - sharedDeliverables: false
13
+ *
14
+ * `retentionPolicy` replaces the Phase 1 `RetentionPolicyRef = unknown`
15
+ * placeholder with the real {@link RetentionPolicy} shape (§12.3). Absent
16
+ * (deny-by-default per Convention #5) means archival is fully disabled for
17
+ * the project; explicit configuration is required.
18
+ */
19
+ export interface ProjectConfig {
20
+ maxDelegationDepth: number
21
+ maxDelegationWidth: number
22
+ maxInterventionDepth: number
23
+ sharedMemoryStores?: readonly MemoryStoreRef[]
24
+ sharedVaults?: readonly VaultRef[]
25
+ sharedKnowledgeBases?: readonly KnowledgeBaseRef[]
26
+ sharedDeliverables?: boolean
27
+ retentionPolicy?: RetentionPolicy
28
+ }
29
+
30
+ /**
31
+ * Long-lived goal scope that owns shared memory, vaults, knowledge bases,
32
+ * and deliverables across sessions. See session-hierarchy.md §4.2.
33
+ */
34
+ export interface Project {
35
+ id: ProjectId
36
+ tenantId: TenantId
37
+ name: string
38
+ config: ProjectConfig
39
+ createdAt: Date
40
+ updatedAt: Date
41
+ }
@@ -0,0 +1,109 @@
1
+ import type { SessionId, TenantId } from '../../types/ids/index.js'
2
+ import type { RunStatus } from '../../types/run/status.js'
3
+ import type { ProjectId, ThreadId, WorkspaceId } from '../../types/session/ids.js'
4
+ import type { ActorRef } from './actor.js'
5
+
6
+ /**
7
+ * Session lifecycle states. See session-hierarchy.md §4.3 and the state
8
+ * machine in §5.1. `awaiting_merge` is a sub-state of idle used on the
9
+ * broadcast source session (§5.4) between fan-out and all recipients
10
+ * terminalizing.
11
+ */
12
+ export type SessionStatus =
13
+ | 'active'
14
+ | 'idle'
15
+ | 'locked'
16
+ | 'awaiting_hitl'
17
+ | 'awaiting_merge'
18
+ | 'failed'
19
+ | 'archived'
20
+
21
+ /**
22
+ * Multi-turn work unit owned by exactly one {@link ActorRef} at a time.
23
+ *
24
+ * Scope identifiers:
25
+ * - `threadId` — the topic-level {@link Thread} this Session lives under.
26
+ * Set at creation, immutable; Sessions never move threads.
27
+ * - `projectId` — the {@link Project} the owning Thread belongs to.
28
+ * **Denormalized** from `thread.projectId` at creation time; immutable.
29
+ * Kept on the Session record for ergonomic access (Project-scoped
30
+ * consumers — handoff validators, archival, retention — would otherwise
31
+ * need a second round-trip to ThreadStore on every read). This is NOT
32
+ * a deprecated mirror of a fading field; it is a deliberate
33
+ * denormalization of structurally-immutable derived data.
34
+ *
35
+ * Other invariants (session-hierarchy.md §4.3):
36
+ * - `previousActors` is append-only and publicly read-only; previous
37
+ * owners cannot write to the session again.
38
+ * - `ownerVersion` is the CAS counter for handoff (§6.1 / §6.2 / §6.4).
39
+ * - `workspaceId` is nullable for sessions whose workspace has not yet
40
+ * been provisioned (or has been torn down during archival).
41
+ */
42
+ export interface Session {
43
+ id: SessionId
44
+ threadId: ThreadId
45
+ projectId: ProjectId
46
+ tenantId: TenantId
47
+ status: SessionStatus
48
+ currentActor: ActorRef | null
49
+ previousActors: readonly ActorRef[]
50
+ workspaceId: WorkspaceId | null
51
+ ownerVersion: number
52
+ createdAt: Date
53
+ updatedAt: Date
54
+ }
55
+
56
+ /**
57
+ * Pure Run→Session fan-in helper per session-hierarchy.md §5.1.
58
+ *
59
+ * The precedence (highest first) matches the pattern-doc table:
60
+ * 1. Session-level states that do not fan in from Run status:
61
+ * - `locked` (handoff CAS window) — preserved verbatim
62
+ * - `awaiting_merge` (broadcast source post-fan-out, §5.4) — preserved
63
+ * - `archived` (retention tombstone, §12.3) — preserved
64
+ * 2. Any Run `running` or `awaiting_subsession` → Session `active`.
65
+ * Delegation-in-flight is an active state of the parent — the parent
66
+ * Run is suspended waiting on the child's SessionSummaryMaterializer,
67
+ * and the session is NOT idle while that is pending.
68
+ * 3. Any Run `awaiting_hitl` or `awaiting_hitl_resolution` → Session
69
+ * `awaiting_hitl`.
70
+ * 4. All Runs `failed` and at least one Run present → Session `failed`.
71
+ * 5. Otherwise (all runs terminal — succeeded/cancelled/failed mix, or no
72
+ * runs at all) → Session `idle`.
73
+ *
74
+ * `cancelled` does NOT surface a `failed` Session (§5.1 — "Cancellation is
75
+ * not a terminal Session state"). Only `failed` runs drive the Session to
76
+ * `failed` when every Run ended that way.
77
+ */
78
+ export function deriveStatus(
79
+ session: Session,
80
+ runs: readonly { status: RunStatus }[],
81
+ ): SessionStatus {
82
+ // Session-level overrides — these states do not fan in from Run status.
83
+ if (session.status === 'locked') return 'locked'
84
+ if (session.status === 'awaiting_merge') return 'awaiting_merge'
85
+ if (session.status === 'archived') return 'archived'
86
+
87
+ // Any active Run (in-flight iteration or awaiting a child sub-session) →
88
+ // `active`. Delegation is an active state: the parent Run is suspended
89
+ // waiting on the child's Materializer, not idle.
90
+ const hasActive = runs.some((r) => r.status === 'running' || r.status === 'awaiting_subsession')
91
+ if (hasActive) return 'active'
92
+
93
+ // Any HITL block (synchronous or persisted) → `awaiting_hitl`.
94
+ const hasHitl = runs.some(
95
+ (r) => r.status === 'awaiting_hitl' || r.status === 'awaiting_hitl_resolution',
96
+ )
97
+ if (hasHitl) return 'awaiting_hitl'
98
+
99
+ // All failed (with at least one Run) → `failed`. Note that a `cancelled`
100
+ // Run does NOT drive the Session to `failed`; §5.1 is explicit that
101
+ // cancellation leaves the Session `idle`.
102
+ if (runs.length > 0 && runs.every((r) => r.status === 'failed')) {
103
+ return 'failed'
104
+ }
105
+
106
+ // Otherwise — empty run set, or all runs terminated (succeeded / cancelled
107
+ // / mixed with failed) — the Session is `idle`.
108
+ return 'idle'
109
+ }