@namzu/sdk 0.1.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (626) hide show
  1. package/CHANGELOG.md +69 -2
  2. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  3. package/dist/agents/ReactiveAgent.js +5 -2
  4. package/dist/agents/ReactiveAgent.js.map +1 -1
  5. package/dist/agents/RouterAgent.d.ts.map +1 -1
  6. package/dist/agents/RouterAgent.js +3 -0
  7. package/dist/agents/RouterAgent.js.map +1 -1
  8. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  9. package/dist/agents/SupervisorAgent.js +21 -5
  10. package/dist/agents/SupervisorAgent.js.map +1 -1
  11. package/dist/bridge/a2a/index.d.ts +1 -1
  12. package/dist/bridge/a2a/index.d.ts.map +1 -1
  13. package/dist/bridge/a2a/index.js +1 -1
  14. package/dist/bridge/a2a/index.js.map +1 -1
  15. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  16. package/dist/bridge/a2a/mapper.js +6 -0
  17. package/dist/bridge/a2a/mapper.js.map +1 -1
  18. package/dist/bridge/a2a/message.d.ts +0 -2
  19. package/dist/bridge/a2a/message.d.ts.map +1 -1
  20. package/dist/bridge/a2a/message.js +0 -26
  21. package/dist/bridge/a2a/message.js.map +1 -1
  22. package/dist/bridge/a2a/task.d.ts +5 -4
  23. package/dist/bridge/a2a/task.d.ts.map +1 -1
  24. package/dist/bridge/a2a/task.js +4 -4
  25. package/dist/bridge/a2a/task.js.map +1 -1
  26. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  27. package/dist/bridge/sse/mapper.js +6 -0
  28. package/dist/bridge/sse/mapper.js.map +1 -1
  29. package/dist/constants/a2a/index.d.ts +2 -2
  30. package/dist/constants/a2a/index.d.ts.map +1 -1
  31. package/dist/constants/a2a/index.js.map +1 -1
  32. package/dist/contracts/api.d.ts +14 -27
  33. package/dist/contracts/api.d.ts.map +1 -1
  34. package/dist/contracts/ids.d.ts +1 -1
  35. package/dist/contracts/ids.d.ts.map +1 -1
  36. package/dist/contracts/index.d.ts +3 -3
  37. package/dist/contracts/index.d.ts.map +1 -1
  38. package/dist/contracts/index.js +1 -1
  39. package/dist/contracts/index.js.map +1 -1
  40. package/dist/contracts/schemas.d.ts +1 -31
  41. package/dist/contracts/schemas.d.ts.map +1 -1
  42. package/dist/contracts/schemas.js +1 -7
  43. package/dist/contracts/schemas.js.map +1 -1
  44. package/dist/gateway/local.d.ts.map +1 -1
  45. package/dist/gateway/local.js +6 -0
  46. package/dist/gateway/local.js.map +1 -1
  47. package/dist/index.d.ts +6 -3
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +6 -3
  50. package/dist/index.js.map +1 -1
  51. package/dist/manager/agent/__tests__/lifecycle.test.d.ts +2 -0
  52. package/dist/manager/agent/__tests__/lifecycle.test.d.ts.map +1 -0
  53. package/dist/manager/agent/__tests__/lifecycle.test.js +316 -0
  54. package/dist/manager/agent/__tests__/lifecycle.test.js.map +1 -0
  55. package/dist/manager/agent/lifecycle.d.ts +67 -3
  56. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  57. package/dist/manager/agent/lifecycle.js +375 -14
  58. package/dist/manager/agent/lifecycle.js.map +1 -1
  59. package/dist/manager/index.d.ts +2 -0
  60. package/dist/manager/index.d.ts.map +1 -1
  61. package/dist/manager/index.js +1 -0
  62. package/dist/manager/index.js.map +1 -1
  63. package/dist/manager/run/persistence.d.ts +10 -1
  64. package/dist/manager/run/persistence.d.ts.map +1 -1
  65. package/dist/manager/run/persistence.js +20 -0
  66. package/dist/manager/run/persistence.js.map +1 -1
  67. package/dist/manager/thread/__tests__/lifecycle.test.d.ts +2 -0
  68. package/dist/manager/thread/__tests__/lifecycle.test.d.ts.map +1 -0
  69. package/dist/manager/thread/__tests__/lifecycle.test.js +216 -0
  70. package/dist/manager/thread/__tests__/lifecycle.test.js.map +1 -0
  71. package/dist/manager/thread/lifecycle.d.ts +105 -0
  72. package/dist/manager/thread/lifecycle.d.ts.map +1 -0
  73. package/dist/manager/thread/lifecycle.js +186 -0
  74. package/dist/manager/thread/lifecycle.js.map +1 -0
  75. package/dist/rag/retriever.js +2 -2
  76. package/dist/run/reporter.d.ts.map +1 -1
  77. package/dist/run/reporter.js +25 -0
  78. package/dist/run/reporter.js.map +1 -1
  79. package/dist/runtime/query/__tests__/context.test.d.ts +2 -0
  80. package/dist/runtime/query/__tests__/context.test.d.ts.map +1 -0
  81. package/dist/runtime/query/__tests__/context.test.js +85 -0
  82. package/dist/runtime/query/__tests__/context.test.js.map +1 -0
  83. package/dist/runtime/query/context-cache.d.ts +3 -3
  84. package/dist/runtime/query/context-cache.d.ts.map +1 -1
  85. package/dist/runtime/query/context-cache.js +2 -2
  86. package/dist/runtime/query/context-cache.js.map +1 -1
  87. package/dist/runtime/query/context.d.ts +45 -1
  88. package/dist/runtime/query/context.d.ts.map +1 -1
  89. package/dist/runtime/query/context.js +50 -8
  90. package/dist/runtime/query/context.js.map +1 -1
  91. package/dist/runtime/query/events.d.ts.map +1 -1
  92. package/dist/runtime/query/events.js +8 -0
  93. package/dist/runtime/query/events.js.map +1 -1
  94. package/dist/runtime/query/index.d.ts +22 -1
  95. package/dist/runtime/query/index.d.ts.map +1 -1
  96. package/dist/runtime/query/index.js +11 -0
  97. package/dist/runtime/query/index.js.map +1 -1
  98. package/dist/session/__tests__/integration/_fixtures.d.ts +122 -0
  99. package/dist/session/__tests__/integration/_fixtures.d.ts.map +1 -0
  100. package/dist/session/__tests__/integration/_fixtures.js +215 -0
  101. package/dist/session/__tests__/integration/_fixtures.js.map +1 -0
  102. package/dist/session/__tests__/integration/archive-gate.test.d.ts +15 -0
  103. package/dist/session/__tests__/integration/archive-gate.test.d.ts.map +1 -0
  104. package/dist/session/__tests__/integration/archive-gate.test.js +214 -0
  105. package/dist/session/__tests__/integration/archive-gate.test.js.map +1 -0
  106. package/dist/session/__tests__/integration/capacity-caps.test.d.ts +13 -0
  107. package/dist/session/__tests__/integration/capacity-caps.test.d.ts.map +1 -0
  108. package/dist/session/__tests__/integration/capacity-caps.test.js +123 -0
  109. package/dist/session/__tests__/integration/capacity-caps.test.js.map +1 -0
  110. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts +18 -0
  111. package/dist/session/__tests__/integration/e2e-spawn.test.d.ts.map +1 -0
  112. package/dist/session/__tests__/integration/e2e-spawn.test.js +238 -0
  113. package/dist/session/__tests__/integration/e2e-spawn.test.js.map +1 -0
  114. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts +15 -0
  115. package/dist/session/__tests__/integration/event-stream-ordering.test.d.ts.map +1 -0
  116. package/dist/session/__tests__/integration/event-stream-ordering.test.js +330 -0
  117. package/dist/session/__tests__/integration/event-stream-ordering.test.js.map +1 -0
  118. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts +12 -0
  119. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.d.ts.map +1 -0
  120. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js +182 -0
  121. package/dist/session/__tests__/integration/handoff-broadcast-e2e.test.js.map +1 -0
  122. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts +18 -0
  123. package/dist/session/__tests__/integration/handoff-illegal-transition.test.d.ts.map +1 -0
  124. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js +156 -0
  125. package/dist/session/__tests__/integration/handoff-illegal-transition.test.js.map +1 -0
  126. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts +15 -0
  127. package/dist/session/__tests__/integration/handoff-single-e2e.test.d.ts.map +1 -0
  128. package/dist/session/__tests__/integration/handoff-single-e2e.test.js +179 -0
  129. package/dist/session/__tests__/integration/handoff-single-e2e.test.js.map +1 -0
  130. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts +12 -0
  131. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.d.ts.map +1 -0
  132. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js +158 -0
  133. package/dist/session/__tests__/integration/hierarchy-lifecycle.test.js.map +1 -0
  134. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts +11 -0
  135. package/dist/session/__tests__/integration/migration-filesystem.test.d.ts.map +1 -0
  136. package/dist/session/__tests__/integration/migration-filesystem.test.js +140 -0
  137. package/dist/session/__tests__/integration/migration-filesystem.test.js.map +1 -0
  138. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts +13 -0
  139. package/dist/session/__tests__/integration/migration-id-prefix.test.d.ts.map +1 -0
  140. package/dist/session/__tests__/integration/migration-id-prefix.test.js +84 -0
  141. package/dist/session/__tests__/integration/migration-id-prefix.test.js.map +1 -0
  142. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts +14 -0
  143. package/dist/session/__tests__/integration/prev-artifact-dag.test.d.ts.map +1 -0
  144. package/dist/session/__tests__/integration/prev-artifact-dag.test.js +242 -0
  145. package/dist/session/__tests__/integration/prev-artifact-dag.test.js.map +1 -0
  146. package/dist/session/__tests__/integration/retention-archive.test.d.ts +12 -0
  147. package/dist/session/__tests__/integration/retention-archive.test.d.ts.map +1 -0
  148. package/dist/session/__tests__/integration/retention-archive.test.js +187 -0
  149. package/dist/session/__tests__/integration/retention-archive.test.js.map +1 -0
  150. package/dist/session/__tests__/integration/spawn-rollback.test.d.ts +26 -0
  151. package/dist/session/__tests__/integration/spawn-rollback.test.d.ts.map +1 -0
  152. package/dist/session/__tests__/integration/spawn-rollback.test.js +236 -0
  153. package/dist/session/__tests__/integration/spawn-rollback.test.js.map +1 -0
  154. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts +18 -0
  155. package/dist/session/__tests__/integration/summary-materialization-e2e.test.d.ts.map +1 -0
  156. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js +201 -0
  157. package/dist/session/__tests__/integration/summary-materialization-e2e.test.js.map +1 -0
  158. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts +14 -0
  159. package/dist/session/__tests__/integration/tenant-isolation.test.d.ts.map +1 -0
  160. package/dist/session/__tests__/integration/tenant-isolation.test.js +189 -0
  161. package/dist/session/__tests__/integration/tenant-isolation.test.js.map +1 -0
  162. package/dist/session/errors.d.ts +139 -0
  163. package/dist/session/errors.d.ts.map +1 -0
  164. package/dist/session/errors.js +107 -0
  165. package/dist/session/errors.js.map +1 -0
  166. package/dist/session/events/index.d.ts +4 -0
  167. package/dist/session/events/index.d.ts.map +1 -0
  168. package/dist/session/events/index.js +8 -0
  169. package/dist/session/events/index.js.map +1 -0
  170. package/dist/session/events/schema-version.d.ts +13 -0
  171. package/dist/session/events/schema-version.d.ts.map +1 -0
  172. package/dist/session/events/schema-version.js +12 -0
  173. package/dist/session/events/schema-version.js.map +1 -0
  174. package/dist/session/events/types.d.ts +64 -0
  175. package/dist/session/events/types.d.ts.map +1 -0
  176. package/dist/session/events/types.js +2 -0
  177. package/dist/session/events/types.js.map +1 -0
  178. package/dist/session/handoff/__tests__/broadcast.test.d.ts +2 -0
  179. package/dist/session/handoff/__tests__/broadcast.test.d.ts.map +1 -0
  180. package/dist/session/handoff/__tests__/broadcast.test.js +261 -0
  181. package/dist/session/handoff/__tests__/broadcast.test.js.map +1 -0
  182. package/dist/session/handoff/__tests__/capacity.test.d.ts +2 -0
  183. package/dist/session/handoff/__tests__/capacity.test.d.ts.map +1 -0
  184. package/dist/session/handoff/__tests__/capacity.test.js +103 -0
  185. package/dist/session/handoff/__tests__/capacity.test.js.map +1 -0
  186. package/dist/session/handoff/__tests__/single.test.d.ts +2 -0
  187. package/dist/session/handoff/__tests__/single.test.d.ts.map +1 -0
  188. package/dist/session/handoff/__tests__/single.test.js +239 -0
  189. package/dist/session/handoff/__tests__/single.test.js.map +1 -0
  190. package/dist/session/handoff/assignment.d.ts +71 -0
  191. package/dist/session/handoff/assignment.d.ts.map +1 -0
  192. package/dist/session/handoff/assignment.js +11 -0
  193. package/dist/session/handoff/assignment.js.map +1 -0
  194. package/dist/session/handoff/broadcast.d.ts +54 -0
  195. package/dist/session/handoff/broadcast.d.ts.map +1 -0
  196. package/dist/session/handoff/broadcast.js +311 -0
  197. package/dist/session/handoff/broadcast.js.map +1 -0
  198. package/dist/session/handoff/capacity.d.ts +66 -0
  199. package/dist/session/handoff/capacity.d.ts.map +1 -0
  200. package/dist/session/handoff/capacity.js +60 -0
  201. package/dist/session/handoff/capacity.js.map +1 -0
  202. package/dist/session/handoff/events.d.ts +66 -0
  203. package/dist/session/handoff/events.d.ts.map +1 -0
  204. package/dist/session/handoff/events.js +13 -0
  205. package/dist/session/handoff/events.js.map +1 -0
  206. package/dist/session/handoff/index.d.ts +12 -0
  207. package/dist/session/handoff/index.d.ts.map +1 -0
  208. package/dist/session/handoff/index.js +9 -0
  209. package/dist/session/handoff/index.js.map +1 -0
  210. package/dist/session/handoff/single.d.ts +69 -0
  211. package/dist/session/handoff/single.d.ts.map +1 -0
  212. package/dist/session/handoff/single.js +229 -0
  213. package/dist/session/handoff/single.js.map +1 -0
  214. package/dist/session/handoff/version.d.ts +52 -0
  215. package/dist/session/handoff/version.d.ts.map +1 -0
  216. package/dist/session/handoff/version.js +36 -0
  217. package/dist/session/handoff/version.js.map +1 -0
  218. package/dist/session/hierarchy/__tests__/session.test.d.ts +2 -0
  219. package/dist/session/hierarchy/__tests__/session.test.d.ts.map +1 -0
  220. package/dist/session/hierarchy/__tests__/session.test.js +69 -0
  221. package/dist/session/hierarchy/__tests__/session.test.js.map +1 -0
  222. package/dist/session/hierarchy/actor.d.ts +26 -0
  223. package/dist/session/hierarchy/actor.d.ts.map +1 -0
  224. package/dist/session/hierarchy/actor.js +2 -0
  225. package/dist/session/hierarchy/actor.js.map +1 -0
  226. package/dist/session/hierarchy/index.d.ts +9 -0
  227. package/dist/session/hierarchy/index.d.ts.map +1 -0
  228. package/dist/session/hierarchy/index.js +4 -0
  229. package/dist/session/hierarchy/index.js.map +1 -0
  230. package/dist/session/hierarchy/lineage.d.ts +15 -0
  231. package/dist/session/hierarchy/lineage.d.ts.map +1 -0
  232. package/dist/session/hierarchy/lineage.js +2 -0
  233. package/dist/session/hierarchy/lineage.js.map +1 -0
  234. package/dist/session/hierarchy/project.d.ts +40 -0
  235. package/dist/session/hierarchy/project.d.ts.map +1 -0
  236. package/dist/session/hierarchy/project.js +2 -0
  237. package/dist/session/hierarchy/project.js.map +1 -0
  238. package/dist/session/hierarchy/session.d.ts +71 -0
  239. package/dist/session/hierarchy/session.d.ts.map +1 -0
  240. package/dist/session/hierarchy/session.js +51 -0
  241. package/dist/session/hierarchy/session.js.map +1 -0
  242. package/dist/session/hierarchy/sub-session.d.ts +76 -0
  243. package/dist/session/hierarchy/sub-session.d.ts.map +1 -0
  244. package/dist/session/hierarchy/sub-session.js +2 -0
  245. package/dist/session/hierarchy/sub-session.js.map +1 -0
  246. package/dist/session/hierarchy/tenant.d.ts +13 -0
  247. package/dist/session/hierarchy/tenant.d.ts.map +1 -0
  248. package/dist/session/hierarchy/tenant.js +2 -0
  249. package/dist/session/hierarchy/tenant.js.map +1 -0
  250. package/dist/session/hierarchy/thread.d.ts +54 -0
  251. package/dist/session/hierarchy/thread.d.ts.map +1 -0
  252. package/dist/session/hierarchy/thread.js +2 -0
  253. package/dist/session/hierarchy/thread.js.map +1 -0
  254. package/dist/session/index.d.ts +10 -0
  255. package/dist/session/index.d.ts.map +1 -0
  256. package/dist/session/index.js +15 -0
  257. package/dist/session/index.js.map +1 -0
  258. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts +2 -0
  259. package/dist/session/intervention/__tests__/prev-artifact.test.d.ts.map +1 -0
  260. package/dist/session/intervention/__tests__/prev-artifact.test.js +179 -0
  261. package/dist/session/intervention/__tests__/prev-artifact.test.js.map +1 -0
  262. package/dist/session/intervention/index.d.ts +3 -0
  263. package/dist/session/intervention/index.d.ts.map +1 -0
  264. package/dist/session/intervention/index.js +8 -0
  265. package/dist/session/intervention/index.js.map +1 -0
  266. package/dist/session/intervention/prev-artifact.d.ts +103 -0
  267. package/dist/session/intervention/prev-artifact.d.ts.map +1 -0
  268. package/dist/session/intervention/prev-artifact.js +112 -0
  269. package/dist/session/intervention/prev-artifact.js.map +1 -0
  270. package/dist/session/migration/__tests__/filesystem.test.d.ts +2 -0
  271. package/dist/session/migration/__tests__/filesystem.test.d.ts.map +1 -0
  272. package/dist/session/migration/__tests__/filesystem.test.js +188 -0
  273. package/dist/session/migration/__tests__/filesystem.test.js.map +1 -0
  274. package/dist/session/migration/__tests__/id-prefix.test.d.ts +2 -0
  275. package/dist/session/migration/__tests__/id-prefix.test.d.ts.map +1 -0
  276. package/dist/session/migration/__tests__/id-prefix.test.js +83 -0
  277. package/dist/session/migration/__tests__/id-prefix.test.js.map +1 -0
  278. package/dist/session/migration/__tests__/marker.test.d.ts +2 -0
  279. package/dist/session/migration/__tests__/marker.test.d.ts.map +1 -0
  280. package/dist/session/migration/__tests__/marker.test.js +75 -0
  281. package/dist/session/migration/__tests__/marker.test.js.map +1 -0
  282. package/dist/session/migration/errors.d.ts +26 -0
  283. package/dist/session/migration/errors.d.ts.map +1 -0
  284. package/dist/session/migration/errors.js +22 -0
  285. package/dist/session/migration/errors.js.map +1 -0
  286. package/dist/session/migration/filesystem.d.ts +94 -0
  287. package/dist/session/migration/filesystem.d.ts.map +1 -0
  288. package/dist/session/migration/filesystem.js +319 -0
  289. package/dist/session/migration/filesystem.js.map +1 -0
  290. package/dist/session/migration/id-prefix.d.ts +93 -0
  291. package/dist/session/migration/id-prefix.d.ts.map +1 -0
  292. package/dist/session/migration/id-prefix.js +111 -0
  293. package/dist/session/migration/id-prefix.js.map +1 -0
  294. package/dist/session/migration/index.d.ts +8 -0
  295. package/dist/session/migration/index.d.ts.map +1 -0
  296. package/dist/session/migration/index.js +8 -0
  297. package/dist/session/migration/index.js.map +1 -0
  298. package/dist/session/migration/marker.d.ts +57 -0
  299. package/dist/session/migration/marker.d.ts.map +1 -0
  300. package/dist/session/migration/marker.js +111 -0
  301. package/dist/session/migration/marker.js.map +1 -0
  302. package/dist/session/retention/__tests__/archive.test.d.ts +2 -0
  303. package/dist/session/retention/__tests__/archive.test.d.ts.map +1 -0
  304. package/dist/session/retention/__tests__/archive.test.js +253 -0
  305. package/dist/session/retention/__tests__/archive.test.js.map +1 -0
  306. package/dist/session/retention/__tests__/disk-backend.test.d.ts +2 -0
  307. package/dist/session/retention/__tests__/disk-backend.test.d.ts.map +1 -0
  308. package/dist/session/retention/__tests__/disk-backend.test.js +154 -0
  309. package/dist/session/retention/__tests__/disk-backend.test.js.map +1 -0
  310. package/dist/session/retention/archive-backend-ref.d.ts +18 -0
  311. package/dist/session/retention/archive-backend-ref.d.ts.map +1 -0
  312. package/dist/session/retention/archive-backend-ref.js +2 -0
  313. package/dist/session/retention/archive-backend-ref.js.map +1 -0
  314. package/dist/session/retention/archive.d.ts +130 -0
  315. package/dist/session/retention/archive.d.ts.map +1 -0
  316. package/dist/session/retention/archive.js +203 -0
  317. package/dist/session/retention/archive.js.map +1 -0
  318. package/dist/session/retention/backend.d.ts +101 -0
  319. package/dist/session/retention/backend.d.ts.map +1 -0
  320. package/dist/session/retention/backend.js +15 -0
  321. package/dist/session/retention/backend.js.map +1 -0
  322. package/dist/session/retention/disk-backend.d.ts +59 -0
  323. package/dist/session/retention/disk-backend.d.ts.map +1 -0
  324. package/dist/session/retention/disk-backend.js +236 -0
  325. package/dist/session/retention/disk-backend.js.map +1 -0
  326. package/dist/session/retention/index.d.ts +9 -0
  327. package/dist/session/retention/index.d.ts.map +1 -0
  328. package/dist/session/retention/index.js +6 -0
  329. package/dist/session/retention/index.js.map +1 -0
  330. package/dist/session/retention/policy.d.ts +49 -0
  331. package/dist/session/retention/policy.d.ts.map +1 -0
  332. package/dist/session/retention/policy.js +21 -0
  333. package/dist/session/retention/policy.js.map +1 -0
  334. package/dist/session/summary/__tests__/materialize.test.d.ts +2 -0
  335. package/dist/session/summary/__tests__/materialize.test.d.ts.map +1 -0
  336. package/dist/session/summary/__tests__/materialize.test.js +270 -0
  337. package/dist/session/summary/__tests__/materialize.test.js.map +1 -0
  338. package/dist/session/summary/deliverable.d.ts +74 -0
  339. package/dist/session/summary/deliverable.d.ts.map +1 -0
  340. package/dist/session/summary/deliverable.js +20 -0
  341. package/dist/session/summary/deliverable.js.map +1 -0
  342. package/dist/session/summary/index.d.ts +6 -0
  343. package/dist/session/summary/index.d.ts.map +1 -0
  344. package/dist/session/summary/index.js +9 -0
  345. package/dist/session/summary/index.js.map +1 -0
  346. package/dist/session/summary/materialize.d.ts +82 -0
  347. package/dist/session/summary/materialize.d.ts.map +1 -0
  348. package/dist/session/summary/materialize.js +117 -0
  349. package/dist/session/summary/materialize.js.map +1 -0
  350. package/dist/session/summary/ref.d.ts +91 -0
  351. package/dist/session/summary/ref.d.ts.map +1 -0
  352. package/dist/session/summary/ref.js +51 -0
  353. package/dist/session/summary/ref.js.map +1 -0
  354. package/dist/session/workspace/__tests__/git-worktree.test.d.ts +2 -0
  355. package/dist/session/workspace/__tests__/git-worktree.test.d.ts.map +1 -0
  356. package/dist/session/workspace/__tests__/git-worktree.test.js +244 -0
  357. package/dist/session/workspace/__tests__/git-worktree.test.js.map +1 -0
  358. package/dist/session/workspace/__tests__/path-builder.test.d.ts +2 -0
  359. package/dist/session/workspace/__tests__/path-builder.test.d.ts.map +1 -0
  360. package/dist/session/workspace/__tests__/path-builder.test.js +37 -0
  361. package/dist/session/workspace/__tests__/path-builder.test.js.map +1 -0
  362. package/dist/session/workspace/driver.d.ts +55 -0
  363. package/dist/session/workspace/driver.d.ts.map +1 -0
  364. package/dist/session/workspace/driver.js +12 -0
  365. package/dist/session/workspace/driver.js.map +1 -0
  366. package/dist/session/workspace/git-worktree.d.ts +65 -0
  367. package/dist/session/workspace/git-worktree.d.ts.map +1 -0
  368. package/dist/session/workspace/git-worktree.js +156 -0
  369. package/dist/session/workspace/git-worktree.js.map +1 -0
  370. package/dist/session/workspace/index.d.ts +8 -0
  371. package/dist/session/workspace/index.d.ts.map +1 -0
  372. package/dist/session/workspace/index.js +7 -0
  373. package/dist/session/workspace/index.js.map +1 -0
  374. package/dist/session/workspace/path-builder.d.ts +50 -0
  375. package/dist/session/workspace/path-builder.d.ts.map +1 -0
  376. package/dist/session/workspace/path-builder.js +50 -0
  377. package/dist/session/workspace/path-builder.js.map +1 -0
  378. package/dist/session/workspace/ref.d.ts +46 -0
  379. package/dist/session/workspace/ref.d.ts.map +1 -0
  380. package/dist/session/workspace/ref.js +11 -0
  381. package/dist/session/workspace/ref.js.map +1 -0
  382. package/dist/session/workspace/registry.d.ts +26 -0
  383. package/dist/session/workspace/registry.d.ts.map +1 -0
  384. package/dist/session/workspace/registry.js +35 -0
  385. package/dist/session/workspace/registry.js.map +1 -0
  386. package/dist/store/index.d.ts +0 -2
  387. package/dist/store/index.d.ts.map +1 -1
  388. package/dist/store/index.js +0 -1
  389. package/dist/store/index.js.map +1 -1
  390. package/dist/store/session/__tests__/disk.test.d.ts +2 -0
  391. package/dist/store/session/__tests__/disk.test.d.ts.map +1 -0
  392. package/dist/store/session/__tests__/disk.test.js +267 -0
  393. package/dist/store/session/__tests__/disk.test.js.map +1 -0
  394. package/dist/store/session/__tests__/memory.test.d.ts +2 -0
  395. package/dist/store/session/__tests__/memory.test.d.ts.map +1 -0
  396. package/dist/store/session/__tests__/memory.test.js +258 -0
  397. package/dist/store/session/__tests__/memory.test.js.map +1 -0
  398. package/dist/store/session/disk.d.ts +86 -0
  399. package/dist/store/session/disk.d.ts.map +1 -0
  400. package/dist/store/session/disk.js +818 -0
  401. package/dist/store/session/disk.js.map +1 -0
  402. package/dist/store/session/index.d.ts +7 -0
  403. package/dist/store/session/index.d.ts.map +1 -0
  404. package/dist/store/session/index.js +10 -0
  405. package/dist/store/session/index.js.map +1 -0
  406. package/dist/store/session/linkage.d.ts +38 -0
  407. package/dist/store/session/linkage.d.ts.map +1 -0
  408. package/dist/store/session/linkage.js +64 -0
  409. package/dist/store/session/linkage.js.map +1 -0
  410. package/dist/store/session/memory.d.ts +49 -0
  411. package/dist/store/session/memory.d.ts.map +1 -0
  412. package/dist/store/session/memory.js +335 -0
  413. package/dist/store/session/memory.js.map +1 -0
  414. package/dist/store/session/messages.d.ts +20 -0
  415. package/dist/store/session/messages.d.ts.map +1 -0
  416. package/dist/store/session/messages.js +12 -0
  417. package/dist/store/session/messages.js.map +1 -0
  418. package/dist/store/thread/disk.d.ts +41 -0
  419. package/dist/store/thread/disk.d.ts.map +1 -0
  420. package/dist/store/thread/disk.js +229 -0
  421. package/dist/store/thread/disk.js.map +1 -0
  422. package/dist/store/thread/index.d.ts +4 -0
  423. package/dist/store/thread/index.d.ts.map +1 -0
  424. package/dist/store/thread/index.js +6 -0
  425. package/dist/store/thread/index.js.map +1 -0
  426. package/dist/store/thread/memory.d.ts +23 -0
  427. package/dist/store/thread/memory.d.ts.map +1 -0
  428. package/dist/store/thread/memory.js +90 -0
  429. package/dist/store/thread/memory.js.map +1 -0
  430. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +1 -1
  431. package/dist/types/agent/base.d.ts +24 -1
  432. package/dist/types/agent/base.d.ts.map +1 -1
  433. package/dist/types/agent/factory.d.ts +8 -2
  434. package/dist/types/agent/factory.d.ts.map +1 -1
  435. package/dist/types/agent/task.d.ts +57 -2
  436. package/dist/types/agent/task.d.ts.map +1 -1
  437. package/dist/types/agent/task.js.map +1 -1
  438. package/dist/types/ids/index.d.ts +22 -3
  439. package/dist/types/ids/index.d.ts.map +1 -1
  440. package/dist/types/ids/index.js +8 -1
  441. package/dist/types/ids/index.js.map +1 -1
  442. package/dist/types/invocation/__tests__/state.test.js +36 -29
  443. package/dist/types/invocation/__tests__/state.test.js.map +1 -1
  444. package/dist/types/invocation/index.d.ts +20 -4
  445. package/dist/types/invocation/index.d.ts.map +1 -1
  446. package/dist/types/invocation/index.js +10 -7
  447. package/dist/types/invocation/index.js.map +1 -1
  448. package/dist/types/rag/retrieval.d.ts +4 -3
  449. package/dist/types/rag/retrieval.d.ts.map +1 -1
  450. package/dist/types/run/config.d.ts +12 -1
  451. package/dist/types/run/config.d.ts.map +1 -1
  452. package/dist/types/run/events.d.ts +26 -1
  453. package/dist/types/run/events.d.ts.map +1 -1
  454. package/dist/types/run/index.d.ts.map +1 -1
  455. package/dist/types/run/index.js +8 -0
  456. package/dist/types/run/index.js.map +1 -1
  457. package/dist/types/run/metadata.d.ts +12 -2
  458. package/dist/types/run/metadata.d.ts.map +1 -1
  459. package/dist/types/run/status.d.ts +26 -0
  460. package/dist/types/run/status.d.ts.map +1 -0
  461. package/dist/types/run/status.js +2 -0
  462. package/dist/types/run/status.js.map +1 -0
  463. package/dist/types/session/ids.d.ts +9 -0
  464. package/dist/types/session/ids.d.ts.map +1 -0
  465. package/dist/types/session/ids.js +9 -0
  466. package/dist/types/session/ids.js.map +1 -0
  467. package/dist/types/session/index.d.ts +3 -0
  468. package/dist/types/session/index.d.ts.map +1 -0
  469. package/dist/types/session/index.js +5 -0
  470. package/dist/types/session/index.js.map +1 -0
  471. package/dist/types/session/store.d.ts +210 -0
  472. package/dist/types/session/store.d.ts.map +1 -0
  473. package/dist/types/session/store.js +9 -0
  474. package/dist/types/session/store.js.map +1 -0
  475. package/dist/types/thread/index.d.ts +2 -0
  476. package/dist/types/thread/index.d.ts.map +1 -0
  477. package/dist/types/thread/index.js +5 -0
  478. package/dist/types/thread/index.js.map +1 -0
  479. package/dist/types/thread/store.d.ts +86 -0
  480. package/dist/types/thread/store.d.ts.map +1 -0
  481. package/dist/types/thread/store.js +22 -0
  482. package/dist/types/thread/store.js.map +1 -0
  483. package/dist/utils/id.d.ts +8 -2
  484. package/dist/utils/id.d.ts.map +1 -1
  485. package/dist/utils/id.js +22 -4
  486. package/dist/utils/id.js.map +1 -1
  487. package/package.json +6 -11
  488. package/src/agents/ReactiveAgent.ts +7 -2
  489. package/src/agents/RouterAgent.ts +5 -0
  490. package/src/agents/SupervisorAgent.ts +29 -6
  491. package/src/bridge/a2a/index.ts +0 -1
  492. package/src/bridge/a2a/mapper.ts +7 -0
  493. package/src/bridge/a2a/message.ts +0 -32
  494. package/src/bridge/a2a/task.ts +9 -8
  495. package/src/bridge/sse/mapper.ts +8 -1
  496. package/src/constants/a2a/index.ts +2 -2
  497. package/src/contracts/api.ts +14 -30
  498. package/src/contracts/ids.ts +1 -1
  499. package/src/contracts/index.ts +3 -7
  500. package/src/contracts/schemas.ts +1 -8
  501. package/src/gateway/local.ts +6 -0
  502. package/src/index.ts +14 -4
  503. package/src/manager/agent/__tests__/lifecycle.test.ts +473 -0
  504. package/src/manager/agent/lifecycle.ts +515 -21
  505. package/src/manager/index.ts +3 -0
  506. package/src/manager/run/persistence.ts +26 -1
  507. package/src/manager/thread/__tests__/lifecycle.test.ts +286 -0
  508. package/src/manager/thread/lifecycle.ts +217 -0
  509. package/src/rag/retriever.ts +2 -2
  510. package/src/run/reporter.ts +28 -0
  511. package/src/runtime/query/__tests__/context.test.ts +102 -0
  512. package/src/runtime/query/context-cache.ts +4 -4
  513. package/src/runtime/query/context.ts +98 -9
  514. package/src/runtime/query/events.ts +8 -0
  515. package/src/runtime/query/index.ts +38 -1
  516. package/src/session/__tests__/integration/_fixtures.ts +310 -0
  517. package/src/session/__tests__/integration/archive-gate.test.ts +288 -0
  518. package/src/session/__tests__/integration/capacity-caps.test.ts +171 -0
  519. package/src/session/__tests__/integration/e2e-spawn.test.ts +296 -0
  520. package/src/session/__tests__/integration/event-stream-ordering.test.ts +410 -0
  521. package/src/session/__tests__/integration/handoff-broadcast-e2e.test.ts +271 -0
  522. package/src/session/__tests__/integration/handoff-illegal-transition.test.ts +214 -0
  523. package/src/session/__tests__/integration/handoff-single-e2e.test.ts +251 -0
  524. package/src/session/__tests__/integration/hierarchy-lifecycle.test.ts +240 -0
  525. package/src/session/__tests__/integration/migration-filesystem.test.ts +209 -0
  526. package/src/session/__tests__/integration/migration-id-prefix.test.ts +101 -0
  527. package/src/session/__tests__/integration/prev-artifact-dag.test.ts +325 -0
  528. package/src/session/__tests__/integration/retention-archive.test.ts +233 -0
  529. package/src/session/__tests__/integration/spawn-rollback.test.ts +313 -0
  530. package/src/session/__tests__/integration/summary-materialization-e2e.test.ts +239 -0
  531. package/src/session/__tests__/integration/tenant-isolation.test.ts +292 -0
  532. package/src/session/errors.ts +159 -0
  533. package/src/session/events/index.ts +16 -0
  534. package/src/session/events/schema-version.ts +13 -0
  535. package/src/session/events/types.ts +71 -0
  536. package/src/session/handoff/__tests__/broadcast.test.ts +378 -0
  537. package/src/session/handoff/__tests__/capacity.test.ts +129 -0
  538. package/src/session/handoff/__tests__/single.test.ts +333 -0
  539. package/src/session/handoff/assignment.ts +74 -0
  540. package/src/session/handoff/broadcast.ts +406 -0
  541. package/src/session/handoff/capacity.ts +121 -0
  542. package/src/session/handoff/events.ts +72 -0
  543. package/src/session/handoff/index.ts +29 -0
  544. package/src/session/handoff/single.ts +310 -0
  545. package/src/session/handoff/version.ts +59 -0
  546. package/src/session/hierarchy/__tests__/session.test.ts +100 -0
  547. package/src/session/hierarchy/actor.ts +17 -0
  548. package/src/session/hierarchy/index.ts +18 -0
  549. package/src/session/hierarchy/lineage.ts +15 -0
  550. package/src/session/hierarchy/project.ts +41 -0
  551. package/src/session/hierarchy/session.ts +109 -0
  552. package/src/session/hierarchy/sub-session.ts +92 -0
  553. package/src/session/hierarchy/tenant.ts +13 -0
  554. package/src/session/hierarchy/thread.ts +55 -0
  555. package/src/session/index.ts +15 -0
  556. package/src/session/intervention/__tests__/prev-artifact.test.ts +234 -0
  557. package/src/session/intervention/index.ts +16 -0
  558. package/src/session/intervention/prev-artifact.ts +180 -0
  559. package/src/session/migration/__tests__/filesystem.test.ts +263 -0
  560. package/src/session/migration/__tests__/id-prefix.test.ts +101 -0
  561. package/src/session/migration/__tests__/marker.test.ts +84 -0
  562. package/src/session/migration/errors.ts +23 -0
  563. package/src/session/migration/filesystem.ts +401 -0
  564. package/src/session/migration/id-prefix.ts +141 -0
  565. package/src/session/migration/index.ts +38 -0
  566. package/src/session/migration/marker.ts +131 -0
  567. package/src/session/retention/__tests__/archive.test.ts +318 -0
  568. package/src/session/retention/__tests__/disk-backend.test.ts +180 -0
  569. package/src/session/retention/archive-backend-ref.ts +17 -0
  570. package/src/session/retention/archive.ts +281 -0
  571. package/src/session/retention/backend.ts +107 -0
  572. package/src/session/retention/disk-backend.ts +304 -0
  573. package/src/session/retention/index.ts +16 -0
  574. package/src/session/retention/policy.ts +53 -0
  575. package/src/session/summary/__tests__/materialize.test.ts +343 -0
  576. package/src/session/summary/deliverable.ts +84 -0
  577. package/src/session/summary/index.ts +31 -0
  578. package/src/session/summary/materialize.ts +169 -0
  579. package/src/session/summary/ref.ts +104 -0
  580. package/src/session/workspace/__tests__/git-worktree.test.ts +258 -0
  581. package/src/session/workspace/__tests__/path-builder.test.ts +51 -0
  582. package/src/session/workspace/driver.ts +60 -0
  583. package/src/session/workspace/git-worktree.ts +209 -0
  584. package/src/session/workspace/index.ts +25 -0
  585. package/src/session/workspace/path-builder.ts +71 -0
  586. package/src/session/workspace/ref.ts +50 -0
  587. package/src/session/workspace/registry.ts +42 -0
  588. package/src/store/index.ts +0 -3
  589. package/src/store/session/__tests__/disk.test.ts +397 -0
  590. package/src/store/session/__tests__/memory.test.ts +402 -0
  591. package/src/store/session/disk.ts +976 -0
  592. package/src/store/session/index.ts +13 -0
  593. package/src/store/session/linkage.ts +80 -0
  594. package/src/store/session/memory.ts +412 -0
  595. package/src/store/session/messages.ts +21 -0
  596. package/src/store/thread/disk.ts +261 -0
  597. package/src/store/thread/index.ts +7 -0
  598. package/src/store/thread/memory.ts +104 -0
  599. package/src/types/agent/base.ts +27 -1
  600. package/src/types/agent/factory.ts +8 -3
  601. package/src/types/agent/task.ts +66 -2
  602. package/src/types/ids/index.ts +34 -3
  603. package/src/types/invocation/__tests__/state.test.ts +37 -29
  604. package/src/types/invocation/index.ts +26 -10
  605. package/src/types/rag/retrieval.ts +4 -3
  606. package/src/types/run/config.ts +13 -1
  607. package/src/types/run/events.ts +36 -1
  608. package/src/types/run/index.ts +8 -0
  609. package/src/types/run/metadata.ts +12 -2
  610. package/src/types/run/status.ts +33 -0
  611. package/src/types/session/ids.ts +23 -0
  612. package/src/types/session/index.ts +27 -0
  613. package/src/types/session/store.ts +252 -0
  614. package/src/types/thread/index.ts +5 -0
  615. package/src/types/thread/store.ts +92 -0
  616. package/src/utils/id.ts +34 -4
  617. package/dist/store/conversation/memory.d.ts +0 -21
  618. package/dist/store/conversation/memory.d.ts.map +0 -1
  619. package/dist/store/conversation/memory.js +0 -86
  620. package/dist/store/conversation/memory.js.map +0 -1
  621. package/dist/types/conversation/index.d.ts +0 -7
  622. package/dist/types/conversation/index.d.ts.map +0 -1
  623. package/dist/types/conversation/index.js +0 -2
  624. package/dist/types/conversation/index.js.map +0 -1
  625. package/src/store/conversation/memory.ts +0 -121
  626. package/src/types/conversation/index.ts +0 -8
@@ -0,0 +1,104 @@
1
+ /**
2
+ * SessionSummaryRef — the structured pointer a parent session sees when a
3
+ * sub-session completes. Kernel-owned terminalization primitive: the only
4
+ * producer is {@link SessionSummaryMaterializer.materialize} (see
5
+ * `./materialize.ts`). See session-hierarchy.md §4.7 (shape) and §8.1
6
+ * (emission invariant).
7
+ *
8
+ * The `materializedBy: 'kernel'` literal field is load-bearing — combined
9
+ * with the opaque {@link SummaryId} brand (mintable only by
10
+ * `generateSummaryId`), it enforces at the type level that no agent or tool
11
+ * can construct a valid `SessionSummaryRef`. `SessionStore.recordSummary`
12
+ * only accepts `SessionSummaryRef & { materializedBy: 'kernel' }`, so even a
13
+ * payload shaped correctly would fail the structural check.
14
+ *
15
+ * This is Convention #0 load-bearing: there is no "tool" path to emit a
16
+ * summary; the parent agent sees only what the kernel seals.
17
+ */
18
+
19
+ import type { SessionId, TenantId } from '../../types/ids/index.js'
20
+ import type { SummaryId } from '../../types/session/ids.js'
21
+ import type { DeliverableRef } from './deliverable.js'
22
+
23
+ /**
24
+ * Max characters allowed for {@link SessionSummaryRef.agentSummary}. See
25
+ * session-hierarchy.md §4.7 — the agent's narration is bounded to keep
26
+ * parent prompts token-finite regardless of the child's transcript length.
27
+ */
28
+ export const AGENT_SUMMARY_MAX_CHARS = 4000
29
+
30
+ export type SessionSummaryOutcomeStatus = 'succeeded' | 'partial' | 'failed'
31
+
32
+ export interface SessionSummaryOutcome {
33
+ readonly status: SessionSummaryOutcomeStatus
34
+ /** Short human-readable one-liner. Optional per pattern doc §4.7. */
35
+ readonly verdict?: string
36
+ }
37
+
38
+ export interface SessionSummaryKeyDecision {
39
+ readonly at: Date
40
+ readonly summary: string
41
+ }
42
+
43
+ /**
44
+ * Structured completion pointer emitted by the kernel when a sub-session
45
+ * terminalizes. See session-hierarchy.md §4.7 and §8.1.
46
+ *
47
+ * Readonly across the board — the record is immutable once sealed.
48
+ */
49
+ export interface SessionSummaryRef {
50
+ readonly id: SummaryId
51
+ readonly sessionRef: SessionId
52
+ readonly tenantId: TenantId
53
+ readonly outcome: SessionSummaryOutcome
54
+ readonly deliverables: readonly DeliverableRef[]
55
+ /** Agent's own narration; bounded to {@link AGENT_SUMMARY_MAX_CHARS}. */
56
+ readonly agentSummary: string
57
+ readonly keyDecisions: readonly SessionSummaryKeyDecision[]
58
+ /** When the summary was materialized. */
59
+ readonly at: Date
60
+ /**
61
+ * Literal `'kernel'` — enforces kernel-only emission at the type level.
62
+ * See the module header for the invariant rationale.
63
+ */
64
+ readonly materializedBy: 'kernel'
65
+ }
66
+
67
+ /**
68
+ * Raised by {@link SessionSummaryMaterializer.materialize} when the provided
69
+ * `agentSummary` exceeds {@link AGENT_SUMMARY_MAX_CHARS}. Convention #5
70
+ * deny-by-default — the kernel does not truncate silently.
71
+ */
72
+ export class AgentSummaryTooLongError extends Error {
73
+ readonly details: {
74
+ readonly actual: number
75
+ readonly max: number
76
+ }
77
+
78
+ constructor(details: { actual: number; max: number }) {
79
+ super(`agentSummary ${details.actual} chars exceeds max ${details.max}`)
80
+ this.name = 'AgentSummaryTooLongError'
81
+ this.details = details
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Raised when {@link SessionSummaryMaterializer.materialize} is invoked
87
+ * against a session that already has a persisted summary. Re-materialization
88
+ * would duplicate history — callers wanting to append must open a new
89
+ * intervention sub-session (see session-hierarchy.md §4.5).
90
+ */
91
+ export class SessionAlreadySummarizedError extends Error {
92
+ readonly details: {
93
+ readonly sessionId: SessionId
94
+ readonly existingSummaryId: SummaryId
95
+ }
96
+
97
+ constructor(details: { sessionId: SessionId; existingSummaryId: SummaryId }) {
98
+ super(
99
+ `Session ${details.sessionId} already has summary ${details.existingSummaryId}; re-materialization rejected`,
100
+ )
101
+ this.name = 'SessionAlreadySummarizedError'
102
+ this.details = details
103
+ }
104
+ }
@@ -0,0 +1,258 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { WorkspaceBackendError } from '../../errors.js'
3
+ import {
4
+ type ExecFile,
5
+ type ExecFileResult,
6
+ GitWorktreeDriver,
7
+ parseWorktreeList,
8
+ } from '../git-worktree.js'
9
+ import type { WorkspaceRef } from '../ref.js'
10
+
11
+ function stubLogger() {
12
+ return {
13
+ debug: vi.fn(),
14
+ info: vi.fn(),
15
+ warn: vi.fn(),
16
+ error: vi.fn(),
17
+ child() {
18
+ return stubLogger()
19
+ },
20
+ }
21
+ }
22
+
23
+ function okExec(stdout = '', stderr = ''): ExecFileResult {
24
+ return { stdout, stderr }
25
+ }
26
+
27
+ describe('GitWorktreeDriver', () => {
28
+ it('create: invokes `git worktree add` with argv array (no shell interpolation)', async () => {
29
+ const calls: Array<{ file: string; args: readonly string[] }> = []
30
+ const exec: ExecFile = async (file, args) => {
31
+ calls.push({ file, args: [...args] })
32
+ return okExec()
33
+ }
34
+ const driver = new GitWorktreeDriver({
35
+ repoRoot: '/repo',
36
+ logger: stubLogger(),
37
+ execFile: exec,
38
+ })
39
+ const ref = await driver.create({ label: 'foo', baseRef: 'main' })
40
+
41
+ expect(ref.id.startsWith('wsp_')).toBe(true)
42
+ expect(ref.meta.backend).toBe('git-worktree')
43
+ expect(ref.meta.branch).toBe('namzu/foo')
44
+ expect(calls).toHaveLength(1)
45
+ const call = calls[0]
46
+ if (!call) throw new Error('missing call')
47
+ expect(call.file).toBe('git')
48
+ expect(call.args).toEqual([
49
+ '-C',
50
+ '/repo',
51
+ 'worktree',
52
+ 'add',
53
+ '-b',
54
+ 'namzu/foo',
55
+ '/repo/.namzu/worktrees/foo',
56
+ 'main',
57
+ ])
58
+ })
59
+
60
+ it('create: omits baseRef argv slot when not supplied', async () => {
61
+ const calls: Array<{ file: string; args: readonly string[] }> = []
62
+ const exec: ExecFile = async (file, args) => {
63
+ calls.push({ file, args: [...args] })
64
+ return okExec()
65
+ }
66
+ const driver = new GitWorktreeDriver({
67
+ repoRoot: '/repo',
68
+ logger: stubLogger(),
69
+ execFile: exec,
70
+ })
71
+ await driver.create({ label: 'bar' })
72
+ const call = calls[0]
73
+ if (!call) throw new Error('missing call')
74
+ expect(call.args.at(-1)).toBe('/repo/.namzu/worktrees/bar')
75
+ })
76
+
77
+ it('create: wraps failures in WorkspaceBackendError', async () => {
78
+ const exec: ExecFile = async () => {
79
+ throw new Error('invalid baseRef')
80
+ }
81
+ const driver = new GitWorktreeDriver({
82
+ repoRoot: '/repo',
83
+ logger: stubLogger(),
84
+ execFile: exec,
85
+ })
86
+ await expect(driver.create({ baseRef: 'does-not-exist' })).rejects.toBeInstanceOf(
87
+ WorkspaceBackendError,
88
+ )
89
+ })
90
+
91
+ it('dispose: removes worktree with --force', async () => {
92
+ const calls: Array<readonly string[]> = []
93
+ const exec: ExecFile = async (_file, args) => {
94
+ calls.push(args)
95
+ return okExec()
96
+ }
97
+ const driver = new GitWorktreeDriver({
98
+ repoRoot: '/repo',
99
+ logger: stubLogger(),
100
+ execFile: exec,
101
+ })
102
+ const ref: WorkspaceRef = {
103
+ id: 'wsp_x' as unknown as WorkspaceRef['id'],
104
+ meta: {
105
+ backend: 'git-worktree',
106
+ repoRoot: '/repo',
107
+ branch: 'namzu/x',
108
+ worktreePath: '/repo/.namzu/worktrees/x',
109
+ },
110
+ createdAt: new Date(),
111
+ }
112
+ await driver.dispose(ref)
113
+ expect(calls[0]).toEqual([
114
+ '-C',
115
+ '/repo',
116
+ 'worktree',
117
+ 'remove',
118
+ '/repo/.namzu/worktrees/x',
119
+ '--force',
120
+ ])
121
+ })
122
+
123
+ it('dispose: tolerates missing worktree ("not a working tree")', async () => {
124
+ const exec: ExecFile = async () => {
125
+ throw new Error("'/tmp/gone' is not a working tree")
126
+ }
127
+ const driver = new GitWorktreeDriver({
128
+ repoRoot: '/repo',
129
+ logger: stubLogger(),
130
+ execFile: exec,
131
+ })
132
+ const ref: WorkspaceRef = {
133
+ id: 'wsp_x' as unknown as WorkspaceRef['id'],
134
+ meta: {
135
+ backend: 'git-worktree',
136
+ repoRoot: '/repo',
137
+ branch: 'namzu/x',
138
+ worktreePath: '/tmp/gone',
139
+ },
140
+ createdAt: new Date(),
141
+ }
142
+ // Must NOT throw — roadmap Risk #3 mitigation.
143
+ await expect(driver.dispose(ref)).resolves.toBeUndefined()
144
+ })
145
+
146
+ it('dispose: surfaces unexpected failures as WorkspaceBackendError', async () => {
147
+ const exec: ExecFile = async () => {
148
+ throw new Error('fatal: permission denied')
149
+ }
150
+ const driver = new GitWorktreeDriver({
151
+ repoRoot: '/repo',
152
+ logger: stubLogger(),
153
+ execFile: exec,
154
+ })
155
+ const ref: WorkspaceRef = {
156
+ id: 'wsp_x' as unknown as WorkspaceRef['id'],
157
+ meta: {
158
+ backend: 'git-worktree',
159
+ repoRoot: '/repo',
160
+ branch: 'namzu/x',
161
+ worktreePath: '/repo/.namzu/worktrees/x',
162
+ },
163
+ createdAt: new Date(),
164
+ }
165
+ await expect(driver.dispose(ref)).rejects.toBeInstanceOf(WorkspaceBackendError)
166
+ })
167
+
168
+ it('inspect: parses list output and detects clean tree', async () => {
169
+ const listStdout = [
170
+ 'worktree /repo/.namzu/worktrees/x',
171
+ 'HEAD abc123',
172
+ 'branch refs/heads/namzu/x',
173
+ '',
174
+ ].join('\n')
175
+ let callIndex = 0
176
+ const exec: ExecFile = async (_file, args) => {
177
+ callIndex++
178
+ if (args.includes('list')) return okExec(listStdout)
179
+ if (args.includes('status')) return okExec('')
180
+ throw new Error(`unexpected call ${callIndex}`)
181
+ }
182
+ const driver = new GitWorktreeDriver({
183
+ repoRoot: '/repo',
184
+ logger: stubLogger(),
185
+ execFile: exec,
186
+ })
187
+ const ref: WorkspaceRef = {
188
+ id: 'wsp_x' as unknown as WorkspaceRef['id'],
189
+ meta: {
190
+ backend: 'git-worktree',
191
+ repoRoot: '/repo',
192
+ branch: 'namzu/x',
193
+ worktreePath: '/repo/.namzu/worktrees/x',
194
+ },
195
+ createdAt: new Date(),
196
+ }
197
+ const inspection = await driver.inspect(ref)
198
+ expect(inspection.exists).toBe(true)
199
+ expect(inspection.isDirty).toBe(false)
200
+ })
201
+
202
+ it('inspect: reports dirty when status --porcelain has output', async () => {
203
+ const listStdout = [
204
+ 'worktree /repo/.namzu/worktrees/x',
205
+ 'HEAD abc123',
206
+ 'branch refs/heads/namzu/x',
207
+ '',
208
+ ].join('\n')
209
+ const exec: ExecFile = async (_file, args) => {
210
+ if (args.includes('list')) return okExec(listStdout)
211
+ if (args.includes('status')) return okExec(' M path/to/file\n')
212
+ throw new Error('unexpected')
213
+ }
214
+ const driver = new GitWorktreeDriver({
215
+ repoRoot: '/repo',
216
+ logger: stubLogger(),
217
+ execFile: exec,
218
+ })
219
+ const ref: WorkspaceRef = {
220
+ id: 'wsp_x' as unknown as WorkspaceRef['id'],
221
+ meta: {
222
+ backend: 'git-worktree',
223
+ repoRoot: '/repo',
224
+ branch: 'namzu/x',
225
+ worktreePath: '/repo/.namzu/worktrees/x',
226
+ },
227
+ createdAt: new Date(),
228
+ }
229
+ const inspection = await driver.inspect(ref)
230
+ expect(inspection.isDirty).toBe(true)
231
+ })
232
+ })
233
+
234
+ describe('parseWorktreeList', () => {
235
+ it('returns null when the target path is absent', () => {
236
+ const stdout = ['worktree /other', 'HEAD abc', 'branch refs/heads/main', ''].join('\n')
237
+ expect(parseWorktreeList(stdout, '/missing')).toBeNull()
238
+ })
239
+
240
+ it('extracts head + branch for the matching entry', () => {
241
+ const stdout = [
242
+ 'worktree /repo/.namzu/worktrees/x',
243
+ 'HEAD deadbeef',
244
+ 'branch refs/heads/namzu/x',
245
+ '',
246
+ 'worktree /other',
247
+ 'HEAD abc',
248
+ 'bare',
249
+ '',
250
+ ].join('\n')
251
+ const entry = parseWorktreeList(stdout, '/repo/.namzu/worktrees/x')
252
+ expect(entry).toEqual({
253
+ path: '/repo/.namzu/worktrees/x',
254
+ head: 'deadbeef',
255
+ branch: 'refs/heads/namzu/x',
256
+ })
257
+ })
258
+ })
@@ -0,0 +1,51 @@
1
+ import { join } from 'node:path'
2
+ import { describe, expect, it } from 'vitest'
3
+ import type { ProjectId, RunId, SessionId } from '../../../types/ids/index.js'
4
+ import type { SubSessionId } from '../../../types/session/ids.js'
5
+ import { DefaultPathBuilder } from '../path-builder.js'
6
+
7
+ const projectId = 'prj_abc' as ProjectId
8
+ const sessionId = 'ses_xyz' as SessionId
9
+ const subSessionId = 'sub_qqq' as SubSessionId
10
+ const runId = 'run_rrr' as RunId
11
+
12
+ describe('DefaultPathBuilder', () => {
13
+ it('rootDir returns the injected root verbatim', () => {
14
+ const pb = new DefaultPathBuilder('/tmp/ns')
15
+ expect(pb.rootDir()).toBe('/tmp/ns')
16
+ })
17
+
18
+ it('projectDir resolves to {root}/projects/{projectId}', () => {
19
+ const pb = new DefaultPathBuilder('/tmp/ns')
20
+ expect(pb.projectDir(projectId)).toBe(join('/tmp/ns', 'projects', projectId))
21
+ })
22
+
23
+ it('sessionDir resolves to {root}/projects/{projectId}/sessions/{sessionId}', () => {
24
+ const pb = new DefaultPathBuilder('/tmp/ns')
25
+ expect(pb.sessionDir(projectId, sessionId)).toBe(
26
+ join('/tmp/ns', 'projects', projectId, 'sessions', sessionId),
27
+ )
28
+ })
29
+
30
+ it('subSessionDir nests under session/subsessions/{subSessionId}', () => {
31
+ const pb = new DefaultPathBuilder('/tmp/ns')
32
+ expect(pb.subSessionDir(projectId, sessionId, subSessionId)).toBe(
33
+ join('/tmp/ns', 'projects', projectId, 'sessions', sessionId, 'subsessions', subSessionId),
34
+ )
35
+ })
36
+
37
+ it('runDir nests under session/runs/{runId}', () => {
38
+ const pb = new DefaultPathBuilder('/tmp/ns')
39
+ expect(pb.runDir(projectId, sessionId, runId)).toBe(
40
+ join('/tmp/ns', 'projects', projectId, 'sessions', sessionId, 'runs', runId),
41
+ )
42
+ })
43
+
44
+ it('root injection is per-instance (does not mutate global state)', () => {
45
+ const a = new DefaultPathBuilder('/tmp/a')
46
+ const b = new DefaultPathBuilder('/tmp/b')
47
+ expect(a.rootDir()).toBe('/tmp/a')
48
+ expect(b.rootDir()).toBe('/tmp/b')
49
+ expect(a.projectDir(projectId)).not.toBe(b.projectDir(projectId))
50
+ })
51
+ })
@@ -0,0 +1,60 @@
1
+ /**
2
+ * WorkspaceBackendDriver — pluggable backend contract for workspace
3
+ * provisioning. See session-hierarchy.md §7.1.
4
+ *
5
+ * Every Session persists a {@link WorkspaceRef}; the driver owns the
6
+ * underlying filesystem/container/etc. semantics. Phase 3 ships the
7
+ * git-worktree reference implementation (`git-worktree.ts`); tmpfs,
8
+ * container, and shared variants slot behind this same interface in a
9
+ * later phase (Convention #10: provider abstraction).
10
+ */
11
+
12
+ import type { WorkspaceBackendKind, WorkspaceRef } from './ref.js'
13
+
14
+ /**
15
+ * Params for {@link WorkspaceBackendDriver.create}. `baseRef` selects the
16
+ * commit / branch the workspace should track; when absent the driver
17
+ * provisions from the backend's default (e.g. the current branch of the
18
+ * repo for git-worktree).
19
+ */
20
+ export interface CreateWorkspaceParams {
21
+ baseRef?: string
22
+ label?: string
23
+ }
24
+
25
+ /**
26
+ * Params for {@link WorkspaceBackendDriver.branch}. `label` is a free-form
27
+ * tag embedded into the new workspace name so operators can trace provenance
28
+ * without reaching into the driver's internal naming scheme.
29
+ */
30
+ export interface BranchWorkspaceParams {
31
+ label?: string
32
+ }
33
+
34
+ /**
35
+ * Snapshot returned by {@link WorkspaceBackendDriver.inspect}. `exists` is
36
+ * `false` when the underlying resource has been disposed out-of-band (e.g.
37
+ * manual `git worktree remove` on disk); consumers can use it to detect
38
+ * divergence between the persisted {@link WorkspaceRef} and the backend.
39
+ */
40
+ export interface WorkspaceInspection {
41
+ exists: boolean
42
+ currentRef: string
43
+ isDirty: boolean
44
+ }
45
+
46
+ /**
47
+ * Backend driver contract. All methods are async and may throw
48
+ * {@link WorkspaceBackendError} on I/O failures. `dispose` is idempotent —
49
+ * calling it against an already-disposed ref is not an error (mitigates
50
+ * roadmap Risk #3: broadcast rollback must not fail on partial state).
51
+ */
52
+ export interface WorkspaceBackendDriver {
53
+ readonly kind: WorkspaceBackendKind
54
+ create(params: CreateWorkspaceParams): Promise<WorkspaceRef>
55
+ branch(source: WorkspaceRef, params: BranchWorkspaceParams): Promise<WorkspaceRef>
56
+ dispose(ref: WorkspaceRef): Promise<void>
57
+ inspect(ref: WorkspaceRef): Promise<WorkspaceInspection>
58
+ }
59
+
60
+ export type { WorkspaceBackendKind } from './ref.js'
@@ -0,0 +1,209 @@
1
+ /**
2
+ * GitWorktreeDriver — reference implementation of
3
+ * {@link WorkspaceBackendDriver} backed by `git worktree`.
4
+ *
5
+ * See session-hierarchy.md §7.2 (Git-worktree reference backend).
6
+ *
7
+ * Safety: every subprocess invocation uses `execFile` with an argv array —
8
+ * no shell interpolation — so caller-supplied `label`/`baseRef` strings
9
+ * cannot escape their argument slot. Failures surface as
10
+ * {@link WorkspaceBackendError} carrying the underlying cause.
11
+ */
12
+
13
+ import { execFile } from 'node:child_process'
14
+ import { join } from 'node:path'
15
+ import { promisify } from 'node:util'
16
+ import { generateWorkspaceId } from '../../utils/id.js'
17
+ import type { Logger } from '../../utils/logger.js'
18
+ import { WorkspaceBackendError } from '../errors.js'
19
+ import type {
20
+ BranchWorkspaceParams,
21
+ CreateWorkspaceParams,
22
+ WorkspaceBackendDriver,
23
+ WorkspaceInspection,
24
+ } from './driver.js'
25
+ import type { GitWorktreeBackendMeta, WorkspaceRef } from './ref.js'
26
+
27
+ const execFileAsync = promisify(execFile)
28
+
29
+ /**
30
+ * Minimal shape of `execFile`'s promisified result — allows tests to stub
31
+ * via dependency injection without pulling in the full `ChildProcess` type.
32
+ */
33
+ export interface ExecFileResult {
34
+ stdout: string
35
+ stderr: string
36
+ }
37
+
38
+ /**
39
+ * Async exec callable used by {@link GitWorktreeDriver}. Matches the shape
40
+ * of `promisify(execFile)` for the argv-array overload. Injected via the
41
+ * constructor so tests can stub without touching `child_process`.
42
+ */
43
+ export type ExecFile = (file: string, args: readonly string[]) => Promise<ExecFileResult>
44
+
45
+ const defaultExecFile: ExecFile = async (file, args) => execFileAsync(file, [...args])
46
+
47
+ /**
48
+ * Configuration for {@link GitWorktreeDriver}.
49
+ */
50
+ export interface GitWorktreeDriverConfig {
51
+ /** Absolute path to the repo root whose `.git` backs the worktrees. */
52
+ repoRoot: string
53
+ /**
54
+ * Directory (absolute) where worktree checkouts live. Defaults to
55
+ * `{repoRoot}/.namzu/worktrees` per session-hierarchy.md §7.2.
56
+ */
57
+ worktreesDir?: string
58
+ logger: Logger
59
+ /** Test-seam: inject a stub `execFile` implementation. */
60
+ execFile?: ExecFile
61
+ }
62
+
63
+ export class GitWorktreeDriver implements WorkspaceBackendDriver {
64
+ readonly kind = 'git-worktree' as const
65
+
66
+ private readonly repoRoot: string
67
+ private readonly worktreesDir: string
68
+ private readonly log: Logger
69
+ private readonly exec: ExecFile
70
+
71
+ constructor(config: GitWorktreeDriverConfig) {
72
+ this.repoRoot = config.repoRoot
73
+ this.worktreesDir = config.worktreesDir ?? join(config.repoRoot, '.namzu', 'worktrees')
74
+ this.log = config.logger.child({ component: 'GitWorktreeDriver' })
75
+ this.exec = config.execFile ?? defaultExecFile
76
+ }
77
+
78
+ async create(params: CreateWorkspaceParams): Promise<WorkspaceRef> {
79
+ const id = generateWorkspaceId()
80
+ const label = params.label ?? id
81
+ const branch = `namzu/${label}`
82
+ const worktreePath = join(this.worktreesDir, label)
83
+
84
+ const argv = ['-C', this.repoRoot, 'worktree', 'add', '-b', branch, worktreePath]
85
+ if (params.baseRef !== undefined) {
86
+ argv.push(params.baseRef)
87
+ }
88
+
89
+ try {
90
+ await this.exec('git', argv)
91
+ } catch (cause) {
92
+ throw new WorkspaceBackendError({ op: 'create', kind: this.kind, cause })
93
+ }
94
+
95
+ const meta: GitWorktreeBackendMeta = {
96
+ backend: 'git-worktree',
97
+ repoRoot: this.repoRoot,
98
+ branch,
99
+ worktreePath,
100
+ }
101
+
102
+ this.log.info('git-worktree created', { id, branch, worktreePath })
103
+ return {
104
+ id,
105
+ meta,
106
+ createdAt: new Date(),
107
+ }
108
+ }
109
+
110
+ async branch(source: WorkspaceRef, params: BranchWorkspaceParams): Promise<WorkspaceRef> {
111
+ // Branch from the source worktree's current branch. The source's
112
+ // `meta.branch` is the ref we base off.
113
+ return this.create({ baseRef: source.meta.branch, label: params.label })
114
+ }
115
+
116
+ async dispose(ref: WorkspaceRef): Promise<void> {
117
+ // Tolerate missing directories per roadmap Risk #3 mitigation: the
118
+ // broadcast-rollback compensating step calls dispose on partially
119
+ // provisioned refs and must not propagate "already gone" errors.
120
+ try {
121
+ await this.exec('git', [
122
+ '-C',
123
+ this.repoRoot,
124
+ 'worktree',
125
+ 'remove',
126
+ ref.meta.worktreePath,
127
+ '--force',
128
+ ])
129
+ this.log.info('git-worktree disposed', { id: ref.id, path: ref.meta.worktreePath })
130
+ } catch (cause) {
131
+ const message = cause instanceof Error ? cause.message : String(cause)
132
+ // git exits non-zero with "is not a working tree" when the path is
133
+ // absent; treat as idempotent success and log at debug.
134
+ if (/not a working tree|does not exist|No such file/i.test(message)) {
135
+ this.log.debug('git-worktree already gone; dispose idempotent', {
136
+ id: ref.id,
137
+ path: ref.meta.worktreePath,
138
+ })
139
+ return
140
+ }
141
+ throw new WorkspaceBackendError({ op: 'dispose', kind: this.kind, cause })
142
+ }
143
+ }
144
+
145
+ async inspect(ref: WorkspaceRef): Promise<WorkspaceInspection> {
146
+ let listStdout: string
147
+ try {
148
+ const result = await this.exec('git', [
149
+ '-C',
150
+ this.repoRoot,
151
+ 'worktree',
152
+ 'list',
153
+ '--porcelain',
154
+ ])
155
+ listStdout = result.stdout
156
+ } catch (cause) {
157
+ throw new WorkspaceBackendError({ op: 'inspect:list', kind: this.kind, cause })
158
+ }
159
+
160
+ const entry = parseWorktreeList(listStdout, ref.meta.worktreePath)
161
+ if (!entry) {
162
+ return { exists: false, currentRef: ref.meta.branch, isDirty: false }
163
+ }
164
+
165
+ let statusStdout: string
166
+ try {
167
+ const result = await this.exec('git', ['-C', ref.meta.worktreePath, 'status', '--porcelain'])
168
+ statusStdout = result.stdout
169
+ } catch (cause) {
170
+ throw new WorkspaceBackendError({ op: 'inspect:status', kind: this.kind, cause })
171
+ }
172
+
173
+ return {
174
+ exists: true,
175
+ currentRef: entry.branch ?? entry.head ?? ref.meta.branch,
176
+ isDirty: statusStdout.trim().length > 0,
177
+ }
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Parses `git worktree list --porcelain` output, returning the record for
183
+ * `worktreePath` or `null` when absent. Exported for tests.
184
+ */
185
+ export function parseWorktreeList(
186
+ stdout: string,
187
+ worktreePath: string,
188
+ ): { path: string; head?: string; branch?: string } | null {
189
+ const blocks = stdout.split(/\n\n+/)
190
+ for (const block of blocks) {
191
+ const lines = block.split('\n').filter((l) => l.length > 0)
192
+ let path: string | undefined
193
+ let head: string | undefined
194
+ let branch: string | undefined
195
+ for (const line of lines) {
196
+ if (line.startsWith('worktree ')) path = line.slice('worktree '.length)
197
+ else if (line.startsWith('HEAD ')) head = line.slice('HEAD '.length)
198
+ else if (line.startsWith('branch ')) branch = line.slice('branch '.length)
199
+ }
200
+ if (path === worktreePath) {
201
+ return {
202
+ path,
203
+ ...(head !== undefined && { head }),
204
+ ...(branch !== undefined && { branch }),
205
+ }
206
+ }
207
+ }
208
+ return null
209
+ }