@ag-eco/agentplate-cli 0.13.0

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 (455) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +462 -0
  3. package/agents/ap-co-creation.md +90 -0
  4. package/agents/builder.md +144 -0
  5. package/agents/coordinator.md +377 -0
  6. package/agents/lead.md +435 -0
  7. package/agents/merger.md +164 -0
  8. package/agents/monitor.md +214 -0
  9. package/agents/orchestrator.md +239 -0
  10. package/agents/reviewer.md +140 -0
  11. package/agents/scout.md +125 -0
  12. package/agents/supervisor.md +427 -0
  13. package/package.json +66 -0
  14. package/src/agents/capabilities.test.ts +85 -0
  15. package/src/agents/capabilities.ts +125 -0
  16. package/src/agents/checkpoint.test.ts +88 -0
  17. package/src/agents/checkpoint.ts +101 -0
  18. package/src/agents/copilot-hooks-deployer.test.ts +162 -0
  19. package/src/agents/copilot-hooks-deployer.ts +93 -0
  20. package/src/agents/guard-rules.test.ts +372 -0
  21. package/src/agents/guard-rules.ts +97 -0
  22. package/src/agents/headless-mail-injector.test.ts +709 -0
  23. package/src/agents/headless-mail-injector.ts +377 -0
  24. package/src/agents/headless-prompt.test.ts +102 -0
  25. package/src/agents/headless-prompt.ts +68 -0
  26. package/src/agents/hooks-deployer.test.ts +3119 -0
  27. package/src/agents/hooks-deployer.ts +804 -0
  28. package/src/agents/identity.test.ts +604 -0
  29. package/src/agents/identity.ts +384 -0
  30. package/src/agents/lifecycle.test.ts +196 -0
  31. package/src/agents/lifecycle.ts +183 -0
  32. package/src/agents/mail-poll-detect.test.ts +153 -0
  33. package/src/agents/mail-poll-detect.ts +73 -0
  34. package/src/agents/manifest.test.ts +1026 -0
  35. package/src/agents/manifest.ts +376 -0
  36. package/src/agents/overlay.test.ts +1058 -0
  37. package/src/agents/overlay.ts +490 -0
  38. package/src/agents/scope-detect.test.ts +190 -0
  39. package/src/agents/scope-detect.ts +146 -0
  40. package/src/agents/turn-lock.test.ts +181 -0
  41. package/src/agents/turn-lock.ts +235 -0
  42. package/src/agents/turn-runner-dispatch.test.ts +182 -0
  43. package/src/agents/turn-runner-dispatch.ts +105 -0
  44. package/src/agents/turn-runner.test.ts +2312 -0
  45. package/src/agents/turn-runner.ts +1383 -0
  46. package/src/beads/client.test.ts +217 -0
  47. package/src/beads/client.ts +230 -0
  48. package/src/beads/molecules.test.ts +338 -0
  49. package/src/beads/molecules.ts +198 -0
  50. package/src/commands/agents.test.ts +328 -0
  51. package/src/commands/agents.ts +299 -0
  52. package/src/commands/clean.test.ts +797 -0
  53. package/src/commands/clean.ts +791 -0
  54. package/src/commands/completions.test.ts +348 -0
  55. package/src/commands/completions.ts +981 -0
  56. package/src/commands/coordinator.test.ts +2975 -0
  57. package/src/commands/coordinator.ts +1841 -0
  58. package/src/commands/costs.test.ts +1183 -0
  59. package/src/commands/costs.ts +599 -0
  60. package/src/commands/dashboard.test.ts +954 -0
  61. package/src/commands/dashboard.ts +1212 -0
  62. package/src/commands/discover.test.ts +288 -0
  63. package/src/commands/discover.ts +202 -0
  64. package/src/commands/doctor.test.ts +303 -0
  65. package/src/commands/doctor.ts +311 -0
  66. package/src/commands/ecosystem.test.ts +226 -0
  67. package/src/commands/ecosystem.ts +248 -0
  68. package/src/commands/errors.test.ts +654 -0
  69. package/src/commands/errors.ts +197 -0
  70. package/src/commands/feed.test.ts +709 -0
  71. package/src/commands/feed.ts +260 -0
  72. package/src/commands/group.test.ts +475 -0
  73. package/src/commands/group.ts +546 -0
  74. package/src/commands/hooks.test.ts +458 -0
  75. package/src/commands/hooks.ts +263 -0
  76. package/src/commands/init.test.ts +1011 -0
  77. package/src/commands/init.ts +967 -0
  78. package/src/commands/inspect.test.ts +1239 -0
  79. package/src/commands/inspect.ts +648 -0
  80. package/src/commands/log.test.ts +1913 -0
  81. package/src/commands/log.ts +958 -0
  82. package/src/commands/logs.test.ts +801 -0
  83. package/src/commands/logs.ts +483 -0
  84. package/src/commands/mail.test.ts +1501 -0
  85. package/src/commands/mail.ts +848 -0
  86. package/src/commands/merge.test.ts +864 -0
  87. package/src/commands/merge.ts +381 -0
  88. package/src/commands/metrics.test.ts +458 -0
  89. package/src/commands/metrics.ts +129 -0
  90. package/src/commands/monitor.test.ts +191 -0
  91. package/src/commands/monitor.ts +409 -0
  92. package/src/commands/nudge.test.ts +579 -0
  93. package/src/commands/nudge.ts +646 -0
  94. package/src/commands/orchestrator.ts +42 -0
  95. package/src/commands/prime.test.ts +612 -0
  96. package/src/commands/prime.ts +359 -0
  97. package/src/commands/replay.test.ts +757 -0
  98. package/src/commands/replay.ts +231 -0
  99. package/src/commands/run.test.ts +469 -0
  100. package/src/commands/run.ts +353 -0
  101. package/src/commands/serve/agent-actions.test.ts +210 -0
  102. package/src/commands/serve/agent-actions.ts +192 -0
  103. package/src/commands/serve/build.test.ts +202 -0
  104. package/src/commands/serve/build.ts +206 -0
  105. package/src/commands/serve/coordinator-actions.test.ts +339 -0
  106. package/src/commands/serve/coordinator-actions.ts +410 -0
  107. package/src/commands/serve/dev.test.ts +168 -0
  108. package/src/commands/serve/dev.ts +117 -0
  109. package/src/commands/serve/mail-actions.test.ts +312 -0
  110. package/src/commands/serve/mail-actions.ts +167 -0
  111. package/src/commands/serve/rest.test.ts +1680 -0
  112. package/src/commands/serve/rest.ts +1130 -0
  113. package/src/commands/serve/static.ts +51 -0
  114. package/src/commands/serve/ws.test.ts +361 -0
  115. package/src/commands/serve/ws.ts +332 -0
  116. package/src/commands/serve.test.ts +459 -0
  117. package/src/commands/serve.ts +654 -0
  118. package/src/commands/sling.test.ts +1583 -0
  119. package/src/commands/sling.ts +1351 -0
  120. package/src/commands/spec.test.ts +179 -0
  121. package/src/commands/spec.ts +105 -0
  122. package/src/commands/status.test.ts +614 -0
  123. package/src/commands/status.ts +403 -0
  124. package/src/commands/stop.test.ts +964 -0
  125. package/src/commands/stop.ts +319 -0
  126. package/src/commands/supervisor.test.ts +185 -0
  127. package/src/commands/supervisor.ts +537 -0
  128. package/src/commands/trace.test.ts +762 -0
  129. package/src/commands/trace.ts +205 -0
  130. package/src/commands/update.test.ts +466 -0
  131. package/src/commands/update.ts +263 -0
  132. package/src/commands/upgrade.test.ts +48 -0
  133. package/src/commands/upgrade.ts +240 -0
  134. package/src/commands/watch.test.ts +257 -0
  135. package/src/commands/watch.ts +308 -0
  136. package/src/commands/worktree.test.ts +1297 -0
  137. package/src/commands/worktree.ts +451 -0
  138. package/src/config.test.ts +1535 -0
  139. package/src/config.ts +1064 -0
  140. package/src/doctor/agents.test.ts +523 -0
  141. package/src/doctor/agents.ts +399 -0
  142. package/src/doctor/config-check.test.ts +191 -0
  143. package/src/doctor/config-check.ts +183 -0
  144. package/src/doctor/consistency.test.ts +807 -0
  145. package/src/doctor/consistency.ts +347 -0
  146. package/src/doctor/databases.test.ts +350 -0
  147. package/src/doctor/databases.ts +243 -0
  148. package/src/doctor/dependencies.test.ts +296 -0
  149. package/src/doctor/dependencies.ts +272 -0
  150. package/src/doctor/ecosystem.test.ts +308 -0
  151. package/src/doctor/ecosystem.ts +156 -0
  152. package/src/doctor/logs.test.ts +253 -0
  153. package/src/doctor/logs.ts +295 -0
  154. package/src/doctor/merge-queue.test.ts +315 -0
  155. package/src/doctor/merge-queue.ts +167 -0
  156. package/src/doctor/providers.test.ts +409 -0
  157. package/src/doctor/providers.ts +250 -0
  158. package/src/doctor/serve.test.ts +95 -0
  159. package/src/doctor/serve.ts +86 -0
  160. package/src/doctor/structure.test.ts +423 -0
  161. package/src/doctor/structure.ts +285 -0
  162. package/src/doctor/types.ts +43 -0
  163. package/src/doctor/version.test.ts +241 -0
  164. package/src/doctor/version.ts +132 -0
  165. package/src/doctor/watchdog.test.ts +167 -0
  166. package/src/doctor/watchdog.ts +214 -0
  167. package/src/e2e/init-sling-lifecycle.test.ts +283 -0
  168. package/src/errors.test.ts +350 -0
  169. package/src/errors.ts +217 -0
  170. package/src/events/store.test.ts +660 -0
  171. package/src/events/store.ts +369 -0
  172. package/src/events/tailer.test.ts +719 -0
  173. package/src/events/tailer.ts +332 -0
  174. package/src/events/tool-filter.test.ts +330 -0
  175. package/src/events/tool-filter.ts +126 -0
  176. package/src/index.ts +533 -0
  177. package/src/insights/analyzer.test.ts +466 -0
  178. package/src/insights/analyzer.ts +203 -0
  179. package/src/insights/quality-gates.test.ts +141 -0
  180. package/src/insights/quality-gates.ts +156 -0
  181. package/src/json.test.ts +72 -0
  182. package/src/json.ts +53 -0
  183. package/src/loam/client.test.ts +752 -0
  184. package/src/loam/client.ts +664 -0
  185. package/src/logging/color.test.ts +252 -0
  186. package/src/logging/color.ts +105 -0
  187. package/src/logging/format.test.ts +110 -0
  188. package/src/logging/format.ts +255 -0
  189. package/src/logging/logger.test.ts +814 -0
  190. package/src/logging/logger.ts +266 -0
  191. package/src/logging/reporter.test.ts +259 -0
  192. package/src/logging/reporter.ts +110 -0
  193. package/src/logging/sanitizer.test.ts +190 -0
  194. package/src/logging/sanitizer.ts +57 -0
  195. package/src/logging/theme.ts +140 -0
  196. package/src/mail/broadcast.test.ts +204 -0
  197. package/src/mail/broadcast.ts +92 -0
  198. package/src/mail/client.test.ts +774 -0
  199. package/src/mail/client.ts +236 -0
  200. package/src/mail/store.test.ts +898 -0
  201. package/src/mail/store.ts +425 -0
  202. package/src/merge/lock.test.ts +149 -0
  203. package/src/merge/lock.ts +140 -0
  204. package/src/merge/predict.test.ts +387 -0
  205. package/src/merge/predict.ts +249 -0
  206. package/src/merge/queue.test.ts +426 -0
  207. package/src/merge/queue.ts +246 -0
  208. package/src/merge/resolver.test.ts +1993 -0
  209. package/src/merge/resolver.ts +926 -0
  210. package/src/metrics/pricing.test.ts +258 -0
  211. package/src/metrics/pricing.ts +135 -0
  212. package/src/metrics/store.test.ts +978 -0
  213. package/src/metrics/store.ts +501 -0
  214. package/src/metrics/summary.test.ts +398 -0
  215. package/src/metrics/summary.ts +178 -0
  216. package/src/metrics/transcript.test.ts +483 -0
  217. package/src/metrics/transcript.ts +114 -0
  218. package/src/runtimes/__fixtures__/claude-stream-fixture.ts +22 -0
  219. package/src/runtimes/aider.test.ts +124 -0
  220. package/src/runtimes/aider.ts +147 -0
  221. package/src/runtimes/amp.test.ts +164 -0
  222. package/src/runtimes/amp.ts +154 -0
  223. package/src/runtimes/claude.test.ts +1474 -0
  224. package/src/runtimes/claude.ts +579 -0
  225. package/src/runtimes/codex.test.ts +805 -0
  226. package/src/runtimes/codex.ts +273 -0
  227. package/src/runtimes/connections.test.ts +214 -0
  228. package/src/runtimes/connections.ts +103 -0
  229. package/src/runtimes/copilot.test.ts +707 -0
  230. package/src/runtimes/copilot.ts +316 -0
  231. package/src/runtimes/cursor.test.ts +497 -0
  232. package/src/runtimes/cursor.ts +205 -0
  233. package/src/runtimes/gemini.test.ts +537 -0
  234. package/src/runtimes/gemini.ts +243 -0
  235. package/src/runtimes/goose.test.ts +133 -0
  236. package/src/runtimes/goose.ts +157 -0
  237. package/src/runtimes/headless-connection.test.ts +264 -0
  238. package/src/runtimes/headless-connection.ts +158 -0
  239. package/src/runtimes/opencode.test.ts +325 -0
  240. package/src/runtimes/opencode.ts +188 -0
  241. package/src/runtimes/pi-guards.test.ts +486 -0
  242. package/src/runtimes/pi-guards.ts +367 -0
  243. package/src/runtimes/pi.test.ts +789 -0
  244. package/src/runtimes/pi.ts +305 -0
  245. package/src/runtimes/registry.test.ts +196 -0
  246. package/src/runtimes/registry.ts +99 -0
  247. package/src/runtimes/sapling.test.ts +1267 -0
  248. package/src/runtimes/sapling.ts +710 -0
  249. package/src/runtimes/types.ts +266 -0
  250. package/src/schema-consistency.test.ts +246 -0
  251. package/src/sessions/compat.test.ts +281 -0
  252. package/src/sessions/compat.ts +105 -0
  253. package/src/sessions/store.test.ts +1748 -0
  254. package/src/sessions/store.ts +858 -0
  255. package/src/test-helpers.test.ts +124 -0
  256. package/src/test-helpers.ts +145 -0
  257. package/src/test-setup.test.ts +31 -0
  258. package/src/test-setup.ts +28 -0
  259. package/src/tools/loam/api.ts +368 -0
  260. package/src/tools/loam/cli.ts +278 -0
  261. package/src/tools/loam/commands/add.ts +52 -0
  262. package/src/tools/loam/commands/archive.ts +214 -0
  263. package/src/tools/loam/commands/audit.ts +276 -0
  264. package/src/tools/loam/commands/compact.ts +1062 -0
  265. package/src/tools/loam/commands/completions.ts +79 -0
  266. package/src/tools/loam/commands/config.ts +381 -0
  267. package/src/tools/loam/commands/delete-domain.ts +121 -0
  268. package/src/tools/loam/commands/delete.ts +316 -0
  269. package/src/tools/loam/commands/diff.ts +200 -0
  270. package/src/tools/loam/commands/doctor.ts +1113 -0
  271. package/src/tools/loam/commands/edit.ts +226 -0
  272. package/src/tools/loam/commands/init.ts +31 -0
  273. package/src/tools/loam/commands/learn.ts +179 -0
  274. package/src/tools/loam/commands/move.ts +323 -0
  275. package/src/tools/loam/commands/onboard.ts +374 -0
  276. package/src/tools/loam/commands/outcome.ts +185 -0
  277. package/src/tools/loam/commands/prime.ts +688 -0
  278. package/src/tools/loam/commands/prune.ts +614 -0
  279. package/src/tools/loam/commands/query.ts +218 -0
  280. package/src/tools/loam/commands/rank.ts +180 -0
  281. package/src/tools/loam/commands/ready.ts +189 -0
  282. package/src/tools/loam/commands/record.ts +1210 -0
  283. package/src/tools/loam/commands/restore.ts +166 -0
  284. package/src/tools/loam/commands/search.ts +327 -0
  285. package/src/tools/loam/commands/setup.ts +887 -0
  286. package/src/tools/loam/commands/status.ts +103 -0
  287. package/src/tools/loam/commands/sync.ts +298 -0
  288. package/src/tools/loam/commands/update.ts +19 -0
  289. package/src/tools/loam/commands/upgrade.ts +93 -0
  290. package/src/tools/loam/commands/validate.ts +190 -0
  291. package/src/tools/loam/index.ts +62 -0
  292. package/src/tools/loam/log.ts +127 -0
  293. package/src/tools/loam/registry/builtins.ts +409 -0
  294. package/src/tools/loam/registry/custom.ts +431 -0
  295. package/src/tools/loam/registry/init.ts +55 -0
  296. package/src/tools/loam/registry/template.ts +40 -0
  297. package/src/tools/loam/registry/type-registry.ts +113 -0
  298. package/src/tools/loam/schemas/config-schema.ts +489 -0
  299. package/src/tools/loam/schemas/config.ts +245 -0
  300. package/src/tools/loam/schemas/index.ts +18 -0
  301. package/src/tools/loam/schemas/record-schema.ts +191 -0
  302. package/src/tools/loam/schemas/record.ts +115 -0
  303. package/src/tools/loam/utils/active-work.ts +205 -0
  304. package/src/tools/loam/utils/anchor-validity.ts +80 -0
  305. package/src/tools/loam/utils/archive.ts +146 -0
  306. package/src/tools/loam/utils/audit.ts +667 -0
  307. package/src/tools/loam/utils/bm25.ts +238 -0
  308. package/src/tools/loam/utils/budget.ts +142 -0
  309. package/src/tools/loam/utils/config.ts +344 -0
  310. package/src/tools/loam/utils/dir-anchors.ts +62 -0
  311. package/src/tools/loam/utils/domain-rules.ts +114 -0
  312. package/src/tools/loam/utils/expertise.ts +393 -0
  313. package/src/tools/loam/utils/format-helpers.ts +96 -0
  314. package/src/tools/loam/utils/format.ts +1234 -0
  315. package/src/tools/loam/utils/git-context.ts +50 -0
  316. package/src/tools/loam/utils/git.ts +183 -0
  317. package/src/tools/loam/utils/hooks.ts +299 -0
  318. package/src/tools/loam/utils/index.ts +52 -0
  319. package/src/tools/loam/utils/json-output.ts +13 -0
  320. package/src/tools/loam/utils/lock.ts +76 -0
  321. package/src/tools/loam/utils/markers.ts +48 -0
  322. package/src/tools/loam/utils/numeric-flags.ts +20 -0
  323. package/src/tools/loam/utils/palette.ts +44 -0
  324. package/src/tools/loam/utils/prime-ranking.ts +135 -0
  325. package/src/tools/loam/utils/recipe-discovery.ts +195 -0
  326. package/src/tools/loam/utils/runtime-flags.ts +28 -0
  327. package/src/tools/loam/utils/scoring.ts +94 -0
  328. package/src/tools/loam/utils/version.ts +116 -0
  329. package/src/tools/sprout/commands/block.ts +64 -0
  330. package/src/tools/sprout/commands/blocked.ts +86 -0
  331. package/src/tools/sprout/commands/close.ts +129 -0
  332. package/src/tools/sprout/commands/completions.ts +198 -0
  333. package/src/tools/sprout/commands/config.ts +238 -0
  334. package/src/tools/sprout/commands/create.ts +164 -0
  335. package/src/tools/sprout/commands/dep.ts +148 -0
  336. package/src/tools/sprout/commands/doctor.ts +979 -0
  337. package/src/tools/sprout/commands/init.ts +83 -0
  338. package/src/tools/sprout/commands/label.ts +178 -0
  339. package/src/tools/sprout/commands/list.ts +210 -0
  340. package/src/tools/sprout/commands/migrate.ts +133 -0
  341. package/src/tools/sprout/commands/onboard.ts +207 -0
  342. package/src/tools/sprout/commands/plan-show.ts +278 -0
  343. package/src/tools/sprout/commands/plan.ts +2526 -0
  344. package/src/tools/sprout/commands/prime.ts +399 -0
  345. package/src/tools/sprout/commands/ready.ts +245 -0
  346. package/src/tools/sprout/commands/search.ts +221 -0
  347. package/src/tools/sprout/commands/show.ts +277 -0
  348. package/src/tools/sprout/commands/stats.ts +146 -0
  349. package/src/tools/sprout/commands/sync.ts +134 -0
  350. package/src/tools/sprout/commands/tpl.ts +364 -0
  351. package/src/tools/sprout/commands/unblock.ts +115 -0
  352. package/src/tools/sprout/commands/update.ts +257 -0
  353. package/src/tools/sprout/commands/upgrade.ts +91 -0
  354. package/src/tools/sprout/config-schema.ts +152 -0
  355. package/src/tools/sprout/config.ts +355 -0
  356. package/src/tools/sprout/filter.ts +107 -0
  357. package/src/tools/sprout/format.ts +43 -0
  358. package/src/tools/sprout/id.ts +22 -0
  359. package/src/tools/sprout/index.ts +204 -0
  360. package/src/tools/sprout/log.ts +76 -0
  361. package/src/tools/sprout/markers.ts +22 -0
  362. package/src/tools/sprout/output.ts +121 -0
  363. package/src/tools/sprout/plan-backref.ts +93 -0
  364. package/src/tools/sprout/plan-context.ts +81 -0
  365. package/src/tools/sprout/plan-domain.ts +139 -0
  366. package/src/tools/sprout/plan-lifecycle.ts +65 -0
  367. package/src/tools/sprout/plan-loam.ts +207 -0
  368. package/src/tools/sprout/plan-schema.ts +209 -0
  369. package/src/tools/sprout/sort.ts +31 -0
  370. package/src/tools/sprout/store.ts +172 -0
  371. package/src/tools/sprout/types.ts +118 -0
  372. package/src/tools/sprout/validation.ts +119 -0
  373. package/src/tools/sprout/version.ts +1 -0
  374. package/src/tools/sprout/yaml.ts +387 -0
  375. package/src/tools/trellis/commands/archive.ts +87 -0
  376. package/src/tools/trellis/commands/completions.ts +610 -0
  377. package/src/tools/trellis/commands/config.ts +382 -0
  378. package/src/tools/trellis/commands/create.ts +252 -0
  379. package/src/tools/trellis/commands/diff.ts +150 -0
  380. package/src/tools/trellis/commands/doctor.ts +771 -0
  381. package/src/tools/trellis/commands/emit.ts +365 -0
  382. package/src/tools/trellis/commands/history.ts +83 -0
  383. package/src/tools/trellis/commands/import.ts +198 -0
  384. package/src/tools/trellis/commands/init.ts +81 -0
  385. package/src/tools/trellis/commands/list.ts +103 -0
  386. package/src/tools/trellis/commands/onboard.ts +156 -0
  387. package/src/tools/trellis/commands/pin.ts +172 -0
  388. package/src/tools/trellis/commands/prime.ts +193 -0
  389. package/src/tools/trellis/commands/render.ts +122 -0
  390. package/src/tools/trellis/commands/schema.ts +353 -0
  391. package/src/tools/trellis/commands/show.ts +115 -0
  392. package/src/tools/trellis/commands/stats.ts +65 -0
  393. package/src/tools/trellis/commands/sync.ts +112 -0
  394. package/src/tools/trellis/commands/tree.ts +123 -0
  395. package/src/tools/trellis/commands/update.ts +330 -0
  396. package/src/tools/trellis/commands/upgrade.ts +95 -0
  397. package/src/tools/trellis/commands/validate.ts +166 -0
  398. package/src/tools/trellis/config-schema.ts +81 -0
  399. package/src/tools/trellis/config.ts +108 -0
  400. package/src/tools/trellis/frontmatter.ts +348 -0
  401. package/src/tools/trellis/id.ts +24 -0
  402. package/src/tools/trellis/index.ts +209 -0
  403. package/src/tools/trellis/markers.ts +28 -0
  404. package/src/tools/trellis/output.ts +84 -0
  405. package/src/tools/trellis/render.ts +212 -0
  406. package/src/tools/trellis/store.ts +144 -0
  407. package/src/tools/trellis/types.ts +82 -0
  408. package/src/tools/trellis/validate.ts +199 -0
  409. package/src/tools/trellis/yaml.ts +309 -0
  410. package/src/tracker/beads.test.ts +454 -0
  411. package/src/tracker/beads.ts +56 -0
  412. package/src/tracker/factory.test.ts +90 -0
  413. package/src/tracker/factory.ts +65 -0
  414. package/src/tracker/sprout.test.ts +461 -0
  415. package/src/tracker/sprout.ts +182 -0
  416. package/src/tracker/types.ts +52 -0
  417. package/src/trellis/client.test.ts +107 -0
  418. package/src/trellis/client.ts +179 -0
  419. package/src/types.ts +970 -0
  420. package/src/utils/bin.test.ts +10 -0
  421. package/src/utils/bin.ts +37 -0
  422. package/src/utils/browser.test.ts +49 -0
  423. package/src/utils/browser.ts +48 -0
  424. package/src/utils/fs.test.ts +119 -0
  425. package/src/utils/fs.ts +62 -0
  426. package/src/utils/pid.test.ts +152 -0
  427. package/src/utils/pid.ts +130 -0
  428. package/src/utils/process-scan.test.ts +53 -0
  429. package/src/utils/process-scan.ts +76 -0
  430. package/src/utils/time.test.ts +43 -0
  431. package/src/utils/time.ts +37 -0
  432. package/src/utils/version.test.ts +33 -0
  433. package/src/utils/version.ts +70 -0
  434. package/src/version.ts +5 -0
  435. package/src/watchdog/daemon.test.ts +3721 -0
  436. package/src/watchdog/daemon.ts +1257 -0
  437. package/src/watchdog/health.test.ts +830 -0
  438. package/src/watchdog/health.ts +434 -0
  439. package/src/watchdog/triage.test.ts +205 -0
  440. package/src/watchdog/triage.ts +205 -0
  441. package/src/worktree/manager.test.ts +720 -0
  442. package/src/worktree/manager.ts +405 -0
  443. package/src/worktree/process.test.ts +172 -0
  444. package/src/worktree/process.ts +131 -0
  445. package/src/worktree/tmux.test.ts +1616 -0
  446. package/src/worktree/tmux.ts +721 -0
  447. package/templates/CLAUDE.md.tmpl +100 -0
  448. package/templates/copilot-hooks.json.tmpl +13 -0
  449. package/templates/hooks.json.tmpl +109 -0
  450. package/templates/overlay.md.tmpl +88 -0
  451. package/ui/dist/apple-touch-icon-bdy6teep.png +0 -0
  452. package/ui/dist/chunk-8s31f05k.css +1 -0
  453. package/ui/dist/chunk-vm5rz679.js +300 -0
  454. package/ui/dist/favicon-nzb39vza.svg +4 -0
  455. package/ui/dist/index.html +17 -0
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Unit tests for beads molecules module.
3
+ *
4
+ * WHY MOCKING IS USED HERE:
5
+ * The molecules.ts module expects a bd mol API that doesn't exist yet in beads.
6
+ * Expected API: bd mol create --name, bd mol step add, bd mol list, bd mol status
7
+ * Actual API: bd formula, bd cook, bd mol pour, bd mol wisp
8
+ *
9
+ * These tests mock Bun.spawn to verify the module's logic is correct.
10
+ * When the bd API is implemented to match the module's expectations,
11
+ * these can be converted to integration tests using the real bd CLI.
12
+ *
13
+ * See loam record mx-56558b for why mocking is normally avoided.
14
+ */
15
+
16
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
17
+ import { AgentError } from "../errors.ts";
18
+ import {
19
+ createMoleculePrototype,
20
+ getConvoyStatus,
21
+ listPrototypes,
22
+ pourMolecule,
23
+ } from "./molecules.ts";
24
+
25
+ /**
26
+ * Mock Bun.spawn to simulate bd mol CLI responses.
27
+ * Returns a mock process with configurable stdout/stderr/exitCode.
28
+ */
29
+ function mockSpawn(
30
+ stdout: string,
31
+ stderr = "",
32
+ exitCode = 0,
33
+ ): {
34
+ stdout: ReadableStream<Uint8Array>;
35
+ stderr: ReadableStream<Uint8Array>;
36
+ exited: Promise<number>;
37
+ } {
38
+ const stdoutBody = new Response(stdout).body;
39
+ const stderrBody = new Response(stderr).body;
40
+ if (!stdoutBody || !stderrBody) {
41
+ throw new Error("Response body is null");
42
+ }
43
+ return {
44
+ stdout: stdoutBody,
45
+ stderr: stderrBody,
46
+ exited: Promise.resolve(exitCode),
47
+ };
48
+ }
49
+
50
+ let originalSpawn: typeof Bun.spawn;
51
+
52
+ beforeEach(() => {
53
+ // Save original spawn
54
+ originalSpawn = Bun.spawn;
55
+ });
56
+
57
+ describe("molecules", () => {
58
+ beforeEach(() => {
59
+ // Restore original spawn before each test
60
+ Bun.spawn = originalSpawn;
61
+ });
62
+
63
+ afterEach(() => {
64
+ // Ensure cleanup after each test to prevent mock leaks
65
+ Bun.spawn = originalSpawn;
66
+ });
67
+
68
+ describe("createMoleculePrototype", () => {
69
+ test("creates a prototype with ordered steps", async () => {
70
+ let callCount = 0;
71
+ // @ts-expect-error - Mocking Bun.spawn for testing
72
+ Bun.spawn = mock((cmd: string[], _opts?: unknown) => {
73
+ callCount++;
74
+ // First call: bd mol create
75
+ if (callCount === 1) {
76
+ expect(cmd).toEqual(["bd", "mol", "create", "--name", "Test Workflow", "--json"]);
77
+ return mockSpawn(JSON.stringify({ id: "mol-123" }));
78
+ }
79
+ // Subsequent calls: bd mol step add
80
+ expect(cmd[0]).toBe("bd");
81
+ expect(cmd[1]).toBe("mol");
82
+ expect(cmd[2]).toBe("step");
83
+ expect(cmd[3]).toBe("add");
84
+ expect(cmd[4]).toBe("mol-123");
85
+ return mockSpawn(JSON.stringify({ success: true }));
86
+ });
87
+
88
+ const molId = await createMoleculePrototype("/test/dir", {
89
+ name: "Test Workflow",
90
+ steps: [
91
+ { title: "Step 1: Setup", type: "task" },
92
+ { title: "Step 2: Implementation", type: "task" },
93
+ { title: "Step 3: Testing", type: "task" },
94
+ ],
95
+ });
96
+
97
+ expect(molId).toBe("mol-123");
98
+ expect(callCount).toBe(4); // 1 create + 3 step adds
99
+ });
100
+
101
+ test("creates a prototype with default type (task)", async () => {
102
+ let callCount = 0;
103
+ // @ts-expect-error - Mocking Bun.spawn for testing
104
+ Bun.spawn = mock((cmd: string[], _opts?: unknown) => {
105
+ callCount++;
106
+ if (callCount === 1) {
107
+ return mockSpawn(JSON.stringify({ id: "mol-456" }));
108
+ }
109
+ // Check that default type is "task"
110
+ expect(cmd).toContain("--type");
111
+ const typeIndex = cmd.indexOf("--type");
112
+ expect(cmd[typeIndex + 1]).toBe("task");
113
+ return mockSpawn(JSON.stringify({ success: true }));
114
+ });
115
+
116
+ const molId = await createMoleculePrototype("/test/dir", {
117
+ name: "Default Type Workflow",
118
+ steps: [{ title: "Step without explicit type" }],
119
+ });
120
+
121
+ expect(molId).toBe("mol-456");
122
+ expect(callCount).toBe(2); // 1 create + 1 step add
123
+ });
124
+
125
+ test("creates a prototype with empty steps array", async () => {
126
+ // @ts-expect-error - Mocking Bun.spawn for testing
127
+ Bun.spawn = mock(() => {
128
+ return mockSpawn(JSON.stringify({ id: "mol-empty" }));
129
+ });
130
+
131
+ const molId = await createMoleculePrototype("/test/dir", {
132
+ name: "Empty Workflow",
133
+ steps: [],
134
+ });
135
+
136
+ expect(molId).toBe("mol-empty");
137
+ });
138
+
139
+ test("throws AgentError on create failure", async () => {
140
+ // @ts-expect-error - Mocking Bun.spawn for testing
141
+ Bun.spawn = mock(() => {
142
+ return mockSpawn("", "bd mol create failed: invalid name", 1);
143
+ });
144
+
145
+ await expect(
146
+ createMoleculePrototype("/test/dir", {
147
+ name: "Bad",
148
+ steps: [],
149
+ }),
150
+ ).rejects.toThrow(AgentError);
151
+ });
152
+
153
+ test("throws AgentError on step add failure", async () => {
154
+ let callCount = 0;
155
+ // @ts-expect-error - Mocking Bun.spawn for testing
156
+ Bun.spawn = mock(() => {
157
+ callCount++;
158
+ if (callCount === 1) {
159
+ return mockSpawn(JSON.stringify({ id: "mol-789" }));
160
+ }
161
+ // Step add fails
162
+ return mockSpawn("", "step add failed", 1);
163
+ });
164
+
165
+ await expect(
166
+ createMoleculePrototype("/test/dir", {
167
+ name: "Test",
168
+ steps: [{ title: "Step 1" }],
169
+ }),
170
+ ).rejects.toThrow(AgentError);
171
+ });
172
+ });
173
+
174
+ describe("listPrototypes", () => {
175
+ test("returns all created prototypes", async () => {
176
+ // @ts-expect-error - Mocking Bun.spawn for testing
177
+ Bun.spawn = mock(() => {
178
+ return mockSpawn(
179
+ JSON.stringify([
180
+ { id: "mol-1", name: "List Test 1", stepCount: 1 },
181
+ { id: "mol-2", name: "List Test 2", stepCount: 2 },
182
+ ]),
183
+ );
184
+ });
185
+
186
+ const prototypes = await listPrototypes("/test/dir");
187
+
188
+ expect(prototypes).toHaveLength(2);
189
+ expect(prototypes[0]).toEqual({ id: "mol-1", name: "List Test 1", stepCount: 1 });
190
+ expect(prototypes[1]).toEqual({ id: "mol-2", name: "List Test 2", stepCount: 2 });
191
+ });
192
+
193
+ test("returns empty array when no prototypes exist", async () => {
194
+ // @ts-expect-error - Mocking Bun.spawn for testing
195
+ Bun.spawn = mock(() => {
196
+ return mockSpawn(JSON.stringify([]));
197
+ });
198
+
199
+ const prototypes = await listPrototypes("/test/dir");
200
+
201
+ expect(Array.isArray(prototypes)).toBe(true);
202
+ expect(prototypes).toHaveLength(0);
203
+ });
204
+
205
+ test("throws AgentError on failure", async () => {
206
+ // @ts-expect-error - Mocking Bun.spawn for testing
207
+ Bun.spawn = mock(() => {
208
+ return mockSpawn("", "bd mol list failed", 1);
209
+ });
210
+
211
+ await expect(listPrototypes("/test/dir")).rejects.toThrow(AgentError);
212
+ });
213
+
214
+ test("throws AgentError on empty output", async () => {
215
+ // @ts-expect-error - Mocking Bun.spawn for testing
216
+ Bun.spawn = mock(() => {
217
+ return mockSpawn("");
218
+ });
219
+
220
+ await expect(listPrototypes("/test/dir")).rejects.toThrow(AgentError);
221
+ });
222
+ });
223
+
224
+ describe("pourMolecule", () => {
225
+ test("pours a prototype into actual issues", async () => {
226
+ // @ts-expect-error - Mocking Bun.spawn for testing
227
+ Bun.spawn = mock((cmd: string[]) => {
228
+ expect(cmd).toEqual(["bd", "mol", "pour", "mol-123", "--json"]);
229
+ return mockSpawn(JSON.stringify({ ids: ["issue-1", "issue-2", "issue-3"] }));
230
+ });
231
+
232
+ const issueIds = await pourMolecule("/test/dir", {
233
+ prototypeId: "mol-123",
234
+ });
235
+
236
+ expect(Array.isArray(issueIds)).toBe(true);
237
+ expect(issueIds).toHaveLength(3);
238
+ expect(issueIds).toEqual(["issue-1", "issue-2", "issue-3"]);
239
+ });
240
+
241
+ test("applies prefix when provided", async () => {
242
+ // @ts-expect-error - Mocking Bun.spawn for testing
243
+ Bun.spawn = mock((cmd: string[]) => {
244
+ expect(cmd).toEqual(["bd", "mol", "pour", "mol-456", "--json", "--prefix", "v2.0"]);
245
+ return mockSpawn(JSON.stringify({ ids: ["issue-4", "issue-5"] }));
246
+ });
247
+
248
+ const issueIds = await pourMolecule("/test/dir", {
249
+ prototypeId: "mol-456",
250
+ prefix: "v2.0",
251
+ });
252
+
253
+ expect(issueIds).toEqual(["issue-4", "issue-5"]);
254
+ });
255
+
256
+ test("handles empty prototype (0 steps)", async () => {
257
+ // @ts-expect-error - Mocking Bun.spawn for testing
258
+ Bun.spawn = mock(() => {
259
+ return mockSpawn(JSON.stringify({ ids: [] }));
260
+ });
261
+
262
+ const issueIds = await pourMolecule("/test/dir", {
263
+ prototypeId: "mol-empty",
264
+ });
265
+
266
+ expect(Array.isArray(issueIds)).toBe(true);
267
+ expect(issueIds).toHaveLength(0);
268
+ });
269
+
270
+ test("throws AgentError for nonexistent prototype", async () => {
271
+ // @ts-expect-error - Mocking Bun.spawn for testing
272
+ Bun.spawn = mock(() => {
273
+ return mockSpawn("", "prototype not found", 1);
274
+ });
275
+
276
+ await expect(
277
+ pourMolecule("/test/dir", {
278
+ prototypeId: "nonexistent-mol-id",
279
+ }),
280
+ ).rejects.toThrow(AgentError);
281
+ });
282
+ });
283
+
284
+ describe("getConvoyStatus", () => {
285
+ test("returns status for poured prototype", async () => {
286
+ // @ts-expect-error - Mocking Bun.spawn for testing
287
+ Bun.spawn = mock((cmd: string[]) => {
288
+ expect(cmd).toEqual(["bd", "mol", "status", "mol-123", "--json"]);
289
+ return mockSpawn(
290
+ JSON.stringify({
291
+ total: 3,
292
+ completed: 1,
293
+ inProgress: 1,
294
+ blocked: 0,
295
+ }),
296
+ );
297
+ });
298
+
299
+ const status = await getConvoyStatus("/test/dir", "mol-123");
300
+
301
+ expect(status).toBeDefined();
302
+ expect(status.total).toBe(3);
303
+ expect(status.completed).toBe(1);
304
+ expect(status.inProgress).toBe(1);
305
+ expect(status.blocked).toBe(0);
306
+ });
307
+
308
+ test("handles empty poured prototype", async () => {
309
+ // @ts-expect-error - Mocking Bun.spawn for testing
310
+ Bun.spawn = mock(() => {
311
+ return mockSpawn(
312
+ JSON.stringify({
313
+ total: 0,
314
+ completed: 0,
315
+ inProgress: 0,
316
+ blocked: 0,
317
+ }),
318
+ );
319
+ });
320
+
321
+ const status = await getConvoyStatus("/test/dir", "mol-empty");
322
+
323
+ expect(status.total).toBe(0);
324
+ expect(status.completed).toBe(0);
325
+ expect(status.inProgress).toBe(0);
326
+ expect(status.blocked).toBe(0);
327
+ });
328
+
329
+ test("throws AgentError for nonexistent prototype", async () => {
330
+ // @ts-expect-error - Mocking Bun.spawn for testing
331
+ Bun.spawn = mock(() => {
332
+ return mockSpawn("", "prototype not found", 1);
333
+ });
334
+
335
+ await expect(getConvoyStatus("/test/dir", "nonexistent-mol-id")).rejects.toThrow(AgentError);
336
+ });
337
+ });
338
+ });
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Beads molecule management helpers.
3
+ *
4
+ * Wraps `bd mol` commands via Bun.spawn for multi-step workflow prototypes.
5
+ * Molecules are templates with ordered steps. "Pouring" a prototype creates
6
+ * actual issues with dependencies pre-wired.
7
+ *
8
+ * Zero runtime dependencies — only Bun built-in APIs.
9
+ */
10
+
11
+ import { AgentError } from "../errors.ts";
12
+
13
+ // === Types ===
14
+
15
+ export interface MoleculeStep {
16
+ title: string;
17
+ type?: string;
18
+ }
19
+
20
+ export interface MoleculePrototype {
21
+ id: string;
22
+ name: string;
23
+ stepCount: number;
24
+ }
25
+
26
+ export interface ConvoyStatus {
27
+ total: number;
28
+ completed: number;
29
+ inProgress: number;
30
+ blocked: number;
31
+ }
32
+
33
+ // === Internal helpers ===
34
+
35
+ /**
36
+ * Run a shell command and capture its output.
37
+ */
38
+ async function runCommand(
39
+ cmd: string[],
40
+ cwd: string,
41
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
42
+ const proc = Bun.spawn(cmd, {
43
+ cwd,
44
+ stdout: "pipe",
45
+ stderr: "pipe",
46
+ });
47
+ const stdout = await new Response(proc.stdout).text();
48
+ const stderr = await new Response(proc.stderr).text();
49
+ const exitCode = await proc.exited;
50
+ return { stdout, stderr, exitCode };
51
+ }
52
+
53
+ /**
54
+ * Run a `bd` subcommand and throw on failure.
55
+ */
56
+ async function runBd(
57
+ args: string[],
58
+ cwd: string,
59
+ context: string,
60
+ ): Promise<{ stdout: string; stderr: string }> {
61
+ const { stdout, stderr, exitCode } = await runCommand(["bd", ...args], cwd);
62
+ if (exitCode !== 0) {
63
+ throw new AgentError(`bd ${context} failed (exit ${exitCode}): ${stderr.trim()}`);
64
+ }
65
+ return { stdout, stderr };
66
+ }
67
+
68
+ /**
69
+ * Parse JSON output from a bd command.
70
+ * Handles the case where output may be empty or malformed.
71
+ */
72
+ function parseJsonOutput<T>(stdout: string, context: string): T {
73
+ const trimmed = stdout.trim();
74
+ if (trimmed === "") {
75
+ throw new AgentError(`Empty output from bd ${context}`);
76
+ }
77
+ try {
78
+ return JSON.parse(trimmed) as T;
79
+ } catch {
80
+ throw new AgentError(
81
+ `Failed to parse JSON output from bd ${context}: ${trimmed.slice(0, 200)}`,
82
+ );
83
+ }
84
+ }
85
+
86
+ // === Public API ===
87
+
88
+ /**
89
+ * Create a molecule prototype with ordered steps.
90
+ *
91
+ * First creates the prototype via `bd mol create`, then adds each step
92
+ * in order via `bd mol step add`. Returns the prototype ID.
93
+ *
94
+ * @param cwd - Working directory where bd commands should run
95
+ * @param options - Prototype name and ordered steps
96
+ * @returns The molecule prototype ID
97
+ */
98
+ export async function createMoleculePrototype(
99
+ cwd: string,
100
+ options: { name: string; steps: MoleculeStep[] },
101
+ ): Promise<string> {
102
+ const { stdout } = await runBd(
103
+ ["mol", "create", "--name", options.name, "--json"],
104
+ cwd,
105
+ "mol create",
106
+ );
107
+ const result = parseJsonOutput<{ id: string }>(stdout, "mol create");
108
+ const molId = result.id;
109
+
110
+ for (const step of options.steps) {
111
+ const stepArgs = [
112
+ "mol",
113
+ "step",
114
+ "add",
115
+ molId,
116
+ "--title",
117
+ step.title,
118
+ "--type",
119
+ step.type ?? "task",
120
+ "--json",
121
+ ];
122
+ await runBd(stepArgs, cwd, `mol step add (${step.title})`);
123
+ }
124
+
125
+ return molId;
126
+ }
127
+
128
+ /**
129
+ * Pour (instantiate) a molecule prototype into actual issues.
130
+ *
131
+ * Creates issues from the prototype with dependencies pre-wired.
132
+ * Optionally applies a prefix to all created issue titles.
133
+ *
134
+ * @param cwd - Working directory where bd commands should run
135
+ * @param options - Prototype ID and optional title prefix
136
+ * @returns Array of created issue IDs
137
+ */
138
+ export async function pourMolecule(
139
+ cwd: string,
140
+ options: { prototypeId: string; prefix?: string },
141
+ ): Promise<string[]> {
142
+ const args = ["mol", "pour", options.prototypeId, "--json"];
143
+ if (options.prefix !== undefined) {
144
+ args.push("--prefix", options.prefix);
145
+ }
146
+ const { stdout } = await runBd(args, cwd, "mol pour");
147
+ const result = parseJsonOutput<{ ids: string[] }>(stdout, "mol pour");
148
+ return result.ids;
149
+ }
150
+
151
+ /**
152
+ * List all molecule prototypes.
153
+ *
154
+ * @param cwd - Working directory where bd commands should run
155
+ * @returns Array of prototype summaries
156
+ */
157
+ export async function listPrototypes(cwd: string): Promise<MoleculePrototype[]> {
158
+ const { stdout } = await runBd(["mol", "list", "--json"], cwd, "mol list");
159
+ const result = parseJsonOutput<Array<{ id: string; name: string; stepCount: number }>>(
160
+ stdout,
161
+ "mol list",
162
+ );
163
+ return result.map((entry) => ({
164
+ id: entry.id,
165
+ name: entry.name,
166
+ stepCount: entry.stepCount,
167
+ }));
168
+ }
169
+
170
+ /**
171
+ * Get the convoy status for a molecule prototype instance.
172
+ *
173
+ * Returns counts of total, completed, in-progress, and blocked issues
174
+ * that were poured from this prototype.
175
+ *
176
+ * @param cwd - Working directory where bd commands should run
177
+ * @param prototypeId - The prototype ID to check status for
178
+ * @returns Status counts for the convoy
179
+ */
180
+ export async function getConvoyStatus(cwd: string, prototypeId: string): Promise<ConvoyStatus> {
181
+ const { stdout } = await runBd(
182
+ ["mol", "status", prototypeId, "--json"],
183
+ cwd,
184
+ `mol status ${prototypeId}`,
185
+ );
186
+ const result = parseJsonOutput<{
187
+ total: number;
188
+ completed: number;
189
+ inProgress: number;
190
+ blocked: number;
191
+ }>(stdout, `mol status ${prototypeId}`);
192
+ return {
193
+ total: result.total,
194
+ completed: result.completed,
195
+ inProgress: result.inProgress,
196
+ blocked: result.blocked,
197
+ };
198
+ }