@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,214 @@
1
+ /**
2
+ * Integration — `active → locked` illegal-transition rejection matrix per
3
+ * pattern doc §5.1.
4
+ *
5
+ * A handoff request against a session whose current Run is `running`,
6
+ * `awaiting_hitl`, `awaiting_hitl_resolution`, or `awaiting_subsession`
7
+ * rejects with typed {@link HandoffLockRejected}. The reason enum maps:
8
+ * - running → 'active_run'
9
+ * - awaiting_hitl → 'pending_hitl'
10
+ * - awaiting_hitl_resol. → 'pending_hitl'
11
+ * - awaiting_subsession → 'pending_subsession'
12
+ *
13
+ * This integration test wires the `RunStatusResolver` seam into a full
14
+ * single-handoff flow so the rejection triggers from the run-fan-in check
15
+ * (§5.1), not just from a status precondition.
16
+ */
17
+
18
+ import { describe, expect, it } from 'vitest'
19
+ import { ThreadManager } from '../../../manager/thread/lifecycle.js'
20
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
21
+ import { InMemoryThreadStore } from '../../../store/thread/memory.js'
22
+ import type { ThreadId } from '../../../types/session/ids.js'
23
+ import { generateHandoffId } from '../../../utils/id.js'
24
+ import type { HandoffAssignment } from '../../handoff/assignment.js'
25
+ import { DefaultCapacityValidator } from '../../handoff/capacity.js'
26
+ import type { HandoffEventSink } from '../../handoff/events.js'
27
+ import {
28
+ type RunStatusResolver,
29
+ type SingleHandoffDeps,
30
+ executeSingleHandoff,
31
+ } from '../../handoff/single.js'
32
+ import { HandoffLockRejected } from '../../handoff/version.js'
33
+ import { GitWorktreeDriver } from '../../workspace/git-worktree.js'
34
+ import { WorkspaceBackendRegistry } from '../../workspace/registry.js'
35
+ import { DEFAULT_TENANT, okExec, stubLogger, userActor } from './_fixtures.js'
36
+
37
+ function buildDeps(
38
+ store: InMemorySessionStore,
39
+ threadStore: InMemoryThreadStore,
40
+ runStatus?: RunStatusResolver,
41
+ ): SingleHandoffDeps {
42
+ const driver = new GitWorktreeDriver({
43
+ repoRoot: '/repo',
44
+ logger: stubLogger(),
45
+ execFile: async () => okExec(),
46
+ })
47
+ const workspaceRegistry = new WorkspaceBackendRegistry()
48
+ workspaceRegistry.register(driver)
49
+
50
+ const events: HandoffEventSink = {}
51
+
52
+ return {
53
+ store,
54
+ workspaceRegistry,
55
+ capacity: new DefaultCapacityValidator(store),
56
+ events,
57
+ threadManager: new ThreadManager({ threadStore, sessionStore: store }),
58
+ ...(runStatus !== undefined && { runStatus }),
59
+ }
60
+ }
61
+
62
+ async function seedIdleSession(store: InMemorySessionStore, threadStore: InMemoryThreadStore) {
63
+ const project = await store.createProject(
64
+ { tenantId: DEFAULT_TENANT, name: 'illegal' },
65
+ DEFAULT_TENANT,
66
+ )
67
+ const thread = await threadStore.createThread(
68
+ { projectId: project.id, title: 'illegal' },
69
+ DEFAULT_TENANT,
70
+ )
71
+ const session = await store.createSession(
72
+ { threadId: thread.id, projectId: project.id, currentActor: userActor('usr_source') },
73
+ DEFAULT_TENANT,
74
+ )
75
+ return { project, thread, session }
76
+ }
77
+
78
+ function buildAssignment(
79
+ sourceSessionId: Awaited<ReturnType<InMemorySessionStore['createSession']>>['id'],
80
+ projectId: Awaited<ReturnType<InMemorySessionStore['createProject']>>['id'],
81
+ threadId: ThreadId,
82
+ ): HandoffAssignment {
83
+ return {
84
+ id: generateHandoffId(),
85
+ mode: 'single',
86
+ sourceSessionId,
87
+ tenantId: DEFAULT_TENANT,
88
+ threadId,
89
+ projectId,
90
+ sourceActor: userActor('usr_source'),
91
+ recipientActor: userActor('usr_target'),
92
+ expectedOwnerVersion: 0,
93
+ createdAt: new Date('2026-04-17'),
94
+ }
95
+ }
96
+
97
+ describe('Integration — illegal handoff transitions (§5.1)', () => {
98
+ it('running Run → HandoffLockRejected { reason: active_run }', async () => {
99
+ const store = new InMemorySessionStore()
100
+ const threadStore = new InMemoryThreadStore()
101
+ const { project, thread, session } = await seedIdleSession(store, threadStore)
102
+ const deps = buildDeps(store, threadStore, {
103
+ async blockingRun() {
104
+ return { reason: 'active_run' }
105
+ },
106
+ })
107
+ const assignment = buildAssignment(session.id, project.id, thread.id)
108
+
109
+ try {
110
+ await executeSingleHandoff(deps, assignment, DEFAULT_TENANT)
111
+ expect.fail('expected HandoffLockRejected')
112
+ } catch (err) {
113
+ expect(err).toBeInstanceOf(HandoffLockRejected)
114
+ expect((err as HandoffLockRejected).details.reason).toBe('active_run')
115
+ }
116
+
117
+ // Source never locked — still idle with original version.
118
+ const reloaded = await store.getSession(session.id, DEFAULT_TENANT)
119
+ expect(reloaded?.status).toBe('idle')
120
+ expect(reloaded?.ownerVersion).toBe(0)
121
+ })
122
+
123
+ it('awaiting_hitl → HandoffLockRejected { reason: pending_hitl }', async () => {
124
+ const store = new InMemorySessionStore()
125
+ const threadStore = new InMemoryThreadStore()
126
+ const { project, thread, session } = await seedIdleSession(store, threadStore)
127
+ const deps = buildDeps(store, threadStore, {
128
+ async blockingRun() {
129
+ return { reason: 'pending_hitl' }
130
+ },
131
+ })
132
+
133
+ try {
134
+ await executeSingleHandoff(
135
+ deps,
136
+ buildAssignment(session.id, project.id, thread.id),
137
+ DEFAULT_TENANT,
138
+ )
139
+ expect.fail('expected HandoffLockRejected')
140
+ } catch (err) {
141
+ expect(err).toBeInstanceOf(HandoffLockRejected)
142
+ expect((err as HandoffLockRejected).details.reason).toBe('pending_hitl')
143
+ }
144
+ })
145
+
146
+ it('awaiting_hitl_resolution collapses into pending_hitl reason (timeout variant)', async () => {
147
+ // §5.2 treats `awaiting_hitl_resolution` as the same non-terminal class
148
+ // that forces the source into `awaiting_hitl` — the resolver surfaces
149
+ // `pending_hitl` for both. This keeps the lock-rejection enum
150
+ // conservative (no new reason variant for a sub-state).
151
+ const store = new InMemorySessionStore()
152
+ const threadStore = new InMemoryThreadStore()
153
+ const { project, thread, session } = await seedIdleSession(store, threadStore)
154
+ const deps = buildDeps(store, threadStore, {
155
+ async blockingRun() {
156
+ return { reason: 'pending_hitl' }
157
+ },
158
+ })
159
+
160
+ await expect(
161
+ executeSingleHandoff(
162
+ deps,
163
+ buildAssignment(session.id, project.id, thread.id),
164
+ DEFAULT_TENANT,
165
+ ),
166
+ ).rejects.toBeInstanceOf(HandoffLockRejected)
167
+ })
168
+
169
+ it('awaiting_subsession → HandoffLockRejected { reason: pending_subsession }', async () => {
170
+ const store = new InMemorySessionStore()
171
+ const threadStore = new InMemoryThreadStore()
172
+ const { project, thread, session } = await seedIdleSession(store, threadStore)
173
+ const deps = buildDeps(store, threadStore, {
174
+ async blockingRun() {
175
+ return { reason: 'pending_subsession' }
176
+ },
177
+ })
178
+
179
+ try {
180
+ await executeSingleHandoff(
181
+ deps,
182
+ buildAssignment(session.id, project.id, thread.id),
183
+ DEFAULT_TENANT,
184
+ )
185
+ expect.fail('expected HandoffLockRejected')
186
+ } catch (err) {
187
+ expect(err).toBeInstanceOf(HandoffLockRejected)
188
+ expect((err as HandoffLockRejected).details.reason).toBe('pending_subsession')
189
+ }
190
+ })
191
+
192
+ it('session status precondition: active-status session rejects before resolver fires', async () => {
193
+ // When the session itself is already non-idle (e.g. `active`), the lock
194
+ // rejection fires from the status check — no RunStatusResolver invoked.
195
+ const store = new InMemorySessionStore()
196
+ const threadStore = new InMemoryThreadStore()
197
+ const { project, thread, session } = await seedIdleSession(store, threadStore)
198
+ await store.updateSession({ ...session, status: 'active' }, DEFAULT_TENANT)
199
+
200
+ const deps = buildDeps(store, threadStore, {
201
+ async blockingRun() {
202
+ return null // resolver would allow, but status guard trips first
203
+ },
204
+ })
205
+
206
+ await expect(
207
+ executeSingleHandoff(
208
+ deps,
209
+ buildAssignment(session.id, project.id, thread.id),
210
+ DEFAULT_TENANT,
211
+ ),
212
+ ).rejects.toBeInstanceOf(HandoffLockRejected)
213
+ })
214
+ })
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Integration — single-recipient handoff wired through the full stack.
3
+ *
4
+ * Orthogonal to `handoff/__tests__/single.test.ts` (unit-level): this
5
+ * exercises the real `InMemorySessionStore` + real `GitWorktreeDriver` (with
6
+ * stubbed `execFile`) + real {@link DefaultCapacityValidator} so the commit
7
+ * ordering + workspace provisioning side-effects are verifiable from the
8
+ * outside.
9
+ *
10
+ * Covers roadmap §5 invariants: §4.8 (handoff has no accepted field — commit
11
+ * is atomic), §6.1 (single-recipient flow: lock → commit), §5.1 (source
12
+ * transitions back to idle with bumped ownerVersion + appended previousActors).
13
+ */
14
+
15
+ import { describe, expect, it, vi } from 'vitest'
16
+ import { ThreadManager } from '../../../manager/thread/lifecycle.js'
17
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
18
+ import { InMemoryThreadStore } from '../../../store/thread/memory.js'
19
+ import type { TenantId } from '../../../types/ids/index.js'
20
+ import { generateHandoffId } from '../../../utils/id.js'
21
+ import { TenantIsolationError } from '../../errors.js'
22
+ import type { HandoffAssignment } from '../../handoff/assignment.js'
23
+ import { DefaultCapacityValidator } from '../../handoff/capacity.js'
24
+ import type { HandoffEventSink } from '../../handoff/events.js'
25
+ import { type SingleHandoffDeps, executeSingleHandoff } from '../../handoff/single.js'
26
+ import type { Session } from '../../hierarchy/session.js'
27
+ import { GitWorktreeDriver } from '../../workspace/git-worktree.js'
28
+ import { WorkspaceBackendRegistry } from '../../workspace/registry.js'
29
+ import { DEFAULT_TENANT, OTHER_TENANT, okExec, stubLogger, userActor } from './_fixtures.js'
30
+
31
+ function buildHandoffDeps(
32
+ store: InMemorySessionStore,
33
+ threadStore: InMemoryThreadStore,
34
+ ): {
35
+ deps: SingleHandoffDeps
36
+ updateCalls: Array<{ status?: string; ownerVersion?: number }>
37
+ } {
38
+ const driver = new GitWorktreeDriver({
39
+ repoRoot: '/repo',
40
+ logger: stubLogger(),
41
+ execFile: async () => okExec(),
42
+ })
43
+ const workspaceRegistry = new WorkspaceBackendRegistry()
44
+ workspaceRegistry.register(driver)
45
+
46
+ const sink: HandoffEventSink = {
47
+ onLocked: vi.fn(),
48
+ onUnlocked: vi.fn(),
49
+ onCommitted: vi.fn(),
50
+ onBroadcastRollback: vi.fn(),
51
+ }
52
+
53
+ const updateCalls: Array<{ status?: string; ownerVersion?: number }> = []
54
+ const originalUpdate = store.updateSession.bind(store)
55
+ store.updateSession = async (session: Session, tenantId) => {
56
+ updateCalls.push({ status: session.status, ownerVersion: session.ownerVersion })
57
+ return originalUpdate(session, tenantId)
58
+ }
59
+
60
+ const threadManager = new ThreadManager({ threadStore, sessionStore: store })
61
+ return {
62
+ deps: {
63
+ store,
64
+ workspaceRegistry,
65
+ capacity: new DefaultCapacityValidator(store),
66
+ events: sink,
67
+ threadManager,
68
+ },
69
+ updateCalls,
70
+ }
71
+ }
72
+
73
+ describe('Integration — single-recipient handoff E2E', () => {
74
+ it('idle → locked → commit: source previousActors grew + ownerVersion bumped atomically', async () => {
75
+ const store = new InMemorySessionStore()
76
+ const threadStore = new InMemoryThreadStore()
77
+ const project = await store.createProject(
78
+ { tenantId: DEFAULT_TENANT, name: 'ho' },
79
+ DEFAULT_TENANT,
80
+ )
81
+ const thread = await threadStore.createThread(
82
+ { projectId: project.id, title: 'ho' },
83
+ DEFAULT_TENANT,
84
+ )
85
+ const sourceActor = userActor('usr_source')
86
+ const recipientActor = userActor('usr_target')
87
+ const session = await store.createSession(
88
+ { threadId: thread.id, projectId: project.id, currentActor: sourceActor },
89
+ DEFAULT_TENANT,
90
+ )
91
+
92
+ const { deps, updateCalls } = buildHandoffDeps(store, threadStore)
93
+ const assignment: HandoffAssignment = {
94
+ id: generateHandoffId(),
95
+ mode: 'single',
96
+ sourceSessionId: session.id,
97
+ tenantId: DEFAULT_TENANT,
98
+ threadId: thread.id,
99
+ projectId: project.id,
100
+ sourceActor,
101
+ recipientActor,
102
+ expectedOwnerVersion: 0,
103
+ createdAt: new Date('2026-04-17'),
104
+ }
105
+
106
+ const outcome = await executeSingleHandoff(deps, assignment, DEFAULT_TENANT)
107
+
108
+ expect(outcome.committedOwnerVersion).toBe(1)
109
+
110
+ const reloaded = await store.getSession(session.id, DEFAULT_TENANT)
111
+ expect(reloaded?.status).toBe('idle')
112
+ expect(reloaded?.ownerVersion).toBe(1)
113
+ expect(reloaded?.currentActor).toEqual(recipientActor)
114
+ expect(reloaded?.previousActors).toHaveLength(1)
115
+ expect(reloaded?.previousActors[0]).toEqual(sourceActor)
116
+
117
+ // Wired assertion: updateSession was invoked at least with the lock
118
+ // transition + the final commit. That sequence is what makes the
119
+ // handoff "atomic at the store layer".
120
+ // Expect at minimum locked (v0) followed by committed (v1).
121
+ expect(updateCalls).toEqual(
122
+ expect.arrayContaining([
123
+ { status: 'locked', ownerVersion: 0 },
124
+ { status: 'idle', ownerVersion: 1 },
125
+ ]),
126
+ )
127
+ })
128
+
129
+ it('cross-tenant assignment rejects at entry (TenantIsolationError)', async () => {
130
+ const store = new InMemorySessionStore()
131
+ const threadStore = new InMemoryThreadStore()
132
+ const project = await store.createProject(
133
+ { tenantId: DEFAULT_TENANT, name: 'ct' },
134
+ DEFAULT_TENANT,
135
+ )
136
+ const thread = await threadStore.createThread(
137
+ { projectId: project.id, title: 'ct' },
138
+ DEFAULT_TENANT,
139
+ )
140
+ const session = await store.createSession(
141
+ { threadId: thread.id, projectId: project.id, currentActor: userActor('usr_source') },
142
+ DEFAULT_TENANT,
143
+ )
144
+
145
+ const { deps } = buildHandoffDeps(store, threadStore)
146
+ const assignment: HandoffAssignment = {
147
+ id: generateHandoffId(),
148
+ mode: 'single',
149
+ sourceSessionId: session.id,
150
+ tenantId: OTHER_TENANT,
151
+ threadId: thread.id,
152
+ projectId: project.id,
153
+ sourceActor: userActor('usr_source', OTHER_TENANT),
154
+ recipientActor: userActor('usr_target', OTHER_TENANT),
155
+ expectedOwnerVersion: 0,
156
+ createdAt: new Date('2026-04-17'),
157
+ }
158
+
159
+ await expect(executeSingleHandoff(deps, assignment, OTHER_TENANT)).rejects.toBeInstanceOf(
160
+ TenantIsolationError,
161
+ )
162
+ })
163
+
164
+ it('source-owned workspace provisioned for recipient', async () => {
165
+ const store = new InMemorySessionStore()
166
+ const threadStore = new InMemoryThreadStore()
167
+ const project = await store.createProject(
168
+ { tenantId: DEFAULT_TENANT, name: 'wsp' },
169
+ DEFAULT_TENANT,
170
+ )
171
+ const thread = await threadStore.createThread(
172
+ { projectId: project.id, title: 'wsp' },
173
+ DEFAULT_TENANT,
174
+ )
175
+ const source = await store.createSession(
176
+ { threadId: thread.id, projectId: project.id, currentActor: userActor('usr_source') },
177
+ DEFAULT_TENANT,
178
+ )
179
+
180
+ const { deps } = buildHandoffDeps(store, threadStore)
181
+ const assignment: HandoffAssignment = {
182
+ id: generateHandoffId(),
183
+ mode: 'single',
184
+ sourceSessionId: source.id,
185
+ tenantId: DEFAULT_TENANT,
186
+ threadId: thread.id,
187
+ projectId: project.id,
188
+ sourceActor: userActor('usr_source'),
189
+ recipientActor: userActor('usr_target'),
190
+ expectedOwnerVersion: 0,
191
+ createdAt: new Date('2026-04-17'),
192
+ }
193
+
194
+ const outcome = await executeSingleHandoff(deps, assignment, DEFAULT_TENANT)
195
+
196
+ expect(outcome.workspaceId.startsWith('wsp_')).toBe(true)
197
+ expect(outcome.newSessionId.startsWith('ses_')).toBe(true)
198
+
199
+ // Recipient session exists under the same tenant/project.
200
+ const recipient = await store.getSession(outcome.newSessionId, DEFAULT_TENANT)
201
+ expect(recipient).not.toBeNull()
202
+ expect(recipient?.projectId).toBe(project.id)
203
+ expect(recipient?.tenantId).toBe(DEFAULT_TENANT)
204
+ expect(recipient?.currentActor).toEqual(userActor('usr_target'))
205
+
206
+ // A sub-session edge links the source to the recipient.
207
+ const children = await store.getChildren(source.id, DEFAULT_TENANT)
208
+ expect(children).toHaveLength(1)
209
+ expect(children[0]?.kind).toBe('user_handoff')
210
+ expect(children[0]?.childSessionId).toBe(outcome.newSessionId)
211
+ })
212
+
213
+ // Tenant-denormalization-on-record assertion — every persisted entity
214
+ // carries the tenantId explicitly, which matters for §12 isolation.
215
+ it('denormalized tenantId stamped on Session + SubSession records', async () => {
216
+ const _tenantType: TenantId = DEFAULT_TENANT
217
+ const store = new InMemorySessionStore()
218
+ const threadStore = new InMemoryThreadStore()
219
+ const project = await store.createProject(
220
+ { tenantId: DEFAULT_TENANT, name: 'denorm' },
221
+ DEFAULT_TENANT,
222
+ )
223
+ const thread = await threadStore.createThread(
224
+ { projectId: project.id, title: 'denorm' },
225
+ DEFAULT_TENANT,
226
+ )
227
+ const source = await store.createSession(
228
+ { threadId: thread.id, projectId: project.id, currentActor: userActor('usr_source') },
229
+ DEFAULT_TENANT,
230
+ )
231
+ const { deps } = buildHandoffDeps(store, threadStore)
232
+
233
+ const assignment: HandoffAssignment = {
234
+ id: generateHandoffId(),
235
+ mode: 'single',
236
+ sourceSessionId: source.id,
237
+ tenantId: DEFAULT_TENANT,
238
+ threadId: thread.id,
239
+ projectId: project.id,
240
+ sourceActor: userActor('usr_source'),
241
+ recipientActor: userActor('usr_target'),
242
+ expectedOwnerVersion: 0,
243
+ createdAt: new Date(),
244
+ }
245
+ const outcome = await executeSingleHandoff(deps, assignment, DEFAULT_TENANT)
246
+
247
+ // Recipient's Session stores tenantId explicitly (not inferred).
248
+ const recipient = await store.getSession(outcome.newSessionId, DEFAULT_TENANT)
249
+ expect(recipient?.tenantId).toBe(_tenantType)
250
+ })
251
+ })
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Integration — Tenant → Project → Session → SubSession → Run hierarchy
3
+ * lifecycle against a real {@link InMemorySessionStore}.
4
+ *
5
+ * Covers roadmap §5 invariants §4 (branded IDs), §4.3 (currentActor
6
+ * immutability), §4.4 (sub-session status fan-in to drill), plus the
7
+ * `drill()` navigation primitive (§14.3). Orthogonal to `e2e-spawn.test.ts`
8
+ * (which exercises the full AgentManager spawn path); this file asserts the
9
+ * raw store contract under direct construction.
10
+ */
11
+
12
+ import { describe, expect, it } from 'vitest'
13
+ import type { ThreadId } from '../../../types/session/ids.js'
14
+ import { TenantIsolationError } from '../../errors.js'
15
+ import { DEFAULT_TENANT, agentActor, buildHarness, userActor } from './_fixtures.js'
16
+
17
+ const TEST_THREAD_ID = 'thd_test' as ThreadId
18
+
19
+ describe('Integration — hierarchy lifecycle', () => {
20
+ it('creates Tenant → Project → Session → SubSession with properly branded IDs', async () => {
21
+ const { store } = buildHarness()
22
+ const tenant = DEFAULT_TENANT
23
+
24
+ const project = await store.createProject({ tenantId: tenant, name: 'p1' }, tenant)
25
+ expect(project.id.startsWith('prj_')).toBe(true)
26
+ expect(project.tenantId.startsWith('tnt_')).toBe(true)
27
+
28
+ const session = await store.createSession(
29
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userActor('usr_a') },
30
+ tenant,
31
+ )
32
+ expect(session.id.startsWith('ses_')).toBe(true)
33
+ expect(session.projectId).toBe(project.id)
34
+ expect(session.tenantId).toBe(tenant)
35
+ expect(session.status).toBe('idle')
36
+ expect(session.ownerVersion).toBe(0)
37
+ expect(session.previousActors).toEqual([])
38
+
39
+ const childSession = await store.createSession(
40
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: agentActor('agt_worker') },
41
+ tenant,
42
+ )
43
+ const subSession = await store.createSubSession(
44
+ {
45
+ parentSessionId: session.id,
46
+ childSessionId: childSession.id,
47
+ kind: 'agent_spawn',
48
+ spawnedBy: userActor('usr_a'),
49
+ },
50
+ tenant,
51
+ )
52
+ expect(subSession.id.startsWith('sub_')).toBe(true)
53
+ expect(subSession.parentSessionId).toBe(session.id)
54
+ expect(subSession.childSessionId).toBe(childSession.id)
55
+ expect(subSession.kind).toBe('agent_spawn')
56
+ expect(subSession.status).toBe('pending')
57
+ })
58
+
59
+ it('drill(parentSessionId) returns a SessionView with children[] and ancestry[]', async () => {
60
+ const { store } = buildHarness()
61
+ const tenant = DEFAULT_TENANT
62
+
63
+ const project = await store.createProject({ tenantId: tenant, name: 'drill' }, tenant)
64
+ const parent = await store.createSession(
65
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userActor('usr_root') },
66
+ tenant,
67
+ )
68
+ const childA = await store.createSession(
69
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: agentActor('agt_a') },
70
+ tenant,
71
+ )
72
+ const childB = await store.createSession(
73
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: agentActor('agt_b') },
74
+ tenant,
75
+ )
76
+ await store.createSubSession(
77
+ {
78
+ parentSessionId: parent.id,
79
+ childSessionId: childA.id,
80
+ kind: 'agent_spawn',
81
+ spawnedBy: userActor('usr_root'),
82
+ },
83
+ tenant,
84
+ )
85
+ await store.createSubSession(
86
+ {
87
+ parentSessionId: parent.id,
88
+ childSessionId: childB.id,
89
+ kind: 'agent_spawn',
90
+ spawnedBy: userActor('usr_root'),
91
+ },
92
+ tenant,
93
+ )
94
+
95
+ const parentView = await store.drill(parent.id, tenant)
96
+ expect(parentView).not.toBeNull()
97
+ expect(parentView?.session.id).toBe(parent.id)
98
+ expect(parentView?.children).toHaveLength(2)
99
+ expect(parentView?.ancestry).toEqual([parent.id])
100
+
101
+ const childAView = await store.drill(childA.id, tenant)
102
+ expect(childAView).not.toBeNull()
103
+ expect(childAView?.ancestry).toEqual([parent.id, childA.id])
104
+ expect(childAView?.children).toHaveLength(0)
105
+ })
106
+
107
+ it('drill returns null for unknown session (deny-by-default)', async () => {
108
+ const { store } = buildHarness()
109
+ const view = await store.drill(
110
+ 'ses_missing' as Parameters<typeof store.drill>[0],
111
+ DEFAULT_TENANT,
112
+ )
113
+ expect(view).toBeNull()
114
+ })
115
+
116
+ it('§4.3 currentActor immutable previousActors — append-only on handoff', async () => {
117
+ const { store } = buildHarness()
118
+ const tenant = DEFAULT_TENANT
119
+
120
+ const project = await store.createProject({ tenantId: tenant, name: 'actors' }, tenant)
121
+ const userA = userActor('usr_a')
122
+ const userB = userActor('usr_b')
123
+ const userC = userActor('usr_c')
124
+
125
+ const session = await store.createSession(
126
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userA },
127
+ tenant,
128
+ )
129
+
130
+ // Simulate two successive handoff commits — each pushes the old actor
131
+ // onto previousActors and increments ownerVersion.
132
+ const firstHandoff = {
133
+ ...session,
134
+ currentActor: userB,
135
+ previousActors: [userA],
136
+ ownerVersion: 1,
137
+ }
138
+ await store.updateSession(firstHandoff, tenant)
139
+
140
+ const secondHandoff = {
141
+ ...firstHandoff,
142
+ currentActor: userC,
143
+ previousActors: [...firstHandoff.previousActors, userB],
144
+ ownerVersion: 2,
145
+ }
146
+ await store.updateSession(secondHandoff, tenant)
147
+
148
+ const reloaded = await store.getSession(session.id, tenant)
149
+ expect(reloaded?.currentActor).toEqual(userC)
150
+ expect(reloaded?.previousActors).toEqual([userA, userB])
151
+ expect(reloaded?.ownerVersion).toBe(2)
152
+ })
153
+
154
+ it('cycle guard via AncestryCycleError: ancestry walk detects corrupted parent linkage', async () => {
155
+ const { store } = buildHarness()
156
+ const tenant = DEFAULT_TENANT
157
+
158
+ const project = await store.createProject({ tenantId: tenant, name: 'cycle' }, tenant)
159
+ const sA = await store.createSession(
160
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userActor('usr_a') },
161
+ tenant,
162
+ )
163
+ const sB = await store.createSession(
164
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userActor('usr_b') },
165
+ tenant,
166
+ )
167
+
168
+ // Valid edge sA → sB.
169
+ await store.createSubSession(
170
+ {
171
+ parentSessionId: sA.id,
172
+ childSessionId: sB.id,
173
+ kind: 'agent_spawn',
174
+ spawnedBy: userActor('usr_a'),
175
+ },
176
+ tenant,
177
+ )
178
+ // Corrupting edge sB → sA closes the cycle. The store layer does not
179
+ // pre-check parent direction (the pattern doc §4.5 discusses
180
+ // intervention DAG cycles; ancestry cycles are a store-corruption
181
+ // detection path per session/errors.ts#AncestryCycleError).
182
+ await store.createSubSession(
183
+ {
184
+ parentSessionId: sB.id,
185
+ childSessionId: sA.id,
186
+ kind: 'agent_spawn',
187
+ spawnedBy: userActor('usr_b'),
188
+ },
189
+ tenant,
190
+ )
191
+
192
+ await expect(store.getAncestry(sB.id, tenant)).rejects.toThrow(/cycle/i)
193
+ })
194
+
195
+ it('SubSession pending → active → idle lifecycle', async () => {
196
+ const { store } = buildHarness()
197
+ const tenant = DEFAULT_TENANT
198
+
199
+ const project = await store.createProject({ tenantId: tenant, name: 'lifecycle' }, tenant)
200
+ const parent = await store.createSession(
201
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: userActor('usr_a') },
202
+ tenant,
203
+ )
204
+ const child = await store.createSession(
205
+ { threadId: TEST_THREAD_ID, projectId: project.id, currentActor: agentActor('agt_a') },
206
+ tenant,
207
+ )
208
+ const sub = await store.createSubSession(
209
+ {
210
+ parentSessionId: parent.id,
211
+ childSessionId: child.id,
212
+ kind: 'agent_spawn',
213
+ spawnedBy: userActor('usr_a'),
214
+ },
215
+ tenant,
216
+ )
217
+ expect(sub.status).toBe('pending')
218
+
219
+ // pending → active.
220
+ await store.updateSubSession({ ...sub, status: 'active' }, tenant)
221
+ const active = await store.getSubSession(sub.id, tenant)
222
+ expect(active?.status).toBe('active')
223
+
224
+ // active → idle (§5.3: no 'closed' state — sub-sessions terminate on idle).
225
+ await store.updateSubSession({ ...sub, status: 'idle' }, tenant)
226
+ const idle = await store.getSubSession(sub.id, tenant)
227
+ expect(idle?.status).toBe('idle')
228
+ })
229
+
230
+ it('cross-tenant hierarchy access rejects via TenantIsolationError', async () => {
231
+ const { store } = buildHarness()
232
+ const projectA = await store.createProject(
233
+ { tenantId: DEFAULT_TENANT, name: 'a' },
234
+ DEFAULT_TENANT,
235
+ )
236
+ await expect(
237
+ store.getProject(projectA.id, 'tnt_other' as typeof DEFAULT_TENANT),
238
+ ).rejects.toBeInstanceOf(TenantIsolationError)
239
+ })
240
+ })