@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,451 @@
1
+ /**
2
+ * CLI command: ap worktree list | clean [--completed] [--all]
3
+ *
4
+ * List shows worktrees with agent status.
5
+ * Clean removes worktree dirs, branch refs (if merged), and tmux sessions.
6
+ * Logs are never auto-deleted.
7
+ */
8
+
9
+ import { existsSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { Command } from "commander";
12
+ import { loadConfig } from "../config.ts";
13
+ import { ValidationError } from "../errors.ts";
14
+ import { jsonOutput } from "../json.ts";
15
+ import { printHint, printSuccess, printWarning } from "../logging/color.ts";
16
+ import { createMailStore } from "../mail/store.ts";
17
+ import { openSessionStore } from "../sessions/compat.ts";
18
+ import { createSessionStore } from "../sessions/store.ts";
19
+ import type { AgentSession } from "../types.ts";
20
+ import {
21
+ isBranchMerged,
22
+ listWorktrees,
23
+ preserveSproutChanges,
24
+ removeWorktree,
25
+ } from "../worktree/manager.ts";
26
+ import { isSessionAlive, killSession } from "../worktree/tmux.ts";
27
+
28
+ /**
29
+ * Check for live child sessions nested inside a worktree's own .agentplate/sessions.db.
30
+ *
31
+ * Returns the live children (agentName + pid). Empty array if no nested DB or no live children.
32
+ */
33
+ export async function checkLiveChildren(
34
+ worktreePath: string,
35
+ ): Promise<{ agentName: string; pid: number }[]> {
36
+ const nestedDb = join(worktreePath, ".agentplate", "sessions.db");
37
+ if (!existsSync(nestedDb)) {
38
+ return [];
39
+ }
40
+
41
+ const store = createSessionStore(nestedDb);
42
+ let sessions: AgentSession[];
43
+ try {
44
+ sessions = store.getAll();
45
+ } finally {
46
+ store.close();
47
+ }
48
+
49
+ const deadStates = new Set(["completed", "zombie"]);
50
+ const liveChildren: { agentName: string; pid: number }[] = [];
51
+
52
+ for (const session of sessions) {
53
+ if (deadStates.has(session.state)) continue;
54
+ if (session.pid === null) continue;
55
+
56
+ // process.kill(pid, 0) throws if the process is dead (ESRCH)
57
+ let alive = false;
58
+ try {
59
+ process.kill(session.pid, 0);
60
+ alive = true;
61
+ } catch {
62
+ // ESRCH — process is dead
63
+ }
64
+
65
+ if (alive) {
66
+ liveChildren.push({ agentName: session.agentName, pid: session.pid });
67
+ }
68
+ }
69
+
70
+ return liveChildren;
71
+ }
72
+
73
+ /**
74
+ * Handle `ap worktree list`.
75
+ */
76
+ async function handleList(root: string, json: boolean): Promise<void> {
77
+ const worktrees = await listWorktrees(root);
78
+ const agentplateDir = join(root, ".agentplate");
79
+ const { store } = openSessionStore(agentplateDir);
80
+ let sessions: AgentSession[];
81
+ try {
82
+ sessions = store.getAll();
83
+ } finally {
84
+ store.close();
85
+ }
86
+
87
+ const agentplateWts = worktrees.filter((wt) => wt.branch.startsWith("agentplate/"));
88
+
89
+ if (json) {
90
+ const entries = agentplateWts.map((wt) => {
91
+ const session = sessions.find((s) => s.worktreePath === wt.path);
92
+ return {
93
+ path: wt.path,
94
+ branch: wt.branch,
95
+ head: wt.head,
96
+ agentName: session?.agentName ?? null,
97
+ state: session?.state ?? null,
98
+ taskId: session?.taskId ?? null,
99
+ };
100
+ });
101
+ jsonOutput("worktree list", { worktrees: entries });
102
+ return;
103
+ }
104
+
105
+ if (agentplateWts.length === 0) {
106
+ printHint("No agent worktrees found");
107
+ return;
108
+ }
109
+
110
+ process.stdout.write(`Agent worktrees: ${agentplateWts.length}\n\n`);
111
+ for (const wt of agentplateWts) {
112
+ const session = sessions.find((s) => s.worktreePath === wt.path);
113
+ const state = session?.state ?? "unknown";
114
+ const agent = session?.agentName ?? "?";
115
+ const bead = session?.taskId ?? "?";
116
+ process.stdout.write(` ${wt.branch}\n`);
117
+ process.stdout.write(` Agent: ${agent} | State: ${state} | Task: ${bead}\n`);
118
+ process.stdout.write(` Path: ${wt.path}\n\n`);
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Handle `ap worktree clean [--completed] [--all] [--force]`.
124
+ */
125
+ async function handleClean(
126
+ opts: { all: boolean; force: boolean; completedOnly: boolean },
127
+ root: string,
128
+ json: boolean,
129
+ canonicalBranch: string,
130
+ ): Promise<void> {
131
+ const { force, completedOnly } = opts;
132
+
133
+ const worktrees = await listWorktrees(root);
134
+ const agentplateDir = join(root, ".agentplate");
135
+ const { store } = openSessionStore(agentplateDir);
136
+
137
+ let sessions: AgentSession[];
138
+ try {
139
+ sessions = store.getAll();
140
+ } catch {
141
+ store.close();
142
+ return;
143
+ }
144
+
145
+ const agentplateWts = worktrees.filter((wt) => wt.branch.startsWith("agentplate/"));
146
+ const cleaned: string[] = [];
147
+ const failed: string[] = [];
148
+ const skipped: string[] = [];
149
+ const sproutPreserved: string[] = [];
150
+ const blockedByChildren: string[] = [];
151
+
152
+ try {
153
+ for (const wt of agentplateWts) {
154
+ const session = sessions.find((s) => s.worktreePath === wt.path);
155
+
156
+ // If --completed (default), only clean worktrees whose agent is done/zombie
157
+ if (completedOnly && session && session.state !== "completed" && session.state !== "zombie") {
158
+ continue;
159
+ }
160
+
161
+ // Lead branches are never merged via the normal pipeline — skip merge check for leads.
162
+ const isLead = session?.capability === "lead";
163
+
164
+ // Check if the branch has been merged into the canonical branch (unless --force or lead)
165
+ if (!force && !isLead && wt.branch.length > 0) {
166
+ let merged = false;
167
+ try {
168
+ merged = await isBranchMerged(root, wt.branch, canonicalBranch);
169
+ } catch {
170
+ // If we can't determine merge status, treat as unmerged (safe default)
171
+ merged = false;
172
+ }
173
+
174
+ if (!merged) {
175
+ skipped.push(wt.branch);
176
+ continue;
177
+ }
178
+ }
179
+
180
+ // Live-children guard: refuse to remove a worktree that has active nested agents.
181
+ // Nested sessions live in {wt.path}/.agentplate/sessions.db (lead worktrees).
182
+ const liveChildren = await checkLiveChildren(wt.path);
183
+ if (liveChildren.length > 0) {
184
+ if (!force) {
185
+ blockedByChildren.push(wt.branch);
186
+ continue;
187
+ }
188
+ // --force: SIGTERM each live child, wait briefly, then proceed.
189
+ if (!json) {
190
+ printWarning(
191
+ `Force-terminating ${liveChildren.length} live child${liveChildren.length === 1 ? "" : "ren"} in ${wt.branch}`,
192
+ );
193
+ for (const child of liveChildren) {
194
+ process.stdout.write(` ${child.agentName} (pid ${child.pid})\n`);
195
+ }
196
+ }
197
+ for (const child of liveChildren) {
198
+ try {
199
+ process.kill(child.pid, "SIGTERM");
200
+ } catch {
201
+ // Best effort
202
+ }
203
+ }
204
+ await Bun.sleep(500);
205
+ }
206
+
207
+ // If --all, clean everything
208
+ // Kill tmux session if still alive
209
+ if (session?.tmuxSession) {
210
+ const alive = await isSessionAlive(session.tmuxSession);
211
+ if (alive) {
212
+ try {
213
+ await killSession(session.tmuxSession);
214
+ } catch {
215
+ // Best effort
216
+ }
217
+ }
218
+ }
219
+
220
+ // Warn about force-deleting unmerged branch (non-lead only)
221
+ if (force && !isLead && wt.branch.length > 0) {
222
+ let merged = false;
223
+ try {
224
+ merged = await isBranchMerged(root, wt.branch, canonicalBranch);
225
+ } catch {
226
+ merged = false;
227
+ }
228
+ if (!merged && !json) {
229
+ printWarning("Force-deleting unmerged branch", wt.branch);
230
+ }
231
+ }
232
+
233
+ // Preserve .sprout/ changes from lead worktrees before removal.
234
+ // Lead branches are never merged, so .sprout/ files would otherwise be lost.
235
+ if (isLead && wt.branch.length > 0) {
236
+ const result = await preserveSproutChanges(
237
+ root,
238
+ wt.branch,
239
+ canonicalBranch,
240
+ session?.agentName ?? "unknown-lead",
241
+ );
242
+ if (result.preserved) {
243
+ sproutPreserved.push(wt.branch);
244
+ if (!json) {
245
+ printSuccess("Preserved .sprout/ changes", session?.agentName ?? "unknown-lead");
246
+ }
247
+ } else if (result.error) {
248
+ printWarning(`Failed to preserve .sprout/ from ${wt.branch}`, result.error);
249
+ }
250
+ }
251
+
252
+ // Remove worktree and its branch.
253
+ // Always force worktree removal since deployed .claude/ files create untracked
254
+ // files that cause non-forced removal to fail.
255
+ // Always force-delete the branch since we're cleaning up finished/zombie agents
256
+ // whose branches are typically unmerged.
257
+ try {
258
+ await removeWorktree(root, wt.path, { force: true, forceBranch: true });
259
+ cleaned.push(wt.branch);
260
+
261
+ if (!json) {
262
+ printSuccess("Removed", wt.branch);
263
+ }
264
+ } catch (err) {
265
+ failed.push(wt.branch);
266
+ if (!json) {
267
+ const msg = err instanceof Error ? err.message : String(err);
268
+ printWarning(`Failed to remove ${wt.branch}`, msg);
269
+ }
270
+ }
271
+ }
272
+
273
+ // Purge mail for cleaned agents
274
+ let mailPurged = 0;
275
+ if (cleaned.length > 0) {
276
+ const mailDbPath = join(root, ".agentplate", "mail.db");
277
+ const mailDbFile = Bun.file(mailDbPath);
278
+ if (await mailDbFile.exists()) {
279
+ const mailStore = createMailStore(mailDbPath);
280
+ try {
281
+ for (const branch of cleaned) {
282
+ const session = sessions.find((s) => s.branchName === branch);
283
+ if (session) {
284
+ mailPurged += mailStore.purge({ agent: session.agentName });
285
+ }
286
+ }
287
+ } finally {
288
+ mailStore.close();
289
+ }
290
+ }
291
+ }
292
+
293
+ // Mark cleaned sessions as zombie in the SessionStore
294
+ for (const branch of cleaned) {
295
+ const session = sessions.find((s) => s.branchName === branch);
296
+ if (session) {
297
+ store.updateState(session.agentName, "zombie");
298
+ }
299
+ }
300
+
301
+ // Prune zombie entries whose worktree paths no longer exist on disk.
302
+ // This prevents the session store from growing unbounded with stale entries.
303
+ const remainingWorktrees = await listWorktrees(root);
304
+ const worktreePaths = new Set(remainingWorktrees.map((wt) => wt.path));
305
+ let pruneCount = 0;
306
+
307
+ // Re-read sessions after state updates to get current zombie list
308
+ const currentSessions = store.getAll();
309
+ for (const session of currentSessions) {
310
+ if (session.state === "zombie" && !worktreePaths.has(session.worktreePath)) {
311
+ store.remove(session.agentName);
312
+ pruneCount++;
313
+ }
314
+ }
315
+
316
+ if (json) {
317
+ jsonOutput("worktree clean", {
318
+ cleaned,
319
+ failed,
320
+ skipped,
321
+ blockedByChildren,
322
+ pruned: pruneCount,
323
+ mailPurged,
324
+ sproutPreserved,
325
+ });
326
+ } else if (
327
+ cleaned.length === 0 &&
328
+ pruneCount === 0 &&
329
+ failed.length === 0 &&
330
+ skipped.length === 0 &&
331
+ blockedByChildren.length === 0 &&
332
+ sproutPreserved.length === 0
333
+ ) {
334
+ printHint("No worktrees to clean");
335
+ } else {
336
+ if (cleaned.length > 0) {
337
+ printSuccess(`Cleaned ${cleaned.length} worktree${cleaned.length === 1 ? "" : "s"}`);
338
+ }
339
+ if (failed.length > 0) {
340
+ printWarning(`Failed to clean ${failed.length} worktree${failed.length === 1 ? "" : "s"}`);
341
+ }
342
+ if (mailPurged > 0) {
343
+ printSuccess(
344
+ `Purged ${mailPurged} mail message${mailPurged === 1 ? "" : "s"} from cleaned agents`,
345
+ );
346
+ }
347
+ if (pruneCount > 0) {
348
+ printSuccess(
349
+ `Pruned ${pruneCount} zombie session${pruneCount === 1 ? "" : "s"} from store`,
350
+ );
351
+ }
352
+ if (sproutPreserved.length > 0) {
353
+ printSuccess(
354
+ `Preserved .sprout/ from ${sproutPreserved.length} lead${sproutPreserved.length === 1 ? "" : "s"}`,
355
+ );
356
+ }
357
+ if (skipped.length > 0) {
358
+ printWarning(
359
+ `Skipped ${skipped.length} worktree${skipped.length === 1 ? "" : "s"} with unmerged branches`,
360
+ );
361
+ for (const branch of skipped) {
362
+ process.stdout.write(` ${branch}\n`);
363
+ }
364
+ printHint("Use --force to delete unmerged branches");
365
+ }
366
+ if (blockedByChildren.length > 0) {
367
+ printWarning(
368
+ `Skipped ${blockedByChildren.length} worktree${blockedByChildren.length === 1 ? "" : "s"} with live child agents`,
369
+ );
370
+ for (const branch of blockedByChildren) {
371
+ process.stdout.write(` ${branch}\n`);
372
+ }
373
+ printHint("Use --force to cascade-terminate live children");
374
+ }
375
+ }
376
+ } finally {
377
+ store.close();
378
+ }
379
+ }
380
+
381
+ export function createWorktreeCommand(): Command {
382
+ const cmd = new Command("worktree").description("Manage agent worktrees");
383
+
384
+ cmd
385
+ .command("list")
386
+ .description("List worktrees with agent status")
387
+ .option("--json", "Output as JSON")
388
+ .action(async (opts: { json?: boolean }) => {
389
+ const cwd = process.cwd();
390
+ const config = await loadConfig(cwd);
391
+ await handleList(config.project.root, opts.json ?? false);
392
+ });
393
+
394
+ cmd
395
+ .command("clean")
396
+ .description("Remove completed worktrees")
397
+ .option("--completed", "Only finished agents (default)")
398
+ .option("--all", "Force remove all worktrees")
399
+ .option("--force", "Delete even if branches are unmerged")
400
+ .option("--json", "Output as JSON")
401
+ .action(
402
+ async (opts: { completed?: boolean; all?: boolean; force?: boolean; json?: boolean }) => {
403
+ const cwd = process.cwd();
404
+ const config = await loadConfig(cwd);
405
+ const all = opts.all ?? false;
406
+ await handleClean(
407
+ {
408
+ all,
409
+ force: opts.force ?? false,
410
+ completedOnly: opts.completed ?? !all,
411
+ },
412
+ config.project.root,
413
+ opts.json ?? false,
414
+ config.project.canonicalBranch,
415
+ );
416
+ },
417
+ );
418
+
419
+ return cmd;
420
+ }
421
+
422
+ /**
423
+ * Entry point for `ap worktree <subcommand> [flags]`.
424
+ *
425
+ * Subcommands: list, clean.
426
+ */
427
+ export async function worktreeCommand(args: string[]): Promise<void> {
428
+ const cmd = createWorktreeCommand();
429
+ cmd.exitOverride();
430
+
431
+ if (args.length === 0) {
432
+ process.stdout.write(cmd.helpInformation());
433
+ return;
434
+ }
435
+
436
+ try {
437
+ await cmd.parseAsync(args, { from: "user" });
438
+ } catch (err: unknown) {
439
+ if (err && typeof err === "object" && "code" in err) {
440
+ const code = (err as { code: string }).code;
441
+ if (code === "commander.helpDisplayed" || code === "commander.version") {
442
+ return;
443
+ }
444
+ if (code === "commander.unknownCommand") {
445
+ const message = err instanceof Error ? err.message : String(err);
446
+ throw new ValidationError(message, { field: "subcommand" });
447
+ }
448
+ }
449
+ throw err;
450
+ }
451
+ }