@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,141 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
+ import { mkdtemp } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import {
6
+ cleanupTempDir,
7
+ commitFile,
8
+ createTempGitRepo,
9
+ getDefaultBranch,
10
+ } from "../test-helpers.ts";
11
+ import type { QualityGate } from "../types.ts";
12
+ import { hasWorkToVerify, runQualityGates } from "./quality-gates.ts";
13
+
14
+ describe("runQualityGates", () => {
15
+ let tempDir: string;
16
+
17
+ beforeEach(async () => {
18
+ tempDir = await mkdtemp(join(tmpdir(), "qg-test-"));
19
+ });
20
+
21
+ afterEach(async () => {
22
+ await cleanupTempDir(tempDir);
23
+ });
24
+
25
+ test("returns null when gates list is empty", async () => {
26
+ const result = await runQualityGates([], tempDir);
27
+ expect(result).toBeNull();
28
+ });
29
+
30
+ test("status is 'success' when all gates exit 0", async () => {
31
+ const gates: QualityGate[] = [
32
+ { name: "True", command: "true", description: "always passes" },
33
+ { name: "Echo", command: "echo ok", description: "always passes" },
34
+ ];
35
+ const result = await runQualityGates(gates, tempDir);
36
+ expect(result).not.toBeNull();
37
+ expect(result?.status).toBe("success");
38
+ expect(result?.results).toHaveLength(2);
39
+ expect(result?.results.every((r) => r.passed)).toBe(true);
40
+ });
41
+
42
+ test("status is 'failure' when no gates exit 0", async () => {
43
+ const gates: QualityGate[] = [
44
+ { name: "False1", command: "false", description: "always fails" },
45
+ { name: "False2", command: "false", description: "always fails" },
46
+ ];
47
+ const result = await runQualityGates(gates, tempDir);
48
+ expect(result).not.toBeNull();
49
+ expect(result?.status).toBe("failure");
50
+ expect(result?.results.every((r) => !r.passed)).toBe(true);
51
+ });
52
+
53
+ test("status is 'partial' on mixed exit codes", async () => {
54
+ const gates: QualityGate[] = [
55
+ { name: "Pass", command: "true", description: "passes" },
56
+ { name: "Fail", command: "false", description: "fails" },
57
+ ];
58
+ const result = await runQualityGates(gates, tempDir);
59
+ expect(result).not.toBeNull();
60
+ expect(result?.status).toBe("partial");
61
+ expect(result?.results.filter((r) => r.passed)).toHaveLength(1);
62
+ expect(result?.results.filter((r) => !r.passed)).toHaveLength(1);
63
+ });
64
+
65
+ test("a gate that hangs past the timeout is treated as failed", async () => {
66
+ const gates: QualityGate[] = [
67
+ { name: "Sleeper", command: "sleep 5", description: "intentionally slow" },
68
+ ];
69
+ const result = await runQualityGates(gates, tempDir, { timeoutMs: 200 });
70
+ expect(result).not.toBeNull();
71
+ expect(result?.status).toBe("failure");
72
+ expect(result?.results[0]?.passed).toBe(false);
73
+ expect(result?.results[0]?.exitCode).toBe(-1);
74
+ // Should return well before the 5s the gate would otherwise take
75
+ expect(result?.totalDurationMs).toBeLessThan(2_000);
76
+ });
77
+
78
+ test("captures per-gate duration and exit code", async () => {
79
+ const gates: QualityGate[] = [{ name: "Quick", command: "true", description: "passes fast" }];
80
+ const result = await runQualityGates(gates, tempDir);
81
+ expect(result?.results[0]?.exitCode).toBe(0);
82
+ expect(result?.results[0]?.durationMs).toBeGreaterThanOrEqual(0);
83
+ expect(result?.totalDurationMs).toBeGreaterThanOrEqual(result?.results[0]?.durationMs ?? 0);
84
+ });
85
+ });
86
+
87
+ describe("hasWorkToVerify", () => {
88
+ let repoDir: string;
89
+
90
+ beforeEach(async () => {
91
+ repoDir = await createTempGitRepo();
92
+ });
93
+
94
+ afterEach(async () => {
95
+ await cleanupTempDir(repoDir);
96
+ });
97
+
98
+ test("returns false on a fresh repo with no commits past base and a clean tree", async () => {
99
+ const branch = await getDefaultBranch(repoDir);
100
+ const result = await hasWorkToVerify(repoDir, branch);
101
+ expect(result).toBe(false);
102
+ });
103
+
104
+ test("returns true when worktree has uncommitted changes", async () => {
105
+ const branch = await getDefaultBranch(repoDir);
106
+ await Bun.write(join(repoDir, "dirty.txt"), "uncommitted content");
107
+ const result = await hasWorkToVerify(repoDir, branch);
108
+ expect(result).toBe(true);
109
+ });
110
+
111
+ test("returns true when there are commits past base", async () => {
112
+ // Pin a "base-ref" branch at the initial commit, then add a new commit
113
+ // on the working branch so HEAD is one commit ahead of base-ref.
114
+ const proc = Bun.spawn(["git", "branch", "base-ref", "HEAD"], { cwd: repoDir });
115
+ await proc.exited;
116
+ await commitFile(repoDir, "new-file.txt", "second commit", "second commit");
117
+
118
+ const result = await hasWorkToVerify(repoDir, "base-ref");
119
+ expect(result).toBe(true);
120
+ });
121
+
122
+ test("returns true when base ref cannot be resolved (fail open)", async () => {
123
+ const result = await hasWorkToVerify(repoDir, "definitely-not-a-real-ref");
124
+ expect(result).toBe(true);
125
+ });
126
+
127
+ test("defaults baseRef to 'main' when not provided", async () => {
128
+ // On a clean repo with default branch 'main' the function should resolve
129
+ // 'main' successfully and report no work to verify.
130
+ const branch = await getDefaultBranch(repoDir);
131
+ // Skip this assertion if the default branch isn't 'main' (e.g., master on
132
+ // some CI runners) — fall back to passing the explicit branch.
133
+ if (branch === "main") {
134
+ const result = await hasWorkToVerify(repoDir);
135
+ expect(result).toBe(false);
136
+ } else {
137
+ const result = await hasWorkToVerify(repoDir, branch);
138
+ expect(result).toBe(false);
139
+ }
140
+ });
141
+ });
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Quality-gate runner used at session-end to determine the outcome status
3
+ * threaded into loam record writes (success / partial / failure).
4
+ *
5
+ * Used by `src/commands/log.ts` session-end handler. Cheap precheck via
6
+ * `hasWorkToVerify()` lets read-only agents (scout/reviewer) skip gate
7
+ * execution entirely when no commits or uncommitted changes exist.
8
+ */
9
+
10
+ import type { QualityGate } from "../types.ts";
11
+
12
+ export interface QualityGateResult {
13
+ name: string;
14
+ command: string;
15
+ passed: boolean;
16
+ durationMs: number;
17
+ exitCode: number;
18
+ }
19
+
20
+ export interface QualityGateOutcome {
21
+ status: "success" | "partial" | "failure";
22
+ results: QualityGateResult[];
23
+ totalDurationMs: number;
24
+ }
25
+
26
+ const DEFAULT_TIMEOUT_MS = 300_000;
27
+
28
+ /**
29
+ * Run each configured quality gate against `cwd` and aggregate the result.
30
+ *
31
+ * Returns null when `gates` is empty.
32
+ *
33
+ * - all passed -> "success"
34
+ * - none passed -> "failure"
35
+ * - mixed -> "partial"
36
+ */
37
+ export async function runQualityGates(
38
+ gates: QualityGate[],
39
+ cwd: string,
40
+ options?: { timeoutMs?: number },
41
+ ): Promise<QualityGateOutcome | null> {
42
+ if (gates.length === 0) return null;
43
+
44
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
45
+ const results: QualityGateResult[] = [];
46
+ const totalStart = Date.now();
47
+
48
+ for (const gate of gates) {
49
+ const argv = gate.command.split(/\s+/).filter((s) => s.length > 0);
50
+ if (argv.length === 0) {
51
+ results.push({
52
+ name: gate.name,
53
+ command: gate.command,
54
+ passed: false,
55
+ durationMs: 0,
56
+ exitCode: -1,
57
+ });
58
+ continue;
59
+ }
60
+
61
+ const start = Date.now();
62
+ let proc: ReturnType<typeof Bun.spawn> | undefined;
63
+ let timer: ReturnType<typeof setTimeout> | undefined;
64
+ let timedOut = false;
65
+ try {
66
+ proc = Bun.spawn(argv, {
67
+ cwd,
68
+ stdout: "ignore",
69
+ stderr: "ignore",
70
+ });
71
+ timer = setTimeout(() => {
72
+ timedOut = true;
73
+ try {
74
+ proc?.kill();
75
+ } catch {
76
+ // best-effort kill
77
+ }
78
+ }, timeoutMs);
79
+ const exitCode = await proc.exited;
80
+ const durationMs = Date.now() - start;
81
+ results.push({
82
+ name: gate.name,
83
+ command: gate.command,
84
+ passed: !timedOut && exitCode === 0,
85
+ durationMs,
86
+ exitCode: timedOut ? -1 : exitCode,
87
+ });
88
+ } catch {
89
+ results.push({
90
+ name: gate.name,
91
+ command: gate.command,
92
+ passed: false,
93
+ durationMs: Date.now() - start,
94
+ exitCode: -1,
95
+ });
96
+ } finally {
97
+ if (timer) clearTimeout(timer);
98
+ }
99
+ }
100
+
101
+ const passedCount = results.filter((r) => r.passed).length;
102
+ let status: "success" | "partial" | "failure";
103
+ if (passedCount === results.length) {
104
+ status = "success";
105
+ } else if (passedCount === 0) {
106
+ status = "failure";
107
+ } else {
108
+ status = "partial";
109
+ }
110
+
111
+ return {
112
+ status,
113
+ results,
114
+ totalDurationMs: Date.now() - totalStart,
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Cheap precheck: returns true when the worktree has commits beyond `baseRef`
120
+ * or any uncommitted modifications. Used to skip gate execution for read-only
121
+ * agents that produced no work.
122
+ *
123
+ * Fails open: if HEAD or `baseRef` cannot be resolved, returns true so that
124
+ * gates still run rather than silently skipping.
125
+ */
126
+ export async function hasWorkToVerify(cwd: string, baseRef = "main"): Promise<boolean> {
127
+ const head = await runGit(cwd, ["rev-parse", "--verify", "HEAD"]);
128
+ const base = await runGit(cwd, ["rev-parse", "--verify", baseRef]);
129
+ if (head.exitCode !== 0 || base.exitCode !== 0) return true;
130
+
131
+ const ahead = await runGit(cwd, ["rev-list", "--count", `${baseRef}..HEAD`]);
132
+ if (ahead.exitCode === 0) {
133
+ const count = Number.parseInt(ahead.stdout.trim(), 10);
134
+ if (Number.isFinite(count) && count > 0) return true;
135
+ }
136
+
137
+ const status = await runGit(cwd, ["status", "--porcelain"]);
138
+ if (status.exitCode === 0 && status.stdout.trim().length > 0) return true;
139
+
140
+ return false;
141
+ }
142
+
143
+ async function runGit(cwd: string, args: string[]): Promise<{ stdout: string; exitCode: number }> {
144
+ try {
145
+ const proc = Bun.spawn(["git", ...args], {
146
+ cwd,
147
+ stdout: "pipe",
148
+ stderr: "ignore",
149
+ });
150
+ const stdout = await new Response(proc.stdout).text();
151
+ const exitCode = await proc.exited;
152
+ return { stdout, exitCode };
153
+ } catch {
154
+ return { stdout: "", exitCode: -1 };
155
+ }
156
+ }
@@ -0,0 +1,72 @@
1
+ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
+ import { jsonError, jsonOutput } from "./json.ts";
3
+
4
+ describe("jsonOutput", () => {
5
+ let written: string[] = [];
6
+ let writeSpy: ReturnType<typeof spyOn>;
7
+
8
+ beforeEach(() => {
9
+ written = [];
10
+ writeSpy = spyOn(process.stdout, "write").mockImplementation((chunk: unknown) => {
11
+ written.push(String(chunk));
12
+ return true;
13
+ });
14
+ });
15
+
16
+ afterEach(() => {
17
+ writeSpy.mockRestore();
18
+ });
19
+
20
+ test("writes success envelope to stdout", () => {
21
+ jsonOutput("status", { agents: [] });
22
+ expect(written).toEqual(['{"success":true,"command":"status","agents":[]}\n']);
23
+ });
24
+
25
+ test("spreads data properties into top-level envelope", () => {
26
+ jsonOutput("agents discover", { count: 3, names: ["a", "b", "c"] });
27
+ const parsed = JSON.parse(written[0] ?? "{}");
28
+ expect(parsed.success).toBe(true);
29
+ expect(parsed.command).toBe("agents discover");
30
+ expect(parsed.count).toBe(3);
31
+ expect(parsed.names).toEqual(["a", "b", "c"]);
32
+ // Data is NOT nested under a "data" key
33
+ expect(parsed.data).toBeUndefined();
34
+ });
35
+
36
+ test("produces single-line JSON (no pretty printing)", () => {
37
+ jsonOutput("status", { agents: [] });
38
+ const line = written[0] ?? "";
39
+ expect(line).not.toContain("\n\t");
40
+ expect(line.trimEnd()).toBe('{"success":true,"command":"status","agents":[]}');
41
+ });
42
+ });
43
+
44
+ describe("jsonError", () => {
45
+ let written: string[] = [];
46
+ let writeSpy: ReturnType<typeof spyOn>;
47
+
48
+ beforeEach(() => {
49
+ written = [];
50
+ writeSpy = spyOn(process.stdout, "write").mockImplementation((chunk: unknown) => {
51
+ written.push(String(chunk));
52
+ return true;
53
+ });
54
+ });
55
+
56
+ afterEach(() => {
57
+ writeSpy.mockRestore();
58
+ });
59
+
60
+ test("writes error envelope to stdout", () => {
61
+ jsonError("status", "no config");
62
+ expect(written).toEqual(['{"success":false,"command":"status","error":"no config"}\n']);
63
+ });
64
+
65
+ test("writes to stdout not stderr", () => {
66
+ const stderrSpy = spyOn(process.stderr, "write").mockImplementation(() => true);
67
+ jsonError("mail send", "connection failed");
68
+ expect(written.length).toBe(1);
69
+ expect(stderrSpy).not.toHaveBeenCalled();
70
+ stderrSpy.mockRestore();
71
+ });
72
+ });
package/src/json.ts ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Standard JSON envelope for CLI output.
3
+ *
4
+ * Success: { success: true, command: "<name>", ...data }
5
+ * Error: { success: false, command: "<name>", error: "<message>" }
6
+ *
7
+ * Matches the ecosystem convention used by loam, sprout, and trellis.
8
+ */
9
+
10
+ /**
11
+ * Write a JSON success envelope to stdout.
12
+ * Spreads data properties into the top-level envelope.
13
+ */
14
+ export function jsonOutput(command: string, data: Record<string, unknown>): void {
15
+ process.stdout.write(`${JSON.stringify({ success: true, command, ...data })}\n`);
16
+ }
17
+
18
+ /**
19
+ * Write a JSON error envelope to stdout (not stderr).
20
+ * With --json, errors go to stdout inside the envelope per cli-standards.md.
21
+ */
22
+ export function jsonError(command: string, error: string): void {
23
+ process.stdout.write(`${JSON.stringify({ success: false, command, error })}\n`);
24
+ }
25
+
26
+ /**
27
+ * Build a JSON success Response for HTTP API handlers.
28
+ * Envelope: { success: true, command: 'serve', data, nextCursor? }
29
+ */
30
+ export function apiJson(
31
+ data: unknown,
32
+ init?: { status?: number; nextCursor?: string | null },
33
+ ): Response {
34
+ const envelope: Record<string, unknown> = { success: true, command: "serve", data };
35
+ if (init?.nextCursor != null) {
36
+ envelope.nextCursor = init.nextCursor;
37
+ }
38
+ return new Response(JSON.stringify(envelope), {
39
+ status: init?.status ?? 200,
40
+ headers: { "Content-Type": "application/json" },
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Build a JSON error Response for HTTP API handlers.
46
+ * Envelope: { success: false, command: 'serve', error }
47
+ */
48
+ export function apiError(message: string, status: number): Response {
49
+ return new Response(JSON.stringify({ success: false, command: "serve", error: message }), {
50
+ status,
51
+ headers: { "Content-Type": "application/json" },
52
+ });
53
+ }