@wardby/cli 0.5.3 → 0.7.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 (763) hide show
  1. package/.env.example +33 -0
  2. package/README.md +25 -14
  3. package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
  4. package/dist/claude-coding-worker/context.d.ts +22 -0
  5. package/dist/claude-coding-worker/context.js +92 -0
  6. package/dist/claude-coding-worker/driver.d.ts +27 -3
  7. package/dist/claude-coding-worker/driver.js +161 -20
  8. package/dist/claude-coding-worker/main.js +34 -6
  9. package/dist/claude-coding-worker/sdk.js +25 -5
  10. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  11. package/dist/claude-coding-worker/tool-socket.js +111 -0
  12. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  13. package/dist/claude-coding-worker/transcript.js +77 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +6 -2
  16. package/dist/cli-native-mode.d.ts +9 -0
  17. package/dist/cli-native-mode.js +20 -0
  18. package/dist/cli.d.ts +3 -1
  19. package/dist/cli.js +161 -11
  20. package/dist/coding/claude-context.d.ts +45 -0
  21. package/dist/coding/claude-context.js +434 -0
  22. package/dist/coding/continuation-wording.d.ts +35 -0
  23. package/dist/coding/continuation-wording.js +73 -0
  24. package/dist/coding/linked-issue-note.d.ts +23 -0
  25. package/dist/coding/linked-issue-note.js +47 -0
  26. package/dist/coding/merge-wording.d.ts +28 -0
  27. package/dist/coding/merge-wording.js +78 -0
  28. package/dist/coding/pr-description-note.d.ts +9 -0
  29. package/dist/coding/pr-description-note.js +32 -0
  30. package/dist/coding/profile.d.ts +50 -118
  31. package/dist/coding/profile.js +51 -4
  32. package/dist/coding/protected-path-wording.d.ts +8 -0
  33. package/dist/coding/protected-path-wording.js +1 -1
  34. package/dist/coding/protocol.d.ts +292 -270
  35. package/dist/coding/protocol.js +322 -15
  36. package/dist/coding/redact.d.ts +3 -0
  37. package/dist/coding/redact.js +12 -0
  38. package/dist/coding/registry/allowlist.d.ts +12 -0
  39. package/dist/coding/registry/allowlist.js +14 -1
  40. package/dist/coding/registry/audit-mode.d.ts +153 -0
  41. package/dist/coding/registry/audit-mode.js +304 -0
  42. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  43. package/dist/coding/registry/lockfile-shared.js +128 -0
  44. package/dist/coding/registry/lockfiles.js +1 -1
  45. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  46. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  47. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  48. package/dist/coding/registry/npm-lockfile.js +4 -6
  49. package/dist/coding/registry/npm.js +78 -8
  50. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  51. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  52. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  53. package/dist/coding/registry/pypi-plan.js +406 -0
  54. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  55. package/dist/coding/registry/pypi-requirements.js +155 -0
  56. package/dist/coding/registry/pypi.d.ts +3 -27
  57. package/dist/coding/registry/pypi.js +40 -154
  58. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  59. package/dist/coding/registry/refusal-hints.js +61 -0
  60. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  61. package/dist/coding/registry/refusal-wording.js +56 -0
  62. package/dist/coding/registry/report.d.ts +70 -8
  63. package/dist/coding/registry/report.js +112 -5
  64. package/dist/coding/registry/types.d.ts +58 -8
  65. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  66. package/dist/coding/registry/yarn-lockfile.js +367 -0
  67. package/dist/coding/services/catalog.d.ts +37 -351
  68. package/dist/coding/transcript/claude-code.d.ts +13 -0
  69. package/dist/coding/transcript/claude-code.js +273 -0
  70. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  71. package/dist/coding/transcript/download-protocol.js +18 -0
  72. package/dist/coding/transcript/format.d.ts +20 -0
  73. package/dist/coding/transcript/format.js +32 -0
  74. package/dist/coding/transcript/recorder.d.ts +51 -0
  75. package/dist/coding/transcript/recorder.js +225 -0
  76. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  77. package/dist/coding/transcript/resume/checkout.js +203 -0
  78. package/dist/coding/transcript/resume/command.d.ts +17 -0
  79. package/dist/coding/transcript/resume/command.js +176 -0
  80. package/dist/coding/transcript/resume/download.d.ts +20 -0
  81. package/dist/coding/transcript/resume/download.js +153 -0
  82. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  83. package/dist/coding/transcript/resume/launch.js +128 -0
  84. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  85. package/dist/coding/transcript/resume/session-file.js +79 -0
  86. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  87. package/dist/coding/transcript/resume/stand-in.js +49 -0
  88. package/dist/coding-worker/artifact.d.ts +16 -3
  89. package/dist/coding-worker/artifact.js +5 -3
  90. package/dist/coding-worker/debug-trace.d.ts +6 -5
  91. package/dist/coding-worker/debug-trace.js +13 -18
  92. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  93. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  94. package/dist/coding-worker/driver.d.ts +4 -3
  95. package/dist/coding-worker/driver.js +118 -38
  96. package/dist/coding-worker/errors.d.ts +1 -0
  97. package/dist/coding-worker/errors.js +32 -0
  98. package/dist/coding-worker/sdk.d.ts +6 -0
  99. package/dist/coding-worker/sdk.js +1 -0
  100. package/dist/coding-worker/skills.d.ts +23 -0
  101. package/dist/coding-worker/skills.js +117 -0
  102. package/dist/coding-worker/task-note.d.ts +11 -0
  103. package/dist/coding-worker/task-note.js +13 -0
  104. package/dist/coding-worker/types.d.ts +13 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/github-allowed-accounts.d.ts +15 -0
  108. package/dist/config/github-allowed-accounts.js +36 -0
  109. package/dist/config/low-power.d.ts +12 -0
  110. package/dist/config/low-power.js +18 -0
  111. package/dist/config/mobile.d.ts +12 -0
  112. package/dist/config/mobile.js +18 -0
  113. package/dist/config/providers.d.ts +65 -3
  114. package/dist/config/providers.js +147 -11
  115. package/dist/config/test-simulators.d.ts +82 -0
  116. package/dist/config/test-simulators.js +305 -0
  117. package/dist/core/async-context.d.ts +2 -0
  118. package/dist/core/async-context.js +12 -0
  119. package/dist/core/budget-events.d.ts +108 -0
  120. package/dist/core/budget-events.js +346 -0
  121. package/dist/core/budget-groups.d.ts +50 -1
  122. package/dist/core/budget-groups.js +236 -27
  123. package/dist/core/budget-stopped-head.d.ts +46 -0
  124. package/dist/core/budget-stopped-head.js +81 -0
  125. package/dist/core/budget-topup.d.ts +51 -0
  126. package/dist/core/budget-topup.js +156 -0
  127. package/dist/core/budget-wording.d.ts +16 -2
  128. package/dist/core/budget-wording.js +40 -2
  129. package/dist/core/coding-queue.d.ts +2 -1
  130. package/dist/core/coding-queue.js +7 -0
  131. package/dist/core/cron.d.ts +19 -1
  132. package/dist/core/cron.js +17 -0
  133. package/dist/core/datastores.js +1 -1
  134. package/dist/core/db.d.ts +16 -6
  135. package/dist/core/db.js +12 -10
  136. package/dist/core/deferred-coding.d.ts +14 -0
  137. package/dist/core/deferred-coding.js +62 -0
  138. package/dist/core/delegation-child.d.ts +25 -0
  139. package/dist/core/delegation-child.js +37 -0
  140. package/dist/core/dispatch.d.ts +53 -0
  141. package/dist/core/dispatch.js +167 -57
  142. package/dist/core/engine-native.js +10 -6
  143. package/dist/core/error-code.d.ts +38 -0
  144. package/dist/core/error-code.js +168 -0
  145. package/dist/core/grants.d.ts +19 -6
  146. package/dist/core/grants.js +55 -6
  147. package/dist/core/host-events.d.ts +67 -5
  148. package/dist/core/host-events.js +571 -37
  149. package/dist/core/host-status.d.ts +85 -3
  150. package/dist/core/host-status.js +298 -20
  151. package/dist/core/issue-bridge.d.ts +50 -6
  152. package/dist/core/issue-bridge.js +151 -20
  153. package/dist/core/issue-events.d.ts +1 -1
  154. package/dist/core/issue-events.js +16 -11
  155. package/dist/core/issue-status.d.ts +1 -1
  156. package/dist/core/issue-status.js +68 -29
  157. package/dist/core/logger.d.ts +5 -0
  158. package/dist/core/logger.js +14 -1
  159. package/dist/core/lost-run-children.d.ts +6 -0
  160. package/dist/core/lost-run-children.js +32 -0
  161. package/dist/core/mark-ready.d.ts +34 -0
  162. package/dist/core/mark-ready.js +152 -0
  163. package/dist/core/markdown-code.d.ts +8 -0
  164. package/dist/core/markdown-code.js +107 -0
  165. package/dist/core/memory-tools.js +7 -0
  166. package/dist/core/merge-order-check.d.ts +130 -0
  167. package/dist/core/merge-order-check.js +343 -0
  168. package/dist/core/notification-dispatcher.d.ts +70 -0
  169. package/dist/core/notification-dispatcher.js +368 -0
  170. package/dist/core/notification-templates.d.ts +19 -0
  171. package/dist/core/notification-templates.js +139 -0
  172. package/dist/core/notifications.d.ts +10 -0
  173. package/dist/core/notifications.js +38 -0
  174. package/dist/core/pg-auth.d.ts +22 -0
  175. package/dist/core/pg-auth.js +152 -0
  176. package/dist/core/power-composition.d.ts +16 -0
  177. package/dist/core/power-composition.js +37 -0
  178. package/dist/core/power-idle.d.ts +14 -0
  179. package/dist/core/power-idle.js +30 -0
  180. package/dist/core/power.d.ts +71 -0
  181. package/dist/core/power.js +202 -0
  182. package/dist/core/pull-request-state-sync.js +2 -2
  183. package/dist/core/reconciler.d.ts +8 -5
  184. package/dist/core/reconciler.js +37 -6
  185. package/dist/core/related-pull-requests.d.ts +59 -7
  186. package/dist/core/related-pull-requests.js +140 -25
  187. package/dist/core/reply-parts.d.ts +21 -0
  188. package/dist/core/reply-parts.js +73 -0
  189. package/dist/core/repo-access.d.ts +15 -0
  190. package/dist/core/repo-access.js +66 -0
  191. package/dist/core/review-fix.d.ts +38 -1
  192. package/dist/core/review-fix.js +209 -7
  193. package/dist/core/review-host-checks.d.ts +1 -1
  194. package/dist/core/review-host-tools.d.ts +23 -0
  195. package/dist/core/review-host-tools.js +156 -14
  196. package/dist/core/review-reads.d.ts +55 -0
  197. package/dist/core/review-reads.js +233 -0
  198. package/dist/core/run-status.d.ts +12 -0
  199. package/dist/core/run-status.js +12 -0
  200. package/dist/core/runner.d.ts +384 -5
  201. package/dist/core/runner.js +1244 -372
  202. package/dist/core/schedule-start.d.ts +12 -0
  203. package/dist/core/schedule-start.js +14 -0
  204. package/dist/core/secret-broker-config.d.ts +39 -0
  205. package/dist/core/secret-broker-config.js +112 -0
  206. package/dist/core/secret-guard.d.ts +46 -0
  207. package/dist/core/secret-guard.js +104 -0
  208. package/dist/core/secret-guarded-stores.d.ts +12 -0
  209. package/dist/core/secret-guarded-stores.js +41 -0
  210. package/dist/core/secret-spans.d.ts +50 -0
  211. package/dist/core/secret-spans.js +94 -0
  212. package/dist/core/secrets.d.ts +39 -4
  213. package/dist/core/secrets.js +148 -40
  214. package/dist/core/stop-run.d.ts +46 -0
  215. package/dist/core/stop-run.js +61 -0
  216. package/dist/core/workflow-event-recorder.d.ts +14 -0
  217. package/dist/core/workflow-event-recorder.js +120 -0
  218. package/dist/core/workflow-events.d.ts +94 -0
  219. package/dist/core/workflow-events.js +48 -0
  220. package/dist/core/workflow-run-events.d.ts +18 -0
  221. package/dist/core/workflow-run-events.js +75 -0
  222. package/dist/core/zod-json-schema.d.ts +4 -0
  223. package/dist/core/zod-json-schema.js +39 -0
  224. package/dist/core/zod3-window.d.ts +35 -0
  225. package/dist/core/zod3-window.js +124 -0
  226. package/dist/generated/prisma/browser.d.ts +92 -3
  227. package/dist/generated/prisma/client.d.ts +92 -3
  228. package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
  229. package/dist/generated/prisma/enums.d.ts +37 -0
  230. package/dist/generated/prisma/enums.js +31 -0
  231. package/dist/generated/prisma/internal/class.d.ts +132 -0
  232. package/dist/generated/prisma/internal/class.js +4 -4
  233. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
  234. package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
  235. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
  236. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
  237. package/dist/generated/prisma/models/Agent.d.ts +464 -7
  238. package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
  239. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -1
  240. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  241. package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
  242. package/dist/generated/prisma/models/CodingRun.d.ts +1841 -1
  243. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  244. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  245. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  246. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  247. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  248. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1713 -0
  249. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  250. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
  251. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  252. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  253. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  254. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  255. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  256. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  257. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  258. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  259. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  260. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  261. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  262. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  263. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  264. package/dist/generated/prisma/models/Run.d.ts +1619 -58
  265. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  266. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  267. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  268. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  269. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  270. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  271. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  272. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  273. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  274. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  275. package/dist/generated/prisma/models.d.ts +12 -0
  276. package/dist/help/build.js +4 -2
  277. package/dist/help/catalog.d.ts +1 -1
  278. package/dist/help/catalog.js +31 -6
  279. package/dist/help-index.json +2584 -146
  280. package/dist/import/create.js +49 -3
  281. package/dist/import/neutral-schema.d.ts +50 -277
  282. package/dist/import/neutral-schema.js +7 -4
  283. package/dist/knowledge/check.d.ts +1 -1
  284. package/dist/knowledge/cli.d.ts +11 -1
  285. package/dist/knowledge/cli.js +37 -4
  286. package/dist/knowledge/concept.d.ts +3 -19
  287. package/dist/knowledge/location.d.ts +31 -0
  288. package/dist/knowledge/location.js +78 -0
  289. package/dist/mcp/auth/access.d.ts +11 -2
  290. package/dist/mcp/auth/access.js +15 -1
  291. package/dist/mcp/auth/ownership.d.ts +7 -7
  292. package/dist/mcp/auth/repo-authorization.js +14 -0
  293. package/dist/mcp/auth/resource-server.d.ts +2 -1
  294. package/dist/mcp/auth/resource-server.js +7 -2
  295. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  296. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  297. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  298. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  299. package/dist/mcp/context.d.ts +6 -0
  300. package/dist/mcp/host-events/github-ingress.d.ts +25 -1
  301. package/dist/mcp/host-events/github-ingress.js +70 -1
  302. package/dist/mcp/index.d.ts +19 -0
  303. package/dist/mcp/index.js +117 -20
  304. package/dist/mcp/server.d.ts +13 -0
  305. package/dist/mcp/server.js +33 -14
  306. package/dist/mcp/tools/agents.d.ts +4 -0
  307. package/dist/mcp/tools/agents.js +277 -24
  308. package/dist/mcp/tools/datastore.js +17 -8
  309. package/dist/mcp/tools/grants.js +9 -3
  310. package/dist/mcp/tools/memory.js +11 -1
  311. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  312. package/dist/mcp/tools/notification-channels.js +293 -0
  313. package/dist/mcp/tools/packages.d.ts +2 -0
  314. package/dist/mcp/tools/packages.js +195 -0
  315. package/dist/mcp/tools/power.d.ts +2 -0
  316. package/dist/mcp/tools/power.js +77 -0
  317. package/dist/mcp/tools/repositories.js +18 -5
  318. package/dist/mcp/tools/run-access.d.ts +16 -0
  319. package/dist/mcp/tools/run-access.js +25 -0
  320. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  321. package/dist/mcp/tools/run-transcript-download.js +129 -0
  322. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  323. package/dist/mcp/tools/run-transcript.js +70 -0
  324. package/dist/mcp/tools/runs.d.ts +0 -6
  325. package/dist/mcp/tools/runs.js +41 -14
  326. package/dist/mcp/tools/scheduling.js +3 -1
  327. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  328. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  329. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  330. package/dist/mcp/tools/secret-elicitation-form.js +205 -10
  331. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  332. package/dist/mcp/tools/secret-elicitation-server.js +10 -54
  333. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  334. package/dist/mcp/tools/secret-elicitation.js +110 -12
  335. package/dist/mcp/tools/secrets.js +186 -9
  336. package/dist/mcp/tools/stop-run.d.ts +2 -0
  337. package/dist/mcp/tools/stop-run.js +82 -0
  338. package/dist/mcp/tools/subagents.js +2 -2
  339. package/dist/mcp/tools/tools.d.ts +2 -2
  340. package/dist/mcp/tools/tools.js +47 -11
  341. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  342. package/dist/mcp/transport/stdio-link-host.js +67 -0
  343. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  344. package/dist/mcp/transport/streamable-http.js +41 -1
  345. package/dist/native-worker/composition.d.ts +23 -0
  346. package/dist/native-worker/composition.js +77 -0
  347. package/dist/native-worker/docker-isolation.d.ts +65 -0
  348. package/dist/native-worker/docker-isolation.js +183 -0
  349. package/dist/native-worker/docker-launcher.d.ts +110 -0
  350. package/dist/native-worker/docker-launcher.js +297 -0
  351. package/dist/native-worker/gateway-server.d.ts +77 -0
  352. package/dist/native-worker/gateway-server.js +412 -0
  353. package/dist/native-worker/gateway.d.ts +70 -0
  354. package/dist/native-worker/gateway.js +263 -0
  355. package/dist/native-worker/http-server.d.ts +24 -0
  356. package/dist/native-worker/http-server.js +113 -0
  357. package/dist/native-worker/http-transport.d.ts +17 -0
  358. package/dist/native-worker/http-transport.js +88 -0
  359. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  360. package/dist/native-worker/kubernetes-isolation.js +218 -0
  361. package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
  362. package/dist/native-worker/kubernetes-launcher.js +375 -0
  363. package/dist/native-worker/launch.d.ts +62 -0
  364. package/dist/native-worker/launch.js +49 -0
  365. package/dist/native-worker/ledger.d.ts +125 -0
  366. package/dist/native-worker/ledger.js +245 -0
  367. package/dist/native-worker/loopback.d.ts +12 -0
  368. package/dist/native-worker/loopback.js +44 -0
  369. package/dist/native-worker/main.d.ts +8 -0
  370. package/dist/native-worker/main.js +85 -0
  371. package/dist/native-worker/protocol.d.ts +296 -0
  372. package/dist/native-worker/protocol.js +246 -0
  373. package/dist/native-worker/sandbox-executor.d.ts +83 -0
  374. package/dist/native-worker/sandbox-executor.js +284 -0
  375. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  376. package/dist/native-worker/stderr-redaction.js +237 -0
  377. package/dist/native-worker/stdio.d.ts +29 -0
  378. package/dist/native-worker/stdio.js +189 -0
  379. package/dist/native-worker/warm-delivery.d.ts +16 -0
  380. package/dist/native-worker/warm-delivery.js +33 -0
  381. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  382. package/dist/native-worker/warm-pool-ledger.js +73 -0
  383. package/dist/native-worker/warm-pool.d.ts +107 -0
  384. package/dist/native-worker/warm-pool.js +283 -0
  385. package/dist/native-worker/worker.d.ts +17 -0
  386. package/dist/native-worker/worker.js +141 -0
  387. package/dist/observability/metrics.js +6 -1
  388. package/dist/providers/auth/authorization-server.d.ts +3 -0
  389. package/dist/providers/auth/index.js +2 -0
  390. package/dist/providers/auth/self-hosted.d.ts +14 -2
  391. package/dist/providers/auth/self-hosted.js +54 -4
  392. package/dist/providers/chat/fake.d.ts +46 -0
  393. package/dist/providers/chat/fake.js +39 -0
  394. package/dist/providers/chat/index.d.ts +4 -0
  395. package/dist/providers/chat/index.js +8 -0
  396. package/dist/providers/chat/slack.d.ts +37 -0
  397. package/dist/providers/chat/slack.js +105 -0
  398. package/dist/providers/chat/types.d.ts +42 -0
  399. package/dist/providers/chat/types.js +19 -0
  400. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  401. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  402. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  403. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  404. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  405. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  406. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  407. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  408. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  409. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  410. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  411. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  412. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  413. package/dist/providers/coding-proxy/hold.js +86 -0
  414. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  415. package/dist/providers/coding-proxy/interrupted.js +104 -0
  416. package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
  417. package/dist/providers/coding-proxy/memory-ledger.js +84 -8
  418. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  419. package/dist/providers/coding-proxy/metering.js +27 -4
  420. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
  421. package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
  422. package/dist/providers/coding-proxy/proxy.d.ts +14 -1
  423. package/dist/providers/coding-proxy/proxy.js +166 -14
  424. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  425. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  426. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  427. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  428. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  429. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  430. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  431. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  432. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  433. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  434. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  435. package/dist/providers/coding-proxy/registry/service.js +579 -112
  436. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  437. package/dist/providers/coding-proxy/registry/store.js +54 -1
  438. package/dist/providers/coding-proxy/runtime.d.ts +4 -0
  439. package/dist/providers/coding-proxy/runtime.js +78 -16
  440. package/dist/providers/coding-proxy/server.d.ts +6 -1
  441. package/dist/providers/coding-proxy/server.js +45 -1
  442. package/dist/providers/coding-proxy/types.d.ts +65 -1
  443. package/dist/providers/datastore/types.d.ts +5 -0
  444. package/dist/providers/engine/types.d.ts +36 -2
  445. package/dist/providers/engine/types.js +39 -0
  446. package/dist/providers/executor/composition.d.ts +31 -1
  447. package/dist/providers/executor/composition.js +81 -8
  448. package/dist/providers/executor/container.d.ts +385 -9
  449. package/dist/providers/executor/container.js +1234 -99
  450. package/dist/providers/executor/dbos-status.d.ts +31 -0
  451. package/dist/providers/executor/dbos-status.js +64 -0
  452. package/dist/providers/executor/dbos.d.ts +91 -0
  453. package/dist/providers/executor/dbos.js +319 -26
  454. package/dist/providers/executor/deferred.d.ts +44 -0
  455. package/dist/providers/executor/deferred.js +100 -0
  456. package/dist/providers/executor/in-process.d.ts +9 -1
  457. package/dist/providers/executor/in-process.js +14 -4
  458. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  459. package/dist/providers/executor/linked-issue-reader.js +30 -0
  460. package/dist/providers/executor/routing.d.ts +39 -10
  461. package/dist/providers/executor/routing.js +77 -32
  462. package/dist/providers/executor/types.d.ts +25 -0
  463. package/dist/providers/index.d.ts +2 -1
  464. package/dist/providers/issue-tracker/types.d.ts +17 -0
  465. package/dist/providers/issue-tracker/types.js +39 -1
  466. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  467. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  468. package/dist/providers/jobs/docker-isolation.d.ts +8 -0
  469. package/dist/providers/jobs/docker-isolation.js +17 -0
  470. package/dist/providers/jobs/docker.d.ts +1 -0
  471. package/dist/providers/jobs/docker.js +29 -4
  472. package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
  473. package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
  474. package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
  475. package/dist/providers/jobs/kubernetes-api.js +17 -0
  476. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  477. package/dist/providers/jobs/kubernetes-client.js +61 -3
  478. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  479. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  480. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  481. package/dist/providers/jobs/kubernetes-isolation.js +23 -1
  482. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  483. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  484. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  485. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  486. package/dist/providers/jobs/kubernetes.d.ts +42 -2
  487. package/dist/providers/jobs/kubernetes.js +178 -19
  488. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  489. package/dist/providers/jobs/metadata-probes.js +13 -0
  490. package/dist/providers/jobs/types.d.ts +42 -0
  491. package/dist/providers/jobs/types.js +13 -1
  492. package/dist/providers/llm/anthropic.js +5 -1
  493. package/dist/providers/llm/bedrock.d.ts +0 -12
  494. package/dist/providers/llm/bedrock.js +4 -0
  495. package/dist/providers/llm/claude-messages.d.ts +3 -1
  496. package/dist/providers/llm/claude-messages.js +4 -1
  497. package/dist/providers/llm/claude-provider.d.ts +2 -2
  498. package/dist/providers/llm/claude-provider.js +2 -2
  499. package/dist/providers/llm/openai.d.ts +2 -2
  500. package/dist/providers/llm/openai.js +6 -2
  501. package/dist/providers/llm/routing.d.ts +2 -2
  502. package/dist/providers/llm/routing.js +2 -2
  503. package/dist/providers/llm/types.d.ts +12 -2
  504. package/dist/providers/review-host/github-events.d.ts +9 -1
  505. package/dist/providers/review-host/github-events.js +34 -12
  506. package/dist/providers/review-host/github.d.ts +39 -2
  507. package/dist/providers/review-host/github.js +274 -29
  508. package/dist/providers/review-host/local.d.ts +8 -4
  509. package/dist/providers/review-host/local.js +49 -31
  510. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  511. package/dist/providers/review-host/patch-pages.js +176 -0
  512. package/dist/providers/review-host/review-format.d.ts +19 -1
  513. package/dist/providers/review-host/review-format.js +38 -7
  514. package/dist/providers/review-host/types.d.ts +157 -2
  515. package/dist/providers/review-host/types.js +8 -0
  516. package/dist/providers/storage/gcs.d.ts +63 -0
  517. package/dist/providers/storage/gcs.js +69 -0
  518. package/dist/providers/storage/index.d.ts +15 -0
  519. package/dist/providers/storage/index.js +14 -0
  520. package/dist/providers/storage/local.d.ts +24 -0
  521. package/dist/providers/storage/local.js +92 -0
  522. package/dist/providers/storage/meter.d.ts +14 -0
  523. package/dist/providers/storage/meter.js +34 -0
  524. package/dist/providers/storage/s3.d.ts +41 -0
  525. package/dist/providers/storage/s3.js +107 -0
  526. package/dist/providers/storage/types.d.ts +37 -3
  527. package/dist/providers/storage/types.js +21 -4
  528. package/dist/providers/vcs/git.d.ts +33 -2
  529. package/dist/providers/vcs/git.js +324 -22
  530. package/dist/providers/vcs/github-remote.d.ts +26 -3
  531. package/dist/providers/vcs/github-remote.js +124 -14
  532. package/dist/providers/vcs/github.d.ts +246 -12
  533. package/dist/providers/vcs/github.js +521 -61
  534. package/dist/providers/vcs/index.js +8 -1
  535. package/dist/providers/vcs/pr-description.d.ts +127 -0
  536. package/dist/providers/vcs/pr-description.js +270 -0
  537. package/dist/providers/vcs/remote.d.ts +33 -1
  538. package/dist/providers/vcs/routing.d.ts +4 -2
  539. package/dist/providers/vcs/routing.js +6 -0
  540. package/dist/providers/vcs/types.d.ts +80 -3
  541. package/dist/quickstart/coding-seed.d.ts +21 -3
  542. package/dist/quickstart/coding-seed.js +283 -3
  543. package/dist/quickstart/images.d.ts +2 -0
  544. package/dist/quickstart/images.js +7 -1
  545. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  546. package/dist/quickstart/reviewer-prompt.js +6 -6
  547. package/dist/quickstart-images.json +1 -1
  548. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  549. package/dist/sandbox/brokered-fetch.js +37 -0
  550. package/dist/sandbox/generated/zod.bundle.js +62 -1
  551. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  552. package/dist/sandbox/host-functions.d.ts +35 -0
  553. package/dist/sandbox/host-functions.js +150 -91
  554. package/dist/sandbox/prelude.js +7 -1
  555. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  556. package/dist/sandbox/run-in-sandbox.js +28 -10
  557. package/dist/sandbox/safe-fetch.d.ts +2 -0
  558. package/dist/sandbox/safe-fetch.js +3 -1
  559. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  560. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  561. package/dist/sandbox/secret-broker.d.ts +34 -0
  562. package/dist/sandbox/secret-broker.js +161 -0
  563. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  564. package/dist/sandbox/user-tool.d.ts +14 -0
  565. package/dist/sandbox/user-tool.js +32 -0
  566. package/dist/sandbox/zod-params.d.ts +37 -5
  567. package/dist/sandbox/zod-params.js +181 -26
  568. package/dist/serve.js +25 -0
  569. package/dist/viewer/api-schema.d.ts +372 -2454
  570. package/dist/viewer/api-schema.js +29 -0
  571. package/dist/viewer/build-schemas.js +10 -3
  572. package/dist/viewer/event-bus.d.ts +6 -0
  573. package/dist/viewer/event-bus.js +16 -7
  574. package/dist/viewer/graph.d.ts +5 -2
  575. package/dist/viewer/graph.js +7 -2
  576. package/dist/viewer/http.d.ts +0 -1
  577. package/dist/viewer/http.js +2 -2
  578. package/dist/viewer/infra.js +25 -2
  579. package/dist/viewer/limits.d.ts +4 -0
  580. package/dist/viewer/limits.js +4 -0
  581. package/dist/viewer/openapi.d.ts +15 -0
  582. package/dist/viewer/openapi.js +170 -0
  583. package/dist/wardby-bin.js +10 -0
  584. package/docs/README.md +7 -0
  585. package/docs/agent-recipes.md +114 -27
  586. package/docs/architecture-runtime.md +16 -1
  587. package/docs/code-review-agents.md +689 -45
  588. package/docs/coding-agent-setup.md +602 -12
  589. package/docs/coding-packages.md +1037 -92
  590. package/docs/coding-services.md +30 -13
  591. package/docs/coding-worker-byo-images.md +218 -6
  592. package/docs/coding-worker-isolation.md +173 -44
  593. package/docs/getting-started-gke.md +332 -129
  594. package/docs/getting-started-identity-provider.md +31 -11
  595. package/docs/getting-started.md +14 -4
  596. package/docs/jira-agents.md +22 -9
  597. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  598. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  599. package/docs/knowledge/delegation-admission-slots.md +52 -0
  600. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  601. package/docs/knowledge/import-rename-target.md +52 -0
  602. package/docs/knowledge/index.md +57 -0
  603. package/docs/knowledge/log.md +9 -0
  604. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  605. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  606. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  607. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  608. package/docs/knowledge/overview-cli.md +74 -0
  609. package/docs/knowledge/overview-coding-proxy.md +72 -0
  610. package/docs/knowledge/overview-coding.md +72 -0
  611. package/docs/knowledge/overview-config.md +60 -0
  612. package/docs/knowledge/overview-core.md +72 -0
  613. package/docs/knowledge/overview-deploy.md +83 -0
  614. package/docs/knowledge/overview-mcp.md +61 -0
  615. package/docs/knowledge/overview-prisma.md +72 -0
  616. package/docs/knowledge/overview-providers.md +89 -0
  617. package/docs/knowledge/overview-sandbox.md +83 -0
  618. package/docs/knowledge/overview-surfaces.md +83 -0
  619. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  620. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  621. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  622. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  623. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  624. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  625. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  626. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  627. package/docs/knowledge/warm-input-publication.md +30 -0
  628. package/docs/knowledge/workspace-staging-failure.md +54 -0
  629. package/docs/knowledge.md +54 -14
  630. package/docs/native-sandbox.md +731 -0
  631. package/docs/observability.md +4 -0
  632. package/docs/release-verification.md +9 -0
  633. package/docs/security-deployment.md +146 -14
  634. package/docs/slack-notifications.md +268 -0
  635. package/docs/tool-secrets.md +284 -0
  636. package/docs/viewer-api.md +46 -5
  637. package/docs/viewer-api.openapi.yml +1404 -0
  638. package/help/admin-viewer.md +29 -3
  639. package/help/agent-recipes.md +27 -0
  640. package/help/architecture-agent.md +11 -6
  641. package/help/brokered-secrets.md +79 -0
  642. package/help/build-claude-code-image.md +131 -0
  643. package/help/build-worker-image.md +6 -7
  644. package/help/builder-agent.md +19 -6
  645. package/help/code-review-agents.md +243 -10
  646. package/help/coding-packages.md +156 -6
  647. package/help/cost-attribution.md +9 -5
  648. package/help/creating-agents.md +14 -1
  649. package/help/dependency-cache.md +143 -0
  650. package/help/deploy-gke.md +23 -9
  651. package/help/deployment-targets.md +25 -14
  652. package/help/errors/budget-exhausted.md +187 -0
  653. package/help/errors/budget-group-exhausted.md +5 -1
  654. package/help/errors/coding-provider-not-configured.md +2 -2
  655. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  656. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  657. package/help/errors/continuation-closed.md +9 -12
  658. package/help/errors/database-auth-invalid.md +28 -0
  659. package/help/errors/delegation-conflict.md +24 -0
  660. package/help/errors/file-list-truncated.md +45 -0
  661. package/help/errors/full-read-required.md +49 -0
  662. package/help/errors/github-account-not-allowed.md +29 -0
  663. package/help/errors/graph-incomplete.md +43 -0
  664. package/help/errors/graph-limit.md +43 -0
  665. package/help/errors/low-power-disabled.md +29 -0
  666. package/help/errors/low-power-scale-forbidden.md +35 -0
  667. package/help/errors/low-power-wake-timeout.md +30 -0
  668. package/help/errors/merge-conflict.md +49 -0
  669. package/help/errors/mobile-disabled.md +31 -0
  670. package/help/errors/native-sandbox-capacity.md +22 -0
  671. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  672. package/help/errors/native-sandbox-docker-failed.md +20 -0
  673. package/help/errors/native-sandbox-gateway-error.md +20 -0
  674. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  675. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  676. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  677. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  678. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  679. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  680. package/help/errors/native-sandbox-unavailable.md +19 -0
  681. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  682. package/help/errors/native-sandbox-worker-exited.md +21 -0
  683. package/help/errors/native-sandbox-worker-lost.md +20 -0
  684. package/help/errors/native-sandbox-worker-unready.md +22 -0
  685. package/help/errors/package-not-allowed-pending.md +52 -0
  686. package/help/errors/package-not-allowed.md +51 -0
  687. package/help/errors/package-refusals.md +43 -0
  688. package/help/errors/patch-cursor-malformed.md +31 -0
  689. package/help/errors/run-lost.md +39 -0
  690. package/help/errors/run-transcript-download.md +44 -0
  691. package/help/errors/secret-broker-body-invalid.md +26 -0
  692. package/help/errors/secret-broker-changed.md +20 -0
  693. package/help/errors/secret-broker-config-invalid.md +30 -0
  694. package/help/errors/secret-broker-conflict.md +27 -0
  695. package/help/errors/secret-broker-destination-denied.md +28 -0
  696. package/help/errors/secret-broker-value-invalid.md +28 -0
  697. package/help/errors/secret-brokered.md +24 -0
  698. package/help/errors/secret-in-value.md +69 -0
  699. package/help/errors/secret-not-brokered.md +25 -0
  700. package/help/errors/slack-auth-failed.md +48 -0
  701. package/help/errors/slack-channel-unreachable.md +39 -0
  702. package/help/errors/slack-not-configured.md +33 -0
  703. package/help/errors/target-merge.md +40 -0
  704. package/help/fix-merge-conflicts.md +73 -0
  705. package/help/getting-started.md +4 -5
  706. package/help/github-app-setup.md +132 -0
  707. package/help/github.md +40 -1
  708. package/help/identity-and-access.md +7 -1
  709. package/help/jira.md +23 -6
  710. package/help/knowledge.md +16 -7
  711. package/help/local-repositories.md +3 -4
  712. package/help/low-power-mode.md +131 -0
  713. package/help/merge-order-check.md +122 -0
  714. package/help/mobile-app.md +54 -0
  715. package/help/native-capabilities.md +29 -1
  716. package/help/native-sandbox.md +150 -0
  717. package/help/observability.md +8 -0
  718. package/help/operating-agents.md +5 -0
  719. package/help/package-audit-mode.md +91 -0
  720. package/help/related-pull-requests.md +80 -16
  721. package/help/repo-instructions-and-skills.md +91 -0
  722. package/help/resume-runs-locally.md +131 -0
  723. package/help/review-fix-rounds.md +43 -1
  724. package/help/sharing-agents.md +59 -0
  725. package/help/slack-notifications.md +76 -0
  726. package/help/status-comments.md +31 -0
  727. package/help/stop-run.md +58 -0
  728. package/help/troubleshooting/budgets.md +28 -0
  729. package/help/troubleshooting/coding-workers.md +99 -7
  730. package/package.json +27 -13
  731. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  732. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  733. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  734. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  735. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  736. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  737. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  738. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  739. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  740. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  741. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  742. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  743. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  744. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  745. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  746. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  747. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  748. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  749. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  750. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  751. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  752. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  753. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  754. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  755. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  756. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  757. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  758. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  759. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  760. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  761. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  762. package/prisma/schema.prisma +631 -146
  763. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -9,10 +9,22 @@
9
9
  * comment. Best effort throughout: nothing here throws.
10
10
  */
11
11
  import type { Prisma, PrismaClient, Run, RunStatus } from "#prisma";
12
+ import { type RegistryRefusalSummary } from "../coding/registry/report.js";
13
+ import { type PackageAuditMode, type PackageAuditSummary } from "../coding/registry/audit-mode.js";
12
14
  import type { CodeReviewHost, ReviewHostProvider, ReviewHostRegistry } from "../providers/review-host/types.js";
15
+ /** The most a GitHub follow-up comment holds, header and cut note included (GitHub's limit is 65,536). */
16
+ export declare const GITHUB_REPLY_MAX_CHARS = 60000;
17
+ /** The most follow-up comments a full reply is posted as; the rest is cut, and stays on the run. */
18
+ export declare const REPLY_MAX_PARTS = 4;
19
+ /**
20
+ * The most a Jira follow-up comment holds, header and cut note included. Jira Cloud's limit is 32,767
21
+ * characters, but it may apply to the serialized ADF body markdownToAdf produces rather than to this
22
+ * Markdown (unverified), and ADF's JSON is longer than the text; so keep a wide margin.
23
+ */
24
+ export declare const JIRA_REPLY_MAX_CHARS = 15000;
13
25
  /** The run statuses a run never leaves. */
14
26
  export declare const TERMINAL_RUN_STATUSES: readonly RunStatus[];
15
- export type HostStatusDb = Pick<PrismaClient, "runHostStatus" | "run">;
27
+ export type HostStatusDb = Pick<PrismaClient, "runHostStatus" | "run" | "runBudgetEvent" | "registryFetch" | "registryAuditRecord" | "issuePullRequest" | "codingRun">;
16
28
  export type FinishedRun = Pick<Run, "id" | "status" | "finalText">;
17
29
  /** The parts of a CodingRun result this comment uses. */
18
30
  export interface PullRequestOutcome {
@@ -48,27 +60,96 @@ export declare function mentionStatusRow(provider: ReviewHostProvider, event: {
48
60
  replyToReviewCommentId?: string;
49
61
  }, runId: string): Prisma.RunHostStatusUncheckedCreateInput;
50
62
  export declare function pullRequestOutcome(result: unknown): PullRequestOutcome | null;
63
+ /**
64
+ * The reply to post in full as follow-up comments, or null when the ordinary quote applies: only for a
65
+ * run that succeeded with no pull request and no failed sub-run, whose trimmed reply is longer than the
66
+ * status comment's quote holds.
67
+ */
68
+ export declare function fullReplyOf(run: FinishedRun, pullRequests: PullRequestOutcome[], failedChildren: FailedChild[]): string | null;
69
+ /**
70
+ * Numbered comment bodies for a full reply: "**Reply, part i of n**" then the part, the last ending with
71
+ * the cut note when the reply did not fit in `maxParts`. Each body, header and note included, is at most
72
+ * `maxChars`. @-mentions are defused (splitReply).
73
+ */
74
+ export declare function fullReplyComments(reply: string, opts: {
75
+ maxChars: number;
76
+ maxParts: number;
77
+ }): string[];
78
+ type RefusalOutcome = {
79
+ pullRequests: readonly PullRequestOutcome[];
80
+ failedChildren: readonly FailedChild[];
81
+ packageRefusals?: readonly RegistryRefusalSummary[];
82
+ noChanges?: boolean;
83
+ };
84
+ /**
85
+ * The refusals that can block the run: all of them when a coding sub-run failed, otherwise all but
86
+ * listing-only ones, which the installer may only have looked at (see LISTING_REFUSAL_FILENAME).
87
+ */
88
+ export declare function blockingRefusals(outcome: Omit<RefusalOutcome, "noChanges">): RegistryRefusalSummary[];
89
+ /**
90
+ * Whether package refusals blocked the run: it succeeded, but nothing reached a pull request, a coding
91
+ * sub-run made no changes or failed, and packages were refused (blockingRefusals). The GitHub and Jira
92
+ * status comments and the Slack `run_blocked` event all use it, so they always agree.
93
+ */
94
+ export declare function isBlockedByRefusals(run: Pick<FinishedRun, "status">, outcome: RefusalOutcome): boolean;
51
95
  export declare function outcomeBody(run: FinishedRun, repository: string, pullRequests: PullRequestOutcome[], failedChildren?: FailedChild[], opts?: {
96
+ packageRefusals?: RegistryRefusalSummary[];
97
+ noChanges?: boolean;
52
98
  budgetSentence?: string;
99
+ /** The run came from an issue (GitHub or Jira): a budget-stopped draft can be continued from the issue too. */
100
+ fromIssue?: boolean;
53
101
  noPullRequestText?: string;
54
102
  /** The agent's reply IS the answer (no separate reply comment): shown as written, not quoted. */
55
103
  replyAsAnswer?: boolean;
104
+ /**
105
+ * The caller posts the full reply as follow-up comments when fullReplyOf is not null (see
106
+ * completeHostStatus): the ✅ no-pull-request body then points to them instead of quoting the reply.
107
+ */
108
+ fullReplyFollows?: boolean;
109
+ /** The status comment is in a review thread, so the follow-ups land in the conversation instead. */
110
+ statusInThread?: boolean;
111
+ /** Package audit mode on any coding sub-run: a short block above the run line, whatever the outcome. */
112
+ packageAudit?: {
113
+ mode: PackageAuditMode;
114
+ summary: PackageAuditSummary;
115
+ };
56
116
  }): string;
117
+ /** Package audit mode on a run's coding sub-runs: the strongest mode, and what it recorded across them. */
118
+ export type PackageAuditOutcome = {
119
+ mode: PackageAuditMode;
120
+ summary: PackageAuditSummary;
121
+ };
122
+ /** A run's package audit alone, for a run whose other outcome is not read (one that did not succeed). */
123
+ export declare function collectPackageAudit(db: Pick<PrismaClient, "run" | "registryAuditRecord">, runId: string): Promise<PackageAuditOutcome | undefined>;
57
124
  /** What collectRunOutcome reads: a run's children and, when out of budget, its budget facts. */
58
- export type RunOutcomeDb = Pick<PrismaClient, "run">;
125
+ export type RunOutcomeDb = Pick<PrismaClient, "run" | "runBudgetEvent" | "registryFetch" | "registryAuditRecord">;
59
126
  /** The parts of a finished run's outcome a status comment reports; shared by GitHub and Jira status comments. */
60
127
  export declare function collectRunOutcome(db: RunOutcomeDb, run: FinishedRun): Promise<{
61
128
  pullRequests: PullRequestOutcome[];
62
129
  failedChildren: FailedChild[];
130
+ packageRefusals: RegistryRefusalSummary[];
131
+ noChanges: boolean;
63
132
  budgetSentence?: string;
133
+ packageAudit?: PackageAuditOutcome;
64
134
  }>;
135
+ /**
136
+ * Whether a mention run's stored task is a mention on GitHub issue `number`
137
+ * of `repository`, not on a pull request. Read from the task's header block
138
+ * (mentionTaskText's "[GitHub issue #n…]" then "Repository: …"), which only
139
+ * wardby writes: the first section that opens with "[GitHub " is that header
140
+ * (any continuation hints before it are wardby's too), and everything a
141
+ * person wrote comes after it, so a comment cannot pass for an issue header.
142
+ * A review fix round's header names a PR.
143
+ */
144
+ export declare function isIssueMentionTask(taskOverride: string | null, repository: string, number: number): boolean;
65
145
  /**
66
146
  * Writes a finished run's outcome to its status comment and marks it
67
147
  * complete: edits the comment when it exists; when it does not yet, posts the
68
148
  * outcome as a new comment only if `postIfMissing` (the reconciler, well after
69
149
  * the run ended), and otherwise leaves the row for postMentionStatus, which
70
150
  * is about to post it. A failed host call leaves the row open for the
71
- * reconciler to retry.
151
+ * reconciler to retry. The row is then claimed (completed) in one step, and
152
+ * only the claiming call posts a full reply's follow-up comments.
72
153
  */
73
154
  export declare function completeHostStatus(db: HostStatusDb, run: FinishedRun, hosts: ReviewHostRegistry | undefined, opts?: {
74
155
  postIfMissing?: boolean;
@@ -81,3 +162,4 @@ export declare function completeHostStatus(db: HostStatusDb, run: FinishedRun, h
81
162
  * already complete. Never throws.
82
163
  */
83
164
  export declare function postMentionStatus(db: HostStatusDb, host: CodeReviewHost, runId: string, hosts: ReviewHostRegistry | undefined, heading?: string): Promise<void>;
165
+ export {};
@@ -1,14 +1,37 @@
1
+ import { summarizeRegistryFetches, warningRefusals } from "../coding/registry/report.js";
2
+ import { packageRefusalWording } from "../coding/registry/refusal-wording.js";
3
+ import { isPackageAuditMode, packageAuditWording, summarizePackageAudit, } from "../coding/registry/audit-mode.js";
1
4
  import { CODING_CODE_PROVIDER } from "../coding/protocol.js";
2
5
  import { storedServiceNames } from "../coding/services/catalog.js";
3
6
  import { SERVICE_UNREADY_CATEGORY, serviceRefusalSentence, serviceUnreadySentence, } from "../coding/services/wording.js";
4
7
  import { PROTECTED_PATH_CATEGORY, PROTECTED_PATH_HOST_LINE } from "../coding/protected-path-wording.js";
5
- import { CONTINUATION_CLOSED_CATEGORY, CONTINUATION_CLOSED_HOST_LINE } from "../coding/continuation-wording.js";
8
+ import { budgetStoppedChangesSentence, CONTINUATION_CLOSED_CATEGORY, CONTINUATION_CLOSED_HOST_LINE, } from "../coding/continuation-wording.js";
9
+ import { escapeHtmlComments } from "../providers/review-host/review-format.js";
6
10
  import { loadBudgetSentence } from "./budget-wording.js";
11
+ import { continuedForAnotherIssue, githubIssueKey, recordIssuePullRequests } from "./issue-bridge.js";
7
12
  import { logger } from "./logger.js";
8
13
  import { providerClassOfCategory, providerSentence } from "./provider-wording.js";
14
+ import { defuseMentions, splitReply } from "./reply-parts.js";
15
+ import { splitTaskOverride } from "./untrusted-content.js";
9
16
  const log = logger.child({ module: "host-status" });
10
- /** Keeps the edited comment readable; the full reply stays on the run. */
17
+ /** Keeps the edited comment readable; a longer reply goes out in full as follow-up comments (fullReplyOf). */
11
18
  const MAX_REPLY_CHARS = 2000;
19
+ /** The most a GitHub follow-up comment holds, header and cut note included (GitHub's limit is 65,536). */
20
+ export const GITHUB_REPLY_MAX_CHARS = 60_000;
21
+ /** The most follow-up comments a full reply is posted as; the rest is cut, and stays on the run. */
22
+ export const REPLY_MAX_PARTS = 4;
23
+ /**
24
+ * The most a Jira follow-up comment holds, header and cut note included. Jira Cloud's limit is 32,767
25
+ * characters, but it may apply to the serialized ADF body markdownToAdf produces rather than to this
26
+ * Markdown (unverified), and ADF's JSON is longer than the text; so keep a wide margin.
27
+ */
28
+ export const JIRA_REPLY_MAX_CHARS = 15_000;
29
+ /** The status comment's line when the full reply follows. */
30
+ const FULL_REPLY_FOLLOWS = "The full reply follows in the next comment(s).";
31
+ /** The same, for a status in a review thread: the follow-ups go to the pull request's conversation. */
32
+ const FULL_REPLY_FOLLOWS_IN_CONVERSATION = "The full reply follows in this pull request's conversation.";
33
+ /** Ends the last follow-up when the reply did not fit in REPLY_MAX_PARTS comments. */
34
+ const REPLY_CUT_NOTE = "\n\n---\n\n*The rest of the reply was cut: it was too long to post in full. The full text is on the run (`get_run` → `finalText`).*";
12
35
  /** The run statuses a run never leaves. */
13
36
  export const TERMINAL_RUN_STATUSES = [
14
37
  "succeeded",
@@ -63,21 +86,82 @@ function failedCheckCount(tests) {
63
86
  /** The agent's reply as a quote, cut to MAX_REPLY_CHARS, with @-mentions defused so nobody is pinged. */
64
87
  const cutReply = (text) => text.length > MAX_REPLY_CHARS ? `${text.slice(0, MAX_REPLY_CHARS)}…` : text;
65
88
  function quoteReply(text) {
66
- return cutReply(text)
67
- .replace(/@(?=[\w-])/g, "@​")
89
+ return defuseMentions(cutReply(text))
68
90
  .split("\n")
69
91
  .map((line) => `> ${line}`)
70
92
  .join("\n");
71
93
  }
94
+ /**
95
+ * The reply to post in full as follow-up comments, or null when the ordinary quote applies: only for a
96
+ * run that succeeded with no pull request and no failed sub-run, whose trimmed reply is longer than the
97
+ * status comment's quote holds.
98
+ */
99
+ export function fullReplyOf(run, pullRequests, failedChildren) {
100
+ if (run.status !== "succeeded" || pullRequests.length > 0 || failedChildren.length > 0)
101
+ return null;
102
+ const reply = run.finalText?.trim();
103
+ return reply && reply.length > MAX_REPLY_CHARS ? reply : null;
104
+ }
105
+ const partHeader = (i, n) => `**Reply, part ${i} of ${n}**\n\n`;
106
+ /**
107
+ * Numbered comment bodies for a full reply: "**Reply, part i of n**" then the part, the last ending with
108
+ * the cut note when the reply did not fit in `maxParts`. Each body, header and note included, is at most
109
+ * `maxChars`. @-mentions are defused (splitReply).
110
+ */
111
+ export function fullReplyComments(reply, opts) {
112
+ const maxParts = Math.max(1, Math.floor(opts.maxParts));
113
+ const reserve = partHeader(maxParts, maxParts).length + REPLY_CUT_NOTE.length;
114
+ const { parts, truncated } = splitReply(reply, { maxChars: opts.maxChars - reserve, maxParts });
115
+ return parts.map((part, i) => `${partHeader(i + 1, parts.length)}${part}${truncated && i === parts.length - 1 ? REPLY_CUT_NOTE : ""}`);
116
+ }
117
+ /**
118
+ * The refusals that can block the run: all of them when a coding sub-run failed, otherwise all but
119
+ * listing-only ones, which the installer may only have looked at (see LISTING_REFUSAL_FILENAME).
120
+ */
121
+ export function blockingRefusals(outcome) {
122
+ const refusals = outcome.packageRefusals ?? [];
123
+ return outcome.failedChildren.length > 0 ? [...refusals] : warningRefusals(refusals);
124
+ }
125
+ /**
126
+ * Whether package refusals blocked the run: it succeeded, but nothing reached a pull request, a coding
127
+ * sub-run made no changes or failed, and packages were refused (blockingRefusals). The GitHub and Jira
128
+ * status comments and the Slack `run_blocked` event all use it, so they always agree.
129
+ */
130
+ export function isBlockedByRefusals(run, outcome) {
131
+ return (run.status === "succeeded" &&
132
+ outcome.pullRequests.length === 0 &&
133
+ (outcome.noChanges === true || outcome.failedChildren.length > 0) &&
134
+ blockingRefusals(outcome).length > 0);
135
+ }
72
136
  export function outcomeBody(run, repository, pullRequests, failedChildren = [], opts = {}) {
73
- const links = pullRequests.map((pr) => {
74
- const ref = pr.repository.toLowerCase() === repository.toLowerCase()
75
- ? `#${pr.pullRequestNumber}`
76
- : `${pr.repository}#${pr.pullRequestNumber}`;
77
- return pr.outcome === "pull_request_opened" ? `Opened ${ref}` : `Pushed changes to ${ref}`;
78
- });
137
+ const refOf = (pr) => pr.repository.toLowerCase() === repository.toLowerCase()
138
+ ? `#${pr.pullRequestNumber}`
139
+ : `${pr.repository}#${pr.pullRequestNumber}`;
140
+ const links = pullRequests.map((pr) => pr.outcome === "pull_request_opened" ? `Opened ${refOf(pr)}` : `Pushed changes to ${refOf(pr)}`);
79
141
  const partial = links.length > 0 ? `\n\n${links.join(", ")}.` : "";
80
- const footer = runLine(run.id);
142
+ const refusals = opts.packageRefusals ?? [];
143
+ const blocked = isBlockedByRefusals(run, {
144
+ pullRequests,
145
+ failedChildren,
146
+ packageRefusals: refusals,
147
+ noChanges: opts.noChanges,
148
+ });
149
+ const blockedBy = blocked ? blockingRefusals({ pullRequests, failedChildren, packageRefusals: refusals }) : [];
150
+ // The ⚠️ line: on a no-changes run it keeps listing-only refusals (see LISTING_REFUSAL_FILENAME), and
151
+ // when blocked it holds only those the ⛔ list leaves out.
152
+ const noChangesRun = opts.noChanges === true && pullRequests.length === 0;
153
+ const warned = blocked
154
+ ? refusals.filter((refusal) => !blockedBy.includes(refusal))
155
+ : noChangesRun
156
+ ? refusals
157
+ : warningRefusals(refusals);
158
+ const warning = (links.length > 0 || run.status === "succeeded") && warned.length > 0
159
+ ? packageRefusalWording(warned, { blocked: false })
160
+ : "";
161
+ const audit = opts.packageAudit ? packageAuditWording(opts.packageAudit.mode, opts.packageAudit.summary) : "";
162
+ const footer = warning + (warning ? "\n\n" : "") + audit + (audit ? "\n\n" : "") + runLine(run.id);
163
+ if (blocked)
164
+ return packageRefusalWording(blockedBy) + "\n\n" + footer;
81
165
  if (run.status === "lost") {
82
166
  return `❌ Interrupted before it finished (for example, wardby restarted). Repeat your request to retry.${partial}\n\n${footer}`;
83
167
  }
@@ -93,7 +177,11 @@ export function outcomeBody(run, repository, pullRequests, failedChildren = [],
93
177
  const quoted = reply ? `\n\n${quoteReply(reply)}` : "";
94
178
  if (failedChildren.length > 0) {
95
179
  // The agent itself finished, but the work it handed off did not.
96
- const outOfBudget = failedChildren.filter((c) => c.status === "budget_exhausted");
180
+ // A sub-run stopped at its budget may still have pushed its changes so far (a draft to continue).
181
+ const keptBy = new Map(pullRequests.filter((pr) => pr.runId !== undefined).map((pr) => [pr.runId, pr]));
182
+ const keptOf = (c) => c.status === "budget_exhausted" ? keptBy.get(c.id) : undefined;
183
+ const kept = failedChildren.map(keptOf).filter((pr) => pr !== undefined);
184
+ const outOfBudget = failedChildren.filter((c) => c.status === "budget_exhausted" && !keptOf(c));
97
185
  const providerClassOf = (c) => c.status === "failed" ? providerClassOfCategory(c.failureCategory) : null;
98
186
  // A coding sub-run its services stopped: refused at dispatch, or a sidecar never became ready.
99
187
  const serviceSentenceOf = (c) => c.status === "refused"
@@ -116,7 +204,7 @@ export function outcomeBody(run, repository, pullRequests, failedChildren = [],
116
204
  serviceSentenceOf(c) === null &&
117
205
  !protectedPathOf(c) &&
118
206
  !continuationClosedOf(c));
119
- const lines = [];
207
+ const lines = kept.map((pr) => `A sub-run ran out of budget before finishing. ${budgetStoppedChangesSentence(refOf(pr), pr.outcome === "pull_request_opened", opts.fromIssue === true)}`);
120
208
  if (outOfBudget.length > 0) {
121
209
  lines.push(`A sub-run ran out of budget: ${outOfBudget.map((c) => `\`${c.id}\``).join(", ")}.`);
122
210
  }
@@ -135,7 +223,11 @@ export function outcomeBody(run, repository, pullRequests, failedChildren = [],
135
223
  if (other.length > 0) {
136
224
  lines.push(`A sub-run did not succeed: ${other.map((c) => `\`${c.id}\` (\`${c.status}\`)`).join(", ")}.`);
137
225
  }
138
- return `❌ ${lines.join(" ")}${partial}${quoted}\n\n${footer}`;
226
+ // The kept pull requests are named in their own lines.
227
+ const others = links.filter((_, i) => !kept.includes(pullRequests[i]));
228
+ const otherLinks = others.length > 0 ? `\n\n${others.join(", ")}.` : "";
229
+ const icon = kept.length === failedChildren.length ? "⚠️" : "❌";
230
+ return `${icon} ${lines.join(" ")}${otherLinks}${quoted}\n\n${footer}`;
139
231
  }
140
232
  const failedChecks = pullRequests.reduce((sum, pr) => sum + (pr.failedChecks ?? 0), 0);
141
233
  if (links.length > 0 && failedChecks > 0) {
@@ -144,10 +236,41 @@ export function outcomeBody(run, repository, pullRequests, failedChildren = [],
144
236
  }
145
237
  if (links.length > 0)
146
238
  return `✅ ${links.join(", ")}.\n\n${footer}`;
239
+ if (opts.fullReplyFollows && fullReplyOf(run, pullRequests, failedChildren) !== null) {
240
+ const follows = opts.statusInThread ? FULL_REPLY_FOLLOWS_IN_CONVERSATION : FULL_REPLY_FOLLOWS;
241
+ return opts.replyAsAnswer
242
+ ? `✅ ${follows}\n\n${footer}`
243
+ : `✅ Finished without opening a pull request. ${follows}\n\n${footer}`;
244
+ }
147
245
  if (opts.replyAsAnswer && reply)
148
246
  return `✅ ${cutReply(reply)}\n\n${footer}`;
149
247
  return `✅ ${opts.noPullRequestText ?? "Finished without opening a pull request."}${quoted}\n\n${footer}`;
150
248
  }
249
+ /** The package audit of these children (best effort, like the refusals: a read failure reports none). */
250
+ async function loadPackageAudit(db, children) {
251
+ const audited = children.filter((c) => isPackageAuditMode(c.codingRun?.packageAuditMode));
252
+ if (audited.length === 0)
253
+ return undefined;
254
+ try {
255
+ const rows = await db.registryAuditRecord.findMany({
256
+ where: { runId: { in: audited.map((c) => c.id) } },
257
+ orderBy: { createdAt: "asc" },
258
+ });
259
+ const mode = audited.some((c) => c.codingRun?.packageAuditMode === "full") ? "full" : "audit";
260
+ return { mode, summary: summarizePackageAudit(rows) };
261
+ }
262
+ catch {
263
+ return undefined;
264
+ }
265
+ }
266
+ /** A run's package audit alone, for a run whose other outcome is not read (one that did not succeed). */
267
+ export async function collectPackageAudit(db, runId) {
268
+ const children = await db.run.findMany({
269
+ where: { parentRunId: runId },
270
+ select: { id: true, codingRun: { select: { packageAuditMode: true } } },
271
+ });
272
+ return loadPackageAudit(db, children);
273
+ }
151
274
  /** The parts of a finished run's outcome a status comment reports; shared by GitHub and Jira status comments. */
152
275
  export async function collectRunOutcome(db, run) {
153
276
  const children = await db.run.findMany({
@@ -156,7 +279,7 @@ export async function collectRunOutcome(db, run) {
156
279
  id: true,
157
280
  status: true,
158
281
  error: true,
159
- codingRun: { select: { result: true, failureCategory: true, services: true } },
282
+ codingRun: { select: { result: true, failureCategory: true, services: true, packageAuditMode: true } },
160
283
  },
161
284
  orderBy: { startedAt: "asc" },
162
285
  });
@@ -175,10 +298,116 @@ export async function collectRunOutcome(db, run) {
175
298
  error: c.error ?? null,
176
299
  services: storedServiceNames(c.codingRun?.services),
177
300
  }));
301
+ let packageRefusals = [];
302
+ const codingIds = children.filter((c) => c.codingRun).map((c) => c.id);
303
+ if (codingIds.length > 0) {
304
+ try {
305
+ const fetches = await db.registryFetch.findMany({
306
+ where: { runId: { in: codingIds } },
307
+ select: {
308
+ ecosystem: true,
309
+ name: true,
310
+ version: true,
311
+ outcome: true,
312
+ reason: true,
313
+ sizeBytes: true,
314
+ filename: true,
315
+ runId: true,
316
+ },
317
+ orderBy: { createdAt: "asc" },
318
+ });
319
+ packageRefusals = summarizeRegistryFetches(fetches).packageRefusals;
320
+ }
321
+ catch {
322
+ // Registry reporting is best effort; keep the existing status on read failure.
323
+ }
324
+ }
325
+ const packageAudit = await loadPackageAudit(db, children);
178
326
  const budgetSentence = run.status === "budget_exhausted" || run.status === "refused"
179
327
  ? await loadBudgetSentence(db, run.id, run.status)
180
328
  : undefined;
181
- return { pullRequests, failedChildren, ...(budgetSentence ? { budgetSentence } : {}) };
329
+ const noChanges = children.some((c) => {
330
+ const result = c.codingRun?.result;
331
+ return result && typeof result === "object" && !Array.isArray(result) && result.outcome === "no_changes";
332
+ });
333
+ return {
334
+ pullRequests,
335
+ failedChildren,
336
+ packageRefusals,
337
+ noChanges,
338
+ ...(budgetSentence ? { budgetSentence } : {}),
339
+ ...(packageAudit ? { packageAudit } : {}),
340
+ };
341
+ }
342
+ /**
343
+ * Whether a mention run's stored task is a mention on GitHub issue `number`
344
+ * of `repository`, not on a pull request. Read from the task's header block
345
+ * (mentionTaskText's "[GitHub issue #n…]" then "Repository: …"), which only
346
+ * wardby writes: the first section that opens with "[GitHub " is that header
347
+ * (any continuation hints before it are wardby's too), and everything a
348
+ * person wrote comes after it, so a comment cannot pass for an issue header.
349
+ * A review fix round's header names a PR.
350
+ */
351
+ export function isIssueMentionTask(taskOverride, repository, number) {
352
+ if (!taskOverride)
353
+ return false;
354
+ const header = splitTaskOverride(taskOverride)
355
+ .task.split("\n\n")
356
+ .find((section) => section.startsWith("[GitHub "));
357
+ if (!header)
358
+ return false;
359
+ const [first = "", second] = header.split("\n");
360
+ const opener = `[GitHub issue #${number}`;
361
+ return (first === `${opener}]` || first.startsWith(`${opener}: `)) && second === `Repository: ${repository}`;
362
+ }
363
+ /** Whether the run was started by a mention on a GitHub issue (not a pull request). Never throws. */
364
+ async function runCameFromGitHubIssue(db, status, runId) {
365
+ if (status.provider !== "github")
366
+ return false;
367
+ try {
368
+ const run = await db.run.findUnique({ where: { id: runId }, select: { taskOverride: true } });
369
+ return !!run && isIssueMentionTask(run.taskOverride, status.repository, status.number);
370
+ }
371
+ catch (err) {
372
+ log.warn({ err, runId }, "could not tell whether the run came from an issue");
373
+ return false;
374
+ }
375
+ }
376
+ /**
377
+ * A GitHub issue's run records the pull requests its coding sub-runs opened
378
+ * or continued, exactly as a Jira issue's does (recordIssuePullRequests, key
379
+ * githubIssueKey): a later mention on the issue continues them. Only for a
380
+ * mention on an issue (isIssueMentionTask), never on a pull request; a pull
381
+ * request continued from another tracked issue's run stays that issue's.
382
+ * Safe to repeat (a retried completion adds no row). Never throws.
383
+ */
384
+ async function recordGitHubIssuePullRequests(db, status, runId, pullRequests) {
385
+ if (status.provider !== "github")
386
+ return;
387
+ const recordable = pullRequests.filter((pr) => !!pr.pullRequestUrl && !!pr.runId);
388
+ if (recordable.length === 0)
389
+ return;
390
+ try {
391
+ const run = await db.run.findUnique({ where: { id: runId }, select: { agentId: true, taskOverride: true } });
392
+ if (!run || !isIssueMentionTask(run.taskOverride, status.repository, status.number))
393
+ return;
394
+ const issue = { provider: "github", key: githubIssueKey(status.repository, status.number) };
395
+ const foreign = await continuedForAnotherIssue(db, recordable.map((pr) => pr.runId), issue);
396
+ await recordIssuePullRequests(db, issue, recordable
397
+ .filter((pr) => !foreign.has(pr.runId))
398
+ .map((pr) => ({
399
+ codeProvider: pr.codeProvider,
400
+ repository: pr.repository,
401
+ number: pr.pullRequestNumber,
402
+ url: pr.pullRequestUrl,
403
+ agentId: run.agentId,
404
+ openedByRunId: pr.runId,
405
+ outcome: pr.outcome,
406
+ })));
407
+ }
408
+ catch (err) {
409
+ log.warn({ err, runId }, "could not record the GitHub issue's pull requests");
410
+ }
182
411
  }
183
412
  /**
184
413
  * Writes a finished run's outcome to its status comment and marks it
@@ -186,7 +415,8 @@ export async function collectRunOutcome(db, run) {
186
415
  * outcome as a new comment only if `postIfMissing` (the reconciler, well after
187
416
  * the run ended), and otherwise leaves the row for postMentionStatus, which
188
417
  * is about to post it. A failed host call leaves the row open for the
189
- * reconciler to retry.
418
+ * reconciler to retry. The row is then claimed (completed) in one step, and
419
+ * only the claiming call posts a full reply's follow-up comments.
190
420
  */
191
421
  export async function completeHostStatus(db, run, hosts, opts = {}) {
192
422
  if (!hosts)
@@ -200,8 +430,23 @@ export async function completeHostStatus(db, run, hosts, opts = {}) {
200
430
  const host = hosts[status.provider];
201
431
  if (!host)
202
432
  return;
203
- const { pullRequests, failedChildren, budgetSentence } = await collectRunOutcome(db, run);
204
- const body = outcomeBody(run, status.repository, pullRequests, failedChildren, { budgetSentence });
433
+ const { pullRequests, failedChildren, budgetSentence, packageRefusals, noChanges, packageAudit } = await collectRunOutcome(db, run);
434
+ await recordGitHubIssuePullRequests(db, status, run.id, pullRequests);
435
+ // A blocked status is built from the refusals alone, so the agent's reply is not posted after it.
436
+ const fullReply = isBlockedByRefusals(run, { pullRequests, failedChildren, packageRefusals, noChanges })
437
+ ? null
438
+ : fullReplyOf(run, pullRequests, failedChildren);
439
+ const body = outcomeBody(run, status.repository, pullRequests, failedChildren, {
440
+ budgetSentence,
441
+ fromIssue: failedChildren.some((c) => c.status === "budget_exhausted")
442
+ ? await runCameFromGitHubIssue(db, status, run.id)
443
+ : false,
444
+ packageRefusals,
445
+ packageAudit,
446
+ noChanges,
447
+ fullReplyFollows: true,
448
+ statusInThread: status.commentKind === "inline",
449
+ });
205
450
  let commentId = status.commentId;
206
451
  if (commentId) {
207
452
  await host.editComment(status.repository, {
@@ -217,12 +462,45 @@ export async function completeHostStatus(db, run, hosts, opts = {}) {
217
462
  ...(status.replyToReviewCommentId ? { replyToReviewCommentId: status.replyToReviewCommentId } : {}),
218
463
  })).id;
219
464
  }
220
- await db.runHostStatus.update({ where: { runId: run.id }, data: { commentId, completedAt: new Date() } });
465
+ // Claims the row in one step, saving a posted comment's id at once so a retry edits it instead of
466
+ // posting a second one. Only the completion that claims it posts the full reply, so two racing
467
+ // completions (the run's own and the reconciler's) never post it twice.
468
+ const claimed = await db.runHostStatus.updateMany({
469
+ where: { runId: run.id, completedAt: null },
470
+ data: { commentId, completedAt: new Date() },
471
+ });
472
+ if (claimed.count !== 1) {
473
+ log.warn({ runId: run.id }, "the run's status comment was completed meanwhile; leaving any full reply to that completion");
474
+ return;
475
+ }
476
+ if (fullReply !== null)
477
+ await postFullReply(host, status, run.id, fullReply);
221
478
  }
222
479
  catch (err) {
223
480
  log.warn({ err, runId: run.id }, "could not complete the run's status comment");
224
481
  }
225
482
  }
483
+ /**
484
+ * Posts the full reply's parts in order, each at most once: the status comment already points to them,
485
+ * so a failed part is logged and the rest skipped (a gap would misnumber the reply), and the row is still
486
+ * completed. The full text stays on the run (`get_run` → `finalText`). Never throws.
487
+ */
488
+ async function postFullReply(host, status, runId, reply) {
489
+ // Escaped before it is split, so each part stays under the cap as posted (comment() escapes again, a no-op).
490
+ const bodies = fullReplyComments(escapeHtmlComments(reply), {
491
+ maxChars: GITHUB_REPLY_MAX_CHARS,
492
+ maxParts: REPLY_MAX_PARTS,
493
+ });
494
+ for (const [i, body] of bodies.entries()) {
495
+ try {
496
+ await host.comment(status.repository, { number: status.number, body });
497
+ }
498
+ catch (err) {
499
+ log.warn({ err, runId, part: i + 1, parts: bodies.length }, "could not post a part of the run's full reply; the rest is skipped, the full text stays on the run");
500
+ return;
501
+ }
502
+ }
503
+ }
226
504
  /**
227
505
  * Posts the "working on it" comment for a mention run whose status row was
228
506
  * written at dispatch, and records the comment on the row. When the run
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Links a run's pull requests to the issue that started it: records each
3
- * issue/PR pair, puts a web link on the issue, and applies the link's
4
- * configured status move. Provider-neutral: a code host is only ever
5
- * { provider, repository, number }. The issue key comes from the run tree
6
- * (RunIssueStatus), never from model output. The status move is a control-plane
3
+ * issue/PR pair (recordIssuePullRequests, the same for a Jira issue and a
4
+ * GitHub issue), and for a tracker issue puts a web link on the issue and
5
+ * applies the link's configured status move. Provider-neutral: a code host is
6
+ * only ever { provider, repository, number }. The issue key comes from the run
7
+ * tree (RunIssueStatus, or a GitHub mention's RunHostStatus), never from model
8
+ * output. The status move is a control-plane
7
9
  * action (not gated by allowedTransitions). Nothing here throws, except
8
10
  * handlePullRequestClosed's lookup before it has claimed anything (so the
9
11
  * webhook delivery is rolled back and redelivered).
@@ -29,6 +31,47 @@ export interface RecordPullRequestsInput {
29
31
  pullRequests: BridgedPullRequest[];
30
32
  }
31
33
  export declare const pullRequestGlobalId: (pr: Pick<BridgedPullRequest, "codeProvider" | "repository" | "number">) => string;
34
+ /** The issue side of an IssuePullRequest row: { provider: "jira", key: "PROJ-7" } or githubIssueKey's. */
35
+ export interface RecordedIssue {
36
+ provider: string;
37
+ key: string;
38
+ }
39
+ /** One pull request to record against an issue. */
40
+ export interface IssuePullRequestRecord {
41
+ codeProvider: string;
42
+ repository: string;
43
+ number: number;
44
+ url: string;
45
+ /** The issue-linked agent whose run tree opened it. */
46
+ agentId: string;
47
+ /** The coding run that opened it (the continuePriorRun target for follow-ups). */
48
+ openedByRunId: string;
49
+ /** What the run did to it: only a newly recorded opened pull request notifies (pr_opened). */
50
+ outcome: "pull_request_opened" | "pull_request_updated";
51
+ }
52
+ /** A GitHub issue's IssuePullRequest key: "<owner>/<repo>#<number>", the repository normalised. */
53
+ export declare function githubIssueKey(repository: string, number: number): string;
54
+ /**
55
+ * Records the pull requests a run opened or continued for an issue, the same
56
+ * for every issue provider (a Jira issue, a GitHub issue): one IssuePullRequest
57
+ * row per issue/PR pair, state "open", never duplicated or overwritten (a
58
+ * merged or closed pair stays so; an open one gets its url refreshed), and a
59
+ * pr_opened notification for each newly recorded opened pull request.
60
+ * handlePullRequestClosed settles the rows. A GitHub issue's key is always
61
+ * githubIssueKey's, so any lookup of its rows must build the key the same way.
62
+ * Safe to repeat; never throws.
63
+ */
64
+ export declare function recordIssuePullRequests(db: IssueBridgeDb, issue: RecordedIssue, prs: readonly IssuePullRequestRecord[]): Promise<void>;
65
+ /**
66
+ * The coding runs (of `runIds`) that continued a pull request opened for a
67
+ * different issue: their PR belongs to that issue, not this one. A
68
+ * continuation is foreign when its root coding run was dispatched for another
69
+ * tracked issue (CodingRun.issueKey), or when that root opened a pull request
70
+ * recorded for a different issue of any provider (IssuePullRequest, which a
71
+ * GitHub issue's runs also write). A continued PR with no issue, or this same
72
+ * issue, is fine.
73
+ */
74
+ export declare function continuedForAnotherIssue(db: Pick<PrismaClient, "codingRun" | "issuePullRequest">, runIds: string[], issue: RecordedIssue): Promise<Set<string>>;
32
75
  /**
33
76
  * Returns sentences for the outcome comment (a refused status move); empty
34
77
  * when there is nothing to say. Safe to repeat (a retried completion): each
@@ -48,8 +91,9 @@ export interface ClosedPullRequest {
48
91
  }
49
92
  /**
50
93
  * A pull request wardby recorded against an issue was merged or closed: marks
51
- * each still-open pair, and, where the agent's link to the issue's project is
52
- * still write, comments on the issue (and on merge resolves the web link and
94
+ * each still-open pair (every issue provider, configured tracker or not),
95
+ * and, for an issue in a configured tracker where the agent's link to the
96
+ * issue's project is still write, comments on the issue (and on merge resolves the web link and
53
97
  * applies the link's onPullRequestMerged move). Only rows wardby wrote are
54
98
  * touched, matched by the host's own identity for the PR — nothing from the
55
99
  * PR's text. The row is claimed first (open → merged/closed), so a duplicate