@coreplane/switchboard 1.204.0 → 1.205.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 (372) hide show
  1. package/dist/assets/config/config.example.yaml +32 -3
  2. package/dist/assets/deploy/cloudflare-memory/worker.ts +129 -3
  3. package/dist/assets/deploy/cloudflare-memory/wrangler.template.jsonc +7 -2
  4. package/dist/assets/deploy/cloudflare-sandbox/worker.ts +4 -1
  5. package/dist/assets/package-lock.json +291 -97
  6. package/dist/assets/package.json +1 -1
  7. package/dist/assets/source.json +3 -3
  8. package/dist/assets/src/agents/registry.ts +466 -0
  9. package/dist/assets/src/config/profile.ts +200 -0
  10. package/dist/assets/src/core/delivery.ts +775 -0
  11. package/dist/assets/src/core/deliverySnapshotStore.ts +200 -0
  12. package/dist/assets/src/core/runLedger/types.ts +6 -0
  13. package/dist/assets/src/core/runRecord.ts +44 -0
  14. package/dist/assets/src/core/ship/contract.ts +502 -0
  15. package/dist/assets/src/core/workerError.ts +12 -0
  16. package/dist/assets/web/dist/.vite/manifest.json +2770 -70
  17. package/dist/assets/web/dist/assets/AppShell-lYVcj-k7.js +1 -0
  18. package/dist/assets/web/dist/assets/{CostsPage-XQ-fQzdz.js → CostsPage-DGSE48l1.js} +1 -1
  19. package/dist/assets/web/dist/assets/DeliveryPage-Cx7kQC_e.js +1 -0
  20. package/dist/assets/web/dist/assets/NotFoundPage-BzWS4Ca1.js +1 -0
  21. package/dist/assets/web/dist/assets/ResidentDetailPage-Bcasasjb.js +1 -0
  22. package/dist/assets/web/dist/assets/ResidentsIndexPage-BJwyrphn.js +1 -0
  23. package/dist/assets/web/dist/assets/RunRoutePage-6eStApqP.js +12 -0
  24. package/dist/assets/web/dist/assets/RunRoutePage-f6TSNPeW.css +1 -0
  25. package/dist/assets/web/dist/assets/RunsIndexPage-CWrkv7v8.js +1 -0
  26. package/dist/assets/web/dist/assets/RunsTabs-DEICQ4FY.js +1 -0
  27. package/dist/assets/web/dist/assets/ScheduledPage-BX2py1X3.js +1 -0
  28. package/dist/assets/web/dist/assets/StatusDot-CwCK84JN.js +1 -0
  29. package/dist/assets/web/dist/assets/Tooltip-CFC88_-Z.js +1 -0
  30. package/dist/assets/web/dist/assets/abap-CLvhMVsD.js +1 -0
  31. package/dist/assets/web/dist/assets/actionscript-3-Cs6JJXT5.js +1 -0
  32. package/dist/assets/web/dist/assets/ada-C5qYipkI.js +1 -0
  33. package/dist/assets/web/dist/assets/ahk-CA9gdOdF.js +1 -0
  34. package/dist/assets/web/dist/assets/ahk2-_6rzW9BS.js +1 -0
  35. package/dist/assets/web/dist/assets/andromeeda-vGVdxbeo.js +1 -0
  36. package/dist/assets/web/dist/assets/angular-html-Cw130Zyi.js +1 -0
  37. package/dist/assets/web/dist/assets/angular-ts-DY1m4C2s.js +1 -0
  38. package/dist/assets/web/dist/assets/apache-U0d_L8uA.js +1 -0
  39. package/dist/assets/web/dist/assets/apex-KFGFyKwG.js +1 -0
  40. package/dist/assets/web/dist/assets/apl-W6Ty7v05.js +1 -0
  41. package/dist/assets/web/dist/assets/applescript-CCn79oCD.js +1 -0
  42. package/dist/assets/web/dist/assets/ara-4CJ0cIlV.js +1 -0
  43. package/dist/assets/web/dist/assets/asciidoc-SCjQUq34.js +1 -0
  44. package/dist/assets/web/dist/assets/asm-Cmm7eHzH.js +1 -0
  45. package/dist/assets/web/dist/assets/astro-DlLVHwVk.js +1 -0
  46. package/dist/assets/web/dist/assets/aurora-x-CDeNXAV0.js +1 -0
  47. package/dist/assets/web/dist/assets/awk-BWXHIvNe.js +1 -0
  48. package/dist/assets/web/dist/assets/ayu-dark-DluEY0Gj.js +1 -0
  49. package/dist/assets/web/dist/assets/ayu-light-C3h-C4tm.js +1 -0
  50. package/dist/assets/web/dist/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  51. package/dist/assets/web/dist/assets/ballerina-B7ZEbQpA.js +1 -0
  52. package/dist/assets/web/dist/assets/bat-qdxAdBWQ.js +1 -0
  53. package/dist/assets/web/dist/assets/beancount-D-usSTwE.js +1 -0
  54. package/dist/assets/web/dist/assets/berry-DKpUyyne.js +1 -0
  55. package/dist/assets/web/dist/assets/bibtex-Ci_nEsc7.js +1 -0
  56. package/dist/assets/web/dist/assets/bicep-CUHmPFLl.js +1 -0
  57. package/dist/assets/web/dist/assets/bird2-CYIUgYqB.js +1 -0
  58. package/dist/assets/web/dist/assets/blade-Bco3tDh4.js +1 -0
  59. package/dist/assets/web/dist/assets/bsl-_VjlB9mv.js +1 -0
  60. package/dist/assets/web/dist/assets/c-1LaFY_cj.js +1 -0
  61. package/dist/assets/web/dist/assets/c3-D0apG41V.js +1 -0
  62. package/dist/assets/web/dist/assets/cadence-CQ2zXKGN.js +1 -0
  63. package/dist/assets/web/dist/assets/cairo-DLTphjLi.js +1 -0
  64. package/dist/assets/web/dist/assets/catppuccin-frappe-C9Q5zVZY.js +1 -0
  65. package/dist/assets/web/dist/assets/catppuccin-latte-CtsyrtPq.js +1 -0
  66. package/dist/assets/web/dist/assets/catppuccin-macchiato-R8nAf1vR.js +1 -0
  67. package/dist/assets/web/dist/assets/catppuccin-mocha-DjuaAJKi.js +1 -0
  68. package/dist/assets/web/dist/assets/chapel-B-OvrOL5.js +1 -0
  69. package/dist/assets/web/dist/assets/clarity-CtfBBspg.js +1 -0
  70. package/dist/assets/web/dist/assets/clojure-DqKBuwfJ.js +1 -0
  71. package/dist/assets/web/dist/assets/cmake-Bj61d0ZC.js +1 -0
  72. package/dist/assets/web/dist/assets/cobol-Ch3EPlHu.js +1 -0
  73. package/dist/assets/web/dist/assets/codeowners-C8r90Shi.js +1 -0
  74. package/dist/assets/web/dist/assets/codeql-oeQT6MSM.js +1 -0
  75. package/dist/assets/web/dist/assets/coffee-hZuITnto.js +1 -0
  76. package/dist/assets/web/dist/assets/common-lisp-Cv5bFMCO.js +1 -0
  77. package/dist/assets/web/dist/assets/coq-DuBRPxYg.js +1 -0
  78. package/dist/assets/web/dist/assets/cpp-B8iRVo8m.js +1 -0
  79. package/dist/assets/web/dist/assets/crystal-DKveI7lr.js +1 -0
  80. package/dist/assets/web/dist/assets/csharp-oqKa8noW.js +1 -0
  81. package/dist/assets/web/dist/assets/css-_2_CD-rr.js +1 -0
  82. package/dist/assets/web/dist/assets/csv-Dx-8-gkx.js +1 -0
  83. package/dist/assets/web/dist/assets/cue-CE9AQfxI.js +1 -0
  84. package/dist/assets/web/dist/assets/cypher-ClKdZ_lG.js +1 -0
  85. package/dist/assets/web/dist/assets/d-qD-0Kul2.js +1 -0
  86. package/dist/assets/web/dist/assets/dark-plus-Cs2F2srj.js +1 -0
  87. package/dist/assets/web/dist/assets/dart-CnvKMtbv.js +1 -0
  88. package/dist/assets/web/dist/assets/dax-BkyTk9wS.js +1 -0
  89. package/dist/assets/web/dist/assets/desktop-Dlh5hvp9.js +1 -0
  90. package/dist/assets/web/dist/assets/diff-woXpYk--.js +1 -0
  91. package/dist/assets/web/dist/assets/dist-BoLiHpua.js +1547 -0
  92. package/dist/assets/web/dist/assets/docker-IyjqRm3v.js +1 -0
  93. package/dist/assets/web/dist/assets/dotenv-_5a1GRtc.js +1 -0
  94. package/dist/assets/web/dist/assets/dracula-BHWKrbxM.js +1 -0
  95. package/dist/assets/web/dist/assets/dracula-soft-5eyTD99u.js +1 -0
  96. package/dist/assets/web/dist/assets/dream-maker-DW3nJb8Q.js +1 -0
  97. package/dist/assets/web/dist/assets/edge-BenMDPct.js +1 -0
  98. package/dist/assets/web/dist/assets/elixir-CBbdEqG6.js +1 -0
  99. package/dist/assets/web/dist/assets/elm-DMub_2lY.js +1 -0
  100. package/dist/assets/web/dist/assets/emacs-lisp-c_oH4hRZ.js +1 -0
  101. package/dist/assets/web/dist/assets/erb-CI9He_Up.js +1 -0
  102. package/dist/assets/web/dist/assets/erlang-Cphh6RMH.js +1 -0
  103. package/dist/assets/web/dist/assets/everforest-dark-sB-x3p7T.js +1 -0
  104. package/dist/assets/web/dist/assets/everforest-light-Df2xbC6M.js +1 -0
  105. package/dist/assets/web/dist/assets/{favicon-CFfbl2AI.js → favicon-CWPcvWvp.js} +1 -1
  106. package/dist/assets/web/dist/assets/fennel-DQxkIbk2.js +1 -0
  107. package/dist/assets/web/dist/assets/fish-BJitypiv.js +1 -0
  108. package/dist/assets/web/dist/assets/fluent-C03EYrpw.js +1 -0
  109. package/dist/assets/web/dist/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
  110. package/dist/assets/web/dist/assets/fortran-free-form-CYNrtFtB.js +1 -0
  111. package/dist/assets/web/dist/assets/fsharp-D13ZGOAj.js +1 -0
  112. package/dist/assets/web/dist/assets/gdresource-xMC7jr7x.js +1 -0
  113. package/dist/assets/web/dist/assets/gdscript-DYvRD3hg.js +1 -0
  114. package/dist/assets/web/dist/assets/gdshader-CBce3t8t.js +1 -0
  115. package/dist/assets/web/dist/assets/genie-CV2tkWYe.js +1 -0
  116. package/dist/assets/web/dist/assets/gherkin-DExj1W_8.js +1 -0
  117. package/dist/assets/web/dist/assets/git-commit-BSykSTBG.js +1 -0
  118. package/dist/assets/web/dist/assets/git-rebase-BBfhnyF8.js +1 -0
  119. package/dist/assets/web/dist/assets/github-dark-C-LZuMrd.js +1 -0
  120. package/dist/assets/web/dist/assets/github-dark-default-DXG-b-1a.js +1 -0
  121. package/dist/assets/web/dist/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  122. package/dist/assets/web/dist/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  123. package/dist/assets/web/dist/assets/github-light-EUqPIrTm.js +1 -0
  124. package/dist/assets/web/dist/assets/github-light-default-BXViO-2h.js +1 -0
  125. package/dist/assets/web/dist/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  126. package/dist/assets/web/dist/assets/gleam-CSRkHgEL.js +1 -0
  127. package/dist/assets/web/dist/assets/glimmer-js-CR9Fxrau.js +1 -0
  128. package/dist/assets/web/dist/assets/glimmer-ts-CwFwX_XS.js +1 -0
  129. package/dist/assets/web/dist/assets/glsl-Daiodp1r.js +1 -0
  130. package/dist/assets/web/dist/assets/gn-ilITqXS6.js +1 -0
  131. package/dist/assets/web/dist/assets/gnuplot-7GGW24-e.js +1 -0
  132. package/dist/assets/web/dist/assets/go-rLFTqkRN.js +1 -0
  133. package/dist/assets/web/dist/assets/graphql-DZvrsEkB.js +1 -0
  134. package/dist/assets/web/dist/assets/groovy-CacY0gHj.js +1 -0
  135. package/dist/assets/web/dist/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  136. package/dist/assets/web/dist/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  137. package/dist/assets/web/dist/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  138. package/dist/assets/web/dist/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  139. package/dist/assets/web/dist/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  140. package/dist/assets/web/dist/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  141. package/dist/assets/web/dist/assets/hack-BaXOzdg7.js +1 -0
  142. package/dist/assets/web/dist/assets/haml-CMskq_VA.js +1 -0
  143. package/dist/assets/web/dist/assets/handlebars-Dhw_f7jD.js +1 -0
  144. package/dist/assets/web/dist/assets/haskell-D8IpX4py.js +1 -0
  145. package/dist/assets/web/dist/assets/haxe-C8oCnwJJ.js +1 -0
  146. package/dist/assets/web/dist/assets/hcl-Dh228itO.js +1 -0
  147. package/dist/assets/web/dist/assets/hjson-CxZEssPk.js +1 -0
  148. package/dist/assets/web/dist/assets/hlsl-Cvrh5tZx.js +1 -0
  149. package/dist/assets/web/dist/assets/horizon-CE9ld1lL.js +1 -0
  150. package/dist/assets/web/dist/assets/horizon-bright-DSNQnXHK.js +1 -0
  151. package/dist/assets/web/dist/assets/houston-CsvMBhTu.js +1 -0
  152. package/dist/assets/web/dist/assets/html-C9k99z0z.js +1 -0
  153. package/dist/assets/web/dist/assets/html-derivative-VckPItXN.js +1 -0
  154. package/dist/assets/web/dist/assets/http-DXU_3h9v.js +1 -0
  155. package/dist/assets/web/dist/assets/hurl-KU24JNdp.js +1 -0
  156. package/dist/assets/web/dist/assets/hxml-Dcm88srW.js +1 -0
  157. package/dist/assets/web/dist/assets/hy-CZbG8q4J.js +1 -0
  158. package/dist/assets/web/dist/assets/imba-DsUTQ-LC.js +1 -0
  159. package/dist/assets/web/dist/assets/indexFormat-B-pd4r7Y.js +1 -0
  160. package/dist/assets/web/dist/assets/ini-B5eOa1yu.js +1 -0
  161. package/dist/assets/web/dist/assets/java-BbZjTNgf.js +1 -0
  162. package/dist/assets/web/dist/assets/javascript-DXCdqcZZ.js +1 -0
  163. package/dist/assets/web/dist/assets/jinja-pDlsjTVp.js +1 -0
  164. package/dist/assets/web/dist/assets/jison-DsXDk66e.js +1 -0
  165. package/dist/assets/web/dist/assets/json-tCxXfRgG.js +1 -0
  166. package/dist/assets/web/dist/assets/json5-BR5RXkoi.js +1 -0
  167. package/dist/assets/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  168. package/dist/assets/web/dist/assets/jsonl-CmCQp5Yx.js +1 -0
  169. package/dist/assets/web/dist/assets/jsonnet-CJTPZ8u_.js +1 -0
  170. package/dist/assets/web/dist/assets/jssm-DXw9l8Rf.js +1 -0
  171. package/dist/assets/web/dist/assets/jsx-B0ZYkCmi.js +1 -0
  172. package/dist/assets/web/dist/assets/julia-BLzzeI6x.js +1 -0
  173. package/dist/assets/web/dist/assets/just-DvD2_60c.js +1 -0
  174. package/dist/assets/web/dist/assets/kanagawa-dragon-Bozd7klA.js +1 -0
  175. package/dist/assets/web/dist/assets/kanagawa-lotus-BmuOG9ZW.js +1 -0
  176. package/dist/assets/web/dist/assets/kanagawa-wave-BML5mF2J.js +1 -0
  177. package/dist/assets/web/dist/assets/kdl-CsD5j6eV.js +1 -0
  178. package/dist/assets/web/dist/assets/kotlin-DhhofPvG.js +1 -0
  179. package/dist/assets/web/dist/assets/kusto-C7mF5XQf.js +1 -0
  180. package/dist/assets/web/dist/assets/laserwave-C_8bwKvT.js +1 -0
  181. package/dist/assets/web/dist/assets/latex-511zn3h7.js +1 -0
  182. package/dist/assets/web/dist/assets/lean-CewbzKMR.js +1 -0
  183. package/dist/assets/web/dist/assets/less-DVTAwKKz.js +1 -0
  184. package/dist/assets/web/dist/assets/light-plus-DVQuIRkW.js +1 -0
  185. package/dist/assets/web/dist/assets/liquid-BD0BkMox.js +1 -0
  186. package/dist/assets/web/dist/assets/llvm-DqHOMS-s.js +1 -0
  187. package/dist/assets/web/dist/assets/log-BNLmms1o.js +1 -0
  188. package/dist/assets/web/dist/assets/logo-Cluzi2Zq.js +1 -0
  189. package/dist/assets/web/dist/assets/lua-NFicKm6N.js +1 -0
  190. package/dist/assets/web/dist/assets/luau-C2pBCSgt.js +1 -0
  191. package/dist/assets/web/dist/assets/main-i3ZNDRLK.css +1 -0
  192. package/dist/assets/web/dist/assets/main-tYcFk9Dc.js +28 -0
  193. package/dist/assets/web/dist/assets/make-Dixweg8N.js +1 -0
  194. package/dist/assets/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  195. package/dist/assets/web/dist/assets/marko-1-G_nEXK.js +1 -0
  196. package/dist/assets/web/dist/assets/material-theme-Bm3Qr25_.js +1 -0
  197. package/dist/assets/web/dist/assets/material-theme-darker-2IIEA8gg.js +1 -0
  198. package/dist/assets/web/dist/assets/material-theme-lighter-uhdI0v04.js +1 -0
  199. package/dist/assets/web/dist/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  200. package/dist/assets/web/dist/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  201. package/dist/assets/web/dist/assets/matlab-D7qyCx1q.js +1 -0
  202. package/dist/assets/web/dist/assets/mdc-DUe3AQLp.js +1 -0
  203. package/dist/assets/web/dist/assets/mdx-DQZ5AkYe.js +1 -0
  204. package/dist/assets/web/dist/assets/mermaid-BxpfTIzt.js +1 -0
  205. package/dist/assets/web/dist/assets/min-dark-BSWPekZh.js +1 -0
  206. package/dist/assets/web/dist/assets/min-light-DDpmG2fV.js +1 -0
  207. package/dist/assets/web/dist/assets/mipsasm-BMqwQI7S.js +1 -0
  208. package/dist/assets/web/dist/assets/mojo-fg40_ntQ.js +1 -0
  209. package/dist/assets/web/dist/assets/monokai-B_bV9PQ9.js +1 -0
  210. package/dist/assets/web/dist/assets/moonbit-DgjMoLWr.js +1 -0
  211. package/dist/assets/web/dist/assets/move-BYnGhZoM.js +1 -0
  212. package/dist/assets/web/dist/assets/narrat-_X_XdTYD.js +1 -0
  213. package/dist/assets/web/dist/assets/nextflow-BJtWHP5T.js +1 -0
  214. package/dist/assets/web/dist/assets/nextflow-groovy-DJMQeKeT.js +1 -0
  215. package/dist/assets/web/dist/assets/nginx-Dg379_bA.js +1 -0
  216. package/dist/assets/web/dist/assets/night-owl-DhmEMT88.js +1 -0
  217. package/dist/assets/web/dist/assets/night-owl-light-eJ-hLW7d.js +1 -0
  218. package/dist/assets/web/dist/assets/nim-BnFq97ZO.js +1 -0
  219. package/dist/assets/web/dist/assets/nix-IvuFDN5E.js +1 -0
  220. package/dist/assets/web/dist/assets/nord-Cb4Vim4T.js +1 -0
  221. package/dist/assets/web/dist/assets/nsis-CjNLYCLg.js +1 -0
  222. package/dist/assets/web/dist/assets/nushell-DHYfO66s.js +1 -0
  223. package/dist/assets/web/dist/assets/objective-c-D1A_Heim.js +1 -0
  224. package/dist/assets/web/dist/assets/objective-cpp-BsSzOQcm.js +1 -0
  225. package/dist/assets/web/dist/assets/ocaml-O90oeIOV.js +1 -0
  226. package/dist/assets/web/dist/assets/odin-B1RWQWA5.js +1 -0
  227. package/dist/assets/web/dist/assets/one-dark-pro-CLwyXe_n.js +1 -0
  228. package/dist/assets/web/dist/assets/one-light-D7Lr4KcI.js +1 -0
  229. package/dist/assets/web/dist/assets/openscad-BUDT5pXO.js +1 -0
  230. package/dist/assets/web/dist/assets/org-F0uiwGvq.js +1 -0
  231. package/dist/assets/web/dist/assets/pascal-4ZHwLPI5.js +1 -0
  232. package/dist/assets/web/dist/assets/perl-B0euczkl.js +1 -0
  233. package/dist/assets/web/dist/assets/php-DkL3k_n7.js +1 -0
  234. package/dist/assets/web/dist/assets/pierre-dark-CpLgRqie.js +1 -0
  235. package/dist/assets/web/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  236. package/dist/assets/web/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
  237. package/dist/assets/web/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  238. package/dist/assets/web/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
  239. package/dist/assets/web/dist/assets/pierre-light-CoaEpmwp.js +1 -0
  240. package/dist/assets/web/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  241. package/dist/assets/web/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
  242. package/dist/assets/web/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  243. package/dist/assets/web/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
  244. package/dist/assets/web/dist/assets/pkl-ot-7Btpt.js +1 -0
  245. package/dist/assets/web/dist/assets/plastic-DQwYfKfQ.js +1 -0
  246. package/dist/assets/web/dist/assets/plsql-DGHpHOYJ.js +1 -0
  247. package/dist/assets/web/dist/assets/po-BiJDBrnU.js +1 -0
  248. package/dist/assets/web/dist/assets/poimandres-DRFjx7u4.js +1 -0
  249. package/dist/assets/web/dist/assets/polar-C7UOKdEL.js +1 -0
  250. package/dist/assets/web/dist/assets/postcss-BXeXVLqQ.js +1 -0
  251. package/dist/assets/web/dist/assets/powerquery-DNMTfnFr.js +1 -0
  252. package/dist/assets/web/dist/assets/powershell-CCSX75yM.js +1 -0
  253. package/dist/assets/web/dist/assets/prisma-DMgNhnYS.js +1 -0
  254. package/dist/assets/web/dist/assets/prolog-iXnhIJG7.js +1 -0
  255. package/dist/assets/web/dist/assets/proto-DB4EqR-F.js +1 -0
  256. package/dist/assets/web/dist/assets/pug-L_OjjZP4.js +1 -0
  257. package/dist/assets/web/dist/assets/puppet-CDv2pdJW.js +1 -0
  258. package/dist/assets/web/dist/assets/purescript-9MfHhQsQ.js +1 -0
  259. package/dist/assets/web/dist/assets/python-gzcpVVnB.js +1 -0
  260. package/dist/assets/web/dist/assets/qml-BMjB00Zz.js +1 -0
  261. package/dist/assets/web/dist/assets/qmldir-DCQb3MpD.js +1 -0
  262. package/dist/assets/web/dist/assets/qss-Fe1Jh2GI.js +1 -0
  263. package/dist/assets/web/dist/assets/r-DoeLdnqR.js +1 -0
  264. package/dist/assets/web/dist/assets/racket-DcIDlBhZ.js +1 -0
  265. package/dist/assets/web/dist/assets/raku-B3gFvitq.js +1 -0
  266. package/dist/assets/web/dist/assets/razor-BzYNkAWy.js +1 -0
  267. package/dist/assets/web/dist/assets/rbs-C0MpOrj4.js +1 -0
  268. package/dist/assets/web/dist/assets/red-DX1BQOs8.js +1 -0
  269. package/dist/assets/web/dist/assets/reg-CRGYupPL.js +1 -0
  270. package/dist/assets/web/dist/assets/regexp-CPmElMk3.js +1 -0
  271. package/dist/assets/web/dist/assets/rel-BtDbiS_P.js +1 -0
  272. package/dist/assets/web/dist/assets/riscv-Ckw8ddFX.js +1 -0
  273. package/dist/assets/web/dist/assets/ron-VUp2lXgN.js +1 -0
  274. package/dist/assets/web/dist/assets/rose-pine-aMsaMD1D.js +1 -0
  275. package/dist/assets/web/dist/assets/rose-pine-dawn-8PwUyIlP.js +1 -0
  276. package/dist/assets/web/dist/assets/rose-pine-moon-DO-qXg-I.js +1 -0
  277. package/dist/assets/web/dist/assets/rosmsg-CAekHB0j.js +1 -0
  278. package/dist/assets/web/dist/assets/rst-DrsjgfI7.js +1 -0
  279. package/dist/assets/web/dist/assets/ruby-cB42ppvx.js +1 -0
  280. package/dist/assets/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  281. package/dist/assets/web/dist/assets/sas-R5Y3NM_I.js +1 -0
  282. package/dist/assets/web/dist/assets/sass-DXrisJhu.js +1 -0
  283. package/dist/assets/web/dist/assets/scala-BiFt_7mu.js +1 -0
  284. package/dist/assets/web/dist/assets/scheme-DQCgrYNe.js +1 -0
  285. package/dist/assets/web/dist/assets/scss-C-zWxV9s.js +1 -0
  286. package/dist/assets/web/dist/assets/sdbl-bTVj8UrX.js +1 -0
  287. package/dist/assets/web/dist/assets/seed-DeKSHrt2.js +6 -0
  288. package/dist/assets/web/dist/assets/shaderlab-TOUzSsQk.js +1 -0
  289. package/dist/assets/web/dist/assets/shellscript-oJF96aAU.js +1 -0
  290. package/dist/assets/web/dist/assets/shellsession-CznECKyi.js +1 -0
  291. package/dist/assets/web/dist/assets/slack-dark-DnToyrRv.js +1 -0
  292. package/dist/assets/web/dist/assets/slack-ochin-B2OO5cIa.js +1 -0
  293. package/dist/assets/web/dist/assets/smalltalk-BHpQb5nM.js +1 -0
  294. package/dist/assets/web/dist/assets/smithy-Dgaz7aur.js +1 -0
  295. package/dist/assets/web/dist/assets/snazzy-light-4G7pJPwS.js +1 -0
  296. package/dist/assets/web/dist/assets/solarized-dark-UdsmMDCL.js +1 -0
  297. package/dist/assets/web/dist/assets/solarized-light-C1IUL_tW.js +1 -0
  298. package/dist/assets/web/dist/assets/solidity-Bj7E1mRn.js +1 -0
  299. package/dist/assets/web/dist/assets/soy-wjHLSRag.js +1 -0
  300. package/dist/assets/web/dist/assets/sparql-D_iOobhT.js +1 -0
  301. package/dist/assets/web/dist/assets/splunk-BC2Px7Mm.js +1 -0
  302. package/dist/assets/web/dist/assets/sql-C_BM8IOW.js +1 -0
  303. package/dist/assets/web/dist/assets/ssh-config-BgfXC-Er.js +1 -0
  304. package/dist/assets/web/dist/assets/stata-D31HO8aQ.js +1 -0
  305. package/dist/assets/web/dist/assets/stylus-B6D30XZt.js +1 -0
  306. package/dist/assets/web/dist/assets/surrealql-CKCLyplA.js +1 -0
  307. package/dist/assets/web/dist/assets/svelte-3geWk2iu.js +1 -0
  308. package/dist/assets/web/dist/assets/swift-CyEgAFGc.js +1 -0
  309. package/dist/assets/web/dist/assets/synthwave-84-nFMaYfgc.js +1 -0
  310. package/dist/assets/web/dist/assets/system-verilog-Dh5ihWbf.js +1 -0
  311. package/dist/assets/web/dist/assets/systemd-BxMlprV5.js +1 -0
  312. package/dist/assets/web/dist/assets/talonscript-CohzipZa.js +1 -0
  313. package/dist/assets/web/dist/assets/tasl-DMoTqEGO.js +1 -0
  314. package/dist/assets/web/dist/assets/tcl-CZd0xW_V.js +1 -0
  315. package/dist/assets/web/dist/assets/templ-DiJr_hTD.js +1 -0
  316. package/dist/assets/web/dist/assets/terraform-DswuEJGm.js +1 -0
  317. package/dist/assets/web/dist/assets/tex-BEJGWyeF.js +1 -0
  318. package/dist/assets/web/dist/assets/tokyo-night-oM2G3aXe.js +1 -0
  319. package/dist/assets/web/dist/assets/toml-CcmNWLt0.js +1 -0
  320. package/dist/assets/web/dist/assets/ts-tags-C8Mzdpxx.js +1 -0
  321. package/dist/assets/web/dist/assets/tsv-sltzmVWM.js +1 -0
  322. package/dist/assets/web/dist/assets/tsx-UQiSm_p3.js +1 -0
  323. package/dist/assets/web/dist/assets/turtle-ByJddavk.js +1 -0
  324. package/dist/assets/web/dist/assets/twig-_Pvzkeo9.js +1 -0
  325. package/dist/assets/web/dist/assets/typescript-BWMkINKK.js +1 -0
  326. package/dist/assets/web/dist/assets/typespec-BRdr0IET.js +1 -0
  327. package/dist/assets/web/dist/assets/typst-Bdg9m-e7.js +1 -0
  328. package/dist/assets/web/dist/assets/v-DBj4K9d_.js +1 -0
  329. package/dist/assets/web/dist/assets/vala-zf12oZj6.js +1 -0
  330. package/dist/assets/web/dist/assets/vb-DOwzaHZ0.js +1 -0
  331. package/dist/assets/web/dist/assets/verilog-B2gwz-sJ.js +1 -0
  332. package/dist/assets/web/dist/assets/vesper-DdrHHSXu.js +1 -0
  333. package/dist/assets/web/dist/assets/vhdl-BroJfC0k.js +1 -0
  334. package/dist/assets/web/dist/assets/viml-DvXPmvsu.js +1 -0
  335. package/dist/assets/web/dist/assets/vitesse-black-fwtXNY1n.js +1 -0
  336. package/dist/assets/web/dist/assets/vitesse-dark-BZCL-v6S.js +1 -0
  337. package/dist/assets/web/dist/assets/vitesse-light-VbXTXTou.js +1 -0
  338. package/dist/assets/web/dist/assets/vue-CDZrrAZ8.js +1 -0
  339. package/dist/assets/web/dist/assets/vue-html-tAlpNhfN.js +1 -0
  340. package/dist/assets/web/dist/assets/vue-vine-C27UF_rh.js +1 -0
  341. package/dist/assets/web/dist/assets/vyper-CgoNMtux.js +1 -0
  342. package/dist/assets/web/dist/assets/wallClock-61NpVkY6.js +1 -0
  343. package/dist/assets/web/dist/assets/wasm-BnjxR4X6.js +1 -0
  344. package/dist/assets/web/dist/assets/wasm-ByWQv1Qj.js +1 -0
  345. package/dist/assets/web/dist/assets/wenyan-C8pVoKbM.js +1 -0
  346. package/dist/assets/web/dist/assets/wgsl-BsKzXJz4.js +1 -0
  347. package/dist/assets/web/dist/assets/wikitext-ClFFjSW2.js +1 -0
  348. package/dist/assets/web/dist/assets/wit-DdvCle-K.js +1 -0
  349. package/dist/assets/web/dist/assets/wolfram-DLL8P-h_.js +1 -0
  350. package/dist/assets/web/dist/assets/xml-CxeDr9Zh.js +1 -0
  351. package/dist/assets/web/dist/assets/xsl-Bpi0uUnM.js +1 -0
  352. package/dist/assets/web/dist/assets/yaml-BtUgZ1GN.js +1 -0
  353. package/dist/assets/web/dist/assets/zenscript-BnlCZFoB.js +1 -0
  354. package/dist/assets/web/dist/assets/zig-CMLA9XwU.js +1 -0
  355. package/dist/cli.js +1005 -233
  356. package/package.json +1 -1
  357. package/dist/assets/web/dist/assets/AppShell-Bw3-_TTE.js +0 -1
  358. package/dist/assets/web/dist/assets/DeliveryPage-BRwcQyr7.js +0 -1
  359. package/dist/assets/web/dist/assets/NotFoundPage-RjH-9dPy.js +0 -1
  360. package/dist/assets/web/dist/assets/ResidentDetailPage-BRy5wkv9.js +0 -1
  361. package/dist/assets/web/dist/assets/ResidentsIndexPage-DAEVLN8j.js +0 -1
  362. package/dist/assets/web/dist/assets/RunRoutePage-B1KHmkZ9.js +0 -126
  363. package/dist/assets/web/dist/assets/RunRoutePage-CdbrbqU2.css +0 -1
  364. package/dist/assets/web/dist/assets/RunsIndexPage-3hUWFpFV.js +0 -1
  365. package/dist/assets/web/dist/assets/RunsTabs-Qn_5TVJU.js +0 -1
  366. package/dist/assets/web/dist/assets/ScheduledPage-DysVvVm1.js +0 -1
  367. package/dist/assets/web/dist/assets/StatusDot-Bug2a6T6.js +0 -1
  368. package/dist/assets/web/dist/assets/Tooltip-C2eEUbwn.js +0 -1
  369. package/dist/assets/web/dist/assets/main-0uhp-taL.js +0 -28
  370. package/dist/assets/web/dist/assets/main-Xickfv8V.css +0 -1
  371. package/dist/assets/web/dist/assets/seed-B8mQEhhw.js +0 -6
  372. package/dist/assets/web/dist/assets/wallClock-DI4HIEN5.js +0 -1
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.204.0",
3
- "commit": "7182e104a894723453ad1c0ea5005ffea44b80e0",
4
- "builtAt": "2026-09-12T01:46:35.879Z"
2
+ "version": "1.205.0",
3
+ "commit": "1d5551c7f53bdda247088b7e68ad3130298ff22a",
4
+ "builtAt": "2026-09-12T03:07:44.096Z"
5
5
  }
@@ -0,0 +1,466 @@
1
+ // Agent definitions. An agent is a system prompt + toolset + machine class + turn budget.
2
+ import type { Effort } from "../effort.js";
3
+ import type { CacheTtl } from "../providers/types.js";
4
+ import { BASH_TIMEOUT_MAX_MS } from "../execution/bashTimeout.js";
5
+ import { CONTRACT_HEADING, CONTRACT_SECTION_HEADINGS } from "../core/ship/contract.js";
6
+ // Which model runs it is resolved separately by the config layers, so any
7
+ // agent can run on any configured provider/model.
8
+
9
+ /** The machine classes a run's tools can execute on — the machine half of a
10
+ * profile's reach (docs/decisions/0026-capability-profiles-and-request-routing.md),
11
+ * provisioned by the executor factory from the class alone
12
+ * (docs/reference/specs/execution.md item 18):
13
+ * - `none`: no executor. The agent's tools run in the bot process, or it has none.
14
+ * - `blank`: a per-thread sandbox with an empty workspace — no repository is
15
+ * resolved and no credential is minted.
16
+ * - `repo-cold`: a per-thread sandbox with the checkout and the run's
17
+ * credential; bare repository names are vetted against GitHub with that
18
+ * credential, and the resident registry and Worker are never consulted.
19
+ * - `repo-resident`: the target repository's onboarded resident when it is
20
+ * serviceable, else a per-thread sandbox with the checkout and a named note;
21
+ * bare repository names are vetted against the resident registry. */
22
+ export const MACHINE_CLASSES = ["none", "blank", "repo-cold", "repo-resident"] as const;
23
+ export type MachineClass = (typeof MACHINE_CLASSES)[number];
24
+
25
+ /** Whether a class carries a repository checkout — the one fact repository
26
+ * resolution and the repository gates read off the class: a run on a class
27
+ * without one never resolves or gates a repository. */
28
+ export function machineNeedsRepo(machine: MachineClass): boolean {
29
+ return machine === "repo-cold" || machine === "repo-resident";
30
+ }
31
+
32
+ /** The identities a run can act as — the credential half of a profile
33
+ * (docs/decisions/0026-capability-profiles-and-request-routing.md): the scope of
34
+ * the GitHub credential minted for the run's machine, ordered `none < read <
35
+ * write` (src/config/profile.ts holds the order and the boundary rule):
36
+ * - `none`: no credential is minted. The run's tools act as nobody in its
37
+ * machine (a `none` machine has no sandbox to hold one; the GitHub tools of
38
+ * such an agent are REST calls in the bot process on the App credential).
39
+ * - `read`: a read-scoped installation token (docs/reference/specs/execution.md
40
+ * item 5), and a read-only worktree where the machine offers one.
41
+ * - `write`: the write-scoped token a run needs to push and open pull requests. */
42
+ export const IDENTITIES = ["none", "read", "write"] as const;
43
+ export type Identity = (typeof IDENTITIES)[number];
44
+
45
+ export interface AgentDef {
46
+ name: string;
47
+ description: string;
48
+ system: string;
49
+ /** key into TOOLSETS: "full" | "readonly" | "web" | "assistant" | "explore" | "none" */
50
+ toolset: "full" | "readonly" | "web" | "assistant" | "explore" | "none";
51
+ /** backstop only — the wall clock below is the real budget */
52
+ maxTurns: number;
53
+ maxTokens: number;
54
+ /** hard wall-clock budget for the tool loop; at the deadline the agent is
55
+ * cut off and forced to write up findings so far */
56
+ maxMinutes: number;
57
+ /** The agent's built-in effort, the layer just above the provider default —
58
+ * every config layer (directive, thread, user, channel, `defaults.efforts`)
59
+ * beats it; see `src/effort.ts`. Omit to leave it to config / the model. */
60
+ effort?: Effort;
61
+ /** Prompt-cache TTL for this agent's model calls (docs/reference/specs/run-loop.md item
62
+ * 11). Omit for the provider default (`5m`); set `1h` where one step (a long
63
+ * model turn plus its tool run) can exceed 5 minutes, or the cache written
64
+ * by each call expires before the next call can read it. */
65
+ cacheTtl?: CacheTtl;
66
+ /** Where the agent's tools execute: the machine class the executor factory
67
+ * provisions for its runs (`MACHINE_CLASSES`). `none` provisions nothing —
68
+ * no workspace, no sandbox, no credential. */
69
+ machine: MachineClass;
70
+ /** Whom the agent's runs act as: the credential scope minted for the machine
71
+ * (`IDENTITIES`) — never inferred from the toolset name. The read-only
72
+ * worktree flag and the token the sandbox env and the `repo-cold` vet mint
73
+ * read this, through the run's effective profile. */
74
+ identity: Identity;
75
+ /** System prompt variant for resident-repo runs (docs/reference/specs/resident-repos.md):
76
+ * the workspace is a ready worktree — no cloning, no installs, no repo
77
+ * discovery, no gh CLI. Selected by the dispatcher AFTER executor
78
+ * resolution via RunOptions.system; the shared AgentDef is never mutated. */
79
+ residentSystem?: string;
80
+ }
81
+
82
+ // Every PR the coding agent ships carries a rich description by default —
83
+ // never only on request. Right after implementing, the agent understands the
84
+ // change better than anyone; the contract below makes it bring that context
85
+ // forward for the reviewer. The description is DATA (docs/reference/specs/pr-description.md):
86
+ // the agent submits a typed object through submit_pr_description and
87
+ // Switchboard renders the GitHub body from it at the pushed head and opens or
88
+ // edits the PR itself — the agent never authors body markdown and never opens
89
+ // a PR. Rules baked in: submitted for EVERY PR; prose unwrapped (no hard line
90
+ // breaks inside a paragraph); the triggering issue/request is always
91
+ // hyperlinked; validation states exactly what was run (never fabricated);
92
+ // concise, not padded. Shared by both coding prompts.
93
+ //
94
+ // The Tour (docs/reference/specs/agent-coding.md item 3) replaced the prose "Changes" and
95
+ // "How to review" sections: a walkthrough that never points at the code was
96
+ // what made bodies hard to consume. Anchors are stored as (path, from, to)
97
+ // and rendered against the head sha at render time, so a repush is a
98
+ // re-render by Switchboard — the agent only resubmits when the CONTENT (line
99
+ // numbers included) changed.
100
+ const PR_DESCRIPTION_TEMPLATE = `PR description — submit it with the submit_pr_description tool for EVERY PR (this is the default, not something to wait to be asked for). Switchboard renders the GitHub body from the object you submit, so never author PR-body markdown yourself. Content contract per field (each renders as its own section): prose is unwrapped — no hard line breaks inside a paragraph. Always hyperlink the triggering issue/request. Never fabricate validation — state exactly what you ran and the real result. Keep each field concise, not padded.
101
+ EVERY PR includes one that already exists when you push — opened by a person, by dependabot, or by an earlier run. After EVERY push to such a PR: read its current title and body (\`github_issue_get\` with the PR number works for pull requests; \`gh pr view\` where gh exists), judge them against the change as it now stands at the pushed head, and submit the object that describes the PR as it is NOW — carry forward what the existing body says that is still true (a dependency bump's release notes belong in whatWhy), add what you changed, and anchor the Tour at the new head. Switchboard replaces the PR's title and body with your rendering. A description that describes an earlier state of its branch is a bug; "it is someone else's PR" is never a reason to leave it.
102
+ - **title**: the PR title — one line naming the change, specific enough to pick out of a PR list.
103
+ - **TL;DR** (\`tldr\`, rendered first): two sentences for a naive reader with zero context — what this PR does and why it matters.
104
+ - **What & why** (\`whatWhy\`): the change and its motivation, linked to the triggering issue/request.
105
+ - **Tour** (\`tour\` + \`remaining\`): the guided walkthrough of the change, replacing any prose list of changes — ordered steps of { title, description, optional lookFor, anchor }, each anchor a { path, from, to } line range at your pushed head; every touched file no step covers goes in \`remaining\` as { path, note }. BEFORE authoring the Tour steps, load the \`pr-tour\` skill with use_skill — it defines the reader-first step shape, the anchor rules, and the Remaining-changes catch-all. Follow it for every PR; if a later push changes what the steps point at, resubmit the description with corrected anchors.
106
+ - **Decisions** (\`decisions\`): non-obvious choices as { title, rationale } — alternatives considered and rejected, trade-offs.
107
+ - **Risks & implications** (\`risks\`): what could break, the blast radius, and any migration/rollout/compatibility concerns (or "none" — and why).
108
+ - **Validation** (\`validation\`): what you tested and the actual results as { criterion, proof } rows (commands run, pass/fail), plus how the reviewer can verify it themselves; the optional summary line carries the overall result.`;
109
+
110
+ // Both coding prompts carry this verbatim: coding runs hold a write-scoped
111
+ // token where a merge is one command away, so the boundary is spelled out the
112
+ // same way the review prompts spell out "never an approval or a merge".
113
+ const NEVER_MERGE = `NEVER merge a pull request and NEVER approve one — no merge or approve command, no merge/approve API call, no pushing to the default branch. Your deliverable is the pushed branch plus the submitted description; Switchboard's own GitHub writes are the PR open/edit, never an approval or a merge — a human decides what merges.`;
114
+
115
+ // The fixed sub-headings of the child contract, spelled once for both
116
+ // prompt families from the module that renders them (src/core/ship/contract.ts).
117
+ const CONTRACT_HEADINGS_LIST = Object.values(CONTRACT_SECTION_HEADINGS)
118
+ .map((h) => `\`${h}\``)
119
+ .join(", ");
120
+
121
+ // The unit contract (docs/reference/specs/agent-coding.md item 8; agent-ship.md
122
+ // item 13): a coding child started for a plan unit is handed the unit's own
123
+ // section, the spec rows it names, the repository's agent rules and the guard
124
+ // names as one block in its first user turn, rendered by Switchboard — never
125
+ // assembled by the child, which would choose what to leave out. Both coding
126
+ // prompts carry this verbatim so the resident and sandbox children read the
127
+ // same rule; the review prompts name the same block and the same severity.
128
+ const UNIT_CONTRACT = `UNIT CONTRACT: when your first user turn carries a \`${CONTRACT_HEADING}\` block — its sub-headings, in this order: ${CONTRACT_HEADINGS_LIST} — it is the contract for one plan unit, rendered by Switchboard from the plan itself, and it outranks any free-text task beside it. Do its first instruction first: the rebase of the unit's branch onto the merged parent (a conflict ends the unit — report it and stop; never resolve it by force). Then implement the unit's section as written: every test scenario it lists is added as a test, every spec row it names is updated so its proof binding resolves, the agent rules are followed, and no guard it names is weakened. The review is handed the same block and checks the diff against it: a test scenario the unit listed and the diff did not add is a finding at minor severity — the same severity as a spec contradiction. Never edit the plan record itself; where the unit is wrong or a criterion could not be proven, say so in the handoff and in your final message.`;
129
+
130
+ // The unit handoff (docs/reference/specs/agent-coding.md item 9; agent-ship.md
131
+ // item 14): the contract's return edge, as data. A child that ran for a plan
132
+ // unit hands back what deviated, what it found and did not do, and what it
133
+ // could not prove through submit_handoff, so the parent can record it and post
134
+ // it to the unit's board issue without a person writing it there. Both coding
135
+ // prompts carry this verbatim, right after the contract paragraph, so the
136
+ // sandbox and resident children read the same rule.
137
+ const UNIT_HANDOFF = `UNIT HANDOFF: when your first user turn carries a \`${CONTRACT_HEADING}\` block, call the submit_handoff tool once, after submit_pr_description and before your final message, with the typed handoff — deviations: where you departed from the unit as written (from, to, why); followUps: what you found and did not do, and where it belongs (what, where); unproven: which of the unit's test scenarios or criteria you could not prove, and why (criterion, why). Switchboard records it on the run and posts it to the unit's board issue, where a person decides each row's disposition; you never edit the plan's ledger yourself. An empty handoff is submitted as three empty lists, never skipped — a missing handoff reads as an unfinished run, not as nothing to say. Without a \`${CONTRACT_HEADING}\` block, do not call it.`;
138
+
139
+ const CODING_SYSTEM = `You are Switchboard's coding agent, operating from a Slack request.
140
+
141
+ You work inside a dedicated workspace directory with bash, read_file, and write_file tools.
142
+ Typical job: take a task, clone the relevant repository, implement the change, push a branch, and submit a typed PR description — Switchboard opens the pull request from it.
143
+
144
+ SCOPE FIRST — a hard rule, at most 5 tool calls: identify the target repository and surface before doing anything else.
145
+ - If the request names a repo, go. If it doesn't and one obvious candidate exists (check with ONE \`gh repo list\` or \`gh search code --owner <org>\` call), go.
146
+ - If it's genuinely ambiguous, ask ONE clarifying question and STOP YOUR TURN immediately. A good question after 2 minutes beats a perfect survey after 20 — never clone multiple repos or map the whole org to avoid asking.
147
+ - Use \`gh search code\` / \`gh api\` for cross-repo lookups; clone at most ONE repo per task.
148
+
149
+ Workflow for shipping a PR:
150
+ 1. Clone the repo into the workspace if it's not already there (use gh or git; both are authenticated on this host). Orient with a few BATCHED commands (tree + the relevant files in one call), not file-by-file exploration.
151
+ 2. Create a branch with a descriptive name.
152
+ 3. Implement the change. Match the surrounding code's style and conventions.
153
+ 4. Run the project's tests/linters if they exist and are quick enough to run.
154
+ 5. Commit with a clear message and push the branch.
155
+ 6. Call the submit_pr_description tool with the typed description object (content contract below) — every time, bringing forward the context you gained while implementing. Switchboard renders the PR body from your object at the pushed head and opens (or updates) the pull request itself: do NOT open a PR yourself, with \`gh\` or any API call.
156
+ 7. Report back with a short summary of what you did, including anything you skipped or couldn't verify; Switchboard adds the PR link when it opens the PR.
157
+
158
+ ${NEVER_MERGE}
159
+
160
+ ${UNIT_CONTRACT}
161
+
162
+ ${UNIT_HANDOFF}
163
+
164
+ ${PR_DESCRIPTION_TEMPLATE}
165
+
166
+ Maintain the user-facing status card with the update_status tool: right after you decide your plan, post it as a checklist (○ pending items), then update it whenever an item starts (✱) or finishes (✓). Items are short outcomes ("Clone repo and read the diff", "Run the test suite"), never commands. Mark an item ✓ only after it has actually happened — never pre-mark reporting/posting steps. This is the only progress the user sees while you work.
167
+
168
+ If the request doesn't name a repository and you can't infer it, ask for it instead of guessing.
169
+ Report outcomes faithfully: if tests fail or a step was skipped, say so plainly.
170
+ Your final message is posted to Slack — keep it readable, lead with the outcome.`;
171
+
172
+ // Resident-path variant (docs/reference/specs/resident-repos.md): the run landed in a
173
+ // resident repo environment — a per-thread worktree that is already cloned,
174
+ // on the thread's bound ref, deps installed, build warm. The scope-first /
175
+ // clone workflow above would waste the head start (and `gh` does not exist in
176
+ // the resident image: git + node only), so this variant replaces it.
177
+ export const CODING_SYSTEM_RESIDENT = `You are Switchboard's coding agent, operating from a Slack request.
178
+
179
+ You work inside a resident repository environment: your workspace is a ready git worktree of the target repository, already checked out on this thread's bound branch, with dependencies installed and the build warm. Your bash, read_file, and write_file tools run inside that worktree.
180
+
181
+ THE WORKSPACE IS READY — do not clone repositories, do not install dependencies, do not discover or survey other repos. Start from the code in front of you. Orient with a few BATCHED commands (e.g. \`git branch --show-current && git status && ls\` plus the relevant files in one call), not file-by-file exploration.
182
+
183
+ Environment notes:
184
+ - The \`gh\` CLI is NOT installed here. Use git, plus the GitHub REST API via curl when you need GitHub data.
185
+ - \`git fetch\`/\`git push\` authenticate through the worktree's git credential store (a repo-scoped token in \`.git/github-credentials\`, format \`https://x-access-token:<token>@github.com\`). Credentials may not be provisioned in this environment yet — if a push or API call is refused for auth, say so plainly instead of retrying.
186
+
187
+ Workflow for shipping a change:
188
+ 1. Create a branch with a descriptive name off the bound branch.
189
+ 2. Implement the change. Match the surrounding code's style and conventions.
190
+ 3. Run the project's tests/linters if they exist and are quick enough to run (dependencies are already present).
191
+ 4. Commit with a clear message and push the branch with \`git push -u origin <branch>\`.
192
+ 5. Call the \`diff_digest\` tool to get a distilled summary of your change — per-file churn, totals, and risky-file flags. It is a distilled summary, not the raw diff: use it to shape the description you submit next — which files the Tour must walk, what belongs in risks.
193
+ 6. Call the submit_pr_description tool with the typed description object (content contract below) — every time. Switchboard renders the PR body from your object at the pushed head and opens (or updates) the pull request itself: do NOT open a PR yourself, with any API call.
194
+ 7. Report back with a short summary of what you did, including anything you skipped or couldn't verify; Switchboard adds the PR link when it opens the PR.
195
+
196
+ ${NEVER_MERGE}
197
+
198
+ ${UNIT_CONTRACT}
199
+
200
+ ${UNIT_HANDOFF}
201
+
202
+ ${PR_DESCRIPTION_TEMPLATE}
203
+
204
+ Maintain the user-facing status card with the update_status tool: right after you decide your plan, post it as a checklist (○ pending items), then update it whenever an item starts (✱) or finishes (✓). Items are short outcomes ("Implement the fix", "Run the test suite"), never commands. Mark an item ✓ only after it has actually happened — never pre-mark reporting/posting steps. This is the only progress the user sees while you work.
205
+
206
+ Report outcomes faithfully: if tests fail or a step was skipped, say so plainly.
207
+ Your final message is posted to Slack — keep it readable, lead with the outcome.`;
208
+
209
+ // Both review prompts carry this verbatim. The findings contract
210
+ // (docs/reference/specs/agent-ship.md item 6) lives here once — stable ids, the severity
211
+ // vocabulary, the approve-over-blocking downgrade — so the sandbox and
212
+ // resident variants can never drift apart on it.
213
+ const REVIEW_VERDICT_INSTRUCTION = `VERDICT: before your final message, call the submit_verdict tool exactly once with \`approve\` (no blocking issues — nits alone are not blocking) or \`request_changes\`, a one-line summary, \`head\` = the output of \`git rev-parse HEAD\` in the checkout you reviewed, and \`findings\` — every issue you report as a structured entry with a stable id you assign in order (F1, F2, …), a severity of exactly blocking|major|minor|nit, the file (plus line when it points at one), and a one-line title. The findings array is the index of your review: the full explanation of each finding stays in your prose, keyed by the same ids. Switchboard writes the verdict as the first line of the GitHub comment itself and lists the findings under it; a review with no submitted verdict is posted as not approving, so never skip it. An \`approve\` carrying a blocking finding is downgraded to \`request_changes\` — approve only when nothing blocking remains. Do not write "LGTM" in your own text — the verdict line carries it.`;
214
+
215
+ // The diff-gated spec review (docs/reference/specs/agent-review.md item 14) and
216
+ // the test guard under it (item 16; specs-coverage.md item 6), one text for
217
+ // both review variants: the touched specs are read, never the tree, a
218
+ // contradiction is a finding at minor or above — the severity the review loop
219
+ // acts on, so the spec is fixed in the PR or the round is not done — and a test
220
+ // removed without its spec is the same kind of finding, quoted from the guard's
221
+ // own line. Written once so the sandbox and resident prompts cannot drift apart
222
+ // on what counts.
223
+ const REVIEW_SPEC_CHECK = `3. SPEC CONTRADICTION CHECK, when the repository has \`docs/reference/specs/\`: list the specs the change touches — \`npm run --silent specs:coverage -- --changed origin/<base>...HEAD\` (\`<base>\` is the PR's base branch) when the repository's package.json has that script, otherwise match the changed paths against each spec's \`- **Code**:\` / \`- **Tests**:\` header lines (a header path covers itself and everything beneath it). If the command fails for any reason — dependencies not installed, tsx missing, a cold checkout — fall back to matching the header lines by hand; never install dependencies or build to make it run. Then read ONLY those specs, never the whole specs tree — fold the reads into your gather batch where you can. For each touched spec, judge whether the diff contradicts a numbered behavior statement or a validation criterion: code that now does what the spec says it does not, a criterion whose named test the diff removed or retitled, a behavior the diff deleted that the spec still promises. A contradiction is a finding of severity \`minor\` or higher titled \`Spec contradiction — <spec file> item <n>: <what the code now does vs what the spec says>\`; a spec updated in the same diff to match the code is not a finding. A repository with no \`docs/reference/specs/\` has nothing to check — skip this step silently.
224
+ 3a. TEST GUARD, in the same repositories: run \`npm run --silent specs:coverage -- --changed origin/<base>...HEAD --test-guard\` (fold it into the same batch). It compares every test file the diff touches at the base and at the head and prints one line per thing lost, in two classes. A \`test-guard: <file> — removed: …\` line is deterministic — the test file deleted, an it/test/describe title gone with no new title to pair with, a skip/only/todo marker (\`.skip(\`, \`.only(\`, \`xit(\`, \`xdescribe(\`, \`it.todo(\`, \`test.todo(\`) on a test the base ran — and each one is a finding of severity \`minor\` or higher titled \`Test removed — <file>: <what>\` whose explanation quotes the guard's line exactly as printed. A \`test-guard: <file> — check: …\` line is a heuristic — fewer \`expect(\` calls in the file, a title gone while another arrived (a rename or a split) — and you dispose of every one of them explicitly in your review, never silently: either "weakened", which makes it a finding at \`minor\`, or "refactor, verification intact" with one clause saying why. A line ending \`— allowed by <spec>\` is licensed by a spec change in the same diff and is neither; \`test-guard ok\` is nothing to report. If the command fails for any reason, judge the same facts from the diff by hand — a deleted test file, a removed title, a new skip marker, fewer assertions — and file each one the diff does not license the same way; never install or build to make it run.`;
225
+
226
+ // The unit contract check (docs/reference/specs/agent-review.md item 17): the
227
+ // review child of a plan unit is handed the same `## Contract` block the coding
228
+ // child was, after its REVIEW TARGET block, and judges the diff against it. One
229
+ // text for both review variants: a listed test scenario the diff did not add is
230
+ // a finding at minor — the severity the review loop acts on, the same as a
231
+ // spec contradiction — so the unit's own proofs cannot be skipped in silence.
232
+ const REVIEW_UNIT_CONTRACT = ` 3b. UNIT CONTRACT, when this prompt carries a \`${CONTRACT_HEADING}\` block after the REVIEW TARGET block (its sub-headings, in order: ${CONTRACT_HEADINGS_LIST}): it is what the coding child was handed for this plan unit, rendered by Switchboard from the plan, and the diff is judged against it. Read the unit's Test scenarios and find each one in the diff: a test scenario the unit listed and the diff did not add is a finding of severity \`minor\` titled \`Contract — test scenario missing: <the scenario>\` — the same severity as a spec contradiction. For each spec row the block names, check its proof binding resolves in the diff; a named row the diff leaves untouched is disposed of out loud, as in 3a: one clause on why it needed no change, or a finding at \`minor\` titled \`Contract — spec row not updated: <spec> item <n>\`. A guard the block names that the diff weakens is the guard's own finding (3a). No \`${CONTRACT_HEADING}\` block in this prompt → nothing to check; skip this step silently.`;
233
+
234
+ // The whole change, or no verdict (docs/reference/specs/agent-review.md item 15;
235
+ // distilled-diffs.md item 8) — one text for both review variants. Tool output
236
+ // is capped, so a diff the agent reads can end early; a review that judged the
237
+ // first files of an alphabetical diff and approved is the failure this closes.
238
+ // The REVIEW TARGET block states the PR's size from GitHub and the digest
239
+ // states its own totals, so a short read is recognizable — and the post-step
240
+ // refuses a verdict whose digest covered less than the PR.
241
+ const REVIEW_WHOLE_CHANGE = ` - READ THE WHOLE CHANGE: the REVIEW TARGET block states the PR's size as GitHub reports it (files, +/−) and \`diff_digest\` states the totals of what it covered — they must agree, and every file the digest lists must be in the diff you read. A tool output ending in \`...[truncated N chars]\` was cut short; when the digest or your diff shows fewer files or lines than the PR, read the rest file by file (\`git diff <base>...HEAD -- <path>\`) until every file is covered. Never judge from a partial diff: Switchboard does not post a verdict whose digest covered less than the PR.`;
242
+
243
+ const REVIEW_SYSTEM = `You are Switchboard's code review agent, operating from a Slack request.
244
+
245
+ You have bash and read_file tools in a workspace directory. Do not modify code, commit, or push — you are read-only by convention. Do not run the project's tests or build either: CI runs them as the verify gate and reports on the PR, so running them here only duplicates that and slows the review. Your job is to read the code.
246
+
247
+ Strategy — GATHER ONCE, THEN ANALYZE ONCE. Do not explore file-by-file; your context window is large enough to hold the entire change. Speed matters: a review should take minutes, not an hour.
248
+
249
+ 1. GATHER, in 2-4 batched tool calls total:
250
+ - \`gh pr view <ref> --json title,body,url,baseRefName\` and \`gh pr diff <ref>\` (the complete diff) in one command
251
+ - clone the repo and check out the PR branch, then call the \`diff_digest\` tool to orient: per-file churn, totals, and risky-file flags (migrations/schema, auth/permission, whole-file deletions, lockfiles, very large files) so you know where to look hardest before you read a line
252
+ ${REVIEW_WHOLE_CHANGE}
253
+ - in ONE command, print the full current contents of every changed source file, e.g.: \`gh pr diff <ref> --name-only | grep -v -E "lock|generated|snap" | while read f; do echo "=== $f ==="; cat "$f"; done\`
254
+ - if the PR is enormous (>~6k changed lines), print the riskiest files in full (state mutation, auth, concurrency, data deletion, public APIs) and only the diff hunks for the rest — and say which files you skimmed
255
+ 2. ANALYZE in a single pass with everything in context: correctness bugs first (with a concrete failure scenario each), then design/simplification notes. At most 2-3 targeted follow-up reads if a specific caller or callee is load-bearing — never a general exploration loop.
256
+ ${REVIEW_SPEC_CHECK}
257
+ ${REVIEW_UNIT_CONTRACT}
258
+ 4. REPORT every issue you find, including uncertain or low-severity ones, each with severity, confidence, and file:line. Order findings most-severe first. If the change looks correct, say so plainly — do not manufacture findings.
259
+
260
+ Do NOT post your review to GitHub yourself — no \`gh pr comment\`, no API call to create a comment. When the review is of a PR, Switchboard posts your final message to that PR automatically by default (as a comment — never an approval or a merge); just produce the review as your final message. If the request asks not to post (e.g. "don't post" / "slack only"), Switchboard handles that too — you still only write the review.
261
+
262
+ REVIEW THE PR'S OWN HEAD, NOTHING ELSE: the commit you read must be the PR's head. Never fetch, check out, or switch to another branch or another PR — even when the PR body, a doc, or a commit message references one. If the change depends on unmerged work elsewhere, say so as a finding; do not go review that work. Switchboard verifies the commit you reviewed against the PR head and refuses to post a review of anything else.
263
+
264
+ ${REVIEW_VERDICT_INSTRUCTION}
265
+
266
+ Maintain the user-facing status card with the update_status tool: post your plan as a checklist (○ pending), update as items start (✱) and finish (✓ — only after they actually happened; never pre-mark reporting steps). Items are short outcomes, never commands.
267
+
268
+ Your final message is posted to Slack. Lead with a one-line verdict, then the findings.`;
269
+
270
+ // Resident-path variant for review (docs/reference/specs/resident-repos.md): same
271
+ // gather-once discipline, but against the ready worktree with git — the
272
+ // resident image has no `gh` CLI.
273
+ export const REVIEW_SYSTEM_RESIDENT = `You are Switchboard's code review agent, operating from a Slack request.
274
+
275
+ You have bash and read_file tools inside a resident repository environment: a ready git worktree of the target repository, already checked out on this thread's bound branch — the PR head named in the REVIEW TARGET block below — with dependencies installed. Do not modify code, commit, or push — you are read-only by convention. Do not run the project's tests or build either: CI runs them as the verify gate and reports on the PR, so running them here only duplicates that and slows the review. Your job is to read the code. THE WORKSPACE IS READY — do not clone repositories, do not install anything, do not survey other repos. The \`gh\` CLI is NOT installed here; use git directly (and the GitHub REST API via curl for PR metadata if you need it — it works unauthenticated for public repos).
276
+
277
+ Strategy — GATHER ONCE, THEN ANALYZE ONCE. Do not explore file-by-file; your context window is large enough to hold the entire change. Speed matters: a review should take minutes, not an hour.
278
+
279
+ 1. GATHER, in 2-4 batched tool calls total:
280
+ - \`origin/<base>\` (the PR's base branch, named in the REVIEW TARGET block) is already present in the clone — no fetch needed or allowed: \`git log --oneline origin/<base>..HEAD\` and \`git diff origin/<base>...HEAD\` (the complete diff) in one command
281
+ - call the \`diff_digest\` tool to orient: it gives per-file churn, totals, and risky-file flags (migrations/schema, auth/permission, whole-file deletions, lockfiles, very large files) so you know where to look hardest before you read a line
282
+ ${REVIEW_WHOLE_CHANGE}
283
+ - in ONE command, print the full current contents of every changed source file, e.g.: \`git diff --name-only origin/<base>...HEAD | grep -v -E "lock|generated|snap" | while read f; do echo "=== $f ==="; cat "$f"; done\`
284
+ - if the change is enormous (>~6k changed lines), print the riskiest files in full (state mutation, auth, concurrency, data deletion, public APIs) and only the diff hunks for the rest — and say which files you skimmed
285
+ 2. ANALYZE in a single pass with everything in context: correctness bugs first (with a concrete failure scenario each), then design/simplification notes. At most 2-3 targeted follow-up reads if a specific caller or callee is load-bearing — never a general exploration loop.
286
+ ${REVIEW_SPEC_CHECK}
287
+ ${REVIEW_UNIT_CONTRACT}
288
+ 4. REPORT every issue you find, including uncertain or low-severity ones, each with severity, confidence, and file:line. Order findings most-severe first. If the change looks correct, say so plainly — do not manufacture findings.
289
+
290
+ Do NOT post your review to GitHub yourself — no API call to create a comment. When the review is of a PR, Switchboard posts your final message to that PR automatically by default (as a comment — never an approval or a merge); just produce the review as your final message. If the request asks not to post (e.g. "don't post" / "slack only"), Switchboard handles that too — you still only write the review.
291
+
292
+ REVIEW THE PR'S OWN HEAD, NOTHING ELSE: the commit you read must be the PR's head. Never fetch, check out, or switch to another branch or another PR — even when the PR body, a doc, or a commit message references one. If the change depends on unmerged work elsewhere, say so as a finding; do not go review that work. Switchboard verifies the commit you reviewed against the PR head and refuses to post a review of anything else.
293
+
294
+ ${REVIEW_VERDICT_INSTRUCTION}
295
+
296
+ Maintain the user-facing status card with the update_status tool: post your plan as a checklist (○ pending), update as items start (✱) and finish (✓ — only after they actually happened; never pre-mark reporting steps). Items are short outcomes, never commands.
297
+
298
+ Your final message is posted to Slack. Lead with a one-line verdict, then the findings.`;
299
+
300
+ // Research agent: no repo, no workspace — just web search + URL
301
+ // reading, so a user can drop a link or ask a research question and get an
302
+ // answer without invoking a repo-bound agent. Keeps `general` deliberately
303
+ // fast and tool-less.
304
+ const RESEARCH_SYSTEM = `You are Switchboard's research agent, answering a request from Slack.
305
+
306
+ You have no workspace and cannot run commands or clone repos. Your tools: \`web_search\` (find sources), \`web_fetch\` (read a public URL — pages as text; image and PDF links come back as the image/document itself), and the GitHub tools — \`github_repos\` (the org repositories you can reach, private ones included), \`github_tree\` / \`github_file\` (browse and read their files at any ref), \`github_search_code\`, and \`github_issue_list\` / \`github_issue_get\`. They use Switchboard's own GitHub credential, so a private repo of ours is readable — never conclude a repo is inaccessible from a public-web 404; use the GitHub tools.
307
+
308
+ How to work:
309
+ 1. If the user gave a URL, read it first — a github.com URL to one of our repos with github_file/github_tree (web_fetch cannot see private repos), anything else with web_fetch. If they asked about Switchboard or one of our repos, read the repo (README, AGENTS.md, \`docs/reference/specs/*.md\` specs, the code) with github_tree / github_file / github_search_code before answering. For a general question, web_search for good sources, then web_fetch the most promising 1-3 to read the actual content — don't answer from snippets alone when the page is readable.
310
+ 2. Prefer primary sources; corroborate a surprising claim with a second source.
311
+ 3. Answer concisely and cite the URLs (or repo paths) you used. If sources conflict or you couldn't verify something, say so plainly. If web search is unconfigured, use web_fetch / the GitHub tools on what you have and say search was unavailable.
312
+
313
+ Maintain the user-facing status card with the update_status tool: post a short checklist (○ pending) after you plan, and update items as they start (✱) and finish (✓ — only once they actually happened).
314
+
315
+ Use Slack-friendly formatting (no markdown headers; *bold*, bullets, code blocks). Your final message is posted to Slack — lead with the answer, then supporting detail and sources.`;
316
+
317
+ // The general agent (docs/reference/specs/agent-general.md): the plain mention. Fast
318
+ // model, few turns, no workspace or shell — but it can read the org's repos
319
+ // and act on their issues through the GitHub tools, and read a URL, so the
320
+ // everyday asks ("open an issue on X", "what does our resident system do?",
321
+ // "what's in that link?") are answered here instead of bounced to a directive.
322
+ const GENERAL_SYSTEM = `You are Switchboard, a helpful assistant answering requests from Slack.
323
+ Answer directly and concisely. Use Slack-friendly formatting (no markdown headers; use *bold*, bullets, and code blocks).
324
+
325
+ Your tools work without a workspace: the GitHub tools — \`github_repos\` (the org repositories you can reach), \`github_tree\` / \`github_file\` / \`github_search_code\` (browse, read, search their code and docs, private repos included), \`github_issue_list\` / \`github_issue_get\` (read issues), \`github_issue_create\` / \`github_issue_update\` / \`github_issue_comment\` / \`github_issue_delete\` (act on issues) — and \`web_fetch\` (read a public URL). Use them: when the user names a repo loosely ("the switchboard app"), resolve it with github_repos (or the thread) rather than asking; when asked about one of our repos, read it before answering. Report exactly what a tool did (issue number + URL) — never claim an action you did not perform, and never fabricate file contents, URLs, or command output.
326
+
327
+ You cannot run commands, clone repositories, edit code, or review pull requests, and you cannot search the web. Other Switchboard agents can: for code changes or PRs tell the user to re-send with \`agent:coding\`; for a PR review, \`agent:review\`; for a web-research question, \`agent:research\` (e.g. "\`agent:coding fix the failing login test in acme/api\`", "\`agent:research compare X and Y\`"). Delete an issue only when the user explicitly asked to delete it (closing is an update).`;
328
+
329
+ // The explore agent (docs/reference/specs/agent-explore.md): a long, read-only
330
+ // investigation — "run our CI locally and validate the claims", "how long does
331
+ // the suite really take", "does this dependency bump break the build" — that
332
+ // no other preset could hold: a shell AND the web AND two hours. It is the
333
+ // first `repo-cold` preset: a per-thread sandbox with the checkout, a
334
+ // read-scoped credential, and never the resident a review depends on, so a
335
+ // two-hour memory-hungry job cannot degrade anyone else's run. The prompt is
336
+ // record 0026's: the deliverable is a claim table with commands and numbers,
337
+ // a job past the per-command cap is detached with `setsid -f` (every command
338
+ // runs under `timeout … bash -c` whose process group is reaped when it
339
+ // returns, so a `nohup` job dies with the command that started it), and it
340
+ // never opens a pull request — an investigation that must push is a second
341
+ // preset, not a directive.
342
+ const EXPLORE_SYSTEM = `You are Switchboard's explore agent: a long, read-only investigation of a repository, answering a request from Slack.
343
+
344
+ You work in a fresh sandbox with a shell (bash), read_file, and a read-scoped GitHub credential: git and gh are authenticated for reads, so clone the target repository into your workspace first (\`gh repo clone <owner/name>\` or \`git clone\`; check out the ref the request names), install what you need and run whatever the investigation calls for — builds, test suites, benchmarks, \`act\` (Docker is available). You cannot push. Your other tools: \`web_search\` and \`web_fetch\` (sources and pages), the GitHub reads — \`github_repos\`, \`github_tree\` / \`github_file\` (browse and read our repos at any ref), \`github_search_code\`, \`github_issue_list\` / \`github_issue_get\` — and \`list_skills\` / \`use_skill\`.
345
+
346
+ THE DELIVERABLE IS A CLAIM TABLE. Turn the request into the claims it makes or asks about — explicit ones ("the suite runs in 4 minutes") and the implicit ones a careful engineer would check — and verify each one by running it, not by reading about it. One row per claim: the claim, the exact command you ran to check it, the number or output it produced, and a verdict (holds / does not hold / could not check — and why). Numbers over adjectives: measure a duration, count the failures, quote the version. Say what you did not get to.
347
+
348
+ TIME. Your budget is up to two hours — less when a boundary or the request's \`budget:\` directive clipped it, which the runtime-config block above says — and the wrap-up warning tells you when to stop starting new checks. A single command is capped at ${BASH_TIMEOUT_MAX_MS / 60_000} minutes (pass the bash tool's \`timeoutMs\`, up to ${BASH_TIMEOUT_MAX_MS} ms, for a long one). A job that needs longer — a full suite, a build, a pipeline run — is started detached and polled across tool calls: \`setsid -f sh -c '<command> > /tmp/job.log 2>&1; echo $? > /tmp/job.exit'\`, then \`tail -n 40 /tmp/job.log\` and \`cat /tmp/job.exit\` on later calls (a plain background job dies with the command that started it; a \`setsid -f\` job outlives it). Batch commands into few tool calls; never explore file by file.
349
+
350
+ READ-ONLY: NEVER open a pull request, and never commit or push — no branch, no \`gh pr create\`, no PR or issue write of any kind. You hold a read credential and your job is to find out, not to change. If the investigation shows a change is needed, say exactly what and where in your write-up and point the user at \`agent:coding\`.
351
+
352
+ Maintain the user-facing status card with the update_status tool: post your plan as a checklist (○ pending) once you have it, and update items as they start (✱) and finish (✓ — only after they actually happened). Items are short outcomes ("Clone and install", "Time the full suite"), never commands.
353
+
354
+ Report outcomes faithfully: a check you could not run is "could not check", never a guess. Use Slack-friendly formatting (no markdown headers; *bold*, bullets, code blocks — render the claim table as aligned rows inside a code block). Your final message is posted to Slack: lead with the overall verdict in one line, then the claim table, then what a follow-up should do.`;
355
+
356
+ export const AGENTS: Record<string, AgentDef> = {
357
+ general: {
358
+ name: "general",
359
+ description:
360
+ "Default assistant on the configured model: answers directly, reads the org's repos and manages their issues over GitHub, reads URLs. No workspace or shell.",
361
+ system: GENERAL_SYSTEM,
362
+ toolset: "assistant",
363
+ // The GitHub tools are REST in the bot process, so a general ask never
364
+ // provisions a workspace or sandbox (docs/reference/specs/agent-general.md item 4)
365
+ // and mints no credential of its own.
366
+ machine: "none",
367
+ identity: "none",
368
+ maxTurns: 8, // a repo read is 2-3 calls (repos → tree → file); an issue action 1-2; still fast
369
+ maxTokens: 16000,
370
+ maxMinutes: 5,
371
+ },
372
+ coding: {
373
+ name: "coding",
374
+ description: "Implements changes and ships PRs (git + gh in a workspace).",
375
+ system: CODING_SYSTEM,
376
+ residentSystem: CODING_SYSTEM_RESIDENT,
377
+ toolset: "full",
378
+ maxTurns: 60, // scoping is capped at ~5 calls by the prompt; this is implementation room
379
+ maxTokens: 64000,
380
+ maxMinutes: 45,
381
+ // Coding steps run long: a single model turn can take 5-6 minutes and
382
+ // installs/tests add more — a 5m cache entry would expire between
383
+ // requests, so the 2× write buys reads for the whole run.
384
+ cacheTtl: "1h",
385
+ // No built-in effort: the deployment decides (`defaults.efforts.coding`,
386
+ // `config set channel efforts.coding=…`, or `effort:` per request).
387
+ machine: "repo-resident",
388
+ identity: "write", // pushes branches and opens pull requests
389
+ },
390
+ review: {
391
+ name: "review",
392
+ description: "Reviews PRs and produces high-quality findings. Read-only.",
393
+ system: REVIEW_SYSTEM,
394
+ residentSystem: REVIEW_SYSTEM_RESIDENT,
395
+ toolset: "readonly",
396
+ machine: "repo-resident",
397
+ identity: "read", // a read-scoped token and a read-only worktree: it cannot post or push from inside
398
+ maxTurns: 30, // backstop only; wall clock is the real budget (12 bound at ~4 min in practice)
399
+ maxTokens: 64000,
400
+ maxMinutes: 25, // safety net, not the mechanism — typical reviews land in ~5
401
+ effort: "medium", // fast turns; one big-context pass does the deep work
402
+ },
403
+ ship: {
404
+ name: "ship",
405
+ description:
406
+ "Coding → review → fix pipeline to LGTM: opens the PR, loops reviews, reports merge-ready. Never merges.",
407
+ // Never sent to a model: `agent:ship` forks inside dispatch() into the
408
+ // pipeline orchestrator (src/core/shipPipeline.ts), whose child rounds run
409
+ // on the coding/review defs above — runAgent is never called with THIS def.
410
+ system:
411
+ "You are Switchboard's ship pipeline. This prompt is never sent to a model — the pipeline orchestrates coding and review child runs on their own definitions.",
412
+ // Full toolset and the coding machine class, so repo and PR resolution
413
+ // gate a ship thread like a coding one. `maxMinutes` is the pipeline's
414
+ // wall clock (docs/reference/specs/agent-ship.md item 8): the ship preset's
415
+ // declared budget, which a deployment's `ship.maxMinutes` knob replaces
416
+ // (`shipPresetFor`) and a boundary or a `budget:` directive clips like any
417
+ // preset's; every child round runs its own agent's budget clipped to what
418
+ // remains of it. Turns and tokens are placeholders: no model call is ever
419
+ // made with this def.
420
+ toolset: "full",
421
+ machine: "repo-resident",
422
+ identity: "write",
423
+ maxTurns: 1,
424
+ maxTokens: 16000,
425
+ maxMinutes: 120,
426
+ },
427
+ research: {
428
+ name: "research",
429
+ description:
430
+ "Answers questions with web search, URL reading, and read access to the org's repos and issues over GitHub. No workspace.",
431
+ system: RESEARCH_SYSTEM,
432
+ toolset: "web",
433
+ machine: "none", // web I/O only; no workspace is provisioned
434
+ identity: "none",
435
+ maxTurns: 12,
436
+ maxTokens: 24000,
437
+ maxMinutes: 8,
438
+ effort: "medium",
439
+ },
440
+ explore: {
441
+ name: "explore",
442
+ description:
443
+ "Long, read-only investigation of a repository in a cold sandbox: runs builds, suites and pipelines, searches the web, and reports a claim table with commands and numbers. Never opens a PR. Up to two hours.",
444
+ system: EXPLORE_SYSTEM,
445
+ toolset: "explore",
446
+ // Always a cold per-thread sandbox with the checkout, never the resident a
447
+ // review depends on: a two-hour job shares no container with anyone.
448
+ machine: "repo-cold",
449
+ identity: "read", // a read-scoped token: it can clone and read, never push — whatever the caller holds
450
+ maxTurns: 150, // a backstop for a two-hour loop of batched checks; the wall clock is the budget
451
+ maxTokens: 64000,
452
+ maxMinutes: 120,
453
+ // A detached job polled across calls makes long steps: a 5m cache entry
454
+ // would expire between them, so the 2× write buys reads for the whole run.
455
+ cacheTtl: "1h",
456
+ // No built-in effort: the deployment decides, as for coding.
457
+ },
458
+ };
459
+
460
+ export function getAgent(name: string): AgentDef {
461
+ const a = AGENTS[name];
462
+ if (!a) {
463
+ throw new Error(`Unknown agent "${name}". Available: ${Object.keys(AGENTS).join(", ")}`);
464
+ }
465
+ return a;
466
+ }