@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,124 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { AiderRuntime } from "./aider.ts";
6
+
7
+ describe("AiderRuntime", () => {
8
+ const runtime = new AiderRuntime();
9
+ let testDir: string;
10
+
11
+ beforeEach(async () => {
12
+ testDir = await mkdtemp(join(tmpdir(), "agentplate-aider-test-"));
13
+ });
14
+
15
+ afterEach(async () => {
16
+ await rm(testDir, { recursive: true });
17
+ });
18
+
19
+ it("has correct id and instruction path", () => {
20
+ expect(runtime.id).toBe("aider");
21
+ expect(runtime.instructionPath).toBe("CONVENTIONS.md");
22
+ });
23
+
24
+ it("buildSpawnCommand includes --yes-always --no-auto-commits and model", () => {
25
+ const cmd = runtime.buildSpawnCommand({
26
+ model: "anthropic/claude-sonnet-4-6",
27
+ permissionMode: "bypass",
28
+ cwd: "/tmp/test",
29
+ env: {},
30
+ });
31
+ expect(cmd).toContain("aider --yes-always --no-auto-commits");
32
+ expect(cmd).toContain("--model anthropic/claude-sonnet-4-6");
33
+ });
34
+
35
+ it("buildSpawnCommand includes append system prompt as --message", () => {
36
+ const cmd = runtime.buildSpawnCommand({
37
+ model: "sonnet",
38
+ permissionMode: "bypass",
39
+ appendSystemPrompt: "You are a scout.",
40
+ cwd: "/tmp/test",
41
+ env: {},
42
+ });
43
+ expect(cmd).toContain("--message");
44
+ expect(cmd).toContain("You are a scout.");
45
+ });
46
+
47
+ it("buildSpawnCommand uses --read for appendSystemPromptFile", () => {
48
+ const cmd = runtime.buildSpawnCommand({
49
+ model: "sonnet",
50
+ permissionMode: "bypass",
51
+ appendSystemPromptFile: "/tmp/role.md",
52
+ cwd: "/tmp/test",
53
+ env: {},
54
+ });
55
+ expect(cmd).toContain("--read '/tmp/role.md'");
56
+ });
57
+
58
+ it("buildPrintCommand returns correct argv", () => {
59
+ const argv = runtime.buildPrintCommand("fix the bug");
60
+ expect(argv[0]).toBe("aider");
61
+ expect(argv).toContain("--message");
62
+ expect(argv).toContain("fix the bug");
63
+ expect(argv).toContain("--yes-always");
64
+ expect(argv).toContain("--no-auto-commits");
65
+ });
66
+
67
+ it("buildPrintCommand includes model when provided", () => {
68
+ const argv = runtime.buildPrintCommand("fix the bug", "gpt-4o");
69
+ expect(argv).toContain("--model");
70
+ expect(argv).toContain("gpt-4o");
71
+ });
72
+
73
+ it("deployConfig writes CONVENTIONS.md", async () => {
74
+ await runtime.deployConfig(
75
+ testDir,
76
+ { content: "# Scout instructions" },
77
+ {
78
+ agentName: "scout-1",
79
+ capability: "scout",
80
+ worktreePath: testDir,
81
+ },
82
+ );
83
+ const content = await readFile(join(testDir, "CONVENTIONS.md"), "utf-8");
84
+ expect(content).toBe("# Scout instructions");
85
+ });
86
+
87
+ it("deployConfig is no-op when overlay is undefined", async () => {
88
+ await runtime.deployConfig(testDir, undefined, {
89
+ agentName: "scout-1",
90
+ capability: "scout",
91
+ worktreePath: testDir,
92
+ });
93
+ const file = Bun.file(join(testDir, "CONVENTIONS.md"));
94
+ expect(await file.exists()).toBe(false);
95
+ });
96
+
97
+ it("detectReady recognizes aider prompt", () => {
98
+ expect(runtime.detectReady("some output\naider> ").phase).toBe("ready");
99
+ expect(runtime.detectReady("> ").phase).toBe("ready");
100
+ expect(runtime.detectReady("Loading...").phase).toBe("loading");
101
+ });
102
+
103
+ it("does not require beacon verification", () => {
104
+ expect(runtime.requiresBeaconVerification()).toBe(false);
105
+ });
106
+
107
+ it("parseTranscript returns null", async () => {
108
+ expect(await runtime.parseTranscript("/nonexistent")).toBeNull();
109
+ });
110
+
111
+ it("buildEnv returns model env vars", () => {
112
+ expect(runtime.buildEnv({ model: "sonnet", env: { OPENAI_API_KEY: "sk-test" } })).toEqual({
113
+ OPENAI_API_KEY: "sk-test",
114
+ });
115
+ });
116
+
117
+ it("buildEnv returns empty object when no env", () => {
118
+ expect(runtime.buildEnv({ model: "sonnet" })).toEqual({});
119
+ });
120
+
121
+ it("getTranscriptDir returns null", () => {
122
+ expect(runtime.getTranscriptDir("/tmp/project")).toBeNull();
123
+ });
124
+ });
@@ -0,0 +1,147 @@
1
+ // Aider runtime adapter for agentplate's AgentRuntime interface.
2
+ // Implements the AgentRuntime contract for the `aider` CLI (Paul Gauthier's AI pair programming tool).
3
+ //
4
+ // Key differences from Claude/Pi adapters:
5
+ // - Interactive: `aider` stays alive in tmux as a REPL-like session
6
+ // - Instruction file: .aider.conf.yml or CONVENTIONS.md (we use CONVENTIONS.md for overlay)
7
+ // - No hooks: Aider has no PreToolUse/PostToolUse hook system
8
+ // - One-shot calls use `aider --message <prompt> --yes-always`
9
+ // - Model is passed via `--model <model>` (supports litellm model strings)
10
+
11
+ import { mkdir } from "node:fs/promises";
12
+ import { join } from "node:path";
13
+ import type { ResolvedModel } from "../types.ts";
14
+ import type {
15
+ AgentRuntime,
16
+ HooksDef,
17
+ OverlayContent,
18
+ ReadyState,
19
+ SpawnOpts,
20
+ TranscriptSummary,
21
+ } from "./types.ts";
22
+
23
+ /**
24
+ * Aider runtime adapter.
25
+ *
26
+ * Implements AgentRuntime for Paul Gauthier's `aider` CLI. Tmux-spawned
27
+ * Aider agents run in interactive mode with `--yes-always` for automatic
28
+ * confirmation of file edits.
29
+ *
30
+ * Security relies on Aider's built-in file-scope limiting — it only edits
31
+ * files explicitly added to its context. No OS-level sandbox or hook guards.
32
+ */
33
+ export class AiderRuntime implements AgentRuntime {
34
+ readonly id = "aider";
35
+
36
+ /** Experimental — community-contributed adapter, not yet battle-tested in production. */
37
+ readonly stability = "experimental" as const;
38
+
39
+ /**
40
+ * Aider reads CONVENTIONS.md from the repo root for project-level instructions.
41
+ * We write the overlay here so Aider picks it up natively.
42
+ */
43
+ readonly instructionPath = "CONVENTIONS.md";
44
+
45
+ /**
46
+ * Build the shell command string to spawn an Aider agent in a tmux pane.
47
+ *
48
+ * Uses `--yes-always` for automatic approval of file edits and
49
+ * `--no-auto-commits` so agentplate controls git operations.
50
+ *
51
+ * @param opts - Spawn options
52
+ * @returns Shell command string suitable for tmux new-session
53
+ */
54
+ buildSpawnCommand(opts: SpawnOpts): string {
55
+ let cmd = "aider --yes-always --no-auto-commits";
56
+
57
+ // Aider accepts litellm model strings: provider/model-name
58
+ cmd += ` --model ${opts.model}`;
59
+
60
+ if (opts.appendSystemPromptFile) {
61
+ const escaped = opts.appendSystemPromptFile.replace(/'/g, "'\\''");
62
+ cmd += ` --read '${escaped}'`;
63
+ } else if (opts.appendSystemPrompt) {
64
+ const escaped = opts.appendSystemPrompt.replace(/'/g, "'\\''");
65
+ cmd += ` --message '${escaped} Read CONVENTIONS.md for your task assignment and begin.'`;
66
+ } else {
67
+ cmd += ` --message 'Read CONVENTIONS.md for your task assignment and begin immediately.'`;
68
+ }
69
+
70
+ return cmd;
71
+ }
72
+
73
+ /**
74
+ * Build argv for a headless one-shot Aider invocation.
75
+ *
76
+ * Uses `--message` for the prompt with `--yes-always` for non-interactive mode.
77
+ *
78
+ * @param prompt - The prompt to pass
79
+ * @param model - Optional model override
80
+ * @returns Argv array for Bun.spawn
81
+ */
82
+ buildPrintCommand(prompt: string, model?: string): string[] {
83
+ const cmd = ["aider", "--message", prompt, "--yes-always", "--no-auto-commits"];
84
+ if (model !== undefined) {
85
+ cmd.push("--model", model);
86
+ }
87
+ return cmd;
88
+ }
89
+
90
+ /**
91
+ * Deploy per-agent instructions to a worktree.
92
+ *
93
+ * Writes the overlay to CONVENTIONS.md (Aider's native conventions file).
94
+ * No hooks or guard extensions — Aider has no hook system.
95
+ *
96
+ * @param worktreePath - Absolute path to the agent's git worktree
97
+ * @param overlay - Overlay content, or undefined for no-op
98
+ * @param _hooks - Unused — Aider has no hook system
99
+ */
100
+ async deployConfig(
101
+ worktreePath: string,
102
+ overlay: OverlayContent | undefined,
103
+ _hooks: HooksDef,
104
+ ): Promise<void> {
105
+ if (!overlay) return;
106
+ await mkdir(worktreePath, { recursive: true });
107
+ await Bun.write(join(worktreePath, this.instructionPath), overlay.content);
108
+ }
109
+
110
+ /**
111
+ * Detect Aider TUI readiness from tmux pane content.
112
+ *
113
+ * Aider shows a prompt like "aider>" or "> " when ready for input.
114
+ *
115
+ * @param paneContent - Captured tmux pane content
116
+ * @returns Readiness phase
117
+ */
118
+ detectReady(paneContent: string): ReadyState {
119
+ // Aider shows its prompt when ready: "aider> " or "> "
120
+ if (/(?:aider)?>\s*$/.test(paneContent)) {
121
+ return { phase: "ready" };
122
+ }
123
+ return { phase: "loading" };
124
+ }
125
+
126
+ /** Aider does not require beacon verification — accepts input reliably. */
127
+ requiresBeaconVerification(): boolean {
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Aider does not produce machine-readable transcripts.
133
+ * Returns null — cost tracking relies on provider billing.
134
+ */
135
+ async parseTranscript(_path: string): Promise<TranscriptSummary | null> {
136
+ return null;
137
+ }
138
+
139
+ buildEnv(model: ResolvedModel): Record<string, string> {
140
+ return model.env ?? {};
141
+ }
142
+
143
+ /** Aider logs to .aider.chat.history.md but not in a parseable transcript format. */
144
+ getTranscriptDir(_projectRoot: string): string | null {
145
+ return null;
146
+ }
147
+ }
@@ -0,0 +1,164 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { AmpRuntime } from "./amp.ts";
6
+
7
+ describe("AmpRuntime", () => {
8
+ const runtime = new AmpRuntime();
9
+ let testDir: string;
10
+
11
+ beforeEach(async () => {
12
+ testDir = await mkdtemp(join(tmpdir(), "agentplate-amp-test-"));
13
+ });
14
+
15
+ afterEach(async () => {
16
+ await rm(testDir, { recursive: true });
17
+ });
18
+
19
+ it("has correct id and instruction path", () => {
20
+ expect(runtime.id).toBe("amp");
21
+ expect(runtime.instructionPath).toBe(".amp/AGENT.md");
22
+ });
23
+
24
+ it("buildSpawnCommand includes --model and --yes", () => {
25
+ const cmd = runtime.buildSpawnCommand({
26
+ model: "anthropic/claude-sonnet-4-6",
27
+ permissionMode: "bypass",
28
+ cwd: "/tmp/test",
29
+ env: {},
30
+ });
31
+ expect(cmd).toContain("amp --model anthropic/claude-sonnet-4-6 --yes");
32
+ });
33
+
34
+ it("buildSpawnCommand includes append system prompt as --prompt", () => {
35
+ const cmd = runtime.buildSpawnCommand({
36
+ model: "sonnet",
37
+ permissionMode: "bypass",
38
+ appendSystemPrompt: "You are a reviewer.",
39
+ cwd: "/tmp/test",
40
+ env: {},
41
+ });
42
+ expect(cmd).toContain("--prompt");
43
+ expect(cmd).toContain("You are a reviewer.");
44
+ });
45
+
46
+ it("buildSpawnCommand uses cat for appendSystemPromptFile", () => {
47
+ const cmd = runtime.buildSpawnCommand({
48
+ model: "sonnet",
49
+ permissionMode: "bypass",
50
+ appendSystemPromptFile: "/tmp/role.md",
51
+ cwd: "/tmp/test",
52
+ env: {},
53
+ });
54
+ expect(cmd).toContain("--prompt");
55
+ expect(cmd).toContain("cat '/tmp/role.md'");
56
+ });
57
+
58
+ it("buildSpawnCommand includes default prompt when no append", () => {
59
+ const cmd = runtime.buildSpawnCommand({
60
+ model: "sonnet",
61
+ permissionMode: "bypass",
62
+ cwd: "/tmp/test",
63
+ env: {},
64
+ });
65
+ expect(cmd).toContain("--prompt");
66
+ expect(cmd).toContain("Read .amp/AGENT.md");
67
+ });
68
+
69
+ it("buildPrintCommand returns correct argv", () => {
70
+ const argv = runtime.buildPrintCommand("review the diff");
71
+ expect(argv[0]).toBe("amp");
72
+ expect(argv).toContain("--prompt");
73
+ expect(argv).toContain("review the diff");
74
+ expect(argv).toContain("--no-input");
75
+ expect(argv).toContain("--yes");
76
+ });
77
+
78
+ it("buildPrintCommand includes model when provided", () => {
79
+ const argv = runtime.buildPrintCommand("review the diff", "gpt-4o");
80
+ expect(argv).toContain("--model");
81
+ expect(argv).toContain("gpt-4o");
82
+ });
83
+
84
+ it("deployConfig writes .amp/AGENT.md", async () => {
85
+ await runtime.deployConfig(
86
+ testDir,
87
+ { content: "# Reviewer instructions" },
88
+ {
89
+ agentName: "reviewer-1",
90
+ capability: "reviewer",
91
+ worktreePath: testDir,
92
+ },
93
+ );
94
+ const content = await readFile(join(testDir, ".amp", "AGENT.md"), "utf-8");
95
+ expect(content).toBe("# Reviewer instructions");
96
+ });
97
+
98
+ it("deployConfig creates parent .amp directory", async () => {
99
+ await runtime.deployConfig(
100
+ testDir,
101
+ { content: "# Test" },
102
+ {
103
+ agentName: "test",
104
+ capability: "scout",
105
+ worktreePath: testDir,
106
+ },
107
+ );
108
+ const file = Bun.file(join(testDir, ".amp", "AGENT.md"));
109
+ expect(await file.exists()).toBe(true);
110
+ });
111
+
112
+ it("deployConfig is no-op when overlay is undefined", async () => {
113
+ await runtime.deployConfig(testDir, undefined, {
114
+ agentName: "test",
115
+ capability: "scout",
116
+ worktreePath: testDir,
117
+ });
118
+ const file = Bun.file(join(testDir, ".amp", "AGENT.md"));
119
+ expect(await file.exists()).toBe(false);
120
+ });
121
+
122
+ it("detectReady requires both prompt AND branding (AND logic)", () => {
123
+ // Both prompt and branding → ready
124
+ expect(runtime.detectReady("some output\namp> ").phase).toBe("ready");
125
+ expect(runtime.detectReady("amp v1.0.0\n> ").phase).toBe("ready");
126
+ expect(runtime.detectReady("AMP CLI\n> ").phase).toBe("ready");
127
+
128
+ // Prompt only (no branding) → loading
129
+ expect(runtime.detectReady("some output\n> ").phase).toBe("loading");
130
+
131
+ // Branding only (no prompt) → loading
132
+ expect(runtime.detectReady("amp v1.0.0").phase).toBe("loading");
133
+ expect(runtime.detectReady("amp v1.2.3 starting...").phase).toBe("loading");
134
+
135
+ // Neither → loading
136
+ expect(runtime.detectReady("Initializing...").phase).toBe("loading");
137
+
138
+ // Substring false-positive prevention: "amp" inside other words must NOT match branding
139
+ expect(runtime.detectReady("this is an example output\n> ").phase).toBe("loading");
140
+ expect(runtime.detectReady("stamped result\n> ").phase).toBe("loading");
141
+ });
142
+
143
+ it("does not require beacon verification", () => {
144
+ expect(runtime.requiresBeaconVerification()).toBe(false);
145
+ });
146
+
147
+ it("parseTranscript returns null", async () => {
148
+ expect(await runtime.parseTranscript("/nonexistent")).toBeNull();
149
+ });
150
+
151
+ it("buildEnv returns model env vars", () => {
152
+ expect(runtime.buildEnv({ model: "sonnet", env: { SRC_ACCESS_TOKEN: "token" } })).toEqual({
153
+ SRC_ACCESS_TOKEN: "token",
154
+ });
155
+ });
156
+
157
+ it("buildEnv returns empty object when no env", () => {
158
+ expect(runtime.buildEnv({ model: "sonnet" })).toEqual({});
159
+ });
160
+
161
+ it("getTranscriptDir returns null", () => {
162
+ expect(runtime.getTranscriptDir("/tmp/project")).toBeNull();
163
+ });
164
+ });
@@ -0,0 +1,154 @@
1
+ // Amp runtime adapter for agentplate's AgentRuntime interface.
2
+ // Implements the AgentRuntime contract for Sourcegraph's `amp` CLI (AI coding agent).
3
+ //
4
+ // Key differences from Claude/Pi adapters:
5
+ // - Interactive: `amp` runs as an interactive chat session in tmux
6
+ // - Instruction file: .amp/AGENT.md (Amp's native instruction file)
7
+ // - No hooks: Amp manages permissions via its own approval system
8
+ // - One-shot calls use `amp --prompt <prompt> --no-input`
9
+ // - Model is passed via `--model <model>`
10
+
11
+ import { mkdir } from "node:fs/promises";
12
+ import { dirname, join } from "node:path";
13
+ import type { ResolvedModel } from "../types.ts";
14
+ import type {
15
+ AgentRuntime,
16
+ HooksDef,
17
+ OverlayContent,
18
+ ReadyState,
19
+ SpawnOpts,
20
+ TranscriptSummary,
21
+ } from "./types.ts";
22
+
23
+ /**
24
+ * Amp runtime adapter.
25
+ *
26
+ * Implements AgentRuntime for Sourcegraph's `amp` CLI. Amp agents run
27
+ * as interactive chat sessions with configurable models and tools.
28
+ *
29
+ * Security is managed by Amp's built-in approval system for file
30
+ * modifications and command execution.
31
+ */
32
+ export class AmpRuntime implements AgentRuntime {
33
+ readonly id = "amp";
34
+
35
+ /** Experimental — community-contributed adapter, not yet battle-tested in production. */
36
+ readonly stability = "experimental" as const;
37
+
38
+ /**
39
+ * Amp reads .amp/AGENT.md from the repo for project-level instructions.
40
+ */
41
+ readonly instructionPath = ".amp/AGENT.md";
42
+
43
+ /**
44
+ * Build the shell command string to spawn an Amp agent in a tmux pane.
45
+ *
46
+ * Uses `amp` in interactive mode with `--model` for model selection
47
+ * and `--yes` for automatic approval.
48
+ *
49
+ * @param opts - Spawn options
50
+ * @returns Shell command string suitable for tmux new-session
51
+ */
52
+ buildSpawnCommand(opts: SpawnOpts): string {
53
+ let cmd = `amp --model ${opts.model} --yes`;
54
+
55
+ if (opts.appendSystemPromptFile) {
56
+ const escaped = opts.appendSystemPromptFile.replace(/'/g, "'\\''");
57
+ cmd += ` --prompt "$(cat '${escaped}') Read .amp/AGENT.md for your task assignment."`;
58
+ } else if (opts.appendSystemPrompt) {
59
+ const escaped =
60
+ `${opts.appendSystemPrompt}\n\nRead .amp/AGENT.md for your task assignment and begin.`.replace(
61
+ /'/g,
62
+ "'\\''",
63
+ );
64
+ cmd += ` --prompt '${escaped}'`;
65
+ } else {
66
+ cmd += ` --prompt 'Read .amp/AGENT.md for your task assignment and begin immediately.'`;
67
+ }
68
+
69
+ return cmd;
70
+ }
71
+
72
+ /**
73
+ * Build argv for a headless one-shot Amp invocation.
74
+ *
75
+ * Uses `amp --prompt <prompt> --no-input --yes` for non-interactive execution.
76
+ *
77
+ * @param prompt - The prompt to pass
78
+ * @param model - Optional model override
79
+ * @returns Argv array for Bun.spawn
80
+ */
81
+ buildPrintCommand(prompt: string, model?: string): string[] {
82
+ const cmd = ["amp", "--prompt", prompt, "--no-input", "--yes"];
83
+ if (model !== undefined) {
84
+ cmd.push("--model", model);
85
+ }
86
+ return cmd;
87
+ }
88
+
89
+ /**
90
+ * Deploy per-agent instructions to a worktree.
91
+ *
92
+ * Writes the overlay to .amp/AGENT.md (Amp's native instruction file).
93
+ * No hooks — Amp manages approvals internally.
94
+ *
95
+ * @param worktreePath - Absolute path to the agent's git worktree
96
+ * @param overlay - Overlay content, or undefined for no-op
97
+ * @param _hooks - Unused — Amp has no hook system
98
+ */
99
+ async deployConfig(
100
+ worktreePath: string,
101
+ overlay: OverlayContent | undefined,
102
+ _hooks: HooksDef,
103
+ ): Promise<void> {
104
+ if (!overlay) return;
105
+ const agentPath = join(worktreePath, this.instructionPath);
106
+ await mkdir(dirname(agentPath), { recursive: true });
107
+ await Bun.write(agentPath, overlay.content);
108
+ }
109
+
110
+ /**
111
+ * Detect Amp TUI readiness from tmux pane content.
112
+ *
113
+ * Amp shows a prompt indicator when ready for input.
114
+ *
115
+ * @param paneContent - Captured tmux pane content
116
+ * @returns Readiness phase
117
+ */
118
+ detectReady(paneContent: string): ReadyState {
119
+ const lower = paneContent.toLowerCase();
120
+
121
+ // Prompt indicator: ">" or "amp>" at end of a line
122
+ const hasPrompt = /(?:amp)?>\s*$/.test(paneContent);
123
+
124
+ // Branding indicator: "amp" as a standalone word (word boundary prevents
125
+ // matching inside "example", "stamp", "&amp;", etc.)
126
+ const hasBranding = /\bamp\b/.test(lower);
127
+
128
+ // Both required (AND logic) to prevent premature ready detection
129
+ // during startup messages like "amp v1.2.3 starting..."
130
+ if (hasPrompt && hasBranding) {
131
+ return { phase: "ready" };
132
+ }
133
+ return { phase: "loading" };
134
+ }
135
+
136
+ /** Amp does not require beacon verification. */
137
+ requiresBeaconVerification(): boolean {
138
+ return false;
139
+ }
140
+
141
+ /** Amp does not produce machine-readable transcripts. */
142
+ async parseTranscript(_path: string): Promise<TranscriptSummary | null> {
143
+ return null;
144
+ }
145
+
146
+ buildEnv(model: ResolvedModel): Record<string, string> {
147
+ return model.env ?? {};
148
+ }
149
+
150
+ /** Amp does not expose a transcript directory. */
151
+ getTranscriptDir(_projectRoot: string): string | null {
152
+ return null;
153
+ }
154
+ }