@desplega.ai/agent-swarm 1.131.1 → 1.134.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 (360) hide show
  1. package/README.md +3 -3
  2. package/dist/{actions-jgcy477k.js → actions-7kast243.js} +20 -18
  3. package/dist/{anthropic-messages-rjmd2e7n.js → anthropic-messages-706yad38.js} +33 -17
  4. package/dist/app-0g84t8wf.js +28 -0
  5. package/dist/{artifact-jysj3wrg.js → artifact-dje5ke4h.js} +37 -131
  6. package/dist/{assistant-f2vkk1hj.js → assistant-ac4htcky.js} +25 -22
  7. package/dist/{azure-openai-responses-c0yjmbfd.js → azure-openai-responses-be59fbsz.js} +13 -13
  8. package/dist/{boot-reembed-q7mp8hcr.js → boot-reembed-b1rcqn85.js} +13 -11
  9. package/dist/{boot-reembed-xmw8wcx6.js → boot-reembed-kw2541c4.js} +14 -12
  10. package/dist/{boot-scrub-logs-dsqrv79n.js → boot-scrub-logs-ja29t92g.js} +11 -9
  11. package/dist/{claude-adapter-q6x7yspx.js → claude-adapter-5cg1fv8s.js} +33 -29
  12. package/dist/{claude-managed-adapter-wsg37bt8.js → claude-managed-adapter-9z9sdytx.js} +9 -9
  13. package/dist/{claude-managed-setup-52z4mq9w.js → claude-managed-setup-3zqp51cr.js} +5 -5
  14. package/dist/{claude-1ex232fc.js → claude-wqn3dtca.js} +1 -1
  15. package/dist/{cli-4wgngmwv.js → cli-00w4hbam.js} +1 -1
  16. package/dist/{cli-er3a4bb0.js → cli-15429qdw.js} +6 -1
  17. package/dist/{cli-e5dabkx0.js → cli-1cwhyvta.js} +4 -4
  18. package/dist/{cli-zsspvvm2.js → cli-1ybr6vw2.js} +237 -237
  19. package/dist/{cli-xpxde7rm.js → cli-2wv4kj0e.js} +60 -31
  20. package/dist/cli-34w2584r.js +530 -0
  21. package/dist/{cli-se2p6rkb.js → cli-38taxznr.js} +6 -6
  22. package/dist/{cli-9sbhdpvb.js → cli-3cgfyfzm.js} +14 -14
  23. package/dist/{cli-5n6e5yfn.js → cli-3zmdzfjf.js} +79 -74
  24. package/dist/{cli-3ty0t082.js → cli-43x36mty.js} +197 -8
  25. package/dist/{cli-ycrnynpw.js → cli-480nehnh.js} +29 -22
  26. package/dist/{cli-0258203w.js → cli-492e7ap5.js} +140 -20
  27. package/dist/{cli-3fj60etf.js → cli-497b685t.js} +3 -3
  28. package/dist/{cli-pxfxkx5m.js → cli-4bap00k0.js} +1 -1
  29. package/dist/{cli-w2wxd56v.js → cli-4bc8vmhm.js} +848 -770
  30. package/dist/{cli-aca5pz9f.js → cli-589599p9.js} +1 -1
  31. package/dist/{cli-t930g0xh.js → cli-5tnr64pm.js} +1 -1
  32. package/dist/{cli-jxg3s9ey.js → cli-65d93ves.js} +7 -7
  33. package/dist/{cli-6dpytdr2.js → cli-6x363v1z.js} +2 -2
  34. package/dist/{cli-dxak0fqd.js → cli-787ph852.js} +11 -11
  35. package/dist/{cli-793jvbsh.js → cli-7bv8nckk.js} +16 -11
  36. package/dist/{cli-zyxs93y9.js → cli-7jcc9y1r.js} +3 -3
  37. package/dist/{cli-f1am9szv.js → cli-87t2gstf.js} +1 -1
  38. package/dist/{cli-9aryf9tv.js → cli-95m51ztz.js} +1 -1
  39. package/dist/{cli-4w4fmq9x.js → cli-9w49enmh.js} +2 -2
  40. package/dist/{cli-v69vk5h0.js → cli-9y5b02vr.js} +13 -13
  41. package/dist/{cli-x23me2mg.js → cli-a1rrkrb4.js} +1 -1
  42. package/dist/{cli-psrqtw2m.js → cli-a3pkfpqs.js} +2 -2
  43. package/dist/{cli-h0rgxd24.js → cli-a4ajmfvp.js} +6 -6
  44. package/dist/{cli-ygrbmjja.js → cli-aw8bb6sf.js} +6 -6
  45. package/dist/{cli-g74vpjp2.js → cli-brm3et47.js} +55 -22
  46. package/dist/{cli-czkae1fp.js → cli-c5ddbdfj.js} +9 -9
  47. package/dist/{cli-114fvtmj.js → cli-c79a9zrc.js} +1 -1
  48. package/dist/{cli-49n9f49x.js → cli-dx3dz0ms.js} +3 -3
  49. package/dist/{cli-6dp3ydxa.js → cli-e07exmsb.js} +18 -14
  50. package/dist/cli-et1bbwqf.js +13 -0
  51. package/dist/{cli-yazx6hap.js → cli-f3s9dry0.js} +14 -14
  52. package/dist/{cli-t8d349cy.js → cli-f4wj0s3m.js} +3 -3
  53. package/dist/{cli-d6n0thxw.js → cli-f64gdfxc.js} +1 -1
  54. package/dist/{cli-pwfsqc2x.js → cli-fyd58xgb.js} +55 -55
  55. package/dist/{cli-7dm2zqy2.js → cli-g0j14czv.js} +2 -2
  56. package/dist/{cli-b0p7rfnd.js → cli-g2p9bd1z.js} +14 -14
  57. package/dist/{cli-z905tvmm.js → cli-g814jbst.js} +2 -2
  58. package/dist/{cli-5dsbcjjw.js → cli-ghexzd2d.js} +970 -970
  59. package/dist/{cli-jvv0g8bh.js → cli-gpt9kf01.js} +15 -15
  60. package/dist/{cli-rgrfzg8z.js → cli-grt6qv91.js} +380 -380
  61. package/dist/{cli-wz9115x0.js → cli-gtafvdy0.js} +8 -8
  62. package/dist/{cli-q5dzzak0.js → cli-gy07xk4s.js} +2 -2
  63. package/dist/{cli-sy7jk3tx.js → cli-h0djenzm.js} +2 -2
  64. package/dist/{cli-nrkkknat.js → cli-h37gbjbf.js} +2 -281
  65. package/dist/{cli-jevgrb4w.js → cli-h39xxnq6.js} +1200 -491
  66. package/dist/{cli-gz9sbyk3.js → cli-jepmgn7r.js} +1 -1
  67. package/dist/{cli-ccf9vy7q.js → cli-jmvk6et8.js} +7 -7
  68. package/dist/{cli-2rk0cx7s.js → cli-jxj92gkt.js} +51 -41
  69. package/dist/{cli-bqw0mt1n.js → cli-k46t4664.js} +18 -3
  70. package/dist/{cli-50vbt00w.js → cli-m07313tr.js} +1153 -696
  71. package/dist/{cli-4j2mrzag.js → cli-mkq1rk7b.js} +1 -1
  72. package/dist/{cli-1z7048dy.js → cli-mnm7w46e.js} +1 -1
  73. package/dist/{cli-kd1ck4rx.js → cli-mp9sg4cg.js} +14 -8
  74. package/dist/{cli-jbcva0xj.js → cli-mrammd8c.js} +60 -35
  75. package/dist/cli-nanaxrz6.js +27 -0
  76. package/dist/{cli-p9swy5t3.js → cli-pq2ee5ja.js} +8 -6
  77. package/dist/{cli-2wadx7p2.js → cli-pt43pdp1.js} +2 -2
  78. package/dist/{cli-7sgrxg9a.js → cli-q6d0vvey.js} +4 -4
  79. package/dist/{cli-k9qkf1hw.js → cli-qf9kpsve.js} +9 -9
  80. package/dist/cli-qh4sqfws.js +15 -0
  81. package/dist/{cli-e15jhafb.js → cli-qntkxysp.js} +14 -14
  82. package/dist/{cli-sajgpkqg.js → cli-qs9hhsvb.js} +1723 -325
  83. package/dist/{cli-z2zcxes1.js → cli-qt5bt3vk.js} +1 -1
  84. package/dist/{cli-wx82tw1k.js → cli-qtekrty1.js} +3 -3
  85. package/dist/{cli-g1re8r05.js → cli-rh6f3s9n.js} +3 -3
  86. package/dist/{cli-n0krnc6d.js → cli-rzhcrw2p.js} +2 -2
  87. package/dist/{cli-gecy3z2s.js → cli-snw62ze5.js} +4 -4
  88. package/dist/{cli-n6h8qt8n.js → cli-snz3p4yf.js} +15 -10
  89. package/dist/{cli-r6kqqbj0.js → cli-tkf8n6cw.js} +11 -11
  90. package/dist/{cli-4rkfg1wx.js → cli-tkrr24mz.js} +14 -9
  91. package/dist/{cli-9dr5qzc0.js → cli-tv9f1kyb.js} +54 -43
  92. package/dist/{cli-gm9cbhbq.js → cli-vtz6yj3v.js} +28 -9
  93. package/dist/{cli-2f07m0xr.js → cli-wf86d5t7.js} +1 -1
  94. package/dist/{cli-7zd05xb4.js → cli-whrvct19.js} +45 -45
  95. package/dist/{cli-ap1czx8f.js → cli-wrrea8xm.js} +3 -3
  96. package/dist/{cli-57khth04.js → cli-xmyqv00z.js} +120 -4
  97. package/dist/{cli-cwy5hqbq.js → cli-yjmk7tzc.js} +1 -1
  98. package/dist/{cli-6pcz9h15.js → cli-zykjrwcx.js} +180 -394
  99. package/dist/cli.js +45 -45
  100. package/dist/{codex-adapter-htjkn22b.js → codex-adapter-hsq6mz3m.js} +21 -19
  101. package/dist/{codex-hook-hq54t9ft.js → codex-hook-8c500gq8.js} +8 -7
  102. package/dist/{codex-login-z6yhbkmk.js → codex-login-x7603481.js} +3 -3
  103. package/dist/{codex-session-runner-wjfc7smz.js → codex-session-runner-c1x3x143.js} +15 -13
  104. package/dist/{commands-xhrfwqsk.js → commands-rwtddtst.js} +11 -9
  105. package/dist/{db-anvwb22f.js → db-j2b355vz.js} +458 -444
  106. package/dist/{devin-adapter-v1sarqtw.js → devin-adapter-8qmhqpy3.js} +3 -3
  107. package/dist/{devtools-2y1r7yqk.js → devtools-j2rnj8w7.js} +4 -4
  108. package/dist/{e2b-jdkwemv2.js → e2b-znpx78eg.js} +16 -16
  109. package/dist/{es5-vjgtkgp6.js → es5-fmqrjzy3.js} +2 -2
  110. package/dist/{event-bus-axn823e9.js → event-bus-n8sb35pw.js} +4 -4
  111. package/dist/{getMachineId-bsd-6tc9wxdj.js → getMachineId-bsd-wpzbhkm6.js} +4 -4
  112. package/dist/{getMachineId-darwin-sjt9sgnc.js → getMachineId-darwin-45zabjy0.js} +4 -4
  113. package/dist/{getMachineId-linux-v5n18y9p.js → getMachineId-linux-warnp5pd.js} +3 -3
  114. package/dist/{getMachineId-unsupported-yrjyqw3d.js → getMachineId-unsupported-5spent2a.js} +3 -3
  115. package/dist/{getMachineId-win-w3r8063c.js → getMachineId-win-v4bvcw7a.js} +4 -4
  116. package/dist/{google-generative-ai-hysrd8qx.js → google-generative-ai-b0wzss55.js} +17 -14
  117. package/dist/{google-vertex-p5arrga0.js → google-vertex-e8q4dpya.js} +18 -15
  118. package/dist/{handlers-b9kbc621.js → handlers-hchgrxkh.js} +32 -29
  119. package/dist/{hook-xkvn6c5h.js → hook-p49egqc0.js} +66 -52
  120. package/dist/hook-spb00w76.js +34 -0
  121. package/dist/{http-9xh6ta4r.js → http-nh14kkms.js} +663 -181
  122. package/dist/index-1qthq7vc.js +6 -0
  123. package/dist/{index-0g68f0p6.js → index-20xqmn3v.js} +3 -3
  124. package/dist/{index-vdkr5z2w.js → index-3e03k6e4.js} +114 -114
  125. package/dist/{index-ywds4812.js → index-4cbyhq2g.js} +43 -41
  126. package/dist/index-67pzqfrb.js +36 -0
  127. package/dist/{index-bccrkdkn.js → index-7m8yxkw5.js} +16 -16
  128. package/dist/{index-eaxyqcmj.js → index-dvsk64sm.js} +163 -83
  129. package/dist/{index-dqkpnmqm.js → index-e19s2m8k.js} +18 -18
  130. package/dist/{index-j30k5zxn.js → index-emvxcy98.js} +16 -16
  131. package/dist/{index-7ndw6ecy.js → index-gqnmr60d.js} +9 -9
  132. package/dist/{index-9znhar3x.js → index-j02xvjtd.js} +184 -185
  133. package/dist/{index-1s2442yw.js → index-ns5kksc1.js} +7 -7
  134. package/dist/{index-dpy2hth8.js → index-pdxc8kfh.js} +71 -71
  135. package/dist/{index-z1m7pw0v.js → index-ptcqm8bc.js} +107 -107
  136. package/dist/{index-070v4eyb.js → index-pyp7rexm.js} +5 -6
  137. package/dist/{index-86znjz1p.js → index-shne41sd.js} +13 -13
  138. package/dist/{index-2qn2qndv.js → index-t36q2v4t.js} +183 -183
  139. package/dist/index-tcnvv8w6.js +7 -0
  140. package/dist/index-w91qbfv1.js +7 -0
  141. package/dist/{index-fzc0mwvj.js → index-yqweff5n.js} +32 -32
  142. package/dist/index-yrfphye1.js +39 -0
  143. package/dist/{keepalive-vc7s2aa6.js → keepalive-9k51nqhc.js} +21 -15
  144. package/dist/lead-2xq3dxbz.js +88 -0
  145. package/dist/maintenance-0c0g6nym.js +28 -0
  146. package/dist/mistral-conversations-2njwdwhj.js +717 -0
  147. package/dist/{multipart-parser-qaktc7p8.js → multipart-parser-6gftesw0.js} +2 -2
  148. package/dist/{oauth-refresh-sweep-yecgjpk4.js → oauth-refresh-sweep-273a64r2.js} +14 -12
  149. package/dist/{onboard-xj0f73f9.js → onboard-tsv9wwhz.js} +12 -12
  150. package/dist/{openai-codex-responses-5g27pd6f.js → openai-codex-responses-kt84eq86.js} +26 -26
  151. package/dist/{openai-completions-3vkmfz2a.js → openai-completions-mrypq7qp.js} +17 -16
  152. package/dist/{openai-responses-dg4t7j7a.js → openai-responses-qhrk21ez.js} +20 -17
  153. package/dist/{opencode-adapter-1gm38aba.js → opencode-adapter-rar9676j.js} +13 -11
  154. package/dist/{openrouter-images-g3gm8931.js → openrouter-images-684fysx9.js} +5 -5
  155. package/dist/{otel-impl-nxg0n0b3.js → otel-impl-wp1mfzd2.js} +752 -537
  156. package/dist/{photon_rs-ky7dj5qw.js → photon_rs-8dwt2pzy.js} +581 -581
  157. package/dist/{pi-messages-tqj8q6b9.js → pi-messages-txp9f97r.js} +7 -7
  158. package/dist/{pi-mono-adapter-4g5kby31.js → pi-mono-adapter-yz47kk8e.js} +1910 -1180
  159. package/dist/pricing-refresh-jw1yw2fn.js +22 -0
  160. package/dist/rbac-roles-dg964c8p.js +32 -0
  161. package/dist/{rbac-roles-1hcxdtg7.js → rbac-roles-p53cg5cv.js} +19 -17
  162. package/dist/{registry-02cy9z5z.js → registry-mh12y17v.js} +4 -4
  163. package/dist/render-v2-56vn2rk9.js +36 -0
  164. package/dist/seed-pricing-52xx6z63.js +19 -0
  165. package/dist/{setup-46xtgq3c.js → setup-e8gp79sy.js} +7 -7
  166. package/dist/token-util-zy908s1a.js +6 -0
  167. package/dist/{token-fxkn2zf2.js → token-xg5711x5.js} +4 -4
  168. package/dist/worker-s17f1g46.js +88 -0
  169. package/dist/{x-6mg4kfpe.js → x-xkfh0w0v.js} +5 -5
  170. package/openapi.json +566 -22
  171. package/package.json +6 -6
  172. package/src/be/budget-refusal-notify.ts +14 -7
  173. package/src/be/db-queries/task-artifacts.ts +182 -0
  174. package/src/be/db.ts +834 -171
  175. package/src/be/events.ts +5 -0
  176. package/src/be/migrations/131_session_logs_created_at_index.sql +2 -0
  177. package/src/be/migrations/132_multi_runtime_instances.sql +44 -0
  178. package/src/be/migrations/133_workflow_run_trigger_type.sql +12 -0
  179. package/src/be/migrations/135_backfill_task_pull_request_attachments.sql +228 -0
  180. package/src/be/migrations/136_task_requester_provenance.sql +37 -0
  181. package/src/be/migrations/137_memory_retrieval_composite_index.sql +1 -0
  182. package/src/be/migrations/runner.ts +17 -11
  183. package/src/be/multi-runtime.ts +430 -0
  184. package/src/be/scripts/extract-schema.ts +3 -1
  185. package/src/be/scripts/typecheck.ts +6 -2
  186. package/src/be/seed-prompt-templates.ts +25 -2
  187. package/src/be/seed-skills/index.ts +7 -0
  188. package/src/be/steering.ts +1 -1
  189. package/src/be/swarm-config-guard.ts +18 -0
  190. package/src/commands/credential-wait.ts +54 -0
  191. package/src/commands/onboard/steps/core-credentials.tsx +1 -1
  192. package/src/commands/onboard/steps/custom-templates.tsx +1 -1
  193. package/src/commands/onboard/steps/harness-credentials.tsx +1 -1
  194. package/src/commands/onboard/steps/health-check.tsx +1 -1
  195. package/src/commands/onboard/steps/start.tsx +1 -1
  196. package/src/commands/profile-sync-audit.ts +56 -0
  197. package/src/commands/profile-sync.ts +287 -15
  198. package/src/commands/provider-credentials.ts +46 -19
  199. package/src/commands/runner.ts +199 -33
  200. package/src/commands/templates.ts +22 -0
  201. package/src/github/handlers.ts +55 -9
  202. package/src/heartbeat/heartbeat.ts +109 -17
  203. package/src/hooks/hook.ts +49 -33
  204. package/src/http/active-sessions.ts +11 -1
  205. package/src/http/agents.ts +261 -30
  206. package/src/http/all-routes.ts +1 -0
  207. package/src/http/config.ts +13 -2
  208. package/src/http/core.ts +102 -4
  209. package/src/http/db-query-bounded.ts +313 -0
  210. package/src/http/db-query-shared.ts +249 -0
  211. package/src/http/db-query.ts +54 -42
  212. package/src/http/events.ts +2 -0
  213. package/src/http/index.ts +23 -2
  214. package/src/http/mcp-bridge.ts +37 -3
  215. package/src/http/mcp.ts +12 -0
  216. package/src/http/memory.ts +13 -2
  217. package/src/http/openapi.ts +1 -0
  218. package/src/http/poll.ts +70 -27
  219. package/src/http/prompt-templates.ts +36 -13
  220. package/src/http/route-def.ts +43 -9
  221. package/src/http/schedules.ts +2 -2
  222. package/src/http/scripts.ts +10 -1
  223. package/src/http/session-data.ts +44 -0
  224. package/src/http/tasks.ts +2 -2
  225. package/src/http/users.ts +74 -52
  226. package/src/http/webhooks.ts +5 -2
  227. package/src/http/workflows.ts +1 -4
  228. package/src/integrations/kapso/inbound.ts +1 -1
  229. package/src/jira/outbound.ts +39 -8
  230. package/src/jira/webhook-lifecycle.ts +13 -2
  231. package/src/linear/outbound.ts +43 -10
  232. package/src/oauth/keepalive.ts +13 -2
  233. package/src/prompts/base-prompt.ts +1 -1
  234. package/src/prompts/default-drift.ts +21 -0
  235. package/src/prompts/session-templates.ts +56 -7
  236. package/src/providers/claude-adapter.ts +6 -0
  237. package/src/providers/codex-adapter.ts +6 -0
  238. package/src/providers/opencode-adapter.ts +6 -0
  239. package/src/providers/pi-mono-adapter.ts +8 -0
  240. package/src/providers/pricing-sources.md +24 -0
  241. package/src/queue-stall-alarm.ts +216 -0
  242. package/src/rbac/legacy-policy.ts +3 -0
  243. package/src/rbac/permissions.ts +12 -0
  244. package/src/scheduler/scheduler.ts +7 -0
  245. package/src/script-workflows/executor.ts +2 -1
  246. package/src/scripts-runtime/executors/native.ts +2 -1
  247. package/src/scripts-runtime/executors/types.ts +5 -0
  248. package/src/scripts-runtime/loader.ts +5 -0
  249. package/src/scripts-runtime/sdk-allowlist.ts +3 -0
  250. package/src/scripts-runtime/swarm-config.ts +8 -0
  251. package/src/scripts-runtime/swarm-sdk.ts +7 -0
  252. package/src/scripts-runtime/types/stdlib.d.ts +4 -0
  253. package/src/scripts-runtime/types/swarm-sdk.d.ts +4 -0
  254. package/src/server.ts +6 -0
  255. package/src/slack/channel-join.ts +22 -3
  256. package/src/slack/channel-lifecycle.ts +114 -0
  257. package/src/tests/budget-claim-gate.test.ts +20 -0
  258. package/src/tests/claude-adapter.test.ts +32 -0
  259. package/src/tests/codex-adapter.test.ts +30 -0
  260. package/src/tests/create-task-validation.test.ts +128 -0
  261. package/src/tests/credential-wait.test.ts +67 -1
  262. package/src/tests/db-query.test.ts +711 -2
  263. package/src/tests/heartbeat-checklist.test.ts +28 -0
  264. package/src/tests/http-api-integration.test.ts +81 -0
  265. package/src/tests/http-users.test.ts +166 -1
  266. package/src/tests/identity-field-budget.test.ts +176 -0
  267. package/src/tests/mcp-tools-user.test.ts +34 -0
  268. package/src/tests/mcp-user-route.test.ts +17 -0
  269. package/src/tests/metrics-http.test.ts +44 -0
  270. package/src/tests/migration-failure.test.ts +86 -0
  271. package/src/tests/multi-runtime-registration.test.ts +2810 -0
  272. package/src/tests/openapi-response-contract.test.ts +24 -0
  273. package/src/tests/openapi-route-headers.test.ts +83 -0
  274. package/src/tests/opencode-adapter.test.ts +40 -0
  275. package/src/tests/outbound-listener-rejection.test.ts +138 -0
  276. package/src/tests/pi-mono-adapter.test.ts +98 -0
  277. package/src/tests/preload.ts +2 -0
  278. package/src/tests/profile-sync-warning.test.ts +277 -0
  279. package/src/tests/profile-sync.test.ts +232 -6
  280. package/src/tests/prompt-template-resolver.test.ts +177 -6
  281. package/src/tests/prompt-template-session.test.ts +39 -3
  282. package/src/tests/queue-stall-alarm.test.ts +226 -0
  283. package/src/tests/rbac-charact-slack.test.ts +29 -0
  284. package/src/tests/rbac-engine.test.ts +3 -0
  285. package/src/tests/requester-comms.test.ts +32 -0
  286. package/src/tests/runner-requester-profile.test.ts +38 -0
  287. package/src/tests/schedule-target-type.test.ts +38 -0
  288. package/src/tests/script-connections.test.ts +13 -1
  289. package/src/tests/scripts-runtime-identity.test.ts +375 -0
  290. package/src/tests/scripts-runtime.test.ts +4 -3
  291. package/src/tests/sdk-allowlist.test.ts +47 -0
  292. package/src/tests/send-task-requested-by.test.ts +9 -0
  293. package/src/tests/session-costs.test.ts +506 -1
  294. package/src/tests/shutdown-error-scrubbing.test.ts +92 -0
  295. package/src/tests/slack-channel-lifecycle.test.ts +241 -0
  296. package/src/tests/slack-render-v2.test.ts +43 -0
  297. package/src/tests/steering-core.test.ts +28 -0
  298. package/src/tests/swarm-config-reserved-keys.test.ts +22 -0
  299. package/src/tests/task-artifacts.test.ts +386 -0
  300. package/src/tests/task-attachments-schema.test.ts +17 -1
  301. package/src/tests/task-completion-idempotency.test.ts +57 -0
  302. package/src/tests/task-pull-request-backfill-migration.test.ts +321 -0
  303. package/src/tests/tool-annotations.test.ts +4 -0
  304. package/src/tests/update-profile-api.test.ts +67 -39
  305. package/src/tests/update-profile-auth.test.ts +48 -4
  306. package/src/tests/user-attribution-migration.test.ts +54 -0
  307. package/src/tests/user-identity.test.ts +72 -0
  308. package/src/tests/workflow-async-v2.test.ts +39 -1
  309. package/src/tests/workflow-http-v2.test.ts +3 -2
  310. package/src/tests/workflow-mcp-trigger-schema.test.ts +52 -3
  311. package/src/tests/workflow-retry-v2.test.ts +45 -1
  312. package/src/tools/db-query.ts +18 -8
  313. package/src/tools/get-task-details.ts +24 -3
  314. package/src/tools/manage-user.ts +36 -3
  315. package/src/tools/poll-task.ts +93 -14
  316. package/src/tools/script-common.ts +5 -0
  317. package/src/tools/send-task.ts +1 -4
  318. package/src/tools/slack-archive-channel.ts +70 -0
  319. package/src/tools/slack-create-channel.ts +74 -0
  320. package/src/tools/slack-invite-to-channel.ts +78 -0
  321. package/src/tools/store-progress.ts +13 -2
  322. package/src/tools/swarm-config/delete-config.ts +9 -0
  323. package/src/tools/swarm-config/set-config.ts +3 -2
  324. package/src/tools/task-action.ts +30 -0
  325. package/src/tools/task-tool-ctx.ts +8 -1
  326. package/src/tools/tool-config.ts +4 -1
  327. package/src/tools/update-profile.ts +16 -21
  328. package/src/tools/utils.ts +5 -0
  329. package/src/tools/workflows/trigger-workflow.ts +7 -1
  330. package/src/types.ts +165 -1
  331. package/src/utils/github-pull-request.ts +76 -0
  332. package/src/utils/identity-field-budget.ts +73 -0
  333. package/src/utils/multi-runtime.ts +20 -0
  334. package/src/utils/requester-comms.ts +24 -0
  335. package/src/workflows/engine.ts +22 -2
  336. package/src/workflows/resume.ts +19 -11
  337. package/src/workflows/retry-poller.ts +1 -0
  338. package/src/workflows/triggers.ts +4 -0
  339. package/templates/skills/db-query-guidance/config.json +14 -0
  340. package/templates/skills/db-query-guidance/content.md +57 -0
  341. package/dist/app-5da78bd4.js +0 -26
  342. package/dist/cli-3te4jdkm.js +0 -225
  343. package/dist/cli-bmze986d.js +0 -7
  344. package/dist/cli-kh3ba2zf.js +0 -607
  345. package/dist/hook-cgk4wxmx.js +0 -31
  346. package/dist/index-25wjsdv2.js +0 -34
  347. package/dist/index-76at2ymp.js +0 -7
  348. package/dist/index-hase6zbe.js +0 -6
  349. package/dist/index-vg4snay4.js +0 -36
  350. package/dist/index-vy8edt27.js +0 -7
  351. package/dist/lead-r2yqfmx7.js +0 -85
  352. package/dist/maintenance-mw70k468.js +0 -26
  353. package/dist/mistral-conversations-81fwav0j.js +0 -30578
  354. package/dist/otel-nqa12wf3.js +0 -3149
  355. package/dist/pricing-refresh-2cn6effr.js +0 -20
  356. package/dist/rbac-roles-vynday5g.js +0 -30
  357. package/dist/render-v2-tc0bh8kk.js +0 -34
  358. package/dist/seed-pricing-8kceb43f.js +0 -17
  359. package/dist/token-util-pqyc8kng.js +0 -6
  360. package/dist/worker-qrbz6hmv.js +0 -85
@@ -65,9 +65,15 @@ import { interpolate } from "../utils/template.ts";
65
65
  import { detectVcsProvider } from "../vcs/index.ts";
66
66
  import { validateJsonSchema } from "../workflows/json-schema-validator.ts";
67
67
  import { buildContextPreamble, buildResumeContextPreamble } from "./context-preamble.ts";
68
- import { awaitCredentials, BootMaxWaitExceededError, EX_CONFIG } from "./credential-wait.ts";
68
+ import {
69
+ awaitCredentials,
70
+ BootMaxWaitExceededError,
71
+ EX_CONFIG,
72
+ retryBootStep,
73
+ } from "./credential-wait.ts";
69
74
  import {
70
75
  contentSha256,
76
+ prependProfileSyncRejectionBanner,
71
77
  resolveClaudeMdPath,
72
78
  syncProfileFilesToServer,
73
79
  writeIdentityBaselines,
@@ -80,6 +86,7 @@ import {
80
86
  isCredCheckDisabled,
81
87
  reportCredStatus,
82
88
  reportLatestModel,
89
+ sendCredStatusReport,
83
90
  } from "./provider-credentials.ts";
84
91
  import {
85
92
  type ResumeSessionCandidate,
@@ -481,6 +488,13 @@ export interface ApiConfig {
481
488
  apiUrl: string;
482
489
  apiKey: string;
483
490
  agentId: string;
491
+ /**
492
+ * Per-boot identity for this worker PROCESS, as opposed to `agentId` (the
493
+ * logical agent). Sent as the X-Runtime-Instance-ID header on ping/close so
494
+ * a server can track this process's liveness and retire only this runtime.
495
+ * Servers ignore it unless MULTI_RUNTIME_ENABLED.
496
+ */
497
+ runtimeInstanceId?: string;
484
498
  }
485
499
 
486
500
  export interface SteeringDispatchState {
@@ -589,6 +603,9 @@ async function pingServer(config: ApiConfig, _role: string): Promise<void> {
589
603
  if (config.apiKey) {
590
604
  headers.Authorization = `Bearer ${config.apiKey}`;
591
605
  }
606
+ if (config.runtimeInstanceId) {
607
+ headers["X-Runtime-Instance-ID"] = config.runtimeInstanceId;
608
+ }
592
609
 
593
610
  try {
594
611
  await fetch(`${config.apiUrl}/ping`, {
@@ -608,6 +625,9 @@ async function closeAgent(config: ApiConfig, role: string): Promise<void> {
608
625
  if (config.apiKey) {
609
626
  headers.Authorization = `Bearer ${config.apiKey}`;
610
627
  }
628
+ if (config.runtimeInstanceId) {
629
+ headers["X-Runtime-Instance-ID"] = config.runtimeInstanceId;
630
+ }
611
631
 
612
632
  try {
613
633
  console.log(`[${role}] Marking agent as offline...`);
@@ -932,6 +952,9 @@ const SWARM_TOOL_LABELS: Record<string, string | null> = {
932
952
  // Slack
933
953
  "slack-post": "💬 Posting to Slack",
934
954
  "slack-start-thread": "💬 Starting Slack thread",
955
+ "slack-create-channel": "💬 Creating Slack channel",
956
+ "slack-invite-to-channel": "💬 Inviting to Slack channel",
957
+ "slack-archive-channel": "💬 Archiving Slack channel",
935
958
  "slack-reply": "💬 Replying in Slack",
936
959
  "slack-read": "💬 Reading Slack",
937
960
  "slack-list-channels": "💬 Listing Slack channels",
@@ -2448,6 +2471,7 @@ async function registerActiveSession(
2448
2471
  triggerType: session.triggerType,
2449
2472
  taskDescription: session.taskDescription,
2450
2473
  runnerSessionId: session.runnerSessionId,
2474
+ runtimeInstanceId: config.runtimeInstanceId,
2451
2475
  }),
2452
2476
  });
2453
2477
  } catch {
@@ -2563,7 +2587,14 @@ interface Trigger {
2563
2587
  text?: string;
2564
2588
  }>;
2565
2589
  cursorUpdates?: Array<{ channelId: string; ts: string }>; // Deferred cursor commits for channel_activity
2566
- requestedBy?: { name: string; email?: string; role?: string; notes?: string };
2590
+ requestedBy?: {
2591
+ name: string;
2592
+ email?: string;
2593
+ role?: string;
2594
+ notes?: string;
2595
+ /** Structured communication preferences from `users.metadata.comms`. */
2596
+ comms?: { tone?: string; language?: string; verbosity?: string };
2597
+ };
2567
2598
  // Phase 4 — budget_refused fields. The server emits this envelope from
2568
2599
  // /api/poll and MCP task-action accept when an admission gate refuses to
2569
2600
  // let the agent claim a task. Worker reads cause + reset/spend/budget for
@@ -2581,6 +2612,8 @@ interface PollOptions {
2581
2612
  apiUrl: string;
2582
2613
  apiKey: string;
2583
2614
  agentId: string;
2615
+ /** Identifies the polling process so a retired runtime is not given work. */
2616
+ runtimeInstanceId?: string;
2584
2617
  pollInterval: number;
2585
2618
  pollTimeout: number;
2586
2619
  since?: string; // Optional: for filtering finished tasks
@@ -2591,15 +2624,24 @@ type RequesterProfile = NonNullable<Trigger["requestedBy"]>;
2591
2624
  export async function buildRequesterProfilePrompt(
2592
2625
  requestedBy: RequesterProfile | undefined,
2593
2626
  ): Promise<string> {
2594
- if (!requestedBy?.role && !requestedBy?.notes) return "";
2595
-
2596
- const notes = requestedBy.notes?.trim();
2627
+ const comms = requestedBy?.comms;
2628
+ const commsParts = [
2629
+ comms?.tone ? `tone: ${comms.tone}` : undefined,
2630
+ comms?.language ? `language: ${comms.language}` : undefined,
2631
+ comms?.verbosity ? `verbosity: ${comms.verbosity}` : undefined,
2632
+ ].filter((part): part is string => Boolean(part));
2633
+ if (!requestedBy?.role && !requestedBy?.notes && commsParts.length === 0) return "";
2634
+
2635
+ const commsSection =
2636
+ commsParts.length > 0 ? `\nTheir communication preferences: ${commsParts.join(", ")}.` : "";
2637
+ const notes = requestedBy?.notes?.trim();
2597
2638
  const notesSection = notes
2598
2639
  ? `\nTheir stated notes for how you should respond and act:\n${notes}`
2599
2640
  : "";
2600
2641
  const result = await resolveTemplateAsync("task.requester.profile", {
2601
- requester_name: requestedBy.name,
2602
- requester_role_suffix: requestedBy.role ? ` (${requestedBy.role})` : "",
2642
+ requester_name: requestedBy?.name ?? "",
2643
+ requester_role_suffix: requestedBy?.role ? ` (${requestedBy.role})` : "",
2644
+ requester_comms_section: commsSection,
2603
2645
  requester_notes_section: notesSection,
2604
2646
  });
2605
2647
 
@@ -2623,6 +2665,7 @@ async function registerAgent(opts: {
2623
2665
  * haven't migrated to passing it explicitly.
2624
2666
  */
2625
2667
  harnessProvider?: ProviderName;
2668
+ runtimeInstanceId?: string;
2626
2669
  }): Promise<{ serverCapabilities?: string[] }> {
2627
2670
  const headers: Record<string, string> = {
2628
2671
  "Content-Type": "application/json",
@@ -2654,6 +2697,7 @@ async function registerAgent(opts: {
2654
2697
  maxTasks: opts.maxTasks,
2655
2698
  provider,
2656
2699
  harness_provider: harnessProvider,
2700
+ runtimeInstanceId: opts.runtimeInstanceId,
2657
2701
  }),
2658
2702
  });
2659
2703
 
@@ -2702,6 +2746,9 @@ async function pollForTriggerOnce(opts: PollOptions): Promise<Trigger | null> {
2702
2746
  const headers: Record<string, string> = {
2703
2747
  "X-Agent-ID": opts.agentId,
2704
2748
  };
2749
+ if (opts.runtimeInstanceId) {
2750
+ headers["X-Runtime-Instance-ID"] = opts.runtimeInstanceId;
2751
+ }
2705
2752
  if (opts.apiKey) {
2706
2753
  headers.Authorization = `Bearer ${opts.apiKey}`;
2707
2754
  }
@@ -3395,7 +3442,12 @@ async function spawnProviderProcess(
3395
3442
  function bufferEvent(evt: BufferedEvent) {
3396
3443
  eventBuffer.push(evt);
3397
3444
  if (eventBuffer.length >= EVENT_BUFFER_MAX) {
3398
- flushEvents();
3445
+ flushEvents().catch((err) =>
3446
+ console.error(
3447
+ "[runner] event flush failed:",
3448
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
3449
+ ),
3450
+ );
3399
3451
  }
3400
3452
  }
3401
3453
 
@@ -4086,7 +4138,12 @@ async function checkCompletedProcesses(
4086
4138
  cancelledSignaled?.delete(taskId);
4087
4139
 
4088
4140
  if (apiConfig) {
4089
- removeActiveSession(apiConfig, taskId);
4141
+ removeActiveSession(apiConfig, taskId).catch((err) =>
4142
+ console.error(
4143
+ "[runner] active-session removal failed:",
4144
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
4145
+ ),
4146
+ );
4090
4147
  }
4091
4148
 
4092
4149
  // Detect VCS before finishing — last chance to link a PR
@@ -4699,8 +4756,16 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
4699
4756
  let lastBedrockRefreshAt = 0;
4700
4757
  const BEDROCK_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
4701
4758
 
4759
+ // Fresh per boot and shared by registration, ping, and close: a restarted
4760
+ // process is a new runtime, but one process presents one identity.
4761
+ const runtimeInstanceId = crypto.randomUUID();
4762
+
4763
+ // Session MCP configs are built in provider adapters, which read this to
4764
+ // stamp the runtime identity onto worker tool calls.
4765
+ process.env.SWARM_RUNTIME_INSTANCE_ID = runtimeInstanceId;
4766
+
4702
4767
  // Create API config for ping/close
4703
- const apiConfig: ApiConfig = { apiUrl, apiKey, agentId };
4768
+ const apiConfig: ApiConfig = { apiUrl, apiKey, agentId, runtimeInstanceId };
4704
4769
 
4705
4770
  // Setup graceful shutdown handlers with API config and runner state access
4706
4771
  setupShutdownHandlers(role, apiConfig, () => state);
@@ -4821,22 +4886,32 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
4821
4886
  }
4822
4887
  };
4823
4888
 
4824
- /** Push the current live state back to the API so the dashboard reflects it. */
4889
+ /** Register this boot's runtime with the current live state; propagates failure. */
4890
+ const registerCurrentRuntime = async () => {
4891
+ const reg = await registerAgent({
4892
+ apiUrl,
4893
+ apiKey,
4894
+ agentId,
4895
+ name: agentName,
4896
+ role,
4897
+ isLead,
4898
+ capabilities,
4899
+ maxTasks: state.maxConcurrent,
4900
+ harnessProvider: state.harnessProvider,
4901
+ runtimeInstanceId,
4902
+ });
4903
+ lastServerCapsRefreshAt = Date.now();
4904
+ await applyServerCapabilities(reg.serverCapabilities);
4905
+ };
4906
+
4907
+ /**
4908
+ * Best-effort wrapper for the periodic/fire-and-forget callers: the
4909
+ * dashboard tolerates a missed refresh. Recovery paths that must observe
4910
+ * failure use registerCurrentRuntime directly.
4911
+ */
4825
4912
  const reregisterAgent = async () => {
4826
4913
  try {
4827
- const reg = await registerAgent({
4828
- apiUrl,
4829
- apiKey,
4830
- agentId,
4831
- name: agentName,
4832
- role,
4833
- isLead,
4834
- capabilities,
4835
- maxTasks: state.maxConcurrent,
4836
- harnessProvider: state.harnessProvider,
4837
- });
4838
- lastServerCapsRefreshAt = Date.now();
4839
- await applyServerCapabilities(reg.serverCapabilities);
4914
+ await registerCurrentRuntime();
4840
4915
  } catch (err) {
4841
4916
  console.warn(`[${role}] [config] Re-register failed (non-fatal): ${err}`);
4842
4917
  }
@@ -4852,6 +4927,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
4852
4927
  capabilities,
4853
4928
  maxTasks: maxConcurrent,
4854
4929
  harnessProvider: bootProvider,
4930
+ runtimeInstanceId,
4855
4931
  });
4856
4932
  lastServerCapsRefreshAt = Date.now();
4857
4933
  // Rebuilds the prompt immediately: the initial build above ran before
@@ -4918,6 +4994,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
4918
4994
  headers: {
4919
4995
  Authorization: `Bearer ${apiKey}`,
4920
4996
  "X-Agent-ID": agentId,
4997
+ "X-Runtime-Instance-ID": runtimeInstanceId,
4921
4998
  "Content-Type": "application/json",
4922
4999
  },
4923
5000
  body: JSON.stringify({ ready: status.ready, missing: status.missing }),
@@ -4934,16 +5011,71 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
4934
5011
  throw err;
4935
5012
  }
4936
5013
 
5014
+ // Re-register before reporting readiness or doing any work. A worker
5015
+ // blocked on credentials is not usable execution capacity, so its runtime
5016
+ // is allowed to expire during the wait rather than being kept alive
5017
+ // artificially — but once it can work again the server has to know, or
5018
+ // its pings and polls would reference a runtime that no longer exists
5019
+ // until the periodic refresh (up to 5 min later) happened to fix it.
5020
+ // Same per-boot runtime id, so this refreshes the original row instead of
5021
+ // creating a second one. Ordering matters: a readiness report sent while
5022
+ // the row is still stale is dropped (only a live runtime may report), and
5023
+ // the revival preserves credential_ready — reporting first would leave
5024
+ // the agent parked on waiting_for_credentials forever. Best-effort is not
5025
+ // enough here for the same reason: a swallowed transient failure would
5026
+ // still let the report target the stale row, so recovery retries and
5027
+ // treats exhaustion like boot-registration failure.
5028
+ try {
5029
+ await retryBootStep(registerCurrentRuntime, {
5030
+ label: "runtime re-registration",
5031
+ log: (line) => console.warn(`[${role}] ${line}`),
5032
+ });
5033
+ } catch (error) {
5034
+ console.error(`[${role}] Failed to re-register after credential wait: ${error}`);
5035
+ process.exit(1);
5036
+ }
5037
+
4937
5038
  // Migration 055: build the full snapshot (presence + live test) once
4938
5039
  // creds are ready and POST it to the agent row. Status endpoint reads
4939
5040
  // this instead of running predicates server-side. Always uses the
4940
5041
  // *current* state.harnessProvider in case it flipped during the wait.
5042
+ // The snapshot build stays best-effort — its live test can hiccup, and
5043
+ // that must not lose the readiness transition below.
5044
+ let bootCredSnapshot: Awaited<ReturnType<typeof buildCredStatusReport>> | undefined;
4941
5045
  try {
4942
- const snapshot = await buildCredStatusReport(state.harnessProvider, process.env, {}, "boot");
4943
- await reportCredStatus(apiUrl, apiKey, agentId, snapshot);
5046
+ bootCredSnapshot = await buildCredStatusReport(
5047
+ state.harnessProvider,
5048
+ process.env,
5049
+ {},
5050
+ "boot",
5051
+ );
4944
5052
  } catch (err) {
4945
- // Non-fatal — worker proceeds even if reporting fails.
4946
- console.warn(`[${role}] cred_status boot report failed (non-fatal): ${err}`);
5053
+ console.warn(`[${role}] cred_status boot snapshot failed (non-fatal): ${err}`);
5054
+ }
5055
+
5056
+ // The readiness write is the only transition out of
5057
+ // waiting_for_credentials after a stale-runtime revival (the wait's final
5058
+ // tick targeted the pre-registration row, and revival preserves the old
5059
+ // credential_ready) — so like the registration above, it retries and
5060
+ // treats exhaustion as a failed boot rather than proceeding parked.
5061
+ try {
5062
+ await retryBootStep(
5063
+ () =>
5064
+ sendCredStatusReport(apiUrl, apiKey, agentId, runtimeInstanceId, {
5065
+ // The snapshot's verdict when it built; otherwise the wait's own
5066
+ // conclusion (it only returns once credentials are ready).
5067
+ ready: bootCredSnapshot?.ready ?? true,
5068
+ missing: bootCredSnapshot?.missing ?? [],
5069
+ credStatus: bootCredSnapshot,
5070
+ }),
5071
+ {
5072
+ label: "credential readiness report",
5073
+ log: (line) => console.warn(`[${role}] ${line}`),
5074
+ },
5075
+ );
5076
+ } catch (error) {
5077
+ console.error(`[${role}] Failed to report credential readiness after recovery: ${error}`);
5078
+ process.exit(1);
4947
5079
  }
4948
5080
  }
4949
5081
 
@@ -5291,6 +5423,15 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5291
5423
  }
5292
5424
  }
5293
5425
 
5426
+ const resumeWithSyncWarning = await prependProfileSyncRejectionBanner(resumePrompt, {
5427
+ ...apiConfig,
5428
+ claudeMdPath: resolveClaudeMdPath([state.harnessProvider]),
5429
+ });
5430
+ resumePrompt = resumeWithSyncWarning.prompt;
5431
+ if (resumeWithSyncWarning.injected) {
5432
+ console.warn(`[${role}] Injected persisted profile sync rejection warning`);
5433
+ }
5434
+
5294
5435
  // Resolve provider-aware resume: prefer own session, then parent.
5295
5436
  const resumeCandidates: ResumeSessionCandidate[] = [
5296
5437
  {
@@ -5428,7 +5569,12 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5428
5569
  triggerType: "task_resumed",
5429
5570
  taskDescription: task.task?.slice(0, 200),
5430
5571
  runnerSessionId: resumeRunnerSessionId,
5431
- });
5572
+ }).catch((err) =>
5573
+ console.error(
5574
+ "[runner] active-session registration failed:",
5575
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
5576
+ ),
5577
+ );
5432
5578
  console.log(
5433
5579
  `[${role}] Resumed task ${task.id.slice(0, 8)} (${state.activeTasks.size}/${state.maxConcurrent} active)`,
5434
5580
  );
@@ -5522,7 +5668,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5522
5668
  if (currentHarness !== cachedCredHarnessProvider) {
5523
5669
  cachedCredHarnessProvider = currentHarness;
5524
5670
  buildCredStatusReport(currentHarness, process.env, {}, "post_task")
5525
- .then((snap) => reportCredStatus(apiUrl, apiKey, agentId, snap))
5671
+ .then((snap) => reportCredStatus(apiUrl, apiKey, agentId, runtimeInstanceId, snap))
5526
5672
  .catch((err) =>
5527
5673
  console.warn(`[${role}] cred_status post_task report failed (non-fatal): ${err}`),
5528
5674
  );
@@ -5538,7 +5684,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5538
5684
  // account state. One bounded AWS round-trip per tick.
5539
5685
  lastBedrockRefreshAt = Date.now();
5540
5686
  buildCredStatusReport(currentHarness, process.env, {}, "post_task")
5541
- .then((snap) => reportCredStatus(apiUrl, apiKey, agentId, snap))
5687
+ .then((snap) => reportCredStatus(apiUrl, apiKey, agentId, runtimeInstanceId, snap))
5542
5688
  .catch((err) =>
5543
5689
  console.warn(`[${role}] bedrock enumeration refresh failed (non-fatal): ${err}`),
5544
5690
  );
@@ -5554,7 +5700,12 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5554
5700
  if (!task.workingDir) continue;
5555
5701
 
5556
5702
  vcsCheckTimestamps.set(taskId, now);
5557
- detectVcsForTask(apiUrl, apiKey, taskId, task.workingDir);
5703
+ detectVcsForTask(apiUrl, apiKey, taskId, task.workingDir).catch((err) =>
5704
+ console.error(
5705
+ "[runner] VCS detection failed:",
5706
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
5707
+ ),
5708
+ );
5558
5709
  }
5559
5710
 
5560
5711
  // Check for cancelled tasks and signal their subprocesses. Deliberately
@@ -5631,6 +5782,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5631
5782
  apiKey,
5632
5783
  agentId,
5633
5784
  pollInterval: PollIntervalMs,
5785
+ runtimeInstanceId,
5634
5786
  pollTimeout: effectiveTimeout,
5635
5787
  });
5636
5788
 
@@ -5739,6 +5891,15 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5739
5891
  }
5740
5892
  }
5741
5893
 
5894
+ const triggerWithSyncWarning = await prependProfileSyncRejectionBanner(triggerPrompt, {
5895
+ ...apiConfig,
5896
+ claudeMdPath: resolveClaudeMdPath([state.harnessProvider]),
5897
+ });
5898
+ triggerPrompt = triggerWithSyncWarning.prompt;
5899
+ if (triggerWithSyncWarning.injected) {
5900
+ console.warn(`[${role}] Injected persisted profile sync rejection warning`);
5901
+ }
5902
+
5742
5903
  // Resolve provider-aware resume for child tasks with parentTaskId.
5743
5904
  let resumeSessionId: string | undefined;
5744
5905
  if (taskObj?.parentTaskId) {
@@ -5990,7 +6151,12 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
5990
6151
  triggerType: trigger.type,
5991
6152
  taskDescription: taskDesc,
5992
6153
  runnerSessionId: taskRunnerSessionId,
5993
- });
6154
+ }).catch((err) =>
6155
+ console.error(
6156
+ "[runner] active-session registration failed:",
6157
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
6158
+ ),
6159
+ );
5994
6160
 
5995
6161
  console.log(
5996
6162
  `[${role}] Started task ${runningTask.taskId.slice(0, 8)} (${state.activeTasks.size}/${state.maxConcurrent} active, trigger: ${trigger.type})`,
@@ -50,6 +50,28 @@ Accept if you have capacity and skills. Reject with a reason if you cannot handl
50
50
  category: "task_lifecycle",
51
51
  });
52
52
 
53
+ registerTemplate({
54
+ eventType: "task.profile_sync_rejection",
55
+ header: "",
56
+ defaultBody: `=== PERSISTED PROFILE SYNC REJECTION ===
57
+ A {{timestamp}} sync of {{field_label}} did not reach the database. Disk size: {{disk_size}}; DB size: {{db_size}}; budget: {{budget}}; delta: {{delta}}.
58
+ Audit event: {{event_id}}. {{recovery_guidance}}
59
+ === END PROFILE SYNC REJECTION ===
60
+
61
+ `,
62
+ variables: [
63
+ { name: "timestamp", description: "UTC timestamp of the rejected sync" },
64
+ { name: "field_label", description: "Profile field and its harness-specific file path" },
65
+ { name: "disk_size", description: "Rejected local file size" },
66
+ { name: "db_size", description: "Stored database field size" },
67
+ { name: "budget", description: "Configured field budget" },
68
+ { name: "delta", description: "Signed size delta" },
69
+ { name: "event_id", description: "Persisted audit event ID" },
70
+ { name: "recovery_guidance", description: "Accurate field-specific recovery instructions" },
71
+ ],
72
+ category: "task_lifecycle",
73
+ });
74
+
53
75
  registerTemplate({
54
76
  eventType: "task.trigger.unread_mentions",
55
77
  header: "",
@@ -4,6 +4,7 @@ import { findUserByExternalId } from "../be/users";
4
4
  import { resolveTemplate } from "../prompts/resolver";
5
5
  import { githubContextKey } from "../tasks/context-key";
6
6
  import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
7
+ import { scrubSecrets } from "../utils/secret-scrubber";
7
8
  import { getInstallationToken } from "./app";
8
9
  import {
9
10
  detectMention,
@@ -280,7 +281,12 @@ export async function handlePullRequest(
280
281
  }
281
282
 
282
283
  if (installation?.id) {
283
- addIssueReaction(repository.full_name, pr.number, "eyes", installation.id);
284
+ addIssueReaction(repository.full_name, pr.number, "eyes", installation.id).catch((err) =>
285
+ console.error(
286
+ "[GitHub] failed to add issue reaction:",
287
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
288
+ ),
289
+ );
284
290
  }
285
291
 
286
292
  return { created: true, taskId: task.id };
@@ -388,7 +394,12 @@ export async function handlePullRequest(
388
394
  }
389
395
 
390
396
  if (installation?.id) {
391
- addIssueReaction(repository.full_name, pr.number, "eyes", installation.id);
397
+ addIssueReaction(repository.full_name, pr.number, "eyes", installation.id).catch((err) =>
398
+ console.error(
399
+ "[GitHub] failed to add issue reaction:",
400
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
401
+ ),
402
+ );
392
403
  }
393
404
 
394
405
  return { created: true, taskId: task.id };
@@ -488,7 +499,12 @@ export async function handlePullRequest(
488
499
  }
489
500
 
490
501
  if (installation?.id) {
491
- addIssueReaction(repository.full_name, pr.number, "eyes", installation.id);
502
+ addIssueReaction(repository.full_name, pr.number, "eyes", installation.id).catch((err) =>
503
+ console.error(
504
+ "[GitHub] failed to add issue reaction:",
505
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
506
+ ),
507
+ );
492
508
  }
493
509
 
494
510
  return { created: true, taskId: task.id };
@@ -577,7 +593,12 @@ export async function handlePullRequest(
577
593
 
578
594
  // Add 👀 reaction to acknowledge the mention
579
595
  if (installation?.id) {
580
- addIssueReaction(repository.full_name, pr.number, "eyes", installation.id);
596
+ addIssueReaction(repository.full_name, pr.number, "eyes", installation.id).catch((err) =>
597
+ console.error(
598
+ "[GitHub] failed to add issue reaction:",
599
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
600
+ ),
601
+ );
581
602
  }
582
603
 
583
604
  return { created: true, taskId: task.id };
@@ -657,7 +678,12 @@ export async function handleIssue(
657
678
  }
658
679
 
659
680
  if (installation?.id) {
660
- addIssueReaction(repository.full_name, issue.number, "eyes", installation.id);
681
+ addIssueReaction(repository.full_name, issue.number, "eyes", installation.id).catch((err) =>
682
+ console.error(
683
+ "[GitHub] failed to add issue reaction:",
684
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
685
+ ),
686
+ );
661
687
  }
662
688
 
663
689
  return { created: true, taskId: task.id };
@@ -753,7 +779,12 @@ export async function handleIssue(
753
779
  }
754
780
 
755
781
  if (installation?.id) {
756
- addIssueReaction(repository.full_name, issue.number, "eyes", installation.id);
782
+ addIssueReaction(repository.full_name, issue.number, "eyes", installation.id).catch((err) =>
783
+ console.error(
784
+ "[GitHub] failed to add issue reaction:",
785
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
786
+ ),
787
+ );
757
788
  }
758
789
 
759
790
  return { created: true, taskId: task.id };
@@ -824,7 +855,12 @@ export async function handleIssue(
824
855
 
825
856
  // Add 👀 reaction to acknowledge the mention
826
857
  if (installation?.id) {
827
- addIssueReaction(repository.full_name, issue.number, "eyes", installation.id);
858
+ addIssueReaction(repository.full_name, issue.number, "eyes", installation.id).catch((err) =>
859
+ console.error(
860
+ "[GitHub] failed to add issue reaction:",
861
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
862
+ ),
863
+ );
828
864
  }
829
865
 
830
866
  return { created: true, taskId: task.id };
@@ -932,7 +968,12 @@ export async function handleComment(
932
968
 
933
969
  // Add 👀 reaction to the comment to acknowledge the mention
934
970
  if (installation?.id) {
935
- addReaction(repository.full_name, comment.id, "eyes", installation.id);
971
+ addReaction(repository.full_name, comment.id, "eyes", installation.id).catch((err) =>
972
+ console.error(
973
+ "[GitHub] failed to add comment reaction:",
974
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
975
+ ),
976
+ );
936
977
  }
937
978
 
938
979
  return { created: true, taskId: task.id };
@@ -1240,7 +1281,12 @@ export async function handlePullRequestReview(
1240
1281
 
1241
1282
  // Add reaction to acknowledge the review
1242
1283
  if (installation?.id) {
1243
- addIssueReaction(repository.full_name, pr.number, "eyes", installation.id);
1284
+ addIssueReaction(repository.full_name, pr.number, "eyes", installation.id).catch((err) =>
1285
+ console.error(
1286
+ "[GitHub] failed to add issue reaction:",
1287
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
1288
+ ),
1289
+ );
1244
1290
  }
1245
1291
 
1246
1292
  return { created: true, taskId: task.id };