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,617 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { SettingsManager } from "../settings.js";
3
- import * as fs from "node:fs";
4
- import * as path from "node:path";
5
- import * as os from "node:os";
6
-
7
- describe("SettingsManager", () => {
8
- let tempDir: string;
9
- let settingsManager: SettingsManager;
10
-
11
- beforeEach(async () => {
12
- tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "settings-test-"));
13
- });
14
-
15
- afterEach(async () => {
16
- settingsManager?.dispose();
17
- await fs.promises.rm(tempDir, { recursive: true, force: true });
18
- });
19
-
20
- describe("permission checking", () => {
21
- it("should return 'ask' when no settings exist", async () => {
22
- settingsManager = new SettingsManager(tempDir);
23
- await settingsManager.initialize();
24
-
25
- const result = settingsManager.checkPermission("mcp__acp__Read", {
26
- file_path: "/some/file.txt",
27
- });
28
- expect(result.decision).toBe("ask");
29
- });
30
-
31
- it("should return 'ask' for non-ACP tools (permission checks only apply to mcp__acp__* tools)", async () => {
32
- const claudeDir = path.join(tempDir, ".claude");
33
- await fs.promises.mkdir(claudeDir, { recursive: true });
34
- await fs.promises.writeFile(
35
- path.join(claudeDir, "settings.json"),
36
- JSON.stringify({
37
- permissions: {
38
- deny: ["Read"],
39
- },
40
- }),
41
- );
42
-
43
- settingsManager = new SettingsManager(tempDir);
44
- await settingsManager.initialize();
45
-
46
- // Non-ACP tools should always return 'ask' regardless of rules
47
- const result = settingsManager.checkPermission("Read", { file_path: "/some/file.txt" });
48
- expect(result.decision).toBe("ask");
49
- });
50
-
51
- it("should allow tool use when matching allow rule exists", async () => {
52
- const claudeDir = path.join(tempDir, ".claude");
53
- await fs.promises.mkdir(claudeDir, { recursive: true });
54
- await fs.promises.writeFile(
55
- path.join(claudeDir, "settings.json"),
56
- JSON.stringify({
57
- permissions: {
58
- allow: ["Read"],
59
- },
60
- }),
61
- );
62
-
63
- settingsManager = new SettingsManager(tempDir);
64
- await settingsManager.initialize();
65
-
66
- const result = settingsManager.checkPermission("mcp__acp__Read", {
67
- file_path: "/some/file.txt",
68
- });
69
- expect(result.decision).toBe("allow");
70
- expect(result.rule).toBe("Read");
71
- });
72
-
73
- it("should deny tool use when matching deny rule exists", async () => {
74
- const claudeDir = path.join(tempDir, ".claude");
75
- await fs.promises.mkdir(claudeDir, { recursive: true });
76
- await fs.promises.writeFile(
77
- path.join(claudeDir, "settings.json"),
78
- JSON.stringify({
79
- permissions: {
80
- deny: ["Read(./.env)"],
81
- },
82
- }),
83
- );
84
-
85
- settingsManager = new SettingsManager(tempDir);
86
- await settingsManager.initialize();
87
-
88
- const result = settingsManager.checkPermission("mcp__acp__Read", {
89
- file_path: path.join(tempDir, ".env"),
90
- });
91
- expect(result.decision).toBe("deny");
92
- expect(result.rule).toBe("Read(./.env)");
93
- });
94
-
95
- it("should prioritize deny rules over allow rules", async () => {
96
- const claudeDir = path.join(tempDir, ".claude");
97
- await fs.promises.mkdir(claudeDir, { recursive: true });
98
- await fs.promises.writeFile(
99
- path.join(claudeDir, "settings.json"),
100
- JSON.stringify({
101
- permissions: {
102
- allow: ["Read"],
103
- deny: ["Read(./.env)"],
104
- },
105
- }),
106
- );
107
-
108
- settingsManager = new SettingsManager(tempDir);
109
- await settingsManager.initialize();
110
-
111
- // .env should be denied
112
- const envResult = settingsManager.checkPermission("mcp__acp__Read", {
113
- file_path: path.join(tempDir, ".env"),
114
- });
115
- expect(envResult.decision).toBe("deny");
116
-
117
- // other files should be allowed
118
- const otherResult = settingsManager.checkPermission("mcp__acp__Read", {
119
- file_path: path.join(tempDir, "other.txt"),
120
- });
121
- expect(otherResult.decision).toBe("allow");
122
- });
123
-
124
- it("should handle ACP-prefixed tool names", async () => {
125
- const claudeDir = path.join(tempDir, ".claude");
126
- await fs.promises.mkdir(claudeDir, { recursive: true });
127
- await fs.promises.writeFile(
128
- path.join(claudeDir, "settings.json"),
129
- JSON.stringify({
130
- permissions: {
131
- allow: ["Read"],
132
- },
133
- }),
134
- );
135
-
136
- settingsManager = new SettingsManager(tempDir);
137
- await settingsManager.initialize();
138
-
139
- const result = settingsManager.checkPermission("mcp__acp__Read", {
140
- file_path: "/some/file.txt",
141
- });
142
- expect(result.decision).toBe("allow");
143
- });
144
- });
145
-
146
- describe("Bash permission rules", () => {
147
- it("should match exact Bash commands without :* wildcard", async () => {
148
- const claudeDir = path.join(tempDir, ".claude");
149
- await fs.promises.mkdir(claudeDir, { recursive: true });
150
- await fs.promises.writeFile(
151
- path.join(claudeDir, "settings.json"),
152
- JSON.stringify({
153
- permissions: {
154
- // Per docs: Bash(npm run build) matches the EXACT command "npm run build"
155
- allow: ["Bash(npm run lint)"],
156
- },
157
- }),
158
- );
159
-
160
- settingsManager = new SettingsManager(tempDir);
161
- await settingsManager.initialize();
162
-
163
- // Exact match should be allowed
164
- const exactResult = settingsManager.checkPermission("mcp__acp__Bash", {
165
- command: "npm run lint",
166
- });
167
- expect(exactResult.decision).toBe("allow");
168
-
169
- // Command with extra arguments should NOT match (exact match only)
170
- const withArgsResult = settingsManager.checkPermission("mcp__acp__Bash", {
171
- command: "npm run lint --fix",
172
- });
173
- expect(withArgsResult.decision).toBe("ask");
174
-
175
- // Similar command should NOT match (exact match only)
176
- const similarResult = settingsManager.checkPermission("mcp__acp__Bash", {
177
- command: "npm run linting",
178
- });
179
- expect(similarResult.decision).toBe("ask");
180
-
181
- // Different command should not match
182
- const differentResult = settingsManager.checkPermission("mcp__acp__Bash", {
183
- command: "npm run test",
184
- });
185
- expect(differentResult.decision).toBe("ask");
186
- });
187
-
188
- it("should match Bash commands with :* wildcard suffix (prefix matching)", async () => {
189
- const claudeDir = path.join(tempDir, ".claude");
190
- await fs.promises.mkdir(claudeDir, { recursive: true });
191
- await fs.promises.writeFile(
192
- path.join(claudeDir, "settings.json"),
193
- JSON.stringify({
194
- permissions: {
195
- // The :* suffix is a convention to make prefix matching explicit
196
- allow: ["Bash(npm run:*)"],
197
- },
198
- }),
199
- );
200
-
201
- settingsManager = new SettingsManager(tempDir);
202
- await settingsManager.initialize();
203
-
204
- // Any command starting with "npm run" should match (prefix matching with :*)
205
- const lintResult = settingsManager.checkPermission("mcp__acp__Bash", {
206
- command: "npm run lint",
207
- });
208
- expect(lintResult.decision).toBe("allow");
209
-
210
- const testResult = settingsManager.checkPermission("mcp__acp__Bash", {
211
- command: "npm run test",
212
- });
213
- expect(testResult.decision).toBe("allow");
214
-
215
- // Commands with additional args also match
216
- const withArgsResult = settingsManager.checkPermission("mcp__acp__Bash", {
217
- command: "npm run test --watch",
218
- });
219
- expect(withArgsResult.decision).toBe("allow");
220
-
221
- // Non-matching command
222
- const installResult = settingsManager.checkPermission("mcp__acp__Bash", {
223
- command: "npm install",
224
- });
225
- expect(installResult.decision).toBe("ask");
226
- });
227
-
228
- it("should not allow shell operators to bypass prefix matching", async () => {
229
- const claudeDir = path.join(tempDir, ".claude");
230
- await fs.promises.mkdir(claudeDir, { recursive: true });
231
- await fs.promises.writeFile(
232
- path.join(claudeDir, "settings.json"),
233
- JSON.stringify({
234
- permissions: {
235
- allow: ["Bash(safe-cmd:*)"],
236
- },
237
- }),
238
- );
239
-
240
- settingsManager = new SettingsManager(tempDir);
241
- await settingsManager.initialize();
242
-
243
- // Normal prefix match should work
244
- const normalResult = settingsManager.checkPermission("mcp__acp__Bash", {
245
- command: "safe-cmd --flag",
246
- });
247
- expect(normalResult.decision).toBe("allow");
248
-
249
- // Shell operators should NOT be allowed (per docs: Claude Code is aware of shell operators)
250
- const andResult = settingsManager.checkPermission("mcp__acp__Bash", {
251
- command: "safe-cmd && malicious-cmd",
252
- });
253
- expect(andResult.decision).toBe("ask");
254
-
255
- const orResult = settingsManager.checkPermission("mcp__acp__Bash", {
256
- command: "safe-cmd || malicious-cmd",
257
- });
258
- expect(orResult.decision).toBe("ask");
259
-
260
- const semicolonResult = settingsManager.checkPermission("mcp__acp__Bash", {
261
- command: "safe-cmd; malicious-cmd",
262
- });
263
- expect(semicolonResult.decision).toBe("ask");
264
-
265
- const pipeResult = settingsManager.checkPermission("mcp__acp__Bash", {
266
- command: "safe-cmd | malicious-cmd",
267
- });
268
- expect(pipeResult.decision).toBe("ask");
269
-
270
- const subshellResult = settingsManager.checkPermission("mcp__acp__Bash", {
271
- command: "safe-cmd $(malicious-cmd)",
272
- });
273
- expect(subshellResult.decision).toBe("ask");
274
-
275
- const backtickResult = settingsManager.checkPermission("mcp__acp__Bash", {
276
- command: "safe-cmd `malicious-cmd`",
277
- });
278
- expect(backtickResult.decision).toBe("ask");
279
-
280
- const newlineResult = settingsManager.checkPermission("mcp__acp__Bash", {
281
- command: "safe-cmd\nmalicious-cmd",
282
- });
283
- expect(newlineResult.decision).toBe("ask");
284
- });
285
-
286
- it("should deny dangerous Bash commands", async () => {
287
- const claudeDir = path.join(tempDir, ".claude");
288
- await fs.promises.mkdir(claudeDir, { recursive: true });
289
- await fs.promises.writeFile(
290
- path.join(claudeDir, "settings.json"),
291
- JSON.stringify({
292
- permissions: {
293
- deny: ["Bash(curl:*)", "Bash(wget:*)"],
294
- },
295
- }),
296
- );
297
-
298
- settingsManager = new SettingsManager(tempDir);
299
- await settingsManager.initialize();
300
-
301
- const curlResult = settingsManager.checkPermission("mcp__acp__Bash", {
302
- command: "curl https://example.com",
303
- });
304
- expect(curlResult.decision).toBe("deny");
305
-
306
- const wgetResult = settingsManager.checkPermission("mcp__acp__Bash", {
307
- command: "wget https://example.com",
308
- });
309
- expect(wgetResult.decision).toBe("deny");
310
-
311
- const lsResult = settingsManager.checkPermission("mcp__acp__Bash", { command: "ls -la" });
312
- expect(lsResult.decision).toBe("ask");
313
- });
314
- });
315
-
316
- describe("file path glob matching", () => {
317
- it("should match exact file paths", async () => {
318
- const claudeDir = path.join(tempDir, ".claude");
319
- await fs.promises.mkdir(claudeDir, { recursive: true });
320
- await fs.promises.writeFile(
321
- path.join(claudeDir, "settings.json"),
322
- JSON.stringify({
323
- permissions: {
324
- deny: ["Read(./.env)"],
325
- },
326
- }),
327
- );
328
-
329
- settingsManager = new SettingsManager(tempDir);
330
- await settingsManager.initialize();
331
-
332
- const envResult = settingsManager.checkPermission("mcp__acp__Read", {
333
- file_path: path.join(tempDir, ".env"),
334
- });
335
- expect(envResult.decision).toBe("deny");
336
-
337
- const otherResult = settingsManager.checkPermission("mcp__acp__Read", {
338
- file_path: path.join(tempDir, ".envrc"),
339
- });
340
- expect(otherResult.decision).toBe("ask");
341
- });
342
-
343
- it("should match glob patterns with single wildcard", async () => {
344
- const claudeDir = path.join(tempDir, ".claude");
345
- await fs.promises.mkdir(claudeDir, { recursive: true });
346
- await fs.promises.writeFile(
347
- path.join(claudeDir, "settings.json"),
348
- JSON.stringify({
349
- permissions: {
350
- deny: ["Read(./.env.*)"],
351
- },
352
- }),
353
- );
354
-
355
- settingsManager = new SettingsManager(tempDir);
356
- await settingsManager.initialize();
357
-
358
- const envLocalResult = settingsManager.checkPermission("mcp__acp__Read", {
359
- file_path: path.join(tempDir, ".env.local"),
360
- });
361
- expect(envLocalResult.decision).toBe("deny");
362
-
363
- const envProdResult = settingsManager.checkPermission("mcp__acp__Read", {
364
- file_path: path.join(tempDir, ".env.production"),
365
- });
366
- expect(envProdResult.decision).toBe("deny");
367
-
368
- // Plain .env should not match .env.*
369
- const plainEnvResult = settingsManager.checkPermission("mcp__acp__Read", {
370
- file_path: path.join(tempDir, ".env"),
371
- });
372
- expect(plainEnvResult.decision).toBe("ask");
373
- });
374
-
375
- it("should match glob patterns with double wildcard (recursive)", async () => {
376
- const claudeDir = path.join(tempDir, ".claude");
377
- await fs.promises.mkdir(claudeDir, { recursive: true });
378
- await fs.promises.writeFile(
379
- path.join(claudeDir, "settings.json"),
380
- JSON.stringify({
381
- permissions: {
382
- deny: ["Read(./secrets/**)"],
383
- },
384
- }),
385
- );
386
-
387
- settingsManager = new SettingsManager(tempDir);
388
- await settingsManager.initialize();
389
-
390
- const secretResult = settingsManager.checkPermission("mcp__acp__Read", {
391
- file_path: path.join(tempDir, "secrets", "api-key.txt"),
392
- });
393
- expect(secretResult.decision).toBe("deny");
394
-
395
- const nestedSecretResult = settingsManager.checkPermission("mcp__acp__Read", {
396
- file_path: path.join(tempDir, "secrets", "deep", "nested", "key.txt"),
397
- });
398
- expect(nestedSecretResult.decision).toBe("deny");
399
-
400
- const otherResult = settingsManager.checkPermission("mcp__acp__Read", {
401
- file_path: path.join(tempDir, "public", "file.txt"),
402
- });
403
- expect(otherResult.decision).toBe("ask");
404
- });
405
-
406
- it("should handle home directory expansion", async () => {
407
- const claudeDir = path.join(tempDir, ".claude");
408
- await fs.promises.mkdir(claudeDir, { recursive: true });
409
- await fs.promises.writeFile(
410
- path.join(claudeDir, "settings.json"),
411
- JSON.stringify({
412
- permissions: {
413
- allow: ["Read(~/.zshrc)"],
414
- },
415
- }),
416
- );
417
-
418
- settingsManager = new SettingsManager(tempDir);
419
- await settingsManager.initialize();
420
-
421
- const zshrcResult = settingsManager.checkPermission("mcp__acp__Read", {
422
- file_path: path.join(os.homedir(), ".zshrc"),
423
- });
424
- expect(zshrcResult.decision).toBe("allow");
425
- });
426
- });
427
-
428
- describe("settings merging", () => {
429
- it("should merge project and local settings", async () => {
430
- const claudeDir = path.join(tempDir, ".claude");
431
- await fs.promises.mkdir(claudeDir, { recursive: true });
432
-
433
- // Project settings
434
- await fs.promises.writeFile(
435
- path.join(claudeDir, "settings.json"),
436
- JSON.stringify({
437
- permissions: {
438
- allow: ["Read"],
439
- },
440
- }),
441
- );
442
-
443
- // Local settings
444
- await fs.promises.writeFile(
445
- path.join(claudeDir, "settings.local.json"),
446
- JSON.stringify({
447
- permissions: {
448
- deny: ["Read(./.env)"],
449
- },
450
- }),
451
- );
452
-
453
- settingsManager = new SettingsManager(tempDir);
454
- await settingsManager.initialize();
455
-
456
- // Read should be allowed in general
457
- const readResult = settingsManager.checkPermission("mcp__acp__Read", {
458
- file_path: path.join(tempDir, "file.txt"),
459
- });
460
- expect(readResult.decision).toBe("allow");
461
-
462
- // But .env should be denied (local settings take precedence)
463
- const envResult = settingsManager.checkPermission("mcp__acp__Read", {
464
- file_path: path.join(tempDir, ".env"),
465
- });
466
- expect(envResult.decision).toBe("deny");
467
- });
468
- });
469
-
470
- describe("ask rules", () => {
471
- it("should return 'ask' for matching ask rules", async () => {
472
- const claudeDir = path.join(tempDir, ".claude");
473
- await fs.promises.mkdir(claudeDir, { recursive: true });
474
- await fs.promises.writeFile(
475
- path.join(claudeDir, "settings.json"),
476
- JSON.stringify({
477
- permissions: {
478
- ask: ["Bash(git push:*)"],
479
- },
480
- }),
481
- );
482
-
483
- settingsManager = new SettingsManager(tempDir);
484
- await settingsManager.initialize();
485
-
486
- const result = settingsManager.checkPermission("mcp__acp__Bash", {
487
- command: "git push origin main",
488
- });
489
- expect(result.decision).toBe("ask");
490
- expect(result.rule).toBe("Bash(git push:*)");
491
- });
492
- });
493
-
494
- describe("Edit and Write tools", () => {
495
- it("should handle Edit tool permissions", async () => {
496
- const claudeDir = path.join(tempDir, ".claude");
497
- await fs.promises.mkdir(claudeDir, { recursive: true });
498
- await fs.promises.writeFile(
499
- path.join(claudeDir, "settings.json"),
500
- JSON.stringify({
501
- permissions: {
502
- deny: ["Edit(./package-lock.json)"],
503
- },
504
- }),
505
- );
506
-
507
- settingsManager = new SettingsManager(tempDir);
508
- await settingsManager.initialize();
509
-
510
- const lockFileResult = settingsManager.checkPermission("mcp__acp__Edit", {
511
- file_path: path.join(tempDir, "package-lock.json"),
512
- });
513
- expect(lockFileResult.decision).toBe("deny");
514
-
515
- const otherResult = settingsManager.checkPermission("mcp__acp__Edit", {
516
- file_path: path.join(tempDir, "package.json"),
517
- });
518
- expect(otherResult.decision).toBe("ask");
519
- });
520
-
521
- it("should handle mcp__acp__Edit and mcp__acp__Write tool names", async () => {
522
- const claudeDir = path.join(tempDir, ".claude");
523
- await fs.promises.mkdir(claudeDir, { recursive: true });
524
- await fs.promises.writeFile(
525
- path.join(claudeDir, "settings.json"),
526
- JSON.stringify({
527
- permissions: {
528
- allow: ["Edit", "Write"],
529
- },
530
- }),
531
- );
532
-
533
- settingsManager = new SettingsManager(tempDir);
534
- await settingsManager.initialize();
535
-
536
- const editResult = settingsManager.checkPermission("mcp__acp__Edit", {
537
- file_path: "/some/file.ts",
538
- });
539
- expect(editResult.decision).toBe("allow");
540
-
541
- const writeResult = settingsManager.checkPermission("mcp__acp__Write", {
542
- file_path: "/some/file.ts",
543
- });
544
- expect(writeResult.decision).toBe("allow");
545
- });
546
- });
547
-
548
- describe("getSettings", () => {
549
- it("should return merged settings", async () => {
550
- const claudeDir = path.join(tempDir, ".claude");
551
- await fs.promises.mkdir(claudeDir, { recursive: true });
552
- await fs.promises.writeFile(
553
- path.join(claudeDir, "settings.json"),
554
- JSON.stringify({
555
- permissions: {
556
- allow: ["Read", "Bash(npm:*)"],
557
- deny: ["Read(./.env)"],
558
- },
559
- env: {
560
- FOO: "bar",
561
- },
562
- }),
563
- );
564
-
565
- settingsManager = new SettingsManager(tempDir);
566
- await settingsManager.initialize();
567
-
568
- const settings = settingsManager.getSettings();
569
- expect(settings.permissions?.allow).toContain("Read");
570
- expect(settings.permissions?.allow).toContain("Bash(npm:*)");
571
- expect(settings.permissions?.deny).toContain("Read(./.env)");
572
- expect(settings.env?.FOO).toBe("bar");
573
- });
574
- });
575
-
576
- describe("setCwd", () => {
577
- it("should reload settings when cwd changes", async () => {
578
- const claudeDir1 = path.join(tempDir, ".claude");
579
- await fs.promises.mkdir(claudeDir1, { recursive: true });
580
- await fs.promises.writeFile(
581
- path.join(claudeDir1, "settings.json"),
582
- JSON.stringify({
583
- permissions: {
584
- allow: ["Read"],
585
- },
586
- }),
587
- );
588
-
589
- settingsManager = new SettingsManager(tempDir);
590
- await settingsManager.initialize();
591
-
592
- let result = settingsManager.checkPermission("mcp__acp__Read", { file_path: "/file.txt" });
593
- expect(result.decision).toBe("allow");
594
-
595
- // Create a new temp directory with different settings
596
- const tempDir2 = await fs.promises.mkdtemp(path.join(os.tmpdir(), "settings-test-2-"));
597
- const claudeDir2 = path.join(tempDir2, ".claude");
598
- await fs.promises.mkdir(claudeDir2, { recursive: true });
599
- await fs.promises.writeFile(
600
- path.join(claudeDir2, "settings.json"),
601
- JSON.stringify({
602
- permissions: {
603
- deny: ["Read"],
604
- },
605
- }),
606
- );
607
-
608
- await settingsManager.setCwd(tempDir2);
609
-
610
- result = settingsManager.checkPermission("mcp__acp__Read", { file_path: "/file.txt" });
611
- expect(result.decision).toBe("deny");
612
-
613
- // Cleanup second temp dir
614
- await fs.promises.rm(tempDir2, { recursive: true, force: true });
615
- });
616
- });
617
- });