macro-agent 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (660) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/.sudocode/issues.jsonl +28 -0
  3. package/.sudocode/specs.jsonl +8 -0
  4. package/CLAUDE.md +25 -17
  5. package/README.md +11 -29
  6. package/dist/acp/macro-agent.d.ts +15 -0
  7. package/dist/acp/macro-agent.d.ts.map +1 -1
  8. package/dist/acp/macro-agent.js +131 -35
  9. package/dist/acp/macro-agent.js.map +1 -1
  10. package/dist/acp/types.d.ts +32 -1
  11. package/dist/acp/types.d.ts.map +1 -1
  12. package/dist/acp/types.js.map +1 -1
  13. package/dist/agent/agent-manager.d.ts +65 -1
  14. package/dist/agent/agent-manager.d.ts.map +1 -1
  15. package/dist/agent/agent-manager.js +544 -200
  16. package/dist/agent/agent-manager.js.map +1 -1
  17. package/dist/agent/types.d.ts +8 -1
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/agent/types.js.map +1 -1
  20. package/dist/api/server.d.ts +8 -1
  21. package/dist/api/server.d.ts.map +1 -1
  22. package/dist/api/server.js +136 -8
  23. package/dist/api/server.js.map +1 -1
  24. package/dist/api/types.d.ts +1 -1
  25. package/dist/api/types.d.ts.map +1 -1
  26. package/dist/auth/index.d.ts +2 -0
  27. package/dist/auth/index.d.ts.map +1 -0
  28. package/dist/auth/index.js +2 -0
  29. package/dist/auth/index.js.map +1 -0
  30. package/dist/auth/token.d.ts +41 -0
  31. package/dist/auth/token.d.ts.map +1 -0
  32. package/dist/auth/token.js +73 -0
  33. package/dist/auth/token.js.map +1 -0
  34. package/dist/cli/acp.d.ts +2 -23
  35. package/dist/cli/acp.d.ts.map +1 -1
  36. package/dist/cli/acp.js +197 -61
  37. package/dist/cli/acp.js.map +1 -1
  38. package/dist/cli/index.js +152 -16
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/mcp.d.ts +6 -0
  41. package/dist/cli/mcp.d.ts.map +1 -1
  42. package/dist/cli/mcp.js +279 -173
  43. package/dist/cli/mcp.js.map +1 -1
  44. package/dist/cli/parse-args.d.ts +20 -0
  45. package/dist/cli/parse-args.d.ts.map +1 -0
  46. package/dist/cli/parse-args.js +43 -0
  47. package/dist/cli/parse-args.js.map +1 -0
  48. package/dist/cli/stable-instance-id.d.ts +8 -0
  49. package/dist/cli/stable-instance-id.d.ts.map +1 -0
  50. package/dist/cli/stable-instance-id.js +14 -0
  51. package/dist/cli/stable-instance-id.js.map +1 -0
  52. package/dist/config/project-config.d.ts +85 -7
  53. package/dist/config/project-config.d.ts.map +1 -1
  54. package/dist/config/project-config.js +133 -20
  55. package/dist/config/project-config.js.map +1 -1
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/lifecycle/handlers/index.d.ts +7 -3
  61. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  62. package/dist/lifecycle/handlers/index.js +25 -8
  63. package/dist/lifecycle/handlers/index.js.map +1 -1
  64. package/dist/lifecycle/types.d.ts +2 -0
  65. package/dist/lifecycle/types.d.ts.map +1 -1
  66. package/dist/lifecycle/types.js.map +1 -1
  67. package/dist/map/adapter/acp-over-map.d.ts +17 -0
  68. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  69. package/dist/map/adapter/acp-over-map.js +384 -23
  70. package/dist/map/adapter/acp-over-map.js.map +1 -1
  71. package/dist/map/adapter/connection-manager.d.ts.map +1 -1
  72. package/dist/map/adapter/connection-manager.js +3 -0
  73. package/dist/map/adapter/connection-manager.js.map +1 -1
  74. package/dist/map/adapter/event-log.d.ts +87 -0
  75. package/dist/map/adapter/event-log.d.ts.map +1 -0
  76. package/dist/map/adapter/event-log.js +122 -0
  77. package/dist/map/adapter/event-log.js.map +1 -0
  78. package/dist/map/adapter/event-translator.js +6 -6
  79. package/dist/map/adapter/event-translator.js.map +1 -1
  80. package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
  81. package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
  82. package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
  83. package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
  84. package/dist/map/adapter/extensions/index.d.ts +13 -1
  85. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  86. package/dist/map/adapter/extensions/index.js +61 -0
  87. package/dist/map/adapter/extensions/index.js.map +1 -1
  88. package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
  89. package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
  91. package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
  92. package/dist/map/adapter/extensions/rename.d.ts +29 -0
  93. package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
  94. package/dist/map/adapter/extensions/rename.js +49 -0
  95. package/dist/map/adapter/extensions/rename.js.map +1 -0
  96. package/dist/map/adapter/extensions/streams.d.ts +95 -0
  97. package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/streams.js +515 -0
  99. package/dist/map/adapter/extensions/streams.js.map +1 -0
  100. package/dist/map/adapter/extensions/task.d.ts.map +1 -1
  101. package/dist/map/adapter/extensions/task.js +10 -0
  102. package/dist/map/adapter/extensions/task.js.map +1 -1
  103. package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
  104. package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
  105. package/dist/map/adapter/extensions/update-metadata.js +67 -0
  106. package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
  107. package/dist/map/adapter/index.d.ts +2 -1
  108. package/dist/map/adapter/index.d.ts.map +1 -1
  109. package/dist/map/adapter/index.js +10 -2
  110. package/dist/map/adapter/index.js.map +1 -1
  111. package/dist/map/adapter/interface.d.ts +2 -0
  112. package/dist/map/adapter/interface.d.ts.map +1 -1
  113. package/dist/map/adapter/map-adapter.d.ts +3 -0
  114. package/dist/map/adapter/map-adapter.d.ts.map +1 -1
  115. package/dist/map/adapter/map-adapter.js +258 -35
  116. package/dist/map/adapter/map-adapter.js.map +1 -1
  117. package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
  118. package/dist/map/adapter/subscription-manager.js +5 -1
  119. package/dist/map/adapter/subscription-manager.js.map +1 -1
  120. package/dist/map/adapter/types.d.ts +3 -1
  121. package/dist/map/adapter/types.d.ts.map +1 -1
  122. package/dist/mcp/map-client.d.ts +39 -0
  123. package/dist/mcp/map-client.d.ts.map +1 -0
  124. package/dist/mcp/map-client.js +129 -0
  125. package/dist/mcp/map-client.js.map +1 -0
  126. package/dist/mcp/mcp-server.d.ts +16 -0
  127. package/dist/mcp/mcp-server.d.ts.map +1 -1
  128. package/dist/mcp/mcp-server.js +125 -88
  129. package/dist/mcp/mcp-server.js.map +1 -1
  130. package/dist/mcp/tools/done.d.ts.map +1 -1
  131. package/dist/mcp/tools/done.js +18 -0
  132. package/dist/mcp/tools/done.js.map +1 -1
  133. package/dist/mcp/types.d.ts +9 -1
  134. package/dist/mcp/types.d.ts.map +1 -1
  135. package/dist/mcp/types.js.map +1 -1
  136. package/dist/metrics/metrics.js +1 -1
  137. package/dist/metrics/metrics.js.map +1 -1
  138. package/dist/roles/builtin/coordinator.d.ts.map +1 -1
  139. package/dist/roles/builtin/coordinator.js +2 -1
  140. package/dist/roles/builtin/coordinator.js.map +1 -1
  141. package/dist/roles/builtin/integrator.d.ts.map +1 -1
  142. package/dist/roles/builtin/integrator.js +2 -1
  143. package/dist/roles/builtin/integrator.js.map +1 -1
  144. package/dist/roles/builtin/worker.d.ts.map +1 -1
  145. package/dist/roles/builtin/worker.js +3 -1
  146. package/dist/roles/builtin/worker.js.map +1 -1
  147. package/dist/roles/capabilities.d.ts +9 -1
  148. package/dist/roles/capabilities.d.ts.map +1 -1
  149. package/dist/roles/capabilities.js +27 -7
  150. package/dist/roles/capabilities.js.map +1 -1
  151. package/dist/roles/config-loader.d.ts +6 -6
  152. package/dist/roles/config-loader.d.ts.map +1 -1
  153. package/dist/roles/config-loader.js +8 -7
  154. package/dist/roles/config-loader.js.map +1 -1
  155. package/dist/roles/registry.d.ts +2 -2
  156. package/dist/roles/registry.js +2 -2
  157. package/dist/roles/types.d.ts +3 -1
  158. package/dist/roles/types.d.ts.map +1 -1
  159. package/dist/server/combined-server.d.ts +28 -1
  160. package/dist/server/combined-server.d.ts.map +1 -1
  161. package/dist/server/combined-server.js +111 -8
  162. package/dist/server/combined-server.js.map +1 -1
  163. package/dist/store/event-store.d.ts +2 -1
  164. package/dist/store/event-store.d.ts.map +1 -1
  165. package/dist/store/event-store.js +80 -24
  166. package/dist/store/event-store.js.map +1 -1
  167. package/dist/store/instance.d.ts +1 -1
  168. package/dist/store/instance.d.ts.map +1 -1
  169. package/dist/store/instance.js +2 -2
  170. package/dist/store/instance.js.map +1 -1
  171. package/dist/store/types/agents.d.ts +23 -0
  172. package/dist/store/types/agents.d.ts.map +1 -1
  173. package/dist/store/types/events.d.ts +1 -1
  174. package/dist/store/types/events.d.ts.map +1 -1
  175. package/dist/task/backend/index.d.ts +47 -29
  176. package/dist/task/backend/index.d.ts.map +1 -1
  177. package/dist/task/backend/index.js +109 -71
  178. package/dist/task/backend/index.js.map +1 -1
  179. package/dist/task/backend/memory.d.ts +1 -0
  180. package/dist/task/backend/memory.d.ts.map +1 -1
  181. package/dist/task/backend/memory.js +3 -0
  182. package/dist/task/backend/memory.js.map +1 -1
  183. package/dist/task/backend/opentasks/backend.d.ts +140 -0
  184. package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
  185. package/dist/task/backend/opentasks/backend.js +1023 -0
  186. package/dist/task/backend/opentasks/backend.js.map +1 -0
  187. package/dist/task/backend/opentasks/client.d.ts +337 -0
  188. package/dist/task/backend/opentasks/client.d.ts.map +1 -0
  189. package/dist/task/backend/opentasks/client.js +225 -0
  190. package/dist/task/backend/opentasks/client.js.map +1 -0
  191. package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
  192. package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
  193. package/dist/task/backend/opentasks/daemon-manager.js +195 -0
  194. package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
  195. package/dist/task/backend/opentasks/index.d.ts +21 -0
  196. package/dist/task/backend/opentasks/index.d.ts.map +1 -0
  197. package/dist/task/backend/opentasks/index.js +21 -0
  198. package/dist/task/backend/opentasks/index.js.map +1 -0
  199. package/dist/task/backend/opentasks/mapping.d.ts +48 -0
  200. package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
  201. package/dist/task/backend/opentasks/mapping.js +77 -0
  202. package/dist/task/backend/opentasks/mapping.js.map +1 -0
  203. package/dist/task/backend/types.d.ts +33 -53
  204. package/dist/task/backend/types.d.ts.map +1 -1
  205. package/dist/task/backend/types.js +7 -11
  206. package/dist/task/backend/types.js.map +1 -1
  207. package/dist/task/backend/unified-tool-provider.d.ts +57 -0
  208. package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
  209. package/dist/task/backend/unified-tool-provider.js +623 -0
  210. package/dist/task/backend/unified-tool-provider.js.map +1 -0
  211. package/dist/teams/index.d.ts +3 -1
  212. package/dist/teams/index.d.ts.map +1 -1
  213. package/dist/teams/index.js +2 -0
  214. package/dist/teams/index.js.map +1 -1
  215. package/dist/teams/seed-defaults.d.ts +20 -0
  216. package/dist/teams/seed-defaults.d.ts.map +1 -0
  217. package/dist/teams/seed-defaults.js +71 -0
  218. package/dist/teams/seed-defaults.js.map +1 -0
  219. package/dist/teams/team-loader.d.ts +7 -3
  220. package/dist/teams/team-loader.d.ts.map +1 -1
  221. package/dist/teams/team-loader.js +156 -164
  222. package/dist/teams/team-loader.js.map +1 -1
  223. package/dist/teams/team-manager.d.ts +112 -0
  224. package/dist/teams/team-manager.d.ts.map +1 -0
  225. package/dist/teams/team-manager.js +305 -0
  226. package/dist/teams/team-manager.js.map +1 -0
  227. package/dist/teams/team-runtime.d.ts +125 -19
  228. package/dist/teams/team-runtime.d.ts.map +1 -1
  229. package/dist/teams/team-runtime.js +529 -119
  230. package/dist/teams/team-runtime.js.map +1 -1
  231. package/dist/teams/types.d.ts +41 -151
  232. package/dist/teams/types.d.ts.map +1 -1
  233. package/dist/teams/types.js +2 -3
  234. package/dist/teams/types.js.map +1 -1
  235. package/docs/architecture.md +7 -6
  236. package/docs/configuration.md +26 -62
  237. package/docs/implementation-details.md +5 -5
  238. package/docs/implementation-summary.md +17 -17
  239. package/docs/plan-self-driving-support.md +4 -4
  240. package/docs/spec-self-driving-support.md +10 -10
  241. package/docs/team-templates.md +2 -2
  242. package/docs/teams.md +76 -3
  243. package/docs/troubleshooting.md +10 -11
  244. package/package.json +7 -4
  245. package/references/minimem/.claude/settings.json +7 -0
  246. package/references/minimem/.sudocode/issues.jsonl +18 -0
  247. package/references/minimem/.sudocode/specs.jsonl +1 -0
  248. package/references/minimem/CLAUDE.md +310 -0
  249. package/references/minimem/README.md +562 -0
  250. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
  251. package/references/minimem/claude-plugin/.mcp.json +7 -0
  252. package/references/minimem/claude-plugin/README.md +158 -0
  253. package/references/minimem/claude-plugin/commands/recall.md +47 -0
  254. package/references/minimem/claude-plugin/commands/remember.md +41 -0
  255. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
  256. package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
  257. package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
  258. package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
  259. package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
  260. package/references/minimem/media/banner.png +0 -0
  261. package/references/minimem/package-lock.json +5373 -0
  262. package/references/minimem/package.json +72 -0
  263. package/references/minimem/scripts/postbuild.js +35 -0
  264. package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
  265. package/references/minimem/src/__tests__/errors.test.ts +265 -0
  266. package/references/minimem/src/__tests__/helpers.ts +199 -0
  267. package/references/minimem/src/__tests__/internal.test.ts +407 -0
  268. package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
  269. package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
  270. package/references/minimem/src/__tests__/session.test.ts +190 -0
  271. package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
  272. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
  273. package/references/minimem/src/cli/commands/append.ts +76 -0
  274. package/references/minimem/src/cli/commands/config.ts +262 -0
  275. package/references/minimem/src/cli/commands/conflicts.ts +413 -0
  276. package/references/minimem/src/cli/commands/daemon.ts +169 -0
  277. package/references/minimem/src/cli/commands/index.ts +12 -0
  278. package/references/minimem/src/cli/commands/init.ts +88 -0
  279. package/references/minimem/src/cli/commands/mcp.ts +177 -0
  280. package/references/minimem/src/cli/commands/push-pull.ts +213 -0
  281. package/references/minimem/src/cli/commands/search.ts +158 -0
  282. package/references/minimem/src/cli/commands/status.ts +84 -0
  283. package/references/minimem/src/cli/commands/sync-init.ts +290 -0
  284. package/references/minimem/src/cli/commands/sync.ts +70 -0
  285. package/references/minimem/src/cli/commands/upsert.ts +197 -0
  286. package/references/minimem/src/cli/config.ts +584 -0
  287. package/references/minimem/src/cli/index.ts +264 -0
  288. package/references/minimem/src/cli/shared.ts +161 -0
  289. package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
  290. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
  291. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
  292. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
  293. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
  294. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
  295. package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
  296. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
  297. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
  298. package/references/minimem/src/cli/sync/central.ts +292 -0
  299. package/references/minimem/src/cli/sync/conflicts.ts +204 -0
  300. package/references/minimem/src/cli/sync/daemon.ts +407 -0
  301. package/references/minimem/src/cli/sync/detection.ts +138 -0
  302. package/references/minimem/src/cli/sync/index.ts +107 -0
  303. package/references/minimem/src/cli/sync/operations.ts +373 -0
  304. package/references/minimem/src/cli/sync/registry.ts +279 -0
  305. package/references/minimem/src/cli/sync/state.ts +355 -0
  306. package/references/minimem/src/cli/sync/validation.ts +206 -0
  307. package/references/minimem/src/cli/sync/watcher.ts +234 -0
  308. package/references/minimem/src/cli/version.ts +34 -0
  309. package/references/minimem/src/core/index.ts +9 -0
  310. package/references/minimem/src/core/indexer.ts +628 -0
  311. package/references/minimem/src/core/searcher.ts +221 -0
  312. package/references/minimem/src/db/schema.ts +183 -0
  313. package/references/minimem/src/db/sqlite-vec.ts +24 -0
  314. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
  315. package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
  316. package/references/minimem/src/embeddings/batch-openai.ts +409 -0
  317. package/references/minimem/src/embeddings/embeddings.ts +434 -0
  318. package/references/minimem/src/index.ts +109 -0
  319. package/references/minimem/src/internal.ts +299 -0
  320. package/references/minimem/src/minimem.ts +1276 -0
  321. package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
  322. package/references/minimem/src/search/graph.ts +234 -0
  323. package/references/minimem/src/search/hybrid.ts +151 -0
  324. package/references/minimem/src/search/search.ts +256 -0
  325. package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
  326. package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
  327. package/references/minimem/src/server/mcp.ts +326 -0
  328. package/references/minimem/src/server/tools.ts +720 -0
  329. package/references/minimem/src/session.ts +460 -0
  330. package/references/minimem/tsconfig.json +19 -0
  331. package/references/minimem/tsup.config.ts +26 -0
  332. package/references/minimem/vitest.config.ts +24 -0
  333. package/references/openteams/.claude/settings.json +6 -0
  334. package/references/openteams/README.md +1 -0
  335. package/references/openteams/SKILL.md +341 -0
  336. package/references/openteams/design.md +411 -0
  337. package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
  338. package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
  339. package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
  340. package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
  341. package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
  342. package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
  343. package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
  344. package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
  345. package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
  346. package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
  347. package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
  348. package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
  349. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
  350. package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
  351. package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
  352. package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
  353. package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
  354. package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
  355. package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
  356. package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
  357. package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
  358. package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
  359. package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
  360. package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
  361. package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
  362. package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
  363. package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
  364. package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
  365. package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
  366. package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
  367. package/references/openteams/examples/bmad-method/team.yaml +161 -0
  368. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
  369. package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
  370. package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
  371. package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
  372. package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
  373. package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
  374. package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
  375. package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
  376. package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
  377. package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
  378. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
  379. package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
  380. package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
  381. package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
  382. package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
  383. package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
  384. package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
  385. package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
  386. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
  387. package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
  388. package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
  389. package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
  390. package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
  391. package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
  392. package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
  393. package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
  394. package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
  395. package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
  396. package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
  397. package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
  398. package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
  399. package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
  400. package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
  401. package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
  402. package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
  403. package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
  404. package/references/openteams/examples/get-shit-done/team.yaml +154 -0
  405. package/references/openteams/package-lock.json +2181 -0
  406. package/references/openteams/package.json +48 -0
  407. package/references/openteams/schema/role.schema.json +125 -0
  408. package/references/openteams/schema/team.schema.json +284 -0
  409. package/references/openteams/src/cli/agent.ts +104 -0
  410. package/references/openteams/src/cli/cli.test.ts +381 -0
  411. package/references/openteams/src/cli/generate.ts +220 -0
  412. package/references/openteams/src/cli/message.ts +241 -0
  413. package/references/openteams/src/cli/task.ts +154 -0
  414. package/references/openteams/src/cli/team.ts +104 -0
  415. package/references/openteams/src/cli/template.ts +207 -0
  416. package/references/openteams/src/cli.ts +45 -0
  417. package/references/openteams/src/db/database.test.ts +185 -0
  418. package/references/openteams/src/db/database.ts +240 -0
  419. package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
  420. package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
  421. package/references/openteams/src/generators/package-generator.test.ts +129 -0
  422. package/references/openteams/src/generators/package-generator.ts +102 -0
  423. package/references/openteams/src/generators/skill-generator.test.ts +246 -0
  424. package/references/openteams/src/generators/skill-generator.ts +374 -0
  425. package/references/openteams/src/index.ts +104 -0
  426. package/references/openteams/src/services/agent-service.test.ts +158 -0
  427. package/references/openteams/src/services/agent-service.ts +84 -0
  428. package/references/openteams/src/services/communication-service.test.ts +455 -0
  429. package/references/openteams/src/services/communication-service.ts +371 -0
  430. package/references/openteams/src/services/message-service.test.ts +342 -0
  431. package/references/openteams/src/services/message-service.ts +203 -0
  432. package/references/openteams/src/services/task-service.test.ts +434 -0
  433. package/references/openteams/src/services/task-service.ts +239 -0
  434. package/references/openteams/src/services/team-service.test.ts +181 -0
  435. package/references/openteams/src/services/team-service.ts +139 -0
  436. package/references/openteams/src/services/template-service.test.ts +306 -0
  437. package/references/openteams/src/services/template-service.ts +182 -0
  438. package/references/openteams/src/spawner/acp-factory.ts +96 -0
  439. package/references/openteams/src/spawner/interface.ts +31 -0
  440. package/references/openteams/src/spawner/mock.test.ts +93 -0
  441. package/references/openteams/src/spawner/mock.ts +59 -0
  442. package/references/openteams/src/template/loader.test.ts +1319 -0
  443. package/references/openteams/src/template/loader.ts +698 -0
  444. package/references/openteams/src/template/types.ts +200 -0
  445. package/references/openteams/src/types.ts +205 -0
  446. package/references/openteams/tsconfig.json +18 -0
  447. package/references/openteams/vitest.config.ts +9 -0
  448. package/references/skill-tree/.claude/settings.json +6 -0
  449. package/references/skill-tree/.sudocode/issues.jsonl +11 -0
  450. package/references/skill-tree/.sudocode/specs.jsonl +1 -0
  451. package/references/skill-tree/CLAUDE.md +150 -0
  452. package/references/skill-tree/README.md +324 -0
  453. package/references/skill-tree/docs/GAPS_v1.md +221 -0
  454. package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
  455. package/references/skill-tree/docs/TODOS.md +91 -0
  456. package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
  457. package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
  458. package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
  459. package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
  460. package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
  461. package/references/skill-tree/docs/scraper/README.md +170 -0
  462. package/references/skill-tree/examples/basic-usage.ts +190 -0
  463. package/references/skill-tree/package-lock.json +1509 -0
  464. package/references/skill-tree/package.json +66 -0
  465. package/references/skill-tree/scraper/README.md +123 -0
  466. package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
  467. package/references/skill-tree/scraper/docs/PLAN.md +336 -0
  468. package/references/skill-tree/scraper/drizzle.config.ts +10 -0
  469. package/references/skill-tree/scraper/package-lock.json +6329 -0
  470. package/references/skill-tree/scraper/package.json +68 -0
  471. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
  472. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
  473. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
  474. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
  475. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
  476. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
  477. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
  478. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
  479. package/references/skill-tree/scraper/tsup.config.ts +14 -0
  480. package/references/skill-tree/scraper/vitest.config.ts +17 -0
  481. package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
  482. package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
  483. package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
  484. package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
  485. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
  486. package/references/skill-tree/test/run-all.ts +106 -0
  487. package/references/skill-tree/test/utils.ts +128 -0
  488. package/references/skill-tree/vitest.config.ts +16 -0
  489. package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
  490. package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
  491. package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
  492. package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
  493. package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
  494. package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
  495. package/src/acp/__tests__/integration.test.ts +56 -31
  496. package/src/acp/__tests__/macro-agent.test.ts +16 -7
  497. package/src/acp/macro-agent.ts +170 -36
  498. package/src/acp/types.ts +46 -1
  499. package/src/agent/__tests__/agent-manager.test.ts +228 -2
  500. package/src/agent/agent-manager.ts +809 -285
  501. package/src/agent/types.ts +12 -1
  502. package/src/api/__tests__/server.test.ts +203 -4
  503. package/src/api/server.ts +169 -10
  504. package/src/api/types.ts +3 -1
  505. package/src/auth/__tests__/token.test.ts +100 -0
  506. package/src/auth/index.ts +1 -0
  507. package/src/auth/token.ts +82 -0
  508. package/src/cli/__tests__/acp.test.ts +1 -1
  509. package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
  510. package/src/cli/acp.ts +197 -72
  511. package/src/cli/index.ts +125 -15
  512. package/src/cli/mcp.ts +315 -197
  513. package/src/cli/parse-args.ts +54 -0
  514. package/src/cli/stable-instance-id.ts +14 -0
  515. package/src/config/project-config.ts +214 -27
  516. package/src/index.ts +3 -0
  517. package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
  518. package/src/lifecycle/__tests__/handlers.test.ts +53 -0
  519. package/src/lifecycle/handlers/index.ts +25 -8
  520. package/src/lifecycle/types.ts +3 -0
  521. package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
  522. package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
  523. package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
  524. package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
  525. package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
  526. package/src/map/adapter/__tests__/event-log.test.ts +527 -0
  527. package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
  528. package/src/map/adapter/__tests__/extensions.test.ts +408 -0
  529. package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
  530. package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
  531. package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
  532. package/src/map/adapter/__tests__/stream-extensions.test.ts +494 -0
  533. package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
  534. package/src/map/adapter/acp-over-map.ts +678 -66
  535. package/src/map/adapter/connection-manager.ts +3 -0
  536. package/src/map/adapter/event-log.ts +208 -0
  537. package/src/map/adapter/event-translator.ts +6 -6
  538. package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
  539. package/src/map/adapter/extensions/index.ts +96 -0
  540. package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
  541. package/src/map/adapter/extensions/streams.ts +839 -0
  542. package/src/map/adapter/extensions/task.ts +11 -0
  543. package/src/map/adapter/extensions/update-metadata.ts +126 -0
  544. package/src/map/adapter/index.ts +33 -0
  545. package/src/map/adapter/interface.ts +2 -0
  546. package/src/map/adapter/map-adapter.ts +312 -47
  547. package/src/map/adapter/subscription-manager.ts +5 -1
  548. package/src/map/adapter/types.ts +10 -1
  549. package/src/mcp/__tests__/map-client.test.ts +386 -0
  550. package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
  551. package/src/mcp/__tests__/mcp-server.test.ts +100 -1
  552. package/src/mcp/map-client.ts +177 -0
  553. package/src/mcp/mcp-server.ts +205 -103
  554. package/src/mcp/tools/done.ts +19 -0
  555. package/src/mcp/types.ts +6 -1
  556. package/src/metrics/metrics.ts +1 -1
  557. package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
  558. package/src/roles/__tests__/config-loader.test.ts +7 -7
  559. package/src/roles/builtin/coordinator.ts +2 -0
  560. package/src/roles/builtin/integrator.ts +2 -0
  561. package/src/roles/builtin/worker.ts +3 -0
  562. package/src/roles/capabilities.ts +28 -7
  563. package/src/roles/config-loader.ts +8 -7
  564. package/src/roles/registry.ts +2 -2
  565. package/src/roles/types.ts +7 -0
  566. package/src/server/__tests__/combined-server.test.ts +94 -21
  567. package/src/server/combined-server.ts +203 -33
  568. package/src/steering/__tests__/steering-integration.test.ts +1 -1
  569. package/src/store/__tests__/event-store-oob.test.ts +109 -0
  570. package/src/store/__tests__/event-store.test.ts +196 -1
  571. package/src/store/__tests__/instance.test.ts +3 -3
  572. package/src/store/event-store.ts +92 -23
  573. package/src/store/instance.ts +2 -2
  574. package/src/store/types/agents.ts +20 -0
  575. package/src/store/types/events.ts +1 -1
  576. package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
  577. package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
  578. package/src/task/backend/__tests__/memory-pull-mode.test.ts +153 -0
  579. package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
  580. package/src/task/backend/index.ts +156 -106
  581. package/src/task/backend/memory.ts +4 -0
  582. package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
  583. package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
  584. package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
  585. package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
  586. package/src/task/backend/opentasks/backend.ts +1323 -0
  587. package/src/task/backend/opentasks/client.ts +652 -0
  588. package/src/task/backend/opentasks/daemon-manager.ts +256 -0
  589. package/src/task/backend/opentasks/index.ts +69 -0
  590. package/src/task/backend/opentasks/mapping.ts +94 -0
  591. package/src/task/backend/types.ts +42 -66
  592. package/src/task/backend/unified-tool-provider.ts +779 -0
  593. package/src/teams/CLAUDE.md +180 -0
  594. package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
  595. package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
  596. package/src/teams/__tests__/team-manager.test.ts +814 -0
  597. package/src/teams/__tests__/team-system.test.ts +1291 -8
  598. package/src/teams/index.ts +21 -3
  599. package/src/teams/seed-defaults.ts +79 -0
  600. package/src/teams/team-loader.ts +202 -236
  601. package/src/teams/team-manager.ts +387 -0
  602. package/src/teams/team-runtime.ts +592 -121
  603. package/src/teams/types.ts +99 -200
  604. package/test_fixtures/README.md +2 -3
  605. package/test_fixtures/fixtures/index.ts +0 -3
  606. package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
  607. package/test_fixtures/fixtures/repos/index.ts +1 -3
  608. package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
  609. package/test_fixtures/fixtures/repos/types.ts +0 -11
  610. package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
  611. package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
  612. package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
  613. package/vitest.config.ts +1 -1
  614. package/vitest.e2e.config.ts +1 -1
  615. package/vitest.setup.ts +1 -30
  616. package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
  617. package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
  618. package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
  619. package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
  620. package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
  621. package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
  622. package/.macro-agent/teams/self-driving/team.yaml +0 -103
  623. package/.macro-agent/teams/structured/prompts/developer.md +0 -26
  624. package/.macro-agent/teams/structured/prompts/lead.md +0 -25
  625. package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
  626. package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
  627. package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
  628. package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
  629. package/.macro-agent/teams/structured/team.yaml +0 -89
  630. package/docs/sudocode-integration.md +0 -383
  631. package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
  632. package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
  633. package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
  634. package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
  635. package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
  636. package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
  637. package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
  638. package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
  639. package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
  640. package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
  641. package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
  642. package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
  643. package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
  644. package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
  645. package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
  646. package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
  647. package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
  648. package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
  649. package/src/task/backend/sudocode/backend.ts +0 -1237
  650. package/src/task/backend/sudocode/client.ts +0 -515
  651. package/src/task/backend/sudocode/index.ts +0 -120
  652. package/src/task/backend/sudocode/mapping.ts +0 -93
  653. package/src/task/backend/sudocode/server-client.ts +0 -522
  654. package/src/task/backend/sudocode/standalone-client.ts +0 -623
  655. package/src/task/backend/sudocode/sync-policy.ts +0 -387
  656. package/src/task/backend/sudocode/tools.ts +0 -896
  657. package/src/task/backend/tool-provider.ts +0 -506
  658. package/test_fixtures/fixtures/sudocode/index.ts +0 -29
  659. package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
  660. package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
@@ -0,0 +1,207 @@
1
+ import { Command } from "commander";
2
+ import { TemplateService } from "../services/template-service";
3
+ import { CommunicationService } from "../services/communication-service";
4
+ import { TemplateLoader } from "../template/loader";
5
+ import type Database from "better-sqlite3";
6
+
7
+ export function createTemplateCommands(db: Database.Database): Command {
8
+ const templateService = new TemplateService(db);
9
+ const commService = new CommunicationService(db);
10
+ const template = new Command("template").description(
11
+ "Load and manage team templates"
12
+ );
13
+
14
+ template
15
+ .command("load <dir>")
16
+ .description("Load a team template from a directory and create a team")
17
+ .option("-n, --name <name>", "Override the team name from the manifest")
18
+ .action((dir: string, opts) => {
19
+ try {
20
+ const result = templateService.bootstrap(dir, opts.name);
21
+ console.log(`Team "${result.team.name}" created from template.`);
22
+ console.log(` Roles: ${result.roles.join(", ")}`);
23
+ if (result.channels.length > 0) {
24
+ console.log(` Channels: ${result.channels.join(", ")}`);
25
+ }
26
+ if (result.spawnRules.length > 0) {
27
+ console.log(" Spawn rules:");
28
+ for (const rule of result.spawnRules) {
29
+ console.log(
30
+ ` ${rule.from} -> [${rule.canSpawn.join(", ")}]`
31
+ );
32
+ }
33
+ }
34
+ } catch (err: any) {
35
+ console.error(`Error: ${err.message}`);
36
+ process.exitCode = 1;
37
+ }
38
+ });
39
+
40
+ template
41
+ .command("validate <dir>")
42
+ .description("Validate a team template directory without creating a team")
43
+ .action((dir: string) => {
44
+ try {
45
+ const resolved = TemplateLoader.load(dir);
46
+ console.log(`Template "${resolved.manifest.name}" is valid.`);
47
+ console.log(` Version: ${resolved.manifest.version}`);
48
+ console.log(` Roles: ${resolved.manifest.roles.join(", ")}`);
49
+ console.log(` Root: ${resolved.manifest.topology.root.role}`);
50
+ if (resolved.manifest.topology.companions) {
51
+ const companions = resolved.manifest.topology.companions.map(
52
+ (c) => c.role
53
+ );
54
+ console.log(` Companions: ${companions.join(", ")}`);
55
+ }
56
+ if (resolved.prompts.size > 0) {
57
+ console.log(
58
+ ` Prompts loaded: ${Array.from(resolved.prompts.keys()).join(", ")}`
59
+ );
60
+ }
61
+ if (resolved.manifest.communication?.channels) {
62
+ console.log(
63
+ ` Channels: ${Object.keys(resolved.manifest.communication.channels).join(", ")}`
64
+ );
65
+ }
66
+ } catch (err: any) {
67
+ console.error(`Invalid template: ${err.message}`);
68
+ process.exitCode = 1;
69
+ }
70
+ });
71
+
72
+ template
73
+ .command("info <team>")
74
+ .description("Show template information for a team")
75
+ .action((teamName: string) => {
76
+ const info = templateService.getTemplateInfo(teamName);
77
+ if (!info) {
78
+ console.error(`Error: Team "${teamName}" not found.`);
79
+ process.exitCode = 1;
80
+ return;
81
+ }
82
+ if (!info.templateName) {
83
+ console.log(`Team "${teamName}" was not created from a template.`);
84
+ return;
85
+ }
86
+ console.log(`Template: ${info.templateName}`);
87
+ if (info.templatePath) {
88
+ console.log(`Source: ${info.templatePath}`);
89
+ }
90
+
91
+ // Show communication topology
92
+ const channels = commService.listChannels(teamName);
93
+ if (channels.length > 0) {
94
+ console.log("\nChannels:");
95
+ for (const ch of channels) {
96
+ const desc = ch.description ? ` - ${ch.description}` : "";
97
+ console.log(` ${ch.name}${desc}`);
98
+ console.log(` Signals: ${ch.signals.join(", ")}`);
99
+ }
100
+ }
101
+
102
+ const subs = commService.listSubscriptions(teamName);
103
+ if (subs.length > 0) {
104
+ console.log("\nSubscriptions:");
105
+ // Group by role
106
+ const grouped: Record<string, string[]> = {};
107
+ for (const sub of subs) {
108
+ if (!grouped[sub.role]) grouped[sub.role] = [];
109
+ const label = sub.signal
110
+ ? `${sub.channel}:${sub.signal}`
111
+ : `${sub.channel}:*`;
112
+ grouped[sub.role].push(label);
113
+ }
114
+ for (const [role, channels] of Object.entries(grouped)) {
115
+ console.log(` ${role}: ${channels.join(", ")}`);
116
+ }
117
+ }
118
+
119
+ const routes = commService.listPeerRoutes(teamName);
120
+ if (routes.length > 0) {
121
+ console.log("\nPeer Routes:");
122
+ for (const route of routes) {
123
+ const signals =
124
+ route.signals.length > 0
125
+ ? ` [${route.signals.join(", ")}]`
126
+ : "";
127
+ console.log(
128
+ ` ${route.from_role} -> ${route.to_role} via ${route.via}${signals}`
129
+ );
130
+ }
131
+ }
132
+
133
+ const spawnRules = templateService.listSpawnRules(teamName);
134
+ if (spawnRules.length > 0) {
135
+ console.log("\nSpawn Rules:");
136
+ for (const rule of spawnRules) {
137
+ console.log(
138
+ ` ${rule.from} -> [${rule.canSpawn.join(", ")}]`
139
+ );
140
+ }
141
+ }
142
+ });
143
+
144
+ template
145
+ .command("emit <team>")
146
+ .description("Emit a signal on a channel")
147
+ .requiredOption("-c, --channel <channel>", "Channel name")
148
+ .requiredOption("-s, --signal <signal>", "Signal name")
149
+ .requiredOption("--sender <sender>", "Sender agent/role name")
150
+ .option("-p, --payload <json>", "JSON payload")
151
+ .action((teamName: string, opts) => {
152
+ try {
153
+ const { event, permitted, enforcement } = commService.emit({
154
+ teamName,
155
+ channel: opts.channel,
156
+ signal: opts.signal,
157
+ sender: opts.sender,
158
+ payload: opts.payload ? JSON.parse(opts.payload) : undefined,
159
+ });
160
+ let msg = `Signal ${event.signal} emitted on ${event.channel} by ${event.sender} (event #${event.id}).`;
161
+ if (!permitted && enforcement === "audit") {
162
+ msg += ` [AUDIT: "${opts.sender}" is not permitted to emit "${opts.signal}"]`;
163
+ }
164
+ console.log(msg);
165
+ } catch (err: any) {
166
+ console.error(`Error: ${err.message}`);
167
+ process.exitCode = 1;
168
+ }
169
+ });
170
+
171
+ template
172
+ .command("events <team>")
173
+ .description("List signal events for a team")
174
+ .option("-c, --channel <channel>", "Filter by channel")
175
+ .option("-s, --signal <signal>", "Filter by signal")
176
+ .option("--sender <sender>", "Filter by sender")
177
+ .option("--role <role>", "Show events visible to a specific role")
178
+ .action((teamName: string, opts) => {
179
+ let events;
180
+ if (opts.role) {
181
+ events = commService.getEventsForRole(teamName, opts.role);
182
+ } else {
183
+ events = commService.listEvents(teamName, {
184
+ channel: opts.channel,
185
+ signal: opts.signal,
186
+ sender: opts.sender,
187
+ });
188
+ }
189
+
190
+ if (events.length === 0) {
191
+ console.log("No signal events found.");
192
+ return;
193
+ }
194
+
195
+ for (const e of events) {
196
+ const payload =
197
+ e.payload && Object.keys(e.payload).length > 0
198
+ ? ` ${JSON.stringify(e.payload)}`
199
+ : "";
200
+ console.log(
201
+ ` #${e.id} [${e.channel}] ${e.signal} from ${e.sender}${payload}`
202
+ );
203
+ }
204
+ });
205
+
206
+ return template;
207
+ }
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import { createDatabase } from "./db/database";
5
+ import { createTeamCommands } from "./cli/team";
6
+ import { createTaskCommands } from "./cli/task";
7
+ import { createMessageCommands } from "./cli/message";
8
+ import { createAgentCommands } from "./cli/agent";
9
+ import { createTemplateCommands } from "./cli/template";
10
+ import { createGenerateCommands } from "./cli/generate";
11
+ import { MockSpawner } from "./spawner/mock";
12
+ import type { AgentSpawner } from "./types";
13
+
14
+ function loadSpawner(): AgentSpawner {
15
+ try {
16
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
17
+ const { ACPFactorySpawner } = require("./spawner/acp-factory");
18
+ return new ACPFactorySpawner();
19
+ } catch {
20
+ // Fall back to mock spawner if acp-factory is not available
21
+ return new MockSpawner();
22
+ }
23
+ }
24
+
25
+ const db = createDatabase();
26
+ const spawner = loadSpawner();
27
+
28
+ const program = new Command();
29
+
30
+ program
31
+ .name("openteams")
32
+ .description("Multi-agent team coordination CLI")
33
+ .version("0.1.0");
34
+
35
+ program.addCommand(createTeamCommands(db));
36
+ program.addCommand(createTaskCommands(db));
37
+ program.addCommand(createMessageCommands(db));
38
+ program.addCommand(createAgentCommands(db, spawner));
39
+ program.addCommand(createTemplateCommands(db));
40
+ program.addCommand(createGenerateCommands());
41
+
42
+ program.parseAsync(process.argv).catch((err) => {
43
+ console.error(err.message);
44
+ process.exit(1);
45
+ });
@@ -0,0 +1,185 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import Database from "better-sqlite3";
3
+ import {
4
+ createInMemoryDatabase,
5
+ getSchemaVersion,
6
+ applyMigrations,
7
+ CURRENT_VERSION,
8
+ } from "./database";
9
+ import type { Migration } from "./database";
10
+
11
+ describe("database", () => {
12
+ it("creates an in-memory database with all tables", () => {
13
+ const db = createInMemoryDatabase();
14
+
15
+ const tables = db
16
+ .prepare(
17
+ "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
18
+ )
19
+ .all() as Array<{ name: string }>;
20
+
21
+ const tableNames = tables.map((t) => t.name);
22
+ expect(tableNames).toContain("teams");
23
+ expect(tableNames).toContain("members");
24
+ expect(tableNames).toContain("tasks");
25
+ expect(tableNames).toContain("task_deps");
26
+ expect(tableNames).toContain("messages");
27
+ expect(tableNames).toContain("schema_version");
28
+ expect(tableNames).toContain("channels");
29
+ expect(tableNames).toContain("channel_signals");
30
+ expect(tableNames).toContain("subscriptions");
31
+ expect(tableNames).toContain("emissions");
32
+ expect(tableNames).toContain("peer_routes");
33
+ expect(tableNames).toContain("signal_events");
34
+ expect(tableNames).toContain("spawn_rules");
35
+
36
+ db.close();
37
+ });
38
+
39
+ it("stores schema version", () => {
40
+ const db = createInMemoryDatabase();
41
+
42
+ const row = db
43
+ .prepare("SELECT version FROM schema_version LIMIT 1")
44
+ .get() as { version: number };
45
+
46
+ expect(row.version).toBe(CURRENT_VERSION);
47
+ db.close();
48
+ });
49
+
50
+ it("enables WAL mode and foreign keys", () => {
51
+ const db = createInMemoryDatabase();
52
+
53
+ const wal = db.pragma("journal_mode") as Array<{ journal_mode: string }>;
54
+ // In-memory databases may use 'memory' instead of 'wal'
55
+ expect(["wal", "memory"]).toContain(wal[0].journal_mode);
56
+
57
+ const fk = db.pragma("foreign_keys") as Array<{ foreign_keys: number }>;
58
+ expect(fk[0].foreign_keys).toBe(1);
59
+
60
+ db.close();
61
+ });
62
+
63
+ it("is idempotent - can be called multiple times on same db", () => {
64
+ const db = createInMemoryDatabase();
65
+
66
+ // Calling schema creation again should not fail
67
+ db.exec(
68
+ "CREATE TABLE IF NOT EXISTS teams (name TEXT PRIMARY KEY, description TEXT, agent_type TEXT, created_at TEXT, status TEXT)"
69
+ );
70
+
71
+ db.close();
72
+ });
73
+ });
74
+
75
+ describe("migrations", () => {
76
+ it("getSchemaVersion returns 0 for empty schema_version table", () => {
77
+ const db = new Database(":memory:");
78
+ db.exec("CREATE TABLE schema_version (version INTEGER PRIMARY KEY)");
79
+
80
+ expect(getSchemaVersion(db)).toBe(0);
81
+ db.close();
82
+ });
83
+
84
+ it("getSchemaVersion returns stored version", () => {
85
+ const db = createInMemoryDatabase();
86
+ expect(getSchemaVersion(db)).toBe(CURRENT_VERSION);
87
+ db.close();
88
+ });
89
+
90
+ it("applyMigrations runs pending migrations in order", () => {
91
+ const db = createInMemoryDatabase();
92
+
93
+ // Simulate a v2 database that needs v3 and v4
94
+ const migrations: Migration[] = [
95
+ { version: 3, up: "ALTER TABLE teams ADD COLUMN extra1 TEXT;" },
96
+ { version: 4, up: "ALTER TABLE teams ADD COLUMN extra2 TEXT;" },
97
+ ];
98
+
99
+ const result = applyMigrations(db, 2, migrations);
100
+ expect(result).toBe(4);
101
+
102
+ // Verify version was updated
103
+ expect(getSchemaVersion(db)).toBe(4);
104
+
105
+ // Verify columns were added
106
+ const info = db.prepare("PRAGMA table_info(teams)").all() as Array<{
107
+ name: string;
108
+ }>;
109
+ const colNames = info.map((c) => c.name);
110
+ expect(colNames).toContain("extra1");
111
+ expect(colNames).toContain("extra2");
112
+
113
+ db.close();
114
+ });
115
+
116
+ it("applyMigrations skips already-applied versions", () => {
117
+ const db = createInMemoryDatabase();
118
+
119
+ const migrations: Migration[] = [
120
+ { version: 1, up: "SELECT 1;" }, // already past this
121
+ { version: 2, up: "SELECT 1;" }, // already at this
122
+ { version: 3, up: "ALTER TABLE teams ADD COLUMN new_col TEXT;" },
123
+ ];
124
+
125
+ const result = applyMigrations(db, 2, migrations);
126
+ expect(result).toBe(3);
127
+
128
+ // Only the v3 migration should have run
129
+ const info = db.prepare("PRAGMA table_info(teams)").all() as Array<{
130
+ name: string;
131
+ }>;
132
+ const colNames = info.map((c) => c.name);
133
+ expect(colNames).toContain("new_col");
134
+
135
+ db.close();
136
+ });
137
+
138
+ it("applyMigrations returns current version when nothing to apply", () => {
139
+ const db = createInMemoryDatabase();
140
+
141
+ const result = applyMigrations(db, CURRENT_VERSION, []);
142
+ expect(result).toBe(CURRENT_VERSION);
143
+
144
+ db.close();
145
+ });
146
+
147
+ it("applyMigrations rolls back on failure", () => {
148
+ const db = createInMemoryDatabase();
149
+
150
+ const migrations: Migration[] = [
151
+ { version: 3, up: "ALTER TABLE teams ADD COLUMN good_col TEXT;" },
152
+ { version: 4, up: "ALTER TABLE nonexistent_table ADD COLUMN bad TEXT;" },
153
+ ];
154
+
155
+ expect(() => applyMigrations(db, 2, migrations)).toThrow();
156
+
157
+ // Version should still be 2 — transaction rolled back
158
+ expect(getSchemaVersion(db)).toBe(CURRENT_VERSION);
159
+
160
+ // The v3 column should NOT exist — entire transaction rolled back
161
+ const info = db.prepare("PRAGMA table_info(teams)").all() as Array<{
162
+ name: string;
163
+ }>;
164
+ const colNames = info.map((c) => c.name);
165
+ expect(colNames).not.toContain("good_col");
166
+
167
+ db.close();
168
+ });
169
+
170
+ it("applies migrations in version order regardless of array order", () => {
171
+ const db = createInMemoryDatabase();
172
+
173
+ // Provide migrations out of order
174
+ const migrations: Migration[] = [
175
+ { version: 4, up: "ALTER TABLE teams ADD COLUMN col_b TEXT;" },
176
+ { version: 3, up: "ALTER TABLE teams ADD COLUMN col_a TEXT;" },
177
+ ];
178
+
179
+ const result = applyMigrations(db, 2, migrations);
180
+ expect(result).toBe(4);
181
+ expect(getSchemaVersion(db)).toBe(4);
182
+
183
+ db.close();
184
+ });
185
+ });
@@ -0,0 +1,240 @@
1
+ import Database from "better-sqlite3";
2
+ import path from "path";
3
+ import os from "os";
4
+ import fs from "fs";
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Migration framework
8
+ // ---------------------------------------------------------------------------
9
+ // SCHEMA_SQL is the full current schema for fresh installs.
10
+ // MIGRATIONS handles upgrades for existing databases.
11
+ //
12
+ // When adding a new schema change:
13
+ // 1. Update SCHEMA_SQL to include the change (for fresh installs)
14
+ // 2. Add a Migration entry with the next version number (for existing installs)
15
+ // 3. Bump CURRENT_VERSION to match
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export interface Migration {
19
+ version: number;
20
+ up: string;
21
+ }
22
+
23
+ export const CURRENT_VERSION = 2;
24
+
25
+ /**
26
+ * Migrations applied incrementally to existing databases.
27
+ * Each migration brings the schema from (version - 1) to version.
28
+ * For now this is empty because v2 is the baseline — no users have
29
+ * older databases. Future changes add entries here.
30
+ */
31
+ export const MIGRATIONS: Migration[] = [
32
+ // Example for a future change:
33
+ // {
34
+ // version: 3,
35
+ // up: `ALTER TABLE teams ADD COLUMN some_new_col TEXT;`
36
+ // },
37
+ ];
38
+
39
+ const SCHEMA_SQL = `
40
+ CREATE TABLE IF NOT EXISTS schema_version (
41
+ version INTEGER PRIMARY KEY
42
+ );
43
+
44
+ CREATE TABLE IF NOT EXISTS teams (
45
+ name TEXT PRIMARY KEY,
46
+ description TEXT,
47
+ agent_type TEXT,
48
+ template_name TEXT,
49
+ template_path TEXT,
50
+ enforcement TEXT DEFAULT 'permissive' CHECK (enforcement IN ('strict', 'permissive', 'audit')),
51
+ created_at TEXT DEFAULT (datetime('now')),
52
+ status TEXT DEFAULT 'active' CHECK (status IN ('active', 'deleted'))
53
+ );
54
+
55
+ CREATE TABLE IF NOT EXISTS members (
56
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
57
+ team_name TEXT NOT NULL REFERENCES teams(name),
58
+ agent_name TEXT NOT NULL,
59
+ agent_id TEXT,
60
+ agent_type TEXT DEFAULT 'general-purpose',
61
+ role TEXT,
62
+ status TEXT DEFAULT 'idle' CHECK (status IN ('idle', 'running', 'shutdown')),
63
+ spawn_prompt TEXT,
64
+ model TEXT,
65
+ created_at TEXT DEFAULT (datetime('now')),
66
+ UNIQUE(team_name, agent_name)
67
+ );
68
+
69
+ CREATE TABLE IF NOT EXISTS tasks (
70
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
71
+ team_name TEXT NOT NULL REFERENCES teams(name),
72
+ subject TEXT NOT NULL,
73
+ description TEXT NOT NULL,
74
+ active_form TEXT,
75
+ status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed', 'deleted')),
76
+ owner TEXT,
77
+ metadata TEXT DEFAULT '{}',
78
+ created_at TEXT DEFAULT (datetime('now')),
79
+ updated_at TEXT DEFAULT (datetime('now'))
80
+ );
81
+
82
+ CREATE TABLE IF NOT EXISTS task_deps (
83
+ task_id INTEGER NOT NULL REFERENCES tasks(id),
84
+ blocked_by INTEGER NOT NULL REFERENCES tasks(id),
85
+ PRIMARY KEY (task_id, blocked_by)
86
+ );
87
+
88
+ CREATE TABLE IF NOT EXISTS messages (
89
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
90
+ team_name TEXT NOT NULL REFERENCES teams(name),
91
+ type TEXT NOT NULL CHECK (type IN ('message', 'broadcast', 'shutdown_request', 'shutdown_response', 'plan_approval_response')),
92
+ sender TEXT NOT NULL,
93
+ recipient TEXT,
94
+ content TEXT NOT NULL,
95
+ summary TEXT,
96
+ request_id TEXT,
97
+ approve INTEGER,
98
+ delivered INTEGER DEFAULT 0,
99
+ created_at TEXT DEFAULT (datetime('now'))
100
+ );
101
+
102
+ -- Communication: channel definitions per team
103
+ CREATE TABLE IF NOT EXISTS channels (
104
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
105
+ team_name TEXT NOT NULL REFERENCES teams(name),
106
+ name TEXT NOT NULL,
107
+ description TEXT,
108
+ UNIQUE(team_name, name)
109
+ );
110
+
111
+ -- Signals belonging to a channel
112
+ CREATE TABLE IF NOT EXISTS channel_signals (
113
+ channel_id INTEGER NOT NULL REFERENCES channels(id),
114
+ signal TEXT NOT NULL,
115
+ PRIMARY KEY (channel_id, signal)
116
+ );
117
+
118
+ -- Role subscriptions to channels (with optional signal filter)
119
+ CREATE TABLE IF NOT EXISTS subscriptions (
120
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
121
+ team_name TEXT NOT NULL REFERENCES teams(name),
122
+ role TEXT NOT NULL,
123
+ channel TEXT NOT NULL,
124
+ signal TEXT,
125
+ UNIQUE(team_name, role, channel, signal)
126
+ );
127
+
128
+ -- Emission permissions per role
129
+ CREATE TABLE IF NOT EXISTS emissions (
130
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
131
+ team_name TEXT NOT NULL REFERENCES teams(name),
132
+ role TEXT NOT NULL,
133
+ signal TEXT NOT NULL,
134
+ UNIQUE(team_name, role, signal)
135
+ );
136
+
137
+ -- Peer routing rules
138
+ CREATE TABLE IF NOT EXISTS peer_routes (
139
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
140
+ team_name TEXT NOT NULL REFERENCES teams(name),
141
+ from_role TEXT NOT NULL,
142
+ to_role TEXT NOT NULL,
143
+ via TEXT NOT NULL DEFAULT 'direct' CHECK (via IN ('direct', 'topic', 'scope')),
144
+ signals TEXT DEFAULT '[]'
145
+ );
146
+
147
+ -- Signal events log
148
+ CREATE TABLE IF NOT EXISTS signal_events (
149
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
150
+ team_name TEXT NOT NULL REFERENCES teams(name),
151
+ channel TEXT NOT NULL,
152
+ signal TEXT NOT NULL,
153
+ sender TEXT NOT NULL,
154
+ payload TEXT DEFAULT '{}',
155
+ created_at TEXT DEFAULT (datetime('now'))
156
+ );
157
+
158
+ -- Spawn rules per team
159
+ CREATE TABLE IF NOT EXISTS spawn_rules (
160
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
161
+ team_name TEXT NOT NULL REFERENCES teams(name),
162
+ from_role TEXT NOT NULL,
163
+ to_role TEXT NOT NULL,
164
+ UNIQUE(team_name, from_role, to_role)
165
+ );
166
+ `;
167
+
168
+ function getDefaultDbPath(): string {
169
+ const dir = path.join(os.homedir(), ".openteams");
170
+ fs.mkdirSync(dir, { recursive: true });
171
+ return path.join(dir, "openteams.db");
172
+ }
173
+
174
+ /**
175
+ * Read the current schema version from the database.
176
+ * Returns 0 if no version row exists (fresh install).
177
+ */
178
+ export function getSchemaVersion(db: Database.Database): number {
179
+ const row = db
180
+ .prepare("SELECT version FROM schema_version LIMIT 1")
181
+ .get() as { version: number } | undefined;
182
+ return row?.version ?? 0;
183
+ }
184
+
185
+ /**
186
+ * Apply pending migrations to bring the database up to CURRENT_VERSION.
187
+ * Runs inside a transaction so partial migrations are rolled back.
188
+ */
189
+ export function applyMigrations(
190
+ db: Database.Database,
191
+ fromVersion: number,
192
+ migrations: Migration[] = MIGRATIONS
193
+ ): number {
194
+ const pending = migrations
195
+ .filter((m) => m.version > fromVersion)
196
+ .sort((a, b) => a.version - b.version);
197
+
198
+ if (pending.length === 0) return fromVersion;
199
+
200
+ const targetVersion = pending[pending.length - 1].version;
201
+
202
+ const migrate = db.transaction(() => {
203
+ for (const migration of pending) {
204
+ db.exec(migration.up);
205
+ }
206
+ db.prepare("UPDATE schema_version SET version = ?").run(targetVersion);
207
+ });
208
+
209
+ migrate();
210
+ return targetVersion;
211
+ }
212
+
213
+ export function createDatabase(dbPath?: string): Database.Database {
214
+ const resolvedPath = dbPath ?? getDefaultDbPath();
215
+ const db = new Database(resolvedPath);
216
+
217
+ db.pragma("journal_mode = WAL");
218
+ db.pragma("foreign_keys = ON");
219
+
220
+ // Create all tables (IF NOT EXISTS is safe for both fresh and existing DBs)
221
+ db.exec(SCHEMA_SQL);
222
+
223
+ const currentVersion = getSchemaVersion(db);
224
+
225
+ if (currentVersion === 0) {
226
+ // Fresh install — stamp with current version
227
+ db.prepare("INSERT INTO schema_version (version) VALUES (?)").run(
228
+ CURRENT_VERSION
229
+ );
230
+ } else if (currentVersion < CURRENT_VERSION) {
231
+ // Existing database needs migration
232
+ applyMigrations(db, currentVersion);
233
+ }
234
+
235
+ return db;
236
+ }
237
+
238
+ export function createInMemoryDatabase(): Database.Database {
239
+ return createDatabase(":memory:");
240
+ }