@wardby/cli 0.6.0 → 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 (576) hide show
  1. package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
  2. package/dist/claude-coding-worker/driver.d.ts +21 -3
  3. package/dist/claude-coding-worker/driver.js +125 -17
  4. package/dist/claude-coding-worker/main.js +34 -6
  5. package/dist/claude-coding-worker/sdk.js +12 -1
  6. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  7. package/dist/claude-coding-worker/tool-socket.js +111 -0
  8. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  9. package/dist/claude-coding-worker/transcript.js +77 -0
  10. package/dist/cli-help.d.ts +1 -1
  11. package/dist/cli-help.js +1 -0
  12. package/dist/cli.js +24 -10
  13. package/dist/coding/continuation-wording.d.ts +35 -0
  14. package/dist/coding/continuation-wording.js +73 -0
  15. package/dist/coding/linked-issue-note.d.ts +23 -0
  16. package/dist/coding/linked-issue-note.js +47 -0
  17. package/dist/coding/merge-wording.d.ts +28 -0
  18. package/dist/coding/merge-wording.js +78 -0
  19. package/dist/coding/pr-description-note.d.ts +9 -0
  20. package/dist/coding/pr-description-note.js +32 -0
  21. package/dist/coding/profile.d.ts +46 -126
  22. package/dist/coding/profile.js +45 -4
  23. package/dist/coding/protected-path-wording.d.ts +8 -0
  24. package/dist/coding/protected-path-wording.js +1 -1
  25. package/dist/coding/protocol.d.ts +264 -346
  26. package/dist/coding/protocol.js +235 -12
  27. package/dist/coding/redact.d.ts +3 -0
  28. package/dist/coding/redact.js +12 -0
  29. package/dist/coding/registry/allowlist.d.ts +12 -0
  30. package/dist/coding/registry/allowlist.js +14 -1
  31. package/dist/coding/registry/audit-mode.d.ts +153 -0
  32. package/dist/coding/registry/audit-mode.js +304 -0
  33. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  34. package/dist/coding/registry/lockfile-shared.js +128 -0
  35. package/dist/coding/registry/lockfiles.js +1 -1
  36. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  37. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  38. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  39. package/dist/coding/registry/npm-lockfile.js +4 -6
  40. package/dist/coding/registry/npm.js +78 -8
  41. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  42. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  43. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  44. package/dist/coding/registry/pypi-plan.js +406 -0
  45. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  46. package/dist/coding/registry/pypi-requirements.js +155 -0
  47. package/dist/coding/registry/pypi.d.ts +3 -27
  48. package/dist/coding/registry/pypi.js +40 -154
  49. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  50. package/dist/coding/registry/refusal-hints.js +61 -0
  51. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  52. package/dist/coding/registry/refusal-wording.js +56 -0
  53. package/dist/coding/registry/report.d.ts +70 -8
  54. package/dist/coding/registry/report.js +112 -5
  55. package/dist/coding/registry/types.d.ts +58 -8
  56. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  57. package/dist/coding/registry/yarn-lockfile.js +367 -0
  58. package/dist/coding/services/catalog.d.ts +37 -351
  59. package/dist/coding/transcript/claude-code.d.ts +13 -0
  60. package/dist/coding/transcript/claude-code.js +273 -0
  61. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  62. package/dist/coding/transcript/download-protocol.js +18 -0
  63. package/dist/coding/transcript/format.d.ts +20 -0
  64. package/dist/coding/transcript/format.js +32 -0
  65. package/dist/coding/transcript/recorder.d.ts +51 -0
  66. package/dist/coding/transcript/recorder.js +225 -0
  67. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  68. package/dist/coding/transcript/resume/checkout.js +203 -0
  69. package/dist/coding/transcript/resume/command.d.ts +17 -0
  70. package/dist/coding/transcript/resume/command.js +176 -0
  71. package/dist/coding/transcript/resume/download.d.ts +20 -0
  72. package/dist/coding/transcript/resume/download.js +153 -0
  73. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  74. package/dist/coding/transcript/resume/launch.js +128 -0
  75. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  76. package/dist/coding/transcript/resume/session-file.js +79 -0
  77. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  78. package/dist/coding/transcript/resume/stand-in.js +49 -0
  79. package/dist/coding-worker/artifact.d.ts +8 -3
  80. package/dist/coding-worker/artifact.js +3 -1
  81. package/dist/coding-worker/debug-trace.d.ts +6 -5
  82. package/dist/coding-worker/debug-trace.js +13 -18
  83. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  84. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  85. package/dist/coding-worker/driver.d.ts +4 -3
  86. package/dist/coding-worker/driver.js +116 -38
  87. package/dist/coding-worker/errors.d.ts +1 -0
  88. package/dist/coding-worker/errors.js +32 -0
  89. package/dist/coding-worker/task-note.d.ts +11 -0
  90. package/dist/coding-worker/task-note.js +13 -0
  91. package/dist/coding-worker/types.d.ts +11 -0
  92. package/dist/config/dependency-cache.d.ts +23 -0
  93. package/dist/config/dependency-cache.js +32 -0
  94. package/dist/config/providers.d.ts +12 -3
  95. package/dist/config/providers.js +55 -5
  96. package/dist/config/test-simulators.d.ts +82 -0
  97. package/dist/config/test-simulators.js +305 -0
  98. package/dist/core/async-context.d.ts +2 -0
  99. package/dist/core/async-context.js +12 -0
  100. package/dist/core/budget-events.d.ts +108 -0
  101. package/dist/core/budget-events.js +346 -0
  102. package/dist/core/budget-groups.d.ts +50 -1
  103. package/dist/core/budget-groups.js +236 -27
  104. package/dist/core/budget-stopped-head.d.ts +46 -0
  105. package/dist/core/budget-stopped-head.js +81 -0
  106. package/dist/core/budget-topup.d.ts +51 -0
  107. package/dist/core/budget-topup.js +156 -0
  108. package/dist/core/budget-wording.d.ts +16 -2
  109. package/dist/core/budget-wording.js +40 -2
  110. package/dist/core/coding-queue.d.ts +2 -1
  111. package/dist/core/coding-queue.js +7 -0
  112. package/dist/core/cron.d.ts +19 -1
  113. package/dist/core/cron.js +17 -0
  114. package/dist/core/datastores.js +1 -1
  115. package/dist/core/deferred-coding.d.ts +14 -0
  116. package/dist/core/deferred-coding.js +62 -0
  117. package/dist/core/delegation-child.d.ts +25 -0
  118. package/dist/core/delegation-child.js +37 -0
  119. package/dist/core/dispatch.d.ts +42 -0
  120. package/dist/core/dispatch.js +131 -56
  121. package/dist/core/engine-native.js +1 -1
  122. package/dist/core/error-code.d.ts +38 -0
  123. package/dist/core/error-code.js +168 -0
  124. package/dist/core/grants.d.ts +19 -6
  125. package/dist/core/grants.js +55 -6
  126. package/dist/core/host-events.d.ts +18 -2
  127. package/dist/core/host-events.js +284 -24
  128. package/dist/core/host-status.d.ts +85 -3
  129. package/dist/core/host-status.js +298 -20
  130. package/dist/core/issue-bridge.d.ts +50 -6
  131. package/dist/core/issue-bridge.js +124 -33
  132. package/dist/core/issue-events.d.ts +1 -1
  133. package/dist/core/issue-events.js +4 -10
  134. package/dist/core/issue-status.d.ts +1 -1
  135. package/dist/core/issue-status.js +54 -26
  136. package/dist/core/logger.d.ts +5 -0
  137. package/dist/core/logger.js +14 -1
  138. package/dist/core/lost-run-children.d.ts +6 -0
  139. package/dist/core/lost-run-children.js +32 -0
  140. package/dist/core/mark-ready.d.ts +34 -0
  141. package/dist/core/mark-ready.js +152 -0
  142. package/dist/core/markdown-code.d.ts +8 -0
  143. package/dist/core/markdown-code.js +107 -0
  144. package/dist/core/memory-tools.js +7 -0
  145. package/dist/core/merge-order-check.d.ts +2 -1
  146. package/dist/core/merge-order-check.js +8 -1
  147. package/dist/core/notification-templates.d.ts +1 -7
  148. package/dist/core/notification-templates.js +36 -2
  149. package/dist/core/pull-request-state-sync.js +2 -2
  150. package/dist/core/reconciler.d.ts +4 -3
  151. package/dist/core/reconciler.js +8 -1
  152. package/dist/core/related-pull-requests.d.ts +11 -3
  153. package/dist/core/related-pull-requests.js +27 -14
  154. package/dist/core/reply-parts.d.ts +21 -0
  155. package/dist/core/reply-parts.js +73 -0
  156. package/dist/core/review-fix.d.ts +1 -1
  157. package/dist/core/review-fix.js +2 -1
  158. package/dist/core/review-host-checks.d.ts +1 -1
  159. package/dist/core/review-host-tools.d.ts +3 -0
  160. package/dist/core/review-host-tools.js +99 -13
  161. package/dist/core/review-reads.d.ts +55 -0
  162. package/dist/core/review-reads.js +233 -0
  163. package/dist/core/run-status.d.ts +12 -0
  164. package/dist/core/run-status.js +12 -0
  165. package/dist/core/runner.d.ts +80 -34
  166. package/dist/core/runner.js +439 -144
  167. package/dist/core/schedule-start.d.ts +12 -0
  168. package/dist/core/schedule-start.js +14 -0
  169. package/dist/core/secret-broker-config.d.ts +10 -74
  170. package/dist/core/secret-guard.d.ts +46 -0
  171. package/dist/core/secret-guard.js +104 -0
  172. package/dist/core/secret-guarded-stores.d.ts +12 -0
  173. package/dist/core/secret-guarded-stores.js +41 -0
  174. package/dist/core/secret-spans.d.ts +50 -0
  175. package/dist/core/secret-spans.js +94 -0
  176. package/dist/core/stop-run.d.ts +46 -0
  177. package/dist/core/stop-run.js +61 -0
  178. package/dist/core/workflow-events.d.ts +14 -2
  179. package/dist/core/workflow-events.js +4 -0
  180. package/dist/core/workflow-run-events.d.ts +5 -3
  181. package/dist/core/workflow-run-events.js +43 -8
  182. package/dist/core/zod-json-schema.d.ts +4 -0
  183. package/dist/core/zod-json-schema.js +39 -0
  184. package/dist/core/zod3-window.d.ts +35 -0
  185. package/dist/core/zod3-window.js +124 -0
  186. package/dist/generated/prisma/browser.d.ts +34 -3
  187. package/dist/generated/prisma/client.d.ts +34 -3
  188. package/dist/generated/prisma/commonInputTypes.d.ts +220 -60
  189. package/dist/generated/prisma/enums.d.ts +10 -0
  190. package/dist/generated/prisma/enums.js +8 -0
  191. package/dist/generated/prisma/internal/class.d.ts +44 -0
  192. package/dist/generated/prisma/internal/class.js +4 -4
  193. package/dist/generated/prisma/internal/prismaNamespace.d.ts +428 -9
  194. package/dist/generated/prisma/internal/prismaNamespace.js +92 -1
  195. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +95 -0
  196. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +92 -1
  197. package/dist/generated/prisma/models/Agent.d.ts +106 -8
  198. package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
  199. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +229 -1
  200. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  201. package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
  202. package/dist/generated/prisma/models/CodingRun.d.ts +1637 -1
  203. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  204. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  205. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  206. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  207. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
  208. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
  209. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  210. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  211. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  212. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  213. package/dist/generated/prisma/models/Run.d.ts +738 -2
  214. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  215. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  216. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  217. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  218. package/dist/generated/prisma/models.d.ts +4 -0
  219. package/dist/help-index.json +1320 -69
  220. package/dist/import/create.js +32 -3
  221. package/dist/import/neutral-schema.d.ts +50 -281
  222. package/dist/import/neutral-schema.js +5 -4
  223. package/dist/knowledge/check.d.ts +1 -1
  224. package/dist/knowledge/cli.d.ts +11 -1
  225. package/dist/knowledge/cli.js +37 -4
  226. package/dist/knowledge/concept.d.ts +3 -19
  227. package/dist/knowledge/location.d.ts +31 -0
  228. package/dist/knowledge/location.js +78 -0
  229. package/dist/mcp/auth/access.d.ts +10 -2
  230. package/dist/mcp/auth/access.js +15 -1
  231. package/dist/mcp/auth/ownership.d.ts +7 -7
  232. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  233. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  234. package/dist/mcp/host-events/github-ingress.d.ts +2 -0
  235. package/dist/mcp/host-events/github-ingress.js +2 -1
  236. package/dist/mcp/index.d.ts +6 -0
  237. package/dist/mcp/index.js +58 -10
  238. package/dist/mcp/server.d.ts +13 -0
  239. package/dist/mcp/server.js +33 -14
  240. package/dist/mcp/tools/agents.d.ts +4 -0
  241. package/dist/mcp/tools/agents.js +198 -16
  242. package/dist/mcp/tools/datastore.js +17 -8
  243. package/dist/mcp/tools/grants.js +9 -3
  244. package/dist/mcp/tools/memory.js +11 -1
  245. package/dist/mcp/tools/notification-channels.js +2 -2
  246. package/dist/mcp/tools/packages.d.ts +2 -0
  247. package/dist/mcp/tools/packages.js +195 -0
  248. package/dist/mcp/tools/repositories.js +18 -5
  249. package/dist/mcp/tools/run-access.d.ts +16 -0
  250. package/dist/mcp/tools/run-access.js +25 -0
  251. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  252. package/dist/mcp/tools/run-transcript-download.js +129 -0
  253. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  254. package/dist/mcp/tools/run-transcript.js +70 -0
  255. package/dist/mcp/tools/runs.js +34 -12
  256. package/dist/mcp/tools/scheduling.js +3 -1
  257. package/dist/mcp/tools/secret-elicitation-form.js +5 -0
  258. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  259. package/dist/mcp/tools/secret-elicitation-server.js +10 -61
  260. package/dist/mcp/tools/secrets.js +2 -2
  261. package/dist/mcp/tools/stop-run.d.ts +2 -0
  262. package/dist/mcp/tools/stop-run.js +82 -0
  263. package/dist/mcp/tools/subagents.js +2 -2
  264. package/dist/mcp/tools/tools.d.ts +1 -1
  265. package/dist/mcp/tools/tools.js +25 -9
  266. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  267. package/dist/mcp/transport/stdio-link-host.js +67 -0
  268. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  269. package/dist/mcp/transport/streamable-http.js +41 -1
  270. package/dist/native-worker/docker-launcher.d.ts +38 -2
  271. package/dist/native-worker/docker-launcher.js +65 -5
  272. package/dist/native-worker/gateway-server.d.ts +41 -3
  273. package/dist/native-worker/gateway-server.js +124 -27
  274. package/dist/native-worker/gateway.d.ts +27 -1
  275. package/dist/native-worker/gateway.js +70 -4
  276. package/dist/native-worker/http-server.d.ts +3 -1
  277. package/dist/native-worker/http-server.js +11 -7
  278. package/dist/native-worker/http-transport.js +1 -1
  279. package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
  280. package/dist/native-worker/kubernetes-launcher.js +43 -3
  281. package/dist/native-worker/launch.d.ts +18 -1
  282. package/dist/native-worker/launch.js +6 -1
  283. package/dist/native-worker/ledger.d.ts +18 -2
  284. package/dist/native-worker/ledger.js +57 -4
  285. package/dist/native-worker/loopback.js +3 -8
  286. package/dist/native-worker/main.d.ts +2 -1
  287. package/dist/native-worker/main.js +14 -3
  288. package/dist/native-worker/protocol.d.ts +129 -577
  289. package/dist/native-worker/protocol.js +47 -1
  290. package/dist/native-worker/sandbox-executor.d.ts +17 -2
  291. package/dist/native-worker/sandbox-executor.js +78 -4
  292. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  293. package/dist/native-worker/stderr-redaction.js +237 -0
  294. package/dist/native-worker/stdio.d.ts +1 -1
  295. package/dist/native-worker/stdio.js +6 -5
  296. package/dist/native-worker/warm-pool.d.ts +2 -2
  297. package/dist/native-worker/warm-pool.js +4 -4
  298. package/dist/native-worker/worker.js +28 -2
  299. package/dist/observability/metrics.js +6 -1
  300. package/dist/providers/auth/self-hosted.d.ts +1 -1
  301. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  302. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  303. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  304. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  305. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  306. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  307. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  308. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  309. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  310. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  311. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  312. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  313. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  314. package/dist/providers/coding-proxy/hold.js +86 -0
  315. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  316. package/dist/providers/coding-proxy/interrupted.js +104 -0
  317. package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
  318. package/dist/providers/coding-proxy/memory-ledger.js +84 -8
  319. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  320. package/dist/providers/coding-proxy/metering.js +27 -4
  321. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
  322. package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
  323. package/dist/providers/coding-proxy/proxy.d.ts +14 -1
  324. package/dist/providers/coding-proxy/proxy.js +166 -14
  325. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  326. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  327. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  328. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  329. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  330. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  331. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  332. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  333. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  334. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  335. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  336. package/dist/providers/coding-proxy/registry/service.js +579 -112
  337. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  338. package/dist/providers/coding-proxy/registry/store.js +54 -1
  339. package/dist/providers/coding-proxy/runtime.d.ts +4 -0
  340. package/dist/providers/coding-proxy/runtime.js +78 -16
  341. package/dist/providers/coding-proxy/server.d.ts +6 -1
  342. package/dist/providers/coding-proxy/server.js +45 -1
  343. package/dist/providers/coding-proxy/types.d.ts +65 -1
  344. package/dist/providers/datastore/types.d.ts +5 -0
  345. package/dist/providers/engine/types.d.ts +17 -2
  346. package/dist/providers/engine/types.js +17 -0
  347. package/dist/providers/executor/composition.d.ts +10 -3
  348. package/dist/providers/executor/composition.js +47 -7
  349. package/dist/providers/executor/container.d.ts +361 -8
  350. package/dist/providers/executor/container.js +1136 -91
  351. package/dist/providers/executor/dbos-status.d.ts +31 -0
  352. package/dist/providers/executor/dbos-status.js +64 -0
  353. package/dist/providers/executor/dbos.d.ts +50 -1
  354. package/dist/providers/executor/dbos.js +207 -20
  355. package/dist/providers/executor/deferred.d.ts +12 -24
  356. package/dist/providers/executor/deferred.js +10 -29
  357. package/dist/providers/executor/in-process.d.ts +9 -1
  358. package/dist/providers/executor/in-process.js +14 -4
  359. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  360. package/dist/providers/executor/linked-issue-reader.js +30 -0
  361. package/dist/providers/executor/routing.d.ts +2 -0
  362. package/dist/providers/executor/routing.js +4 -0
  363. package/dist/providers/executor/types.d.ts +13 -0
  364. package/dist/providers/index.d.ts +2 -1
  365. package/dist/providers/issue-tracker/types.d.ts +17 -0
  366. package/dist/providers/issue-tracker/types.js +39 -1
  367. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  368. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  369. package/dist/providers/jobs/docker-isolation.d.ts +8 -0
  370. package/dist/providers/jobs/docker-isolation.js +17 -0
  371. package/dist/providers/jobs/docker.d.ts +1 -0
  372. package/dist/providers/jobs/docker.js +27 -2
  373. package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
  374. package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
  375. package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
  376. package/dist/providers/jobs/kubernetes-api.js +10 -0
  377. package/dist/providers/jobs/kubernetes-client.js +10 -1
  378. package/dist/providers/jobs/kubernetes-isolation.d.ts +2 -0
  379. package/dist/providers/jobs/kubernetes-isolation.js +17 -1
  380. package/dist/providers/jobs/kubernetes.d.ts +6 -1
  381. package/dist/providers/jobs/kubernetes.js +105 -16
  382. package/dist/providers/jobs/types.d.ts +33 -0
  383. package/dist/providers/jobs/types.js +13 -1
  384. package/dist/providers/llm/anthropic.js +5 -1
  385. package/dist/providers/llm/bedrock.d.ts +0 -12
  386. package/dist/providers/llm/bedrock.js +4 -0
  387. package/dist/providers/llm/claude-messages.d.ts +3 -1
  388. package/dist/providers/llm/claude-messages.js +4 -1
  389. package/dist/providers/llm/claude-provider.d.ts +2 -2
  390. package/dist/providers/llm/claude-provider.js +2 -2
  391. package/dist/providers/llm/openai.d.ts +2 -2
  392. package/dist/providers/llm/openai.js +6 -2
  393. package/dist/providers/llm/routing.d.ts +2 -2
  394. package/dist/providers/llm/routing.js +2 -2
  395. package/dist/providers/llm/types.d.ts +12 -2
  396. package/dist/providers/review-host/github-events.d.ts +9 -1
  397. package/dist/providers/review-host/github-events.js +34 -12
  398. package/dist/providers/review-host/github.d.ts +29 -2
  399. package/dist/providers/review-host/github.js +224 -29
  400. package/dist/providers/review-host/local.d.ts +8 -4
  401. package/dist/providers/review-host/local.js +49 -31
  402. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  403. package/dist/providers/review-host/patch-pages.js +176 -0
  404. package/dist/providers/review-host/review-format.d.ts +19 -1
  405. package/dist/providers/review-host/review-format.js +38 -7
  406. package/dist/providers/review-host/types.d.ts +134 -2
  407. package/dist/providers/review-host/types.js +8 -0
  408. package/dist/providers/storage/gcs.d.ts +63 -0
  409. package/dist/providers/storage/gcs.js +69 -0
  410. package/dist/providers/storage/index.d.ts +15 -0
  411. package/dist/providers/storage/index.js +14 -0
  412. package/dist/providers/storage/local.d.ts +24 -0
  413. package/dist/providers/storage/local.js +92 -0
  414. package/dist/providers/storage/meter.d.ts +14 -0
  415. package/dist/providers/storage/meter.js +34 -0
  416. package/dist/providers/storage/s3.d.ts +41 -0
  417. package/dist/providers/storage/s3.js +107 -0
  418. package/dist/providers/storage/types.d.ts +37 -3
  419. package/dist/providers/storage/types.js +21 -4
  420. package/dist/providers/vcs/git.d.ts +33 -2
  421. package/dist/providers/vcs/git.js +324 -22
  422. package/dist/providers/vcs/github-remote.d.ts +26 -3
  423. package/dist/providers/vcs/github-remote.js +124 -14
  424. package/dist/providers/vcs/github.d.ts +214 -6
  425. package/dist/providers/vcs/github.js +447 -45
  426. package/dist/providers/vcs/index.js +8 -1
  427. package/dist/providers/vcs/pr-description.d.ts +127 -0
  428. package/dist/providers/vcs/pr-description.js +270 -0
  429. package/dist/providers/vcs/remote.d.ts +33 -1
  430. package/dist/providers/vcs/routing.d.ts +4 -2
  431. package/dist/providers/vcs/routing.js +6 -0
  432. package/dist/providers/vcs/types.d.ts +80 -3
  433. package/dist/quickstart/coding-seed.d.ts +14 -3
  434. package/dist/quickstart/coding-seed.js +213 -4
  435. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  436. package/dist/quickstart/reviewer-prompt.js +6 -6
  437. package/dist/quickstart-images.json +1 -1
  438. package/dist/sandbox/generated/zod.bundle.js +62 -1
  439. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  440. package/dist/sandbox/host-functions.d.ts +1 -0
  441. package/dist/sandbox/host-functions.js +6 -11
  442. package/dist/sandbox/secret-broker.js +3 -4
  443. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  444. package/dist/sandbox/zod-params.d.ts +37 -5
  445. package/dist/sandbox/zod-params.js +181 -26
  446. package/dist/serve.js +8 -1
  447. package/dist/viewer/api-schema.d.ts +349 -2627
  448. package/dist/viewer/api-schema.js +7 -0
  449. package/dist/viewer/build-schemas.js +6 -2
  450. package/dist/viewer/openapi.js +2 -4
  451. package/dist/wardby-bin.js +10 -0
  452. package/docs/agent-recipes.md +58 -20
  453. package/docs/code-review-agents.md +551 -41
  454. package/docs/coding-agent-setup.md +489 -7
  455. package/docs/coding-packages.md +1033 -90
  456. package/docs/coding-services.md +27 -12
  457. package/docs/coding-worker-byo-images.md +20 -0
  458. package/docs/coding-worker-isolation.md +105 -30
  459. package/docs/getting-started-gke.md +124 -137
  460. package/docs/getting-started-identity-provider.md +10 -1
  461. package/docs/getting-started.md +9 -0
  462. package/docs/jira-agents.md +17 -8
  463. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  464. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  465. package/docs/knowledge/delegation-admission-slots.md +52 -0
  466. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  467. package/docs/knowledge/import-rename-target.md +52 -0
  468. package/docs/knowledge/index.md +57 -0
  469. package/docs/knowledge/log.md +9 -0
  470. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  471. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  472. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  473. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  474. package/docs/knowledge/overview-cli.md +74 -0
  475. package/docs/knowledge/overview-coding-proxy.md +72 -0
  476. package/docs/knowledge/overview-coding.md +72 -0
  477. package/docs/knowledge/overview-config.md +60 -0
  478. package/docs/knowledge/overview-core.md +72 -0
  479. package/docs/knowledge/overview-deploy.md +83 -0
  480. package/docs/knowledge/overview-mcp.md +61 -0
  481. package/docs/knowledge/overview-prisma.md +72 -0
  482. package/docs/knowledge/overview-providers.md +89 -0
  483. package/docs/knowledge/overview-sandbox.md +83 -0
  484. package/docs/knowledge/overview-surfaces.md +83 -0
  485. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  486. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  487. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  488. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  489. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  490. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  491. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  492. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  493. package/docs/knowledge/warm-input-publication.md +30 -0
  494. package/docs/knowledge/workspace-staging-failure.md +54 -0
  495. package/docs/knowledge.md +54 -14
  496. package/docs/native-sandbox.md +119 -23
  497. package/docs/observability.md +4 -0
  498. package/docs/security-deployment.md +33 -2
  499. package/docs/slack-notifications.md +35 -19
  500. package/docs/tool-secrets.md +42 -10
  501. package/docs/viewer-api.openapi.yml +1 -1
  502. package/help/admin-viewer.md +24 -2
  503. package/help/architecture-agent.md +11 -6
  504. package/help/build-worker-image.md +3 -1
  505. package/help/builder-agent.md +19 -6
  506. package/help/code-review-agents.md +177 -6
  507. package/help/coding-packages.md +156 -6
  508. package/help/cost-attribution.md +9 -5
  509. package/help/creating-agents.md +14 -1
  510. package/help/dependency-cache.md +143 -0
  511. package/help/deploy-gke.md +15 -8
  512. package/help/errors/budget-exhausted.md +187 -0
  513. package/help/errors/budget-group-exhausted.md +5 -1
  514. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  515. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  516. package/help/errors/continuation-closed.md +9 -12
  517. package/help/errors/delegation-conflict.md +24 -0
  518. package/help/errors/file-list-truncated.md +45 -0
  519. package/help/errors/full-read-required.md +49 -0
  520. package/help/errors/github-account-not-allowed.md +4 -0
  521. package/help/errors/graph-incomplete.md +43 -0
  522. package/help/errors/graph-limit.md +43 -0
  523. package/help/errors/merge-conflict.md +49 -0
  524. package/help/errors/native-sandbox-gateway-error.md +20 -0
  525. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  526. package/help/errors/native-sandbox-worker-exited.md +3 -2
  527. package/help/errors/package-not-allowed-pending.md +52 -0
  528. package/help/errors/package-not-allowed.md +51 -0
  529. package/help/errors/package-refusals.md +43 -0
  530. package/help/errors/patch-cursor-malformed.md +31 -0
  531. package/help/errors/run-lost.md +39 -0
  532. package/help/errors/run-transcript-download.md +44 -0
  533. package/help/errors/secret-in-value.md +69 -0
  534. package/help/errors/target-merge.md +40 -0
  535. package/help/fix-merge-conflicts.md +73 -0
  536. package/help/github-app-setup.md +132 -0
  537. package/help/github.md +22 -0
  538. package/help/identity-and-access.md +2 -0
  539. package/help/jira.md +23 -6
  540. package/help/knowledge.md +16 -7
  541. package/help/local-repositories.md +1 -1
  542. package/help/low-power-mode.md +7 -1
  543. package/help/merge-order-check.md +5 -0
  544. package/help/native-capabilities.md +29 -1
  545. package/help/native-sandbox.md +15 -1
  546. package/help/operating-agents.md +5 -0
  547. package/help/package-audit-mode.md +91 -0
  548. package/help/related-pull-requests.md +10 -7
  549. package/help/resume-runs-locally.md +131 -0
  550. package/help/review-fix-rounds.md +33 -1
  551. package/help/sharing-agents.md +59 -0
  552. package/help/slack-notifications.md +19 -5
  553. package/help/status-comments.md +31 -0
  554. package/help/stop-run.md +58 -0
  555. package/help/troubleshooting/budgets.md +28 -0
  556. package/help/troubleshooting/coding-workers.md +78 -7
  557. package/package.json +17 -10
  558. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  559. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  560. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  561. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  562. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  563. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  564. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  565. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  566. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  567. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  568. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  569. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  570. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  571. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  572. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  573. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  574. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  575. package/prisma/schema.prisma +311 -97
  576. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -1,33 +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";
14
17
  import { dedupeKeys, emitWorkflowEvent } from "./workflow-events.js";
15
18
  const log = logger.child({ module: "issue-bridge" });
16
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
+ }
17
24
  /**
18
25
  * Makes sure the issue/PR pair has a row, without ever overwriting one: a new
19
26
  * row is "created"; an existing open one gets its url refreshed ("open"); a
20
27
  * merged or closed one is left alone ("settled"). A lost create race (P2002)
21
28
  * reads back the winner's row. "unknown" when the store could not be read.
22
29
  */
23
- async function ensurePair(db, input, pr) {
30
+ async function ensurePair(db, issue, pr) {
24
31
  const where = {
25
32
  codeProvider_repository_number_issueProvider_issueKey: {
26
33
  codeProvider: pr.codeProvider,
27
34
  repository: pr.repository,
28
35
  number: pr.number,
29
- issueProvider: input.issueProvider,
30
- issueKey: input.issueKey,
36
+ issueProvider: issue.provider,
37
+ issueKey: issue.key,
31
38
  },
32
39
  };
33
40
  try {
@@ -36,13 +43,13 @@ async function ensurePair(db, input, pr) {
36
43
  try {
37
44
  await db.issuePullRequest.create({
38
45
  data: {
39
- issueProvider: input.issueProvider,
40
- issueKey: input.issueKey,
46
+ issueProvider: issue.provider,
47
+ issueKey: issue.key,
41
48
  codeProvider: pr.codeProvider,
42
49
  repository: pr.repository,
43
50
  number: pr.number,
44
51
  url: pr.url,
45
- agentId: input.agentId,
52
+ agentId: pr.agentId,
46
53
  openedByRunId: pr.openedByRunId,
47
54
  },
48
55
  });
@@ -62,10 +69,98 @@ async function ensurePair(db, input, pr) {
62
69
  return "open";
63
70
  }
64
71
  catch (err) {
65
- 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");
66
73
  return "unknown";
67
74
  }
68
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
+ }
69
164
  /**
70
165
  * Returns sentences for the outcome comment (a refused status move); empty
71
166
  * when there is nothing to say. Safe to repeat (a retried completion): each
@@ -78,13 +173,13 @@ export async function recordPullRequests(db, tracker, input) {
78
173
  const notes = [];
79
174
  try {
80
175
  let newlyOpened = false;
81
- const opened = [];
82
- for (const pr of input.pullRequests) {
83
- const state = await ensurePair(db, input, pr);
84
- if (state === "created" && pr.outcome === "pull_request_opened") {
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];
181
+ if (state === "created" && pr.outcome === "pull_request_opened")
85
182
  newlyOpened = true;
86
- opened.push(pr);
87
- }
88
183
  if (state !== "created" && state !== "open")
89
184
  continue;
90
185
  try {
@@ -111,16 +206,7 @@ export async function recordPullRequests(db, tracker, input) {
111
206
  }
112
207
  }
113
208
  // Only pairs this call newly recorded, so a retried completion does not notify twice. Never throws.
114
- for (const pr of opened) {
115
- await emitWorkflowEvent({
116
- dedupeKey: dedupeKeys.prOpened(pr.codeProvider, pr.repository, pr.number),
117
- runId: pr.openedByRunId,
118
- agentId: input.agentId,
119
- workItem: { provider: input.issueProvider, key: input.issueKey },
120
- pullRequest: { codeProvider: pr.codeProvider, repository: pr.repository, number: pr.number },
121
- payload: { kind: "pr_opened", prLabel: `${pr.repository}#${pr.number}`, prUrl: pr.url, movedTo },
122
- });
123
- }
209
+ await emitNewlyOpened(issue, records, states, movedTo);
124
210
  }
125
211
  catch (err) {
126
212
  log.warn({ err, issueKey: input.issueKey }, "could not bridge the pull requests to the issue");
@@ -129,8 +215,9 @@ export async function recordPullRequests(db, tracker, input) {
129
215
  }
130
216
  /**
131
217
  * A pull request wardby recorded against an issue was merged or closed: marks
132
- * each still-open pair, and, where the agent's link to the issue's project is
133
- * 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
134
221
  * applies the link's onPullRequestMerged move). Only rows wardby wrote are
135
222
  * touched, matched by the host's own identity for the PR — nothing from the
136
223
  * PR's text. The row is claimed first (open → merged/closed), so a duplicate
@@ -139,11 +226,14 @@ export async function recordPullRequests(db, tracker, input) {
139
226
  * delivery is rolled back and redelivered; never throws after that.
140
227
  */
141
228
  export async function handlePullRequestClosed(db, trackers, pr) {
142
- if (!trackers)
143
- return;
144
229
  const where = { codeProvider: pr.codeProvider, repository: pr.repository, number: pr.number };
145
230
  // Not caught: nothing is claimed yet, and a throw rolls back the delivery so it is redelivered.
146
- 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
+ });
147
237
  for (const row of rows) {
148
238
  // Exactly once per claimed row, from the finally below, even when a later step throws: the row is no
149
239
  // longer open, so nothing would retry it. Never throws.
@@ -170,7 +260,8 @@ export async function handlePullRequestClosed(db, trackers, pr) {
170
260
  if (claimed.count === 0)
171
261
  continue;
172
262
  claimedRow = true;
173
- const tracker = trackers[row.issueProvider];
263
+ // A pair with no configured tracker (a GitHub issue's, say) is only marked.
264
+ const tracker = trackers?.[row.issueProvider];
174
265
  if (!tracker)
175
266
  continue;
176
267
  const link = await db.agentIssueProject.findUnique({
@@ -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,12 +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
7
  import { dedupeKeys, emitWorkflowEvent } from "./workflow-events.js";
8
8
  const log = logger.child({ module: "issue-events" });
9
9
  const MAX_TASK_BODY = 8000;
10
- const RUN_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
11
10
  /** Only admin-configured values (trigger labels, the target status) appear here: never free text from the actor. */
12
11
  function describeKind(event, kind, link) {
13
12
  switch (kind) {
@@ -45,14 +44,9 @@ export function issueTaskText(event, matched, issueUrl, link, openPrs = []) {
45
44
  "do not also post it with jira_comment; use jira_comment only for other issues or progress notes on long work.",
46
45
  ];
47
46
  // Control-plane data from stored rows (validated here), never issue text.
48
- const hinted = openPrs.filter((p) => RUN_ID_RE.test(p.openedByRunId));
49
- for (const pr of hinted) {
50
- sections.push(`This issue already has an open pull request wardby opened: ${pr.repository}#${pr.number} ` +
51
- `(https://github.com/${pr.repository}/pull/${pr.number}). ` +
52
- `To revise it, delegate with continuePriorRun set to exactly "${pr.openedByRunId}".`);
53
- }
54
- if (hinted.length > 0)
55
- sections.push(SIBLING_GUIDANCE);
47
+ const hints = openPullRequestHints(openPrs);
48
+ if (hints)
49
+ sections.push(hints);
56
50
  if (matched.includes("mention") && event.comment) {
57
51
  sections.push(`Request comment:\n${event.comment.body.slice(0, MAX_TASK_BODY)}`);
58
52
  }
@@ -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"]);
@@ -126,26 +126,6 @@ async function currentLink(db, runId, issueKey, provider) {
126
126
  });
127
127
  return link ? { agentId: run.agentId, ...link } : null;
128
128
  }
129
- /**
130
- * The coding runs (of `runIds`) that continued a pull request opened for a
131
- * different issue: their PR belongs to that issue, not this one. A continued
132
- * PR with no issue, or this same issue, is fine.
133
- */
134
- async function continuedForAnotherIssue(db, runIds, issue) {
135
- if (runIds.length === 0)
136
- return new Set();
137
- const rows = await db.codingRun.findMany({
138
- where: { runId: { in: runIds } },
139
- select: { runId: true, rootCodingRun: { select: { issueProvider: true, issueKey: true } } },
140
- });
141
- return new Set(rows
142
- .filter(({ rootCodingRun: root }) => {
143
- if (!root?.issueKey)
144
- return false;
145
- return root.issueKey !== issue.issueKey || root.issueProvider !== issue.provider;
146
- })
147
- .map((row) => row.runId));
148
- }
149
129
  export async function completeIssueStatus(db, run, trackers, opts = {}) {
150
130
  if (!trackers)
151
131
  return;
@@ -164,9 +144,10 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
164
144
  const writable = link?.access === "write";
165
145
  const project = projectOf(status.issueKey);
166
146
  let body;
147
+ let fullReply = null;
167
148
  if (writable) {
168
- const { pullRequests, failedChildren, budgetSentence } = await collectRunOutcome(db, run);
169
- 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 });
170
151
  for (const runId of foreign) {
171
152
  log.info({ runId: run.id, codingRunId: runId, issueKey: status.issueKey }, "not linking a pull request continued from another issue's run");
172
153
  }
@@ -191,9 +172,18 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
191
172
  pullRequests: bridged,
192
173
  })
193
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);
194
179
  const outcome = outcomeBody(run, "", pullRequests, failedChildren, {
195
180
  budgetSentence,
181
+ packageRefusals,
182
+ packageAudit,
183
+ noChanges,
184
+ fullReplyFollows: true,
196
185
  noPullRequestText: "Done.",
186
+ fromIssue: true,
197
187
  // One comment per request: this status comment carries the agent's answer.
198
188
  replyAsAnswer: true,
199
189
  });
@@ -221,12 +211,50 @@ export async function completeIssueStatus(db, run, trackers, opts = {}) {
221
211
  }
222
212
  // Unlinked or read-only with no status comment yet: complete the row
223
213
  // without posting; never create content where the agent may not write.
224
- 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
+ }
225
228
  }
226
229
  catch (err) {
227
230
  log.warn({ err, runId: run.id }, "could not complete the issue status comment");
228
231
  }
229
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
+ }
230
258
  export async function closeOrphanedIssueStatuses(db, trackers, now = new Date()) {
231
259
  const providers = Object.keys(trackers ?? {});
232
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>;