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
@@ -1,13 +1,42 @@
1
1
  /**
2
- * MessageRouter - High-level message routing service
2
+ * MessageRouter - Core Internal Message Routing Service
3
3
  *
4
- * Provides message routing between agents with support for:
5
- * - Direct agent-to-agent messaging
6
- * - Task-based routing (to assigned agent)
7
- * - Topic-based pub/sub
8
- * - Lineage routing (ancestors to descendants)
9
- * - Subtree routing (status events to parent subscribers)
10
- * - Message acknowledgment
4
+ * ## Routing Architecture
5
+ *
6
+ * MessageRouter is the **core internal routing authority** for macro-agent.
7
+ * It handles all message delivery between internal agents.
8
+ *
9
+ * ```
10
+ * External MAPAdapter/TriggerRouter → MessageRouter → EventStore
11
+ * (protocol translation) (routing logic) (persistence)
12
+ * ```
13
+ *
14
+ * **Three routing entry points exist:**
15
+ *
16
+ * 1. **MessageRouter** (this module)
17
+ * - Internal routing for agent-to-agent communication
18
+ * - Supports: send(), sendToAddress(), emitStatus()
19
+ * - Used by: AgentManager, MCP tools, internal components
20
+ *
21
+ * 2. **MAPAdapter** (src/map/adapter/)
22
+ * - External MAP protocol interface for clients/agents/gateways
23
+ * - Translates MAP protocol → internal routing
24
+ * - Delegates message delivery to MessageRouter
25
+ *
26
+ * 3. **TriggerRouter** (src/trigger/router/)
27
+ * - External event routing (webhooks, cron, system events)
28
+ * - Queues events for batch delivery
29
+ * - Uses WakeManager for delivery scheduling
30
+ *
31
+ * ## Supported Routing Methods
32
+ *
33
+ * **Legacy Channel-based** (send, sendMessage):
34
+ * - Direct agent, task, topic, lineage, subtree, broadcast
35
+ *
36
+ * **MAP Address-based** (sendToAddress):
37
+ * - Agent, agents, task, scope, role, broadcast, hierarchical, federated
38
+ *
39
+ * @module router/message-router
11
40
  */
12
41
 
13
42
  import { nanoid } from "nanoid";
@@ -35,6 +64,7 @@ import type {
35
64
  SendToAddressRequest,
36
65
  AddressSendResult,
37
66
  Address,
67
+ TurnRecorderCallback,
38
68
  } from "./types.js";
39
69
  import { RoutingError, AddressRoutingError, DEFAULT_TRUNCATION_CONFIG } from "./types.js";
40
70
  import {
@@ -62,6 +92,7 @@ import {
62
92
  isFederatedAddress,
63
93
  describeAddress,
64
94
  } from "../map/types.js";
95
+ import type { DeliveryHint, HierarchicalAddress } from "../map/types.js";
65
96
  import type { FederationHandler } from "../map/federation/types.js";
66
97
  import { getSystemFromAddress } from "../map/federation/federation-handler.js";
67
98
  import {
@@ -166,8 +197,68 @@ export interface MessageRouter {
166
197
  * - Optionally subscribes parent to agent's subtree
167
198
  */
168
199
  setupDefaultSubscriptions(options: DefaultSubscriptionOptions): void;
200
+
201
+ /**
202
+ * Set turn recorder for conversation tracking.
203
+ * Called after direct message (agent/task address) delivery.
204
+ * Supports late binding since mail services may be created after router.
205
+ */
206
+ setTurnRecorder(recorder: TurnRecorderCallback): void;
207
+
208
+ /**
209
+ * Set signal filter for status notification delivery.
210
+ * Called before delivering each status notification — return false to suppress.
211
+ * Supports late binding since TeamRuntime is created after router.
212
+ */
213
+ setSignalFilter(filter: SignalFilter): void;
214
+
215
+ /**
216
+ * Set emission validator for outbound status events.
217
+ * Called before emitting a status event — can reject, warn, or audit.
218
+ * Supports late binding since TeamRuntime is created after router.
219
+ */
220
+ setEmissionValidator(validator: EmissionValidator): void;
169
221
  }
170
222
 
223
+ /**
224
+ * Signal filter callback for status notification delivery.
225
+ * Return true to deliver, false to suppress.
226
+ *
227
+ * @param from - Agent emitting the status
228
+ * @param to - Agent that would receive the notification
229
+ * @param signal - Signal name from details.signal (undefined if not tagged)
230
+ */
231
+ export type SignalFilter = (
232
+ from: AgentId,
233
+ to: AgentId,
234
+ signal: string | undefined
235
+ ) => boolean;
236
+
237
+ /**
238
+ * Emission validator result.
239
+ * - "allow": emit normally
240
+ * - "reject": block the emission (strict mode)
241
+ * - "warn": log warning but allow (permissive mode)
242
+ * - "audit": record audit event but allow (audit mode)
243
+ */
244
+ export type EmissionValidatorResult = {
245
+ action: "allow" | "reject" | "warn" | "audit";
246
+ message?: string;
247
+ };
248
+
249
+ /**
250
+ * Emission validator callback for outbound status events.
251
+ * Called with the emitting agent's ID and the signal name.
252
+ * Returns an action to take (allow, reject, warn, audit).
253
+ *
254
+ * @param agentId - Agent emitting the status
255
+ * @param signal - Signal name from details.signal (undefined if not tagged)
256
+ */
257
+ export type EmissionValidator = (
258
+ agentId: AgentId,
259
+ signal: string | undefined
260
+ ) => EmissionValidatorResult;
261
+
171
262
  /**
172
263
  * Callback invoked when a message determines a wake action
173
264
  */
@@ -223,6 +314,15 @@ export function createMessageRouter(
223
314
  const wakeHandler = config.wakeHandler;
224
315
  const federationHandler = config.federationHandler;
225
316
 
317
+ // Turn recorder for conversation tracking (late-bound)
318
+ let turnRecorder: TurnRecorderCallback | undefined;
319
+
320
+ // Signal filter for status notification delivery (late-bound)
321
+ let signalFilter: SignalFilter | undefined;
322
+
323
+ // Emission validator for outbound status events (late-bound)
324
+ let emissionValidator: EmissionValidator | undefined;
325
+
226
326
  // Track acknowledged messages: Map<agentId, Set<messageId>>
227
327
  const acknowledgedMessages = new Map<AgentId, Set<EventId>>();
228
328
 
@@ -323,7 +423,7 @@ export function createMessageRouter(
323
423
  if (sessionChecker && wakeHandler) {
324
424
  const decision = getWakeDecisionWithHint(
325
425
  to.agent,
326
- { priority: priority as MessagePriority, deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined },
426
+ { priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
327
427
  sessionChecker
328
428
  );
329
429
  if (decision.shouldWake || decision.shouldInterrupt) {
@@ -333,6 +433,15 @@ export function createMessageRouter(
333
433
 
334
434
  delivered.push(to.agent);
335
435
 
436
+ // Record turn for conversation tracking
437
+ if (turnRecorder) {
438
+ try {
439
+ turnRecorder({ from, toAgent: to.agent, content, messageId: event.id, addressType: "agent" });
440
+ } catch {
441
+ // Never fail delivery due to turn recording
442
+ }
443
+ }
444
+
336
445
  return {
337
446
  id: event.id,
338
447
  from,
@@ -392,7 +501,7 @@ export function createMessageRouter(
392
501
  if (sessionChecker && wakeHandler) {
393
502
  const decision = getWakeDecisionWithHint(
394
503
  targetAgentId,
395
- { priority: priority as MessagePriority, deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined },
504
+ { priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
396
505
  sessionChecker
397
506
  );
398
507
  if (decision.shouldWake || decision.shouldInterrupt) {
@@ -402,6 +511,15 @@ export function createMessageRouter(
402
511
 
403
512
  delivered.push(targetAgentId);
404
513
 
514
+ // Record turn for conversation tracking
515
+ if (turnRecorder) {
516
+ try {
517
+ turnRecorder({ from, toAgent: targetAgentId, content, messageId: event.id, addressType: "task" });
518
+ } catch {
519
+ // Never fail delivery due to turn recording
520
+ }
521
+ }
522
+
405
523
  return {
406
524
  id: event.id,
407
525
  from,
@@ -451,7 +569,7 @@ export function createMessageRouter(
451
569
  if (sessionChecker && wakeHandler) {
452
570
  const decision = getWakeDecisionWithHint(
453
571
  subscriberId,
454
- { priority: priority as MessagePriority, deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined },
572
+ { priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
455
573
  sessionChecker
456
574
  );
457
575
  if (decision.shouldWake || decision.shouldInterrupt) {
@@ -478,11 +596,16 @@ export function createMessageRouter(
478
596
  const agentSource: RoleAgentSource = {
479
597
  listAgents: () => eventStore.listAgents(),
480
598
  getAgent: (id) => eventStore.getAgent(id),
599
+ // Get agents subscribed to a scope/topic
600
+ getScopeMembers: (scope) => {
601
+ return eventStore.getSubscribers({ type: "topic", target: scope });
602
+ },
481
603
  };
482
604
 
483
605
  const recipientIds = resolveRoleTarget(agentSource, {
484
606
  role: to.role,
485
- coordinatorId: to.within,
607
+ // RoleAddress.within is a ScopeId (subscription-based), not a coordinatorId (hierarchy-based)
608
+ scope: to.within,
486
609
  });
487
610
 
488
611
  if (recipientIds.length === 0) {
@@ -537,7 +660,7 @@ export function createMessageRouter(
537
660
  if (sessionChecker && wakeHandler) {
538
661
  const decision = getWakeDecisionWithHint(
539
662
  recipientId,
540
- { priority: priority as MessagePriority, deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined },
663
+ { priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
541
664
  sessionChecker
542
665
  );
543
666
  if (decision.shouldWake || decision.shouldInterrupt) {
@@ -610,7 +733,7 @@ export function createMessageRouter(
610
733
  if (sessionChecker && wakeHandler) {
611
734
  const decision = getWakeDecisionWithHint(
612
735
  recipientId,
613
- { priority: priority as MessagePriority, deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined },
736
+ { priority: priority as MessagePriority, deliveryHint: delivery as DeliveryHint | undefined },
614
737
  sessionChecker
615
738
  );
616
739
  if (decision.shouldWake || decision.shouldInterrupt) {
@@ -676,7 +799,7 @@ export function createMessageRouter(
676
799
 
677
800
  // Resolve the hierarchical address
678
801
  const resolved = resolveHierarchicalAddress(
679
- to as import("../map/types.js").HierarchicalAddress,
802
+ to as HierarchicalAddress,
680
803
  from,
681
804
  hierarchySource
682
805
  );
@@ -735,7 +858,7 @@ export function createMessageRouter(
735
858
  recipientId,
736
859
  {
737
860
  priority: priority as MessagePriority,
738
- deliveryHint: delivery as import("../map/types.js").DeliveryHint | undefined,
861
+ deliveryHint: delivery as DeliveryHint | undefined,
739
862
  },
740
863
  sessionChecker
741
864
  );
@@ -865,6 +988,36 @@ export function createMessageRouter(
865
988
  function emitStatus(request: EmitStatusRequest): void {
866
989
  const { from, status_type, summary, details } = request;
867
990
 
991
+ // Check emission restrictions if validator installed
992
+ if (emissionValidator) {
993
+ const signal = (details as Record<string, unknown> | undefined)?.signal as string | undefined;
994
+ const result = emissionValidator(from.agent_id, signal);
995
+
996
+ if (result.action === "reject") {
997
+ // Strict mode: block the emission entirely
998
+ return;
999
+ }
1000
+
1001
+ if (result.action === "audit") {
1002
+ // Audit mode: record audit event, then continue with emission
1003
+ eventStore.emit({
1004
+ type: "status",
1005
+ source: { agent_id: "system" },
1006
+ payload: {
1007
+ status_type: "discovery",
1008
+ summary: result.message ?? `Emission audit: agent ${from.agent_id} emitted signal '${signal}'`,
1009
+ audit: {
1010
+ type: "emission_violation",
1011
+ agent_id: from.agent_id,
1012
+ signal,
1013
+ status_type,
1014
+ },
1015
+ },
1016
+ });
1017
+ }
1018
+ // "warn" and "allow" proceed normally (warning is logged by the validator installer)
1019
+ }
1020
+
868
1021
  // Emit status event to event store
869
1022
  const event = eventStore.emit({
870
1023
  type: "status",
@@ -879,15 +1032,20 @@ export function createMessageRouter(
879
1032
  },
880
1033
  });
881
1034
 
882
- // Route to subtree subscribers
883
- routeStatusToSubtreeSubscribers(from.agent_id, {
1035
+ const statusNotification: StatusNotification = {
884
1036
  agent_id: from.agent_id,
885
1037
  task_id: from.task_id,
886
1038
  status_type,
887
1039
  summary,
888
1040
  details,
889
1041
  timestamp: event.timestamp,
890
- });
1042
+ };
1043
+
1044
+ // Route to subtree subscribers (hierarchical: parents/ancestors)
1045
+ const subtreeRecipients = routeStatusToSubtreeSubscribers(from.agent_id, statusNotification);
1046
+
1047
+ // Route to topic co-subscribers (non-hierarchical: peers sharing topics)
1048
+ routeStatusToTopicSubscribers(from.agent_id, statusNotification, subtreeRecipients);
891
1049
  }
892
1050
 
893
1051
  // ─────────────────────────────────────────────────────────────────
@@ -1024,13 +1182,15 @@ export function createMessageRouter(
1024
1182
  /**
1025
1183
  * Route status event to subtree subscribers.
1026
1184
  * Parents who have subscribed to an agent's subtree receive status notifications.
1185
+ * Returns the set of agents that were notified (for dedup with topic routing).
1027
1186
  */
1028
1187
  function routeStatusToSubtreeSubscribers(
1029
1188
  agentId: AgentId,
1030
1189
  status: StatusNotification
1031
- ): void {
1190
+ ): Set<AgentId> {
1191
+ const notified = new Set<AgentId>();
1032
1192
  const agent = eventStore.getAgent(agentId);
1033
- if (!agent) return;
1193
+ if (!agent) return notified;
1034
1194
 
1035
1195
  // Find all agents with subtree subscription that includes this agent
1036
1196
  // This includes:
@@ -1064,17 +1224,25 @@ export function createMessageRouter(
1064
1224
  }
1065
1225
  }
1066
1226
 
1227
+ // Extract signal name from details (if tagged)
1228
+ const statusSignal = (status.details as Record<string, unknown> | undefined)?.signal as string | undefined;
1229
+
1067
1230
  // Send status notification to each subscriber
1068
1231
  for (const subscriberId of agentsToNotify) {
1069
1232
  // Skip self-notification
1070
1233
  if (subscriberId === agentId) continue;
1071
1234
 
1235
+ // Apply signal filter if installed
1236
+ if (signalFilter && !signalFilter(agentId, subscriberId, statusSignal)) {
1237
+ continue;
1238
+ }
1239
+
1072
1240
  const statusContent = JSON.stringify({
1073
1241
  type: "status_notification",
1074
1242
  ...status,
1075
1243
  });
1076
1244
 
1077
- eventStore.emit({
1245
+ const event = eventStore.emit({
1078
1246
  type: "message",
1079
1247
  source: {
1080
1248
  agent_id: agentId,
@@ -1087,7 +1255,122 @@ export function createMessageRouter(
1087
1255
  via: "subtree",
1088
1256
  },
1089
1257
  });
1258
+
1259
+ // Wake sleeping agents on status notifications
1260
+ if (sessionChecker && wakeHandler) {
1261
+ try {
1262
+ const decision = getWakeDecisionWithHint(
1263
+ subscriberId,
1264
+ { priority: "normal" as MessagePriority },
1265
+ sessionChecker
1266
+ );
1267
+ if (decision.shouldWake || decision.shouldInterrupt) {
1268
+ wakeHandler(subscriberId, decision, event.id);
1269
+ }
1270
+ } catch {
1271
+ // Never fail status delivery due to wake errors
1272
+ }
1273
+ }
1274
+
1275
+ notified.add(subscriberId);
1276
+ }
1277
+
1278
+ return notified;
1279
+ }
1280
+
1281
+ /**
1282
+ * Route status event to topic co-subscribers.
1283
+ * Agents sharing topic subscriptions with the emitting agent receive status notifications.
1284
+ * This enables non-hierarchical visibility: peers on the same topic see each other's status.
1285
+ * Skips agents already notified via subtree routing to avoid duplicates.
1286
+ */
1287
+ function routeStatusToTopicSubscribers(
1288
+ agentId: AgentId,
1289
+ status: StatusNotification,
1290
+ alreadyNotified: Set<AgentId>
1291
+ ): void {
1292
+ // Find all topics the emitting agent is subscribed to
1293
+ const subscriptions = eventStore.getSubscriptions(agentId);
1294
+ const topicSubscriptions = subscriptions.filter(
1295
+ (s) => s.type === "topic"
1296
+ );
1297
+
1298
+ if (topicSubscriptions.length === 0) return;
1299
+
1300
+ // Collect unique recipients across all shared topics
1301
+ const topicRecipients = new Set<AgentId>();
1302
+ for (const sub of topicSubscriptions) {
1303
+ const subscribers = eventStore.getSubscribers({
1304
+ type: "topic",
1305
+ target: sub.target,
1306
+ });
1307
+ for (const subscriberId of subscribers) {
1308
+ // Skip self and already-notified (from subtree routing)
1309
+ if (subscriberId !== agentId && !alreadyNotified.has(subscriberId)) {
1310
+ topicRecipients.add(subscriberId);
1311
+ }
1312
+ }
1090
1313
  }
1314
+
1315
+ if (topicRecipients.size === 0) return;
1316
+
1317
+ // Extract signal name from details (if tagged)
1318
+ const statusSignal = (status.details as Record<string, unknown> | undefined)?.signal as string | undefined;
1319
+
1320
+ const statusContent = JSON.stringify({
1321
+ type: "status_notification",
1322
+ ...status,
1323
+ });
1324
+
1325
+ // Deliver to each topic co-subscriber
1326
+ for (const recipientId of topicRecipients) {
1327
+ // Apply signal filter if installed
1328
+ if (signalFilter && !signalFilter(agentId, recipientId, statusSignal)) {
1329
+ continue;
1330
+ }
1331
+
1332
+ const event = eventStore.emit({
1333
+ type: "message",
1334
+ source: {
1335
+ agent_id: agentId,
1336
+ },
1337
+ target: {
1338
+ agent_id: recipientId,
1339
+ },
1340
+ payload: {
1341
+ content: statusContent,
1342
+ via: "topic",
1343
+ },
1344
+ });
1345
+
1346
+ // Wake sleeping agents on status notifications
1347
+ if (sessionChecker && wakeHandler) {
1348
+ try {
1349
+ const decision = getWakeDecisionWithHint(
1350
+ recipientId,
1351
+ { priority: "normal" as MessagePriority },
1352
+ sessionChecker
1353
+ );
1354
+ if (decision.shouldWake || decision.shouldInterrupt) {
1355
+ wakeHandler(recipientId, decision, event.id);
1356
+ }
1357
+ } catch {
1358
+ // Never fail status delivery due to wake errors
1359
+ }
1360
+ }
1361
+ }
1362
+ }
1363
+
1364
+ function setTurnRecorder(recorder: TurnRecorderCallback): void {
1365
+ turnRecorder = recorder;
1366
+ }
1367
+
1368
+ function setSignalFilter(filter: SignalFilter): void {
1369
+ signalFilter = filter;
1370
+ }
1371
+
1372
+ function setEmissionValidator(validator: EmissionValidator): void {
1373
+ emissionValidator = validator;
1091
1374
  }
1092
1375
 
1093
1376
  return {
@@ -1102,5 +1385,8 @@ export function createMessageRouter(
1102
1385
  getSubscriptions,
1103
1386
  getSubscribers,
1104
1387
  setupDefaultSubscriptions,
1388
+ setTurnRecorder,
1389
+ setSignalFilter,
1390
+ setEmissionValidator,
1105
1391
  };
1106
1392
  }
@@ -31,6 +31,11 @@ export interface RoleAgentInfo {
31
31
  export interface RoleAgentSource {
32
32
  listAgents(): RoleAgentInfo[];
33
33
  getAgent(agentId: AgentId): RoleAgentInfo | null;
34
+ /**
35
+ * Optional: Get agents subscribed to a scope/topic.
36
+ * Used when filtering by scope membership.
37
+ */
38
+ getScopeMembers?(scope: string): AgentId[];
34
39
  }
35
40
 
36
41
  // =============================================================================
@@ -90,8 +95,12 @@ export function getSubtreeIds(
90
95
  /**
91
96
  * Resolve a role channel to recipient agent IDs.
92
97
  *
98
+ * Supports two filtering mechanisms (can be combined):
99
+ * - coordinatorId: Filter to agents within a coordinator's subtree (hierarchy-based)
100
+ * - scope: Filter to agents that are members of a scope (subscription-based)
101
+ *
93
102
  * @param agentSource - Source for listing/getting agents
94
- * @param target - Role target with role name and optional coordinator scope
103
+ * @param target - Role target with role name and optional filters
95
104
  * @returns Array of agent IDs for fan-out delivery
96
105
  */
97
106
  export function resolveRoleTarget(
@@ -106,6 +115,13 @@ export function resolveRoleTarget(
106
115
  subtreeIds = getSubtreeIds(target.coordinatorId, agentSource);
107
116
  }
108
117
 
118
+ // Get scope member IDs if scope filtering is requested
119
+ let scopeMemberIds: Set<AgentId> | null = null;
120
+ if (target.scope && agentSource.getScopeMembers) {
121
+ const members = agentSource.getScopeMembers(target.scope);
122
+ scopeMemberIds = new Set(members);
123
+ }
124
+
109
125
  return agents
110
126
  .filter((agent) => {
111
127
  // Only include running agents
@@ -123,6 +139,11 @@ export function resolveRoleTarget(
123
139
  return false;
124
140
  }
125
141
 
142
+ // If scope filtering, check if agent is a scope member
143
+ if (scopeMemberIds && !scopeMemberIds.has(agent.id)) {
144
+ return false;
145
+ }
146
+
126
147
  return true;
127
148
  })
128
149
  .map((agent) => agent.id);
@@ -39,8 +39,16 @@ export type BroadcastScope = "all" | "coordinators" | "workers" | "monitors";
39
39
  export interface RoleTarget {
40
40
  /** Role name to target (e.g., "worker", "integrator", "monitor") */
41
41
  role: string;
42
- /** Optional: scope to specific coordinator's agents */
42
+ /**
43
+ * Optional: Filter to agents within a coordinator's subtree (hierarchy-based).
44
+ * Agents must be descendants of the specified coordinator.
45
+ */
43
46
  coordinatorId?: AgentId;
47
+ /**
48
+ * Optional: Filter to agents that are members of a scope (subscription-based).
49
+ * Requires EventStore scope/topic membership lookup.
50
+ */
51
+ scope?: string;
44
52
  }
45
53
 
46
54
  // Message sender identification
@@ -266,6 +274,33 @@ export class AddressRoutingError extends Error {
266
274
  }
267
275
  }
268
276
 
277
+ // =============================================================================
278
+ // Turn Recording
279
+ // =============================================================================
280
+
281
+ /**
282
+ * Information passed to a turn recorder callback.
283
+ * Only agent and task addresses produce turns.
284
+ */
285
+ export interface TurnRecordInfo {
286
+ /** Sending agent ID */
287
+ from: AgentId;
288
+ /** Receiving agent ID (resolved for task addresses) */
289
+ toAgent: AgentId;
290
+ /** Message content */
291
+ content: string;
292
+ /** Event ID of the emitted message event */
293
+ messageId: EventId;
294
+ /** Type of address that was sent to */
295
+ addressType: "agent" | "task";
296
+ }
297
+
298
+ /**
299
+ * Callback invoked when a direct message (agent or task address) is sent.
300
+ * Used to record the message as a conversation turn.
301
+ */
302
+ export type TurnRecorderCallback = (info: TurnRecordInfo) => void;
303
+
269
304
  // Re-export Address and related types for convenience
270
305
  export type { Address, SendOptions, DeliveryHint };
271
306
  export { MAPMessagePriority };
@@ -31,6 +31,9 @@ import {
31
31
  } from "../map/adapter/index.js";
32
32
  import type { Agent, AgentId } from "../store/types/index.js";
33
33
  import type { Address, SendOptions } from "../map/types.js";
34
+ import { createMailService, type MailService } from "../mail/mail-service.js";
35
+ import { createConversationMap, type ConversationMap } from "../mail/conversation-map.js";
36
+ import { createTurnRecorder } from "../mail/turn-recorder.js";
34
37
 
35
38
  // ─────────────────────────────────────────────────────────────────
36
39
  // Types
@@ -91,6 +94,12 @@ export interface CombinedServer {
91
94
 
92
95
  /** MAP adapter (for testing) */
93
96
  readonly mapAdapter?: MAPAdapter;
97
+
98
+ /** Mail service (for conversation tracking) */
99
+ readonly mailService?: MailService;
100
+
101
+ /** Conversation map (for agent-to-conversation tracking) */
102
+ readonly conversationMap?: ConversationMap;
94
103
  }
95
104
 
96
105
  // ─────────────────────────────────────────────────────────────────
@@ -179,8 +188,30 @@ export function createCombinedServer(
179
188
  disableMap = false,
180
189
  } = config;
181
190
 
182
- // Create Express app with API routes
183
- const app = createAPIApp(services, { cors });
191
+ // Set up mail service and conversation map (always created, independent of MAP)
192
+ const mailService = createMailService({ eventStore: services.eventStore });
193
+ const conversationMap = createConversationMap();
194
+
195
+ // Wire mail services into AgentManager for conversation lifecycle
196
+ if (services.agentManager.setMailServices) {
197
+ services.agentManager.setMailServices(mailService, conversationMap);
198
+ }
199
+
200
+ // Wire turn recorder into MessageRouter for automatic turn tracking
201
+ if (services.messageRouter.setTurnRecorder) {
202
+ const turnRecorder = createTurnRecorder({
203
+ mailService,
204
+ conversationMap,
205
+ eventStore: services.eventStore,
206
+ });
207
+ services.messageRouter.setTurnRecorder(turnRecorder);
208
+ }
209
+
210
+ // Create Express app with API routes (include mail services)
211
+ const app = createAPIApp(
212
+ { ...services, mailService, conversationMap },
213
+ { cors }
214
+ );
184
215
 
185
216
  // Create HTTP server with Express
186
217
  const httpServer = http.createServer(app);
@@ -203,6 +234,7 @@ export function createCombinedServer(
203
234
  const mapServices = {
204
235
  ...createMAPServices(services),
205
236
  defaultCwd,
237
+ mailService,
206
238
  };
207
239
  mapAdapter = createMAPAdapter(
208
240
  { name: "macro-agent", version: "1.0.0" },
@@ -326,5 +358,7 @@ export function createCombinedServer(
326
358
  httpServer,
327
359
  app,
328
360
  mapAdapter,
361
+ mailService,
362
+ conversationMap,
329
363
  };
330
364
  }