@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
@@ -1,32 +1,40 @@
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).
10
12
  */
11
13
  import { Prisma } from "#prisma";
12
14
  import { projectOf, } from "../providers/issue-tracker/types.js";
15
+ import { normalizeGitHubRepository } from "../coding/protocol.js";
13
16
  import { logger } from "./logger.js";
17
+ import { dedupeKeys, emitWorkflowEvent } from "./workflow-events.js";
14
18
  const log = logger.child({ module: "issue-bridge" });
15
19
  export const pullRequestGlobalId = (pr) => `wardby:pr:${pr.codeProvider}:${pr.repository}#${pr.number}`;
20
+ /** A GitHub issue's IssuePullRequest key: "<owner>/<repo>#<number>", the repository normalised. */
21
+ export function githubIssueKey(repository, number) {
22
+ return `${normalizeGitHubRepository(repository)}#${number}`;
23
+ }
16
24
  /**
17
25
  * Makes sure the issue/PR pair has a row, without ever overwriting one: a new
18
26
  * row is "created"; an existing open one gets its url refreshed ("open"); a
19
27
  * merged or closed one is left alone ("settled"). A lost create race (P2002)
20
28
  * reads back the winner's row. "unknown" when the store could not be read.
21
29
  */
22
- async function ensurePair(db, input, pr) {
30
+ async function ensurePair(db, issue, pr) {
23
31
  const where = {
24
32
  codeProvider_repository_number_issueProvider_issueKey: {
25
33
  codeProvider: pr.codeProvider,
26
34
  repository: pr.repository,
27
35
  number: pr.number,
28
- issueProvider: input.issueProvider,
29
- issueKey: input.issueKey,
36
+ issueProvider: issue.provider,
37
+ issueKey: issue.key,
30
38
  },
31
39
  };
32
40
  try {
@@ -35,13 +43,13 @@ async function ensurePair(db, input, pr) {
35
43
  try {
36
44
  await db.issuePullRequest.create({
37
45
  data: {
38
- issueProvider: input.issueProvider,
39
- issueKey: input.issueKey,
46
+ issueProvider: issue.provider,
47
+ issueKey: issue.key,
40
48
  codeProvider: pr.codeProvider,
41
49
  repository: pr.repository,
42
50
  number: pr.number,
43
51
  url: pr.url,
44
- agentId: input.agentId,
52
+ agentId: pr.agentId,
45
53
  openedByRunId: pr.openedByRunId,
46
54
  },
47
55
  });
@@ -61,10 +69,98 @@ async function ensurePair(db, input, pr) {
61
69
  return "open";
62
70
  }
63
71
  catch (err) {
64
- log.warn({ err, issueKey: input.issueKey, repository: pr.repository, number: pr.number }, "could not record the issue/PR pair");
72
+ log.warn({ err, issueKey: issue.key, repository: pr.repository, number: pr.number }, "could not record the issue/PR pair");
65
73
  return "unknown";
66
74
  }
67
75
  }
76
+ /** Records each pair (ensurePair), in order; each state lines up with its pull request. Never throws. */
77
+ async function recordPairs(db, issue, prs) {
78
+ const states = [];
79
+ for (const pr of prs)
80
+ states.push(await ensurePair(db, issue, pr));
81
+ return states;
82
+ }
83
+ /**
84
+ * Notifies pr_opened for each pull request this call newly recorded as opened
85
+ * (`states` lines up with `prs`), so a retried completion does not notify
86
+ * twice. One message and dedupe key for every issue provider. Never throws.
87
+ */
88
+ async function emitNewlyOpened(issue, prs, states, movedTo) {
89
+ for (const [i, pr] of prs.entries()) {
90
+ if (states[i] !== "created" || pr.outcome !== "pull_request_opened")
91
+ continue;
92
+ await emitWorkflowEvent({
93
+ dedupeKey: dedupeKeys.prOpened(pr.codeProvider, pr.repository, pr.number),
94
+ runId: pr.openedByRunId,
95
+ agentId: pr.agentId,
96
+ workItem: { provider: issue.provider, key: issue.key },
97
+ pullRequest: { codeProvider: pr.codeProvider, repository: pr.repository, number: pr.number },
98
+ payload: { kind: "pr_opened", prLabel: `${pr.repository}#${pr.number}`, prUrl: pr.url, movedTo },
99
+ });
100
+ }
101
+ }
102
+ /**
103
+ * Records the pull requests a run opened or continued for an issue, the same
104
+ * for every issue provider (a Jira issue, a GitHub issue): one IssuePullRequest
105
+ * row per issue/PR pair, state "open", never duplicated or overwritten (a
106
+ * merged or closed pair stays so; an open one gets its url refreshed), and a
107
+ * pr_opened notification for each newly recorded opened pull request.
108
+ * handlePullRequestClosed settles the rows. A GitHub issue's key is always
109
+ * githubIssueKey's, so any lookup of its rows must build the key the same way.
110
+ * Safe to repeat; never throws.
111
+ */
112
+ export async function recordIssuePullRequests(db, issue, prs) {
113
+ try {
114
+ await emitNewlyOpened(issue, prs, await recordPairs(db, issue, prs), null);
115
+ }
116
+ catch (err) {
117
+ log.warn({ err, issueKey: issue.key }, "could not record the issue's pull requests");
118
+ }
119
+ }
120
+ /**
121
+ * The coding runs (of `runIds`) that continued a pull request opened for a
122
+ * different issue: their PR belongs to that issue, not this one. A
123
+ * continuation is foreign when its root coding run was dispatched for another
124
+ * tracked issue (CodingRun.issueKey), or when that root opened a pull request
125
+ * recorded for a different issue of any provider (IssuePullRequest, which a
126
+ * GitHub issue's runs also write). A continued PR with no issue, or this same
127
+ * issue, is fine.
128
+ */
129
+ export async function continuedForAnotherIssue(db, runIds, issue) {
130
+ if (runIds.length === 0)
131
+ return new Set();
132
+ const rows = await db.codingRun.findMany({
133
+ where: { runId: { in: runIds } },
134
+ select: {
135
+ runId: true,
136
+ rootCodingRunId: true,
137
+ rootCodingRun: { select: { issueProvider: true, issueKey: true } },
138
+ },
139
+ });
140
+ const foreign = new Set();
141
+ const byRoot = new Map();
142
+ for (const { runId, rootCodingRunId, rootCodingRun: root } of rows) {
143
+ if (root?.issueKey && (root.issueKey !== issue.key || root.issueProvider !== issue.provider)) {
144
+ foreign.add(runId);
145
+ }
146
+ else if (rootCodingRunId) {
147
+ byRoot.set(rootCodingRunId, [...(byRoot.get(rootCodingRunId) ?? []), runId]);
148
+ }
149
+ }
150
+ if (byRoot.size > 0) {
151
+ const recorded = await db.issuePullRequest.findMany({
152
+ where: { openedByRunId: { in: [...byRoot.keys()] } },
153
+ select: { openedByRunId: true, issueProvider: true, issueKey: true },
154
+ });
155
+ for (const r of recorded) {
156
+ if (r.issueProvider === issue.provider && r.issueKey === issue.key)
157
+ continue;
158
+ for (const runId of byRoot.get(r.openedByRunId) ?? [])
159
+ foreign.add(runId);
160
+ }
161
+ }
162
+ return foreign;
163
+ }
68
164
  /**
69
165
  * Returns sentences for the outcome comment (a refused status move); empty
70
166
  * when there is nothing to say. Safe to repeat (a retried completion): each
@@ -77,8 +173,11 @@ export async function recordPullRequests(db, tracker, input) {
77
173
  const notes = [];
78
174
  try {
79
175
  let newlyOpened = false;
80
- for (const pr of input.pullRequests) {
81
- const state = await ensurePair(db, input, pr);
176
+ const issue = { provider: input.issueProvider, key: input.issueKey };
177
+ const records = input.pullRequests.map((pr) => ({ ...pr, agentId: input.agentId }));
178
+ const states = await recordPairs(db, issue, records);
179
+ for (const [i, pr] of input.pullRequests.entries()) {
180
+ const state = states[i];
82
181
  if (state === "created" && pr.outcome === "pull_request_opened")
83
182
  newlyOpened = true;
84
183
  if (state !== "created" && state !== "open")
@@ -95,15 +194,19 @@ export async function recordPullRequests(db, tracker, input) {
95
194
  }
96
195
  }
97
196
  const target = input.onPullRequestOpened;
197
+ let movedTo = null;
98
198
  if (target && newlyOpened) {
99
199
  try {
100
- await tracker.transitionTo(input.issueKey, target);
200
+ const moved = await tracker.transitionTo(input.issueKey, target);
201
+ movedTo = moved.toStatus || target;
101
202
  }
102
203
  catch (err) {
103
204
  log.warn({ err, issueKey: input.issueKey, target }, "could not move the issue after a pull request opened");
104
205
  notes.push(`Could not move ${input.issueKey} to "${target}"; it may need a manual move.`);
105
206
  }
106
207
  }
208
+ // Only pairs this call newly recorded, so a retried completion does not notify twice. Never throws.
209
+ await emitNewlyOpened(issue, records, states, movedTo);
107
210
  }
108
211
  catch (err) {
109
212
  log.warn({ err, issueKey: input.issueKey }, "could not bridge the pull requests to the issue");
@@ -112,8 +215,9 @@ export async function recordPullRequests(db, tracker, input) {
112
215
  }
113
216
  /**
114
217
  * A pull request wardby recorded against an issue was merged or closed: marks
115
- * each still-open pair, and, where the agent's link to the issue's project is
116
- * still write, comments on the issue (and on merge resolves the web link and
218
+ * each still-open pair (every issue provider, configured tracker or not),
219
+ * and, for an issue in a configured tracker where the agent's link to the
220
+ * issue's project is still write, comments on the issue (and on merge resolves the web link and
117
221
  * applies the link's onPullRequestMerged move). Only rows wardby wrote are
118
222
  * touched, matched by the host's own identity for the PR — nothing from the
119
223
  * PR's text. The row is claimed first (open → merged/closed), so a duplicate
@@ -122,12 +226,32 @@ export async function recordPullRequests(db, tracker, input) {
122
226
  * delivery is rolled back and redelivered; never throws after that.
123
227
  */
124
228
  export async function handlePullRequestClosed(db, trackers, pr) {
125
- if (!trackers)
126
- return;
127
229
  const where = { codeProvider: pr.codeProvider, repository: pr.repository, number: pr.number };
128
230
  // Not caught: nothing is claimed yet, and a throw rolls back the delivery so it is redelivered.
129
- const rows = await db.issuePullRequest.findMany({ where: { ...where, state: "open" } });
231
+ // Oldest pair first: pr_closed's dedupe key is per pull request, so the first-recorded issue's event is
232
+ // the one kept, every delivery alike.
233
+ const rows = await db.issuePullRequest.findMany({
234
+ where: { ...where, state: "open" },
235
+ orderBy: { createdAt: "asc" },
236
+ });
130
237
  for (const row of rows) {
238
+ // Exactly once per claimed row, from the finally below, even when a later step throws: the row is no
239
+ // longer open, so nothing would retry it. Never throws.
240
+ const emitClosed = (movedTo) => emitWorkflowEvent({
241
+ dedupeKey: dedupeKeys.prClosed(pr.codeProvider, pr.repository, pr.number),
242
+ agentId: row.agentId,
243
+ workItem: { provider: row.issueProvider, key: row.issueKey },
244
+ pullRequest: { codeProvider: pr.codeProvider, repository: pr.repository, number: pr.number },
245
+ payload: {
246
+ kind: "pr_closed",
247
+ prLabel: `${row.repository}#${row.number}`,
248
+ prUrl: row.url,
249
+ merged: pr.merged,
250
+ movedTo,
251
+ },
252
+ });
253
+ let claimedRow = false;
254
+ let movedTo = null;
131
255
  try {
132
256
  const claimed = await db.issuePullRequest.updateMany({
133
257
  where: { id: row.id, state: "open" },
@@ -135,7 +259,9 @@ export async function handlePullRequestClosed(db, trackers, pr) {
135
259
  });
136
260
  if (claimed.count === 0)
137
261
  continue;
138
- const tracker = trackers[row.issueProvider];
262
+ claimedRow = true;
263
+ // A pair with no configured tracker (a GitHub issue's, say) is only marked.
264
+ const tracker = trackers?.[row.issueProvider];
139
265
  if (!tracker)
140
266
  continue;
141
267
  const link = await db.agentIssueProject.findUnique({
@@ -166,6 +292,7 @@ export async function handlePullRequestClosed(db, trackers, pr) {
166
292
  if (target) {
167
293
  try {
168
294
  const moved = await tracker.transitionTo(row.issueKey, target);
295
+ movedTo = moved.toStatus;
169
296
  markdown += ` Moved to ${moved.toStatus}.`;
170
297
  }
171
298
  catch (err) {
@@ -185,5 +312,9 @@ export async function handlePullRequestClosed(db, trackers, pr) {
185
312
  catch (err) {
186
313
  log.warn({ err, issueKey: row.issueKey, ...where }, "could not bridge the closed pull request to the issue");
187
314
  }
315
+ finally {
316
+ if (claimedRow)
317
+ await emitClosed(movedTo);
318
+ }
188
319
  }
189
320
  }
@@ -12,7 +12,7 @@ import type { Executor } from "../providers/executor/types.js";
12
12
  import type { IssueEvent, IssueEventKind, IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
13
13
  import { type DispatchDb } from "./dispatch.js";
14
14
  import { type OpenSibling } from "./related-pull-requests.js";
15
- export type IssueEventDb = DispatchDb & Pick<PrismaClient, "agentIssueProject" | "runIssueStatus" | "issuePullRequest" | "workItem">;
15
+ export type IssueEventDb = DispatchDb & Pick<PrismaClient, "registryFetch" | "registryAuditRecord" | "runBudgetEvent" | "agentIssueProject" | "runIssueStatus" | "issuePullRequest" | "workItem">;
16
16
  export interface RouteIssueEventDeps {
17
17
  db: IssueEventDb;
18
18
  executor: Executor;
@@ -2,11 +2,11 @@ import { RESPONSE_PATH_SNAPSHOT_BUDGET, resolveWorkItem } from "./attribution.js
2
2
  import { dispatchRun } from "./dispatch.js";
3
3
  import { issueStatusRow, postIssueWorkingStatus } from "./issue-status.js";
4
4
  import { logger } from "./logger.js";
5
- import { openSiblingsForIssue, SIBLING_GUIDANCE } from "./related-pull-requests.js";
5
+ import { openPullRequestHints, openSiblingsForIssue } from "./related-pull-requests.js";
6
6
  import { composeTaskOverride } from "./untrusted-content.js";
7
+ import { dedupeKeys, emitWorkflowEvent } from "./workflow-events.js";
7
8
  const log = logger.child({ module: "issue-events" });
8
9
  const MAX_TASK_BODY = 8000;
9
- const RUN_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
10
10
  /** Only admin-configured values (trigger labels, the target status) appear here: never free text from the actor. */
11
11
  function describeKind(event, kind, link) {
12
12
  switch (kind) {
@@ -44,14 +44,9 @@ export function issueTaskText(event, matched, issueUrl, link, openPrs = []) {
44
44
  "do not also post it with jira_comment; use jira_comment only for other issues or progress notes on long work.",
45
45
  ];
46
46
  // Control-plane data from stored rows (validated here), never issue text.
47
- const hinted = openPrs.filter((p) => RUN_ID_RE.test(p.openedByRunId));
48
- for (const pr of hinted) {
49
- sections.push(`This issue already has an open pull request wardby opened: ${pr.repository}#${pr.number} ` +
50
- `(https://github.com/${pr.repository}/pull/${pr.number}). ` +
51
- `To revise it, delegate with continuePriorRun set to exactly "${pr.openedByRunId}".`);
52
- }
53
- if (hinted.length > 0)
54
- sections.push(SIBLING_GUIDANCE);
47
+ const hints = openPullRequestHints(openPrs);
48
+ if (hints)
49
+ sections.push(hints);
55
50
  if (matched.includes("mention") && event.comment) {
56
51
  sections.push(`Request comment:\n${event.comment.body.slice(0, MAX_TASK_BODY)}`);
57
52
  }
@@ -93,7 +88,7 @@ export async function routeIssueEvent(event, deps) {
93
88
  return result;
94
89
  const links = (await deps.db.agentIssueProject.findMany({
95
90
  where: { provider: event.provider, projectKey: event.projectKey },
96
- include: { agent: { select: { ownerId: true, kind: true } } },
91
+ include: { agent: { select: { ownerId: true, kind: true, name: true } } },
97
92
  }));
98
93
  const bot = await tracker.botAccountId();
99
94
  // One snapshot per event, taken lazily on the first dispatch so an event no link matches costs nothing.
@@ -139,6 +134,16 @@ export async function routeIssueEvent(event, deps) {
139
134
  const runId = dispatched.run.id;
140
135
  result.runIds.push(runId);
141
136
  result.followUps.push(() => postIssueWorkingStatus(deps.db, deps.trackers, runId));
137
+ // describeKind shows only admin-configured values, so the trigger is safe to show in chat.
138
+ const trigger = matched.map((k) => describeKind(event, k, link)).join("; ");
139
+ const agentName = link.agent.name;
140
+ result.followUps.push(() => emitWorkflowEvent({
141
+ dedupeKey: dedupeKeys.issuePickedUp(runId),
142
+ runId,
143
+ agentId: link.agentId,
144
+ workItem: { provider: event.provider, key: event.issueKey },
145
+ payload: { kind: "issue_picked_up", agentName, trigger },
146
+ }));
142
147
  log.info({ issueKey: event.issueKey, agentId: link.agentId, runId, kinds: matched }, "issue run dispatched");
143
148
  }
144
149
  catch (err) {
@@ -7,7 +7,7 @@
7
7
  import { Prisma, type PrismaClient } from "#prisma";
8
8
  import { type IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
9
9
  import { type FinishedRun } from "./host-status.js";
10
- export type IssueStatusDb = Pick<PrismaClient, "runIssueStatus" | "run" | "agentIssueProject" | "issuePullRequest" | "codingRun" | "$queryRaw">;
10
+ export type IssueStatusDb = Pick<PrismaClient, "registryFetch" | "registryAuditRecord" | "runIssueStatus" | "run" | "runBudgetEvent" | "agentIssueProject" | "issuePullRequest" | "codingRun" | "$queryRaw">;
11
11
  export declare function toJiraMarkdown(text: string): string;
12
12
  export declare function issueStatusRow(event: {
13
13
  issueKey: string;
@@ -5,9 +5,9 @@
5
5
  * text. Best effort throughout: nothing here throws.
6
6
  */
7
7
  import { Prisma } from "#prisma";
8
- import { projectOf } from "../providers/issue-tracker/types.js";
9
- import { collectRunOutcome, outcomeBody, runLine, workingBody } from "./host-status.js";
10
- import { recordPullRequests } from "./issue-bridge.js";
8
+ import { projectOf, } from "../providers/issue-tracker/types.js";
9
+ import { collectRunOutcome, fullReplyComments, fullReplyOf, isBlockedByRefusals, JIRA_REPLY_MAX_CHARS, outcomeBody, REPLY_MAX_PARTS, runLine, workingBody, } from "./host-status.js";
10
+ import { continuedForAnotherIssue, recordPullRequests } from "./issue-bridge.js";
11
11
  import { logger } from "./logger.js";
12
12
  const log = logger.child({ module: "issue-status" });
13
13
  const TERMINAL = new Set(["succeeded", "failed", "refused", "lost", "budget_exhausted", "cancelled"]);
@@ -22,12 +22,23 @@ export function toJiraMarkdown(text) {
22
22
  export function issueStatusRow(event, runId, visibilityRole) {
23
23
  return { runId, provider: "jira", issueKey: event.issueKey, visibilityRole };
24
24
  }
25
+ /**
26
+ * Cents from $1 up ($12.34, $1234.50); below $1, two significant digits with at
27
+ * least two decimals so fractions of a cent stay readable ($0.50, $0.12, $0.0035).
28
+ * Never exponent form.
29
+ */
30
+ const usd = (amount) => {
31
+ const abs = Math.abs(amount);
32
+ const decimals = abs === 0 || abs >= 1 ? 2 : Math.max(2, 1 - Math.floor(Math.log10(abs)));
33
+ // Trailing zeros past the cents are noise ($0.010, $0.100 from rounding up).
34
+ return `$${amount.toFixed(Math.min(decimals, 20)).replace(/(\.\d\d\d*?)0+$/, "$1")}`;
35
+ };
25
36
  export function formatSpendLine(input) {
26
- const parts = [`Agent spend: $${input.treeUsd.toFixed(4)} this run`];
37
+ const parts = [`Agent spend: ${usd(input.treeUsd)} this run`];
27
38
  if (input.issueUsd !== null)
28
- parts.push(`$${input.issueUsd.toFixed(4)} on this issue so far`);
39
+ parts.push(`${usd(input.issueUsd)} on this issue so far`);
29
40
  if (input.models.length > 0)
30
- parts.push(input.models.map((m) => `${m.model} $${m.costUsd.toFixed(4)}`).join(", "));
41
+ parts.push(input.models.map((m) => `${m.model} ${usd(m.costUsd)}`).join(", "));
31
42
  return parts.join(" · ");
32
43
  }
33
44
  /** The whole run tree under `runId` (every depth), the issue's total across all its runs, and the tree's models. */
@@ -115,26 +126,6 @@ async function currentLink(db, runId, issueKey, provider) {
115
126
  });
116
127
  return link ? { agentId: run.agentId, ...link } : null;
117
128
  }
118
- /**
119
- * The coding runs (of `runIds`) that continued a pull request opened for a
120
- * different issue: their PR belongs to that issue, not this one. A continued
121
- * PR with no issue, or this same issue, is fine.
122
- */
123
- async function continuedForAnotherIssue(db, runIds, issue) {
124
- if (runIds.length === 0)
125
- return new Set();
126
- const rows = await db.codingRun.findMany({
127
- where: { runId: { in: runIds } },
128
- select: { runId: true, rootCodingRun: { select: { issueProvider: true, issueKey: true } } },
129
- });
130
- return new Set(rows
131
- .filter(({ rootCodingRun: root }) => {
132
- if (!root?.issueKey)
133
- return false;
134
- return root.issueKey !== issue.issueKey || root.issueProvider !== issue.provider;
135
- })
136
- .map((row) => row.runId));
137
- }
138
129
  export async function completeIssueStatus(db, run, trackers, opts = {}) {
139
130
  if (!trackers)
140
131
  return;
@@ -153,9 +144,10 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
153
144
  const writable = link?.access === "write";
154
145
  const project = projectOf(status.issueKey);
155
146
  let body;
147
+ let fullReply = null;
156
148
  if (writable) {
157
- const { pullRequests, failedChildren, budgetSentence } = await collectRunOutcome(db, run);
158
- const foreign = await continuedForAnotherIssue(db, pullRequests.flatMap((pr) => (pr.pullRequestUrl && pr.runId ? [pr.runId] : [])), status);
149
+ const { pullRequests, failedChildren, budgetSentence, packageRefusals, noChanges, packageAudit } = await collectRunOutcome(db, run);
150
+ const foreign = await continuedForAnotherIssue(db, pullRequests.flatMap((pr) => (pr.pullRequestUrl && pr.runId ? [pr.runId] : [])), { provider: status.provider, key: status.issueKey });
159
151
  for (const runId of foreign) {
160
152
  log.info({ runId: run.id, codingRunId: runId, issueKey: status.issueKey }, "not linking a pull request continued from another issue's run");
161
153
  }
@@ -180,9 +172,18 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
180
172
  pullRequests: bridged,
181
173
  })
182
174
  : { notes: [] };
175
+ // A blocked status is built from the refusals alone, so the agent's reply is not posted after it.
176
+ fullReply = isBlockedByRefusals(run, { pullRequests, failedChildren, packageRefusals, noChanges })
177
+ ? null
178
+ : fullReplyOf(run, pullRequests, failedChildren);
183
179
  const outcome = outcomeBody(run, "", pullRequests, failedChildren, {
184
180
  budgetSentence,
181
+ packageRefusals,
182
+ packageAudit,
183
+ noChanges,
184
+ fullReplyFollows: true,
185
185
  noPullRequestText: "Done.",
186
+ fromIssue: true,
186
187
  // One comment per request: this status comment carries the agent's answer.
187
188
  replyAsAnswer: true,
188
189
  });
@@ -210,12 +211,50 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
210
211
  }
211
212
  // Unlinked or read-only with no status comment yet: complete the row
212
213
  // without posting; never create content where the agent may not write.
213
- await db.runIssueStatus.update({ where: { runId: run.id }, data: { commentId, completedAt: new Date() } });
214
+ // Claims the row in one step, saving a posted comment's id at once so a retry edits it instead of
215
+ // posting a second one. Only the completion that claims it posts the full reply, so two racing
216
+ // completions (the run's own and the reconciler's) never post it twice.
217
+ const claimed = await db.runIssueStatus.updateMany({
218
+ where: { runId: run.id, completedAt: null },
219
+ data: { commentId, completedAt: new Date() },
220
+ });
221
+ if (claimed.count !== 1) {
222
+ log.warn({ runId: run.id }, "the issue status comment was completed meanwhile; leaving any full reply to that completion");
223
+ return;
224
+ }
225
+ if (writable && fullReply !== null) {
226
+ await postFullReply(tracker, status.issueKey, run.id, fullReply, issueKeyProjects, link.commentVisibilityRole);
227
+ }
214
228
  }
215
229
  catch (err) {
216
230
  log.warn({ err, runId: run.id }, "could not complete the issue status comment");
217
231
  }
218
232
  }
233
+ /**
234
+ * Posts the full reply's parts in order, each at most once: the status comment already points to them,
235
+ * so a failed part is logged and the rest skipped (a gap would misnumber the reply), and the row is still
236
+ * completed. The full text stays on the run. Never throws.
237
+ */
238
+ async function postFullReply(tracker, issueKey, runId, reply, issueKeyProjects, visibilityRole) {
239
+ // Converted first, then split: the conversion lengthens `owner/repo#N` references, and the parts must fit after it.
240
+ const bodies = fullReplyComments(toJiraMarkdown(reply), {
241
+ maxChars: JIRA_REPLY_MAX_CHARS,
242
+ maxParts: REPLY_MAX_PARTS,
243
+ });
244
+ for (const [i, body] of bodies.entries()) {
245
+ try {
246
+ await tracker.comment(issueKey, {
247
+ markdown: body,
248
+ issueKeyProjects,
249
+ ...(visibilityRole ? { visibilityRole } : {}),
250
+ });
251
+ }
252
+ catch (err) {
253
+ 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");
254
+ return;
255
+ }
256
+ }
257
+ }
219
258
  export async function closeOrphanedIssueStatuses(db, trackers, now = new Date()) {
220
259
  const providers = Object.keys(trackers ?? {});
221
260
  if (!trackers || providers.length === 0)
@@ -9,5 +9,10 @@
9
9
  * for the CLI's own output — see cli.ts's stdout/stderr split).
10
10
  */
11
11
  import pino from "pino";
12
+ /**
13
+ * Sets the filter every log line passes through on its way to stderr. The native sandbox worker
14
+ * uses it to redact the secret values it received (native-worker/stderr-redaction.ts).
15
+ */
16
+ export declare function setLogLineFilter(filter: (line: string) => string): void;
12
17
  export declare const logger: pino.Logger<never, boolean>;
13
18
  export type Logger = typeof logger;
@@ -42,4 +42,17 @@ function redactErr(error) {
42
42
  // last two); an AggregateError adds `aggregateErrors`, hence the walk.
43
43
  return redactDeep(pino.stdSerializers.err(error));
44
44
  }
45
- export const logger = pino({ level: process.env.LOG_LEVEL ?? "info", serializers: { err: redactErr } }, pino.destination({ fd: 2, sync: false }));
45
+ /** Applied to every serialized line before it is written. Identity unless a process sets one. */
46
+ let lineFilter = (line) => line;
47
+ /**
48
+ * Sets the filter every log line passes through on its way to stderr. The native sandbox worker
49
+ * uses it to redact the secret values it received (native-worker/stderr-redaction.ts).
50
+ */
51
+ export function setLogLineFilter(filter) {
52
+ lineFilter = filter;
53
+ }
54
+ export const logger = pino({
55
+ level: process.env.LOG_LEVEL ?? "info",
56
+ serializers: { err: redactErr },
57
+ hooks: { streamWrite: (line) => lineFilter(line) },
58
+ }, pino.destination({ fd: 2, sync: false }));
@@ -0,0 +1,6 @@
1
+ import type { PrismaClient } from "#prisma";
2
+ import type { Executor } from "../providers/executor/types.js";
3
+ /** The stop reason recorded on every child stopped because its parent run ended lost. */
4
+ export declare const PARENT_LOST_REASON = "parent run lost";
5
+ /** Stops the still-drivable children of a run that ended lost, so none keeps spending for nobody. */
6
+ export declare function stopChildrenOfLostRun(db: Pick<PrismaClient, "run">, executor: Pick<Executor, "stop"> | undefined, runId: string): Promise<number>;
@@ -0,0 +1,32 @@
1
+ import { DRIVABLE } from "./run-status.js";
2
+ import { logger } from "./logger.js";
3
+ const log = logger.child({ module: "lost-run-children" });
4
+ /** The stop reason recorded on every child stopped because its parent run ended lost. */
5
+ export const PARENT_LOST_REASON = "parent run lost";
6
+ /** Stops the still-drivable children of a run that ended lost, so none keeps spending for nobody. */
7
+ export async function stopChildrenOfLostRun(db, executor, runId) {
8
+ if (!executor)
9
+ return 0;
10
+ let children;
11
+ try {
12
+ children = await db.run.findMany({
13
+ where: { parentRunId: runId, status: { in: [...DRIVABLE] } },
14
+ select: { id: true },
15
+ });
16
+ }
17
+ catch (err) {
18
+ log.error({ err, runId }, "could not list the children of a lost run");
19
+ return 0;
20
+ }
21
+ let stopped = 0;
22
+ for (const child of children) {
23
+ try {
24
+ await executor.stop(child.id, PARENT_LOST_REASON);
25
+ stopped++;
26
+ }
27
+ catch (err) {
28
+ log.error({ err, runId, childRunId: child.id }, "could not stop a child of a lost run");
29
+ }
30
+ }
31
+ return stopped;
32
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Marks a draft pull request Wardby's own App opened ready for review once it passes (#287):
3
+ * every Wardby review check on the head succeeded, CI is green, and the `wardby merge order`
4
+ * check is success or absent. Opt-in per write link (AgentRepository.markReadyWhenPassing) of
5
+ * the agent the repository event triggers: the builder that opened the pull request, or a lead
6
+ * that delegated to it (coding agents cannot link repositories, so a lead's link carries it).
7
+ * At most once per pull request (CodingRun.markedReadyAt on the opener's root coding run), so
8
+ * a person moving it back to draft is final. Cheap DB checks first; no host reads unless some
9
+ * link on the repository opted in.
10
+ *
11
+ * The host only confirms the pull request was authored by this App. The trust boundary is
12
+ * here: the pull request's marker must resolve (through rootCodingRunId) to a root coding run
13
+ * in this repository, recorded as this pull request, whose agent, or an ancestor agent in its
14
+ * run tree (Run.parentRunId, at most MAX_ANCESTOR_HOPS up), has an authorized, opted-in write
15
+ * link on this repository. An opted-in agent outside that run tree never counts. Only
16
+ * authorized links (authorizedVia set) count, for opting in and for review checks.
17
+ *
18
+ * Work a run stopped at its budget pushed (a draft to continue) is never marked ready.
19
+ *
20
+ * Never approves, merges, or converts back to draft. Never throws.
21
+ */
22
+ import type { PrismaClient } from "#prisma";
23
+ import type { ReviewHostRegistry } from "../providers/review-host/types.js";
24
+ import type { Logger } from "./logger.js";
25
+ export type MarkReadyOutcome = "marked" | "off" | "not_ready" | "skipped" | "failed";
26
+ export type MarkReadyDb = Pick<PrismaClient, "agentRepository" | "codingRun" | "run" | "runHostCheck">;
27
+ export interface MarkReadyDeps {
28
+ db: MarkReadyDb;
29
+ hosts: ReviewHostRegistry | undefined;
30
+ log?: Logger;
31
+ }
32
+ export declare function maybeMarkReady(deps: MarkReadyDeps, repository: string, prNumber: number, provider?: string): Promise<MarkReadyOutcome>;
33
+ /** After a reviewer run ends: evaluate the pull request it reviewed. Null when it reviewed none. */
34
+ export declare function markReadyAfterRun(deps: MarkReadyDeps, runId: string): Promise<MarkReadyOutcome | null>;