macro-agent 0.1.1 → 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 (406) hide show
  1. package/.sudocode/issues.jsonl +28 -0
  2. package/.sudocode/specs.jsonl +4 -0
  3. package/CLAUDE.md +9 -3
  4. package/dist/agent/agent-manager.d.ts.map +1 -1
  5. package/dist/agent/agent-manager.js +111 -48
  6. package/dist/agent/agent-manager.js.map +1 -1
  7. package/dist/agent/types.d.ts +7 -0
  8. package/dist/agent/types.d.ts.map +1 -1
  9. package/dist/agent/types.js.map +1 -1
  10. package/dist/api/server.d.ts +5 -1
  11. package/dist/api/server.d.ts.map +1 -1
  12. package/dist/api/server.js +100 -3
  13. package/dist/api/server.js.map +1 -1
  14. package/dist/api/types.d.ts +1 -1
  15. package/dist/api/types.d.ts.map +1 -1
  16. package/dist/cli/acp.d.ts.map +1 -1
  17. package/dist/cli/acp.js +71 -1
  18. package/dist/cli/acp.js.map +1 -1
  19. package/dist/cli/index.js +5 -1
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/mcp.js +27 -8
  22. package/dist/cli/mcp.js.map +1 -1
  23. package/dist/config/project-config.d.ts +13 -2
  24. package/dist/config/project-config.d.ts.map +1 -1
  25. package/dist/config/project-config.js +12 -2
  26. package/dist/config/project-config.js.map +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/lifecycle/handlers/index.d.ts +7 -3
  32. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  33. package/dist/lifecycle/handlers/index.js +25 -8
  34. package/dist/lifecycle/handlers/index.js.map +1 -1
  35. package/dist/lifecycle/types.d.ts +2 -0
  36. package/dist/lifecycle/types.d.ts.map +1 -1
  37. package/dist/lifecycle/types.js.map +1 -1
  38. package/dist/map/adapter/extensions/index.d.ts +4 -1
  39. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  40. package/dist/map/adapter/extensions/index.js +27 -0
  41. package/dist/map/adapter/extensions/index.js.map +1 -1
  42. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  43. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  44. package/dist/map/adapter/extensions/streams.js +515 -0
  45. package/dist/map/adapter/extensions/streams.js.map +1 -0
  46. package/dist/map/adapter/index.d.ts +1 -1
  47. package/dist/map/adapter/index.d.ts.map +1 -1
  48. package/dist/map/adapter/index.js +3 -1
  49. package/dist/map/adapter/index.js.map +1 -1
  50. package/dist/map/adapter/types.d.ts +1 -1
  51. package/dist/map/adapter/types.d.ts.map +1 -1
  52. package/dist/mcp/mcp-server.d.ts +2 -0
  53. package/dist/mcp/mcp-server.d.ts.map +1 -1
  54. package/dist/mcp/mcp-server.js +12 -3
  55. package/dist/mcp/mcp-server.js.map +1 -1
  56. package/dist/mcp/tools/done.d.ts.map +1 -1
  57. package/dist/mcp/tools/done.js +18 -0
  58. package/dist/mcp/tools/done.js.map +1 -1
  59. package/dist/roles/builtin/coordinator.d.ts.map +1 -1
  60. package/dist/roles/builtin/coordinator.js +2 -1
  61. package/dist/roles/builtin/coordinator.js.map +1 -1
  62. package/dist/roles/builtin/integrator.d.ts.map +1 -1
  63. package/dist/roles/builtin/integrator.js +2 -1
  64. package/dist/roles/builtin/integrator.js.map +1 -1
  65. package/dist/roles/builtin/worker.d.ts.map +1 -1
  66. package/dist/roles/builtin/worker.js +3 -1
  67. package/dist/roles/builtin/worker.js.map +1 -1
  68. package/dist/roles/capabilities.d.ts +6 -0
  69. package/dist/roles/capabilities.d.ts.map +1 -1
  70. package/dist/roles/capabilities.js +10 -0
  71. package/dist/roles/capabilities.js.map +1 -1
  72. package/dist/roles/config-loader.d.ts +1 -1
  73. package/dist/roles/config-loader.d.ts.map +1 -1
  74. package/dist/roles/config-loader.js +3 -2
  75. package/dist/roles/config-loader.js.map +1 -1
  76. package/dist/roles/types.d.ts +3 -1
  77. package/dist/roles/types.d.ts.map +1 -1
  78. package/dist/server/combined-server.d.ts +8 -1
  79. package/dist/server/combined-server.d.ts.map +1 -1
  80. package/dist/server/combined-server.js +6 -2
  81. package/dist/server/combined-server.js.map +1 -1
  82. package/dist/store/event-store.d.ts.map +1 -1
  83. package/dist/store/event-store.js +12 -5
  84. package/dist/store/event-store.js.map +1 -1
  85. package/dist/store/instance.d.ts +1 -1
  86. package/dist/store/instance.d.ts.map +1 -1
  87. package/dist/store/instance.js +2 -2
  88. package/dist/store/instance.js.map +1 -1
  89. package/dist/store/types/agents.d.ts +5 -0
  90. package/dist/store/types/agents.d.ts.map +1 -1
  91. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -1
  92. package/dist/task/backend/opentasks/daemon-manager.js +1 -1
  93. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -1
  94. package/dist/teams/index.d.ts +3 -1
  95. package/dist/teams/index.d.ts.map +1 -1
  96. package/dist/teams/index.js +2 -0
  97. package/dist/teams/index.js.map +1 -1
  98. package/dist/teams/seed-defaults.d.ts +20 -0
  99. package/dist/teams/seed-defaults.d.ts.map +1 -0
  100. package/dist/teams/seed-defaults.js +71 -0
  101. package/dist/teams/seed-defaults.js.map +1 -0
  102. package/dist/teams/team-loader.d.ts +6 -2
  103. package/dist/teams/team-loader.d.ts.map +1 -1
  104. package/dist/teams/team-loader.js +154 -162
  105. package/dist/teams/team-loader.js.map +1 -1
  106. package/dist/teams/team-manager.d.ts +112 -0
  107. package/dist/teams/team-manager.d.ts.map +1 -0
  108. package/dist/teams/team-manager.js +305 -0
  109. package/dist/teams/team-manager.js.map +1 -0
  110. package/dist/teams/team-runtime.d.ts +125 -19
  111. package/dist/teams/team-runtime.d.ts.map +1 -1
  112. package/dist/teams/team-runtime.js +527 -119
  113. package/dist/teams/team-runtime.js.map +1 -1
  114. package/dist/teams/types.d.ts +41 -151
  115. package/dist/teams/types.d.ts.map +1 -1
  116. package/dist/teams/types.js +2 -3
  117. package/dist/teams/types.js.map +1 -1
  118. package/docs/teams.md +73 -0
  119. package/package.json +2 -1
  120. package/references/minimem/.claude/settings.json +7 -0
  121. package/references/minimem/.sudocode/issues.jsonl +18 -0
  122. package/references/minimem/.sudocode/specs.jsonl +1 -0
  123. package/references/minimem/CLAUDE.md +310 -0
  124. package/references/minimem/README.md +562 -0
  125. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
  126. package/references/minimem/claude-plugin/.mcp.json +7 -0
  127. package/references/minimem/claude-plugin/README.md +158 -0
  128. package/references/minimem/claude-plugin/commands/recall.md +47 -0
  129. package/references/minimem/claude-plugin/commands/remember.md +41 -0
  130. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
  131. package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
  132. package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
  133. package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
  134. package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
  135. package/references/minimem/media/banner.png +0 -0
  136. package/references/minimem/package-lock.json +5373 -0
  137. package/references/minimem/package.json +72 -0
  138. package/references/minimem/scripts/postbuild.js +35 -0
  139. package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
  140. package/references/minimem/src/__tests__/errors.test.ts +265 -0
  141. package/references/minimem/src/__tests__/helpers.ts +199 -0
  142. package/references/minimem/src/__tests__/internal.test.ts +407 -0
  143. package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
  144. package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
  145. package/references/minimem/src/__tests__/session.test.ts +190 -0
  146. package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
  147. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
  148. package/references/minimem/src/cli/commands/append.ts +76 -0
  149. package/references/minimem/src/cli/commands/config.ts +262 -0
  150. package/references/minimem/src/cli/commands/conflicts.ts +413 -0
  151. package/references/minimem/src/cli/commands/daemon.ts +169 -0
  152. package/references/minimem/src/cli/commands/index.ts +12 -0
  153. package/references/minimem/src/cli/commands/init.ts +88 -0
  154. package/references/minimem/src/cli/commands/mcp.ts +177 -0
  155. package/references/minimem/src/cli/commands/push-pull.ts +213 -0
  156. package/references/minimem/src/cli/commands/search.ts +158 -0
  157. package/references/minimem/src/cli/commands/status.ts +84 -0
  158. package/references/minimem/src/cli/commands/sync-init.ts +290 -0
  159. package/references/minimem/src/cli/commands/sync.ts +70 -0
  160. package/references/minimem/src/cli/commands/upsert.ts +197 -0
  161. package/references/minimem/src/cli/config.ts +584 -0
  162. package/references/minimem/src/cli/index.ts +264 -0
  163. package/references/minimem/src/cli/shared.ts +161 -0
  164. package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
  165. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
  166. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
  167. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
  168. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
  169. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
  170. package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
  171. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
  172. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
  173. package/references/minimem/src/cli/sync/central.ts +292 -0
  174. package/references/minimem/src/cli/sync/conflicts.ts +204 -0
  175. package/references/minimem/src/cli/sync/daemon.ts +407 -0
  176. package/references/minimem/src/cli/sync/detection.ts +138 -0
  177. package/references/minimem/src/cli/sync/index.ts +107 -0
  178. package/references/minimem/src/cli/sync/operations.ts +373 -0
  179. package/references/minimem/src/cli/sync/registry.ts +279 -0
  180. package/references/minimem/src/cli/sync/state.ts +355 -0
  181. package/references/minimem/src/cli/sync/validation.ts +206 -0
  182. package/references/minimem/src/cli/sync/watcher.ts +234 -0
  183. package/references/minimem/src/cli/version.ts +34 -0
  184. package/references/minimem/src/core/index.ts +9 -0
  185. package/references/minimem/src/core/indexer.ts +628 -0
  186. package/references/minimem/src/core/searcher.ts +221 -0
  187. package/references/minimem/src/db/schema.ts +183 -0
  188. package/references/minimem/src/db/sqlite-vec.ts +24 -0
  189. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
  190. package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
  191. package/references/minimem/src/embeddings/batch-openai.ts +409 -0
  192. package/references/minimem/src/embeddings/embeddings.ts +434 -0
  193. package/references/minimem/src/index.ts +109 -0
  194. package/references/minimem/src/internal.ts +299 -0
  195. package/references/minimem/src/minimem.ts +1276 -0
  196. package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
  197. package/references/minimem/src/search/graph.ts +234 -0
  198. package/references/minimem/src/search/hybrid.ts +151 -0
  199. package/references/minimem/src/search/search.ts +256 -0
  200. package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
  201. package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
  202. package/references/minimem/src/server/mcp.ts +326 -0
  203. package/references/minimem/src/server/tools.ts +720 -0
  204. package/references/minimem/src/session.ts +460 -0
  205. package/references/minimem/tsconfig.json +19 -0
  206. package/references/minimem/tsup.config.ts +26 -0
  207. package/references/minimem/vitest.config.ts +24 -0
  208. package/references/openteams/.claude/settings.json +6 -0
  209. package/references/openteams/README.md +1 -0
  210. package/references/openteams/SKILL.md +341 -0
  211. package/references/openteams/design.md +411 -0
  212. package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
  213. package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
  214. package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
  215. package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
  216. package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
  217. package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
  218. package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
  219. package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
  220. package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
  221. package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
  222. package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
  223. package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
  224. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
  225. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
  226. package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
  227. package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
  228. package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
  229. package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
  230. package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
  231. package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
  232. package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
  233. package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
  234. package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
  235. package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
  236. package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
  237. package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
  238. package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
  239. package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
  240. package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
  241. package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
  242. package/references/openteams/examples/bmad-method/team.yaml +161 -0
  243. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
  244. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
  245. package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
  246. package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
  247. package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
  248. package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
  249. package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
  250. package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
  251. package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
  252. package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
  253. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
  254. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
  255. package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
  256. package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
  257. package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
  258. package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
  259. package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
  260. package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
  261. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
  262. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
  263. package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
  264. package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
  265. package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
  266. package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
  267. package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
  268. package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
  269. package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
  270. package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
  271. package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
  272. package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
  273. package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
  274. package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
  275. package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
  276. package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
  277. package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
  278. package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
  279. package/references/openteams/examples/get-shit-done/team.yaml +154 -0
  280. package/references/openteams/package-lock.json +2181 -0
  281. package/references/openteams/package.json +48 -0
  282. package/references/openteams/schema/role.schema.json +125 -0
  283. package/references/openteams/schema/team.schema.json +284 -0
  284. package/references/openteams/src/cli/agent.ts +104 -0
  285. package/references/openteams/src/cli/cli.test.ts +381 -0
  286. package/references/openteams/src/cli/generate.ts +220 -0
  287. package/references/openteams/src/cli/message.ts +241 -0
  288. package/references/openteams/src/cli/task.ts +154 -0
  289. package/references/openteams/src/cli/team.ts +104 -0
  290. package/references/openteams/src/cli/template.ts +207 -0
  291. package/references/openteams/src/cli.ts +45 -0
  292. package/references/openteams/src/db/database.test.ts +185 -0
  293. package/references/openteams/src/db/database.ts +240 -0
  294. package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
  295. package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
  296. package/references/openteams/src/generators/package-generator.test.ts +129 -0
  297. package/references/openteams/src/generators/package-generator.ts +102 -0
  298. package/references/openteams/src/generators/skill-generator.test.ts +246 -0
  299. package/references/openteams/src/generators/skill-generator.ts +374 -0
  300. package/references/openteams/src/index.ts +104 -0
  301. package/references/openteams/src/services/agent-service.test.ts +158 -0
  302. package/references/openteams/src/services/agent-service.ts +84 -0
  303. package/references/openteams/src/services/communication-service.test.ts +455 -0
  304. package/references/openteams/src/services/communication-service.ts +371 -0
  305. package/references/openteams/src/services/message-service.test.ts +342 -0
  306. package/references/openteams/src/services/message-service.ts +203 -0
  307. package/references/openteams/src/services/task-service.test.ts +434 -0
  308. package/references/openteams/src/services/task-service.ts +239 -0
  309. package/references/openteams/src/services/team-service.test.ts +181 -0
  310. package/references/openteams/src/services/team-service.ts +139 -0
  311. package/references/openteams/src/services/template-service.test.ts +306 -0
  312. package/references/openteams/src/services/template-service.ts +182 -0
  313. package/references/openteams/src/spawner/acp-factory.ts +96 -0
  314. package/references/openteams/src/spawner/interface.ts +31 -0
  315. package/references/openteams/src/spawner/mock.test.ts +93 -0
  316. package/references/openteams/src/spawner/mock.ts +59 -0
  317. package/references/openteams/src/template/loader.test.ts +1319 -0
  318. package/references/openteams/src/template/loader.ts +698 -0
  319. package/references/openteams/src/template/types.ts +200 -0
  320. package/references/openteams/src/types.ts +205 -0
  321. package/references/openteams/tsconfig.json +18 -0
  322. package/references/openteams/vitest.config.ts +9 -0
  323. package/references/skill-tree/.claude/settings.json +6 -0
  324. package/references/skill-tree/.sudocode/issues.jsonl +11 -0
  325. package/references/skill-tree/.sudocode/specs.jsonl +1 -0
  326. package/references/skill-tree/CLAUDE.md +150 -0
  327. package/references/skill-tree/README.md +324 -0
  328. package/references/skill-tree/docs/GAPS_v1.md +221 -0
  329. package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
  330. package/references/skill-tree/docs/TODOS.md +91 -0
  331. package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
  332. package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
  333. package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
  334. package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
  335. package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
  336. package/references/skill-tree/docs/scraper/README.md +170 -0
  337. package/references/skill-tree/examples/basic-usage.ts +190 -0
  338. package/references/skill-tree/package-lock.json +1509 -0
  339. package/references/skill-tree/package.json +66 -0
  340. package/references/skill-tree/scraper/README.md +123 -0
  341. package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
  342. package/references/skill-tree/scraper/docs/PLAN.md +336 -0
  343. package/references/skill-tree/scraper/drizzle.config.ts +10 -0
  344. package/references/skill-tree/scraper/package-lock.json +6329 -0
  345. package/references/skill-tree/scraper/package.json +68 -0
  346. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
  347. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
  348. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
  349. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
  350. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
  351. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
  352. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
  353. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
  354. package/references/skill-tree/scraper/tsup.config.ts +14 -0
  355. package/references/skill-tree/scraper/vitest.config.ts +17 -0
  356. package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
  357. package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
  358. package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
  359. package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
  360. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
  361. package/references/skill-tree/test/run-all.ts +106 -0
  362. package/references/skill-tree/test/utils.ts +128 -0
  363. package/references/skill-tree/vitest.config.ts +16 -0
  364. package/src/agent/agent-manager.ts +143 -72
  365. package/src/agent/types.ts +9 -0
  366. package/src/api/__tests__/server.test.ts +203 -4
  367. package/src/api/server.ts +130 -5
  368. package/src/api/types.ts +3 -1
  369. package/src/cli/acp.ts +68 -1
  370. package/src/cli/index.ts +5 -1
  371. package/src/cli/mcp.ts +27 -13
  372. package/src/config/project-config.ts +27 -3
  373. package/src/index.ts +3 -0
  374. package/src/lifecycle/__tests__/handlers.test.ts +53 -0
  375. package/src/lifecycle/handlers/index.ts +25 -8
  376. package/src/lifecycle/types.ts +3 -0
  377. package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
  378. package/src/map/adapter/extensions/index.ts +36 -0
  379. package/src/map/adapter/extensions/streams.ts +839 -0
  380. package/src/map/adapter/index.ts +5 -0
  381. package/src/map/adapter/types.ts +8 -1
  382. package/src/mcp/mcp-server.ts +14 -3
  383. package/src/mcp/tools/done.ts +19 -0
  384. package/src/roles/builtin/coordinator.ts +2 -0
  385. package/src/roles/builtin/integrator.ts +2 -0
  386. package/src/roles/builtin/worker.ts +3 -0
  387. package/src/roles/capabilities.ts +11 -0
  388. package/src/roles/config-loader.ts +3 -2
  389. package/src/roles/types.ts +7 -0
  390. package/src/server/combined-server.ts +15 -1
  391. package/src/store/__tests__/event-store-oob.test.ts +109 -0
  392. package/src/store/event-store.ts +13 -3
  393. package/src/store/instance.ts +2 -2
  394. package/src/store/types/agents.ts +5 -0
  395. package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
  396. package/src/task/backend/opentasks/daemon-manager.ts +4 -1
  397. package/src/teams/CLAUDE.md +180 -0
  398. package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
  399. package/src/teams/__tests__/team-manager.test.ts +814 -0
  400. package/src/teams/__tests__/team-system.test.ts +1291 -8
  401. package/src/teams/index.ts +21 -3
  402. package/src/teams/seed-defaults.ts +79 -0
  403. package/src/teams/team-loader.ts +200 -234
  404. package/src/teams/team-manager.ts +387 -0
  405. package/src/teams/team-runtime.ts +590 -121
  406. package/src/teams/types.ts +99 -200
@@ -0,0 +1,521 @@
1
+ import type {
2
+ ResolvedTemplate,
3
+ ResolvedRole,
4
+ ResolvedPrompts,
5
+ SubscriptionEntry,
6
+ PeerRoute,
7
+ } from "../template/types";
8
+
9
+ export interface AgentPrompt {
10
+ role: string;
11
+ prompt: string;
12
+ }
13
+
14
+ export interface AgentPromptGeneratorOptions {
15
+ /** Team name override */
16
+ teamName?: string;
17
+ /** Additional context to prepend to every agent prompt */
18
+ preamble?: string;
19
+ }
20
+
21
+ export interface RoleSkillMd {
22
+ role: string;
23
+ content: string;
24
+ }
25
+
26
+ export interface RoleSkillMdOptions {
27
+ /** Team name override */
28
+ teamName?: string;
29
+ }
30
+
31
+ /**
32
+ * Generates per-role agent prompts in Claude sub-agent Task tool format.
33
+ *
34
+ * Each prompt includes:
35
+ * - The role identity and team context
36
+ * - The role's prompt content (from prompts/*.md or inline)
37
+ * - Communication subscriptions, emissions, and peer routes for that role
38
+ * - Spawn permissions
39
+ * - CLI commands tailored to the role
40
+ *
41
+ * These prompts are designed to be passed directly to the Task tool's
42
+ * prompt parameter when spawning Claude sub-agents.
43
+ */
44
+ export function generateAgentPrompts(
45
+ template: ResolvedTemplate,
46
+ options: AgentPromptGeneratorOptions = {}
47
+ ): AgentPrompt[] {
48
+ const teamName = options.teamName ?? template.manifest.name;
49
+ return template.manifest.roles.map((roleName) =>
50
+ generateSingleAgentPrompt(template, roleName, teamName, options.preamble)
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Generate a prompt for a single role.
56
+ */
57
+ export function generateAgentPrompt(
58
+ template: ResolvedTemplate,
59
+ roleName: string,
60
+ options: AgentPromptGeneratorOptions = {}
61
+ ): AgentPrompt {
62
+ const teamName = options.teamName ?? template.manifest.name;
63
+ return generateSingleAgentPrompt(
64
+ template,
65
+ roleName,
66
+ teamName,
67
+ options.preamble
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Generate a standalone SKILL.md for a single role.
73
+ *
74
+ * Unlike generateAgentPrompt, this produces an agent-agnostic document
75
+ * with YAML frontmatter and self-contained context. Designed to be
76
+ * readable by any AI agent, not just Claude.
77
+ */
78
+ export function generateRoleSkillMd(
79
+ template: ResolvedTemplate,
80
+ roleName: string,
81
+ options: RoleSkillMdOptions = {}
82
+ ): RoleSkillMd {
83
+ const teamName = options.teamName ?? template.manifest.name;
84
+ const m = template.manifest;
85
+ const role = template.roles.get(roleName);
86
+ const rolePrompts = template.prompts.get(roleName);
87
+
88
+ const sections: string[] = [];
89
+
90
+ // YAML frontmatter
91
+ sections.push(generateRoleFrontmatter(template, roleName, teamName));
92
+
93
+ // Identity header
94
+ sections.push(`# Role: ${roleName}`);
95
+ sections.push(
96
+ `Member of the **${teamName}** team.`
97
+ );
98
+
99
+ // Position in topology
100
+ if (m.topology.root.role === roleName) {
101
+ sections.push("Position: **root** (team lead)");
102
+ } else if (m.topology.companions?.some((c) => c.role === roleName)) {
103
+ sections.push(`Position: **companion** to root (${m.topology.root.role})`);
104
+ } else {
105
+ sections.push("Position: **spawned** agent");
106
+ }
107
+
108
+ // Role description
109
+ if (role?.description && role.description !== `Role: ${roleName}`) {
110
+ sections.push(`## Description\n\n${role.description}`);
111
+ }
112
+
113
+ // Additional prompt sections (e.g. SOUL.md) come before instructions
114
+ if (rolePrompts) {
115
+ for (const section of rolePrompts.additional) {
116
+ const heading = section.name.charAt(0).toUpperCase() + section.name.slice(1);
117
+ sections.push(`## ${heading}\n\n${section.content.trim()}`);
118
+ }
119
+ sections.push(`## Instructions\n\n${rolePrompts.primary.trim()}`);
120
+ }
121
+
122
+ // Teammates
123
+ const otherRoles = m.roles.filter((r) => r !== roleName);
124
+ if (otherRoles.length > 0) {
125
+ sections.push(`## Teammates\n\n${otherRoles.join(", ")}`);
126
+ }
127
+
128
+ // Communication — agent-agnostic
129
+ if (m.communication) {
130
+ sections.push(
131
+ generateAgnosticCommunicationSection(template, roleName, teamName)
132
+ );
133
+ }
134
+
135
+ // Spawn permissions
136
+ sections.push(generateRoleSpawnSection(template, roleName));
137
+
138
+ // CLI reference
139
+ sections.push(generateRoleCliSection(roleName, teamName, template));
140
+
141
+ return {
142
+ role: roleName,
143
+ content: sections.join("\n\n") + "\n",
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Generate standalone SKILL.md files for all roles.
149
+ */
150
+ export function generateAllRoleSkillMds(
151
+ template: ResolvedTemplate,
152
+ options: RoleSkillMdOptions = {}
153
+ ): RoleSkillMd[] {
154
+ return template.manifest.roles.map((roleName) =>
155
+ generateRoleSkillMd(template, roleName, options)
156
+ );
157
+ }
158
+
159
+ function generateRoleFrontmatter(
160
+ template: ResolvedTemplate,
161
+ roleName: string,
162
+ teamName: string
163
+ ): string {
164
+ const m = template.manifest;
165
+ const role = template.roles.get(roleName);
166
+
167
+ let position: string;
168
+ if (m.topology.root.role === roleName) {
169
+ position = "root";
170
+ } else if (m.topology.companions?.some((c) => c.role === roleName)) {
171
+ position = "companion";
172
+ } else {
173
+ position = "spawned";
174
+ }
175
+
176
+ const lines: string[] = ["---"];
177
+ lines.push(`name: ${teamName}/${roleName}`);
178
+
179
+ const desc =
180
+ role?.description && role.description !== `Role: ${roleName}`
181
+ ? role.description
182
+ : `${roleName} role in the ${teamName} team`;
183
+ lines.push(`description: ${desc}`);
184
+
185
+ lines.push(`role: ${roleName}`);
186
+ lines.push(`team: ${teamName}`);
187
+ lines.push(`position: ${position}`);
188
+
189
+ // Communication summary
190
+ const subs = m.communication?.subscriptions?.[roleName];
191
+ if (subs && subs.length > 0) {
192
+ const channels = subs.map((s) => s.channel);
193
+ lines.push(`subscribes: [${channels.join(", ")}]`);
194
+ }
195
+
196
+ const emissions = m.communication?.emissions?.[roleName];
197
+ if (emissions && emissions.length > 0) {
198
+ lines.push(`emits: [${emissions.join(", ")}]`);
199
+ }
200
+
201
+ const spawnRules = m.topology.spawn_rules?.[roleName];
202
+ if (spawnRules && spawnRules.length > 0) {
203
+ lines.push(`can_spawn: [${spawnRules.join(", ")}]`);
204
+ }
205
+
206
+ lines.push("---");
207
+ return lines.join("\n");
208
+ }
209
+
210
+ function generateAgnosticCommunicationSection(
211
+ template: ResolvedTemplate,
212
+ roleName: string,
213
+ teamName: string
214
+ ): string {
215
+ const comm = template.manifest.communication!;
216
+ const lines: string[] = ["## Communication"];
217
+
218
+ // Subscriptions
219
+ const subs = comm.subscriptions?.[roleName];
220
+ if (subs && subs.length > 0) {
221
+ lines.push("");
222
+ lines.push("### Subscriptions");
223
+ lines.push("");
224
+ for (const sub of subs) {
225
+ if (sub.signals && sub.signals.length > 0) {
226
+ lines.push(`- **${sub.channel}**: ${sub.signals.join(", ")}`);
227
+ } else {
228
+ lines.push(`- **${sub.channel}**: all signals`);
229
+ }
230
+ }
231
+ } else {
232
+ lines.push("");
233
+ lines.push("No channel subscriptions.");
234
+ }
235
+
236
+ // Emissions
237
+ const emissions = comm.emissions?.[roleName];
238
+ if (emissions && emissions.length > 0) {
239
+ lines.push("");
240
+ lines.push("### Can Emit");
241
+ lines.push("");
242
+ lines.push(emissions.join(", "));
243
+ }
244
+
245
+ // Peer routes
246
+ const peers = comm.routing?.peers;
247
+ if (peers && peers.length > 0) {
248
+ const outgoing = peers.filter((p) => p.from === roleName);
249
+ const incoming = peers.filter((p) => p.to === roleName);
250
+
251
+ if (outgoing.length > 0) {
252
+ lines.push("");
253
+ lines.push("### Peer Routes (outgoing)");
254
+ for (const route of outgoing) {
255
+ const signals = route.signals ? route.signals.join(", ") : "any";
256
+ lines.push(`- To **${route.to}** via ${route.via} (signals: ${signals})`);
257
+ }
258
+ }
259
+
260
+ if (incoming.length > 0) {
261
+ lines.push("");
262
+ lines.push("### Peer Routes (incoming)");
263
+ for (const route of incoming) {
264
+ const signals = route.signals ? route.signals.join(", ") : "any";
265
+ lines.push(`- From **${route.from}** via ${route.via} (signals: ${signals})`);
266
+ }
267
+ }
268
+ }
269
+
270
+ return lines.join("\n");
271
+ }
272
+
273
+ function generateSingleAgentPrompt(
274
+ template: ResolvedTemplate,
275
+ roleName: string,
276
+ teamName: string,
277
+ preamble?: string
278
+ ): AgentPrompt {
279
+ const m = template.manifest;
280
+ const role = template.roles.get(roleName);
281
+ const rolePrompts = template.prompts.get(roleName);
282
+
283
+ const sections: string[] = [];
284
+
285
+ // Identity header
286
+ sections.push(`# Role: ${roleName}`);
287
+ sections.push(
288
+ `You are the **${role?.displayName ?? roleName}** in the **${teamName}** team.`
289
+ );
290
+
291
+ if (preamble) {
292
+ sections.push(preamble);
293
+ }
294
+
295
+ // Role description
296
+ if (role?.description && role.description !== `Role: ${roleName}`) {
297
+ sections.push(`## Description\n\n${role.description}`);
298
+ }
299
+
300
+ // Additional prompt sections (e.g. SOUL.md) come before instructions
301
+ if (rolePrompts) {
302
+ for (const section of rolePrompts.additional) {
303
+ const heading = section.name.charAt(0).toUpperCase() + section.name.slice(1);
304
+ sections.push(`## ${heading}\n\n${section.content.trim()}`);
305
+ }
306
+ sections.push(`## Instructions\n\n${rolePrompts.primary.trim()}`);
307
+ }
308
+
309
+ // Team context
310
+ sections.push(generateTeamContextSection(template, roleName, teamName));
311
+
312
+ // Communication — what this role sees and can do
313
+ if (m.communication) {
314
+ sections.push(
315
+ generateRoleCommunicationSection(template, roleName, teamName)
316
+ );
317
+ }
318
+
319
+ // Spawn permissions
320
+ sections.push(generateRoleSpawnSection(template, roleName));
321
+
322
+ // CLI reference
323
+ sections.push(generateRoleCliSection(roleName, teamName, template));
324
+
325
+ return {
326
+ role: roleName,
327
+ prompt: sections.join("\n\n") + "\n",
328
+ };
329
+ }
330
+
331
+ function generateTeamContextSection(
332
+ template: ResolvedTemplate,
333
+ roleName: string,
334
+ teamName: string
335
+ ): string {
336
+ const m = template.manifest;
337
+ const lines: string[] = ["## Team Context"];
338
+
339
+ // Position in topology
340
+ if (m.topology.root.role === roleName) {
341
+ lines.push(
342
+ `You are the **root agent** (team lead) of the ${teamName} team.`
343
+ );
344
+ } else {
345
+ const isCompanion = m.topology.companions?.some(
346
+ (c) => c.role === roleName
347
+ );
348
+ if (isCompanion) {
349
+ lines.push(
350
+ `You are a **companion agent** to the root (${m.topology.root.role}).`
351
+ );
352
+ } else {
353
+ lines.push(
354
+ `You are a **spawned agent** under the direction of the team.`
355
+ );
356
+ }
357
+ }
358
+
359
+ // Teammates
360
+ const otherRoles = m.roles.filter((r) => r !== roleName);
361
+ if (otherRoles.length > 0) {
362
+ lines.push(`Your teammates: ${otherRoles.join(", ")}`);
363
+ }
364
+
365
+ return lines.join("\n");
366
+ }
367
+
368
+ function generateRoleCommunicationSection(
369
+ template: ResolvedTemplate,
370
+ roleName: string,
371
+ teamName: string
372
+ ): string {
373
+ const comm = template.manifest.communication!;
374
+ const lines: string[] = ["## Communication"];
375
+
376
+ // Subscriptions for this role
377
+ const subs = comm.subscriptions?.[roleName];
378
+ if (subs && subs.length > 0) {
379
+ lines.push("");
380
+ lines.push("### You receive events from:");
381
+ for (const sub of subs) {
382
+ if (sub.signals && sub.signals.length > 0) {
383
+ lines.push(`- **${sub.channel}**: ${sub.signals.join(", ")}`);
384
+ } else {
385
+ lines.push(`- **${sub.channel}**: all signals`);
386
+ }
387
+ }
388
+ lines.push("");
389
+ lines.push(
390
+ "Check for new events with:"
391
+ );
392
+ lines.push(
393
+ `\`openteams template events ${teamName} --role ${roleName}\``
394
+ );
395
+ } else {
396
+ lines.push("");
397
+ lines.push("You have no channel subscriptions.");
398
+ }
399
+
400
+ // Emissions for this role
401
+ const emissions = comm.emissions?.[roleName];
402
+ if (emissions && emissions.length > 0) {
403
+ lines.push("");
404
+ lines.push("### You can emit:");
405
+ lines.push(`- ${emissions.join(", ")}`);
406
+ lines.push("");
407
+ lines.push("Emit via the appropriate channel:");
408
+
409
+ // Map signals back to channels
410
+ if (comm.channels) {
411
+ for (const signal of emissions) {
412
+ for (const [chName, chDef] of Object.entries(comm.channels)) {
413
+ if (chDef.signals.includes(signal)) {
414
+ lines.push(
415
+ `- \`openteams template emit ${teamName} -c ${chName} -s ${signal} --sender ${roleName}\``
416
+ );
417
+ break;
418
+ }
419
+ }
420
+ }
421
+ }
422
+ }
423
+
424
+ // Peer routes involving this role
425
+ const peers = comm.routing?.peers;
426
+ if (peers && peers.length > 0) {
427
+ const outgoing = peers.filter((p) => p.from === roleName);
428
+ const incoming = peers.filter((p) => p.to === roleName);
429
+
430
+ if (outgoing.length > 0) {
431
+ lines.push("");
432
+ lines.push("### Direct routes (outgoing):");
433
+ for (const route of outgoing) {
434
+ const signals = route.signals ? route.signals.join(", ") : "any";
435
+ lines.push(
436
+ `- To **${route.to}** via ${route.via} (signals: ${signals})`
437
+ );
438
+ }
439
+ }
440
+
441
+ if (incoming.length > 0) {
442
+ lines.push("");
443
+ lines.push("### Direct routes (incoming):");
444
+ for (const route of incoming) {
445
+ const signals = route.signals ? route.signals.join(", ") : "any";
446
+ lines.push(
447
+ `- From **${route.from}** via ${route.via} (signals: ${signals})`
448
+ );
449
+ }
450
+ }
451
+ }
452
+
453
+ return lines.join("\n");
454
+ }
455
+
456
+ function generateRoleSpawnSection(
457
+ template: ResolvedTemplate,
458
+ roleName: string
459
+ ): string {
460
+ const rules = template.manifest.topology.spawn_rules;
461
+ const lines: string[] = ["## Spawn Permissions"];
462
+
463
+ if (!rules) {
464
+ lines.push("No spawn rules defined — spawning is permissive.");
465
+ return lines.join("\n");
466
+ }
467
+
468
+ const allowed = rules[roleName];
469
+ if (!allowed) {
470
+ lines.push("No spawn rules for your role — spawning is permissive.");
471
+ } else if (allowed.length === 0) {
472
+ lines.push("You **cannot** spawn other agents.");
473
+ } else {
474
+ lines.push(`You can spawn: **${allowed.join(", ")}**`);
475
+ }
476
+
477
+ return lines.join("\n");
478
+ }
479
+
480
+ function generateRoleCliSection(
481
+ roleName: string,
482
+ teamName: string,
483
+ template: ResolvedTemplate
484
+ ): string {
485
+ const lines: string[] = ["## CLI Quick Reference"];
486
+ lines.push("");
487
+ lines.push("```bash");
488
+ lines.push("# View your tasks");
489
+ lines.push(`openteams task list ${teamName} --owner <your-agent-name>`);
490
+ lines.push("");
491
+ lines.push("# Claim a pending task");
492
+ lines.push(
493
+ `openteams task update ${teamName} <task-id> --owner <your-agent-name> --status in_progress`
494
+ );
495
+ lines.push("");
496
+ lines.push("# Mark task complete");
497
+ lines.push(
498
+ `openteams task update ${teamName} <task-id> --status completed`
499
+ );
500
+ lines.push("");
501
+ lines.push("# Check messages");
502
+ lines.push(
503
+ `openteams message list ${teamName} --agent <your-agent-name>`
504
+ );
505
+ lines.push("");
506
+ lines.push("# Send a message");
507
+ lines.push(
508
+ `openteams message send ${teamName} --from <your-agent-name> --to <recipient> --content "..." --summary "..."`
509
+ );
510
+
511
+ if (template.manifest.communication?.channels) {
512
+ lines.push("");
513
+ lines.push("# Check events for your role");
514
+ lines.push(
515
+ `openteams template events ${teamName} --role ${roleName}`
516
+ );
517
+ }
518
+
519
+ lines.push("```");
520
+ return lines.join("\n");
521
+ }
@@ -0,0 +1,129 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import os from "os";
5
+ import { TemplateLoader } from "../template/loader";
6
+ import { generatePackage } from "./package-generator";
7
+ import type { TeamManifest, ResolvedTemplate } from "../template/types";
8
+
9
+ function makeFullTemplate(): ResolvedTemplate {
10
+ const manifest: TeamManifest = {
11
+ name: "self-driving",
12
+ description: "Autonomous codebase development",
13
+ version: 1,
14
+ roles: ["planner", "grinder", "judge"],
15
+ topology: {
16
+ root: {
17
+ role: "planner",
18
+ config: { model: "sonnet" },
19
+ },
20
+ companions: [{ role: "judge" }],
21
+ spawn_rules: {
22
+ planner: ["grinder", "planner"],
23
+ judge: [],
24
+ grinder: [],
25
+ },
26
+ },
27
+ communication: {
28
+ channels: {
29
+ task_updates: {
30
+ description: "Task lifecycle events",
31
+ signals: ["TASK_CREATED", "TASK_COMPLETED", "TASK_FAILED"],
32
+ },
33
+ },
34
+ subscriptions: {
35
+ planner: [{ channel: "task_updates" }],
36
+ },
37
+ emissions: {
38
+ planner: ["TASK_CREATED"],
39
+ },
40
+ },
41
+ };
42
+ return TemplateLoader.loadFromManifest(manifest);
43
+ }
44
+
45
+ describe("generatePackage", () => {
46
+ let tmpDir: string;
47
+
48
+ beforeEach(() => {
49
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "openteams-pkg-test-"));
50
+ });
51
+
52
+ afterEach(() => {
53
+ fs.rmSync(tmpDir, { recursive: true, force: true });
54
+ });
55
+
56
+ it("creates the output directory", () => {
57
+ const outputDir = path.join(tmpDir, "output");
58
+ generatePackage(makeFullTemplate(), { outputDir });
59
+ expect(fs.existsSync(outputDir)).toBe(true);
60
+ });
61
+
62
+ it("generates a top-level SKILL.md catalog", () => {
63
+ const outputDir = path.join(tmpDir, "output");
64
+ const result = generatePackage(makeFullTemplate(), { outputDir });
65
+
66
+ expect(result.catalogPath).toBe(path.join(outputDir, "SKILL.md"));
67
+ expect(fs.existsSync(result.catalogPath)).toBe(true);
68
+
69
+ const content = fs.readFileSync(result.catalogPath, "utf-8");
70
+ expect(content).toContain("# Team: self-driving");
71
+ expect(content).toContain("## Roles");
72
+ expect(content).toContain("| planner |");
73
+ expect(content).toContain("## Loading a role");
74
+ });
75
+
76
+ it("generates per-role SKILL.md files", () => {
77
+ const outputDir = path.join(tmpDir, "output");
78
+ const result = generatePackage(makeFullTemplate(), { outputDir });
79
+
80
+ expect(result.rolePaths).toHaveLength(3);
81
+
82
+ for (const rp of result.rolePaths) {
83
+ expect(fs.existsSync(rp.path)).toBe(true);
84
+ const content = fs.readFileSync(rp.path, "utf-8");
85
+ expect(content).toMatch(/^---\n/);
86
+ expect(content).toContain(`role: ${rp.role}`);
87
+ expect(content).toContain(`# Role: ${rp.role}`);
88
+ }
89
+ });
90
+
91
+ it("places role files in roles/<name>/SKILL.md", () => {
92
+ const outputDir = path.join(tmpDir, "output");
93
+ const result = generatePackage(makeFullTemplate(), { outputDir });
94
+
95
+ const plannerPath = result.rolePaths.find(
96
+ (r) => r.role === "planner"
97
+ )!.path;
98
+ expect(plannerPath).toBe(
99
+ path.join(outputDir, "roles", "planner", "SKILL.md")
100
+ );
101
+ });
102
+
103
+ it("respects team name override", () => {
104
+ const outputDir = path.join(tmpDir, "output");
105
+ generatePackage(makeFullTemplate(), {
106
+ outputDir,
107
+ teamName: "my-project",
108
+ });
109
+
110
+ const catalog = fs.readFileSync(
111
+ path.join(outputDir, "SKILL.md"),
112
+ "utf-8"
113
+ );
114
+ expect(catalog).toContain("# Team: my-project");
115
+
116
+ const roleMd = fs.readFileSync(
117
+ path.join(outputDir, "roles", "planner", "SKILL.md"),
118
+ "utf-8"
119
+ );
120
+ expect(roleMd).toContain("team: my-project");
121
+ });
122
+
123
+ it("returns null manifestPath when no source exists", () => {
124
+ const outputDir = path.join(tmpDir, "output");
125
+ const result = generatePackage(makeFullTemplate(), { outputDir });
126
+ // loadFromManifest sets sourcePath to "", so no team.yaml to copy
127
+ expect(result.manifestPath).toBeNull();
128
+ });
129
+ });