@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,207 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import type { Command } from "commander";
4
+ import { findSproutDir, projectRootFromSproutDir } from "../config.ts";
5
+ import { hasMarkerSection, replaceMarkerSection, wrapInMarkers } from "../markers.ts";
6
+ import { outputJson, printError, printSuccess } from "../output.ts";
7
+ import { VERSION } from "../version.ts";
8
+
9
+ // Schema version drives outdated-snippet detection. Bump when the snippet body changes
10
+ // in a way agents should re-render. Independent of the package version so patch releases
11
+ // don't mark every existing snippet as outdated.
12
+ const ONBOARD_SCHEMA = 7;
13
+ const SCHEMA_MARKER = `<!-- sprout-onboard-schema:${String(ONBOARD_SCHEMA)} -->`;
14
+ const VERSION_MARKER = `<!-- sprout-onboard:v${VERSION} -->`;
15
+ const LEGACY_VERSION_MARKER_PREFIX = "<!-- sprout-onboard-v:";
16
+
17
+ const CANDIDATE_FILES = ["CLAUDE.md", ".claude/CLAUDE.md", "AGENTS.md"] as const;
18
+
19
+ function onboardSnippet(): string {
20
+ return `## Issue Tracking (Sprout)
21
+ ${VERSION_MARKER}
22
+ ${SCHEMA_MARKER}
23
+
24
+ This project uses [Sprout](https://github.com/jayminwest/sprout) v${VERSION} for git-native issue tracking.
25
+
26
+ **At the start of every session**, run:
27
+ \`\`\`
28
+ sr prime
29
+ \`\`\`
30
+
31
+ This injects session context: rules, command reference, and workflows. Pass \`--format json|compact|markdown|plain|ids\` on any command for agent-friendly output.
32
+
33
+ **Quick reference:**
34
+ - \`sr ready\` — Find unblocked work
35
+ - \`sr search <query>\` — Full-text search across titles + descriptions
36
+ - \`sr create --title "..." --type task --priority 2\` — Create issue
37
+ - \`sr update <id> --status in_progress\` — Claim work
38
+ - \`sr close <id>\` — Complete work
39
+ - \`sr dep add <id> <depends-on>\` — Add dependency between issues
40
+ - \`sr sync\` — Sync with git (run before pushing)
41
+
42
+ ### Planning
43
+ Use \`sr plan\` when work is large or ambiguous enough that an LLM benefits from structured decomposition. Submit spawns one child seed per step; \`step.blocks\` uses forward semantics (step i with \`blocks: [j]\` means step i blocks step j, and step j gets step i's id in its \`blockedBy\`).
44
+
45
+ - \`sr plan templates\` — List built-ins (\`feature\`, \`bug\`, \`refactor\`) plus custom templates
46
+ - \`sr plan prompt <seed-id>\` — Emit a structured prompt the LLM fills in
47
+ - \`sr plan submit <seed-id> --plan <file>\` — Validate + spawn child sprout
48
+ - \`sr plan show <pl-id>\` — View sections, children, sub-plans
49
+ - \`sr plan edit <id> [--name | --section <name> <text> | --step <i> --title/--priority/--type]\` — In-place field edits; bumps revision
50
+ - \`sr plan outcome <pl-id> --result success|partial|failure\` — Record outcome (storage-only)
51
+ - \`sr plan review <pl-id> --by <name>\` — Record reviewer (informational)
52
+
53
+ ### Before You Finish
54
+ 1. Close completed issues: \`sr close <id>\`
55
+ 2. File issues for remaining work: \`sr create --title "..."\`
56
+ 3. Sync and push: \`sr sync && git push\``;
57
+ }
58
+
59
+ function findTargetFile(projectRoot: string): string | null {
60
+ for (const candidate of CANDIDATE_FILES) {
61
+ const fullPath = join(projectRoot, candidate);
62
+ if (existsSync(fullPath)) {
63
+ return fullPath;
64
+ }
65
+ }
66
+ return null;
67
+ }
68
+
69
+ function detectStatus(content: string): "missing" | "current" | "outdated" {
70
+ if (!hasMarkerSection(content)) return "missing";
71
+ // Legacy snippets used `sprout-onboard-v:N`. Always treat them as outdated so
72
+ // the next run upgrades them to the new schema/version markers.
73
+ if (content.includes(LEGACY_VERSION_MARKER_PREFIX)) return "outdated";
74
+ if (content.includes(SCHEMA_MARKER)) return "current";
75
+ return "outdated";
76
+ }
77
+
78
+ export async function run(args: string[]): Promise<void> {
79
+ const jsonMode = args.includes("--json");
80
+ const stdoutMode = args.includes("--stdout");
81
+ const checkMode = args.includes("--check");
82
+
83
+ const sproutDir = await findSproutDir();
84
+ const projectRoot = projectRootFromSproutDir(sproutDir);
85
+
86
+ const targetPath = findTargetFile(projectRoot);
87
+ const snippet = onboardSnippet();
88
+
89
+ // --check mode: report status only
90
+ if (checkMode) {
91
+ if (!targetPath) {
92
+ if (jsonMode) {
93
+ await outputJson({ success: true, command: "onboard", status: "missing", file: null });
94
+ } else {
95
+ console.log("Status: missing (no CLAUDE.md found)");
96
+ }
97
+ return;
98
+ }
99
+ const content = await Bun.file(targetPath).text();
100
+ const status = detectStatus(content);
101
+ if (jsonMode) {
102
+ await outputJson({ success: true, command: "onboard", status, file: targetPath });
103
+ } else {
104
+ console.log(`Status: ${status} (${targetPath})`);
105
+ }
106
+ return;
107
+ }
108
+
109
+ // --stdout mode: print what would be written
110
+ if (stdoutMode) {
111
+ process.stdout.write(wrapInMarkers(snippet));
112
+ process.stdout.write("\n");
113
+ return;
114
+ }
115
+
116
+ // Default mode: write to file
117
+ const filePath = targetPath ?? join(projectRoot, "CLAUDE.md");
118
+ const fileExists = existsSync(filePath);
119
+ const wrappedSnippet = wrapInMarkers(snippet);
120
+
121
+ if (!fileExists) {
122
+ await Bun.write(filePath, `${wrappedSnippet}\n`);
123
+ if (jsonMode) {
124
+ await outputJson({ success: true, command: "onboard", action: "created", file: filePath });
125
+ } else {
126
+ printSuccess(`Created ${filePath} with sprout section`);
127
+ }
128
+ return;
129
+ }
130
+
131
+ const content = await Bun.file(filePath).text();
132
+ const status = detectStatus(content);
133
+
134
+ if (status === "current") {
135
+ if (jsonMode) {
136
+ await outputJson({
137
+ success: true,
138
+ command: "onboard",
139
+ action: "unchanged",
140
+ file: filePath,
141
+ });
142
+ } else {
143
+ printSuccess("Sprout section is already up to date");
144
+ }
145
+ return;
146
+ }
147
+
148
+ if (status === "outdated") {
149
+ const updated = replaceMarkerSection(content, snippet);
150
+ if (!updated) {
151
+ // Defensive: detectStatus saw markers but replaceMarkerSection refused
152
+ // (e.g. markers out of order, truncated, or duplicated). Surface this
153
+ // instead of silently no-op'ing — agents need to know their snippet is stale.
154
+ const msg = `Found sprout markers in ${filePath} but could not replace the section (markers may be malformed, out of order, or duplicated). Fix the file manually or remove the sprout:start/sprout:end block and re-run.`;
155
+ if (jsonMode) {
156
+ await outputJson({
157
+ success: false,
158
+ command: "onboard",
159
+ action: "failed",
160
+ file: filePath,
161
+ error: msg,
162
+ });
163
+ } else {
164
+ printError(msg);
165
+ }
166
+ process.exitCode = 1;
167
+ return;
168
+ }
169
+ await Bun.write(filePath, updated);
170
+ if (jsonMode) {
171
+ await outputJson({
172
+ success: true,
173
+ command: "onboard",
174
+ action: "updated",
175
+ file: filePath,
176
+ });
177
+ } else {
178
+ printSuccess(`Updated sprout section in ${filePath}`);
179
+ }
180
+ return;
181
+ }
182
+
183
+ // status === "missing": append
184
+ const separator = content.endsWith("\n") ? "\n" : "\n\n";
185
+ await Bun.write(filePath, `${content}${separator}${wrappedSnippet}\n`);
186
+ if (jsonMode) {
187
+ await outputJson({ success: true, command: "onboard", action: "appended", file: filePath });
188
+ } else {
189
+ printSuccess(`Added sprout section to ${filePath}`);
190
+ }
191
+ }
192
+
193
+ export function register(program: Command): void {
194
+ program
195
+ .command("onboard")
196
+ .description("Add sprout section to CLAUDE.md / AGENTS.md")
197
+ .option("--stdout", "Print what would be written to stdout")
198
+ .option("--check", "Check status without modifying files")
199
+ .option("--json", "Output as JSON")
200
+ .action(async (opts: { stdout?: boolean; check?: boolean; json?: boolean }) => {
201
+ const args: string[] = [];
202
+ if (opts.stdout) args.push("--stdout");
203
+ if (opts.check) args.push("--check");
204
+ if (opts.json) args.push("--json");
205
+ await run(args);
206
+ });
207
+ }
@@ -0,0 +1,278 @@
1
+ import { findSproutDir, loadPlanTemplates, maxPlanDepth, readConfig } from "../config.ts";
2
+ import { accent, brand, muted, outputJson } from "../output.ts";
3
+ import { type ChildSummary, summarisePlanChildren } from "../plan-context.ts";
4
+ import { readIssues, readPlans } from "../store.ts";
5
+ import type { Issue, Plan, PlanTemplate, SectionSpec } from "../types.ts";
6
+
7
+ interface PlanTreeNode {
8
+ plan: Plan;
9
+ children: ChildSummary[];
10
+ children_plans: PlanTreeEntry[];
11
+ }
12
+
13
+ interface PlanTreeTruncation {
14
+ plan_id: string;
15
+ truncated: true;
16
+ hint: string;
17
+ }
18
+
19
+ type PlanTreeEntry = PlanTreeNode | PlanTreeTruncation;
20
+
21
+ function buildPlansBySeed(plans: Plan[]): Map<string, Plan> {
22
+ const out = new Map<string, Plan>();
23
+ for (const p of plans) {
24
+ const existing = out.get(p.seed);
25
+ if (!existing || existing.updatedAt < p.updatedAt) out.set(p.seed, p);
26
+ }
27
+ return out;
28
+ }
29
+
30
+ function truncationHint(planId: string): string {
31
+ return `depth limit reached — use \`sr plan show ${planId}\` to drill in`;
32
+ }
33
+
34
+ // PLAN_SPEC.md:340, 425, 430 — recurse through nested plans up to max_plan_depth.
35
+ // Depth is 1-indexed: the root plan is at depth 1, nested plans start at 2.
36
+ function buildPlanTree(
37
+ plan: Plan,
38
+ issues: Issue[],
39
+ plansBySeed: Map<string, Plan>,
40
+ depth: number,
41
+ maxDepth: number,
42
+ ): PlanTreeNode {
43
+ const childrenSummary = summarisePlanChildren(plan, issues);
44
+ const childrenPlans: PlanTreeEntry[] = [];
45
+ for (const childId of plan.children) {
46
+ const sub = plansBySeed.get(childId);
47
+ if (!sub) continue;
48
+ const nextDepth = depth + 1;
49
+ if (nextDepth > maxDepth) {
50
+ childrenPlans.push({
51
+ plan_id: sub.id,
52
+ truncated: true,
53
+ hint: truncationHint(sub.id),
54
+ });
55
+ } else {
56
+ childrenPlans.push(buildPlanTree(sub, issues, plansBySeed, nextDepth, maxDepth));
57
+ }
58
+ }
59
+ return { plan, children: childrenSummary, children_plans: childrenPlans };
60
+ }
61
+
62
+ function renderPlanSections(plan: Plan, template: PlanTemplate | undefined): void {
63
+ console.log(brand("Sections:"));
64
+ const order = ["context", "approach", "alternatives", "steps", "risks", "acceptance"];
65
+ const knownKeys = new Set(order);
66
+ const orderedKeys = [
67
+ ...order.filter((k) => k in plan.sections),
68
+ ...Object.keys(plan.sections).filter((k) => !knownKeys.has(k)),
69
+ ];
70
+ for (const key of orderedKeys) {
71
+ const value = plan.sections[key];
72
+ const spec = template?.sections[key];
73
+ console.log(` ${accent.bold(key)}`);
74
+ if (value === undefined || value === null) {
75
+ console.log(muted(" (empty)"));
76
+ continue;
77
+ }
78
+ if (typeof value === "string") {
79
+ for (const line of value.split("\n")) console.log(` ${line}`);
80
+ continue;
81
+ }
82
+ if (Array.isArray(value)) {
83
+ if (value.length === 0) {
84
+ console.log(muted(" (none)"));
85
+ continue;
86
+ }
87
+ renderListSection(value, spec);
88
+ continue;
89
+ }
90
+ console.log(` ${JSON.stringify(value)}`);
91
+ }
92
+ }
93
+
94
+ function renderListSection(entries: unknown[], spec: SectionSpec | undefined): void {
95
+ const kind = spec?.kind;
96
+ const itemSpec = spec?.item;
97
+ entries.forEach((entry, i) => {
98
+ const marker = ` ${i + 1}.`;
99
+ if (typeof entry === "string") {
100
+ console.log(`${marker} ${entry}`);
101
+ return;
102
+ }
103
+ if (kind === "steps" && isPlainRecord(entry)) {
104
+ renderStepEntry(marker, entry);
105
+ return;
106
+ }
107
+ if (kind === "list" && isPlainRecord(entry) && isItemSchema(itemSpec)) {
108
+ renderListEntry(marker, entry, itemSpec);
109
+ return;
110
+ }
111
+ console.log(`${marker} ${JSON.stringify(entry)}`);
112
+ });
113
+ }
114
+
115
+ function renderStepEntry(marker: string, entry: Record<string, unknown>): void {
116
+ const title = typeof entry.title === "string" ? entry.title : JSON.stringify(entry);
117
+ console.log(`${marker} ${title}`);
118
+ const subIndent = " ".repeat(marker.length + 1);
119
+ const blocks = entry.blocks;
120
+ if (Array.isArray(blocks) && blocks.length > 0) {
121
+ // blocks values are stored 1-based (sprout-185f), so render verbatim.
122
+ const labels = blocks
123
+ .map((b) => (typeof b === "number" ? String(b) : JSON.stringify(b)))
124
+ .join(", ");
125
+ console.log(`${subIndent}${muted(`blocks: ${labels}`)}`);
126
+ }
127
+ if (entry.requires_plan === true) {
128
+ console.log(`${subIndent}${muted("requires_plan: true")}`);
129
+ }
130
+ if (typeof entry.plan_template === "string" && entry.plan_template.length > 0) {
131
+ console.log(`${subIndent}${muted(`plan_template: ${entry.plan_template}`)}`);
132
+ }
133
+ }
134
+
135
+ function renderListEntry(
136
+ marker: string,
137
+ entry: Record<string, unknown>,
138
+ itemSpec: Record<string, SectionSpec>,
139
+ ): void {
140
+ const subIndent = " ".repeat(marker.length + 1);
141
+ const fieldNames = Object.keys(itemSpec);
142
+ let firstLineWritten = false;
143
+ for (const field of fieldNames) {
144
+ const fv = entry[field];
145
+ if (fv === undefined || fv === null || fv === "") continue;
146
+ const rendered = typeof fv === "string" ? fv : JSON.stringify(fv);
147
+ if (!firstLineWritten) {
148
+ console.log(`${marker} ${field}: ${rendered}`);
149
+ firstLineWritten = true;
150
+ } else {
151
+ console.log(`${subIndent}${field}: ${rendered}`);
152
+ }
153
+ }
154
+ if (!firstLineWritten) {
155
+ console.log(`${marker} ${JSON.stringify(entry)}`);
156
+ }
157
+ }
158
+
159
+ function isPlainRecord(v: unknown): v is Record<string, unknown> {
160
+ return typeof v === "object" && v !== null && !Array.isArray(v);
161
+ }
162
+
163
+ function isItemSchema(item: SectionSpec["item"]): item is Record<string, SectionSpec> {
164
+ return typeof item === "object" && item !== null;
165
+ }
166
+
167
+ function renderNestedPlanHuman(entry: PlanTreeEntry, indent: string): void {
168
+ if ("truncated" in entry) {
169
+ console.log(`${indent}${muted(entry.hint)}`);
170
+ return;
171
+ }
172
+ const { plan, children, children_plans } = entry;
173
+ const nameLabel = plan.name ? ` ${plan.name}` : "";
174
+ console.log(
175
+ `${indent}${brand("Sub-plan:")} ${accent.bold(plan.id)}${nameLabel} ${muted(`[${plan.status}]`)} ${muted(`rev ${plan.revision}`)} ${muted(`seed=${plan.seed}`)}`,
176
+ );
177
+ console.log(`${indent}${muted(`Children (${children.length}):`)}`);
178
+ const childIndent = `${indent} `;
179
+ if (children.length === 0) {
180
+ console.log(`${childIndent}${muted("(none)")}`);
181
+ } else {
182
+ for (const c of children) {
183
+ const tag = c.adopted ? ` ${muted("(adopted)")}` : "";
184
+ console.log(`${childIndent}${accent(c.id)} ${muted(`[${c.status}]`)} ${c.title}${tag}`);
185
+ }
186
+ }
187
+ for (const sub of children_plans) {
188
+ console.log("");
189
+ renderNestedPlanHuman(sub, childIndent);
190
+ }
191
+ }
192
+
193
+ // Accept either a plan id (pl-xxxx) or a seed id; sprout resolve through
194
+ // seed.plan_id (PLAN_SPEC contract: "the seed knows its plan"). The shared
195
+ // helper keeps show/validate/outcome/review consistent so an agent that has a
196
+ // seed id in hand never has to round-trip through `sr plan list` for the
197
+ // pl-xxxx token.
198
+ export async function resolvePlanIdArg(arg: string, dir: string): Promise<string> {
199
+ if (arg.startsWith("pl-")) return arg;
200
+ const issues = await readIssues(dir);
201
+ const seed = issues.find((i) => i.id === arg);
202
+ if (!seed) {
203
+ throw new Error(`Plan not found: ${arg}. Run 'sr plan list' to see available plans.`);
204
+ }
205
+ if (!seed.plan_id) {
206
+ throw new Error(
207
+ `Seed ${arg} has no plan. Submit one with 'sr plan submit ${arg} --plan <file>'.`,
208
+ );
209
+ }
210
+ return seed.plan_id;
211
+ }
212
+
213
+ export async function runShow(idArg: string, jsonMode: boolean): Promise<void> {
214
+ const dir = await findSproutDir();
215
+ const planId = await resolvePlanIdArg(idArg, dir);
216
+ const config = await readConfig(dir);
217
+ const maxDepth = maxPlanDepth(config);
218
+ const plans = await readPlans(dir);
219
+ const plan = plans.find((p) => p.id === planId);
220
+ if (!plan) {
221
+ throw new Error(`Plan not found: ${planId}. Run 'sr plan list' to see available plans.`);
222
+ }
223
+ const issues = await readIssues(dir);
224
+ const plansBySeed = buildPlansBySeed(plans);
225
+ const tree = buildPlanTree(plan, issues, plansBySeed, 1, maxDepth);
226
+ const templates = await loadPlanTemplates(dir);
227
+ const template = templates[plan.template];
228
+
229
+ if (jsonMode) {
230
+ await outputJson({
231
+ success: true,
232
+ command: "plan show",
233
+ plan,
234
+ children: tree.children,
235
+ children_plans: tree.children_plans,
236
+ });
237
+ return;
238
+ }
239
+
240
+ console.log(`${accent.bold(plan.id)} ${brand(plan.status)} ${muted(`rev ${plan.revision}`)}`);
241
+ if (plan.name) console.log(`Name: ${plan.name}`);
242
+ console.log(`Seed: ${accent(plan.seed)}`);
243
+ console.log(`Template: ${plan.template}`);
244
+ console.log(`Created: ${muted(plan.createdAt)}`);
245
+ console.log(`Updated: ${muted(plan.updatedAt)}`);
246
+ if (plan.outcome) {
247
+ const note = plan.outcomeNote ? ` — ${plan.outcomeNote}` : "";
248
+ console.log(`Outcome: ${plan.outcome}${note}`);
249
+ }
250
+ // PLAN_SPEC.md:404-413 — review hint is purely cosmetic and only relevant
251
+ // while a plan is awaiting work or in flight.
252
+ const reviewActionable = plan.status === "approved" || plan.status === "active";
253
+ if (!plan.reviewedBy && reviewActionable) {
254
+ console.log(muted("Review suggested (no reviewer recorded yet)"));
255
+ }
256
+ if (plan.reviewedBy) {
257
+ console.log(`Reviewed: ${plan.reviewedBy}`);
258
+ }
259
+
260
+ console.log("");
261
+ renderPlanSections(plan, template);
262
+
263
+ console.log("");
264
+ console.log(brand(`Children (${tree.children.length}):`));
265
+ if (tree.children.length === 0) {
266
+ console.log(muted(" (none)"));
267
+ } else {
268
+ for (const c of tree.children) {
269
+ const tag = c.adopted ? ` ${muted("(adopted)")}` : "";
270
+ console.log(` ${accent(c.id)} ${muted(`[${c.status}]`)} ${c.title}${tag}`);
271
+ }
272
+ }
273
+
274
+ for (const sub of tree.children_plans) {
275
+ console.log("");
276
+ renderNestedPlanHuman(sub, " ");
277
+ }
278
+ }