@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,183 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { LifecycleError } from "../errors.ts";
4
+ import type { SessionCheckpoint, SessionHandoff } from "../types.ts";
5
+ import { clearCheckpoint, loadCheckpoint, saveCheckpoint } from "./checkpoint.ts";
6
+
7
+ const HANDOFFS_FILENAME = "handoffs.json";
8
+
9
+ /**
10
+ * Load handoffs array from disk.
11
+ * Returns an empty array if the file doesn't exist.
12
+ */
13
+ async function loadHandoffs(agentsDir: string, agentName: string): Promise<SessionHandoff[]> {
14
+ const filePath = join(agentsDir, agentName, HANDOFFS_FILENAME);
15
+ const file = Bun.file(filePath);
16
+ const exists = await file.exists();
17
+
18
+ if (!exists) {
19
+ return [];
20
+ }
21
+
22
+ try {
23
+ const text = await file.text();
24
+ return JSON.parse(text) as SessionHandoff[];
25
+ } catch (err) {
26
+ throw new LifecycleError(`Failed to read handoffs: ${filePath}`, {
27
+ agentName,
28
+ cause: err instanceof Error ? err : undefined,
29
+ });
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Write handoffs array to disk.
35
+ */
36
+ async function writeHandoffs(
37
+ agentsDir: string,
38
+ agentName: string,
39
+ handoffs: SessionHandoff[],
40
+ ): Promise<void> {
41
+ const filePath = join(agentsDir, agentName, HANDOFFS_FILENAME);
42
+ const dir = dirname(filePath);
43
+
44
+ try {
45
+ await mkdir(dir, { recursive: true });
46
+ } catch (err) {
47
+ throw new LifecycleError(`Failed to create handoffs directory: ${dir}`, {
48
+ agentName,
49
+ cause: err instanceof Error ? err : undefined,
50
+ });
51
+ }
52
+
53
+ try {
54
+ await Bun.write(filePath, `${JSON.stringify(handoffs, null, "\t")}\n`);
55
+ } catch (err) {
56
+ throw new LifecycleError(`Failed to write handoffs: ${filePath}`, {
57
+ agentName,
58
+ cause: err instanceof Error ? err : undefined,
59
+ });
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Initiate a session handoff.
65
+ *
66
+ * 1. Builds a SessionCheckpoint from options
67
+ * 2. Saves the checkpoint to disk
68
+ * 3. Builds a SessionHandoff record
69
+ * 4. Appends to handoffs.json
70
+ * 5. Returns the handoff
71
+ */
72
+ export async function initiateHandoff(options: {
73
+ agentsDir: string;
74
+ agentName: string;
75
+ sessionId: string;
76
+ taskId: string;
77
+ reason: SessionHandoff["reason"];
78
+ progressSummary: string;
79
+ pendingWork: string;
80
+ currentBranch: string;
81
+ filesModified: string[];
82
+ loamDomains: string[];
83
+ }): Promise<SessionHandoff> {
84
+ const checkpoint: SessionCheckpoint = {
85
+ agentName: options.agentName,
86
+ taskId: options.taskId,
87
+ sessionId: options.sessionId,
88
+ timestamp: new Date().toISOString(),
89
+ progressSummary: options.progressSummary,
90
+ filesModified: options.filesModified,
91
+ currentBranch: options.currentBranch,
92
+ pendingWork: options.pendingWork,
93
+ loamDomains: options.loamDomains,
94
+ };
95
+
96
+ await saveCheckpoint(options.agentsDir, checkpoint);
97
+
98
+ const handoff: SessionHandoff = {
99
+ fromSessionId: options.sessionId,
100
+ toSessionId: null,
101
+ checkpoint,
102
+ reason: options.reason,
103
+ handoffAt: new Date().toISOString(),
104
+ };
105
+
106
+ const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
107
+ handoffs.push(handoff);
108
+ await writeHandoffs(options.agentsDir, options.agentName, handoffs);
109
+
110
+ return handoff;
111
+ }
112
+
113
+ /**
114
+ * Resume from a pending handoff.
115
+ *
116
+ * Finds the most recent handoff where `toSessionId` is null,
117
+ * loads the associated checkpoint, and returns both.
118
+ * Returns null if no pending handoff exists.
119
+ */
120
+ export async function resumeFromHandoff(options: {
121
+ agentsDir: string;
122
+ agentName: string;
123
+ }): Promise<{ checkpoint: SessionCheckpoint; handoff: SessionHandoff } | null> {
124
+ const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
125
+
126
+ // Find most recent pending handoff (search from end)
127
+ let pendingHandoff: SessionHandoff | undefined;
128
+ for (let i = handoffs.length - 1; i >= 0; i--) {
129
+ const h = handoffs[i];
130
+ if (h !== undefined && h.toSessionId === null) {
131
+ pendingHandoff = h;
132
+ break;
133
+ }
134
+ }
135
+
136
+ if (pendingHandoff === undefined) {
137
+ return null;
138
+ }
139
+
140
+ const checkpoint = await loadCheckpoint(options.agentsDir, options.agentName);
141
+ if (checkpoint === null) {
142
+ return null;
143
+ }
144
+
145
+ return { checkpoint, handoff: pendingHandoff };
146
+ }
147
+
148
+ /**
149
+ * Complete a pending handoff.
150
+ *
151
+ * 1. Loads handoffs.json
152
+ * 2. Finds the most recent handoff with toSessionId === null
153
+ * 3. Sets toSessionId to the new session ID
154
+ * 4. Writes back handoffs.json
155
+ * 5. Clears the checkpoint
156
+ */
157
+ export async function completeHandoff(options: {
158
+ agentsDir: string;
159
+ agentName: string;
160
+ newSessionId: string;
161
+ }): Promise<void> {
162
+ const handoffs = await loadHandoffs(options.agentsDir, options.agentName);
163
+
164
+ // Find most recent pending handoff (search from end)
165
+ let found = false;
166
+ for (let i = handoffs.length - 1; i >= 0; i--) {
167
+ const h = handoffs[i];
168
+ if (h !== undefined && h.toSessionId === null) {
169
+ h.toSessionId = options.newSessionId;
170
+ found = true;
171
+ break;
172
+ }
173
+ }
174
+
175
+ if (!found) {
176
+ throw new LifecycleError("No pending handoff to complete", {
177
+ agentName: options.agentName,
178
+ });
179
+ }
180
+
181
+ await writeHandoffs(options.agentsDir, options.agentName, handoffs);
182
+ await clearCheckpoint(options.agentsDir, options.agentName);
183
+ }
@@ -0,0 +1,153 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { detectMailPollPattern } from "./mail-poll-detect.ts";
3
+
4
+ describe("detectMailPollPattern", () => {
5
+ describe("matched patterns", () => {
6
+ test("until ap mail list with sleep body", () => {
7
+ const result = detectMailPollPattern("until ap mail list; do sleep 1; done");
8
+ expect(result.matched).toBe(true);
9
+ expect(result.reason).toBe("until ap mail loop");
10
+ });
11
+
12
+ test("while ! ap mail check with sleep body", () => {
13
+ const result = detectMailPollPattern("while ! ap mail check; do sleep 5; done");
14
+ expect(result.matched).toBe(true);
15
+ expect(result.reason).toBe("while-not ap mail loop");
16
+ });
17
+
18
+ test("while ! ap mail list --unread with sleep body", () => {
19
+ const result = detectMailPollPattern("while ! ap mail list --unread; do sleep 2; done");
20
+ expect(result.matched).toBe(true);
21
+ expect(result.reason).toBe("while-not ap mail loop");
22
+ });
23
+
24
+ test("until ap mail check with extra args and sleep body", () => {
25
+ const result = detectMailPollPattern("until ap mail check --agent foo; do sleep 1; done");
26
+ expect(result.matched).toBe(true);
27
+ expect(result.reason).toBe("until ap mail loop");
28
+ });
29
+
30
+ test("until [ ... $(ap mail list ... | wc -l) ... ] piped condition", () => {
31
+ const result = detectMailPollPattern(
32
+ `until [ "$(ap mail list --unread | wc -l)" -gt 0 ]; do sleep 1; done`,
33
+ );
34
+ expect(result.matched).toBe(true);
35
+ expect(result.reason).toBe("ap mail piped condition");
36
+ });
37
+
38
+ test("while [ -z $(ap mail check | jq) ] piped condition", () => {
39
+ const result = detectMailPollPattern(
40
+ `while [ -z "$(ap mail check | jq '.id')" ]; do sleep 2; done`,
41
+ );
42
+ expect(result.matched).toBe(true);
43
+ expect(result.reason).toBe("ap mail piped condition");
44
+ });
45
+
46
+ test("multi-line with leading whitespace and tabs is detected", () => {
47
+ const cmd = "\t\tuntil ap mail list;\n\t\tdo\n\t\t\tsleep 1;\n\t\tdone";
48
+ const result = detectMailPollPattern(cmd);
49
+ expect(result.matched).toBe(true);
50
+ expect(result.reason).toBe("until ap mail loop");
51
+ });
52
+
53
+ test("multi-line newline-separated (no semicolons before do/done) is detected", () => {
54
+ const cmd = "until ap mail list\ndo\n sleep 1\ndone";
55
+ const result = detectMailPollPattern(cmd);
56
+ expect(result.matched).toBe(true);
57
+ expect(result.reason).toBe("until ap mail loop");
58
+ });
59
+
60
+ test("while loop with negated ap mail and pipe-through is the piped variant", () => {
61
+ // `while [ ... ]` (no `!`) with `ap mail` substituted inside the test
62
+ // expression is the piped form, not while-not.
63
+ const result = detectMailPollPattern(
64
+ `while [ "$(ap mail list --unread --json)" = "[]" ]; do sleep 3; done`,
65
+ );
66
+ expect(result.matched).toBe(true);
67
+ expect(result.reason).toBe("ap mail piped condition");
68
+ });
69
+
70
+ test("until with extra padding around ! does not derail kind detection", () => {
71
+ // Note: `until !` is unusual but the spec says `!` may have surrounding
72
+ // spaces; we only assert that `until` direct form still classifies.
73
+ const result = detectMailPollPattern("until ap mail check ; do sleep 1 ; done");
74
+ expect(result.matched).toBe(true);
75
+ expect(result.reason).toBe("until ap mail loop");
76
+ });
77
+
78
+ test("while !ap (no space after !) still classifies as while-not", () => {
79
+ const result = detectMailPollPattern("while !ap mail check; do sleep 1; done");
80
+ expect(result.matched).toBe(true);
81
+ expect(result.reason).toBe("while-not ap mail loop");
82
+ });
83
+ });
84
+
85
+ describe("not matched", () => {
86
+ test("ap mail check (no loop wrapper)", () => {
87
+ expect(detectMailPollPattern("ap mail check").matched).toBe(false);
88
+ });
89
+
90
+ test("ap mail list --unread --json (no loop wrapper)", () => {
91
+ expect(detectMailPollPattern("ap mail list --unread --json").matched).toBe(false);
92
+ });
93
+
94
+ test("for loop sending mail (bounded, not a wait-poll)", () => {
95
+ const cmd =
96
+ "for i in 1 2 3; do ap mail send --to lead --subject hi --body x --type status; done";
97
+ expect(detectMailPollPattern(cmd).matched).toBe(false);
98
+ });
99
+
100
+ test("while read line over a file (no ap mail reference)", () => {
101
+ expect(detectMailPollPattern("while read line; do echo $line; done < file.txt").matched).toBe(
102
+ false,
103
+ );
104
+ });
105
+
106
+ test("until-loop with ap mail in condition but no sleep in body (not a poll)", () => {
107
+ // Without `sleep` the body is a one-shot reaction, not a wait-poll.
108
+ expect(detectMailPollPattern("until ap mail check; do echo got-mail; done").matched).toBe(
109
+ false,
110
+ );
111
+ });
112
+
113
+ test("non-string command (undefined) returns matched=false without throwing", () => {
114
+ expect(() => detectMailPollPattern(undefined)).not.toThrow();
115
+ expect(detectMailPollPattern(undefined).matched).toBe(false);
116
+ });
117
+
118
+ test("non-string command (null) returns matched=false", () => {
119
+ expect(detectMailPollPattern(null).matched).toBe(false);
120
+ });
121
+
122
+ test("non-string command (number) returns matched=false", () => {
123
+ expect(detectMailPollPattern(42).matched).toBe(false);
124
+ });
125
+
126
+ test("empty string returns matched=false", () => {
127
+ expect(detectMailPollPattern("").matched).toBe(false);
128
+ });
129
+
130
+ test("for loop with sleep but no ap mail reference is not a poll", () => {
131
+ expect(detectMailPollPattern("for i in 1 2 3; do sleep 1; echo hi; done").matched).toBe(
132
+ false,
133
+ );
134
+ });
135
+ });
136
+
137
+ describe("regex statefulness", () => {
138
+ test("repeated calls return consistent results (no lastIndex leakage)", () => {
139
+ const cmd = "until ap mail list; do sleep 1; done";
140
+ for (let i = 0; i < 5; i++) {
141
+ const result = detectMailPollPattern(cmd);
142
+ expect(result.matched).toBe(true);
143
+ expect(result.reason).toBe("until ap mail loop");
144
+ }
145
+ });
146
+
147
+ test("matched call followed by non-match returns non-match correctly", () => {
148
+ expect(detectMailPollPattern("until ap mail list; do sleep 1; done").matched).toBe(true);
149
+ expect(detectMailPollPattern("ap mail check").matched).toBe(false);
150
+ expect(detectMailPollPattern("until ap mail list; do sleep 1; done").matched).toBe(true);
151
+ });
152
+ });
153
+ });
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Defense-in-depth detector for Bash mail-poll patterns (agentplate-c92c).
3
+ *
4
+ * The lead.md prompt forbids Bash polling for mail (agentplate-fa84) — the
5
+ * primary mitigation. This helper is the runtime backstop: if a future custom
6
+ * overlay or contributed agent definition silently reintroduces the pattern,
7
+ * the turn-runner emits a warning and a custom event so it surfaces in
8
+ * `ap logs` / `ap feed` / the UI. Warn-only by design; the seed's P3 severity
9
+ * is met without aborting the turn.
10
+ *
11
+ * What counts as a wait-poll:
12
+ * 1. A `until` or `while` loop construct.
13
+ * 2. The loop condition references `ap mail check` or `ap mail list`
14
+ * (directly, negated with `!`, or wrapped in `[ "$(...)" ... ]`).
15
+ * 3. The loop body contains `sleep` (otherwise it's bounded work, not a
16
+ * poll).
17
+ *
18
+ * `for` loops are bounded and never classified as wait-polls — `for i in 1 2 3;
19
+ * do ap mail send ...; done` is a legitimate batched send, not a poll.
20
+ */
21
+
22
+ const LOOP_PATTERN =
23
+ /\b(until|while)\b([\s\S]*?)\s*(?:;|\n)\s*do\b([\s\S]*?)\s*(?:;|\n)\s*\bdone\b/g;
24
+ const SLEEP_IN_BODY = /\bsleep\b/;
25
+ const AP_MAIL_REF = /\bap\s+mail\s+(?:check|list)\b/;
26
+ const DIRECT_AP_MAIL = /^ap\s+mail\s+(?:check|list)\b/;
27
+ const NEGATED_AP_MAIL = /^!\s*ap\s+mail\s+(?:check|list)\b/;
28
+
29
+ export interface MailPollDetectionResult {
30
+ matched: boolean;
31
+ reason?: string;
32
+ }
33
+
34
+ /**
35
+ * Pure detector — no I/O, no side effects. Accepts any input and returns
36
+ * `{ matched: false }` for non-string values so callers can pass the raw
37
+ * `event.input.command` field without pre-validation.
38
+ */
39
+ export function detectMailPollPattern(command: unknown): MailPollDetectionResult {
40
+ if (typeof command !== "string") return { matched: false };
41
+
42
+ // Reset lastIndex because the regex is module-level with the `g` flag.
43
+ LOOP_PATTERN.lastIndex = 0;
44
+ let match: RegExpExecArray | null = LOOP_PATTERN.exec(command);
45
+ while (match !== null) {
46
+ const kind = match[1] as "until" | "while";
47
+ const condition = (match[2] ?? "").trim();
48
+ const body = match[3] ?? "";
49
+
50
+ if (!SLEEP_IN_BODY.test(body)) {
51
+ match = LOOP_PATTERN.exec(command);
52
+ continue;
53
+ }
54
+ if (!AP_MAIL_REF.test(condition)) {
55
+ match = LOOP_PATTERN.exec(command);
56
+ continue;
57
+ }
58
+
59
+ if (kind === "until") {
60
+ if (DIRECT_AP_MAIL.test(condition)) {
61
+ return { matched: true, reason: "until ap mail loop" };
62
+ }
63
+ return { matched: true, reason: "ap mail piped condition" };
64
+ }
65
+
66
+ if (NEGATED_AP_MAIL.test(condition)) {
67
+ return { matched: true, reason: "while-not ap mail loop" };
68
+ }
69
+ return { matched: true, reason: "ap mail piped condition" };
70
+ }
71
+
72
+ return { matched: false };
73
+ }