macro-agent 0.1.0 → 0.1.2

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 (660) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/issues.jsonl +28 -0
  3. package/.sudocode/specs.jsonl +8 -0
  4. package/CLAUDE.md +25 -17
  5. package/README.md +11 -29
  6. package/dist/acp/macro-agent.d.ts +15 -0
  7. package/dist/acp/macro-agent.d.ts.map +1 -1
  8. package/dist/acp/macro-agent.js +131 -35
  9. package/dist/acp/macro-agent.js.map +1 -1
  10. package/dist/acp/types.d.ts +32 -1
  11. package/dist/acp/types.d.ts.map +1 -1
  12. package/dist/acp/types.js.map +1 -1
  13. package/dist/agent/agent-manager.d.ts +65 -1
  14. package/dist/agent/agent-manager.d.ts.map +1 -1
  15. package/dist/agent/agent-manager.js +544 -200
  16. package/dist/agent/agent-manager.js.map +1 -1
  17. package/dist/agent/types.d.ts +8 -1
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/agent/types.js.map +1 -1
  20. package/dist/api/server.d.ts +8 -1
  21. package/dist/api/server.d.ts.map +1 -1
  22. package/dist/api/server.js +136 -8
  23. package/dist/api/server.js.map +1 -1
  24. package/dist/api/types.d.ts +1 -1
  25. package/dist/api/types.d.ts.map +1 -1
  26. package/dist/auth/index.d.ts +2 -0
  27. package/dist/auth/index.d.ts.map +1 -0
  28. package/dist/auth/index.js +2 -0
  29. package/dist/auth/index.js.map +1 -0
  30. package/dist/auth/token.d.ts +41 -0
  31. package/dist/auth/token.d.ts.map +1 -0
  32. package/dist/auth/token.js +73 -0
  33. package/dist/auth/token.js.map +1 -0
  34. package/dist/cli/acp.d.ts +2 -23
  35. package/dist/cli/acp.d.ts.map +1 -1
  36. package/dist/cli/acp.js +197 -61
  37. package/dist/cli/acp.js.map +1 -1
  38. package/dist/cli/index.js +152 -16
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/mcp.d.ts +6 -0
  41. package/dist/cli/mcp.d.ts.map +1 -1
  42. package/dist/cli/mcp.js +279 -173
  43. package/dist/cli/mcp.js.map +1 -1
  44. package/dist/cli/parse-args.d.ts +20 -0
  45. package/dist/cli/parse-args.d.ts.map +1 -0
  46. package/dist/cli/parse-args.js +43 -0
  47. package/dist/cli/parse-args.js.map +1 -0
  48. package/dist/cli/stable-instance-id.d.ts +8 -0
  49. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  50. package/dist/cli/stable-instance-id.js +14 -0
  51. package/dist/cli/stable-instance-id.js.map +1 -0
  52. package/dist/config/project-config.d.ts +85 -7
  53. package/dist/config/project-config.d.ts.map +1 -1
  54. package/dist/config/project-config.js +133 -20
  55. package/dist/config/project-config.js.map +1 -1
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/lifecycle/handlers/index.d.ts +7 -3
  61. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  62. package/dist/lifecycle/handlers/index.js +25 -8
  63. package/dist/lifecycle/handlers/index.js.map +1 -1
  64. package/dist/lifecycle/types.d.ts +2 -0
  65. package/dist/lifecycle/types.d.ts.map +1 -1
  66. package/dist/lifecycle/types.js.map +1 -1
  67. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  68. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  69. package/dist/map/adapter/acp-over-map.js +384 -23
  70. package/dist/map/adapter/acp-over-map.js.map +1 -1
  71. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  72. package/dist/map/adapter/connection-manager.js +3 -0
  73. package/dist/map/adapter/connection-manager.js.map +1 -1
  74. package/dist/map/adapter/event-log.d.ts +87 -0
  75. package/dist/map/adapter/event-log.d.ts.map +1 -0
  76. package/dist/map/adapter/event-log.js +122 -0
  77. package/dist/map/adapter/event-log.js.map +1 -0
  78. package/dist/map/adapter/event-translator.js +6 -6
  79. package/dist/map/adapter/event-translator.js.map +1 -1
  80. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  81. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  82. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  83. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  84. package/dist/map/adapter/extensions/index.d.ts +13 -1
  85. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  86. package/dist/map/adapter/extensions/index.js +61 -0
  87. package/dist/map/adapter/extensions/index.js.map +1 -1
  88. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  89. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  91. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  92. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  93. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  94. package/dist/map/adapter/extensions/rename.js +49 -0
  95. package/dist/map/adapter/extensions/rename.js.map +1 -0
  96. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  97. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/streams.js +515 -0
  99. package/dist/map/adapter/extensions/streams.js.map +1 -0
  100. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  101. package/dist/map/adapter/extensions/task.js +10 -0
  102. package/dist/map/adapter/extensions/task.js.map +1 -1
  103. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  104. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  105. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  106. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  107. package/dist/map/adapter/index.d.ts +2 -1
  108. package/dist/map/adapter/index.d.ts.map +1 -1
  109. package/dist/map/adapter/index.js +10 -2
  110. package/dist/map/adapter/index.js.map +1 -1
  111. package/dist/map/adapter/interface.d.ts +2 -0
  112. package/dist/map/adapter/interface.d.ts.map +1 -1
  113. package/dist/map/adapter/map-adapter.d.ts +3 -0
  114. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  115. package/dist/map/adapter/map-adapter.js +258 -35
  116. package/dist/map/adapter/map-adapter.js.map +1 -1
  117. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  118. package/dist/map/adapter/subscription-manager.js +5 -1
  119. package/dist/map/adapter/subscription-manager.js.map +1 -1
  120. package/dist/map/adapter/types.d.ts +3 -1
  121. package/dist/map/adapter/types.d.ts.map +1 -1
  122. package/dist/mcp/map-client.d.ts +39 -0
  123. package/dist/mcp/map-client.d.ts.map +1 -0
  124. package/dist/mcp/map-client.js +129 -0
  125. package/dist/mcp/map-client.js.map +1 -0
  126. package/dist/mcp/mcp-server.d.ts +16 -0
  127. package/dist/mcp/mcp-server.d.ts.map +1 -1
  128. package/dist/mcp/mcp-server.js +125 -88
  129. package/dist/mcp/mcp-server.js.map +1 -1
  130. package/dist/mcp/tools/done.d.ts.map +1 -1
  131. package/dist/mcp/tools/done.js +18 -0
  132. package/dist/mcp/tools/done.js.map +1 -1
  133. package/dist/mcp/types.d.ts +9 -1
  134. package/dist/mcp/types.d.ts.map +1 -1
  135. package/dist/mcp/types.js.map +1 -1
  136. package/dist/metrics/metrics.js +1 -1
  137. package/dist/metrics/metrics.js.map +1 -1
  138. package/dist/roles/builtin/coordinator.d.ts.map +1 -1
  139. package/dist/roles/builtin/coordinator.js +2 -1
  140. package/dist/roles/builtin/coordinator.js.map +1 -1
  141. package/dist/roles/builtin/integrator.d.ts.map +1 -1
  142. package/dist/roles/builtin/integrator.js +2 -1
  143. package/dist/roles/builtin/integrator.js.map +1 -1
  144. package/dist/roles/builtin/worker.d.ts.map +1 -1
  145. package/dist/roles/builtin/worker.js +3 -1
  146. package/dist/roles/builtin/worker.js.map +1 -1
  147. package/dist/roles/capabilities.d.ts +9 -1
  148. package/dist/roles/capabilities.d.ts.map +1 -1
  149. package/dist/roles/capabilities.js +27 -7
  150. package/dist/roles/capabilities.js.map +1 -1
  151. package/dist/roles/config-loader.d.ts +6 -6
  152. package/dist/roles/config-loader.d.ts.map +1 -1
  153. package/dist/roles/config-loader.js +8 -7
  154. package/dist/roles/config-loader.js.map +1 -1
  155. package/dist/roles/registry.d.ts +2 -2
  156. package/dist/roles/registry.js +2 -2
  157. package/dist/roles/types.d.ts +3 -1
  158. package/dist/roles/types.d.ts.map +1 -1
  159. package/dist/server/combined-server.d.ts +28 -1
  160. package/dist/server/combined-server.d.ts.map +1 -1
  161. package/dist/server/combined-server.js +111 -8
  162. package/dist/server/combined-server.js.map +1 -1
  163. package/dist/store/event-store.d.ts +2 -1
  164. package/dist/store/event-store.d.ts.map +1 -1
  165. package/dist/store/event-store.js +80 -24
  166. package/dist/store/event-store.js.map +1 -1
  167. package/dist/store/instance.d.ts +1 -1
  168. package/dist/store/instance.d.ts.map +1 -1
  169. package/dist/store/instance.js +2 -2
  170. package/dist/store/instance.js.map +1 -1
  171. package/dist/store/types/agents.d.ts +23 -0
  172. package/dist/store/types/agents.d.ts.map +1 -1
  173. package/dist/store/types/events.d.ts +1 -1
  174. package/dist/store/types/events.d.ts.map +1 -1
  175. package/dist/task/backend/index.d.ts +47 -29
  176. package/dist/task/backend/index.d.ts.map +1 -1
  177. package/dist/task/backend/index.js +109 -71
  178. package/dist/task/backend/index.js.map +1 -1
  179. package/dist/task/backend/memory.d.ts +1 -0
  180. package/dist/task/backend/memory.d.ts.map +1 -1
  181. package/dist/task/backend/memory.js +3 -0
  182. package/dist/task/backend/memory.js.map +1 -1
  183. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  184. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  185. package/dist/task/backend/opentasks/backend.js +1023 -0
  186. package/dist/task/backend/opentasks/backend.js.map +1 -0
  187. package/dist/task/backend/opentasks/client.d.ts +337 -0
  188. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  189. package/dist/task/backend/opentasks/client.js +225 -0
  190. package/dist/task/backend/opentasks/client.js.map +1 -0
  191. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  192. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  193. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  194. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  195. package/dist/task/backend/opentasks/index.d.ts +21 -0
  196. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  197. package/dist/task/backend/opentasks/index.js +21 -0
  198. package/dist/task/backend/opentasks/index.js.map +1 -0
  199. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  200. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  201. package/dist/task/backend/opentasks/mapping.js +77 -0
  202. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  203. package/dist/task/backend/types.d.ts +33 -53
  204. package/dist/task/backend/types.d.ts.map +1 -1
  205. package/dist/task/backend/types.js +7 -11
  206. package/dist/task/backend/types.js.map +1 -1
  207. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  208. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  209. package/dist/task/backend/unified-tool-provider.js +623 -0
  210. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  211. package/dist/teams/index.d.ts +3 -1
  212. package/dist/teams/index.d.ts.map +1 -1
  213. package/dist/teams/index.js +2 -0
  214. package/dist/teams/index.js.map +1 -1
  215. package/dist/teams/seed-defaults.d.ts +20 -0
  216. package/dist/teams/seed-defaults.d.ts.map +1 -0
  217. package/dist/teams/seed-defaults.js +71 -0
  218. package/dist/teams/seed-defaults.js.map +1 -0
  219. package/dist/teams/team-loader.d.ts +7 -3
  220. package/dist/teams/team-loader.d.ts.map +1 -1
  221. package/dist/teams/team-loader.js +156 -164
  222. package/dist/teams/team-loader.js.map +1 -1
  223. package/dist/teams/team-manager.d.ts +112 -0
  224. package/dist/teams/team-manager.d.ts.map +1 -0
  225. package/dist/teams/team-manager.js +305 -0
  226. package/dist/teams/team-manager.js.map +1 -0
  227. package/dist/teams/team-runtime.d.ts +125 -19
  228. package/dist/teams/team-runtime.d.ts.map +1 -1
  229. package/dist/teams/team-runtime.js +529 -119
  230. package/dist/teams/team-runtime.js.map +1 -1
  231. package/dist/teams/types.d.ts +41 -151
  232. package/dist/teams/types.d.ts.map +1 -1
  233. package/dist/teams/types.js +2 -3
  234. package/dist/teams/types.js.map +1 -1
  235. package/docs/architecture.md +7 -6
  236. package/docs/configuration.md +26 -62
  237. package/docs/implementation-details.md +5 -5
  238. package/docs/implementation-summary.md +17 -17
  239. package/docs/plan-self-driving-support.md +4 -4
  240. package/docs/spec-self-driving-support.md +10 -10
  241. package/docs/team-templates.md +2 -2
  242. package/docs/teams.md +76 -3
  243. package/docs/troubleshooting.md +10 -11
  244. package/package.json +7 -4
  245. package/references/minimem/.claude/settings.json +7 -0
  246. package/references/minimem/.sudocode/issues.jsonl +18 -0
  247. package/references/minimem/.sudocode/specs.jsonl +1 -0
  248. package/references/minimem/CLAUDE.md +310 -0
  249. package/references/minimem/README.md +562 -0
  250. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
  251. package/references/minimem/claude-plugin/.mcp.json +7 -0
  252. package/references/minimem/claude-plugin/README.md +158 -0
  253. package/references/minimem/claude-plugin/commands/recall.md +47 -0
  254. package/references/minimem/claude-plugin/commands/remember.md +41 -0
  255. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
  256. package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
  257. package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
  258. package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
  259. package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
  260. package/references/minimem/media/banner.png +0 -0
  261. package/references/minimem/package-lock.json +5373 -0
  262. package/references/minimem/package.json +72 -0
  263. package/references/minimem/scripts/postbuild.js +35 -0
  264. package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
  265. package/references/minimem/src/__tests__/errors.test.ts +265 -0
  266. package/references/minimem/src/__tests__/helpers.ts +199 -0
  267. package/references/minimem/src/__tests__/internal.test.ts +407 -0
  268. package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
  269. package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
  270. package/references/minimem/src/__tests__/session.test.ts +190 -0
  271. package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
  272. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
  273. package/references/minimem/src/cli/commands/append.ts +76 -0
  274. package/references/minimem/src/cli/commands/config.ts +262 -0
  275. package/references/minimem/src/cli/commands/conflicts.ts +413 -0
  276. package/references/minimem/src/cli/commands/daemon.ts +169 -0
  277. package/references/minimem/src/cli/commands/index.ts +12 -0
  278. package/references/minimem/src/cli/commands/init.ts +88 -0
  279. package/references/minimem/src/cli/commands/mcp.ts +177 -0
  280. package/references/minimem/src/cli/commands/push-pull.ts +213 -0
  281. package/references/minimem/src/cli/commands/search.ts +158 -0
  282. package/references/minimem/src/cli/commands/status.ts +84 -0
  283. package/references/minimem/src/cli/commands/sync-init.ts +290 -0
  284. package/references/minimem/src/cli/commands/sync.ts +70 -0
  285. package/references/minimem/src/cli/commands/upsert.ts +197 -0
  286. package/references/minimem/src/cli/config.ts +584 -0
  287. package/references/minimem/src/cli/index.ts +264 -0
  288. package/references/minimem/src/cli/shared.ts +161 -0
  289. package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
  290. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
  291. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
  292. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
  293. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
  294. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
  295. package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
  296. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
  297. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
  298. package/references/minimem/src/cli/sync/central.ts +292 -0
  299. package/references/minimem/src/cli/sync/conflicts.ts +204 -0
  300. package/references/minimem/src/cli/sync/daemon.ts +407 -0
  301. package/references/minimem/src/cli/sync/detection.ts +138 -0
  302. package/references/minimem/src/cli/sync/index.ts +107 -0
  303. package/references/minimem/src/cli/sync/operations.ts +373 -0
  304. package/references/minimem/src/cli/sync/registry.ts +279 -0
  305. package/references/minimem/src/cli/sync/state.ts +355 -0
  306. package/references/minimem/src/cli/sync/validation.ts +206 -0
  307. package/references/minimem/src/cli/sync/watcher.ts +234 -0
  308. package/references/minimem/src/cli/version.ts +34 -0
  309. package/references/minimem/src/core/index.ts +9 -0
  310. package/references/minimem/src/core/indexer.ts +628 -0
  311. package/references/minimem/src/core/searcher.ts +221 -0
  312. package/references/minimem/src/db/schema.ts +183 -0
  313. package/references/minimem/src/db/sqlite-vec.ts +24 -0
  314. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
  315. package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
  316. package/references/minimem/src/embeddings/batch-openai.ts +409 -0
  317. package/references/minimem/src/embeddings/embeddings.ts +434 -0
  318. package/references/minimem/src/index.ts +109 -0
  319. package/references/minimem/src/internal.ts +299 -0
  320. package/references/minimem/src/minimem.ts +1276 -0
  321. package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
  322. package/references/minimem/src/search/graph.ts +234 -0
  323. package/references/minimem/src/search/hybrid.ts +151 -0
  324. package/references/minimem/src/search/search.ts +256 -0
  325. package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
  326. package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
  327. package/references/minimem/src/server/mcp.ts +326 -0
  328. package/references/minimem/src/server/tools.ts +720 -0
  329. package/references/minimem/src/session.ts +460 -0
  330. package/references/minimem/tsconfig.json +19 -0
  331. package/references/minimem/tsup.config.ts +26 -0
  332. package/references/minimem/vitest.config.ts +24 -0
  333. package/references/openteams/.claude/settings.json +6 -0
  334. package/references/openteams/README.md +1 -0
  335. package/references/openteams/SKILL.md +341 -0
  336. package/references/openteams/design.md +411 -0
  337. package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
  338. package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
  339. package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
  340. package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
  341. package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
  342. package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
  343. package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
  344. package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
  345. package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
  346. package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
  347. package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
  348. package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
  349. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
  350. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
  351. package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
  352. package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
  353. package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
  354. package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
  355. package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
  356. package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
  357. package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
  358. package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
  359. package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
  360. package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
  361. package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
  362. package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
  363. package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
  364. package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
  365. package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
  366. package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
  367. package/references/openteams/examples/bmad-method/team.yaml +161 -0
  368. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
  369. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
  370. package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
  371. package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
  372. package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
  373. package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
  374. package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
  375. package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
  376. package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
  377. package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
  378. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
  379. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
  380. package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
  381. package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
  382. package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
  383. package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
  384. package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
  385. package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
  386. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
  387. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
  388. package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
  389. package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
  390. package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
  391. package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
  392. package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
  393. package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
  394. package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
  395. package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
  396. package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
  397. package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
  398. package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
  399. package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
  400. package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
  401. package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
  402. package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
  403. package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
  404. package/references/openteams/examples/get-shit-done/team.yaml +154 -0
  405. package/references/openteams/package-lock.json +2181 -0
  406. package/references/openteams/package.json +48 -0
  407. package/references/openteams/schema/role.schema.json +125 -0
  408. package/references/openteams/schema/team.schema.json +284 -0
  409. package/references/openteams/src/cli/agent.ts +104 -0
  410. package/references/openteams/src/cli/cli.test.ts +381 -0
  411. package/references/openteams/src/cli/generate.ts +220 -0
  412. package/references/openteams/src/cli/message.ts +241 -0
  413. package/references/openteams/src/cli/task.ts +154 -0
  414. package/references/openteams/src/cli/team.ts +104 -0
  415. package/references/openteams/src/cli/template.ts +207 -0
  416. package/references/openteams/src/cli.ts +45 -0
  417. package/references/openteams/src/db/database.test.ts +185 -0
  418. package/references/openteams/src/db/database.ts +240 -0
  419. package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
  420. package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
  421. package/references/openteams/src/generators/package-generator.test.ts +129 -0
  422. package/references/openteams/src/generators/package-generator.ts +102 -0
  423. package/references/openteams/src/generators/skill-generator.test.ts +246 -0
  424. package/references/openteams/src/generators/skill-generator.ts +374 -0
  425. package/references/openteams/src/index.ts +104 -0
  426. package/references/openteams/src/services/agent-service.test.ts +158 -0
  427. package/references/openteams/src/services/agent-service.ts +84 -0
  428. package/references/openteams/src/services/communication-service.test.ts +455 -0
  429. package/references/openteams/src/services/communication-service.ts +371 -0
  430. package/references/openteams/src/services/message-service.test.ts +342 -0
  431. package/references/openteams/src/services/message-service.ts +203 -0
  432. package/references/openteams/src/services/task-service.test.ts +434 -0
  433. package/references/openteams/src/services/task-service.ts +239 -0
  434. package/references/openteams/src/services/team-service.test.ts +181 -0
  435. package/references/openteams/src/services/team-service.ts +139 -0
  436. package/references/openteams/src/services/template-service.test.ts +306 -0
  437. package/references/openteams/src/services/template-service.ts +182 -0
  438. package/references/openteams/src/spawner/acp-factory.ts +96 -0
  439. package/references/openteams/src/spawner/interface.ts +31 -0
  440. package/references/openteams/src/spawner/mock.test.ts +93 -0
  441. package/references/openteams/src/spawner/mock.ts +59 -0
  442. package/references/openteams/src/template/loader.test.ts +1319 -0
  443. package/references/openteams/src/template/loader.ts +698 -0
  444. package/references/openteams/src/template/types.ts +200 -0
  445. package/references/openteams/src/types.ts +205 -0
  446. package/references/openteams/tsconfig.json +18 -0
  447. package/references/openteams/vitest.config.ts +9 -0
  448. package/references/skill-tree/.claude/settings.json +6 -0
  449. package/references/skill-tree/.sudocode/issues.jsonl +11 -0
  450. package/references/skill-tree/.sudocode/specs.jsonl +1 -0
  451. package/references/skill-tree/CLAUDE.md +150 -0
  452. package/references/skill-tree/README.md +324 -0
  453. package/references/skill-tree/docs/GAPS_v1.md +221 -0
  454. package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
  455. package/references/skill-tree/docs/TODOS.md +91 -0
  456. package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
  457. package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
  458. package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
  459. package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
  460. package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
  461. package/references/skill-tree/docs/scraper/README.md +170 -0
  462. package/references/skill-tree/examples/basic-usage.ts +190 -0
  463. package/references/skill-tree/package-lock.json +1509 -0
  464. package/references/skill-tree/package.json +66 -0
  465. package/references/skill-tree/scraper/README.md +123 -0
  466. package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
  467. package/references/skill-tree/scraper/docs/PLAN.md +336 -0
  468. package/references/skill-tree/scraper/drizzle.config.ts +10 -0
  469. package/references/skill-tree/scraper/package-lock.json +6329 -0
  470. package/references/skill-tree/scraper/package.json +68 -0
  471. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
  472. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
  473. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
  474. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
  475. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
  476. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
  477. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
  478. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
  479. package/references/skill-tree/scraper/tsup.config.ts +14 -0
  480. package/references/skill-tree/scraper/vitest.config.ts +17 -0
  481. package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
  482. package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
  483. package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
  484. package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
  485. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
  486. package/references/skill-tree/test/run-all.ts +106 -0
  487. package/references/skill-tree/test/utils.ts +128 -0
  488. package/references/skill-tree/vitest.config.ts +16 -0
  489. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  490. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  491. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  492. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  493. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  494. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  495. package/src/acp/__tests__/integration.test.ts +56 -31
  496. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  497. package/src/acp/macro-agent.ts +170 -36
  498. package/src/acp/types.ts +46 -1
  499. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  500. package/src/agent/agent-manager.ts +809 -285
  501. package/src/agent/types.ts +12 -1
  502. package/src/api/__tests__/server.test.ts +203 -4
  503. package/src/api/server.ts +169 -10
  504. package/src/api/types.ts +3 -1
  505. package/src/auth/__tests__/token.test.ts +100 -0
  506. package/src/auth/index.ts +1 -0
  507. package/src/auth/token.ts +82 -0
  508. package/src/cli/__tests__/acp.test.ts +1 -1
  509. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  510. package/src/cli/acp.ts +197 -72
  511. package/src/cli/index.ts +125 -15
  512. package/src/cli/mcp.ts +315 -197
  513. package/src/cli/parse-args.ts +54 -0
  514. package/src/cli/stable-instance-id.ts +14 -0
  515. package/src/config/project-config.ts +214 -27
  516. package/src/index.ts +3 -0
  517. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  518. package/src/lifecycle/__tests__/handlers.test.ts +53 -0
  519. package/src/lifecycle/handlers/index.ts +25 -8
  520. package/src/lifecycle/types.ts +3 -0
  521. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  522. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  523. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  524. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  525. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  526. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  527. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  528. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  529. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  530. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  531. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  532. package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
  533. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  534. package/src/map/adapter/acp-over-map.ts +678 -66
  535. package/src/map/adapter/connection-manager.ts +3 -0
  536. package/src/map/adapter/event-log.ts +208 -0
  537. package/src/map/adapter/event-translator.ts +6 -6
  538. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  539. package/src/map/adapter/extensions/index.ts +96 -0
  540. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  541. package/src/map/adapter/extensions/streams.ts +839 -0
  542. package/src/map/adapter/extensions/task.ts +11 -0
  543. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  544. package/src/map/adapter/index.ts +33 -0
  545. package/src/map/adapter/interface.ts +2 -0
  546. package/src/map/adapter/map-adapter.ts +312 -47
  547. package/src/map/adapter/subscription-manager.ts +5 -1
  548. package/src/map/adapter/types.ts +10 -1
  549. package/src/mcp/__tests__/map-client.test.ts +386 -0
  550. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  551. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  552. package/src/mcp/map-client.ts +177 -0
  553. package/src/mcp/mcp-server.ts +205 -103
  554. package/src/mcp/tools/done.ts +19 -0
  555. package/src/mcp/types.ts +6 -1
  556. package/src/metrics/metrics.ts +1 -1
  557. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  558. package/src/roles/__tests__/config-loader.test.ts +7 -7
  559. package/src/roles/builtin/coordinator.ts +2 -0
  560. package/src/roles/builtin/integrator.ts +2 -0
  561. package/src/roles/builtin/worker.ts +3 -0
  562. package/src/roles/capabilities.ts +28 -7
  563. package/src/roles/config-loader.ts +8 -7
  564. package/src/roles/registry.ts +2 -2
  565. package/src/roles/types.ts +7 -0
  566. package/src/server/__tests__/combined-server.test.ts +94 -21
  567. package/src/server/combined-server.ts +203 -33
  568. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  569. package/src/store/__tests__/event-store-oob.test.ts +109 -0
  570. package/src/store/__tests__/event-store.test.ts +196 -1
  571. package/src/store/__tests__/instance.test.ts +3 -3
  572. package/src/store/event-store.ts +92 -23
  573. package/src/store/instance.ts +2 -2
  574. package/src/store/types/agents.ts +20 -0
  575. package/src/store/types/events.ts +1 -1
  576. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  577. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  578. package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
  579. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  580. package/src/task/backend/index.ts +156 -106
  581. package/src/task/backend/memory.ts +4 -0
  582. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  583. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  584. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  585. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  586. package/src/task/backend/opentasks/backend.ts +1323 -0
  587. package/src/task/backend/opentasks/client.ts +652 -0
  588. package/src/task/backend/opentasks/daemon-manager.ts +256 -0
  589. package/src/task/backend/opentasks/index.ts +69 -0
  590. package/src/task/backend/opentasks/mapping.ts +94 -0
  591. package/src/task/backend/types.ts +42 -66
  592. package/src/task/backend/unified-tool-provider.ts +779 -0
  593. package/src/teams/CLAUDE.md +180 -0
  594. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  595. package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
  596. package/src/teams/__tests__/team-manager.test.ts +814 -0
  597. package/src/teams/__tests__/team-system.test.ts +1291 -8
  598. package/src/teams/index.ts +21 -3
  599. package/src/teams/seed-defaults.ts +79 -0
  600. package/src/teams/team-loader.ts +202 -236
  601. package/src/teams/team-manager.ts +387 -0
  602. package/src/teams/team-runtime.ts +592 -121
  603. package/src/teams/types.ts +99 -200
  604. package/test_fixtures/README.md +2 -3
  605. package/test_fixtures/fixtures/index.ts +0 -3
  606. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  607. package/test_fixtures/fixtures/repos/index.ts +1 -3
  608. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  609. package/test_fixtures/fixtures/repos/types.ts +0 -11
  610. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  611. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  612. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  613. package/vitest.config.ts +1 -1
  614. package/vitest.e2e.config.ts +1 -1
  615. package/vitest.setup.ts +1 -30
  616. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  617. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  618. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  619. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  620. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  621. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  622. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  623. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  624. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  625. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  626. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  627. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  628. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  629. package/.macro-agent/teams/structured/team.yaml +0 -89
  630. package/docs/sudocode-integration.md +0 -383
  631. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  632. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  633. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  634. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  635. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  636. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  637. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  638. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  639. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  640. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  641. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  642. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  643. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  644. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  645. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  646. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  647. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  648. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  649. package/src/task/backend/sudocode/backend.ts +0 -1237
  650. package/src/task/backend/sudocode/client.ts +0 -515
  651. package/src/task/backend/sudocode/index.ts +0 -120
  652. package/src/task/backend/sudocode/mapping.ts +0 -93
  653. package/src/task/backend/sudocode/server-client.ts +0 -522
  654. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  655. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  656. package/src/task/backend/sudocode/tools.ts +0 -896
  657. package/src/task/backend/tool-provider.ts +0 -506
  658. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  659. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  660. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -0,0 +1,524 @@
1
+ /**
2
+ * E2E Tests for UnifiedTaskToolProvider with real OpenTasks daemon
3
+ *
4
+ * Starts a real opentasks daemon, connects via IPCOpenTasksClient,
5
+ * creates an OpenTasksTaskBackend, and exercises all 7 tools end-to-end.
6
+ *
7
+ * Requires: opentasks@0.0.3+ installed
8
+ *
9
+ * @module task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test
10
+ */
11
+
12
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
13
+ import * as fs from "fs";
14
+ import * as path from "path";
15
+ import * as os from "os";
16
+ import { createEventStore, type EventStore } from "../../../../store/event-store.js";
17
+ import { OpenTasksTaskBackend } from "../../opentasks/backend.js";
18
+ import { IPCOpenTasksClient } from "../../opentasks/client.js";
19
+ import {
20
+ UnifiedTaskToolProvider,
21
+ type GetToolContext,
22
+ } from "../../unified-tool-provider.js";
23
+ import type { MCPToolDefinition } from "../../types.js";
24
+
25
+ // =============================================================================
26
+ // Helpers
27
+ // =============================================================================
28
+
29
+ const TEST_AGENT_ID = "agent_e2e_test";
30
+ const getContext: GetToolContext = () => ({ agent_id: TEST_AGENT_ID });
31
+
32
+ function findTool(
33
+ tools: MCPToolDefinition[],
34
+ name: string
35
+ ): MCPToolDefinition {
36
+ const tool = tools.find((t) => t.name === name);
37
+ if (!tool) throw new Error(`Tool not found: ${name}`);
38
+ return tool;
39
+ }
40
+
41
+ /**
42
+ * Wait for a condition with timeout
43
+ */
44
+ async function waitFor(
45
+ condition: () => Promise<boolean> | boolean,
46
+ timeoutMs = 5000,
47
+ intervalMs = 100
48
+ ): Promise<void> {
49
+ const start = Date.now();
50
+ while (Date.now() - start < timeoutMs) {
51
+ if (await condition()) return;
52
+ await new Promise((r) => setTimeout(r, intervalMs));
53
+ }
54
+ throw new Error(`Timed out after ${timeoutMs}ms`);
55
+ }
56
+
57
+ // =============================================================================
58
+ // Test Suite
59
+ // =============================================================================
60
+
61
+ describe("UnifiedTaskToolProvider E2E with real OpenTasks", () => {
62
+ let tempDir: string;
63
+ let locationPath: string;
64
+ let daemon: any;
65
+ let socketPath: string;
66
+ let eventStore: EventStore;
67
+ let otClient: IPCOpenTasksClient;
68
+ let backend: OpenTasksTaskBackend;
69
+ let provider: UnifiedTaskToolProvider;
70
+
71
+ beforeAll(async () => {
72
+ // Create temp directory for opentasks data
73
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "macro-e2e-opentasks-"));
74
+ locationPath = path.join(tempDir, ".opentasks");
75
+ fs.mkdirSync(locationPath, { recursive: true });
76
+
77
+ const registryPath = path.join(tempDir, "registry.json");
78
+
79
+ // Start a real opentasks daemon
80
+ const opentasks = await import("opentasks");
81
+
82
+ daemon = await opentasks.createDaemonWithStore({
83
+ locationPath,
84
+ version: "0.0.3",
85
+ registryPath,
86
+ shutdownTimeoutMs: 2000,
87
+ });
88
+
89
+ await daemon.start();
90
+ socketPath = daemon.socketPath;
91
+
92
+ // Create macro-agent event store (in-memory)
93
+ eventStore = await createEventStore({ inMemory: true });
94
+
95
+ // Create IPCOpenTasksClient pointing at the real daemon
96
+ otClient = new IPCOpenTasksClient({
97
+ socketPath,
98
+ autoConnect: true,
99
+ timeout: 10000,
100
+ });
101
+ await otClient.connect();
102
+
103
+ // Create OpenTasks backend
104
+ backend = new OpenTasksTaskBackend(eventStore, otClient, {
105
+ socketPath,
106
+ syncStatus: true,
107
+ sourceLabel: "e2e-test",
108
+ });
109
+
110
+ // Create unified tool provider with all 7 tools
111
+ provider = new UnifiedTaskToolProvider(backend, getContext, otClient);
112
+ }, 30000);
113
+
114
+ afterAll(async () => {
115
+ // Teardown in reverse order
116
+ try {
117
+ otClient?.disconnect();
118
+ } catch { /* ignore */ }
119
+ try {
120
+ await daemon?.stop();
121
+ } catch { /* ignore */ }
122
+ try {
123
+ await eventStore?.close();
124
+ } catch { /* ignore */ }
125
+ try {
126
+ if (tempDir) fs.rmSync(tempDir, { recursive: true, force: true });
127
+ } catch { /* ignore */ }
128
+ }, 15000);
129
+
130
+ // ─────────────────────────────────────────────────────────────────────────────
131
+ // Tool Exposure
132
+ // ─────────────────────────────────────────────────────────────────────────────
133
+
134
+ it("should expose all 8 tools with OpenTasks client", () => {
135
+ const tools = provider.getTools();
136
+ expect(tools).toHaveLength(8);
137
+ expect(tools.map((t) => t.name)).toEqual([
138
+ "create_task",
139
+ "get_task",
140
+ "list_tasks",
141
+ "assign_task",
142
+ "task",
143
+ "link",
144
+ "annotate",
145
+ "list_providers",
146
+ ]);
147
+ });
148
+
149
+ // ─────────────────────────────────────────────────────────────────────────────
150
+ // Core CRUD Tools (real backend → real daemon)
151
+ // ─────────────────────────────────────────────────────────────────────────────
152
+
153
+ describe("create_task → get_task roundtrip", () => {
154
+ let createdTaskId: string;
155
+
156
+ it("should create a task via create_task tool", async () => {
157
+ const tool = findTool(provider.getTools(), "create_task");
158
+ const result = (await tool.handler({
159
+ description: "E2E test task",
160
+ })) as { task_id: string; status: string; external_id?: string };
161
+
162
+ expect(result.task_id).toMatch(/^task_/);
163
+ expect(result.status).toBe("pending");
164
+ createdTaskId = result.task_id;
165
+ });
166
+
167
+ it("should retrieve the task via get_task tool", async () => {
168
+ const tool = findTool(provider.getTools(), "get_task");
169
+ const result = (await tool.handler({
170
+ task_id: createdTaskId,
171
+ })) as { id: string; description: string; status: string };
172
+
173
+ expect(result.id).toBe(createdTaskId);
174
+ expect(result.description).toBe("E2E test task");
175
+ expect(result.status).toBe("pending");
176
+ });
177
+ });
178
+
179
+ describe("list_tasks", () => {
180
+ it("should list tasks with filters", async () => {
181
+ const createTool = findTool(provider.getTools(), "create_task");
182
+ const listTool = findTool(provider.getTools(), "list_tasks");
183
+
184
+ // Create a couple tasks
185
+ await createTool.handler({ description: "List test A" });
186
+ await createTool.handler({ description: "List test B" });
187
+
188
+ const result = (await listTool.handler({})) as {
189
+ tasks: Array<{ id: string; description: string }>;
190
+ total: number;
191
+ };
192
+
193
+ expect(result.total).toBeGreaterThanOrEqual(2);
194
+ expect(result.tasks.some((t) => t.description === "List test A")).toBe(true);
195
+ expect(result.tasks.some((t) => t.description === "List test B")).toBe(true);
196
+ });
197
+ });
198
+
199
+ describe("assign_task", () => {
200
+ it("should assign a task to an agent", async () => {
201
+ const createTool = findTool(provider.getTools(), "create_task");
202
+ const assignTool = findTool(provider.getTools(), "assign_task");
203
+ const getTool = findTool(provider.getTools(), "get_task");
204
+
205
+ // Create
206
+ const created = (await createTool.handler({
207
+ description: "Assign test task",
208
+ })) as { task_id: string };
209
+
210
+ // Assign
211
+ const assignResult = (await assignTool.handler({
212
+ task_id: created.task_id,
213
+ agent_id: "agent_worker_1",
214
+ })) as { assigned_agent: string; assigned: boolean };
215
+
216
+ expect(assignResult.assigned_agent).toBe("agent_worker_1");
217
+ expect(assignResult.assigned).toBe(true);
218
+
219
+ // Verify
220
+ const task = (await getTool.handler({
221
+ task_id: created.task_id,
222
+ })) as { assigned_agent: string; status: string };
223
+
224
+ expect(task.assigned_agent).toBe("agent_worker_1");
225
+ expect(task.status).toBe("assigned");
226
+ });
227
+ });
228
+
229
+ // ─────────────────────────────────────────────────────────────────────────────
230
+ // OpenTasks Graph Tools (real daemon)
231
+ // ─────────────────────────────────────────────────────────────────────────────
232
+
233
+ describe("task tool", () => {
234
+ it("should transition a task through its lifecycle and sync to EventStore", async () => {
235
+ const createTool = findTool(provider.getTools(), "create_task");
236
+ const taskTool = findTool(provider.getTools(), "task");
237
+ const getTool = findTool(provider.getTools(), "get_task");
238
+
239
+ const created = (await createTool.handler({
240
+ description: "Lifecycle test task",
241
+ })) as { task_id: string; external_id?: string };
242
+
243
+ const taskDetails = (await getTool.handler({
244
+ task_id: created.task_id,
245
+ })) as { external_id?: string; status: string };
246
+
247
+ const externalId = taskDetails.external_id;
248
+ expect(externalId).toBeDefined();
249
+ expect(taskDetails.status).toBe("pending");
250
+
251
+ // Start the task via opentasks daemon
252
+ const startResult = await taskTool.handler({
253
+ transition: { id: externalId, action: "start" },
254
+ });
255
+ expect(startResult).toBeDefined();
256
+
257
+ // Verify EventStore was synced — get_task reads from EventStore
258
+ const afterStart = (await getTool.handler({
259
+ task_id: created.task_id,
260
+ })) as { status: string };
261
+ expect(afterStart.status).toBe("in_progress");
262
+
263
+ // Complete the task via opentasks daemon
264
+ const completeResult = await taskTool.handler({
265
+ transition: { id: externalId, action: "complete" },
266
+ });
267
+ expect(completeResult).toBeDefined();
268
+
269
+ // Verify EventStore was synced
270
+ const afterComplete = (await getTool.handler({
271
+ task_id: created.task_id,
272
+ })) as { status: string };
273
+ expect(afterComplete.status).toBe("completed");
274
+ });
275
+
276
+ it("should sync task assignment via task tool to EventStore", async () => {
277
+ const createTool = findTool(provider.getTools(), "create_task");
278
+ const taskTool = findTool(provider.getTools(), "task");
279
+ const getTool = findTool(provider.getTools(), "get_task");
280
+
281
+ const created = (await createTool.handler({
282
+ description: "Assign sync test task",
283
+ })) as { task_id: string };
284
+
285
+ const taskDetails = (await getTool.handler({
286
+ task_id: created.task_id,
287
+ })) as { external_id: string };
288
+
289
+ // Assign via task tool (opentasks daemon path)
290
+ await taskTool.handler({
291
+ assign: { id: taskDetails.external_id, assignee: "agent_worker_2" },
292
+ });
293
+
294
+ // Verify EventStore was synced
295
+ const afterAssign = (await getTool.handler({
296
+ task_id: created.task_id,
297
+ })) as { assigned_agent: string };
298
+ expect(afterAssign.assigned_agent).toBe("agent_worker_2");
299
+ });
300
+
301
+ it("should query ready tasks", async () => {
302
+ const createTool = findTool(provider.getTools(), "create_task");
303
+ const taskTool = findTool(provider.getTools(), "task");
304
+
305
+ // Create a fresh task (should be ready since no blockers)
306
+ await createTool.handler({ description: "Ready test task" });
307
+
308
+ const readyResult = (await taskTool.handler({
309
+ ready: {},
310
+ })) as { type?: string; items?: unknown[] };
311
+
312
+ expect(readyResult).toBeDefined();
313
+ });
314
+
315
+ it("should get valid actions for a task", async () => {
316
+ const createTool = findTool(provider.getTools(), "create_task");
317
+ const taskTool = findTool(provider.getTools(), "task");
318
+ const getTool = findTool(provider.getTools(), "get_task");
319
+
320
+ const created = (await createTool.handler({
321
+ description: "Valid actions test",
322
+ })) as { task_id: string };
323
+
324
+ const taskDetails = (await getTool.handler({
325
+ task_id: created.task_id,
326
+ })) as { external_id?: string };
327
+
328
+ const result = await taskTool.handler({
329
+ validActions: { id: taskDetails.external_id! },
330
+ });
331
+
332
+ expect(result).toBeDefined();
333
+ });
334
+ });
335
+
336
+ describe("link tool", () => {
337
+ it("should create and remove edges between tasks", async () => {
338
+ const createTool = findTool(provider.getTools(), "create_task");
339
+ const linkTool = findTool(provider.getTools(), "link");
340
+ const getTool = findTool(provider.getTools(), "get_task");
341
+
342
+ // Create two tasks
343
+ const blocker = (await createTool.handler({
344
+ description: "Blocker task",
345
+ })) as { task_id: string };
346
+ const blocked = (await createTool.handler({
347
+ description: "Blocked task",
348
+ })) as { task_id: string };
349
+
350
+ // Get external IDs
351
+ const blockerDetails = (await getTool.handler({
352
+ task_id: blocker.task_id,
353
+ })) as { external_id: string };
354
+ const blockedDetails = (await getTool.handler({
355
+ task_id: blocked.task_id,
356
+ })) as { external_id: string };
357
+
358
+ // Create a "blocks" edge
359
+ const createResult = (await linkTool.handler({
360
+ from_id: blockerDetails.external_id,
361
+ to_id: blockedDetails.external_id,
362
+ type: "blocks",
363
+ })) as { created: boolean };
364
+
365
+ expect(createResult.created).toBe(true);
366
+
367
+ // Remove the edge
368
+ const removeResult = (await linkTool.handler({
369
+ from_id: blockerDetails.external_id,
370
+ to_id: blockedDetails.external_id,
371
+ type: "blocks",
372
+ remove: true,
373
+ })) as { removed: boolean };
374
+
375
+ expect(removeResult.removed).toBe(true);
376
+ });
377
+ });
378
+
379
+ describe("annotate tool", () => {
380
+ it("should create feedback on a task", async () => {
381
+ const createTool = findTool(provider.getTools(), "create_task");
382
+ const annotateTool = findTool(provider.getTools(), "annotate");
383
+ const getTool = findTool(provider.getTools(), "get_task");
384
+
385
+ // Create a task
386
+ const created = (await createTool.handler({
387
+ description: "Feedback target task",
388
+ })) as { task_id: string };
389
+
390
+ const details = (await getTool.handler({
391
+ task_id: created.task_id,
392
+ })) as { external_id: string };
393
+
394
+ // Add a comment
395
+ const annotateResult = (await annotateTool.handler({
396
+ target_id: details.external_id,
397
+ content: "E2E test feedback comment",
398
+ feedback_type: "comment",
399
+ })) as { feedback_id: string; created: boolean; type: string };
400
+
401
+ expect(annotateResult.created).toBe(true);
402
+ expect(annotateResult.type).toBe("comment");
403
+ expect(annotateResult.feedback_id).toBeDefined();
404
+ });
405
+
406
+ it("should resolve feedback", async () => {
407
+ const createTool = findTool(provider.getTools(), "create_task");
408
+ const annotateTool = findTool(provider.getTools(), "annotate");
409
+ const getTool = findTool(provider.getTools(), "get_task");
410
+
411
+ const created = (await createTool.handler({
412
+ description: "Resolve feedback target",
413
+ })) as { task_id: string };
414
+
415
+ const details = (await getTool.handler({
416
+ task_id: created.task_id,
417
+ })) as { external_id: string };
418
+
419
+ // Create feedback
420
+ const feedback = (await annotateTool.handler({
421
+ target_id: details.external_id,
422
+ content: "Feedback to resolve",
423
+ feedback_type: "suggestion",
424
+ })) as { feedback_id: string };
425
+
426
+ // Resolve it
427
+ const resolveResult = (await annotateTool.handler({
428
+ target_id: details.external_id,
429
+ resolve: feedback.feedback_id,
430
+ })) as { resolved: boolean; feedback_id: string };
431
+
432
+ expect(resolveResult.resolved).toBe(true);
433
+ expect(resolveResult.feedback_id).toBe(feedback.feedback_id);
434
+ });
435
+ });
436
+
437
+ // ─────────────────────────────────────────────────────────────────────────────
438
+ // Full Workflow
439
+ // ─────────────────────────────────────────────────────────────────────────────
440
+
441
+ describe("full workflow", () => {
442
+ it("should execute a complete task lifecycle: create → assign → link → annotate → transition", async () => {
443
+ const tools = provider.getTools();
444
+ const createTool = findTool(tools, "create_task");
445
+ const getTool = findTool(tools, "get_task");
446
+ const assignTool = findTool(tools, "assign_task");
447
+ const linkTool = findTool(tools, "link");
448
+ const annotateTool = findTool(tools, "annotate");
449
+ const taskTool = findTool(tools, "task");
450
+
451
+ // 1. Create parent and child tasks
452
+ const parent = (await createTool.handler({
453
+ description: "Full workflow parent task",
454
+ })) as { task_id: string };
455
+
456
+ const child = (await createTool.handler({
457
+ description: "Full workflow child task",
458
+ parent_task: parent.task_id,
459
+ })) as { task_id: string };
460
+
461
+ // 2. Get external IDs
462
+ const parentDetails = (await getTool.handler({
463
+ task_id: parent.task_id,
464
+ })) as { external_id: string };
465
+
466
+ const childDetails = (await getTool.handler({
467
+ task_id: child.task_id,
468
+ })) as { external_id: string };
469
+
470
+ expect(parentDetails.external_id).toBeDefined();
471
+ expect(childDetails.external_id).toBeDefined();
472
+
473
+ // 3. Create a "blocks" link: parent blocks child
474
+ const linkResult = (await linkTool.handler({
475
+ from_id: parentDetails.external_id,
476
+ to_id: childDetails.external_id,
477
+ type: "blocks",
478
+ })) as { created: boolean };
479
+
480
+ expect(linkResult.created).toBe(true);
481
+
482
+ // 4. Assign parent task
483
+ const assignResult = (await assignTool.handler({
484
+ task_id: parent.task_id,
485
+ agent_id: TEST_AGENT_ID,
486
+ })) as { assigned: boolean };
487
+
488
+ expect(assignResult.assigned).toBe(true);
489
+
490
+ // 5. Add feedback on the parent
491
+ const feedbackResult = (await annotateTool.handler({
492
+ target_id: parentDetails.external_id,
493
+ content: "Starting work on this task",
494
+ feedback_type: "comment",
495
+ })) as { created: boolean; feedback_id: string };
496
+
497
+ expect(feedbackResult.created).toBe(true);
498
+
499
+ // 6. Start parent via task tool
500
+ const startResult = (await taskTool.handler({
501
+ transition: { id: parentDetails.external_id, action: "start" },
502
+ })) as { success: boolean };
503
+
504
+ expect(startResult).toBeDefined();
505
+
506
+ // 7. Complete parent via task tool
507
+ const completeResult = (await taskTool.handler({
508
+ transition: { id: parentDetails.external_id, action: "complete" },
509
+ })) as { success: boolean };
510
+
511
+ expect(completeResult).toBeDefined();
512
+
513
+ // 8. Verify parent is completed in EventStore (syncExternalTransition)
514
+ const finalParent = (await getTool.handler({
515
+ task_id: parent.task_id,
516
+ })) as { status: string; external_id: string; assigned_agent: string };
517
+
518
+ expect(finalParent).toBeDefined();
519
+ expect(finalParent.external_id).toBe(parentDetails.external_id);
520
+ expect(finalParent.status).toBe("completed");
521
+ expect(finalParent.assigned_agent).toBe(TEST_AGENT_ID);
522
+ });
523
+ });
524
+ });
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Pull-Mode Task Backend Tests
3
+ *
4
+ * Tests the claim/unclaim/listClaimable methods of InMemoryTaskBackend
5
+ * which enable the pull model where workers claim tasks from a pool.
6
+ *
7
+ * @module task/backend/__tests__/memory-pull-mode
8
+ */
9
+
10
+ import { describe, it, expect, beforeEach } from "vitest";
11
+ import { createEventStore, type EventStore } from "../../../store/event-store.js";
12
+ import { InMemoryTaskBackend } from "../memory.js";
13
+ import type { AgentId, TaskId } from "../../../store/types/index.js";
14
+
15
+ describe("InMemoryTaskBackend — Pull Mode", () => {
16
+ let eventStore: EventStore;
17
+ let backend: InMemoryTaskBackend;
18
+
19
+ const AGENT_A = "agent-a" as AgentId;
20
+ const AGENT_B = "agent-b" as AgentId;
21
+ const CREATOR = "creator-001" as AgentId;
22
+
23
+ beforeEach(async () => {
24
+ eventStore = await createEventStore({ instanceId: `pull-test-${Date.now()}` });
25
+ backend = new InMemoryTaskBackend(eventStore);
26
+ });
27
+
28
+ // ─────────────────────────────────────────────────────────────────
29
+ // claim()
30
+ // ─────────────────────────────────────────────────────────────────
31
+
32
+ it("claim returns first pending unblocked task", async () => {
33
+ const t1 = await backend.create({ description: "Task 1", created_by: CREATOR });
34
+ const t2 = await backend.create({ description: "Task 2", created_by: CREATOR });
35
+ const t3 = await backend.create({ description: "Task 3", created_by: CREATOR });
36
+
37
+ const claimed = await backend.claim!(AGENT_A);
38
+ expect(claimed).not.toBeNull();
39
+ expect(claimed!.id).toBe(t1.id);
40
+ expect(claimed!.assigned_agent).toBe(AGENT_A);
41
+
42
+ // Second claim should return t2
43
+ const claimed2 = await backend.claim!(AGENT_B);
44
+ expect(claimed2).not.toBeNull();
45
+ expect(claimed2!.id).toBe(t2.id);
46
+ expect(claimed2!.assigned_agent).toBe(AGENT_B);
47
+ });
48
+
49
+ it("claim skips assigned tasks", async () => {
50
+ const t1 = await backend.create({ description: "Task 1", created_by: CREATOR });
51
+ const t2 = await backend.create({ description: "Task 2", created_by: CREATOR });
52
+
53
+ // Assign t1 directly
54
+ await backend.assign(t1.id, { agent_id: AGENT_A });
55
+
56
+ // claim should skip t1 and return t2
57
+ const claimed = await backend.claim!(AGENT_B);
58
+ expect(claimed).not.toBeNull();
59
+ expect(claimed!.id).toBe(t2.id);
60
+ });
61
+
62
+ it("claim skips blocked tasks", async () => {
63
+ const blocker = await backend.create({ description: "Blocker task", created_by: CREATOR });
64
+ const blocked = await backend.create({ description: "Blocked task", created_by: CREATOR });
65
+ const available = await backend.create({ description: "Available task", created_by: CREATOR });
66
+
67
+ // Add blocker dependency
68
+ await backend.addBlocker(blocked.id, blocker.id);
69
+
70
+ // claim should skip blocked and return available
71
+ const claimed = await backend.claim!(AGENT_A);
72
+ expect(claimed).not.toBeNull();
73
+ // Should return either blocker or available (blocker is pending+unblocked, so it comes first)
74
+ // blocker is pending + not assigned + not blocked → claimable
75
+ // blocked is pending + not assigned but IS blocked → not claimable
76
+ // available is pending + not assigned + not blocked → claimable
77
+ expect([blocker.id, available.id]).toContain(claimed!.id);
78
+ expect(claimed!.id).not.toBe(blocked.id);
79
+ });
80
+
81
+ it("claim returns null when no claimable tasks", async () => {
82
+ // Create a task and assign it
83
+ const t1 = await backend.create({ description: "Task 1", created_by: CREATOR });
84
+ await backend.assign(t1.id, { agent_id: AGENT_A });
85
+
86
+ // No unassigned pending tasks left
87
+ const claimed = await backend.claim!(AGENT_B);
88
+ expect(claimed).toBeNull();
89
+ });
90
+
91
+ // ─────────────────────────────────────────────────────────────────
92
+ // unclaim()
93
+ // ─────────────────────────────────────────────────────────────────
94
+
95
+ it("unclaim returns task to pending pool", async () => {
96
+ const t1 = await backend.create({ description: "Task 1", created_by: CREATOR });
97
+
98
+ // Claim it
99
+ const claimed = await backend.claim!(AGENT_A);
100
+ expect(claimed!.id).toBe(t1.id);
101
+ expect(claimed!.assigned_agent).toBe(AGENT_A);
102
+
103
+ // Unclaim it
104
+ await backend.unclaim!(t1.id);
105
+
106
+ // Task should be claimable again
107
+ const reClaimed = await backend.claim!(AGENT_B);
108
+ expect(reClaimed).not.toBeNull();
109
+ expect(reClaimed!.id).toBe(t1.id);
110
+ expect(reClaimed!.assigned_agent).toBe(AGENT_B);
111
+ });
112
+
113
+ it("unclaim throws on unassigned task", async () => {
114
+ const t1 = await backend.create({ description: "Task 1", created_by: CREATOR });
115
+
116
+ await expect(backend.unclaim!(t1.id)).rejects.toThrow("not assigned");
117
+ });
118
+
119
+ // ─────────────────────────────────────────────────────────────────
120
+ // listClaimable()
121
+ // ─────────────────────────────────────────────────────────────────
122
+
123
+ it("listClaimable filters by tags", async () => {
124
+ await backend.create({
125
+ description: "Frontend task",
126
+ created_by: CREATOR,
127
+ tags: ["frontend", "ui"],
128
+ });
129
+ await backend.create({
130
+ description: "Backend task",
131
+ created_by: CREATOR,
132
+ tags: ["backend", "api"],
133
+ });
134
+ await backend.create({
135
+ description: "Untagged task",
136
+ created_by: CREATOR,
137
+ });
138
+
139
+ // Filter by "backend" tag
140
+ const claimable = await backend.listClaimable!({ tags: ["backend"] });
141
+ expect(claimable.length).toBe(1);
142
+ expect(claimable[0].description).toBe("Backend task");
143
+
144
+ // Filter by "frontend" tag
145
+ const frontendTasks = await backend.listClaimable!({ tags: ["frontend"] });
146
+ expect(frontendTasks.length).toBe(1);
147
+ expect(frontendTasks[0].description).toBe("Frontend task");
148
+
149
+ // No filter returns all claimable
150
+ const allClaimable = await backend.listClaimable!();
151
+ expect(allClaimable.length).toBe(3);
152
+ });
153
+ });