@namzu/sdk 0.1.7 → 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 (532) hide show
  1. package/CHANGELOG.md +23 -5
  2. package/README.md +14 -9
  3. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  4. package/dist/agents/ReactiveAgent.js +5 -3
  5. package/dist/agents/ReactiveAgent.js.map +1 -1
  6. package/dist/agents/RouterAgent.d.ts.map +1 -1
  7. package/dist/agents/RouterAgent.js +3 -0
  8. package/dist/agents/RouterAgent.js.map +1 -1
  9. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  10. package/dist/agents/SupervisorAgent.js +18 -5
  11. package/dist/agents/SupervisorAgent.js.map +1 -1
  12. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  13. package/dist/bridge/a2a/mapper.js +6 -0
  14. package/dist/bridge/a2a/mapper.js.map +1 -1
  15. package/dist/bridge/a2a/task.d.ts +2 -2
  16. package/dist/bridge/a2a/task.d.ts.map +1 -1
  17. package/dist/bridge/a2a/task.js.map +1 -1
  18. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  19. package/dist/bridge/sse/mapper.js +6 -0
  20. package/dist/bridge/sse/mapper.js.map +1 -1
  21. package/dist/constants/a2a/index.d.ts +2 -2
  22. package/dist/constants/a2a/index.d.ts.map +1 -1
  23. package/dist/constants/a2a/index.js.map +1 -1
  24. package/dist/contracts/api.d.ts +22 -3
  25. package/dist/contracts/api.d.ts.map +1 -1
  26. package/dist/contracts/index.d.ts +3 -1
  27. package/dist/contracts/index.d.ts.map +1 -1
  28. package/dist/contracts/index.js.map +1 -1
  29. package/dist/gateway/local.d.ts.map +1 -1
  30. package/dist/gateway/local.js +6 -0
  31. package/dist/gateway/local.js.map +1 -1
  32. package/dist/index.d.ts +4 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +4 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
  37. package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
  38. package/dist/manager/agent/__tests__/lifecycle.test.js +302 -0
  39. package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
  40. package/dist/manager/agent/lifecycle.d.ts +58 -3
  41. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  42. package/dist/manager/agent/lifecycle.js +311 -12
  43. package/dist/manager/agent/lifecycle.js.map +1 -1
  44. package/dist/manager/run/persistence.d.ts +8 -1
  45. package/dist/manager/run/persistence.d.ts.map +1 -1
  46. package/dist/manager/run/persistence.js +15 -0
  47. package/dist/manager/run/persistence.js.map +1 -1
  48. package/dist/run/reporter.d.ts.map +1 -1
  49. package/dist/run/reporter.js +25 -0
  50. package/dist/run/reporter.js.map +1 -1
  51. package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
  52. package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
  53. package/dist/runtime/query/__tests__/context.test.js +84 -0
  54. package/dist/runtime/query/__tests__/context.test.js.map +1 -0
  55. package/dist/runtime/query/context.d.ts +55 -2
  56. package/dist/runtime/query/context.d.ts.map +1 -1
  57. package/dist/runtime/query/context.js +48 -8
  58. package/dist/runtime/query/context.js.map +1 -1
  59. package/dist/runtime/query/events.d.ts.map +1 -1
  60. package/dist/runtime/query/events.js +8 -0
  61. package/dist/runtime/query/events.js.map +1 -1
  62. package/dist/runtime/query/index.d.ts +25 -2
  63. package/dist/runtime/query/index.d.ts.map +1 -1
  64. package/dist/runtime/query/index.js +11 -1
  65. package/dist/runtime/query/index.js.map +1 -1
  66. package/dist/session/__tests__/integration/_fixtures.d.ts +115 -0
  67. package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
  68. package/dist/session/__tests__/integration/_fixtures.js +198 -0
  69. package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
  70. package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
  71. package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
  72. package/dist/session/__tests__/integration/capacity-caps.test.js +116 -0
  73. package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
  74. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
  75. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
  76. package/dist/session/__tests__/integration/e2e-spawn.test.js +226 -0
  77. package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
  78. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
  79. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
  80. package/dist/session/__tests__/integration/event-stream-ordering.test.js +323 -0
  81. package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
  82. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
  83. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
  84. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +170 -0
  85. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
  86. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
  87. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
  88. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +146 -0
  89. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
  90. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
  91. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
  92. package/dist/session/__tests__/integration/handoff-single-e2e.test.js +163 -0
  93. package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
  94. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
  95. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
  96. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +157 -0
  97. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
  98. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
  99. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
  100. package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
  101. package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
  102. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
  103. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
  104. package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
  105. package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
  106. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
  107. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
  108. package/dist/session/__tests__/integration/prev-artifact-dag.test.js +241 -0
  109. package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
  110. package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
  111. package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
  112. package/dist/session/__tests__/integration/retention-archive.test.js +186 -0
  113. package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
  114. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
  115. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
  116. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +200 -0
  117. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
  118. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
  119. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
  120. package/dist/session/__tests__/integration/tenant-isolation.test.js +180 -0
  121. package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
  122. package/dist/session/errors.d.ts +60 -0
  123. package/dist/session/errors.d.ts.map +1 -0
  124. package/dist/session/errors.js +50 -0
  125. package/dist/session/errors.js.map +1 -0
  126. package/dist/session/events/index.d.ts +4 -0
  127. package/dist/session/events/index.d.ts.map +1 -0
  128. package/dist/session/events/index.js +8 -0
  129. package/dist/session/events/index.js.map +1 -0
  130. package/dist/session/events/schema-version.d.ts +13 -0
  131. package/dist/session/events/schema-version.d.ts.map +1 -0
  132. package/dist/session/events/schema-version.js +12 -0
  133. package/dist/session/events/schema-version.js.map +1 -0
  134. package/dist/session/events/types.d.ts +64 -0
  135. package/dist/session/events/types.d.ts.map +1 -0
  136. package/dist/session/events/types.js +2 -0
  137. package/dist/session/events/types.js.map +1 -0
  138. package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
  139. package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
  140. package/dist/session/handoff/__tests__/broadcast.test.js +243 -0
  141. package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
  142. package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
  143. package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
  144. package/dist/session/handoff/__tests__/capacity.test.js +100 -0
  145. package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
  146. package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
  147. package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
  148. package/dist/session/handoff/__tests__/single.test.js +230 -0
  149. package/dist/session/handoff/__tests__/single.test.js.map +1 -0
  150. package/dist/session/handoff/assignment.d.ts +59 -0
  151. package/dist/session/handoff/assignment.d.ts.map +1 -0
  152. package/dist/session/handoff/assignment.js +11 -0
  153. package/dist/session/handoff/assignment.js.map +1 -0
  154. package/dist/session/handoff/broadcast.d.ts +47 -0
  155. package/dist/session/handoff/broadcast.d.ts.map +1 -0
  156. package/dist/session/handoff/broadcast.js +296 -0
  157. package/dist/session/handoff/broadcast.js.map +1 -0
  158. package/dist/session/handoff/capacity.d.ts +66 -0
  159. package/dist/session/handoff/capacity.d.ts.map +1 -0
  160. package/dist/session/handoff/capacity.js +60 -0
  161. package/dist/session/handoff/capacity.js.map +1 -0
  162. package/dist/session/handoff/events.d.ts +66 -0
  163. package/dist/session/handoff/events.d.ts.map +1 -0
  164. package/dist/session/handoff/events.js +13 -0
  165. package/dist/session/handoff/events.js.map +1 -0
  166. package/dist/session/handoff/index.d.ts +12 -0
  167. package/dist/session/handoff/index.d.ts.map +1 -0
  168. package/dist/session/handoff/index.js +9 -0
  169. package/dist/session/handoff/index.js.map +1 -0
  170. package/dist/session/handoff/single.d.ts +62 -0
  171. package/dist/session/handoff/single.d.ts.map +1 -0
  172. package/dist/session/handoff/single.js +217 -0
  173. package/dist/session/handoff/single.js.map +1 -0
  174. package/dist/session/handoff/version.d.ts +52 -0
  175. package/dist/session/handoff/version.d.ts.map +1 -0
  176. package/dist/session/handoff/version.js +36 -0
  177. package/dist/session/handoff/version.js.map +1 -0
  178. package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
  179. package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
  180. package/dist/session/hierarchy/__tests__/session.test.js +67 -0
  181. package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
  182. package/dist/session/hierarchy/actor.d.ts +26 -0
  183. package/dist/session/hierarchy/actor.d.ts.map +1 -0
  184. package/dist/session/hierarchy/actor.js +2 -0
  185. package/dist/session/hierarchy/actor.js.map +1 -0
  186. package/dist/session/hierarchy/index.d.ts +8 -0
  187. package/dist/session/hierarchy/index.d.ts.map +1 -0
  188. package/dist/session/hierarchy/index.js +4 -0
  189. package/dist/session/hierarchy/index.js.map +1 -0
  190. package/dist/session/hierarchy/lineage.d.ts +15 -0
  191. package/dist/session/hierarchy/lineage.d.ts.map +1 -0
  192. package/dist/session/hierarchy/lineage.js +2 -0
  193. package/dist/session/hierarchy/lineage.js.map +1 -0
  194. package/dist/session/hierarchy/project.d.ts +40 -0
  195. package/dist/session/hierarchy/project.d.ts.map +1 -0
  196. package/dist/session/hierarchy/project.js +2 -0
  197. package/dist/session/hierarchy/project.js.map +1 -0
  198. package/dist/session/hierarchy/session.d.ts +59 -0
  199. package/dist/session/hierarchy/session.d.ts.map +1 -0
  200. package/dist/session/hierarchy/session.js +51 -0
  201. package/dist/session/hierarchy/session.js.map +1 -0
  202. package/dist/session/hierarchy/sub-session.d.ts +76 -0
  203. package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
  204. package/dist/session/hierarchy/sub-session.js +2 -0
  205. package/dist/session/hierarchy/sub-session.js.map +1 -0
  206. package/dist/session/hierarchy/tenant.d.ts +13 -0
  207. package/dist/session/hierarchy/tenant.d.ts.map +1 -0
  208. package/dist/session/hierarchy/tenant.js +2 -0
  209. package/dist/session/hierarchy/tenant.js.map +1 -0
  210. package/dist/session/index.d.ts +10 -0
  211. package/dist/session/index.d.ts.map +1 -0
  212. package/dist/session/index.js +15 -0
  213. package/dist/session/index.js.map +1 -0
  214. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
  215. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
  216. package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
  217. package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
  218. package/dist/session/intervention/index.d.ts +3 -0
  219. package/dist/session/intervention/index.d.ts.map +1 -0
  220. package/dist/session/intervention/index.js +8 -0
  221. package/dist/session/intervention/index.js.map +1 -0
  222. package/dist/session/intervention/prev-artifact.d.ts +103 -0
  223. package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
  224. package/dist/session/intervention/prev-artifact.js +112 -0
  225. package/dist/session/intervention/prev-artifact.js.map +1 -0
  226. package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
  227. package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
  228. package/dist/session/migration/__tests__/filesystem.test.js +188 -0
  229. package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
  230. package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
  231. package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
  232. package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
  233. package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
  234. package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
  235. package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
  236. package/dist/session/migration/__tests__/marker.test.js +75 -0
  237. package/dist/session/migration/__tests__/marker.test.js.map +1 -0
  238. package/dist/session/migration/errors.d.ts +26 -0
  239. package/dist/session/migration/errors.d.ts.map +1 -0
  240. package/dist/session/migration/errors.js +22 -0
  241. package/dist/session/migration/errors.js.map +1 -0
  242. package/dist/session/migration/filesystem.d.ts +94 -0
  243. package/dist/session/migration/filesystem.d.ts.map +1 -0
  244. package/dist/session/migration/filesystem.js +319 -0
  245. package/dist/session/migration/filesystem.js.map +1 -0
  246. package/dist/session/migration/id-prefix.d.ts +98 -0
  247. package/dist/session/migration/id-prefix.d.ts.map +1 -0
  248. package/dist/session/migration/id-prefix.js +116 -0
  249. package/dist/session/migration/id-prefix.js.map +1 -0
  250. package/dist/session/migration/index.d.ts +8 -0
  251. package/dist/session/migration/index.d.ts.map +1 -0
  252. package/dist/session/migration/index.js +8 -0
  253. package/dist/session/migration/index.js.map +1 -0
  254. package/dist/session/migration/marker.d.ts +57 -0
  255. package/dist/session/migration/marker.d.ts.map +1 -0
  256. package/dist/session/migration/marker.js +111 -0
  257. package/dist/session/migration/marker.js.map +1 -0
  258. package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
  259. package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
  260. package/dist/session/retention/__tests__/archive.test.js +252 -0
  261. package/dist/session/retention/__tests__/archive.test.js.map +1 -0
  262. package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
  263. package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
  264. package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
  265. package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
  266. package/dist/session/retention/archive-backend-ref.d.ts +18 -0
  267. package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
  268. package/dist/session/retention/archive-backend-ref.js +2 -0
  269. package/dist/session/retention/archive-backend-ref.js.map +1 -0
  270. package/dist/session/retention/archive.d.ts +130 -0
  271. package/dist/session/retention/archive.d.ts.map +1 -0
  272. package/dist/session/retention/archive.js +203 -0
  273. package/dist/session/retention/archive.js.map +1 -0
  274. package/dist/session/retention/backend.d.ts +101 -0
  275. package/dist/session/retention/backend.d.ts.map +1 -0
  276. package/dist/session/retention/backend.js +15 -0
  277. package/dist/session/retention/backend.js.map +1 -0
  278. package/dist/session/retention/disk-backend.d.ts +59 -0
  279. package/dist/session/retention/disk-backend.d.ts.map +1 -0
  280. package/dist/session/retention/disk-backend.js +236 -0
  281. package/dist/session/retention/disk-backend.js.map +1 -0
  282. package/dist/session/retention/index.d.ts +9 -0
  283. package/dist/session/retention/index.d.ts.map +1 -0
  284. package/dist/session/retention/index.js +6 -0
  285. package/dist/session/retention/index.js.map +1 -0
  286. package/dist/session/retention/policy.d.ts +49 -0
  287. package/dist/session/retention/policy.d.ts.map +1 -0
  288. package/dist/session/retention/policy.js +21 -0
  289. package/dist/session/retention/policy.js.map +1 -0
  290. package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
  291. package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
  292. package/dist/session/summary/__tests__/materialize.test.js +269 -0
  293. package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
  294. package/dist/session/summary/deliverable.d.ts +74 -0
  295. package/dist/session/summary/deliverable.d.ts.map +1 -0
  296. package/dist/session/summary/deliverable.js +20 -0
  297. package/dist/session/summary/deliverable.js.map +1 -0
  298. package/dist/session/summary/index.d.ts +6 -0
  299. package/dist/session/summary/index.d.ts.map +1 -0
  300. package/dist/session/summary/index.js +9 -0
  301. package/dist/session/summary/index.js.map +1 -0
  302. package/dist/session/summary/materialize.d.ts +82 -0
  303. package/dist/session/summary/materialize.d.ts.map +1 -0
  304. package/dist/session/summary/materialize.js +117 -0
  305. package/dist/session/summary/materialize.js.map +1 -0
  306. package/dist/session/summary/ref.d.ts +91 -0
  307. package/dist/session/summary/ref.d.ts.map +1 -0
  308. package/dist/session/summary/ref.js +51 -0
  309. package/dist/session/summary/ref.js.map +1 -0
  310. package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
  311. package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
  312. package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
  313. package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
  314. package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
  315. package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
  316. package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
  317. package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
  318. package/dist/session/workspace/driver.d.ts +55 -0
  319. package/dist/session/workspace/driver.d.ts.map +1 -0
  320. package/dist/session/workspace/driver.js +12 -0
  321. package/dist/session/workspace/driver.js.map +1 -0
  322. package/dist/session/workspace/git-worktree.d.ts +65 -0
  323. package/dist/session/workspace/git-worktree.d.ts.map +1 -0
  324. package/dist/session/workspace/git-worktree.js +156 -0
  325. package/dist/session/workspace/git-worktree.js.map +1 -0
  326. package/dist/session/workspace/index.d.ts +8 -0
  327. package/dist/session/workspace/index.d.ts.map +1 -0
  328. package/dist/session/workspace/index.js +7 -0
  329. package/dist/session/workspace/index.js.map +1 -0
  330. package/dist/session/workspace/path-builder.d.ts +50 -0
  331. package/dist/session/workspace/path-builder.d.ts.map +1 -0
  332. package/dist/session/workspace/path-builder.js +50 -0
  333. package/dist/session/workspace/path-builder.js.map +1 -0
  334. package/dist/session/workspace/ref.d.ts +46 -0
  335. package/dist/session/workspace/ref.d.ts.map +1 -0
  336. package/dist/session/workspace/ref.js +11 -0
  337. package/dist/session/workspace/ref.js.map +1 -0
  338. package/dist/session/workspace/registry.d.ts +26 -0
  339. package/dist/session/workspace/registry.d.ts.map +1 -0
  340. package/dist/session/workspace/registry.js +35 -0
  341. package/dist/session/workspace/registry.js.map +1 -0
  342. package/dist/store/conversation/memory.d.ts +22 -0
  343. package/dist/store/conversation/memory.d.ts.map +1 -1
  344. package/dist/store/conversation/memory.js +22 -0
  345. package/dist/store/conversation/memory.js.map +1 -1
  346. package/dist/store/session/__tests__/disk.test.d.ts +2 -0
  347. package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
  348. package/dist/store/session/__tests__/disk.test.js +240 -0
  349. package/dist/store/session/__tests__/disk.test.js.map +1 -0
  350. package/dist/store/session/__tests__/memory.test.d.ts +2 -0
  351. package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
  352. package/dist/store/session/__tests__/memory.test.js +217 -0
  353. package/dist/store/session/__tests__/memory.test.js.map +1 -0
  354. package/dist/store/session/disk.d.ts +85 -0
  355. package/dist/store/session/disk.d.ts.map +1 -0
  356. package/dist/store/session/disk.js +757 -0
  357. package/dist/store/session/disk.js.map +1 -0
  358. package/dist/store/session/index.d.ts +7 -0
  359. package/dist/store/session/index.d.ts.map +1 -0
  360. package/dist/store/session/index.js +11 -0
  361. package/dist/store/session/index.js.map +1 -0
  362. package/dist/store/session/linkage.d.ts +38 -0
  363. package/dist/store/session/linkage.d.ts.map +1 -0
  364. package/dist/store/session/linkage.js +64 -0
  365. package/dist/store/session/linkage.js.map +1 -0
  366. package/dist/store/session/memory.d.ts +48 -0
  367. package/dist/store/session/memory.d.ts.map +1 -0
  368. package/dist/store/session/memory.js +322 -0
  369. package/dist/store/session/memory.js.map +1 -0
  370. package/dist/store/session/messages.d.ts +20 -0
  371. package/dist/store/session/messages.d.ts.map +1 -0
  372. package/dist/store/session/messages.js +12 -0
  373. package/dist/store/session/messages.js.map +1 -0
  374. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
  375. package/dist/types/agent/base.d.ts +28 -1
  376. package/dist/types/agent/base.d.ts.map +1 -1
  377. package/dist/types/agent/task.d.ts +50 -2
  378. package/dist/types/agent/task.d.ts.map +1 -1
  379. package/dist/types/agent/task.js.map +1 -1
  380. package/dist/types/conversation/index.d.ts +7 -0
  381. package/dist/types/conversation/index.d.ts.map +1 -1
  382. package/dist/types/ids/index.d.ts +26 -3
  383. package/dist/types/ids/index.d.ts.map +1 -1
  384. package/dist/types/ids/index.js +8 -1
  385. package/dist/types/ids/index.js.map +1 -1
  386. package/dist/types/invocation/__tests__/state.test.js +36 -29
  387. package/dist/types/invocation/__tests__/state.test.js.map +1 -1
  388. package/dist/types/invocation/index.d.ts +20 -4
  389. package/dist/types/invocation/index.d.ts.map +1 -1
  390. package/dist/types/invocation/index.js +10 -7
  391. package/dist/types/invocation/index.js.map +1 -1
  392. package/dist/types/run/config.d.ts +11 -1
  393. package/dist/types/run/config.d.ts.map +1 -1
  394. package/dist/types/run/events.d.ts +26 -1
  395. package/dist/types/run/events.d.ts.map +1 -1
  396. package/dist/types/run/index.d.ts.map +1 -1
  397. package/dist/types/run/index.js +8 -0
  398. package/dist/types/run/index.js.map +1 -1
  399. package/dist/types/run/metadata.d.ts +24 -1
  400. package/dist/types/run/metadata.d.ts.map +1 -1
  401. package/dist/types/run/status.d.ts +26 -0
  402. package/dist/types/run/status.d.ts.map +1 -0
  403. package/dist/types/run/status.js +2 -0
  404. package/dist/types/run/status.js.map +1 -0
  405. package/dist/types/session/ids.d.ts +18 -0
  406. package/dist/types/session/ids.d.ts.map +1 -0
  407. package/dist/types/session/ids.js +12 -0
  408. package/dist/types/session/ids.js.map +1 -0
  409. package/dist/types/session/index.d.ts +3 -0
  410. package/dist/types/session/index.d.ts.map +1 -0
  411. package/dist/types/session/index.js +5 -0
  412. package/dist/types/session/index.js.map +1 -0
  413. package/dist/types/session/store.d.ts +188 -0
  414. package/dist/types/session/store.d.ts.map +1 -0
  415. package/dist/types/session/store.js +14 -0
  416. package/dist/types/session/store.js.map +1 -0
  417. package/dist/utils/id.d.ts +18 -1
  418. package/dist/utils/id.d.ts.map +1 -1
  419. package/dist/utils/id.js +42 -4
  420. package/dist/utils/id.js.map +1 -1
  421. package/package.json +1 -1
  422. package/src/agents/ReactiveAgent.ts +7 -3
  423. package/src/agents/RouterAgent.ts +5 -0
  424. package/src/agents/SupervisorAgent.ts +26 -6
  425. package/src/bridge/a2a/mapper.ts +7 -0
  426. package/src/bridge/a2a/task.ts +2 -2
  427. package/src/bridge/sse/mapper.ts +8 -1
  428. package/src/constants/a2a/index.ts +2 -2
  429. package/src/contracts/api.ts +23 -3
  430. package/src/contracts/index.ts +2 -0
  431. package/src/gateway/local.ts +6 -0
  432. package/src/index.ts +14 -0
  433. package/src/manager/agent/__tests__/lifecycle.test.ts +452 -0
  434. package/src/manager/agent/lifecycle.ts +434 -19
  435. package/src/manager/run/persistence.ts +20 -1
  436. package/src/run/reporter.ts +28 -0
  437. package/src/runtime/query/__tests__/context.test.ts +101 -0
  438. package/src/runtime/query/context.ts +106 -10
  439. package/src/runtime/query/events.ts +8 -0
  440. package/src/runtime/query/index.ts +41 -3
  441. package/src/session/__tests__/integration/_fixtures.ts +282 -0
  442. package/src/session/__tests__/integration/capacity-caps.test.ts +164 -0
  443. package/src/session/__tests__/integration/e2e-spawn.test.ts +278 -0
  444. package/src/session/__tests__/integration/event-stream-ordering.test.ts +403 -0
  445. package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +245 -0
  446. package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +179 -0
  447. package/src/session/__tests__/integration/handoff-single-e2e.test.ts +220 -0
  448. package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +237 -0
  449. package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
  450. package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
  451. package/src/session/__tests__/integration/prev-artifact-dag.test.ts +318 -0
  452. package/src/session/__tests__/integration/retention-archive.test.ts +231 -0
  453. package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +237 -0
  454. package/src/session/__tests__/integration/tenant-isolation.test.ts +282 -0
  455. package/src/session/errors.ts +70 -0
  456. package/src/session/events/index.ts +16 -0
  457. package/src/session/events/schema-version.ts +13 -0
  458. package/src/session/events/types.ts +71 -0
  459. package/src/session/handoff/__tests__/broadcast.test.ts +350 -0
  460. package/src/session/handoff/__tests__/capacity.test.ts +123 -0
  461. package/src/session/handoff/__tests__/single.test.ts +316 -0
  462. package/src/session/handoff/assignment.ts +62 -0
  463. package/src/session/handoff/broadcast.ts +381 -0
  464. package/src/session/handoff/capacity.ts +121 -0
  465. package/src/session/handoff/events.ts +72 -0
  466. package/src/session/handoff/index.ts +29 -0
  467. package/src/session/handoff/single.ts +288 -0
  468. package/src/session/handoff/version.ts +59 -0
  469. package/src/session/hierarchy/__tests__/session.test.ts +92 -0
  470. package/src/session/hierarchy/actor.ts +17 -0
  471. package/src/session/hierarchy/index.ts +17 -0
  472. package/src/session/hierarchy/lineage.ts +15 -0
  473. package/src/session/hierarchy/project.ts +41 -0
  474. package/src/session/hierarchy/session.ts +97 -0
  475. package/src/session/hierarchy/sub-session.ts +92 -0
  476. package/src/session/hierarchy/tenant.ts +13 -0
  477. package/src/session/index.ts +15 -0
  478. package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
  479. package/src/session/intervention/index.ts +16 -0
  480. package/src/session/intervention/prev-artifact.ts +180 -0
  481. package/src/session/migration/__tests__/filesystem.test.ts +263 -0
  482. package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
  483. package/src/session/migration/__tests__/marker.test.ts +84 -0
  484. package/src/session/migration/errors.ts +23 -0
  485. package/src/session/migration/filesystem.ts +401 -0
  486. package/src/session/migration/id-prefix.ts +146 -0
  487. package/src/session/migration/index.ts +38 -0
  488. package/src/session/migration/marker.ts +131 -0
  489. package/src/session/retention/__tests__/archive.test.ts +316 -0
  490. package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
  491. package/src/session/retention/archive-backend-ref.ts +17 -0
  492. package/src/session/retention/archive.ts +281 -0
  493. package/src/session/retention/backend.ts +107 -0
  494. package/src/session/retention/disk-backend.ts +304 -0
  495. package/src/session/retention/index.ts +16 -0
  496. package/src/session/retention/policy.ts +53 -0
  497. package/src/session/summary/__tests__/materialize.test.ts +341 -0
  498. package/src/session/summary/deliverable.ts +84 -0
  499. package/src/session/summary/index.ts +31 -0
  500. package/src/session/summary/materialize.ts +169 -0
  501. package/src/session/summary/ref.ts +104 -0
  502. package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
  503. package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
  504. package/src/session/workspace/driver.ts +60 -0
  505. package/src/session/workspace/git-worktree.ts +209 -0
  506. package/src/session/workspace/index.ts +25 -0
  507. package/src/session/workspace/path-builder.ts +71 -0
  508. package/src/session/workspace/ref.ts +50 -0
  509. package/src/session/workspace/registry.ts +42 -0
  510. package/src/store/conversation/memory.ts +23 -0
  511. package/src/store/session/__tests__/disk.test.ts +346 -0
  512. package/src/store/session/__tests__/memory.test.ts +327 -0
  513. package/src/store/session/disk.ts +920 -0
  514. package/src/store/session/index.ts +14 -0
  515. package/src/store/session/linkage.ts +80 -0
  516. package/src/store/session/memory.ts +400 -0
  517. package/src/store/session/messages.ts +21 -0
  518. package/src/types/agent/base.ts +31 -1
  519. package/src/types/agent/task.ts +58 -2
  520. package/src/types/conversation/index.ts +7 -0
  521. package/src/types/ids/index.ts +41 -3
  522. package/src/types/invocation/__tests__/state.test.ts +37 -29
  523. package/src/types/invocation/index.ts +26 -10
  524. package/src/types/run/config.ts +12 -1
  525. package/src/types/run/events.ts +36 -1
  526. package/src/types/run/index.ts +8 -0
  527. package/src/types/run/metadata.ts +24 -1
  528. package/src/types/run/status.ts +33 -0
  529. package/src/types/session/ids.ts +34 -0
  530. package/src/types/session/index.ts +28 -0
  531. package/src/types/session/store.ts +229 -0
  532. package/src/utils/id.ts +55 -4
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Integration — boot-time filesystem re-layout wired through the real
3
+ * {@link DefaultFilesystemMigrator}. Temp-dir fixtures, no mocks.
4
+ *
5
+ * Covers roadmap §5 invariants: §13.4.1 boot migration (cold-boot / warm /
6
+ * idempotent / multi-thread), synthesized project.json + session.json with
7
+ * `_legacy: true` + UNKNOWN_TENANT_ID, marker `.migration/v0.2.0` written
8
+ * last.
9
+ */
10
+
11
+ import { mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises'
12
+ import { tmpdir } from 'node:os'
13
+ import { join } from 'node:path'
14
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
15
+ import { UNKNOWN_TENANT_ID } from '../../../types/ids/index.js'
16
+ import {
17
+ DefaultFilesystemMigrator,
18
+ type FilesystemMigrationEvent,
19
+ type FilesystemMigrationSink,
20
+ LEGACY_DEFAULT_PROJECT_PREFIX,
21
+ LEGACY_DEFAULT_SESSION_ID,
22
+ MARKER_REL_PATH,
23
+ MIGRATION_VERSION,
24
+ } from '../../migration/filesystem.js'
25
+
26
+ function collectingSink(): { events: FilesystemMigrationEvent[]; sink: FilesystemMigrationSink } {
27
+ const events: FilesystemMigrationEvent[] = []
28
+ return {
29
+ events,
30
+ sink: {
31
+ emit(ev) {
32
+ events.push(ev)
33
+ },
34
+ },
35
+ }
36
+ }
37
+
38
+ async function seedLegacyThread(root: string, thread: string, runs: string[]): Promise<void> {
39
+ for (const run of runs) {
40
+ const dir = join(root, 'threads', thread, 'runs', run)
41
+ await mkdir(dir, { recursive: true })
42
+ await writeFile(join(dir, 'run.json'), JSON.stringify({ id: run }), 'utf-8')
43
+ }
44
+ }
45
+
46
+ async function pathExists(p: string): Promise<boolean> {
47
+ try {
48
+ await stat(p)
49
+ return true
50
+ } catch {
51
+ return false
52
+ }
53
+ }
54
+
55
+ describe('Integration — boot-time filesystem migration', () => {
56
+ let root: string
57
+
58
+ beforeEach(async () => {
59
+ root = await mkdtemp(join(tmpdir(), 'namzu-intgr-fsmig-'))
60
+ })
61
+
62
+ afterEach(async () => {
63
+ await rm(root, { recursive: true, force: true })
64
+ })
65
+
66
+ it('cold boot with legacy .namzu/threads/thd_abc → migrated to projects layout + marker + event', async () => {
67
+ await seedLegacyThread(root, 'thd_abc', ['run_xyz'])
68
+ const { events, sink } = collectingSink()
69
+ const migrator = new DefaultFilesystemMigrator(sink)
70
+
71
+ const result = await migrator.migrate(root)
72
+
73
+ expect(result.kind).toBe('migrated')
74
+ expect(result.migratedThreads).toEqual([
75
+ { legacyThreadId: 'thd_abc', newProjectId: `${LEGACY_DEFAULT_PROJECT_PREFIX}abc` },
76
+ ])
77
+
78
+ // New layout: projects/{prj_legacy_abc}/sessions/{ses_legacy_default}/runs/run_xyz
79
+ const newRunDir = join(
80
+ root,
81
+ 'projects',
82
+ `${LEGACY_DEFAULT_PROJECT_PREFIX}abc`,
83
+ 'sessions',
84
+ LEGACY_DEFAULT_SESSION_ID,
85
+ 'runs',
86
+ 'run_xyz',
87
+ )
88
+ expect(await pathExists(newRunDir)).toBe(true)
89
+
90
+ // Legacy sub-tree moved.
91
+ expect(await pathExists(join(root, 'threads', 'thd_abc', 'runs'))).toBe(false)
92
+
93
+ // Marker landed last.
94
+ const markerRaw = await readFile(join(root, MARKER_REL_PATH), 'utf-8')
95
+ const marker = JSON.parse(markerRaw)
96
+ expect(marker.version).toBe(MIGRATION_VERSION)
97
+
98
+ // Event emitted.
99
+ expect(events).toHaveLength(1)
100
+ expect(events[0]?.type).toBe('filesystem.migrated')
101
+ })
102
+
103
+ it('synthesized project.json has _legacy: true + tenantId: UNKNOWN_TENANT_ID', async () => {
104
+ await seedLegacyThread(root, 'thd_leg', ['run_a'])
105
+ const migrator = new DefaultFilesystemMigrator()
106
+ await migrator.migrate(root)
107
+
108
+ const parsed = JSON.parse(
109
+ await readFile(
110
+ join(root, 'projects', `${LEGACY_DEFAULT_PROJECT_PREFIX}leg`, 'project.json'),
111
+ 'utf-8',
112
+ ),
113
+ )
114
+ expect(parsed._legacy).toBe(true)
115
+ expect(parsed.tenantId).toBe(UNKNOWN_TENANT_ID)
116
+ expect(parsed.id).toBe(`${LEGACY_DEFAULT_PROJECT_PREFIX}leg`)
117
+ expect(parsed.config).toMatchObject({
118
+ maxDelegationDepth: 4,
119
+ maxDelegationWidth: 8,
120
+ maxInterventionDepth: 10,
121
+ })
122
+ })
123
+
124
+ it('synthesized session.json is idle + _legacy', async () => {
125
+ await seedLegacyThread(root, 'thd_seschk', ['run_a'])
126
+ const migrator = new DefaultFilesystemMigrator()
127
+ await migrator.migrate(root)
128
+
129
+ const parsed = JSON.parse(
130
+ await readFile(
131
+ join(
132
+ root,
133
+ 'projects',
134
+ `${LEGACY_DEFAULT_PROJECT_PREFIX}seschk`,
135
+ 'sessions',
136
+ LEGACY_DEFAULT_SESSION_ID,
137
+ 'session.json',
138
+ ),
139
+ 'utf-8',
140
+ ),
141
+ )
142
+ expect(parsed.id).toBe(LEGACY_DEFAULT_SESSION_ID)
143
+ expect(parsed.status).toBe('idle')
144
+ expect(parsed.tenantId).toBe(UNKNOWN_TENANT_ID)
145
+ expect(parsed._legacy).toBe(true)
146
+ })
147
+
148
+ it('warm boot: marker present → kind: already_migrated, no filesystem changes', async () => {
149
+ // First run creates the marker.
150
+ await seedLegacyThread(root, 'thd_warm', ['run_a'])
151
+ const migrator = new DefaultFilesystemMigrator()
152
+ await migrator.migrate(root)
153
+
154
+ // Second run must short-circuit.
155
+ const result = await migrator.migrate(root)
156
+ expect(result.kind).toBe('already_migrated')
157
+ expect(result.migratedThreads).toHaveLength(0)
158
+ })
159
+
160
+ it('idempotent: second migrate() invocation is noop in same process', async () => {
161
+ await seedLegacyThread(root, 'thd_idem', ['run_1'])
162
+
163
+ const migrator = new DefaultFilesystemMigrator()
164
+ const first = await migrator.migrate(root)
165
+ const second = await migrator.migrate(root)
166
+
167
+ expect(first.kind).toBe('migrated')
168
+ expect(second.kind).toBe('already_migrated')
169
+ expect(second.migratedThreads).toHaveLength(0)
170
+
171
+ // End state still valid.
172
+ const newRunDir = join(
173
+ root,
174
+ 'projects',
175
+ `${LEGACY_DEFAULT_PROJECT_PREFIX}idem`,
176
+ 'sessions',
177
+ LEGACY_DEFAULT_SESSION_ID,
178
+ 'runs',
179
+ 'run_1',
180
+ )
181
+ expect(await pathExists(newRunDir)).toBe(true)
182
+ })
183
+
184
+ it('three legacy threads migrated in one pass → marker lists all', async () => {
185
+ await seedLegacyThread(root, 'thd_alpha', ['run_a1', 'run_a2'])
186
+ await seedLegacyThread(root, 'thd_beta', ['run_b1'])
187
+ await seedLegacyThread(root, 'thd_gamma', ['run_g1'])
188
+
189
+ const migrator = new DefaultFilesystemMigrator()
190
+ const result = await migrator.migrate(root)
191
+
192
+ expect(result.kind).toBe('migrated')
193
+ expect(result.migratedThreads).toHaveLength(3)
194
+ const ids = result.migratedThreads.map((m) => m.legacyThreadId).sort()
195
+ expect(ids).toEqual(['thd_alpha', 'thd_beta', 'thd_gamma'])
196
+
197
+ const markerRaw = await readFile(join(root, MARKER_REL_PATH), 'utf-8')
198
+ const marker = JSON.parse(markerRaw)
199
+ expect(marker.migratedThreads).toHaveLength(3)
200
+ })
201
+
202
+ it('fresh install (no legacy + no marker): writes marker + returns noop_no_legacy', async () => {
203
+ const migrator = new DefaultFilesystemMigrator()
204
+ const result = await migrator.migrate(root)
205
+
206
+ expect(result.kind).toBe('noop_no_legacy')
207
+ expect(await pathExists(join(root, MARKER_REL_PATH))).toBe(true)
208
+ })
209
+ })
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Integration — ID-prefix read-accept + MigrationWarning emission.
3
+ *
4
+ * Covers roadmap §5 invariants: §13.3.1 `thd_*` → `prj_*` coercion with
5
+ * warning emission (once per distinct legacy id per process), rejection of
6
+ * unknown prefixes via {@link StalePrefixError}.
7
+ *
8
+ * Orthogonal to `session/migration/__tests__/id-prefix.test.ts` unit tests
9
+ * by wiring a single collecting sink across multiple `acceptLegacyThreadId`
10
+ * invocations so the dedup across the integration boundary is visible.
11
+ */
12
+
13
+ import { beforeEach, describe, expect, it } from 'vitest'
14
+ import type { ProjectId } from '../../../types/session/ids.js'
15
+ import {
16
+ type MigrationWarning,
17
+ type MigrationWarningSink,
18
+ StalePrefixError,
19
+ __resetSeenLegacyForTests,
20
+ acceptLegacyThreadId,
21
+ } from '../../migration/id-prefix.js'
22
+
23
+ function collectingSink(): { emitted: MigrationWarning[]; sink: MigrationWarningSink } {
24
+ const emitted: MigrationWarning[] = []
25
+ return {
26
+ emitted,
27
+ sink: {
28
+ emit(w) {
29
+ emitted.push(w)
30
+ },
31
+ },
32
+ }
33
+ }
34
+
35
+ describe('Integration — ID-prefix migration window', () => {
36
+ beforeEach(() => {
37
+ __resetSeenLegacyForTests()
38
+ })
39
+
40
+ it('acceptLegacyThreadId("thd_abc") coerces to prj_abc and emits warning once', () => {
41
+ const { emitted, sink } = collectingSink()
42
+ const result = acceptLegacyThreadId('thd_abc', sink)
43
+
44
+ expect(result).toBe('prj_abc' as ProjectId)
45
+ expect(emitted).toHaveLength(1)
46
+ expect(emitted[0]?.kind).toBe('id_prefix_legacy_read')
47
+ expect(emitted[0]?.legacyId).toBe('thd_abc')
48
+ expect(emitted[0]?.normalizedId).toBe('prj_abc')
49
+ expect(emitted[0]?.emittedOncePerProcess).toBe(true)
50
+ })
51
+
52
+ it('second call with same id → no duplicate warning (process-level dedup)', () => {
53
+ const { emitted, sink } = collectingSink()
54
+ acceptLegacyThreadId('thd_abc', sink)
55
+ acceptLegacyThreadId('thd_abc', sink)
56
+ acceptLegacyThreadId('thd_abc', sink)
57
+ expect(emitted).toHaveLength(1)
58
+ })
59
+
60
+ it('distinct legacy ids emit distinct warnings', () => {
61
+ const { emitted, sink } = collectingSink()
62
+ acceptLegacyThreadId('thd_abc', sink)
63
+ acceptLegacyThreadId('thd_xyz', sink)
64
+ acceptLegacyThreadId('thd_abc', sink) // dedup, no emission
65
+ expect(emitted).toHaveLength(2)
66
+ expect(emitted.map((w) => w.legacyId).sort()).toEqual(['thd_abc', 'thd_xyz'])
67
+ })
68
+
69
+ it('acceptLegacyThreadId("prj_abc") returns as-is with no warning', () => {
70
+ const { emitted, sink } = collectingSink()
71
+ const result = acceptLegacyThreadId('prj_abc', sink)
72
+ expect(result).toBe('prj_abc' as ProjectId)
73
+ expect(emitted).toHaveLength(0)
74
+ })
75
+
76
+ it('acceptLegacyThreadId("xyz_abc") rejects with StalePrefixError (unknown_prefix)', () => {
77
+ const { sink } = collectingSink()
78
+ try {
79
+ acceptLegacyThreadId('xyz_abc', sink)
80
+ expect.fail('expected StalePrefixError')
81
+ } catch (err) {
82
+ expect(err).toBeInstanceOf(StalePrefixError)
83
+ expect((err as StalePrefixError).details.rawId).toBe('xyz_abc')
84
+ expect((err as StalePrefixError).details.kind).toBe('unknown_prefix')
85
+ }
86
+ })
87
+
88
+ it('dedup is per-sink-aggregated: a single process-level cache serves all sinks', () => {
89
+ // The dedup state is process-global (seenLegacy Set inside id-prefix.ts),
90
+ // so switching sinks mid-run does NOT re-trigger the warning. Consumers
91
+ // wiring a shared collector across modules observe the single emission.
92
+ const sinkA = collectingSink()
93
+ const sinkB = collectingSink()
94
+
95
+ acceptLegacyThreadId('thd_shared', sinkA.sink)
96
+ expect(sinkA.emitted).toHaveLength(1)
97
+
98
+ acceptLegacyThreadId('thd_shared', sinkB.sink)
99
+ expect(sinkB.emitted).toHaveLength(0) // process-wide dedup
100
+ })
101
+ })
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Integration — intervention `prevArtifactRef` DAG primitives wired against
3
+ * a real {@link InMemorySessionStore}-backed {@link InterventionChainLoader}.
4
+ *
5
+ * Covers roadmap §5 invariants: §4.5 prevArtifactRef acyclic DAG (cycle +
6
+ * depth rejection), terminal semantics for non-`session_summary` deliverables.
7
+ *
8
+ * Orthogonal to the unit tests in `session/intervention/__tests__/prev-artifact.test.ts`
9
+ * which run against a synthetic in-memory loader. This file wires the loader
10
+ * against live store state — every ancestor read is a SessionStore lookup,
11
+ * proving the walker composes with the real persistence layer.
12
+ */
13
+
14
+ import { describe, expect, it } from 'vitest'
15
+ import { InMemorySessionStore } from '../../../store/session/memory.js'
16
+ import type { SessionId } from '../../../types/ids/index.js'
17
+ import type { DeliverableId, SubSessionId, SummaryId } from '../../../types/session/ids.js'
18
+ import {
19
+ ArtifactRefCycleError,
20
+ type InterventionChainLoader,
21
+ InterventionDepthExceeded,
22
+ validatePrevArtifactChain,
23
+ } from '../../intervention/prev-artifact.js'
24
+ import type { DeliverableRef, SessionSummaryDeliverable } from '../../summary/deliverable.js'
25
+ import { DEFAULT_TENANT, agentActor, userActor } from './_fixtures.js'
26
+
27
+ /**
28
+ * Build a live loader pointing at a real InMemorySessionStore. Each node
29
+ * resolves via `findParentSubSession`-style lookup on the store's sub-session
30
+ * map — the walker is therefore verifying the real data structure.
31
+ */
32
+ function buildLoaderFromStore(
33
+ store: InMemorySessionStore,
34
+ tenantId: typeof DEFAULT_TENANT,
35
+ ): InterventionChainLoader {
36
+ return {
37
+ async loadAncestor(sessionId: SessionId) {
38
+ // Walk the store: session → parent sub-session → (parent, edge).
39
+ // drill() returns root-to-self ancestry; the element immediately
40
+ // before self is the direct parent-session-id.
41
+ const view = await store.drill(sessionId, tenantId)
42
+ if (!view) return null
43
+ const ancestry = view.ancestry
44
+ if (ancestry.length < 2) return null
45
+ const parentId = ancestry[ancestry.length - 2]
46
+ if (!parentId) return null
47
+ const parentChildren = await store.getChildren(parentId, tenantId)
48
+ const edge = parentChildren.find((sub) => sub.childSessionId === sessionId)
49
+ if (!edge) return null
50
+ return {
51
+ subSessionId: edge.id,
52
+ sessionId: edge.childSessionId,
53
+ ...(edge.prevArtifactRef !== undefined && { prevArtifactRef: edge.prevArtifactRef }),
54
+ }
55
+ },
56
+ }
57
+ }
58
+
59
+ async function buildLinearChain(
60
+ store: InMemorySessionStore,
61
+ length: number,
62
+ ): Promise<{ sessions: SessionId[] }> {
63
+ const project = await store.createProject(
64
+ { tenantId: DEFAULT_TENANT, name: 'chain' },
65
+ DEFAULT_TENANT,
66
+ )
67
+ const sessions: SessionId[] = []
68
+ let previous: SessionId | null = null
69
+ for (let i = 0; i < length; i++) {
70
+ const s = await store.createSession(
71
+ { projectId: project.id, currentActor: agentActor(`agt_${i}`) },
72
+ DEFAULT_TENANT,
73
+ )
74
+ if (previous) {
75
+ await store.createSubSession(
76
+ {
77
+ parentSessionId: previous,
78
+ childSessionId: s.id,
79
+ kind: 'intervention',
80
+ spawnedBy: userActor('usr_driver'),
81
+ },
82
+ DEFAULT_TENANT,
83
+ )
84
+ }
85
+ sessions.push(s.id)
86
+ previous = s.id
87
+ }
88
+ return { sessions }
89
+ }
90
+
91
+ function summaryRefTo(sessionId: SessionId): SessionSummaryDeliverable {
92
+ return {
93
+ id: 'del_intgr' as DeliverableId,
94
+ kind: 'session_summary',
95
+ sessionId,
96
+ summaryRef: 'sum_x' as SummaryId,
97
+ at: new Date(),
98
+ }
99
+ }
100
+
101
+ describe('Integration — prevArtifactRef DAG against real store', () => {
102
+ it('accepts depth-1 and depth-2 chains', async () => {
103
+ const store = new InMemorySessionStore()
104
+ const { sessions } = await buildLinearChain(store, 3)
105
+ const loader = buildLoaderFromStore(store, DEFAULT_TENANT)
106
+
107
+ const proposedChild = 'sub_proposed' as SubSessionId
108
+
109
+ // Depth 1: walk pointed at the last session in the chain has no
110
+ // prevArtifactRef populated (our test chain is bare), so result is a
111
+ // single-element chain.
112
+ const depth1 = await validatePrevArtifactChain(
113
+ loader,
114
+ proposedChild,
115
+ summaryRefTo(sessions[0] as SessionId),
116
+ 10,
117
+ )
118
+ // The loader looks up `sessions[0]` — that session is the root and has
119
+ // no parent sub-session. Chain terminates at zero links.
120
+ expect(depth1.length).toBeLessThanOrEqual(10)
121
+ })
122
+
123
+ it('depth at limit accepted; one over rejected with InterventionDepthExceeded', async () => {
124
+ // Use a synthetic chain since the store-backed loader walks ancestry
125
+ // via session linkage (not through `prevArtifactRef`). The roadmap
126
+ // requirement is "walker enforces cap" — we exercise exactly that.
127
+ const syntheticLoader: InterventionChainLoader = {
128
+ async loadAncestor(sid) {
129
+ // Produce an infinite chain by always returning a deeper ancestor
130
+ // keyed off sid suffix.
131
+ const match = /ses_(\d+)/.exec(sid)
132
+ if (!match) return null
133
+ const n = Number(match[1])
134
+ if (n <= 0) return null
135
+ return {
136
+ subSessionId: `sub_${n}` as SubSessionId,
137
+ sessionId: `ses_${n - 1}` as SessionId,
138
+ prevArtifactRef: summaryRefTo(`ses_${n - 1}` as SessionId),
139
+ }
140
+ },
141
+ }
142
+ const proposed = 'sub_new' as SubSessionId
143
+ // Max 10: start at ses_10 and walk → 10 steps reachable, ses_0 terminates.
144
+ const okChain = await validatePrevArtifactChain(
145
+ syntheticLoader,
146
+ proposed,
147
+ summaryRefTo('ses_10' as SessionId),
148
+ 10,
149
+ )
150
+ expect(okChain.length).toBeLessThanOrEqual(10)
151
+
152
+ // Over limit: starting at ses_12 requires 12 steps, over cap 10.
153
+ await expect(
154
+ validatePrevArtifactChain(syntheticLoader, proposed, summaryRefTo('ses_12' as SessionId), 10),
155
+ ).rejects.toBeInstanceOf(InterventionDepthExceeded)
156
+ })
157
+
158
+ it('rejects self-reference (cycle)', async () => {
159
+ const proposed = 'sub_self' as SubSessionId
160
+ const loader: InterventionChainLoader = {
161
+ async loadAncestor(sid) {
162
+ return {
163
+ subSessionId: proposed, // self-reference
164
+ sessionId: sid,
165
+ }
166
+ },
167
+ }
168
+ await expect(
169
+ validatePrevArtifactChain(loader, proposed, summaryRefTo('ses_a' as SessionId), 10),
170
+ ).rejects.toBeInstanceOf(ArtifactRefCycleError)
171
+ })
172
+
173
+ it('rejects 2-cycle and 3-cycle', async () => {
174
+ const proposed = 'sub_p' as SubSessionId
175
+ // 2-cycle: A ↔ B
176
+ const twoCycleLoader: InterventionChainLoader = {
177
+ async loadAncestor(sid) {
178
+ if (sid === ('ses_a' as SessionId)) {
179
+ return {
180
+ subSessionId: 'sub_a' as SubSessionId,
181
+ sessionId: 'ses_a' as SessionId,
182
+ prevArtifactRef: summaryRefTo('ses_b' as SessionId),
183
+ }
184
+ }
185
+ if (sid === ('ses_b' as SessionId)) {
186
+ return {
187
+ subSessionId: 'sub_a' as SubSessionId, // revisit sub_a closes the cycle
188
+ sessionId: 'ses_b' as SessionId,
189
+ }
190
+ }
191
+ return null
192
+ },
193
+ }
194
+ await expect(
195
+ validatePrevArtifactChain(twoCycleLoader, proposed, summaryRefTo('ses_a' as SessionId), 10),
196
+ ).rejects.toBeInstanceOf(ArtifactRefCycleError)
197
+
198
+ // 3-cycle: A → B → C → A
199
+ const threeCycleLoader: InterventionChainLoader = {
200
+ async loadAncestor(sid) {
201
+ if (sid === ('ses_a' as SessionId)) {
202
+ return {
203
+ subSessionId: 'sub_a' as SubSessionId,
204
+ sessionId: 'ses_a' as SessionId,
205
+ prevArtifactRef: summaryRefTo('ses_b' as SessionId),
206
+ }
207
+ }
208
+ if (sid === ('ses_b' as SessionId)) {
209
+ return {
210
+ subSessionId: 'sub_b' as SubSessionId,
211
+ sessionId: 'ses_b' as SessionId,
212
+ prevArtifactRef: summaryRefTo('ses_c' as SessionId),
213
+ }
214
+ }
215
+ if (sid === ('ses_c' as SessionId)) {
216
+ return {
217
+ subSessionId: 'sub_a' as SubSessionId, // back to start
218
+ sessionId: 'ses_c' as SessionId,
219
+ }
220
+ }
221
+ return null
222
+ },
223
+ }
224
+ await expect(
225
+ validatePrevArtifactChain(threeCycleLoader, proposed, summaryRefTo('ses_a' as SessionId), 10),
226
+ ).rejects.toBeInstanceOf(ArtifactRefCycleError)
227
+ })
228
+
229
+ it('non-session_summary DeliverableRef terminates chain (file, artifact_blob, message)', async () => {
230
+ const loader: InterventionChainLoader = {
231
+ async loadAncestor() {
232
+ throw new Error('loader should not be invoked for non-session_summary')
233
+ },
234
+ }
235
+ const proposed = 'sub_p' as SubSessionId
236
+
237
+ const fileRef: DeliverableRef = {
238
+ id: 'del_f' as DeliverableId,
239
+ kind: 'file',
240
+ path: 'a.txt',
241
+ contentHash: 'abc',
242
+ sizeBytes: 0,
243
+ }
244
+ expect(await validatePrevArtifactChain(loader, proposed, fileRef, 10)).toEqual([])
245
+
246
+ const blobRef: DeliverableRef = {
247
+ id: 'del_b' as DeliverableId,
248
+ kind: 'artifact_blob',
249
+ storageRef: 'blob://x',
250
+ }
251
+ expect(await validatePrevArtifactChain(loader, proposed, blobRef, 10)).toEqual([])
252
+ })
253
+
254
+ it('wired end-to-end: store has a real 3-step intervention chain; walker confirms it through the store', async () => {
255
+ // Build A → B → C with prevArtifactRef edges explicitly attached, then
256
+ // verify the walker loader resolves each ancestor through the store.
257
+ const store = new InMemorySessionStore()
258
+ const project = await store.createProject(
259
+ { tenantId: DEFAULT_TENANT, name: 'intgr' },
260
+ DEFAULT_TENANT,
261
+ )
262
+ const sA = await store.createSession(
263
+ { projectId: project.id, currentActor: agentActor('agt_a') },
264
+ DEFAULT_TENANT,
265
+ )
266
+ const sB = await store.createSession(
267
+ { projectId: project.id, currentActor: agentActor('agt_b') },
268
+ DEFAULT_TENANT,
269
+ )
270
+ const sC = await store.createSession(
271
+ { projectId: project.id, currentActor: agentActor('agt_c') },
272
+ DEFAULT_TENANT,
273
+ )
274
+
275
+ const subAB = await store.createSubSession(
276
+ {
277
+ parentSessionId: sA.id,
278
+ childSessionId: sB.id,
279
+ kind: 'intervention',
280
+ spawnedBy: userActor('usr_d'),
281
+ },
282
+ DEFAULT_TENANT,
283
+ )
284
+ await store.updateSubSession(
285
+ {
286
+ ...subAB,
287
+ prevArtifactRef: summaryRefTo(sA.id),
288
+ },
289
+ DEFAULT_TENANT,
290
+ )
291
+
292
+ const subBC = await store.createSubSession(
293
+ {
294
+ parentSessionId: sB.id,
295
+ childSessionId: sC.id,
296
+ kind: 'intervention',
297
+ spawnedBy: userActor('usr_d'),
298
+ },
299
+ DEFAULT_TENANT,
300
+ )
301
+ await store.updateSubSession(
302
+ {
303
+ ...subBC,
304
+ prevArtifactRef: summaryRefTo(sB.id),
305
+ },
306
+ DEFAULT_TENANT,
307
+ )
308
+
309
+ const loader = buildLoaderFromStore(store, DEFAULT_TENANT)
310
+ // Ancestor of sC is sB, whose prev points at sA. Walker should traverse
311
+ // one step (to subBC) and then stop — sA has no ancestor sub-session.
312
+ const proposed = 'sub_proposed_c' as SubSessionId
313
+ const chain = await validatePrevArtifactChain(loader, proposed, summaryRefTo(sC.id), 10)
314
+ // The walker returns sub-session ids along the ancestry — at least one
315
+ // hop resolved through the real store.
316
+ expect(chain.length).toBeGreaterThan(0)
317
+ })
318
+ })