@namzu/sdk 0.1.8 → 0.2.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 (531) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  3. package/dist/agents/ReactiveAgent.js +5 -3
  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 +18 -5
  10. package/dist/agents/SupervisorAgent.js.map +1 -1
  11. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  12. package/dist/bridge/a2a/mapper.js +6 -0
  13. package/dist/bridge/a2a/mapper.js.map +1 -1
  14. package/dist/bridge/a2a/task.d.ts +2 -2
  15. package/dist/bridge/a2a/task.d.ts.map +1 -1
  16. package/dist/bridge/a2a/task.js.map +1 -1
  17. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  18. package/dist/bridge/sse/mapper.js +6 -0
  19. package/dist/bridge/sse/mapper.js.map +1 -1
  20. package/dist/constants/a2a/index.d.ts +2 -2
  21. package/dist/constants/a2a/index.d.ts.map +1 -1
  22. package/dist/constants/a2a/index.js.map +1 -1
  23. package/dist/contracts/api.d.ts +22 -3
  24. package/dist/contracts/api.d.ts.map +1 -1
  25. package/dist/contracts/index.d.ts +3 -1
  26. package/dist/contracts/index.d.ts.map +1 -1
  27. package/dist/contracts/index.js.map +1 -1
  28. package/dist/gateway/local.d.ts.map +1 -1
  29. package/dist/gateway/local.js +6 -0
  30. package/dist/gateway/local.js.map +1 -1
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +4 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
  36. package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
  37. package/dist/manager/agent/__tests__/lifecycle.test.js +302 -0
  38. package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
  39. package/dist/manager/agent/lifecycle.d.ts +58 -3
  40. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  41. package/dist/manager/agent/lifecycle.js +311 -12
  42. package/dist/manager/agent/lifecycle.js.map +1 -1
  43. package/dist/manager/run/persistence.d.ts +8 -1
  44. package/dist/manager/run/persistence.d.ts.map +1 -1
  45. package/dist/manager/run/persistence.js +15 -0
  46. package/dist/manager/run/persistence.js.map +1 -1
  47. package/dist/run/reporter.d.ts.map +1 -1
  48. package/dist/run/reporter.js +25 -0
  49. package/dist/run/reporter.js.map +1 -1
  50. package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
  51. package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
  52. package/dist/runtime/query/__tests__/context.test.js +84 -0
  53. package/dist/runtime/query/__tests__/context.test.js.map +1 -0
  54. package/dist/runtime/query/context.d.ts +55 -2
  55. package/dist/runtime/query/context.d.ts.map +1 -1
  56. package/dist/runtime/query/context.js +48 -8
  57. package/dist/runtime/query/context.js.map +1 -1
  58. package/dist/runtime/query/events.d.ts.map +1 -1
  59. package/dist/runtime/query/events.js +8 -0
  60. package/dist/runtime/query/events.js.map +1 -1
  61. package/dist/runtime/query/index.d.ts +25 -2
  62. package/dist/runtime/query/index.d.ts.map +1 -1
  63. package/dist/runtime/query/index.js +11 -1
  64. package/dist/runtime/query/index.js.map +1 -1
  65. package/dist/session/__tests__/integration/_fixtures.d.ts +115 -0
  66. package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
  67. package/dist/session/__tests__/integration/_fixtures.js +198 -0
  68. package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
  69. package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
  70. package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
  71. package/dist/session/__tests__/integration/capacity-caps.test.js +116 -0
  72. package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
  73. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
  74. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
  75. package/dist/session/__tests__/integration/e2e-spawn.test.js +226 -0
  76. package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
  77. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
  78. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
  79. package/dist/session/__tests__/integration/event-stream-ordering.test.js +323 -0
  80. package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
  81. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
  82. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
  83. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +170 -0
  84. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
  85. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
  86. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
  87. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +146 -0
  88. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
  89. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
  90. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
  91. package/dist/session/__tests__/integration/handoff-single-e2e.test.js +163 -0
  92. package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
  93. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
  94. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
  95. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +157 -0
  96. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
  97. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
  98. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
  99. package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
  100. package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
  101. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
  102. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
  103. package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
  104. package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
  105. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
  106. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
  107. package/dist/session/__tests__/integration/prev-artifact-dag.test.js +241 -0
  108. package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
  109. package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
  110. package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
  111. package/dist/session/__tests__/integration/retention-archive.test.js +186 -0
  112. package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
  113. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
  114. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
  115. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +200 -0
  116. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
  117. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
  118. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
  119. package/dist/session/__tests__/integration/tenant-isolation.test.js +180 -0
  120. package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
  121. package/dist/session/errors.d.ts +60 -0
  122. package/dist/session/errors.d.ts.map +1 -0
  123. package/dist/session/errors.js +50 -0
  124. package/dist/session/errors.js.map +1 -0
  125. package/dist/session/events/index.d.ts +4 -0
  126. package/dist/session/events/index.d.ts.map +1 -0
  127. package/dist/session/events/index.js +8 -0
  128. package/dist/session/events/index.js.map +1 -0
  129. package/dist/session/events/schema-version.d.ts +13 -0
  130. package/dist/session/events/schema-version.d.ts.map +1 -0
  131. package/dist/session/events/schema-version.js +12 -0
  132. package/dist/session/events/schema-version.js.map +1 -0
  133. package/dist/session/events/types.d.ts +64 -0
  134. package/dist/session/events/types.d.ts.map +1 -0
  135. package/dist/session/events/types.js +2 -0
  136. package/dist/session/events/types.js.map +1 -0
  137. package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
  138. package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
  139. package/dist/session/handoff/__tests__/broadcast.test.js +243 -0
  140. package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
  141. package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
  142. package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
  143. package/dist/session/handoff/__tests__/capacity.test.js +100 -0
  144. package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
  145. package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
  146. package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
  147. package/dist/session/handoff/__tests__/single.test.js +230 -0
  148. package/dist/session/handoff/__tests__/single.test.js.map +1 -0
  149. package/dist/session/handoff/assignment.d.ts +59 -0
  150. package/dist/session/handoff/assignment.d.ts.map +1 -0
  151. package/dist/session/handoff/assignment.js +11 -0
  152. package/dist/session/handoff/assignment.js.map +1 -0
  153. package/dist/session/handoff/broadcast.d.ts +47 -0
  154. package/dist/session/handoff/broadcast.d.ts.map +1 -0
  155. package/dist/session/handoff/broadcast.js +296 -0
  156. package/dist/session/handoff/broadcast.js.map +1 -0
  157. package/dist/session/handoff/capacity.d.ts +66 -0
  158. package/dist/session/handoff/capacity.d.ts.map +1 -0
  159. package/dist/session/handoff/capacity.js +60 -0
  160. package/dist/session/handoff/capacity.js.map +1 -0
  161. package/dist/session/handoff/events.d.ts +66 -0
  162. package/dist/session/handoff/events.d.ts.map +1 -0
  163. package/dist/session/handoff/events.js +13 -0
  164. package/dist/session/handoff/events.js.map +1 -0
  165. package/dist/session/handoff/index.d.ts +12 -0
  166. package/dist/session/handoff/index.d.ts.map +1 -0
  167. package/dist/session/handoff/index.js +9 -0
  168. package/dist/session/handoff/index.js.map +1 -0
  169. package/dist/session/handoff/single.d.ts +62 -0
  170. package/dist/session/handoff/single.d.ts.map +1 -0
  171. package/dist/session/handoff/single.js +217 -0
  172. package/dist/session/handoff/single.js.map +1 -0
  173. package/dist/session/handoff/version.d.ts +52 -0
  174. package/dist/session/handoff/version.d.ts.map +1 -0
  175. package/dist/session/handoff/version.js +36 -0
  176. package/dist/session/handoff/version.js.map +1 -0
  177. package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
  178. package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
  179. package/dist/session/hierarchy/__tests__/session.test.js +67 -0
  180. package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
  181. package/dist/session/hierarchy/actor.d.ts +26 -0
  182. package/dist/session/hierarchy/actor.d.ts.map +1 -0
  183. package/dist/session/hierarchy/actor.js +2 -0
  184. package/dist/session/hierarchy/actor.js.map +1 -0
  185. package/dist/session/hierarchy/index.d.ts +8 -0
  186. package/dist/session/hierarchy/index.d.ts.map +1 -0
  187. package/dist/session/hierarchy/index.js +4 -0
  188. package/dist/session/hierarchy/index.js.map +1 -0
  189. package/dist/session/hierarchy/lineage.d.ts +15 -0
  190. package/dist/session/hierarchy/lineage.d.ts.map +1 -0
  191. package/dist/session/hierarchy/lineage.js +2 -0
  192. package/dist/session/hierarchy/lineage.js.map +1 -0
  193. package/dist/session/hierarchy/project.d.ts +40 -0
  194. package/dist/session/hierarchy/project.d.ts.map +1 -0
  195. package/dist/session/hierarchy/project.js +2 -0
  196. package/dist/session/hierarchy/project.js.map +1 -0
  197. package/dist/session/hierarchy/session.d.ts +59 -0
  198. package/dist/session/hierarchy/session.d.ts.map +1 -0
  199. package/dist/session/hierarchy/session.js +51 -0
  200. package/dist/session/hierarchy/session.js.map +1 -0
  201. package/dist/session/hierarchy/sub-session.d.ts +76 -0
  202. package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
  203. package/dist/session/hierarchy/sub-session.js +2 -0
  204. package/dist/session/hierarchy/sub-session.js.map +1 -0
  205. package/dist/session/hierarchy/tenant.d.ts +13 -0
  206. package/dist/session/hierarchy/tenant.d.ts.map +1 -0
  207. package/dist/session/hierarchy/tenant.js +2 -0
  208. package/dist/session/hierarchy/tenant.js.map +1 -0
  209. package/dist/session/index.d.ts +10 -0
  210. package/dist/session/index.d.ts.map +1 -0
  211. package/dist/session/index.js +15 -0
  212. package/dist/session/index.js.map +1 -0
  213. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
  214. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
  215. package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
  216. package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
  217. package/dist/session/intervention/index.d.ts +3 -0
  218. package/dist/session/intervention/index.d.ts.map +1 -0
  219. package/dist/session/intervention/index.js +8 -0
  220. package/dist/session/intervention/index.js.map +1 -0
  221. package/dist/session/intervention/prev-artifact.d.ts +103 -0
  222. package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
  223. package/dist/session/intervention/prev-artifact.js +112 -0
  224. package/dist/session/intervention/prev-artifact.js.map +1 -0
  225. package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
  226. package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
  227. package/dist/session/migration/__tests__/filesystem.test.js +188 -0
  228. package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
  229. package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
  230. package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
  231. package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
  232. package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
  233. package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
  234. package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
  235. package/dist/session/migration/__tests__/marker.test.js +75 -0
  236. package/dist/session/migration/__tests__/marker.test.js.map +1 -0
  237. package/dist/session/migration/errors.d.ts +26 -0
  238. package/dist/session/migration/errors.d.ts.map +1 -0
  239. package/dist/session/migration/errors.js +22 -0
  240. package/dist/session/migration/errors.js.map +1 -0
  241. package/dist/session/migration/filesystem.d.ts +94 -0
  242. package/dist/session/migration/filesystem.d.ts.map +1 -0
  243. package/dist/session/migration/filesystem.js +319 -0
  244. package/dist/session/migration/filesystem.js.map +1 -0
  245. package/dist/session/migration/id-prefix.d.ts +98 -0
  246. package/dist/session/migration/id-prefix.d.ts.map +1 -0
  247. package/dist/session/migration/id-prefix.js +116 -0
  248. package/dist/session/migration/id-prefix.js.map +1 -0
  249. package/dist/session/migration/index.d.ts +8 -0
  250. package/dist/session/migration/index.d.ts.map +1 -0
  251. package/dist/session/migration/index.js +8 -0
  252. package/dist/session/migration/index.js.map +1 -0
  253. package/dist/session/migration/marker.d.ts +57 -0
  254. package/dist/session/migration/marker.d.ts.map +1 -0
  255. package/dist/session/migration/marker.js +111 -0
  256. package/dist/session/migration/marker.js.map +1 -0
  257. package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
  258. package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
  259. package/dist/session/retention/__tests__/archive.test.js +252 -0
  260. package/dist/session/retention/__tests__/archive.test.js.map +1 -0
  261. package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
  262. package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
  263. package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
  264. package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
  265. package/dist/session/retention/archive-backend-ref.d.ts +18 -0
  266. package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
  267. package/dist/session/retention/archive-backend-ref.js +2 -0
  268. package/dist/session/retention/archive-backend-ref.js.map +1 -0
  269. package/dist/session/retention/archive.d.ts +130 -0
  270. package/dist/session/retention/archive.d.ts.map +1 -0
  271. package/dist/session/retention/archive.js +203 -0
  272. package/dist/session/retention/archive.js.map +1 -0
  273. package/dist/session/retention/backend.d.ts +101 -0
  274. package/dist/session/retention/backend.d.ts.map +1 -0
  275. package/dist/session/retention/backend.js +15 -0
  276. package/dist/session/retention/backend.js.map +1 -0
  277. package/dist/session/retention/disk-backend.d.ts +59 -0
  278. package/dist/session/retention/disk-backend.d.ts.map +1 -0
  279. package/dist/session/retention/disk-backend.js +236 -0
  280. package/dist/session/retention/disk-backend.js.map +1 -0
  281. package/dist/session/retention/index.d.ts +9 -0
  282. package/dist/session/retention/index.d.ts.map +1 -0
  283. package/dist/session/retention/index.js +6 -0
  284. package/dist/session/retention/index.js.map +1 -0
  285. package/dist/session/retention/policy.d.ts +49 -0
  286. package/dist/session/retention/policy.d.ts.map +1 -0
  287. package/dist/session/retention/policy.js +21 -0
  288. package/dist/session/retention/policy.js.map +1 -0
  289. package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
  290. package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
  291. package/dist/session/summary/__tests__/materialize.test.js +269 -0
  292. package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
  293. package/dist/session/summary/deliverable.d.ts +74 -0
  294. package/dist/session/summary/deliverable.d.ts.map +1 -0
  295. package/dist/session/summary/deliverable.js +20 -0
  296. package/dist/session/summary/deliverable.js.map +1 -0
  297. package/dist/session/summary/index.d.ts +6 -0
  298. package/dist/session/summary/index.d.ts.map +1 -0
  299. package/dist/session/summary/index.js +9 -0
  300. package/dist/session/summary/index.js.map +1 -0
  301. package/dist/session/summary/materialize.d.ts +82 -0
  302. package/dist/session/summary/materialize.d.ts.map +1 -0
  303. package/dist/session/summary/materialize.js +117 -0
  304. package/dist/session/summary/materialize.js.map +1 -0
  305. package/dist/session/summary/ref.d.ts +91 -0
  306. package/dist/session/summary/ref.d.ts.map +1 -0
  307. package/dist/session/summary/ref.js +51 -0
  308. package/dist/session/summary/ref.js.map +1 -0
  309. package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
  310. package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
  311. package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
  312. package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
  313. package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
  314. package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
  315. package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
  316. package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
  317. package/dist/session/workspace/driver.d.ts +55 -0
  318. package/dist/session/workspace/driver.d.ts.map +1 -0
  319. package/dist/session/workspace/driver.js +12 -0
  320. package/dist/session/workspace/driver.js.map +1 -0
  321. package/dist/session/workspace/git-worktree.d.ts +65 -0
  322. package/dist/session/workspace/git-worktree.d.ts.map +1 -0
  323. package/dist/session/workspace/git-worktree.js +156 -0
  324. package/dist/session/workspace/git-worktree.js.map +1 -0
  325. package/dist/session/workspace/index.d.ts +8 -0
  326. package/dist/session/workspace/index.d.ts.map +1 -0
  327. package/dist/session/workspace/index.js +7 -0
  328. package/dist/session/workspace/index.js.map +1 -0
  329. package/dist/session/workspace/path-builder.d.ts +50 -0
  330. package/dist/session/workspace/path-builder.d.ts.map +1 -0
  331. package/dist/session/workspace/path-builder.js +50 -0
  332. package/dist/session/workspace/path-builder.js.map +1 -0
  333. package/dist/session/workspace/ref.d.ts +46 -0
  334. package/dist/session/workspace/ref.d.ts.map +1 -0
  335. package/dist/session/workspace/ref.js +11 -0
  336. package/dist/session/workspace/ref.js.map +1 -0
  337. package/dist/session/workspace/registry.d.ts +26 -0
  338. package/dist/session/workspace/registry.d.ts.map +1 -0
  339. package/dist/session/workspace/registry.js +35 -0
  340. package/dist/session/workspace/registry.js.map +1 -0
  341. package/dist/store/conversation/memory.d.ts +22 -0
  342. package/dist/store/conversation/memory.d.ts.map +1 -1
  343. package/dist/store/conversation/memory.js +22 -0
  344. package/dist/store/conversation/memory.js.map +1 -1
  345. package/dist/store/session/__tests__/disk.test.d.ts +2 -0
  346. package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
  347. package/dist/store/session/__tests__/disk.test.js +240 -0
  348. package/dist/store/session/__tests__/disk.test.js.map +1 -0
  349. package/dist/store/session/__tests__/memory.test.d.ts +2 -0
  350. package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
  351. package/dist/store/session/__tests__/memory.test.js +217 -0
  352. package/dist/store/session/__tests__/memory.test.js.map +1 -0
  353. package/dist/store/session/disk.d.ts +85 -0
  354. package/dist/store/session/disk.d.ts.map +1 -0
  355. package/dist/store/session/disk.js +757 -0
  356. package/dist/store/session/disk.js.map +1 -0
  357. package/dist/store/session/index.d.ts +7 -0
  358. package/dist/store/session/index.d.ts.map +1 -0
  359. package/dist/store/session/index.js +11 -0
  360. package/dist/store/session/index.js.map +1 -0
  361. package/dist/store/session/linkage.d.ts +38 -0
  362. package/dist/store/session/linkage.d.ts.map +1 -0
  363. package/dist/store/session/linkage.js +64 -0
  364. package/dist/store/session/linkage.js.map +1 -0
  365. package/dist/store/session/memory.d.ts +48 -0
  366. package/dist/store/session/memory.d.ts.map +1 -0
  367. package/dist/store/session/memory.js +322 -0
  368. package/dist/store/session/memory.js.map +1 -0
  369. package/dist/store/session/messages.d.ts +20 -0
  370. package/dist/store/session/messages.d.ts.map +1 -0
  371. package/dist/store/session/messages.js +12 -0
  372. package/dist/store/session/messages.js.map +1 -0
  373. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
  374. package/dist/types/agent/base.d.ts +28 -1
  375. package/dist/types/agent/base.d.ts.map +1 -1
  376. package/dist/types/agent/task.d.ts +50 -2
  377. package/dist/types/agent/task.d.ts.map +1 -1
  378. package/dist/types/agent/task.js.map +1 -1
  379. package/dist/types/conversation/index.d.ts +7 -0
  380. package/dist/types/conversation/index.d.ts.map +1 -1
  381. package/dist/types/ids/index.d.ts +26 -3
  382. package/dist/types/ids/index.d.ts.map +1 -1
  383. package/dist/types/ids/index.js +8 -1
  384. package/dist/types/ids/index.js.map +1 -1
  385. package/dist/types/invocation/__tests__/state.test.js +36 -29
  386. package/dist/types/invocation/__tests__/state.test.js.map +1 -1
  387. package/dist/types/invocation/index.d.ts +20 -4
  388. package/dist/types/invocation/index.d.ts.map +1 -1
  389. package/dist/types/invocation/index.js +10 -7
  390. package/dist/types/invocation/index.js.map +1 -1
  391. package/dist/types/run/config.d.ts +11 -1
  392. package/dist/types/run/config.d.ts.map +1 -1
  393. package/dist/types/run/events.d.ts +26 -1
  394. package/dist/types/run/events.d.ts.map +1 -1
  395. package/dist/types/run/index.d.ts.map +1 -1
  396. package/dist/types/run/index.js +8 -0
  397. package/dist/types/run/index.js.map +1 -1
  398. package/dist/types/run/metadata.d.ts +24 -1
  399. package/dist/types/run/metadata.d.ts.map +1 -1
  400. package/dist/types/run/status.d.ts +26 -0
  401. package/dist/types/run/status.d.ts.map +1 -0
  402. package/dist/types/run/status.js +2 -0
  403. package/dist/types/run/status.js.map +1 -0
  404. package/dist/types/session/ids.d.ts +18 -0
  405. package/dist/types/session/ids.d.ts.map +1 -0
  406. package/dist/types/session/ids.js +12 -0
  407. package/dist/types/session/ids.js.map +1 -0
  408. package/dist/types/session/index.d.ts +3 -0
  409. package/dist/types/session/index.d.ts.map +1 -0
  410. package/dist/types/session/index.js +5 -0
  411. package/dist/types/session/index.js.map +1 -0
  412. package/dist/types/session/store.d.ts +188 -0
  413. package/dist/types/session/store.d.ts.map +1 -0
  414. package/dist/types/session/store.js +14 -0
  415. package/dist/types/session/store.js.map +1 -0
  416. package/dist/utils/id.d.ts +18 -1
  417. package/dist/utils/id.d.ts.map +1 -1
  418. package/dist/utils/id.js +42 -4
  419. package/dist/utils/id.js.map +1 -1
  420. package/package.json +1 -1
  421. package/src/agents/ReactiveAgent.ts +7 -3
  422. package/src/agents/RouterAgent.ts +5 -0
  423. package/src/agents/SupervisorAgent.ts +26 -6
  424. package/src/bridge/a2a/mapper.ts +7 -0
  425. package/src/bridge/a2a/task.ts +2 -2
  426. package/src/bridge/sse/mapper.ts +8 -1
  427. package/src/constants/a2a/index.ts +2 -2
  428. package/src/contracts/api.ts +23 -3
  429. package/src/contracts/index.ts +2 -0
  430. package/src/gateway/local.ts +6 -0
  431. package/src/index.ts +14 -0
  432. package/src/manager/agent/__tests__/lifecycle.test.ts +452 -0
  433. package/src/manager/agent/lifecycle.ts +434 -19
  434. package/src/manager/run/persistence.ts +20 -1
  435. package/src/run/reporter.ts +28 -0
  436. package/src/runtime/query/__tests__/context.test.ts +101 -0
  437. package/src/runtime/query/context.ts +106 -10
  438. package/src/runtime/query/events.ts +8 -0
  439. package/src/runtime/query/index.ts +41 -3
  440. package/src/session/__tests__/integration/_fixtures.ts +282 -0
  441. package/src/session/__tests__/integration/capacity-caps.test.ts +164 -0
  442. package/src/session/__tests__/integration/e2e-spawn.test.ts +278 -0
  443. package/src/session/__tests__/integration/event-stream-ordering.test.ts +403 -0
  444. package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +245 -0
  445. package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +179 -0
  446. package/src/session/__tests__/integration/handoff-single-e2e.test.ts +220 -0
  447. package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +237 -0
  448. package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
  449. package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
  450. package/src/session/__tests__/integration/prev-artifact-dag.test.ts +318 -0
  451. package/src/session/__tests__/integration/retention-archive.test.ts +231 -0
  452. package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +237 -0
  453. package/src/session/__tests__/integration/tenant-isolation.test.ts +282 -0
  454. package/src/session/errors.ts +70 -0
  455. package/src/session/events/index.ts +16 -0
  456. package/src/session/events/schema-version.ts +13 -0
  457. package/src/session/events/types.ts +71 -0
  458. package/src/session/handoff/__tests__/broadcast.test.ts +350 -0
  459. package/src/session/handoff/__tests__/capacity.test.ts +123 -0
  460. package/src/session/handoff/__tests__/single.test.ts +316 -0
  461. package/src/session/handoff/assignment.ts +62 -0
  462. package/src/session/handoff/broadcast.ts +381 -0
  463. package/src/session/handoff/capacity.ts +121 -0
  464. package/src/session/handoff/events.ts +72 -0
  465. package/src/session/handoff/index.ts +29 -0
  466. package/src/session/handoff/single.ts +288 -0
  467. package/src/session/handoff/version.ts +59 -0
  468. package/src/session/hierarchy/__tests__/session.test.ts +92 -0
  469. package/src/session/hierarchy/actor.ts +17 -0
  470. package/src/session/hierarchy/index.ts +17 -0
  471. package/src/session/hierarchy/lineage.ts +15 -0
  472. package/src/session/hierarchy/project.ts +41 -0
  473. package/src/session/hierarchy/session.ts +97 -0
  474. package/src/session/hierarchy/sub-session.ts +92 -0
  475. package/src/session/hierarchy/tenant.ts +13 -0
  476. package/src/session/index.ts +15 -0
  477. package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
  478. package/src/session/intervention/index.ts +16 -0
  479. package/src/session/intervention/prev-artifact.ts +180 -0
  480. package/src/session/migration/__tests__/filesystem.test.ts +263 -0
  481. package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
  482. package/src/session/migration/__tests__/marker.test.ts +84 -0
  483. package/src/session/migration/errors.ts +23 -0
  484. package/src/session/migration/filesystem.ts +401 -0
  485. package/src/session/migration/id-prefix.ts +146 -0
  486. package/src/session/migration/index.ts +38 -0
  487. package/src/session/migration/marker.ts +131 -0
  488. package/src/session/retention/__tests__/archive.test.ts +316 -0
  489. package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
  490. package/src/session/retention/archive-backend-ref.ts +17 -0
  491. package/src/session/retention/archive.ts +281 -0
  492. package/src/session/retention/backend.ts +107 -0
  493. package/src/session/retention/disk-backend.ts +304 -0
  494. package/src/session/retention/index.ts +16 -0
  495. package/src/session/retention/policy.ts +53 -0
  496. package/src/session/summary/__tests__/materialize.test.ts +341 -0
  497. package/src/session/summary/deliverable.ts +84 -0
  498. package/src/session/summary/index.ts +31 -0
  499. package/src/session/summary/materialize.ts +169 -0
  500. package/src/session/summary/ref.ts +104 -0
  501. package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
  502. package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
  503. package/src/session/workspace/driver.ts +60 -0
  504. package/src/session/workspace/git-worktree.ts +209 -0
  505. package/src/session/workspace/index.ts +25 -0
  506. package/src/session/workspace/path-builder.ts +71 -0
  507. package/src/session/workspace/ref.ts +50 -0
  508. package/src/session/workspace/registry.ts +42 -0
  509. package/src/store/conversation/memory.ts +23 -0
  510. package/src/store/session/__tests__/disk.test.ts +346 -0
  511. package/src/store/session/__tests__/memory.test.ts +327 -0
  512. package/src/store/session/disk.ts +920 -0
  513. package/src/store/session/index.ts +14 -0
  514. package/src/store/session/linkage.ts +80 -0
  515. package/src/store/session/memory.ts +400 -0
  516. package/src/store/session/messages.ts +21 -0
  517. package/src/types/agent/base.ts +31 -1
  518. package/src/types/agent/task.ts +58 -2
  519. package/src/types/conversation/index.ts +7 -0
  520. package/src/types/ids/index.ts +41 -3
  521. package/src/types/invocation/__tests__/state.test.ts +37 -29
  522. package/src/types/invocation/index.ts +26 -10
  523. package/src/types/run/config.ts +12 -1
  524. package/src/types/run/events.ts +36 -1
  525. package/src/types/run/index.ts +8 -0
  526. package/src/types/run/metadata.ts +24 -1
  527. package/src/types/run/status.ts +33 -0
  528. package/src/types/session/ids.ts +34 -0
  529. package/src/types/session/index.ts +28 -0
  530. package/src/types/session/store.ts +229 -0
  531. package/src/utils/id.ts +55 -4
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Integration — retention archive / restore round-trip wired through the
3
+ * real stack: `InMemorySessionStore` + `DiskArchiveBackend` (pointed at
4
+ * `tmpdir()`) + `ArchivalManager` + `GitWorktreeDriver`.
5
+ *
6
+ * Covers roadmap §5 invariants: §12.3 retention deny-by-default, §12.3
7
+ * archive produces tombstone (in-slot), tombstone navigable via `drill`,
8
+ * restore full fidelity round-trip (Phase 9 closed synthetic-id loss),
9
+ * idempotent workspace dispose.
10
+ */
11
+
12
+ import { mkdtempSync, rmSync } from 'node:fs'
13
+ import { tmpdir } from 'node:os'
14
+ import { join } from 'node:path'
15
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
16
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
17
+ import { createUserMessage } from '../../../types/message/index.js'
18
+ import type { WorkspaceId } from '../../../types/session/ids.js'
19
+ import { ArchivalManager, ArchiveNotConfiguredError } from '../../retention/archive.js'
20
+ import { DiskArchiveBackend } from '../../retention/disk-backend.js'
21
+ import type { WorkspaceRef } from '../../workspace/ref.js'
22
+ import { WorkspaceBackendRegistry } from '../../workspace/registry.js'
23
+ import { DEFAULT_TENANT, agentActor, userActor } from './_fixtures.js'
24
+
25
+ async function seedIdleSubSession(store: InMemorySessionStore) {
26
+ const project = await store.createProject(
27
+ { tenantId: DEFAULT_TENANT, name: 'archive' },
28
+ DEFAULT_TENANT,
29
+ )
30
+ const parent = await store.createSession(
31
+ { projectId: project.id, currentActor: userActor('usr_a') },
32
+ DEFAULT_TENANT,
33
+ )
34
+ const child = await store.createSession(
35
+ { projectId: project.id, currentActor: agentActor('agt_w') },
36
+ DEFAULT_TENANT,
37
+ )
38
+ const sub = await store.createSubSession(
39
+ {
40
+ parentSessionId: parent.id,
41
+ childSessionId: child.id,
42
+ kind: 'agent_spawn',
43
+ spawnedBy: userActor('usr_a'),
44
+ },
45
+ DEFAULT_TENANT,
46
+ )
47
+ await store.updateSubSession({ ...sub, status: 'idle' }, DEFAULT_TENANT)
48
+ return { project, parent, child, sub }
49
+ }
50
+
51
+ describe('Integration — retention archive / restore', () => {
52
+ let rootDir: string
53
+ let store: InMemorySessionStore
54
+ let backend: DiskArchiveBackend
55
+
56
+ beforeEach(() => {
57
+ rootDir = mkdtempSync(join(tmpdir(), 'namzu-integration-retention-'))
58
+ store = new InMemorySessionStore()
59
+ backend = new DiskArchiveBackend({ rootDir })
60
+ })
61
+
62
+ afterEach(() => {
63
+ rmSync(rootDir, { recursive: true, force: true })
64
+ })
65
+
66
+ it('archive idle sub-session → tombstone attached (status=archived + archiveRef + archivedAt)', async () => {
67
+ const { sub } = await seedIdleSubSession(store)
68
+ const manager = new ArchivalManager({
69
+ sessionStore: store,
70
+ workspaceRegistry: new WorkspaceBackendRegistry(),
71
+ archiveBackend: backend,
72
+ })
73
+
74
+ const tombstone = await manager.archive(sub.id, DEFAULT_TENANT)
75
+ expect(tombstone.archiveRef.startsWith('arc_')).toBe(true)
76
+
77
+ const after = await store.getSubSession(sub.id, DEFAULT_TENANT)
78
+ expect(after?.status).toBe('archived')
79
+ expect(after?.archiveRef).toBe(tombstone.archiveRef)
80
+ expect(after?.archivedAt).toBeInstanceOf(Date)
81
+ })
82
+
83
+ it('drill(parent) post-archive: archived SubSession still navigable with tombstone fields', async () => {
84
+ const { parent, sub } = await seedIdleSubSession(store)
85
+ const manager = new ArchivalManager({
86
+ sessionStore: store,
87
+ workspaceRegistry: new WorkspaceBackendRegistry(),
88
+ archiveBackend: backend,
89
+ })
90
+ const tombstone = await manager.archive(sub.id, DEFAULT_TENANT)
91
+
92
+ const view = await store.drill(parent.id, DEFAULT_TENANT)
93
+ expect(view?.children).toHaveLength(1)
94
+ const child = view?.children[0]
95
+ expect(child?.id).toBe(sub.id)
96
+ expect(child?.status).toBe('archived')
97
+ expect(child?.archiveRef).toBe(tombstone.archiveRef)
98
+ })
99
+
100
+ it('restore recovers the archive bundle with original MessageId fidelity (not synthetic msg_restored_N)', async () => {
101
+ const { sub, child } = await seedIdleSubSession(store)
102
+ const msg1Id = await store.appendMessage(child.id, createUserMessage('first'), DEFAULT_TENANT)
103
+ const msg2Id = await store.appendMessage(child.id, createUserMessage('second'), DEFAULT_TENANT)
104
+
105
+ const manager = new ArchivalManager({
106
+ sessionStore: store,
107
+ workspaceRegistry: new WorkspaceBackendRegistry(),
108
+ archiveBackend: backend,
109
+ })
110
+ const tombstone = await manager.archive(sub.id, DEFAULT_TENANT)
111
+
112
+ // Restore via backend directly to verify round-trip fidelity
113
+ // (ArchivalManager.restore does NOT return the bundle — it only flips
114
+ // status back to idle).
115
+ const bundle = await backend.restore(tombstone.archiveRef)
116
+ expect(bundle.messages).toHaveLength(2)
117
+ expect(bundle.messages[0]?.id).toBe(msg1Id)
118
+ expect(bundle.messages[1]?.id).toBe(msg2Id)
119
+ expect(bundle.messages[0]?.id.startsWith('msg_restored_')).toBe(false)
120
+
121
+ await manager.restore(sub.id, DEFAULT_TENANT)
122
+ const after = await store.getSubSession(sub.id, DEFAULT_TENANT)
123
+ expect(after?.status).toBe('idle')
124
+ expect(after?.archiveRef).toBeUndefined()
125
+ expect(after?.archivedAt).toBeUndefined()
126
+ })
127
+
128
+ it('deny-by-default: project without archiveBackend → ArchiveNotConfiguredError on archive()', async () => {
129
+ const { sub } = await seedIdleSubSession(store)
130
+ const manager = new ArchivalManager({
131
+ sessionStore: store,
132
+ workspaceRegistry: new WorkspaceBackendRegistry(),
133
+ // archiveBackend omitted — archival fully disabled.
134
+ })
135
+
136
+ await expect(manager.archive(sub.id, DEFAULT_TENANT)).rejects.toBeInstanceOf(
137
+ ArchiveNotConfiguredError,
138
+ )
139
+
140
+ // Sub-session untouched.
141
+ const after = await store.getSubSession(sub.id, DEFAULT_TENANT)
142
+ expect(after?.status).toBe('idle')
143
+ })
144
+
145
+ it('idempotent dispose: workspace already disposed → archive completes without error', async () => {
146
+ const { sub } = await seedIdleSubSession(store)
147
+
148
+ // Registry with a driver whose `dispose` throws a generic error.
149
+ const registry = new WorkspaceBackendRegistry()
150
+ registry.register({
151
+ kind: 'git-worktree',
152
+ async create() {
153
+ return {
154
+ id: 'wsp_x' as WorkspaceId,
155
+ meta: {
156
+ backend: 'git-worktree',
157
+ repoRoot: '/r',
158
+ branch: 'main',
159
+ worktreePath: '/r/x',
160
+ },
161
+ createdAt: new Date(),
162
+ }
163
+ },
164
+ async branch(ref) {
165
+ return ref
166
+ },
167
+ async dispose() {
168
+ throw new Error('simulated already-disposed race')
169
+ },
170
+ async inspect() {
171
+ return { exists: false, currentRef: 'HEAD', isDirty: false }
172
+ },
173
+ })
174
+
175
+ const workspaceRef: WorkspaceRef = {
176
+ id: 'wsp_live' as WorkspaceId,
177
+ meta: { backend: 'git-worktree', repoRoot: '/r', branch: 'main', worktreePath: '/r/y' },
178
+ createdAt: new Date(),
179
+ }
180
+ await store.updateSubSession(
181
+ { ...sub, status: 'idle', workspaceId: workspaceRef.id },
182
+ DEFAULT_TENANT,
183
+ )
184
+
185
+ const manager = new ArchivalManager({
186
+ sessionStore: store,
187
+ workspaceRegistry: registry,
188
+ archiveBackend: backend,
189
+ workspaceResolver: async () => workspaceRef,
190
+ })
191
+
192
+ const tombstone = await manager.archive(sub.id, DEFAULT_TENANT)
193
+ expect(tombstone.archiveRef.startsWith('arc_')).toBe(true)
194
+
195
+ // Committed record persists despite dispose failure.
196
+ const after = await store.getSubSession(sub.id, DEFAULT_TENANT)
197
+ expect(after?.status).toBe('archived')
198
+ })
199
+
200
+ it('archive full round-trip: archive → restore → archive again succeeds', async () => {
201
+ const { sub } = await seedIdleSubSession(store)
202
+ const manager = new ArchivalManager({
203
+ sessionStore: store,
204
+ workspaceRegistry: new WorkspaceBackendRegistry(),
205
+ archiveBackend: backend,
206
+ })
207
+ const tombstone1 = await manager.archive(sub.id, DEFAULT_TENANT)
208
+ await manager.restore(sub.id, DEFAULT_TENANT)
209
+
210
+ const after = await store.getSubSession(sub.id, DEFAULT_TENANT)
211
+ expect(after?.status).toBe('idle')
212
+
213
+ // Re-archive produces a fresh tombstone.
214
+ const tombstone2 = await manager.archive(sub.id, DEFAULT_TENANT)
215
+ expect(tombstone2.archiveRef).not.toBe(tombstone1.archiveRef)
216
+ })
217
+
218
+ it('onArchived callback receives the tombstone exactly once', async () => {
219
+ const { sub } = await seedIdleSubSession(store)
220
+ const onArchived = vi.fn()
221
+ const manager = new ArchivalManager({
222
+ sessionStore: store,
223
+ workspaceRegistry: new WorkspaceBackendRegistry(),
224
+ archiveBackend: backend,
225
+ onArchived,
226
+ })
227
+ const tombstone = await manager.archive(sub.id, DEFAULT_TENANT)
228
+ expect(onArchived).toHaveBeenCalledTimes(1)
229
+ expect(onArchived).toHaveBeenCalledWith(tombstone)
230
+ })
231
+ })
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Integration — SessionSummaryMaterializer + SessionStore atomic transition,
3
+ * plus the crash-recovery path.
4
+ *
5
+ * Covers roadmap §5 invariants: §8.1 (summary kernel-owned, no agent-callable
6
+ * emission surface), §8.1 atomic with terminal transition, recovery path
7
+ * when the status-flip lost to a mid-flight crash. `SessionAlreadySummarizedError`
8
+ * on concurrent re-materialize.
9
+ *
10
+ * The kernel-ownership assertion is expressed both structurally (the
11
+ * `materializedBy: 'kernel'` brand on the persisted record) and by routing
12
+ * every successful materialize through the Materializer — no test below calls
13
+ * `store.recordSummary` directly, and the compile-time type narrows the
14
+ * argument to `& { materializedBy: 'kernel' }` so an agent-constructed payload
15
+ * would fail typecheck (not just runtime validation).
16
+ */
17
+
18
+ import { describe, expect, it } from 'vitest'
19
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
20
+ import type { SessionId } from '../../../types/ids/index.js'
21
+ import type { SummaryId } from '../../../types/session/ids.js'
22
+ import { SessionSummaryMaterializer } from '../../summary/materialize.js'
23
+ import { SessionAlreadySummarizedError } from '../../summary/ref.js'
24
+ import { DEFAULT_TENANT, agentActor } from './_fixtures.js'
25
+
26
+ async function seedActive(store: InMemorySessionStore) {
27
+ const project = await store.createProject(
28
+ { tenantId: DEFAULT_TENANT, name: 'summary' },
29
+ DEFAULT_TENANT,
30
+ )
31
+ const session = await store.createSession(
32
+ { projectId: project.id, currentActor: agentActor('agt_worker') },
33
+ DEFAULT_TENANT,
34
+ )
35
+ await store.updateSession({ ...session, status: 'active' }, DEFAULT_TENANT)
36
+ return { project, session: { ...session, status: 'active' as const } }
37
+ }
38
+
39
+ function makeGen(): () => SummaryId {
40
+ let n = 0
41
+ return () => `sum_materialize_${++n}` as SummaryId
42
+ }
43
+
44
+ describe('Integration — summary materialization E2E', () => {
45
+ it('Materializer writes summary + flips session active→idle atomically', async () => {
46
+ const store = new InMemorySessionStore()
47
+ const { session } = await seedActive(store)
48
+ const materializer = new SessionSummaryMaterializer({
49
+ store,
50
+ generateSummaryId: makeGen(),
51
+ })
52
+
53
+ const summary = await materializer.materialize({
54
+ sessionId: session.id,
55
+ tenantId: DEFAULT_TENANT,
56
+ finalOutcome: { status: 'succeeded' },
57
+ agentSummary: 'done',
58
+ declaredDeliverables: [],
59
+ keyDecisions: [],
60
+ })
61
+
62
+ // Persisted.
63
+ const stored = await store.getSummary(session.id, DEFAULT_TENANT)
64
+ expect(stored?.id).toBe(summary.id)
65
+ expect(stored?.materializedBy).toBe('kernel')
66
+
67
+ // Status atomically flipped.
68
+ const reloaded = await store.getSession(session.id, DEFAULT_TENANT)
69
+ expect(reloaded?.status).toBe('idle')
70
+ })
71
+
72
+ it('§8.1 atomicity invariant: no external observer sees terminal without summary', async () => {
73
+ // With InMemorySessionStore the two writes happen inside a single Map
74
+ // method call — there is no observable mid-state. We assert by reading
75
+ // both resources immediately after a single awaited materialize: the
76
+ // terminal status and the summary are visible together.
77
+ const store = new InMemorySessionStore()
78
+ const { session } = await seedActive(store)
79
+ const materializer = new SessionSummaryMaterializer({
80
+ store,
81
+ generateSummaryId: makeGen(),
82
+ })
83
+
84
+ await materializer.materialize({
85
+ sessionId: session.id,
86
+ tenantId: DEFAULT_TENANT,
87
+ finalOutcome: { status: 'succeeded' },
88
+ agentSummary: '',
89
+ declaredDeliverables: [],
90
+ keyDecisions: [],
91
+ })
92
+
93
+ const [finalSession, finalSummary] = await Promise.all([
94
+ store.getSession(session.id, DEFAULT_TENANT),
95
+ store.getSummary(session.id, DEFAULT_TENANT),
96
+ ])
97
+ // Atomic pairing: idle status AND persisted summary present together.
98
+ expect(finalSession?.status).toBe('idle')
99
+ expect(finalSummary).not.toBeNull()
100
+ })
101
+
102
+ it('concurrent re-materialize rejects with SessionAlreadySummarizedError', async () => {
103
+ const store = new InMemorySessionStore()
104
+ const { session } = await seedActive(store)
105
+ const materializer = new SessionSummaryMaterializer({
106
+ store,
107
+ generateSummaryId: makeGen(),
108
+ })
109
+
110
+ await materializer.materialize({
111
+ sessionId: session.id,
112
+ tenantId: DEFAULT_TENANT,
113
+ finalOutcome: { status: 'succeeded' },
114
+ agentSummary: 'first',
115
+ declaredDeliverables: [],
116
+ keyDecisions: [],
117
+ })
118
+
119
+ await expect(
120
+ materializer.materialize({
121
+ sessionId: session.id,
122
+ tenantId: DEFAULT_TENANT,
123
+ finalOutcome: { status: 'succeeded' },
124
+ agentSummary: 'second',
125
+ declaredDeliverables: [],
126
+ keyDecisions: [],
127
+ }),
128
+ ).rejects.toBeInstanceOf(SessionAlreadySummarizedError)
129
+ })
130
+
131
+ it('crash recovery: summary persisted + session still active → recover() replays idempotently', async () => {
132
+ const store = new InMemorySessionStore()
133
+ const { session } = await seedActive(store)
134
+ const materializer = new SessionSummaryMaterializer({
135
+ store,
136
+ generateSummaryId: makeGen(),
137
+ })
138
+
139
+ // Materialize once (happy path writes both). Then simulate a crash by
140
+ // forcing the session status back to `active` while the summary record
141
+ // stays intact — mimicking summary.json landing but session.json being
142
+ // lost to a mid-write power failure (see session/summary/materialize.ts
143
+ // `recover()` docs).
144
+ await materializer.materialize({
145
+ sessionId: session.id,
146
+ tenantId: DEFAULT_TENANT,
147
+ finalOutcome: { status: 'succeeded' },
148
+ agentSummary: '',
149
+ declaredDeliverables: [],
150
+ keyDecisions: [],
151
+ })
152
+ const mid = await store.getSession(session.id, DEFAULT_TENANT)
153
+ if (!mid) throw new Error('mid session missing')
154
+ await store.updateSession({ ...mid, status: 'active' }, DEFAULT_TENANT)
155
+
156
+ // Recovery call re-triggers the store's flip path without minting a
157
+ // new summary id.
158
+ const recovered = await materializer.recover(session.id, DEFAULT_TENANT)
159
+ expect(recovered).not.toBeNull()
160
+
161
+ const reloaded = await store.getSession(session.id, DEFAULT_TENANT)
162
+ expect(reloaded?.status).toBe('idle')
163
+
164
+ // Second recover call with session already idle: still idempotent.
165
+ const recovered2 = await materializer.recover(session.id, DEFAULT_TENANT)
166
+ expect(recovered2?.id).toBe(recovered?.id)
167
+ const reloaded2 = await store.getSession(session.id, DEFAULT_TENANT)
168
+ expect(reloaded2?.status).toBe('idle')
169
+ })
170
+
171
+ it('agent cannot construct SessionSummaryRef directly: recordSummary rejects non-kernel payload', async () => {
172
+ // The SessionStore contract narrows `recordSummary` to
173
+ // `SessionSummaryRef & { materializedBy: 'kernel' }`. Agents cannot
174
+ // type-construct a brand literal of `'kernel'` without going through
175
+ // the Materializer (see session/summary/ref.ts module header). Even
176
+ // attempting to cast into the shape and call directly would bypass
177
+ // the materialize ordering (status-check, length-check,
178
+ // already-exists guard). This test exercises the runtime guard: a
179
+ // second kernel-branded record for an already-summarized session
180
+ // rejects with SessionAlreadySummarizedError.
181
+ const store = new InMemorySessionStore()
182
+ const { session } = await seedActive(store)
183
+ const materializer = new SessionSummaryMaterializer({
184
+ store,
185
+ generateSummaryId: makeGen(),
186
+ })
187
+ await materializer.materialize({
188
+ sessionId: session.id,
189
+ tenantId: DEFAULT_TENANT,
190
+ finalOutcome: { status: 'succeeded' },
191
+ agentSummary: '',
192
+ declaredDeliverables: [],
193
+ keyDecisions: [],
194
+ })
195
+
196
+ // Direct call with a fabricated "kernel" ref payload — rejected
197
+ // because a summary already exists (store guard). The kernel-brand
198
+ // check at the type layer prevents naive agent-side construction; the
199
+ // runtime guard here catches store-level re-entry (materialize goes
200
+ // through the same path).
201
+ await expect(
202
+ store.recordSummary(
203
+ {
204
+ id: 'sum_fake' as SummaryId,
205
+ sessionRef: session.id,
206
+ tenantId: DEFAULT_TENANT,
207
+ outcome: { status: 'succeeded' },
208
+ deliverables: [],
209
+ agentSummary: 'forged',
210
+ keyDecisions: [],
211
+ at: new Date(),
212
+ materializedBy: 'kernel',
213
+ },
214
+ DEFAULT_TENANT,
215
+ ),
216
+ ).rejects.toBeInstanceOf(SessionAlreadySummarizedError)
217
+ })
218
+
219
+ it('missing session: materialize throws a not-found error', async () => {
220
+ const store = new InMemorySessionStore()
221
+ const materializer = new SessionSummaryMaterializer({
222
+ store,
223
+ generateSummaryId: makeGen(),
224
+ })
225
+
226
+ await expect(
227
+ materializer.materialize({
228
+ sessionId: 'ses_never' as SessionId,
229
+ tenantId: DEFAULT_TENANT,
230
+ finalOutcome: { status: 'succeeded' },
231
+ agentSummary: '',
232
+ declaredDeliverables: [],
233
+ keyDecisions: [],
234
+ }),
235
+ ).rejects.toThrow(/not found/)
236
+ })
237
+ })