macro-agent 0.0.10 → 0.0.12

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 (518) hide show
  1. package/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
  2. package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
  3. package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
  4. package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
  5. package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
  6. package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
  7. package/.macro-agent/teams/self-driving/team.yaml +103 -0
  8. package/.macro-agent/teams/structured/prompts/developer.md +26 -0
  9. package/.macro-agent/teams/structured/prompts/lead.md +25 -0
  10. package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
  11. package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
  12. package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
  13. package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
  14. package/.macro-agent/teams/structured/team.yaml +89 -0
  15. package/.sudocode/issues.jsonl +56 -51
  16. package/.sudocode/specs.jsonl +8 -1
  17. package/CLAUDE.md +121 -30
  18. package/README.md +60 -3
  19. package/dist/acp/macro-agent.d.ts +4 -0
  20. package/dist/acp/macro-agent.d.ts.map +1 -1
  21. package/dist/acp/macro-agent.js +50 -4
  22. package/dist/acp/macro-agent.js.map +1 -1
  23. package/dist/acp/session-mapper.d.ts +20 -1
  24. package/dist/acp/session-mapper.d.ts.map +1 -1
  25. package/dist/acp/session-mapper.js +90 -1
  26. package/dist/acp/session-mapper.js.map +1 -1
  27. package/dist/acp/types.d.ts +24 -1
  28. package/dist/acp/types.d.ts.map +1 -1
  29. package/dist/acp/types.js.map +1 -1
  30. package/dist/agent/agent-manager.d.ts +40 -1
  31. package/dist/agent/agent-manager.d.ts.map +1 -1
  32. package/dist/agent/agent-manager.js +172 -8
  33. package/dist/agent/agent-manager.js.map +1 -1
  34. package/dist/agent/types.d.ts +22 -0
  35. package/dist/agent/types.d.ts.map +1 -1
  36. package/dist/agent/types.js.map +1 -1
  37. package/dist/agent/wake.d.ts +15 -0
  38. package/dist/agent/wake.d.ts.map +1 -1
  39. package/dist/agent/wake.js +15 -0
  40. package/dist/agent/wake.js.map +1 -1
  41. package/dist/agent-detection/command-builder.d.ts +30 -0
  42. package/dist/agent-detection/command-builder.d.ts.map +1 -0
  43. package/dist/agent-detection/command-builder.js +71 -0
  44. package/dist/agent-detection/command-builder.js.map +1 -0
  45. package/dist/agent-detection/detector.d.ts +84 -0
  46. package/dist/agent-detection/detector.d.ts.map +1 -0
  47. package/dist/agent-detection/detector.js +240 -0
  48. package/dist/agent-detection/detector.js.map +1 -0
  49. package/dist/agent-detection/index.d.ts +12 -0
  50. package/dist/agent-detection/index.d.ts.map +1 -0
  51. package/dist/agent-detection/index.js +14 -0
  52. package/dist/agent-detection/index.js.map +1 -0
  53. package/dist/agent-detection/registry.d.ts +53 -0
  54. package/dist/agent-detection/registry.d.ts.map +1 -0
  55. package/dist/agent-detection/registry.js +177 -0
  56. package/dist/agent-detection/registry.js.map +1 -0
  57. package/dist/agent-detection/types.d.ts +121 -0
  58. package/dist/agent-detection/types.d.ts.map +1 -0
  59. package/dist/agent-detection/types.js +20 -0
  60. package/dist/agent-detection/types.js.map +1 -0
  61. package/dist/api/server.d.ts +5 -1
  62. package/dist/api/server.d.ts.map +1 -1
  63. package/dist/api/server.js +362 -0
  64. package/dist/api/server.js.map +1 -1
  65. package/dist/api/types.d.ts +50 -1
  66. package/dist/api/types.d.ts.map +1 -1
  67. package/dist/cli/acp.d.ts +2 -0
  68. package/dist/cli/acp.d.ts.map +1 -1
  69. package/dist/cli/acp.js +8 -1
  70. package/dist/cli/acp.js.map +1 -1
  71. package/dist/cli/index.js +29 -0
  72. package/dist/cli/index.js.map +1 -1
  73. package/dist/cli/mcp.js +38 -0
  74. package/dist/cli/mcp.js.map +1 -1
  75. package/dist/config/index.d.ts +2 -0
  76. package/dist/config/index.d.ts.map +1 -0
  77. package/dist/config/index.js +2 -0
  78. package/dist/config/index.js.map +1 -0
  79. package/dist/config/project-config.d.ts +46 -0
  80. package/dist/config/project-config.d.ts.map +1 -0
  81. package/dist/config/project-config.js +68 -0
  82. package/dist/config/project-config.js.map +1 -0
  83. package/dist/lifecycle/cascade.d.ts +1 -1
  84. package/dist/lifecycle/cascade.d.ts.map +1 -1
  85. package/dist/lifecycle/handlers/index.d.ts +4 -0
  86. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  87. package/dist/lifecycle/handlers/index.js +2 -0
  88. package/dist/lifecycle/handlers/index.js.map +1 -1
  89. package/dist/lifecycle/handlers/worker.d.ts +4 -0
  90. package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
  91. package/dist/lifecycle/handlers/worker.js +35 -3
  92. package/dist/lifecycle/handlers/worker.js.map +1 -1
  93. package/dist/mail/conversation-map.d.ts +33 -0
  94. package/dist/mail/conversation-map.d.ts.map +1 -0
  95. package/dist/mail/conversation-map.js +61 -0
  96. package/dist/mail/conversation-map.js.map +1 -0
  97. package/dist/mail/index.d.ts +11 -0
  98. package/dist/mail/index.d.ts.map +1 -0
  99. package/dist/mail/index.js +11 -0
  100. package/dist/mail/index.js.map +1 -0
  101. package/dist/mail/mail-service.d.ts +85 -0
  102. package/dist/mail/mail-service.d.ts.map +1 -0
  103. package/dist/mail/mail-service.js +121 -0
  104. package/dist/mail/mail-service.js.map +1 -0
  105. package/dist/mail/stores/eventstore-conversation-store.d.ts +40 -0
  106. package/dist/mail/stores/eventstore-conversation-store.d.ts.map +1 -0
  107. package/dist/mail/stores/eventstore-conversation-store.js +131 -0
  108. package/dist/mail/stores/eventstore-conversation-store.js.map +1 -0
  109. package/dist/mail/stores/eventstore-participant-store.d.ts +43 -0
  110. package/dist/mail/stores/eventstore-participant-store.d.ts.map +1 -0
  111. package/dist/mail/stores/eventstore-participant-store.js +145 -0
  112. package/dist/mail/stores/eventstore-participant-store.js.map +1 -0
  113. package/dist/mail/stores/eventstore-thread-store.d.ts +46 -0
  114. package/dist/mail/stores/eventstore-thread-store.d.ts.map +1 -0
  115. package/dist/mail/stores/eventstore-thread-store.js +118 -0
  116. package/dist/mail/stores/eventstore-thread-store.js.map +1 -0
  117. package/dist/mail/stores/eventstore-turn-store.d.ts +47 -0
  118. package/dist/mail/stores/eventstore-turn-store.d.ts.map +1 -0
  119. package/dist/mail/stores/eventstore-turn-store.js +153 -0
  120. package/dist/mail/stores/eventstore-turn-store.js.map +1 -0
  121. package/dist/mail/stores/index.d.ts +12 -0
  122. package/dist/mail/stores/index.d.ts.map +1 -0
  123. package/dist/mail/stores/index.js +12 -0
  124. package/dist/mail/stores/index.js.map +1 -0
  125. package/dist/mail/stores/types.d.ts +146 -0
  126. package/dist/mail/stores/types.d.ts.map +1 -0
  127. package/dist/mail/stores/types.js +13 -0
  128. package/dist/mail/stores/types.js.map +1 -0
  129. package/dist/mail/turn-recorder.d.ts +30 -0
  130. package/dist/mail/turn-recorder.d.ts.map +1 -0
  131. package/dist/mail/turn-recorder.js +98 -0
  132. package/dist/mail/turn-recorder.js.map +1 -0
  133. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  134. package/dist/map/adapter/acp-over-map.js +32 -2
  135. package/dist/map/adapter/acp-over-map.js.map +1 -1
  136. package/dist/map/adapter/event-translator.d.ts.map +1 -1
  137. package/dist/map/adapter/event-translator.js +4 -0
  138. package/dist/map/adapter/event-translator.js.map +1 -1
  139. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  140. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  141. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  142. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  143. package/dist/map/adapter/extensions/index.d.ts +10 -1
  144. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  145. package/dist/map/adapter/extensions/index.js +39 -0
  146. package/dist/map/adapter/extensions/index.js.map +1 -1
  147. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  148. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  149. package/dist/map/adapter/extensions/resume.js +59 -0
  150. package/dist/map/adapter/extensions/resume.js.map +1 -0
  151. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  152. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  153. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  154. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  155. package/dist/map/adapter/mail-handler-adapter.d.ts +27 -0
  156. package/dist/map/adapter/mail-handler-adapter.d.ts.map +1 -0
  157. package/dist/map/adapter/mail-handler-adapter.js +292 -0
  158. package/dist/map/adapter/mail-handler-adapter.js.map +1 -0
  159. package/dist/map/adapter/map-adapter.d.ts +34 -10
  160. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  161. package/dist/map/adapter/map-adapter.js +110 -14
  162. package/dist/map/adapter/map-adapter.js.map +1 -1
  163. package/dist/map/adapter/rpc-handler.d.ts +4 -1
  164. package/dist/map/adapter/rpc-handler.d.ts.map +1 -1
  165. package/dist/map/adapter/rpc-handler.js +6 -0
  166. package/dist/map/adapter/rpc-handler.js.map +1 -1
  167. package/dist/map/index.d.ts +1 -0
  168. package/dist/map/index.d.ts.map +1 -1
  169. package/dist/map/index.js +2 -0
  170. package/dist/map/index.js.map +1 -1
  171. package/dist/map/types.d.ts +3 -1
  172. package/dist/map/types.d.ts.map +1 -1
  173. package/dist/map/types.js.map +1 -1
  174. package/dist/mcp/mcp-server.d.ts +6 -0
  175. package/dist/mcp/mcp-server.d.ts.map +1 -1
  176. package/dist/mcp/mcp-server.js +45 -0
  177. package/dist/mcp/mcp-server.js.map +1 -1
  178. package/dist/mcp/tools/claim_task.d.ts +35 -0
  179. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  180. package/dist/mcp/tools/claim_task.js +58 -0
  181. package/dist/mcp/tools/claim_task.js.map +1 -0
  182. package/dist/mcp/tools/done.d.ts +15 -2
  183. package/dist/mcp/tools/done.d.ts.map +1 -1
  184. package/dist/mcp/tools/done.js +45 -10
  185. package/dist/mcp/tools/done.js.map +1 -1
  186. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  187. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  188. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  189. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  190. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  191. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  192. package/dist/mcp/tools/unclaim_task.js +47 -0
  193. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  194. package/dist/metrics/index.d.ts +2 -0
  195. package/dist/metrics/index.d.ts.map +1 -0
  196. package/dist/metrics/index.js +2 -0
  197. package/dist/metrics/index.js.map +1 -0
  198. package/dist/metrics/metrics.d.ts +79 -0
  199. package/dist/metrics/metrics.d.ts.map +1 -0
  200. package/dist/metrics/metrics.js +166 -0
  201. package/dist/metrics/metrics.js.map +1 -0
  202. package/dist/roles/capabilities.d.ts +1 -0
  203. package/dist/roles/capabilities.d.ts.map +1 -1
  204. package/dist/roles/capabilities.js +3 -0
  205. package/dist/roles/capabilities.js.map +1 -1
  206. package/dist/roles/types.d.ts +1 -1
  207. package/dist/roles/types.d.ts.map +1 -1
  208. package/dist/router/channels.d.ts +2 -4
  209. package/dist/router/channels.d.ts.map +1 -1
  210. package/dist/router/channels.js.map +1 -1
  211. package/dist/router/message-router.d.ts +85 -9
  212. package/dist/router/message-router.d.ts.map +1 -1
  213. package/dist/router/message-router.js +203 -14
  214. package/dist/router/message-router.js.map +1 -1
  215. package/dist/router/role-resolver.d.ts +10 -1
  216. package/dist/router/role-resolver.d.ts.map +1 -1
  217. package/dist/router/role-resolver.js +15 -1
  218. package/dist/router/role-resolver.js.map +1 -1
  219. package/dist/router/types.d.ts +30 -1
  220. package/dist/router/types.d.ts.map +1 -1
  221. package/dist/router/types.js.map +1 -1
  222. package/dist/server/combined-server.d.ts +6 -0
  223. package/dist/server/combined-server.d.ts.map +1 -1
  224. package/dist/server/combined-server.js +24 -2
  225. package/dist/server/combined-server.js.map +1 -1
  226. package/dist/store/event-store.d.ts +14 -1
  227. package/dist/store/event-store.d.ts.map +1 -1
  228. package/dist/store/event-store.js +456 -4
  229. package/dist/store/event-store.js.map +1 -1
  230. package/dist/store/types/agents.d.ts +1 -1
  231. package/dist/store/types/agents.d.ts.map +1 -1
  232. package/dist/store/types/conversations.d.ts +91 -0
  233. package/dist/store/types/conversations.d.ts.map +1 -0
  234. package/dist/store/types/conversations.js +8 -0
  235. package/dist/store/types/conversations.js.map +1 -0
  236. package/dist/store/types/events.d.ts +1 -1
  237. package/dist/store/types/events.d.ts.map +1 -1
  238. package/dist/store/types/events.js.map +1 -1
  239. package/dist/store/types/index.d.ts +2 -0
  240. package/dist/store/types/index.d.ts.map +1 -1
  241. package/dist/store/types/index.js +2 -0
  242. package/dist/store/types/index.js.map +1 -1
  243. package/dist/store/types/sessions.d.ts +44 -0
  244. package/dist/store/types/sessions.d.ts.map +1 -0
  245. package/dist/store/types/sessions.js +9 -0
  246. package/dist/store/types/sessions.js.map +1 -0
  247. package/dist/store/types/tasks.d.ts +2 -0
  248. package/dist/store/types/tasks.d.ts.map +1 -1
  249. package/dist/task/backend/memory.d.ts +4 -1
  250. package/dist/task/backend/memory.d.ts.map +1 -1
  251. package/dist/task/backend/memory.js +81 -0
  252. package/dist/task/backend/memory.js.map +1 -1
  253. package/dist/task/backend/types.d.ts +30 -0
  254. package/dist/task/backend/types.d.ts.map +1 -1
  255. package/dist/task/backend/types.js.map +1 -1
  256. package/dist/teams/index.d.ts +4 -0
  257. package/dist/teams/index.d.ts.map +1 -0
  258. package/dist/teams/index.js +4 -0
  259. package/dist/teams/index.js.map +1 -0
  260. package/dist/teams/team-loader.d.ts +20 -0
  261. package/dist/teams/team-loader.d.ts.map +1 -0
  262. package/dist/teams/team-loader.js +293 -0
  263. package/dist/teams/team-loader.js.map +1 -0
  264. package/dist/teams/team-runtime.d.ts +139 -0
  265. package/dist/teams/team-runtime.d.ts.map +1 -0
  266. package/dist/teams/team-runtime.js +613 -0
  267. package/dist/teams/team-runtime.js.map +1 -0
  268. package/dist/teams/types.d.ts +266 -0
  269. package/dist/teams/types.d.ts.map +1 -0
  270. package/dist/teams/types.js +20 -0
  271. package/dist/teams/types.js.map +1 -0
  272. package/dist/trigger/router/trigger-router.d.ts +30 -3
  273. package/dist/trigger/router/trigger-router.d.ts.map +1 -1
  274. package/dist/trigger/router/trigger-router.js +30 -3
  275. package/dist/trigger/router/trigger-router.js.map +1 -1
  276. package/dist/trigger/wake/types.d.ts +31 -5
  277. package/dist/trigger/wake/types.d.ts.map +1 -1
  278. package/dist/trigger/wake/types.js +19 -0
  279. package/dist/trigger/wake/types.js.map +1 -1
  280. package/dist/workspace/dataplane-adapter.d.ts +1 -1
  281. package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
  282. package/dist/workspace/dataplane-adapter.js +1 -1
  283. package/dist/workspace/dataplane-adapter.js.map +1 -1
  284. package/dist/workspace/index.d.ts +1 -1
  285. package/dist/workspace/index.d.ts.map +1 -1
  286. package/dist/workspace/strategies/index.d.ts +6 -0
  287. package/dist/workspace/strategies/index.d.ts.map +1 -0
  288. package/dist/workspace/strategies/index.js +5 -0
  289. package/dist/workspace/strategies/index.js.map +1 -0
  290. package/dist/workspace/strategies/optimistic.d.ts +26 -0
  291. package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
  292. package/dist/workspace/strategies/optimistic.js +121 -0
  293. package/dist/workspace/strategies/optimistic.js.map +1 -0
  294. package/dist/workspace/strategies/queue.d.ts +26 -0
  295. package/dist/workspace/strategies/queue.d.ts.map +1 -0
  296. package/dist/workspace/strategies/queue.js +67 -0
  297. package/dist/workspace/strategies/queue.js.map +1 -0
  298. package/dist/workspace/strategies/registry.d.ts +37 -0
  299. package/dist/workspace/strategies/registry.d.ts.map +1 -0
  300. package/dist/workspace/strategies/registry.js +63 -0
  301. package/dist/workspace/strategies/registry.js.map +1 -0
  302. package/dist/workspace/strategies/trunk.d.ts +20 -0
  303. package/dist/workspace/strategies/trunk.d.ts.map +1 -0
  304. package/dist/workspace/strategies/trunk.js +108 -0
  305. package/dist/workspace/strategies/trunk.js.map +1 -0
  306. package/dist/workspace/strategies/types.d.ts +104 -0
  307. package/dist/workspace/strategies/types.d.ts.map +1 -0
  308. package/dist/workspace/strategies/types.js +11 -0
  309. package/dist/workspace/strategies/types.js.map +1 -0
  310. package/dist/workspace/types.d.ts +1 -1
  311. package/dist/workspace/types.d.ts.map +1 -1
  312. package/dist/workspace/workspace-manager.d.ts +1 -1
  313. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  314. package/docs/implementation-details.md +1127 -0
  315. package/docs/implementation-summary.md +448 -0
  316. package/docs/mail-integration.md +608 -0
  317. package/docs/plan-self-driving-support.md +433 -0
  318. package/docs/spec-self-driving-support.md +462 -0
  319. package/docs/team-templates.md +860 -0
  320. package/docs/teams.md +233 -0
  321. package/package.json +5 -3
  322. package/src/acp/__tests__/integration.test.ts +161 -1
  323. package/src/acp/__tests__/macro-agent.test.ts +95 -0
  324. package/src/acp/__tests__/session-persistence.test.ts +276 -0
  325. package/src/acp/macro-agent.ts +79 -7
  326. package/src/acp/session-mapper.ts +108 -1
  327. package/src/acp/types.ts +33 -1
  328. package/src/agent/agent-manager.ts +278 -6
  329. package/src/agent/types.ts +27 -0
  330. package/src/agent/wake.ts +15 -0
  331. package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
  332. package/src/agent-detection/__tests__/detector.test.ts +768 -0
  333. package/src/agent-detection/__tests__/registry.test.ts +254 -0
  334. package/src/agent-detection/command-builder.ts +90 -0
  335. package/src/agent-detection/detector.ts +307 -0
  336. package/src/agent-detection/index.ts +36 -0
  337. package/src/agent-detection/registry.ts +200 -0
  338. package/src/agent-detection/types.ts +184 -0
  339. package/src/api/__tests__/conversation-api.test.ts +468 -0
  340. package/src/api/server.ts +425 -1
  341. package/src/api/types.ts +64 -1
  342. package/src/cli/acp.ts +9 -1
  343. package/src/cli/index.ts +44 -0
  344. package/src/cli/mcp.ts +47 -0
  345. package/src/config/index.ts +9 -0
  346. package/src/config/project-config.ts +107 -0
  347. package/src/lifecycle/cascade.ts +1 -1
  348. package/src/lifecycle/handlers/index.ts +8 -0
  349. package/src/lifecycle/handlers/worker.ts +48 -3
  350. package/src/mail/__tests__/conversation-lifecycle.test.ts +409 -0
  351. package/src/mail/__tests__/eventstore-stores.test.ts +1073 -0
  352. package/src/mail/__tests__/mail-full-agent.e2e.test.ts +575 -0
  353. package/src/mail/__tests__/mail-integration.test.ts +759 -0
  354. package/src/mail/__tests__/mail-map-protocol.e2e.test.ts +1068 -0
  355. package/src/mail/__tests__/mail-service.test.ts +506 -0
  356. package/src/mail/__tests__/turn-recorder.test.ts +328 -0
  357. package/src/mail/conversation-map.ts +107 -0
  358. package/src/mail/index.ts +25 -0
  359. package/src/mail/mail-service.ts +257 -0
  360. package/src/mail/stores/eventstore-conversation-store.ts +146 -0
  361. package/src/mail/stores/eventstore-participant-store.ts +172 -0
  362. package/src/mail/stores/eventstore-thread-store.ts +129 -0
  363. package/src/mail/stores/eventstore-turn-store.ts +173 -0
  364. package/src/mail/stores/index.ts +12 -0
  365. package/src/mail/stores/types.ts +160 -0
  366. package/src/mail/turn-recorder.ts +124 -0
  367. package/src/map/README.md +79 -0
  368. package/src/map/adapter/__tests__/extensions.test.ts +359 -0
  369. package/src/map/adapter/__tests__/map-adapter.test.ts +90 -0
  370. package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
  371. package/src/map/adapter/acp-over-map.ts +45 -2
  372. package/src/map/adapter/event-translator.ts +4 -0
  373. package/src/map/adapter/extensions/agent-detection.ts +201 -0
  374. package/src/map/adapter/extensions/index.ts +63 -0
  375. package/src/map/adapter/extensions/resume.ts +114 -0
  376. package/src/map/adapter/extensions/workspace-files.ts +449 -0
  377. package/src/map/adapter/mail-handler-adapter.ts +429 -0
  378. package/src/map/adapter/map-adapter.ts +173 -27
  379. package/src/map/adapter/rpc-handler.ts +8 -1
  380. package/src/map/index.ts +3 -0
  381. package/src/map/types.ts +3 -1
  382. package/src/mcp/mcp-server.ts +67 -0
  383. package/src/mcp/tools/claim_task.ts +86 -0
  384. package/src/mcp/tools/done.ts +59 -10
  385. package/src/mcp/tools/list_claimable_tasks.ts +93 -0
  386. package/src/mcp/tools/unclaim_task.ts +71 -0
  387. package/src/metrics/index.ts +9 -0
  388. package/src/metrics/metrics.ts +280 -0
  389. package/src/roles/capabilities.ts +3 -0
  390. package/src/roles/types.ts +2 -1
  391. package/src/router/README.md +120 -0
  392. package/src/router/__tests__/message-router.test.ts +561 -0
  393. package/src/router/channels.ts +3 -4
  394. package/src/router/message-router.ts +308 -22
  395. package/src/router/role-resolver.ts +22 -1
  396. package/src/router/types.ts +36 -1
  397. package/src/server/combined-server.ts +36 -2
  398. package/src/store/README.md +134 -0
  399. package/src/store/event-store.ts +546 -3
  400. package/src/store/types/agents.ts +1 -1
  401. package/src/store/types/conversations.ts +129 -0
  402. package/src/store/types/events.ts +5 -1
  403. package/src/store/types/index.ts +2 -0
  404. package/src/store/types/sessions.ts +53 -0
  405. package/src/store/types/tasks.ts +3 -0
  406. package/src/task/backend/memory.ts +116 -0
  407. package/src/task/backend/types.ts +43 -0
  408. package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
  409. package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
  410. package/src/teams/__tests__/team-system.test.ts +1280 -0
  411. package/src/teams/index.ts +13 -0
  412. package/src/teams/team-loader.ts +434 -0
  413. package/src/teams/team-runtime.ts +727 -0
  414. package/src/teams/types.ts +377 -0
  415. package/src/trigger/router/trigger-router.ts +30 -3
  416. package/src/trigger/wake/types.ts +32 -5
  417. package/src/trigger/wake/wake-manager.ts +2 -2
  418. package/src/workspace/dataplane-adapter.ts +1 -1
  419. package/src/workspace/index.ts +1 -1
  420. package/src/workspace/strategies/index.ts +18 -0
  421. package/src/workspace/strategies/optimistic.ts +136 -0
  422. package/src/workspace/strategies/queue.ts +81 -0
  423. package/src/workspace/strategies/registry.ts +89 -0
  424. package/src/workspace/strategies/trunk.ts +123 -0
  425. package/src/workspace/strategies/types.ts +145 -0
  426. package/src/workspace/types.ts +1 -1
  427. package/src/workspace/workspace-manager.ts +1 -1
  428. package/.claude/settings.local.json +0 -59
  429. package/dist/map/utils/address-translation.d.ts +0 -99
  430. package/dist/map/utils/address-translation.d.ts.map +0 -1
  431. package/dist/map/utils/address-translation.js +0 -285
  432. package/dist/map/utils/address-translation.js.map +0 -1
  433. package/dist/map/utils/index.d.ts +0 -7
  434. package/dist/map/utils/index.d.ts.map +0 -1
  435. package/dist/map/utils/index.js +0 -7
  436. package/dist/map/utils/index.js.map +0 -1
  437. package/openspec/AGENTS.md +0 -456
  438. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/design.md +0 -128
  439. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/proposal.md +0 -49
  440. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/agent-manager/spec.md +0 -150
  441. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/cli-api/spec.md +0 -258
  442. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/event-store/spec.md +0 -160
  443. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/mcp-tools/spec.md +0 -224
  444. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/message-router/spec.md +0 -153
  445. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/specs/task-manager/spec.md +0 -136
  446. package/openspec/changes/archive/2025-12-21-add-mvp-foundation/tasks.md +0 -147
  447. package/openspec/project.md +0 -31
  448. package/openspec/specs/agent-manager/spec.md +0 -154
  449. package/openspec/specs/cli-api/spec.md +0 -262
  450. package/openspec/specs/event-store/spec.md +0 -164
  451. package/openspec/specs/mcp-tools/spec.md +0 -228
  452. package/openspec/specs/message-router/spec.md +0 -157
  453. package/openspec/specs/task-manager/spec.md +0 -140
  454. package/references/acp-factory-ref/CHANGELOG.md +0 -33
  455. package/references/acp-factory-ref/LICENSE +0 -21
  456. package/references/acp-factory-ref/README.md +0 -341
  457. package/references/acp-factory-ref/package-lock.json +0 -3102
  458. package/references/acp-factory-ref/package.json +0 -96
  459. package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
  460. package/references/acp-factory-ref/python/LICENSE +0 -21
  461. package/references/acp-factory-ref/python/Makefile +0 -57
  462. package/references/acp-factory-ref/python/README.md +0 -253
  463. package/references/acp-factory-ref/python/pyproject.toml +0 -73
  464. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  465. package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
  466. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
  467. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
  468. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
  469. package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
  470. package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
  471. package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
  472. package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
  473. package/references/claude-code-acp/.prettierrc.json +0 -4
  474. package/references/claude-code-acp/CHANGELOG.md +0 -249
  475. package/references/claude-code-acp/LICENSE +0 -222
  476. package/references/claude-code-acp/README.md +0 -53
  477. package/references/claude-code-acp/docs/RELEASES.md +0 -24
  478. package/references/claude-code-acp/eslint.config.js +0 -48
  479. package/references/claude-code-acp/package-lock.json +0 -4570
  480. package/references/claude-code-acp/package.json +0 -88
  481. package/references/claude-code-acp/scripts/release.sh +0 -119
  482. package/references/claude-code-acp/src/acp-agent.ts +0 -2065
  483. package/references/claude-code-acp/src/index.ts +0 -26
  484. package/references/claude-code-acp/src/lib.ts +0 -38
  485. package/references/claude-code-acp/src/mcp-server.ts +0 -911
  486. package/references/claude-code-acp/src/settings.ts +0 -522
  487. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
  488. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
  489. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
  490. package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
  491. package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
  492. package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
  493. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
  494. package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
  495. package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
  496. package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
  497. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
  498. package/references/claude-code-acp/src/tools.ts +0 -819
  499. package/references/claude-code-acp/src/utils.ts +0 -171
  500. package/references/claude-code-acp/tsconfig.json +0 -18
  501. package/references/claude-code-acp/vitest.config.ts +0 -19
  502. package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -82
  503. package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -9
  504. package/references/multi-agent-protocol/LICENSE +0 -21
  505. package/references/multi-agent-protocol/README.md +0 -113
  506. package/references/multi-agent-protocol/docs/00-design-specification.md +0 -460
  507. package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
  508. package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
  509. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
  510. package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
  511. package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
  512. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
  513. package/references/multi-agent-protocol/docs/07-federation.md +0 -259
  514. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
  515. package/references/multi-agent-protocol/package-lock.json +0 -3239
  516. package/references/multi-agent-protocol/package.json +0 -56
  517. package/references/multi-agent-protocol/schema/meta.json +0 -337
  518. package/references/multi-agent-protocol/schema/schema.json +0 -1828
@@ -0,0 +1,553 @@
1
+ /**
2
+ * Team Runtime E2E Tests
3
+ *
4
+ * Tests the full team system pipeline: template loading, runtime initialization,
5
+ * agent bootstrapping, spawn interception, and role capability propagation to
6
+ * MCP subprocesses.
7
+ *
8
+ * Group 1 (infrastructure) runs without real agents — tests TeamRuntime wiring
9
+ * against real EventStore, AgentManager, MessageRouter.
10
+ *
11
+ * Group 2 (full agent) spawns real Claude Code agents and requires:
12
+ * RUN_FULL_AGENT_TESTS=true
13
+ *
14
+ * Run:
15
+ * npm run test:e2e -- src/teams/__tests__/e2e/team-runtime.e2e.test.ts
16
+ * RUN_FULL_AGENT_TESTS=true npm run test:e2e -- src/teams/__tests__/e2e/team-runtime.e2e.test.ts
17
+ */
18
+
19
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
20
+ import * as fs from "fs";
21
+ import * as path from "path";
22
+ import * as os from "os";
23
+ import { execSync } from "child_process";
24
+
25
+ import { createEventStore, type EventStore } from "../../../store/event-store.js";
26
+ import { createAgentManager, type AgentManager } from "../../../agent/agent-manager.js";
27
+ import { createTaskManager, type TaskManager } from "../../../task/task-manager.js";
28
+ import { createMessageRouter, type MessageRouter } from "../../../router/message-router.js";
29
+ import { DefaultRoleRegistry } from "../../../roles/registry.js";
30
+ import type { RoleDefinition } from "../../../roles/types.js";
31
+ import { loadTeam } from "../../team-loader.js";
32
+ import { TeamRuntime, type TeamServices } from "../../team-runtime.js";
33
+
34
+ // ─────────────────────────────────────────────────────────────────
35
+ // Configuration
36
+ // ─────────────────────────────────────────────────────────────────
37
+
38
+ const RUN_FULL_AGENT = !!process.env.RUN_FULL_AGENT_TESTS;
39
+ const testFn = RUN_FULL_AGENT ? it : it.skip;
40
+ const PROJECT_ROOT = path.resolve(import.meta.dirname, "../../../..");
41
+
42
+ const log = (msg: string) => console.log(`[TeamRuntime-E2E] ${msg}`);
43
+
44
+ const TIMEOUT = {
45
+ SPAWN: 60000,
46
+ PROMPT: 120000,
47
+ BOOTSTRAP: 180000,
48
+ };
49
+
50
+ // ─────────────────────────────────────────────────────────────────
51
+ // Helpers
52
+ // ─────────────────────────────────────────────────────────────────
53
+
54
+ interface TempTestEnv {
55
+ tmpDir: string;
56
+ repoPath: string;
57
+ cleanup: () => void;
58
+ }
59
+
60
+ function createTestEnv(prefix: string): TempTestEnv {
61
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `team-e2e-${prefix}-`));
62
+ const repoPath = path.join(tmpDir, "repo");
63
+ fs.mkdirSync(repoPath);
64
+ execSync("git init", { cwd: repoPath, stdio: "pipe" });
65
+ execSync('git config user.email "test@test.com"', { cwd: repoPath, stdio: "pipe" });
66
+ execSync('git config user.name "Test"', { cwd: repoPath, stdio: "pipe" });
67
+ fs.writeFileSync(path.join(repoPath, "README.md"), "# test\n");
68
+ execSync("git add -A && git commit -m init", { cwd: repoPath, stdio: "pipe" });
69
+ return {
70
+ tmpDir,
71
+ repoPath,
72
+ cleanup: () => fs.rmSync(tmpDir, { recursive: true, force: true }),
73
+ };
74
+ }
75
+
76
+ async function waitForAgentState(
77
+ agentManager: AgentManager,
78
+ agentId: string,
79
+ state: "running" | "stopped",
80
+ timeoutMs = 60000
81
+ ): Promise<void> {
82
+ const start = Date.now();
83
+ while (Date.now() - start < timeoutMs) {
84
+ const agent = agentManager.get(agentId);
85
+ if (agent?.state === state) return;
86
+ await new Promise((r) => setTimeout(r, 500));
87
+ }
88
+ throw new Error(`Timeout: agent ${agentId} did not reach state '${state}' in ${timeoutMs}ms`);
89
+ }
90
+
91
+ // ─────────────────────────────────────────────────────────────────
92
+ // Group 1: Team Infrastructure (no real agents)
93
+ // ─────────────────────────────────────────────────────────────────
94
+
95
+ describe("Team Runtime E2E — Infrastructure", () => {
96
+ let env: TempTestEnv;
97
+ let eventStore: EventStore;
98
+ let agentManager: AgentManager;
99
+ let messageRouter: MessageRouter;
100
+ let taskManager: TaskManager;
101
+ let roleRegistry: DefaultRoleRegistry;
102
+
103
+ beforeEach(async () => {
104
+ env = createTestEnv("infra");
105
+ const instanceId = `team-infra-${Date.now()}`;
106
+
107
+ eventStore = await createEventStore({ instanceId, baseDir: env.tmpDir });
108
+ messageRouter = createMessageRouter(eventStore);
109
+ roleRegistry = new DefaultRoleRegistry();
110
+ agentManager = createAgentManager(eventStore, messageRouter, {
111
+ defaultPermissionMode: "auto-approve",
112
+ defaultCwd: env.repoPath,
113
+ });
114
+ taskManager = createTaskManager(eventStore);
115
+ });
116
+
117
+ afterEach(async () => {
118
+ await agentManager?.close();
119
+ await eventStore?.close();
120
+ env?.cleanup();
121
+ });
122
+
123
+ it("loads team template and initializes runtime with serialized roles", async () => {
124
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
125
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
126
+ const runtime = new TeamRuntime(manifest, services);
127
+
128
+ await runtime.initialize();
129
+
130
+ // 1. Roles registered in AgentManager's internal registry
131
+ const amRegistry = agentManager.getRoleRegistry();
132
+ expect(amRegistry.getRole("planner")).toBeDefined();
133
+ expect(amRegistry.getRole("grinder")).toBeDefined();
134
+ expect(amRegistry.getRole("judge")).toBeDefined();
135
+ log("Roles registered in registry");
136
+
137
+ // 2. team_config event emitted to EventStore
138
+ const events = eventStore.query({ type: "status", limit: 50 });
139
+ const configEvent = events.find((e) => e.payload?.team_config != null);
140
+ expect(configEvent).toBeDefined();
141
+
142
+ const tc = configEvent!.payload.team_config as Record<string, unknown>;
143
+ expect(tc.teamName).toBe("self-driving");
144
+ expect(tc.strategy).toBe("trunk");
145
+ expect(tc.taskMode).toBe("pull");
146
+ log("team_config event verified");
147
+
148
+ // 3. Serialized roles included in team_config (Issue #1 fix)
149
+ const roles = tc.roles as Record<string, { name: string; capabilities: string[] }>;
150
+ expect(roles).toBeDefined();
151
+ expect(roles.planner).toBeDefined();
152
+ expect(roles.grinder).toBeDefined();
153
+ expect(roles.judge).toBeDefined();
154
+ expect(roles.grinder.name).toBe("grinder");
155
+ expect(roles.grinder.capabilities).toContain("lifecycle.done");
156
+ expect(roles.planner.capabilities).toContain("task.claim");
157
+ log("Serialized roles in team_config verified");
158
+
159
+ // 4. Integration strategy instantiated (Issue #3 fix)
160
+ const strategy = runtime.getIntegrationStrategy();
161
+ expect(strategy).toBeDefined();
162
+ expect(strategy!.name).toBe("trunk");
163
+ log("Integration strategy instantiated");
164
+
165
+ await runtime.teardown();
166
+ });
167
+
168
+ it("serialized roles are deserializable in a fresh registry", async () => {
169
+ // Step 1: Initialize team to get serialized roles into EventStore
170
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
171
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
172
+ const runtime = new TeamRuntime(manifest, services);
173
+ await runtime.initialize();
174
+
175
+ // Step 2: Read team_config from EventStore (like MCP subprocess would)
176
+ const events = eventStore.query({ type: "status", limit: 50 });
177
+ const configEvent = events.find((e) => e.payload?.team_config != null);
178
+ const tc = configEvent!.payload.team_config as Record<string, unknown>;
179
+ const serializedRoles = tc.roles as Record<string, Record<string, unknown>>;
180
+
181
+ // Step 3: Create a fresh registry (simulating MCP subprocess)
182
+ const freshRegistry = new DefaultRoleRegistry();
183
+
184
+ // Verify "grinder" is unknown before registration
185
+ const beforeResolve = freshRegistry.resolveRole("grinder");
186
+ // Falls back to generic role which won't have lifecycle.done
187
+ expect(beforeResolve.name).not.toBe("grinder");
188
+
189
+ // Step 4: Register serialized roles
190
+ for (const roleDef of Object.values(serializedRoles)) {
191
+ freshRegistry.registerRole(roleDef as RoleDefinition);
192
+ }
193
+
194
+ // Step 5: Verify capability resolution
195
+ expect(freshRegistry.hasCapability("grinder", "lifecycle.done")).toBe(true);
196
+ expect(freshRegistry.hasCapability("planner", "task.claim")).toBe(true);
197
+ expect(freshRegistry.hasCapability("judge", "lifecycle.done")).toBe(true);
198
+ log("Serialized roles deserialized and resolved correctly in fresh registry");
199
+
200
+ await runtime.teardown();
201
+ });
202
+
203
+ it("teardown clears interceptor and strategy lifecycle", async () => {
204
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
205
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
206
+ const runtime = new TeamRuntime(manifest, services);
207
+
208
+ await runtime.initialize();
209
+ expect(runtime.getIntegrationStrategy()).toBeDefined();
210
+
211
+ await runtime.teardown();
212
+
213
+ // Getters still work (they read manifest, not mutable state)
214
+ expect(runtime.getStrategyName()).toBe("trunk");
215
+ expect(runtime.getTaskMode()).toBe("pull");
216
+ log("Teardown completed without errors");
217
+ });
218
+
219
+ it("structured team initializes with queue strategy", async () => {
220
+ const manifest = await loadTeam("structured", roleRegistry, PROJECT_ROOT);
221
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
222
+ const runtime = new TeamRuntime(manifest, services);
223
+
224
+ await runtime.initialize();
225
+
226
+ expect(runtime.getStrategyName()).toBe("queue");
227
+ expect(runtime.getTaskMode()).toBe("push");
228
+
229
+ const strategy = runtime.getIntegrationStrategy();
230
+ expect(strategy).toBeDefined();
231
+ expect(strategy!.name).toBe("queue");
232
+
233
+ // Verify structured team roles serialized
234
+ const events = eventStore.query({ type: "status", limit: 50 });
235
+ const configEvent = events.find((e) => e.payload?.team_config != null);
236
+ const tc = configEvent!.payload.team_config as Record<string, unknown>;
237
+ const roles = tc.roles as Record<string, { name: string; capabilities: string[] }>;
238
+ expect(roles.lead).toBeDefined();
239
+ expect(roles.developer).toBeDefined();
240
+ expect(roles.reviewer).toBeDefined();
241
+ log("Structured team initialized correctly");
242
+
243
+ await runtime.teardown();
244
+ });
245
+ });
246
+
247
+ // ─────────────────────────────────────────────────────────────────
248
+ // Group 2: Full Agent Tests (requires RUN_FULL_AGENT_TESTS)
249
+ // ─────────────────────────────────────────────────────────────────
250
+
251
+ describe("Team Runtime E2E — Full Agent", () => {
252
+ let env: TempTestEnv;
253
+ let eventStore: EventStore;
254
+ let agentManager: AgentManager;
255
+ let messageRouter: MessageRouter;
256
+ let taskManager: TaskManager;
257
+ let roleRegistry: DefaultRoleRegistry;
258
+ let runtime: TeamRuntime | null = null;
259
+
260
+ beforeEach(async () => {
261
+ if (!RUN_FULL_AGENT) return;
262
+
263
+ env = createTestEnv("agent");
264
+ const instanceId = `team-agent-${Date.now()}`;
265
+
266
+ eventStore = await createEventStore({ instanceId, baseDir: env.tmpDir });
267
+ messageRouter = createMessageRouter(eventStore);
268
+ roleRegistry = new DefaultRoleRegistry();
269
+ agentManager = createAgentManager(eventStore, messageRouter, {
270
+ defaultPermissionMode: "auto-approve",
271
+ defaultCwd: env.repoPath,
272
+ });
273
+ taskManager = createTaskManager(eventStore);
274
+
275
+ log("Services initialized");
276
+ });
277
+
278
+ afterEach(async () => {
279
+ if (!RUN_FULL_AGENT) return;
280
+
281
+ // Teardown team runtime first
282
+ if (runtime) {
283
+ try { await runtime.teardown(); } catch { /* ignore */ }
284
+ runtime = null;
285
+ }
286
+
287
+ // Terminate all running agents
288
+ try {
289
+ for (const agent of agentManager.list()) {
290
+ if (agent.state === "running") {
291
+ try { await agentManager.terminate(agent.id, "test_cleanup"); } catch { /* ignore */ }
292
+ }
293
+ }
294
+ } catch { /* ignore */ }
295
+
296
+ await agentManager?.close();
297
+ await eventStore?.close();
298
+ env?.cleanup();
299
+ log("Cleanup complete");
300
+ });
301
+
302
+ testFn(
303
+ "team bootstrap spawns root and companion agents",
304
+ async () => {
305
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
306
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
307
+ runtime = new TeamRuntime(manifest, services);
308
+
309
+ await runtime.initialize();
310
+ log("Runtime initialized");
311
+
312
+ const result = await runtime.bootstrap();
313
+ log(`Bootstrap complete: root=${result.rootId}, companions=${result.companionIds.join(", ")}`);
314
+
315
+ // Verify root agent is running
316
+ await waitForAgentState(agentManager, result.rootId, "running");
317
+ const rootAgent = agentManager.get(result.rootId);
318
+ expect(rootAgent).toBeDefined();
319
+ expect(rootAgent!.state).toBe("running");
320
+ expect(rootAgent!.role).toBe("planner");
321
+ expect(rootAgent!.parent).toBeNull();
322
+ log(`Root agent verified: ${result.rootId} (planner, running)`);
323
+
324
+ // Verify companion agent is running
325
+ expect(result.companionIds).toHaveLength(1);
326
+ const companionId = result.companionIds[0];
327
+ await waitForAgentState(agentManager, companionId, "running");
328
+ const companionAgent = agentManager.get(companionId);
329
+ expect(companionAgent).toBeDefined();
330
+ expect(companionAgent!.state).toBe("running");
331
+ expect(companionAgent!.role).toBe("judge");
332
+ expect(companionAgent!.parent).toBeNull(); // Peer, not child
333
+ log(`Companion agent verified: ${companionId} (judge, running)`);
334
+
335
+ // Verify runtime tracks agent IDs
336
+ expect(runtime.getRootAgentId()).toBe(result.rootId);
337
+ expect(runtime.getCompanionAgentIds()).toEqual(result.companionIds);
338
+ },
339
+ { timeout: TIMEOUT.BOOTSTRAP }
340
+ );
341
+
342
+ testFn(
343
+ "spawn interceptor injects team context into child agents",
344
+ async () => {
345
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
346
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
347
+ runtime = new TeamRuntime(manifest, services);
348
+
349
+ await runtime.initialize();
350
+ const result = await runtime.bootstrap();
351
+ await waitForAgentState(agentManager, result.rootId, "running");
352
+ log("Team bootstrapped");
353
+
354
+ // Spawn a grinder child (through the interceptor)
355
+ const grinder = await agentManager.spawn({
356
+ task: "Test grinder: wait for instructions.",
357
+ role: "grinder",
358
+ parent: result.rootId,
359
+ cwd: env.repoPath,
360
+ });
361
+
362
+ await waitForAgentState(agentManager, grinder.id, "running");
363
+ log(`Grinder spawned: ${grinder.id}`);
364
+
365
+ // Verify agent exists with correct role
366
+ const grinderAgent = agentManager.get(grinder.id);
367
+ expect(grinderAgent).toBeDefined();
368
+ expect(grinderAgent!.role).toBe("grinder");
369
+ expect(grinderAgent!.parent).toBe(result.rootId);
370
+ log("Grinder agent verified with correct role and parent");
371
+
372
+ // Verify team context was injected by checking the spawn event
373
+ // The spawn interceptor sets env vars, topics, and custom prompt
374
+ // We can verify by checking the agent's MCP env vars stored in the spawn event
375
+ const spawnEvents = eventStore.query({ type: "spawn", limit: 50 });
376
+ const grinderSpawn = spawnEvents.find(
377
+ (e) => e.payload?.agent_id === grinder.id
378
+ );
379
+ expect(grinderSpawn).toBeDefined();
380
+ log("Grinder spawn event found in EventStore");
381
+ },
382
+ { timeout: TIMEOUT.BOOTSTRAP }
383
+ );
384
+
385
+ testFn(
386
+ "team-defined role agent can call done() via MCP",
387
+ async () => {
388
+ // This is the critical E2E test for Issue #1: roleRegistry not passed to MCP subprocess
389
+ // The grinder role (extending worker) must have lifecycle.done capability
390
+ // resolved through the serialized roles in the team_config event.
391
+
392
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
393
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
394
+ runtime = new TeamRuntime(manifest, services);
395
+
396
+ await runtime.initialize();
397
+ log("Runtime initialized with serialized roles");
398
+
399
+ // Spawn a grinder agent directly (not through bootstrap — we want a targeted test)
400
+ const grinder = await agentManager.spawn({
401
+ task: `You are a grinder worker. Your only task is to call the done() tool with status "completed" and summary "E2E test done". Do this immediately — do not do any other work.`,
402
+ role: "grinder",
403
+ parent: null,
404
+ cwd: env.repoPath,
405
+ });
406
+
407
+ await waitForAgentState(agentManager, grinder.id, "running");
408
+ log(`Grinder spawned: ${grinder.id}`);
409
+
410
+ // Prompt the agent to trigger done()
411
+ log("Prompting grinder to call done()...");
412
+ let doneToolCalled = false;
413
+ let responseText = "";
414
+
415
+ for await (const update of agentManager.prompt(
416
+ grinder.id,
417
+ 'Call the done() MCP tool now with status "completed" and summary "E2E test done". This is your only task.'
418
+ )) {
419
+ const u = update as Record<string, unknown>;
420
+ if (u.sessionUpdate === "agent_message_chunk") {
421
+ const content = u.content as { text?: string } | undefined;
422
+ if (content?.text) {
423
+ responseText += content.text;
424
+ }
425
+ }
426
+ // Check for tool_use of done()
427
+ if (u.sessionUpdate === "tool_use" || u.type === "tool_use") {
428
+ const toolName =
429
+ (u as { name?: string }).name ??
430
+ (u as { tool_name?: string }).tool_name;
431
+ if (toolName?.includes("done")) {
432
+ doneToolCalled = true;
433
+ log("done() tool was called by agent");
434
+ }
435
+ }
436
+ }
437
+ log(`Prompt completed. Response length: ${responseText.length}`);
438
+
439
+ // The agent should have been able to call done() without a capability error.
440
+ // If done() was blocked by capability check, the agent would report an error.
441
+ // Check status events for a done/completed signal
442
+ const statusEvents = eventStore.query({
443
+ type: "status",
444
+ source_agent_id: grinder.id,
445
+ limit: 10,
446
+ });
447
+ const completionEvent = statusEvents.find(
448
+ (e) =>
449
+ e.payload?.status_type === "completed" ||
450
+ (e.payload?.summary as string)?.includes("done")
451
+ );
452
+
453
+ // At minimum, the agent shouldn't have reported a capability error
454
+ const hasCapabilityError =
455
+ responseText.toLowerCase().includes("does not have lifecycle.done capability") ||
456
+ responseText.toLowerCase().includes("capability check failed");
457
+ expect(hasCapabilityError).toBe(false);
458
+ log(
459
+ `Capability check: no error in response. done() tool called: ${doneToolCalled}. Completion event: ${!!completionEvent}`
460
+ );
461
+
462
+ // Terminate if still running
463
+ const agent = agentManager.get(grinder.id);
464
+ if (agent?.state === "running") {
465
+ await agentManager.terminate(grinder.id, "completed");
466
+ }
467
+ },
468
+ { timeout: TIMEOUT.PROMPT }
469
+ );
470
+
471
+ testFn(
472
+ "multiple team roles can coexist and operate independently",
473
+ async () => {
474
+ const manifest = await loadTeam("self-driving", roleRegistry, PROJECT_ROOT);
475
+ const services: TeamServices = { agentManager, messageRouter, eventStore };
476
+ runtime = new TeamRuntime(manifest, services);
477
+
478
+ await runtime.initialize();
479
+ log("Runtime initialized");
480
+
481
+ // Spawn agents with different team roles simultaneously
482
+ const planner = await agentManager.spawn({
483
+ task: "You are a planner. Wait for instructions.",
484
+ role: "planner",
485
+ parent: null,
486
+ cwd: env.repoPath,
487
+ });
488
+
489
+ const grinder = await agentManager.spawn({
490
+ task: "You are a grinder. Wait for instructions.",
491
+ role: "grinder",
492
+ parent: planner.id,
493
+ cwd: env.repoPath,
494
+ });
495
+
496
+ const judge = await agentManager.spawn({
497
+ task: "You are a judge. Wait for instructions.",
498
+ role: "judge",
499
+ parent: null,
500
+ cwd: env.repoPath,
501
+ });
502
+
503
+ // Wait for all to be running
504
+ await Promise.all([
505
+ waitForAgentState(agentManager, planner.id, "running"),
506
+ waitForAgentState(agentManager, grinder.id, "running"),
507
+ waitForAgentState(agentManager, judge.id, "running"),
508
+ ]);
509
+ log(
510
+ `All agents running: planner=${planner.id}, grinder=${grinder.id}, judge=${judge.id}`
511
+ );
512
+
513
+ // Verify roles
514
+ expect(agentManager.get(planner.id)?.role).toBe("planner");
515
+ expect(agentManager.get(grinder.id)?.role).toBe("grinder");
516
+ expect(agentManager.get(judge.id)?.role).toBe("judge");
517
+
518
+ // Verify hierarchy
519
+ expect(agentManager.get(planner.id)?.parent).toBeNull();
520
+ expect(agentManager.get(grinder.id)?.parent).toBe(planner.id);
521
+ expect(agentManager.get(judge.id)?.parent).toBeNull();
522
+
523
+ const children = agentManager.getChildren(planner.id);
524
+ expect(children).toHaveLength(1);
525
+ expect(children[0].id).toBe(grinder.id);
526
+ log("Hierarchy verified: planner → grinder, judge (peer)");
527
+
528
+ // Terminate in reverse order
529
+ await agentManager.terminate(grinder.id, "completed");
530
+ await agentManager.terminate(judge.id, "completed");
531
+ await agentManager.terminate(planner.id, "completed");
532
+ log("All agents terminated");
533
+ },
534
+ { timeout: TIMEOUT.BOOTSTRAP }
535
+ );
536
+ });
537
+
538
+ // ─────────────────────────────────────────────────────────────────
539
+ // Info message for running tests
540
+ // ─────────────────────────────────────────────────────────────────
541
+
542
+ if (!RUN_FULL_AGENT) {
543
+ console.log("\n┌──────────────────────────────────────────────────────────┐");
544
+ console.log("│ Team Runtime E2E full-agent tests are skipped │");
545
+ console.log("│ (RUN_FULL_AGENT_TESTS not set) │");
546
+ console.log("│ │");
547
+ console.log("│ Infrastructure tests will still run. │");
548
+ console.log("│ │");
549
+ console.log("│ To run with real agents: │");
550
+ console.log("│ RUN_FULL_AGENT_TESTS=true npm run test:e2e -- \\ │");
551
+ console.log("│ src/teams/__tests__/e2e/team-runtime.e2e.test.ts │");
552
+ console.log("└──────────────────────────────────────────────────────────┘\n");
553
+ }