@wardby/cli 0.6.0 → 0.8.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 (740) hide show
  1. package/.env.example +5 -5
  2. package/README.md +6 -1
  3. package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
  4. package/dist/claude-coding-worker/driver.d.ts +33 -3
  5. package/dist/claude-coding-worker/driver.js +151 -21
  6. package/dist/claude-coding-worker/main.js +38 -6
  7. package/dist/claude-coding-worker/sdk.js +29 -2
  8. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  9. package/dist/claude-coding-worker/tool-socket.js +111 -0
  10. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  11. package/dist/claude-coding-worker/transcript.js +77 -0
  12. package/dist/claude-plugin/command.d.ts +61 -0
  13. package/dist/claude-plugin/command.js +376 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +3 -1
  16. package/dist/cli.js +71 -13
  17. package/dist/coding/code-host.d.ts +16 -0
  18. package/dist/coding/code-host.js +60 -0
  19. package/dist/coding/continuation-wording.d.ts +35 -0
  20. package/dist/coding/continuation-wording.js +73 -0
  21. package/dist/coding/linked-issue-note.d.ts +23 -0
  22. package/dist/coding/linked-issue-note.js +47 -0
  23. package/dist/coding/mcp-token.d.ts +12 -0
  24. package/dist/coding/mcp-token.js +26 -0
  25. package/dist/coding/merge-wording.d.ts +28 -0
  26. package/dist/coding/merge-wording.js +78 -0
  27. package/dist/coding/pr-description-note.d.ts +9 -0
  28. package/dist/coding/pr-description-note.js +32 -0
  29. package/dist/coding/profile.d.ts +46 -126
  30. package/dist/coding/profile.js +45 -4
  31. package/dist/coding/protected-path-wording.d.ts +8 -0
  32. package/dist/coding/protected-path-wording.js +1 -1
  33. package/dist/coding/protocol.d.ts +264 -346
  34. package/dist/coding/protocol.js +237 -12
  35. package/dist/coding/redact.d.ts +3 -0
  36. package/dist/coding/redact.js +17 -0
  37. package/dist/coding/registry/allowlist.d.ts +12 -0
  38. package/dist/coding/registry/allowlist.js +14 -1
  39. package/dist/coding/registry/audit-mode.d.ts +153 -0
  40. package/dist/coding/registry/audit-mode.js +304 -0
  41. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  42. package/dist/coding/registry/lockfile-shared.js +128 -0
  43. package/dist/coding/registry/lockfiles.js +1 -1
  44. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  45. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  46. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  47. package/dist/coding/registry/npm-lockfile.js +4 -6
  48. package/dist/coding/registry/npm.js +78 -8
  49. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  50. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  51. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  52. package/dist/coding/registry/pypi-plan.js +406 -0
  53. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  54. package/dist/coding/registry/pypi-requirements.js +155 -0
  55. package/dist/coding/registry/pypi.d.ts +3 -27
  56. package/dist/coding/registry/pypi.js +40 -154
  57. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  58. package/dist/coding/registry/refusal-hints.js +61 -0
  59. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  60. package/dist/coding/registry/refusal-wording.js +56 -0
  61. package/dist/coding/registry/report.d.ts +70 -8
  62. package/dist/coding/registry/report.js +112 -5
  63. package/dist/coding/registry/types.d.ts +58 -8
  64. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  65. package/dist/coding/registry/yarn-lockfile.js +367 -0
  66. package/dist/coding/services/catalog.d.ts +37 -351
  67. package/dist/coding/transcript/claude-code.d.ts +13 -0
  68. package/dist/coding/transcript/claude-code.js +273 -0
  69. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  70. package/dist/coding/transcript/download-protocol.js +18 -0
  71. package/dist/coding/transcript/format.d.ts +20 -0
  72. package/dist/coding/transcript/format.js +32 -0
  73. package/dist/coding/transcript/recorder.d.ts +52 -0
  74. package/dist/coding/transcript/recorder.js +225 -0
  75. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  76. package/dist/coding/transcript/resume/checkout.js +203 -0
  77. package/dist/coding/transcript/resume/command.d.ts +17 -0
  78. package/dist/coding/transcript/resume/command.js +176 -0
  79. package/dist/coding/transcript/resume/download.d.ts +20 -0
  80. package/dist/coding/transcript/resume/download.js +153 -0
  81. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  82. package/dist/coding/transcript/resume/launch.js +128 -0
  83. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  84. package/dist/coding/transcript/resume/session-file.js +79 -0
  85. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  86. package/dist/coding/transcript/resume/stand-in.js +49 -0
  87. package/dist/coding-worker/artifact.d.ts +8 -3
  88. package/dist/coding-worker/artifact.js +3 -1
  89. package/dist/coding-worker/debug-trace.d.ts +9 -6
  90. package/dist/coding-worker/debug-trace.js +16 -19
  91. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  92. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  93. package/dist/coding-worker/driver.d.ts +4 -3
  94. package/dist/coding-worker/driver.js +124 -39
  95. package/dist/coding-worker/errors.d.ts +1 -0
  96. package/dist/coding-worker/errors.js +32 -0
  97. package/dist/coding-worker/main.js +5 -1
  98. package/dist/coding-worker/mcp-config.d.ts +27 -0
  99. package/dist/coding-worker/mcp-config.js +32 -0
  100. package/dist/coding-worker/sdk.d.ts +36 -0
  101. package/dist/coding-worker/sdk.js +28 -1
  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 +15 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/mcp-call-limit.d.ts +8 -0
  108. package/dist/config/mcp-call-limit.js +18 -0
  109. package/dist/config/mcp-servers.d.ts +8 -0
  110. package/dist/config/mcp-servers.js +12 -0
  111. package/dist/config/providers.d.ts +12 -3
  112. package/dist/config/providers.js +55 -5
  113. package/dist/config/test-simulators.d.ts +92 -0
  114. package/dist/config/test-simulators.js +333 -0
  115. package/dist/config/tool-timeout.d.ts +1 -0
  116. package/dist/config/tool-timeout.js +18 -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-mcp.d.ts +36 -0
  130. package/dist/core/coding-mcp.js +253 -0
  131. package/dist/core/coding-queue.d.ts +2 -1
  132. package/dist/core/coding-queue.js +7 -0
  133. package/dist/core/coding-repository.d.ts +46 -0
  134. package/dist/core/coding-repository.js +92 -0
  135. package/dist/core/cron.d.ts +19 -1
  136. package/dist/core/cron.js +17 -0
  137. package/dist/core/datastores.js +1 -1
  138. package/dist/core/deferred-coding.d.ts +14 -0
  139. package/dist/core/deferred-coding.js +62 -0
  140. package/dist/core/delegation-child.d.ts +25 -0
  141. package/dist/core/delegation-child.js +37 -0
  142. package/dist/core/delegation-slots.d.ts +27 -0
  143. package/dist/core/delegation-slots.js +44 -0
  144. package/dist/core/dispatch.d.ts +48 -2
  145. package/dist/core/dispatch.js +166 -66
  146. package/dist/core/engine-native.js +1 -1
  147. package/dist/core/error-code.d.ts +38 -0
  148. package/dist/core/error-code.js +169 -0
  149. package/dist/core/grants.d.ts +46 -8
  150. package/dist/core/grants.js +99 -8
  151. package/dist/core/host-events.d.ts +18 -2
  152. package/dist/core/host-events.js +291 -27
  153. package/dist/core/host-status.d.ts +85 -3
  154. package/dist/core/host-status.js +300 -22
  155. package/dist/core/issue-bridge.d.ts +50 -6
  156. package/dist/core/issue-bridge.js +124 -33
  157. package/dist/core/issue-events.d.ts +1 -1
  158. package/dist/core/issue-events.js +4 -10
  159. package/dist/core/issue-status.d.ts +1 -1
  160. package/dist/core/issue-status.js +58 -29
  161. package/dist/core/logger.d.ts +5 -0
  162. package/dist/core/logger.js +14 -1
  163. package/dist/core/lost-run-children.d.ts +6 -0
  164. package/dist/core/lost-run-children.js +32 -0
  165. package/dist/core/mark-ready.d.ts +34 -0
  166. package/dist/core/mark-ready.js +152 -0
  167. package/dist/core/markdown-code.d.ts +8 -0
  168. package/dist/core/markdown-code.js +107 -0
  169. package/dist/core/mcp-client/client.d.ts +47 -0
  170. package/dist/core/mcp-client/client.js +141 -0
  171. package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
  172. package/dist/core/mcp-client/jsonrpc.js +54 -0
  173. package/dist/core/mcp-client/results.d.ts +13 -0
  174. package/dist/core/mcp-client/results.js +42 -0
  175. package/dist/core/mcp-servers.d.ts +90 -0
  176. package/dist/core/mcp-servers.js +230 -0
  177. package/dist/core/mcp-tools.d.ts +108 -0
  178. package/dist/core/mcp-tools.js +287 -0
  179. package/dist/core/memory-tools.js +7 -0
  180. package/dist/core/merge-order-check.d.ts +2 -1
  181. package/dist/core/merge-order-check.js +44 -18
  182. package/dist/core/notification-dispatcher.js +2 -1
  183. package/dist/core/notification-templates.d.ts +1 -7
  184. package/dist/core/notification-templates.js +36 -2
  185. package/dist/core/pull-request-state-sync.js +2 -2
  186. package/dist/core/reconciler.d.ts +4 -3
  187. package/dist/core/reconciler.js +8 -1
  188. package/dist/core/related-pull-requests.d.ts +11 -3
  189. package/dist/core/related-pull-requests.js +49 -20
  190. package/dist/core/reply-parts.d.ts +21 -0
  191. package/dist/core/reply-parts.js +73 -0
  192. package/dist/core/review-fix.d.ts +1 -1
  193. package/dist/core/review-fix.js +4 -3
  194. package/dist/core/review-host-checks.d.ts +1 -1
  195. package/dist/core/review-host-tools.d.ts +3 -0
  196. package/dist/core/review-host-tools.js +102 -14
  197. package/dist/core/review-reads.d.ts +55 -0
  198. package/dist/core/review-reads.js +233 -0
  199. package/dist/core/run-status.d.ts +12 -0
  200. package/dist/core/run-status.js +12 -0
  201. package/dist/core/runner.d.ts +145 -49
  202. package/dist/core/runner.js +719 -216
  203. package/dist/core/schedule-start.d.ts +12 -0
  204. package/dist/core/schedule-start.js +14 -0
  205. package/dist/core/secret-broker-config.d.ts +12 -74
  206. package/dist/core/secret-broker-config.js +1 -1
  207. package/dist/core/secret-guard.d.ts +49 -0
  208. package/dist/core/secret-guard.js +119 -0
  209. package/dist/core/secret-guarded-stores.d.ts +12 -0
  210. package/dist/core/secret-guarded-stores.js +41 -0
  211. package/dist/core/secret-spans.d.ts +50 -0
  212. package/dist/core/secret-spans.js +94 -0
  213. package/dist/core/secrets.d.ts +11 -1
  214. package/dist/core/secrets.js +27 -1
  215. package/dist/core/serializable-retry.d.ts +18 -0
  216. package/dist/core/serializable-retry.js +43 -0
  217. package/dist/core/stop-run.d.ts +46 -0
  218. package/dist/core/stop-run.js +61 -0
  219. package/dist/core/tool-admin.d.ts +5 -1
  220. package/dist/core/tool-admin.js +7 -2
  221. package/dist/core/tool-names.d.ts +13 -0
  222. package/dist/core/tool-names.js +20 -0
  223. package/dist/core/webhooks.d.ts +4 -0
  224. package/dist/core/webhooks.js +68 -49
  225. package/dist/core/workflow-events.d.ts +14 -2
  226. package/dist/core/workflow-events.js +4 -0
  227. package/dist/core/workflow-run-events.d.ts +5 -3
  228. package/dist/core/workflow-run-events.js +45 -9
  229. package/dist/core/zod-json-schema.d.ts +4 -0
  230. package/dist/core/zod-json-schema.js +39 -0
  231. package/dist/core/zod3-window.d.ts +35 -0
  232. package/dist/core/zod3-window.js +124 -0
  233. package/dist/generated/prisma/browser.d.ts +65 -3
  234. package/dist/generated/prisma/client.d.ts +65 -3
  235. package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
  236. package/dist/generated/prisma/enums.d.ts +10 -0
  237. package/dist/generated/prisma/enums.js +8 -0
  238. package/dist/generated/prisma/internal/class.d.ts +110 -0
  239. package/dist/generated/prisma/internal/class.js +4 -4
  240. package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
  241. package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
  242. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
  243. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
  244. package/dist/generated/prisma/models/Agent.d.ts +377 -8
  245. package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
  246. package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
  247. package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
  248. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  249. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
  250. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  251. package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
  252. package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
  253. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  254. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  255. package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
  256. package/dist/generated/prisma/models/HostProvider.js +1 -0
  257. package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
  258. package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
  259. package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
  260. package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
  261. package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
  262. package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
  263. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  264. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  265. package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
  266. package/dist/generated/prisma/models/McpServer.js +1 -0
  267. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
  268. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
  269. package/dist/generated/prisma/models/Principal.d.ts +167 -0
  270. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  271. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  272. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  273. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  274. package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
  275. package/dist/generated/prisma/models/Run.d.ts +738 -2
  276. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  277. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  278. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  279. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  280. package/dist/generated/prisma/models/Secret.d.ts +387 -0
  281. package/dist/generated/prisma/models/Tool.d.ts +223 -1
  282. package/dist/generated/prisma/models.d.ts +10 -0
  283. package/dist/help/search.js +12 -3
  284. package/dist/help-index.json +2033 -110
  285. package/dist/import/create.js +48 -4
  286. package/dist/import/neutral-schema.d.ts +51 -281
  287. package/dist/import/neutral-schema.js +7 -4
  288. package/dist/knowledge/check.d.ts +1 -1
  289. package/dist/knowledge/cli.d.ts +11 -1
  290. package/dist/knowledge/cli.js +37 -4
  291. package/dist/knowledge/concept.d.ts +3 -19
  292. package/dist/knowledge/location.d.ts +31 -0
  293. package/dist/knowledge/location.js +78 -0
  294. package/dist/mcp/auth/access.d.ts +10 -2
  295. package/dist/mcp/auth/access.js +15 -1
  296. package/dist/mcp/auth/grants-cli.d.ts +6 -4
  297. package/dist/mcp/auth/grants-cli.js +42 -3
  298. package/dist/mcp/auth/ownership.d.ts +7 -7
  299. package/dist/mcp/auth/resource-server.d.ts +3 -1
  300. package/dist/mcp/auth/resource-server.js +17 -2
  301. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  302. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  303. package/dist/mcp/context.d.ts +3 -0
  304. package/dist/mcp/host-events/github-ingress.d.ts +2 -0
  305. package/dist/mcp/host-events/github-ingress.js +2 -1
  306. package/dist/mcp/index.d.ts +6 -0
  307. package/dist/mcp/index.js +69 -10
  308. package/dist/mcp/server.d.ts +13 -0
  309. package/dist/mcp/server.js +33 -14
  310. package/dist/mcp/tools/agents.d.ts +4 -0
  311. package/dist/mcp/tools/agents.js +295 -28
  312. package/dist/mcp/tools/datastore.js +17 -8
  313. package/dist/mcp/tools/grants.js +73 -29
  314. package/dist/mcp/tools/host-providers.d.ts +2 -0
  315. package/dist/mcp/tools/host-providers.js +215 -0
  316. package/dist/mcp/tools/mcp-servers.d.ts +26 -0
  317. package/dist/mcp/tools/mcp-servers.js +481 -0
  318. package/dist/mcp/tools/memory.js +11 -1
  319. package/dist/mcp/tools/notification-channels.js +2 -2
  320. package/dist/mcp/tools/packages.d.ts +2 -0
  321. package/dist/mcp/tools/packages.js +195 -0
  322. package/dist/mcp/tools/repositories.js +65 -12
  323. package/dist/mcp/tools/run-access.d.ts +16 -0
  324. package/dist/mcp/tools/run-access.js +25 -0
  325. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  326. package/dist/mcp/tools/run-transcript-download.js +129 -0
  327. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  328. package/dist/mcp/tools/run-transcript.js +70 -0
  329. package/dist/mcp/tools/runs.js +209 -27
  330. package/dist/mcp/tools/scheduling.js +3 -1
  331. package/dist/mcp/tools/secret-elicitation-form.js +5 -0
  332. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  333. package/dist/mcp/tools/secret-elicitation-server.js +10 -61
  334. package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
  335. package/dist/mcp/tools/secret-elicitation.js +25 -2
  336. package/dist/mcp/tools/secrets.js +40 -6
  337. package/dist/mcp/tools/stop-run.d.ts +2 -0
  338. package/dist/mcp/tools/stop-run.js +82 -0
  339. package/dist/mcp/tools/subagents.js +2 -2
  340. package/dist/mcp/tools/tools.d.ts +7 -5
  341. package/dist/mcp/tools/tools.js +64 -16
  342. package/dist/mcp/tools/trigger.js +28 -6
  343. package/dist/mcp/transport/http-limits.d.ts +2 -0
  344. package/dist/mcp/transport/http-limits.js +6 -2
  345. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  346. package/dist/mcp/transport/stdio-link-host.js +67 -0
  347. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  348. package/dist/mcp/transport/streamable-http.js +41 -1
  349. package/dist/mcp/webhooks/ingress.js +10 -0
  350. package/dist/native-worker/docker-launcher.d.ts +38 -2
  351. package/dist/native-worker/docker-launcher.js +65 -5
  352. package/dist/native-worker/gateway-server.d.ts +55 -3
  353. package/dist/native-worker/gateway-server.js +152 -34
  354. package/dist/native-worker/gateway.d.ts +29 -1
  355. package/dist/native-worker/gateway.js +74 -4
  356. package/dist/native-worker/http-server.d.ts +7 -1
  357. package/dist/native-worker/http-server.js +62 -7
  358. package/dist/native-worker/http-transport.js +1 -1
  359. package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
  360. package/dist/native-worker/kubernetes-launcher.js +43 -3
  361. package/dist/native-worker/launch.d.ts +18 -1
  362. package/dist/native-worker/launch.js +6 -1
  363. package/dist/native-worker/ledger.d.ts +24 -4
  364. package/dist/native-worker/ledger.js +62 -8
  365. package/dist/native-worker/loopback.js +3 -8
  366. package/dist/native-worker/main.d.ts +2 -1
  367. package/dist/native-worker/main.js +14 -3
  368. package/dist/native-worker/protocol.d.ts +130 -577
  369. package/dist/native-worker/protocol.js +51 -2
  370. package/dist/native-worker/sandbox-executor.d.ts +17 -2
  371. package/dist/native-worker/sandbox-executor.js +78 -4
  372. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  373. package/dist/native-worker/stderr-redaction.js +237 -0
  374. package/dist/native-worker/stdio.d.ts +1 -1
  375. package/dist/native-worker/stdio.js +6 -5
  376. package/dist/native-worker/warm-pool.d.ts +2 -2
  377. package/dist/native-worker/warm-pool.js +4 -4
  378. package/dist/native-worker/worker.js +28 -2
  379. package/dist/observability/metrics.js +6 -1
  380. package/dist/providers/auth/self-hosted.d.ts +1 -1
  381. package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
  382. package/dist/providers/coding-proxy/capability-hash.js +5 -0
  383. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  384. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  385. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  386. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  387. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  388. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  389. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  390. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  391. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  392. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  393. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  394. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  395. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  396. package/dist/providers/coding-proxy/hold.js +86 -0
  397. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  398. package/dist/providers/coding-proxy/interrupted.js +104 -0
  399. package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
  400. package/dist/providers/coding-proxy/mcp-route.js +166 -0
  401. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
  402. package/dist/providers/coding-proxy/memory-ledger.js +99 -8
  403. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  404. package/dist/providers/coding-proxy/metering.js +27 -4
  405. package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
  406. package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
  407. package/dist/providers/coding-proxy/proxy.d.ts +21 -2
  408. package/dist/providers/coding-proxy/proxy.js +300 -48
  409. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  410. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  411. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  412. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  413. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  414. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  415. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  416. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  417. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  418. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  419. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  420. package/dist/providers/coding-proxy/registry/service.js +579 -112
  421. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  422. package/dist/providers/coding-proxy/registry/store.js +54 -1
  423. package/dist/providers/coding-proxy/runtime.d.ts +10 -0
  424. package/dist/providers/coding-proxy/runtime.js +109 -16
  425. package/dist/providers/coding-proxy/server.d.ts +9 -1
  426. package/dist/providers/coding-proxy/server.js +55 -1
  427. package/dist/providers/coding-proxy/types.d.ts +78 -1
  428. package/dist/providers/datastore/types.d.ts +5 -0
  429. package/dist/providers/engine/types.d.ts +17 -2
  430. package/dist/providers/engine/types.js +17 -0
  431. package/dist/providers/executor/composition.d.ts +10 -3
  432. package/dist/providers/executor/composition.js +52 -7
  433. package/dist/providers/executor/container.d.ts +394 -9
  434. package/dist/providers/executor/container.js +1210 -96
  435. package/dist/providers/executor/dbos-status.d.ts +31 -0
  436. package/dist/providers/executor/dbos-status.js +64 -0
  437. package/dist/providers/executor/dbos.d.ts +50 -1
  438. package/dist/providers/executor/dbos.js +207 -20
  439. package/dist/providers/executor/deferred.d.ts +12 -24
  440. package/dist/providers/executor/deferred.js +10 -29
  441. package/dist/providers/executor/in-process.d.ts +9 -1
  442. package/dist/providers/executor/in-process.js +14 -4
  443. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  444. package/dist/providers/executor/linked-issue-reader.js +30 -0
  445. package/dist/providers/executor/routing.d.ts +2 -0
  446. package/dist/providers/executor/routing.js +4 -0
  447. package/dist/providers/executor/types.d.ts +13 -0
  448. package/dist/providers/host-tools/invoke.d.ts +37 -0
  449. package/dist/providers/host-tools/invoke.js +117 -0
  450. package/dist/providers/host-tools/operations.d.ts +65 -0
  451. package/dist/providers/host-tools/operations.js +149 -0
  452. package/dist/providers/host-tools/registry.d.ts +79 -0
  453. package/dist/providers/host-tools/registry.js +362 -0
  454. package/dist/providers/host-tools/request-guard.d.ts +17 -0
  455. package/dist/providers/host-tools/request-guard.js +99 -0
  456. package/dist/providers/host-tools/self-test.d.ts +64 -0
  457. package/dist/providers/host-tools/self-test.js +142 -0
  458. package/dist/providers/index.d.ts +2 -1
  459. package/dist/providers/issue-tracker/types.d.ts +17 -0
  460. package/dist/providers/issue-tracker/types.js +39 -1
  461. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  462. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  463. package/dist/providers/jobs/docker-isolation.d.ts +10 -2
  464. package/dist/providers/jobs/docker-isolation.js +47 -8
  465. package/dist/providers/jobs/docker.d.ts +9 -0
  466. package/dist/providers/jobs/docker.js +60 -11
  467. package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
  468. package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
  469. package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
  470. package/dist/providers/jobs/kubernetes-api.js +10 -0
  471. package/dist/providers/jobs/kubernetes-client.js +10 -1
  472. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  473. package/dist/providers/jobs/kubernetes-isolation.js +32 -3
  474. package/dist/providers/jobs/kubernetes.d.ts +11 -1
  475. package/dist/providers/jobs/kubernetes.js +111 -17
  476. package/dist/providers/jobs/types.d.ts +39 -0
  477. package/dist/providers/jobs/types.js +13 -1
  478. package/dist/providers/llm/anthropic.js +5 -1
  479. package/dist/providers/llm/bedrock.d.ts +0 -12
  480. package/dist/providers/llm/bedrock.js +4 -0
  481. package/dist/providers/llm/claude-messages.d.ts +3 -1
  482. package/dist/providers/llm/claude-messages.js +4 -1
  483. package/dist/providers/llm/claude-provider.d.ts +2 -2
  484. package/dist/providers/llm/claude-provider.js +2 -2
  485. package/dist/providers/llm/openai.d.ts +2 -2
  486. package/dist/providers/llm/openai.js +6 -2
  487. package/dist/providers/llm/routing.d.ts +2 -2
  488. package/dist/providers/llm/routing.js +2 -2
  489. package/dist/providers/llm/types.d.ts +12 -2
  490. package/dist/providers/review-host/github-events.d.ts +9 -1
  491. package/dist/providers/review-host/github-events.js +34 -12
  492. package/dist/providers/review-host/github.d.ts +29 -2
  493. package/dist/providers/review-host/github.js +224 -29
  494. package/dist/providers/review-host/local.d.ts +8 -4
  495. package/dist/providers/review-host/local.js +49 -31
  496. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  497. package/dist/providers/review-host/patch-pages.js +176 -0
  498. package/dist/providers/review-host/review-format.d.ts +19 -1
  499. package/dist/providers/review-host/review-format.js +38 -7
  500. package/dist/providers/review-host/types.d.ts +140 -6
  501. package/dist/providers/review-host/types.js +9 -1
  502. package/dist/providers/storage/gcs.d.ts +63 -0
  503. package/dist/providers/storage/gcs.js +69 -0
  504. package/dist/providers/storage/index.d.ts +15 -0
  505. package/dist/providers/storage/index.js +14 -0
  506. package/dist/providers/storage/local.d.ts +24 -0
  507. package/dist/providers/storage/local.js +92 -0
  508. package/dist/providers/storage/meter.d.ts +14 -0
  509. package/dist/providers/storage/meter.js +34 -0
  510. package/dist/providers/storage/s3.d.ts +41 -0
  511. package/dist/providers/storage/s3.js +107 -0
  512. package/dist/providers/storage/types.d.ts +37 -3
  513. package/dist/providers/storage/types.js +21 -4
  514. package/dist/providers/vcs/git.d.ts +39 -4
  515. package/dist/providers/vcs/git.js +339 -26
  516. package/dist/providers/vcs/github-remote.d.ts +26 -3
  517. package/dist/providers/vcs/github-remote.js +124 -14
  518. package/dist/providers/vcs/github.d.ts +183 -44
  519. package/dist/providers/vcs/github.js +455 -56
  520. package/dist/providers/vcs/index.d.ts +1 -1
  521. package/dist/providers/vcs/index.js +9 -2
  522. package/dist/providers/vcs/pr-description.d.ts +127 -0
  523. package/dist/providers/vcs/pr-description.js +270 -0
  524. package/dist/providers/vcs/remote.d.ts +37 -1
  525. package/dist/providers/vcs/remote.js +7 -1
  526. package/dist/providers/vcs/routing.d.ts +16 -8
  527. package/dist/providers/vcs/routing.js +27 -6
  528. package/dist/providers/vcs/types.d.ts +150 -5
  529. package/dist/quickstart/coding-seed.d.ts +14 -3
  530. package/dist/quickstart/coding-seed.js +213 -4
  531. package/dist/quickstart/index.d.ts +5 -0
  532. package/dist/quickstart/index.js +21 -0
  533. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  534. package/dist/quickstart/reviewer-prompt.js +6 -6
  535. package/dist/quickstart-images.json +1 -1
  536. package/dist/sandbox/eval-core.d.ts +12 -2
  537. package/dist/sandbox/eval-core.js +20 -4
  538. package/dist/sandbox/generated/zod.bundle.js +62 -1
  539. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  540. package/dist/sandbox/host-functions.d.ts +5 -0
  541. package/dist/sandbox/host-functions.js +13 -13
  542. package/dist/sandbox/limits.d.ts +4 -1
  543. package/dist/sandbox/limits.js +4 -1
  544. package/dist/sandbox/run-in-sandbox.d.ts +6 -0
  545. package/dist/sandbox/run-in-sandbox.js +14 -2
  546. package/dist/sandbox/safe-fetch.d.ts +2 -0
  547. package/dist/sandbox/safe-fetch.js +1 -1
  548. package/dist/sandbox/secret-broker.d.ts +1 -0
  549. package/dist/sandbox/secret-broker.js +4 -5
  550. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  551. package/dist/sandbox/tool-timeout.d.ts +32 -0
  552. package/dist/sandbox/tool-timeout.js +52 -0
  553. package/dist/sandbox/user-tool.d.ts +8 -1
  554. package/dist/sandbox/user-tool.js +9 -3
  555. package/dist/sandbox/zod-params.d.ts +37 -5
  556. package/dist/sandbox/zod-params.js +181 -26
  557. package/dist/serve.js +8 -1
  558. package/dist/viewer/api-schema.d.ts +349 -2627
  559. package/dist/viewer/api-schema.js +7 -0
  560. package/dist/viewer/build-schemas.js +6 -2
  561. package/dist/viewer/graph.js +2 -1
  562. package/dist/viewer/openapi.js +2 -4
  563. package/dist/wardby-bin.js +15 -0
  564. package/docs/README.md +11 -1
  565. package/docs/agent-recipes.md +95 -24
  566. package/docs/architecture-runtime.md +1 -1
  567. package/docs/claude-code-plugin.md +164 -0
  568. package/docs/code-review-agents.md +557 -41
  569. package/docs/coding-agent-setup.md +566 -8
  570. package/docs/coding-packages.md +1033 -90
  571. package/docs/coding-services.md +27 -12
  572. package/docs/coding-worker-byo-images.md +24 -2
  573. package/docs/coding-worker-isolation.md +183 -37
  574. package/docs/debugging-agent-runs.md +242 -0
  575. package/docs/getting-started-gke.md +129 -141
  576. package/docs/getting-started-identity-provider.md +53 -38
  577. package/docs/getting-started.md +17 -0
  578. package/docs/host-providers.md +294 -0
  579. package/docs/jira-agents.md +17 -8
  580. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  581. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  582. package/docs/knowledge/delegation-admission-slots.md +52 -0
  583. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  584. package/docs/knowledge/import-rename-target.md +52 -0
  585. package/docs/knowledge/index.md +57 -0
  586. package/docs/knowledge/log.md +9 -0
  587. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  588. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  589. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  590. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  591. package/docs/knowledge/overview-cli.md +74 -0
  592. package/docs/knowledge/overview-coding-proxy.md +72 -0
  593. package/docs/knowledge/overview-coding.md +72 -0
  594. package/docs/knowledge/overview-config.md +60 -0
  595. package/docs/knowledge/overview-core.md +72 -0
  596. package/docs/knowledge/overview-deploy.md +83 -0
  597. package/docs/knowledge/overview-mcp.md +61 -0
  598. package/docs/knowledge/overview-prisma.md +72 -0
  599. package/docs/knowledge/overview-providers.md +89 -0
  600. package/docs/knowledge/overview-sandbox.md +83 -0
  601. package/docs/knowledge/overview-surfaces.md +83 -0
  602. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  603. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  604. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  605. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  606. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  607. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  608. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  609. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  610. package/docs/knowledge/warm-input-publication.md +30 -0
  611. package/docs/knowledge/workspace-staging-failure.md +54 -0
  612. package/docs/knowledge.md +54 -14
  613. package/docs/mcp-servers.md +254 -0
  614. package/docs/native-sandbox.md +143 -31
  615. package/docs/observability.md +4 -0
  616. package/docs/security-deployment.md +139 -29
  617. package/docs/slack-notifications.md +35 -19
  618. package/docs/tool-secrets.md +45 -10
  619. package/docs/viewer-api.md +6 -0
  620. package/docs/viewer-api.openapi.yml +1 -1
  621. package/help/admin-viewer.md +28 -2
  622. package/help/agent-recipes.md +33 -2
  623. package/help/architecture-agent.md +11 -6
  624. package/help/brokered-secrets.md +3 -0
  625. package/help/build-claude-code-image.md +1 -1
  626. package/help/build-worker-image.md +3 -1
  627. package/help/builder-agent.md +19 -6
  628. package/help/claude-code-run-pane.md +40 -0
  629. package/help/code-review-agents.md +177 -6
  630. package/help/coding-packages.md +156 -6
  631. package/help/cost-attribution.md +9 -5
  632. package/help/creating-agents.md +14 -1
  633. package/help/dependency-cache.md +143 -0
  634. package/help/deploy-gke.md +15 -8
  635. package/help/errors/budget-exhausted.md +187 -0
  636. package/help/errors/budget-group-exhausted.md +5 -1
  637. package/help/errors/coding-mcp-pins-unavailable.md +35 -0
  638. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  639. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  640. package/help/errors/continuation-closed.md +9 -12
  641. package/help/errors/database-auth-invalid.md +1 -1
  642. package/help/errors/delegation-conflict.md +24 -0
  643. package/help/errors/file-list-truncated.md +45 -0
  644. package/help/errors/full-read-required.md +49 -0
  645. package/help/errors/github-account-not-allowed.md +4 -0
  646. package/help/errors/graph-incomplete.md +43 -0
  647. package/help/errors/graph-limit.md +43 -0
  648. package/help/errors/host-provider-error.md +40 -0
  649. package/help/errors/host-tool-failed.md +36 -0
  650. package/help/errors/mcp-call-limit.md +22 -0
  651. package/help/errors/mcp-call-timeout.md +22 -0
  652. package/help/errors/mcp-server-auth-failed.md +22 -0
  653. package/help/errors/mcp-server-credentials-unavailable.md +45 -0
  654. package/help/errors/mcp-server-error.md +28 -0
  655. package/help/errors/mcp-server-unreachable.md +22 -0
  656. package/help/errors/mcp-servers-off.md +21 -0
  657. package/help/errors/mcp-tool-not-allowed.md +26 -0
  658. package/help/errors/mcp-tool-removed.md +22 -0
  659. package/help/errors/mcp-unavailable.md +25 -0
  660. package/help/errors/merge-conflict.md +49 -0
  661. package/help/errors/native-sandbox-capacity.md +1 -1
  662. package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
  663. package/help/errors/native-sandbox-docker-failed.md +1 -1
  664. package/help/errors/native-sandbox-gateway-error.md +20 -0
  665. package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
  666. package/help/errors/native-sandbox-image-not-pinned.md +1 -1
  667. package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
  668. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  669. package/help/errors/native-sandbox-network-unenforced.md +1 -1
  670. package/help/errors/native-sandbox-requires-catalog.md +1 -1
  671. package/help/errors/native-sandbox-unavailable.md +1 -1
  672. package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
  673. package/help/errors/native-sandbox-worker-exited.md +4 -3
  674. package/help/errors/native-sandbox-worker-lost.md +1 -1
  675. package/help/errors/native-sandbox-worker-unready.md +1 -1
  676. package/help/errors/package-not-allowed-pending.md +52 -0
  677. package/help/errors/package-not-allowed.md +51 -0
  678. package/help/errors/package-refusals.md +43 -0
  679. package/help/errors/patch-cursor-malformed.md +31 -0
  680. package/help/errors/repository-not-listed.md +36 -0
  681. package/help/errors/repository-required.md +36 -0
  682. package/help/errors/run-lost.md +39 -0
  683. package/help/errors/run-transcript-download.md +44 -0
  684. package/help/errors/secret-in-value.md +69 -0
  685. package/help/errors/target-merge.md +40 -0
  686. package/help/errors/tool-timeout.md +38 -0
  687. package/help/fix-merge-conflicts.md +73 -0
  688. package/help/github-app-setup.md +132 -0
  689. package/help/github.md +22 -0
  690. package/help/host-providers.md +40 -0
  691. package/help/identity-and-access.md +6 -1
  692. package/help/jira.md +23 -6
  693. package/help/knowledge.md +16 -7
  694. package/help/local-repositories.md +1 -1
  695. package/help/low-power-mode.md +7 -1
  696. package/help/mcp-servers.md +73 -0
  697. package/help/mcp.md +7 -2
  698. package/help/merge-order-check.md +5 -0
  699. package/help/native-capabilities.md +55 -1
  700. package/help/native-sandbox.md +16 -2
  701. package/help/operating-agents.md +21 -0
  702. package/help/package-audit-mode.md +91 -0
  703. package/help/related-pull-requests.md +17 -10
  704. package/help/repo-instructions-and-skills.md +3 -1
  705. package/help/resume-runs-locally.md +134 -0
  706. package/help/review-fix-rounds.md +33 -1
  707. package/help/sharing-agents.md +59 -0
  708. package/help/slack-notifications.md +19 -5
  709. package/help/status-comments.md +31 -0
  710. package/help/stop-run.md +58 -0
  711. package/help/troubleshooting/budgets.md +28 -0
  712. package/help/troubleshooting/coding-workers.md +86 -7
  713. package/help/troubleshooting/debugging-agent-runs.md +29 -0
  714. package/package.json +18 -10
  715. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  716. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  717. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  718. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  719. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  720. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  721. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  722. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  723. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  724. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  725. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  726. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  727. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  728. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  729. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  730. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  731. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  732. package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
  733. package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
  734. package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
  735. package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
  736. package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
  737. package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
  738. package/prisma/schema.prisma +468 -109
  739. package/scripts/git-askpass.sh +1 -1
  740. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -6,16 +6,21 @@
6
6
  * docs/private/2026-09-25-code-review-host-design.md §6.3.
7
7
  */
8
8
  import { Prisma } from "#prisma";
9
- import { linkedPullRequestAttribution, openingRunAttribution, RESPONSE_PATH_SNAPSHOT_BUDGET } from "./attribution.js";
9
+ import { codeProviderOf, pullRequestWebUrl } from "../coding/code-host.js";
10
+ import { linkedPullRequestAttribution, openingRunAttribution, resolveWorkItem, RESPONSE_PATH_SNAPSHOT_BUDGET, } from "./attribution.js";
11
+ import { headStoppedAtBudget, pushingRunInFlight } from "./budget-stopped-head.js";
10
12
  import { checkContinuation, dispatchRun } from "./dispatch.js";
11
13
  import { mentionStatusRow, postMentionStatus } from "./host-status.js";
12
- import { handlePullRequestClosed } from "./issue-bridge.js";
14
+ import { githubIssueKey, handlePullRequestClosed } from "./issue-bridge.js";
13
15
  import { logger } from "./logger.js";
16
+ import { withoutMarkdownCode } from "./markdown-code.js";
17
+ import { maybeMarkReady } from "./mark-ready.js";
14
18
  import { syncMergeOrderChecksForPullRequest } from "./merge-order-check.js";
15
- import { MAX_SIBLING_HINTS, openSiblings, runTreeRoot, SIBLING_GUIDANCE, } from "./related-pull-requests.js";
19
+ import { MAX_SIBLING_HINTS, openPullRequestHints, openSiblings, openSiblingsForIssue, runTreeRoot, SIBLING_GUIDANCE, } from "./related-pull-requests.js";
16
20
  import { requiredLevel } from "./repo-access.js";
17
21
  import { composeTaskOverride } from "./untrusted-content.js";
18
22
  import { DEFAULT_KNOWLEDGE_BUNDLE_PATH, parseConcept, RESERVED_BUNDLE_FILES, } from "../knowledge/concept.js";
23
+ import { KNOWLEDGE_CONFIG_MAX_BYTES, KNOWLEDGE_CONFIG_PATH, resolveKnowledgeLocation } from "../knowledge/location.js";
19
24
  import { driftScope } from "../knowledge/relevance.js";
20
25
  import { spanHash } from "../knowledge/span-hash.js";
21
26
  const log = logger.child({ module: "host-events" });
@@ -31,11 +36,14 @@ export const DEFERRED_REVIEW_BATCH = 50;
31
36
  function escapeRegExp(value) {
32
37
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33
38
  }
39
+ /** A `@app review` outside code: quoting the command in code documents it. */
34
40
  export function isReviewCommand(body, mentionHandle) {
35
- return new RegExp(`(^|[^\\w-])@${escapeRegExp(mentionHandle)}\\s+review(?![\\w-])`, "i").test(body);
41
+ return new RegExp(`(^|[^\\w-])@${escapeRegExp(mentionHandle)}\\s+review(?![\\w-])`, "i").test(withoutMarkdownCode(body));
36
42
  }
37
43
  const MAX_BUNDLE_FILES = 200;
38
44
  const BUNDLE_FILE_LINES = 2000;
45
+ /** `.wardby/knowledge.yaml` is one short key; a longer read is refused as too large. */
46
+ const KNOWLEDGE_CONFIG_MAX_LINES = 200;
39
47
  const MAX_LISTED_CHANGES = 200;
40
48
  /** The whole bundle load (listing plus reads) must finish inside GitHub's ~10 s webhook window. */
41
49
  const BUNDLE_LOAD_DEADLINE_MS = 4000;
@@ -49,7 +57,7 @@ const BUNDLE_INCOMPLETE_TEXT = "The knowledge bundle could not be fully read; tr
49
57
  * commits, so they and the affected concept paths travel as untrusted context.
50
58
  * Commit messages and author names are never included.
51
59
  */
52
- export function mergeTaskText(event, scope, bundleComplete = true, citations = new Map()) {
60
+ export function mergeTaskText(event, scope, bundleComplete = true, citations = new Map(), bundlePath = DEFAULT_KNOWLEDGE_BUNDLE_PATH) {
53
61
  const statusOf = (concept) => citations.get(concept) ?? { state: "unverified" };
54
62
  const changed = event.changedPathsComplete
55
63
  ? `Changed files:\n${[
@@ -61,7 +69,7 @@ export function mergeTaskText(event, scope, bundleComplete = true, citations = n
61
69
  : "The changed-file list is incomplete (GitHub includes at most 2048 commits per push and the list is capped at 1000 paths); treat every knowledge concept as possibly affected.";
62
70
  const listed = scope
63
71
  ? `Knowledge concepts whose citations, affects globs, or files changed (${scope.reason}):\n` +
64
- scope.concepts.map((p) => `- ${DEFAULT_KNOWLEDGE_BUNDLE_PATH}/${p} — ${describeStatus(statusOf(p))}`).join("\n")
72
+ scope.concepts.map((p) => `- ${bundlePath}/${p} — ${describeStatus(statusOf(p))}`).join("\n")
65
73
  : null;
66
74
  let context;
67
75
  if (!bundleComplete)
@@ -76,7 +84,7 @@ export function mergeTaskText(event, scope, bundleComplete = true, citations = n
76
84
  if (scope && scope.concepts.length > 0) {
77
85
  const states = scope.concepts.map((p) => statusOf(p).state);
78
86
  const count = (state) => states.filter((x) => x === state).length;
79
- const onlyKnowledge = event.changedPathsComplete && event.changedPaths.every((p) => p.startsWith(`${DEFAULT_KNOWLEDGE_BUNDLE_PATH}/`));
87
+ const onlyKnowledge = event.changedPathsComplete && event.changedPaths.every((p) => p.startsWith(`${bundlePath}/`));
80
88
  summary =
81
89
  `Citation check at ${event.after.slice(0, 12)}: ${count("verified")} of ${states.length} affected concepts verified, ` +
82
90
  `${count("stale")} stale, ${count("unverified")} not verified. Only knowledge files changed: ${onlyKnowledge ? "yes" : "no"}.`;
@@ -106,13 +114,36 @@ function startBudget(ms) {
106
114
  });
107
115
  return { promise, expired: () => expired, clear: () => clearTimeout(timer) };
108
116
  }
117
+ /**
118
+ * `.wardby/knowledge.yaml` at the pushed commit, or null when it does not
119
+ * exist. Reads within the shared budget; a deadline or a host error throws,
120
+ * which resolveKnowledgeLocation turns into the default bundle with a warning.
121
+ */
122
+ async function readKnowledgeConfig(host, event, budget) {
123
+ const read = await Promise.race([
124
+ host.readFile(event.repository, KNOWLEDGE_CONFIG_PATH, event.after, {
125
+ startLine: 1,
126
+ maxLines: KNOWLEDGE_CONFIG_MAX_LINES,
127
+ }),
128
+ budget.promise,
129
+ ]);
130
+ if (read === "deadline")
131
+ throw new Error("the read hit its deadline");
132
+ if (read.kind === "not_found")
133
+ return null;
134
+ if (read.kind !== "file")
135
+ throw new Error("it is not a file");
136
+ if (read.truncated || Buffer.byteLength(read.text, "utf8") > KNOWLEDGE_CONFIG_MAX_BYTES)
137
+ throw new Error(`it is larger than ${KNOWLEDGE_CONFIG_MAX_BYTES} bytes`);
138
+ return read.text;
139
+ }
109
140
  /**
110
141
  * The knowledge bundle at the pushed commit, read with bounded concurrency
111
142
  * under one overall deadline. A failure never fails the route; it yields an
112
143
  * incomplete result so the watcher treats every concept as possibly affected.
113
144
  */
114
- async function loadBundle(host, event, budget) {
115
- const prefix = `${DEFAULT_KNOWLEDGE_BUNDLE_PATH}/`;
145
+ async function loadBundle(host, event, budget, bundlePath) {
146
+ const prefix = `${bundlePath}/`;
116
147
  const concepts = [];
117
148
  const where = { repository: event.repository, after: event.after };
118
149
  let filesRead = 0;
@@ -260,7 +291,7 @@ export function continuationHint(prNumber, runId) {
260
291
  `continued instead of opening a new one.]`);
261
292
  }
262
293
  const HINT_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
263
- const HINT_REPOSITORY = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
294
+ const HINT_REPOSITORY = /^(?:[a-z][a-z0-9-]{1,30}:)?[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
264
295
  /** One hint per open sibling (stored rows only; links built, ids re-validated), then the shared guidance. */
265
296
  export function siblingContinuationHints(siblings) {
266
297
  const lines = siblings
@@ -269,8 +300,11 @@ export function siblingContinuationHints(siblings) {
269
300
  Number.isSafeInteger(s.number) &&
270
301
  s.number > 0)
271
302
  .slice(0, MAX_SIBLING_HINTS)
272
- .map((s) => `- ${s.repository}#${s.number} (https://github.com/${s.repository}/pull/${s.number}): to change it, ` +
273
- `delegate to that repository's coding agent and ${continuePriorRunPhrase(s.openedByRunId)}.`);
303
+ .map((s) => {
304
+ const url = pullRequestWebUrl(codeProviderOf(s.repository), s.repository, s.number);
305
+ return (`- ${s.repository}#${s.number}${url ? ` (${url})` : ""}: to change it, ` +
306
+ `delegate to that repository's coding agent and ${continuePriorRunPhrase(s.openedByRunId)}.`);
307
+ });
274
308
  if (lines.length === 0)
275
309
  return undefined;
276
310
  return [
@@ -306,6 +340,12 @@ export function mentionTaskText(event, siblings = []) {
306
340
  if (hints)
307
341
  sections.push(hints);
308
342
  }
343
+ else if (!event.isPullRequest) {
344
+ // An issue mention: the issue's open wardby pull requests, worded as a Jira issue's are.
345
+ const hints = openPullRequestHints(siblings);
346
+ if (hints)
347
+ sections.push(hints);
348
+ }
309
349
  const title = event.subject?.title.replace(/\s+/g, " ").trim().slice(0, MAX_TITLE);
310
350
  const description = event.subject?.body.trim() ? event.subject.body.slice(0, MAX_TASK_BODY) : "";
311
351
  sections.push([
@@ -342,11 +382,49 @@ async function priorRunContinues(deps, event) {
342
382
  const check = await checkContinuation(deps.db, event.priorRunId, event.repository);
343
383
  return check.ok && check.root.pullRequestNumber === event.number;
344
384
  }
385
+ /** The reply to a mention whose author can see the repository but cannot push to it. */
386
+ export const NO_WRITE_ACCESS_BODY = "😕 I can't act on this: a mention starts work only for people with write access to this repository. " +
387
+ "Ask someone with write access to mention me instead.";
388
+ /** Associations that mean the account holds a role on the repository, not just a view of a public one. */
389
+ const ROLE_ASSOCIATIONS = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
390
+ /**
391
+ * Whether a refused author should be told why. Triage is granted explicitly, so
392
+ * it always counts. GitHub reports `read` for every account on a public
393
+ * repository, so there `read` counts only with a role association; on a private
394
+ * repository `read` means the account was given access (a private organization
395
+ * member is labelled CONTRIBUTOR or NONE). Unknown facts stay silent.
396
+ */
397
+ function explainsRefusal(level, event) {
398
+ if (level === "triage")
399
+ return true;
400
+ if (level !== "read")
401
+ return false;
402
+ return event.repositoryPrivate === true || ROLE_ASSOCIATIONS.has(event.authorAssociation ?? "");
403
+ }
345
404
  export function unknownPriorRunBody(priorRunId) {
346
405
  return (`❌ I can't continue this pull request. Its description names wardby run \`${priorRunId}\`, but this wardby ` +
347
406
  "deployment has no record of that run opening this pull request (another wardby deployment may have opened it). " +
348
407
  "Ask the deployment that opened it, or make the change on this branch by hand.");
349
408
  }
409
+ /**
410
+ * Never names the App's handle: this comment is posted by the App, and a
411
+ * body that mentioned it could be matched as a mention of itself.
412
+ */
413
+ export function mentionDeclinedBody(reason) {
414
+ switch (reason) {
415
+ case "no_responder":
416
+ return (`ℹ️ I didn't start a run: no agent on this repository is set up to answer mentions. ` +
417
+ 'An agent owner can link one with the `mention` trigger (`link_repository`, `triggers: ["mention"]`).');
418
+ case "no_reviewer":
419
+ return (`ℹ️ I didn't start a review: no reviewer agent is linked to this repository. ` +
420
+ "An agent owner can link one with the `pull_request` trigger and a `checkName` (`link_repository`).");
421
+ case "agent_not_authorized":
422
+ return ("ℹ️ I didn't start a run: the agent linked here can no longer use this repository. " +
423
+ "Its owner's GitHub account needs access to it again; they can re-authorize it or re-link the agent.");
424
+ case "pull_request_not_reviewable":
425
+ return "ℹ️ I didn't start a review: this pull request is closed or comes from a fork, and wardby reviews only open pull requests from branches of this repository.";
426
+ }
427
+ }
350
428
  /** A review run's task: the head to review, plus any extra context its trigger adds. */
351
429
  export function reviewTaskText(repository, prNumber, headSha, context) {
352
430
  const task = `Review pull request #${prNumber} in ${repository} (head ${headSha}).`;
@@ -457,6 +535,59 @@ context) {
457
535
  }
458
536
  return runIds;
459
537
  }
538
+ async function budgetDraftDecision(deps, host, repository, prNumber, headSha,
539
+ /** The pull request's origin, when the caller already reads it once per event. */
540
+ readOrigin) {
541
+ const review = { kind: "review" };
542
+ const read = readOrigin ?? (host.pullRequestOrigin ? () => host.pullRequestOrigin(repository, prNumber) : undefined);
543
+ if (!read)
544
+ return review;
545
+ try {
546
+ const origin = await read();
547
+ if (origin.draft !== true || !origin.markerRunId)
548
+ return review;
549
+ const runId = await pushingRunInFlight(deps.db, { markerRunId: origin.markerRunId, repository });
550
+ if (runId)
551
+ return { kind: "wait", runId: await pushingRunHold(deps.db, runId) };
552
+ const stopped = await headStoppedAtBudget(deps.db, {
553
+ markerRunId: origin.markerRunId,
554
+ repository,
555
+ prNumber,
556
+ headSha,
557
+ });
558
+ return stopped ? { kind: "skip" } : review;
559
+ }
560
+ catch (err) {
561
+ log.warn({ err, repository, prNumber }, "could not read the pull request's coding run; reviewing as usual");
562
+ return review;
563
+ }
564
+ }
565
+ /**
566
+ * Instead of reviewing a budget-stopped draft (budgetDraftDecision `skip`): completes a neutral
567
+ * check per reviewer. No review run, so no RunHostCheck and no fix round. A reviewer that already
568
+ * reviewed this commit (an explicit request) keeps that review's check: a neutral one over it
569
+ * would stand, unreviewed again, once the draft is marked ready (that automatic review skips a
570
+ * reviewed commit).
571
+ */
572
+ async function postSkippedReviewChecks(deps, host, repository, prNumber, headSha, targets) {
573
+ log.info({ repository, prNumber, headSha, agentIds: targets.map((t) => t.agentId) }, "review skipped: the draft's last push stopped at its budget");
574
+ for (const target of targets) {
575
+ try {
576
+ if (await alreadyReviewed(deps, repository, prNumber, headSha, target.agentId))
577
+ continue;
578
+ const { checkId } = await host.startCheck(repository, { headSha, name: target.checkName });
579
+ await host.completeCheck(repository, {
580
+ checkId,
581
+ conclusion: "neutral",
582
+ title: "Skipped: stopped at its budget",
583
+ summary: "The last push came from a run that stopped at its budget before finishing. This draft is reviewed when the work continues or when it is marked ready for review.",
584
+ });
585
+ }
586
+ catch (err) {
587
+ log.warn({ err, repository, prNumber, agentId: target.agentId }, "could not post the skipped review check");
588
+ }
589
+ }
590
+ }
460
591
  /**
461
592
  * CI finished on a pull request's head: re-runs, once per head, each review
462
593
  * that published only a COMMENT while CI there was still running or had not
@@ -492,6 +623,16 @@ async function rereviewAfterCi(deps, host, event, prNumber, reviewerLinks) {
492
623
  // Only reviewers still authorized are claimed, so a denied one keeps its chance for later.
493
624
  const allowed = await authorizedLinks(deps, event, reviewerLinks.filter((l) => waiting.some((r) => r.run.agentId === l.agentId)));
494
625
  const allowedIds = new Set(allowed.map((l) => l.agentId));
626
+ // Decided before the claim, so a re-review not started here is not used up.
627
+ const decision = await budgetDraftDecision(deps, host, event.repository, prNumber, event.headSha);
628
+ if (decision.kind === "wait") {
629
+ log.info({ repository: event.repository, prNumber, headSha: event.headSha, runId: decision.runId }, "CI finished: re-review held while the pull request's coding run is still running");
630
+ return [];
631
+ }
632
+ if (decision.kind === "skip") {
633
+ await postSkippedReviewChecks(deps, host, event.repository, prNumber, event.headSha, reviewTargets(allowed));
634
+ return [];
635
+ }
495
636
  // Claimed per row, so concurrent completions re-run each review only once.
496
637
  const agentIds = new Set();
497
638
  for (const row of waiting.filter((r) => allowedIds.has(r.run.agentId))) {
@@ -624,6 +765,22 @@ async function deferUntilCi(deps, host, key, links) {
624
765
  }
625
766
  return { startNow: [], runIds };
626
767
  }
768
+ /**
769
+ * Deferred rows whose pull request's coding run is still in flight (budgetDraftDecision `wait`):
770
+ * they now wait for that run, as for a delegating run (reason "request", leadRunId = the run),
771
+ * and are released when it finishes (startDeferredForRequest from its terminal hook, or the
772
+ * sweep). The run may have finished meanwhile, its release finding no row: released here then.
773
+ */
774
+ async function waitForPushingRun(deps, key, rows, runId) {
775
+ const where = { repository: key.repository, prNumber: key.prNumber, headSha: key.headSha };
776
+ await deps.db.deferredReview.updateMany({
777
+ where: { id: { in: rows.map((r) => r.id) } },
778
+ data: { reason: "request", leadRunId: runId },
779
+ });
780
+ log.info({ ...where, runId }, "deferred review held while the pull request's coding run is still running");
781
+ const run = await deps.db.run.findUnique({ where: { id: runId }, select: { status: true } });
782
+ return !run || !RUN_NOT_FINISHED.has(run.status) ? releaseRequestRows(deps, runId, "request") : [];
783
+ }
627
784
  /**
628
785
  * Starts deferred reviews for one PR head. The head must still be that sha,
629
786
  * open, and not a fork; otherwise every row is dropped (a newer push records
@@ -641,6 +798,9 @@ async function startDeferred(deps, host, key, rows, reviewerLinks, mode, reason)
641
798
  log.info({ ...where, state: head.state }, "deferred review dropped: the pull request moved on or closed");
642
799
  return [];
643
800
  }
801
+ const decision = await budgetDraftDecision(deps, host, key.repository, key.prNumber, key.headSha);
802
+ if (decision.kind === "wait")
803
+ return waitForPushingRun(deps, key, rows, decision.runId);
644
804
  const allowed = await authorizedLinks(deps, key, reviewerLinks.filter((l) => rows.some((r) => r.agentId === l.agentId)));
645
805
  const allowedIds = new Set(allowed.map((l) => l.agentId));
646
806
  const targets = [];
@@ -659,6 +819,10 @@ async function startDeferred(deps, host, key, rows, reviewerLinks, mode, reason)
659
819
  return [];
660
820
  log.info({ ...where, agentIds: targets.map((t) => t.agentId), reason }, "starting the deferred review");
661
821
  try {
822
+ if (decision.kind === "skip") {
823
+ await postSkippedReviewChecks(deps, host, key.repository, key.prNumber, key.headSha, targets);
824
+ return [];
825
+ }
662
826
  return await startReviews(deps, host, key.repository, key.prNumber, key.headSha, targets, true);
663
827
  }
664
828
  catch (err) {
@@ -809,13 +973,36 @@ export async function requestLeadRunId(db, prMarkerRunId, repository) {
809
973
  }
810
974
  /** Run statuses that mean the delegating run has not finished. */
811
975
  const RUN_NOT_FINISHED = new Set(["pending", "running"]);
976
+ /**
977
+ * The run a draft's review waits for while its coding run `pushingRunId` may still be pushing:
978
+ * that run's top-level lead while the lead is pending or running, else the coding run itself.
979
+ * A follow-up's lead is not the one requestLeadRunId finds (that walks up from the pull
980
+ * request's opening run), yet the review should still wait for the whole request (#259); and
981
+ * the lead's finalizer releases it outside every workflow step, where the coding run's own
982
+ * terminal hook, inside the lead's delegation step, could not start a review run.
983
+ */
984
+ async function pushingRunHold(db, pushingRunId) {
985
+ // UNION, not UNION ALL: a parentRunId cycle (never written, but not a constraint) can't recurse forever.
986
+ const rows = await db.$queryRaw `
987
+ WITH RECURSIVE up AS (
988
+ SELECT r."id", r."parentRunId", r."status"::text AS "status" FROM "Run" r WHERE r."id" = ${pushingRunId}
989
+ UNION
990
+ SELECT p."id", p."parentRunId", p."status"::text FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
991
+ )
992
+ SELECT u."id", u."status" FROM up u WHERE u."parentRunId" IS NULL LIMIT 1`;
993
+ const root = rows[0];
994
+ return root && root.id !== pushingRunId && RUN_NOT_FINISHED.has(root.status) ? root.id : pushingRunId;
995
+ }
812
996
  /**
813
997
  * pr_updated for a pull request a delegated coding run opened, while the
814
998
  * request's lead run is still running: records one DeferredReview row per
815
999
  * reviewer (reason "request", with or without waitForCi) and starts nothing;
816
1000
  * the lead's finalizer (startDeferredForRequest) or the sweep starts them.
817
1001
  * Returns null, to review as without it, for any other pull request, or when
818
- * the lead cannot be resolved or the deferral cannot be recorded.
1002
+ * the lead cannot be resolved or the deferral cannot be recorded. A draft whose
1003
+ * own coding run (root or continuation) is still in flight waits for that run
1004
+ * the same way: it may have pushed this head before recording whether it
1005
+ * stopped at its budget (budgetDraftDecision); its terminal hook releases them.
819
1006
  */
820
1007
  async function deferUntilRequest(deps, host, key, links,
821
1008
  /** The pull request's origin, read at most once per event (shared with the merge order check). */
@@ -828,6 +1015,15 @@ readOrigin) {
828
1015
  if (!origin.markerRunId)
829
1016
  return null;
830
1017
  leadRunId = await requestLeadRunId(deps.db, origin.markerRunId, key.repository);
1018
+ // A draft's own coding run still in flight may have pushed this head before recording its
1019
+ // result (a stop at its budget among them): wait for it the same way (budgetDraftDecision).
1020
+ if (!leadRunId && origin.draft === true) {
1021
+ const pushing = await pushingRunInFlight(deps.db, {
1022
+ markerRunId: origin.markerRunId,
1023
+ repository: key.repository,
1024
+ });
1025
+ leadRunId = pushing && (await pushingRunHold(deps.db, pushing));
1026
+ }
831
1027
  }
832
1028
  catch (err) {
833
1029
  log.warn({ err, repository: key.repository, prNumber: key.prNumber }, "could not read the pull request's delegating run; reviewing as usual");
@@ -1022,11 +1218,14 @@ export async function routeHostEvent(event, deps) {
1022
1218
  const budget = startBudget(BUNDLE_LOAD_DEADLINE_MS);
1023
1219
  let taskOverride;
1024
1220
  try {
1025
- const { concepts, complete } = await loadBundle(host, event, budget);
1221
+ const { bundlePath, warning } = await resolveKnowledgeLocation(() => readKnowledgeConfig(host, event, budget));
1222
+ if (warning)
1223
+ log.warn({ repository: event.repository, after: event.after }, warning);
1224
+ const { concepts, complete } = await loadBundle(host, event, budget, bundlePath);
1026
1225
  const scope = driftScope({
1027
1226
  changedPaths: event.changedPaths,
1028
1227
  changedPathsComplete: event.changedPathsComplete,
1029
- bundlePath: DEFAULT_KNOWLEDGE_BUNDLE_PATH,
1228
+ bundlePath,
1030
1229
  concepts,
1031
1230
  });
1032
1231
  // Only the concepts the merge affects are checked, and only against a bundle that was fully read.
@@ -1034,7 +1233,7 @@ export async function routeHostEvent(event, deps) {
1034
1233
  const citations = complete
1035
1234
  ? await verifyCitations(host, event, concepts.filter((c) => affected.has(c.path)), budget)
1036
1235
  : new Map();
1037
- taskOverride = mergeTaskText(event, scope, complete, citations);
1236
+ taskOverride = mergeTaskText(event, scope, complete, citations, bundlePath);
1038
1237
  }
1039
1238
  finally {
1040
1239
  budget.clear();
@@ -1101,7 +1300,15 @@ export async function routeHostEvent(event, deps) {
1101
1300
  const reviewers = reviewTargets(allowed.filter((l) => !l.waitForCi || startNow.has(l)));
1102
1301
  const runIds = [...deferral.runIds];
1103
1302
  if (reviewers.length > 0) {
1104
- runIds.push(...(await startReviews(deps, host, event.repository, event.prNumber, event.headSha, reviewers, true)));
1303
+ // A coding run still in flight was already waited for (deferUntilRequest); should
1304
+ // recording that have failed, the head is reviewed as usual.
1305
+ const decision = await budgetDraftDecision(deps, host, event.repository, event.prNumber, event.headSha, readOrigin);
1306
+ if (decision.kind === "skip") {
1307
+ await postSkippedReviewChecks(deps, host, event.repository, event.prNumber, event.headSha, reviewers);
1308
+ }
1309
+ else {
1310
+ runIds.push(...(await startReviews(deps, host, event.repository, event.prNumber, event.headSha, reviewers, true)));
1311
+ }
1105
1312
  }
1106
1313
  return { runIds, followUps };
1107
1314
  }
@@ -1109,11 +1316,16 @@ export async function routeHostEvent(event, deps) {
1109
1316
  if (reviewerLinks.length === 0)
1110
1317
  return none;
1111
1318
  const runIds = [];
1319
+ // CI going green may be the last thing a pull request waited for (#287); evaluated
1320
+ // after the response (a host read per PR could otherwise exceed the webhook timeout).
1321
+ const followUps = event.prNumbers.map((prNumber) => async () => {
1322
+ await maybeMarkReady({ db: deps.db, hosts: deps.hosts, log }, event.repository, prNumber, event.provider);
1323
+ });
1112
1324
  for (const prNumber of event.prNumbers) {
1113
1325
  runIds.push(...(await rereviewAfterCi(deps, host, event, prNumber, reviewerLinks)));
1114
1326
  runIds.push(...(await startDeferredAfterCi(deps, host, event, prNumber, reviewerLinks)));
1115
1327
  }
1116
- return { runIds, followUps: [] };
1328
+ return { runIds, followUps };
1117
1329
  }
1118
1330
  case "check_rerun": {
1119
1331
  const owners = reviewerLinks.filter((l) => l.checkName === event.checkName);
@@ -1136,12 +1348,15 @@ export async function routeHostEvent(event, deps) {
1136
1348
  const reviewCommand = event.isPullRequest && isReviewCommand(event.body, deps.mentionHandle);
1137
1349
  const responderLink = links.find((l) => l.access === "write" && l.triggers.includes("mention"));
1138
1350
  const candidates = reviewCommand ? reviewerLinks : responderLink ? [responderLink] : [];
1139
- if (candidates.length === 0)
1351
+ // Explanations off and nothing to start: say nothing, and skip the author lookup.
1352
+ if (candidates.length === 0 && deps.mentionExplanations === false)
1140
1353
  return none;
1141
1354
  // H5-3: a mention drives a write-capable agent holding its owner's
1142
1355
  // tools and secrets, so its author needs real push access to the
1143
1356
  // repository (author_association, checked upstream, is only a
1144
- // pre-filter). Checked by the author's immutable id.
1357
+ // pre-filter). Checked by the author's immutable id. Checked before
1358
+ // anything is said back: someone without write access gets no reply at
1359
+ // all, so a mention can never be used to probe what is linked here.
1145
1360
  const author = await deps.repoAccess.authorizeHostUser({
1146
1361
  provider: event.provider,
1147
1362
  repository: event.repository,
@@ -1150,15 +1365,54 @@ export async function routeHostEvent(event, deps) {
1150
1365
  });
1151
1366
  if (!author.ok) {
1152
1367
  log.info({ repository: event.repository, number: event.number, reason: author.reason, level: author.level }, "mention ignored: its author lacks write access");
1153
- return none;
1368
+ // Someone who can read the repository gets told why; a stranger on a public repository (GitHub reports `read` for everyone) learns nothing.
1369
+ if (author.reason !== "insufficient_permission" || !explainsRefusal(author.level, event)) {
1370
+ return none;
1371
+ }
1372
+ const refuse = async () => {
1373
+ await host.acknowledge(event.repository, event.comment, "refused").catch((err) => {
1374
+ log.warn({ err, repository: event.repository, number: event.number }, "could not add the reaction");
1375
+ });
1376
+ await host
1377
+ .comment(event.repository, {
1378
+ number: event.number,
1379
+ body: NO_WRITE_ACCESS_BODY,
1380
+ ...(event.replyToReviewCommentId ? { replyToReviewCommentId: event.replyToReviewCommentId } : {}),
1381
+ })
1382
+ .catch((err) => {
1383
+ log.warn({ err, repository: event.repository, number: event.number }, "could not post the refusal");
1384
+ });
1385
+ };
1386
+ return { runIds: [], followUps: [refuse] };
1154
1387
  }
1388
+ // The author may use wardby here, so tell them why nothing started
1389
+ // instead of leaving the mention unanswered.
1390
+ const decline = (reason) => {
1391
+ log.info({ repository: event.repository, number: event.number, reason }, "mention declined");
1392
+ if (deps.mentionExplanations === false)
1393
+ return none;
1394
+ const reply = async () => {
1395
+ await host
1396
+ .comment(event.repository, {
1397
+ number: event.number,
1398
+ body: mentionDeclinedBody(reason),
1399
+ ...(event.replyToReviewCommentId ? { replyToReviewCommentId: event.replyToReviewCommentId } : {}),
1400
+ })
1401
+ .catch((err) => {
1402
+ log.warn({ err, repository: event.repository, number: event.number }, "could not post the explanation");
1403
+ });
1404
+ };
1405
+ return { runIds: [], followUps: [reply] };
1406
+ };
1407
+ if (candidates.length === 0)
1408
+ return decline(reviewCommand ? "no_reviewer" : "no_responder");
1155
1409
  const allowed = await authorizedLinks(deps, event, candidates);
1156
1410
  if (allowed.length === 0)
1157
- return none;
1411
+ return decline("agent_not_authorized");
1158
1412
  if (reviewCommand) {
1159
1413
  const head = await host.pullRequestHead(event.repository, event.number);
1160
1414
  if (head.isFork || head.state !== "open")
1161
- return none;
1415
+ return decline("pull_request_not_reviewable");
1162
1416
  return {
1163
1417
  runIds: await startReviews(deps, host, event.repository, event.number, head.headSha, reviewTargets(allowed)),
1164
1418
  followUps: [react],
@@ -1183,9 +1437,15 @@ export async function routeHostEvent(event, deps) {
1183
1437
  return { runIds: [], followUps: [react, reply] };
1184
1438
  }
1185
1439
  // Seeded from the PR's validated marker run: the request it belongs to. Stored state only.
1186
- const siblings = event.isPullRequest && event.priorRunId
1187
- ? await openSiblings(deps.db, event.priorRunId, { repository: event.repository, number: event.number })
1188
- : [];
1440
+ // An issue mention is seeded from the issue's recorded pull requests instead.
1441
+ const siblings = event.isPullRequest
1442
+ ? event.priorRunId
1443
+ ? await openSiblings(deps.db, event.priorRunId, { repository: event.repository, number: event.number })
1444
+ : []
1445
+ : await openSiblingsForIssue(deps.db, {
1446
+ provider: "github",
1447
+ key: githubIssueKey(event.repository, event.number),
1448
+ });
1189
1449
  const dispatched = await dispatchRun({
1190
1450
  db: deps.db,
1191
1451
  executor: deps.executor,
@@ -1195,7 +1455,11 @@ export async function routeHostEvent(event, deps) {
1195
1455
  taskOverride: mentionTaskText(event, siblings),
1196
1456
  attribution: event.isPullRequest
1197
1457
  ? await linkedPullRequestAttribution(deps.db, deps.issueTrackers, { codeProvider: host.provider, repository: event.repository, number: event.number }, RESPONSE_PATH_SNAPSHOT_BUDGET)
1198
- : undefined,
1458
+ : // A mention on an issue is that issue's own run tree, like a Jira issue event's.
1459
+ {
1460
+ source: "issue_event",
1461
+ item: await resolveWorkItem(deps.db, deps.issueTrackers, "github", githubIssueKey(event.repository, event.number), RESPONSE_PATH_SNAPSHOT_BUDGET),
1462
+ },
1199
1463
  // Where to report, written with the run: even if this instance dies
1200
1464
  // before the follow-up below, the run's outcome still gets a comment.
1201
1465
  afterPersist: async (tx, run) => {
@@ -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 {};