@wardby/cli 0.5.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (763) hide show
  1. package/.env.example +33 -0
  2. package/README.md +25 -14
  3. package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
  4. package/dist/claude-coding-worker/context.d.ts +22 -0
  5. package/dist/claude-coding-worker/context.js +92 -0
  6. package/dist/claude-coding-worker/driver.d.ts +27 -3
  7. package/dist/claude-coding-worker/driver.js +161 -20
  8. package/dist/claude-coding-worker/main.js +34 -6
  9. package/dist/claude-coding-worker/sdk.js +25 -5
  10. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  11. package/dist/claude-coding-worker/tool-socket.js +111 -0
  12. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  13. package/dist/claude-coding-worker/transcript.js +77 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +6 -2
  16. package/dist/cli-native-mode.d.ts +9 -0
  17. package/dist/cli-native-mode.js +20 -0
  18. package/dist/cli.d.ts +3 -1
  19. package/dist/cli.js +161 -11
  20. package/dist/coding/claude-context.d.ts +45 -0
  21. package/dist/coding/claude-context.js +434 -0
  22. package/dist/coding/continuation-wording.d.ts +35 -0
  23. package/dist/coding/continuation-wording.js +73 -0
  24. package/dist/coding/linked-issue-note.d.ts +23 -0
  25. package/dist/coding/linked-issue-note.js +47 -0
  26. package/dist/coding/merge-wording.d.ts +28 -0
  27. package/dist/coding/merge-wording.js +78 -0
  28. package/dist/coding/pr-description-note.d.ts +9 -0
  29. package/dist/coding/pr-description-note.js +32 -0
  30. package/dist/coding/profile.d.ts +50 -118
  31. package/dist/coding/profile.js +51 -4
  32. package/dist/coding/protected-path-wording.d.ts +8 -0
  33. package/dist/coding/protected-path-wording.js +1 -1
  34. package/dist/coding/protocol.d.ts +292 -270
  35. package/dist/coding/protocol.js +322 -15
  36. package/dist/coding/redact.d.ts +3 -0
  37. package/dist/coding/redact.js +12 -0
  38. package/dist/coding/registry/allowlist.d.ts +12 -0
  39. package/dist/coding/registry/allowlist.js +14 -1
  40. package/dist/coding/registry/audit-mode.d.ts +153 -0
  41. package/dist/coding/registry/audit-mode.js +304 -0
  42. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  43. package/dist/coding/registry/lockfile-shared.js +128 -0
  44. package/dist/coding/registry/lockfiles.js +1 -1
  45. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  46. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  47. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  48. package/dist/coding/registry/npm-lockfile.js +4 -6
  49. package/dist/coding/registry/npm.js +78 -8
  50. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  51. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  52. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  53. package/dist/coding/registry/pypi-plan.js +406 -0
  54. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  55. package/dist/coding/registry/pypi-requirements.js +155 -0
  56. package/dist/coding/registry/pypi.d.ts +3 -27
  57. package/dist/coding/registry/pypi.js +40 -154
  58. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  59. package/dist/coding/registry/refusal-hints.js +61 -0
  60. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  61. package/dist/coding/registry/refusal-wording.js +56 -0
  62. package/dist/coding/registry/report.d.ts +70 -8
  63. package/dist/coding/registry/report.js +112 -5
  64. package/dist/coding/registry/types.d.ts +58 -8
  65. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  66. package/dist/coding/registry/yarn-lockfile.js +367 -0
  67. package/dist/coding/services/catalog.d.ts +37 -351
  68. package/dist/coding/transcript/claude-code.d.ts +13 -0
  69. package/dist/coding/transcript/claude-code.js +273 -0
  70. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  71. package/dist/coding/transcript/download-protocol.js +18 -0
  72. package/dist/coding/transcript/format.d.ts +20 -0
  73. package/dist/coding/transcript/format.js +32 -0
  74. package/dist/coding/transcript/recorder.d.ts +51 -0
  75. package/dist/coding/transcript/recorder.js +225 -0
  76. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  77. package/dist/coding/transcript/resume/checkout.js +203 -0
  78. package/dist/coding/transcript/resume/command.d.ts +17 -0
  79. package/dist/coding/transcript/resume/command.js +176 -0
  80. package/dist/coding/transcript/resume/download.d.ts +20 -0
  81. package/dist/coding/transcript/resume/download.js +153 -0
  82. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  83. package/dist/coding/transcript/resume/launch.js +128 -0
  84. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  85. package/dist/coding/transcript/resume/session-file.js +79 -0
  86. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  87. package/dist/coding/transcript/resume/stand-in.js +49 -0
  88. package/dist/coding-worker/artifact.d.ts +16 -3
  89. package/dist/coding-worker/artifact.js +5 -3
  90. package/dist/coding-worker/debug-trace.d.ts +6 -5
  91. package/dist/coding-worker/debug-trace.js +13 -18
  92. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  93. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  94. package/dist/coding-worker/driver.d.ts +4 -3
  95. package/dist/coding-worker/driver.js +118 -38
  96. package/dist/coding-worker/errors.d.ts +1 -0
  97. package/dist/coding-worker/errors.js +32 -0
  98. package/dist/coding-worker/sdk.d.ts +6 -0
  99. package/dist/coding-worker/sdk.js +1 -0
  100. package/dist/coding-worker/skills.d.ts +23 -0
  101. package/dist/coding-worker/skills.js +117 -0
  102. package/dist/coding-worker/task-note.d.ts +11 -0
  103. package/dist/coding-worker/task-note.js +13 -0
  104. package/dist/coding-worker/types.d.ts +13 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/github-allowed-accounts.d.ts +15 -0
  108. package/dist/config/github-allowed-accounts.js +36 -0
  109. package/dist/config/low-power.d.ts +12 -0
  110. package/dist/config/low-power.js +18 -0
  111. package/dist/config/mobile.d.ts +12 -0
  112. package/dist/config/mobile.js +18 -0
  113. package/dist/config/providers.d.ts +65 -3
  114. package/dist/config/providers.js +147 -11
  115. package/dist/config/test-simulators.d.ts +82 -0
  116. package/dist/config/test-simulators.js +305 -0
  117. package/dist/core/async-context.d.ts +2 -0
  118. package/dist/core/async-context.js +12 -0
  119. package/dist/core/budget-events.d.ts +108 -0
  120. package/dist/core/budget-events.js +346 -0
  121. package/dist/core/budget-groups.d.ts +50 -1
  122. package/dist/core/budget-groups.js +236 -27
  123. package/dist/core/budget-stopped-head.d.ts +46 -0
  124. package/dist/core/budget-stopped-head.js +81 -0
  125. package/dist/core/budget-topup.d.ts +51 -0
  126. package/dist/core/budget-topup.js +156 -0
  127. package/dist/core/budget-wording.d.ts +16 -2
  128. package/dist/core/budget-wording.js +40 -2
  129. package/dist/core/coding-queue.d.ts +2 -1
  130. package/dist/core/coding-queue.js +7 -0
  131. package/dist/core/cron.d.ts +19 -1
  132. package/dist/core/cron.js +17 -0
  133. package/dist/core/datastores.js +1 -1
  134. package/dist/core/db.d.ts +16 -6
  135. package/dist/core/db.js +12 -10
  136. package/dist/core/deferred-coding.d.ts +14 -0
  137. package/dist/core/deferred-coding.js +62 -0
  138. package/dist/core/delegation-child.d.ts +25 -0
  139. package/dist/core/delegation-child.js +37 -0
  140. package/dist/core/dispatch.d.ts +53 -0
  141. package/dist/core/dispatch.js +167 -57
  142. package/dist/core/engine-native.js +10 -6
  143. package/dist/core/error-code.d.ts +38 -0
  144. package/dist/core/error-code.js +168 -0
  145. package/dist/core/grants.d.ts +19 -6
  146. package/dist/core/grants.js +55 -6
  147. package/dist/core/host-events.d.ts +67 -5
  148. package/dist/core/host-events.js +571 -37
  149. package/dist/core/host-status.d.ts +85 -3
  150. package/dist/core/host-status.js +298 -20
  151. package/dist/core/issue-bridge.d.ts +50 -6
  152. package/dist/core/issue-bridge.js +151 -20
  153. package/dist/core/issue-events.d.ts +1 -1
  154. package/dist/core/issue-events.js +16 -11
  155. package/dist/core/issue-status.d.ts +1 -1
  156. package/dist/core/issue-status.js +68 -29
  157. package/dist/core/logger.d.ts +5 -0
  158. package/dist/core/logger.js +14 -1
  159. package/dist/core/lost-run-children.d.ts +6 -0
  160. package/dist/core/lost-run-children.js +32 -0
  161. package/dist/core/mark-ready.d.ts +34 -0
  162. package/dist/core/mark-ready.js +152 -0
  163. package/dist/core/markdown-code.d.ts +8 -0
  164. package/dist/core/markdown-code.js +107 -0
  165. package/dist/core/memory-tools.js +7 -0
  166. package/dist/core/merge-order-check.d.ts +130 -0
  167. package/dist/core/merge-order-check.js +343 -0
  168. package/dist/core/notification-dispatcher.d.ts +70 -0
  169. package/dist/core/notification-dispatcher.js +368 -0
  170. package/dist/core/notification-templates.d.ts +19 -0
  171. package/dist/core/notification-templates.js +139 -0
  172. package/dist/core/notifications.d.ts +10 -0
  173. package/dist/core/notifications.js +38 -0
  174. package/dist/core/pg-auth.d.ts +22 -0
  175. package/dist/core/pg-auth.js +152 -0
  176. package/dist/core/power-composition.d.ts +16 -0
  177. package/dist/core/power-composition.js +37 -0
  178. package/dist/core/power-idle.d.ts +14 -0
  179. package/dist/core/power-idle.js +30 -0
  180. package/dist/core/power.d.ts +71 -0
  181. package/dist/core/power.js +202 -0
  182. package/dist/core/pull-request-state-sync.js +2 -2
  183. package/dist/core/reconciler.d.ts +8 -5
  184. package/dist/core/reconciler.js +37 -6
  185. package/dist/core/related-pull-requests.d.ts +59 -7
  186. package/dist/core/related-pull-requests.js +140 -25
  187. package/dist/core/reply-parts.d.ts +21 -0
  188. package/dist/core/reply-parts.js +73 -0
  189. package/dist/core/repo-access.d.ts +15 -0
  190. package/dist/core/repo-access.js +66 -0
  191. package/dist/core/review-fix.d.ts +38 -1
  192. package/dist/core/review-fix.js +209 -7
  193. package/dist/core/review-host-checks.d.ts +1 -1
  194. package/dist/core/review-host-tools.d.ts +23 -0
  195. package/dist/core/review-host-tools.js +156 -14
  196. package/dist/core/review-reads.d.ts +55 -0
  197. package/dist/core/review-reads.js +233 -0
  198. package/dist/core/run-status.d.ts +12 -0
  199. package/dist/core/run-status.js +12 -0
  200. package/dist/core/runner.d.ts +384 -5
  201. package/dist/core/runner.js +1244 -372
  202. package/dist/core/schedule-start.d.ts +12 -0
  203. package/dist/core/schedule-start.js +14 -0
  204. package/dist/core/secret-broker-config.d.ts +39 -0
  205. package/dist/core/secret-broker-config.js +112 -0
  206. package/dist/core/secret-guard.d.ts +46 -0
  207. package/dist/core/secret-guard.js +104 -0
  208. package/dist/core/secret-guarded-stores.d.ts +12 -0
  209. package/dist/core/secret-guarded-stores.js +41 -0
  210. package/dist/core/secret-spans.d.ts +50 -0
  211. package/dist/core/secret-spans.js +94 -0
  212. package/dist/core/secrets.d.ts +39 -4
  213. package/dist/core/secrets.js +148 -40
  214. package/dist/core/stop-run.d.ts +46 -0
  215. package/dist/core/stop-run.js +61 -0
  216. package/dist/core/workflow-event-recorder.d.ts +14 -0
  217. package/dist/core/workflow-event-recorder.js +120 -0
  218. package/dist/core/workflow-events.d.ts +94 -0
  219. package/dist/core/workflow-events.js +48 -0
  220. package/dist/core/workflow-run-events.d.ts +18 -0
  221. package/dist/core/workflow-run-events.js +75 -0
  222. package/dist/core/zod-json-schema.d.ts +4 -0
  223. package/dist/core/zod-json-schema.js +39 -0
  224. package/dist/core/zod3-window.d.ts +35 -0
  225. package/dist/core/zod3-window.js +124 -0
  226. package/dist/generated/prisma/browser.d.ts +92 -3
  227. package/dist/generated/prisma/client.d.ts +92 -3
  228. package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
  229. package/dist/generated/prisma/enums.d.ts +37 -0
  230. package/dist/generated/prisma/enums.js +31 -0
  231. package/dist/generated/prisma/internal/class.d.ts +132 -0
  232. package/dist/generated/prisma/internal/class.js +4 -4
  233. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
  234. package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
  235. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
  236. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
  237. package/dist/generated/prisma/models/Agent.d.ts +464 -7
  238. package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
  239. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -1
  240. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  241. package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
  242. package/dist/generated/prisma/models/CodingRun.d.ts +1841 -1
  243. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  244. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  245. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  246. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  247. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  248. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1713 -0
  249. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  250. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
  251. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  252. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  253. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  254. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  255. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  256. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  257. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  258. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  259. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  260. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  261. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  262. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  263. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  264. package/dist/generated/prisma/models/Run.d.ts +1619 -58
  265. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  266. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  267. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  268. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  269. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  270. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  271. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  272. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  273. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  274. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  275. package/dist/generated/prisma/models.d.ts +12 -0
  276. package/dist/help/build.js +4 -2
  277. package/dist/help/catalog.d.ts +1 -1
  278. package/dist/help/catalog.js +31 -6
  279. package/dist/help-index.json +2584 -146
  280. package/dist/import/create.js +49 -3
  281. package/dist/import/neutral-schema.d.ts +50 -277
  282. package/dist/import/neutral-schema.js +7 -4
  283. package/dist/knowledge/check.d.ts +1 -1
  284. package/dist/knowledge/cli.d.ts +11 -1
  285. package/dist/knowledge/cli.js +37 -4
  286. package/dist/knowledge/concept.d.ts +3 -19
  287. package/dist/knowledge/location.d.ts +31 -0
  288. package/dist/knowledge/location.js +78 -0
  289. package/dist/mcp/auth/access.d.ts +11 -2
  290. package/dist/mcp/auth/access.js +15 -1
  291. package/dist/mcp/auth/ownership.d.ts +7 -7
  292. package/dist/mcp/auth/repo-authorization.js +14 -0
  293. package/dist/mcp/auth/resource-server.d.ts +2 -1
  294. package/dist/mcp/auth/resource-server.js +7 -2
  295. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  296. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  297. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  298. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  299. package/dist/mcp/context.d.ts +6 -0
  300. package/dist/mcp/host-events/github-ingress.d.ts +25 -1
  301. package/dist/mcp/host-events/github-ingress.js +70 -1
  302. package/dist/mcp/index.d.ts +19 -0
  303. package/dist/mcp/index.js +117 -20
  304. package/dist/mcp/server.d.ts +13 -0
  305. package/dist/mcp/server.js +33 -14
  306. package/dist/mcp/tools/agents.d.ts +4 -0
  307. package/dist/mcp/tools/agents.js +277 -24
  308. package/dist/mcp/tools/datastore.js +17 -8
  309. package/dist/mcp/tools/grants.js +9 -3
  310. package/dist/mcp/tools/memory.js +11 -1
  311. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  312. package/dist/mcp/tools/notification-channels.js +293 -0
  313. package/dist/mcp/tools/packages.d.ts +2 -0
  314. package/dist/mcp/tools/packages.js +195 -0
  315. package/dist/mcp/tools/power.d.ts +2 -0
  316. package/dist/mcp/tools/power.js +77 -0
  317. package/dist/mcp/tools/repositories.js +18 -5
  318. package/dist/mcp/tools/run-access.d.ts +16 -0
  319. package/dist/mcp/tools/run-access.js +25 -0
  320. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  321. package/dist/mcp/tools/run-transcript-download.js +129 -0
  322. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  323. package/dist/mcp/tools/run-transcript.js +70 -0
  324. package/dist/mcp/tools/runs.d.ts +0 -6
  325. package/dist/mcp/tools/runs.js +41 -14
  326. package/dist/mcp/tools/scheduling.js +3 -1
  327. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  328. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  329. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  330. package/dist/mcp/tools/secret-elicitation-form.js +205 -10
  331. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  332. package/dist/mcp/tools/secret-elicitation-server.js +10 -54
  333. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  334. package/dist/mcp/tools/secret-elicitation.js +110 -12
  335. package/dist/mcp/tools/secrets.js +186 -9
  336. package/dist/mcp/tools/stop-run.d.ts +2 -0
  337. package/dist/mcp/tools/stop-run.js +82 -0
  338. package/dist/mcp/tools/subagents.js +2 -2
  339. package/dist/mcp/tools/tools.d.ts +2 -2
  340. package/dist/mcp/tools/tools.js +47 -11
  341. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  342. package/dist/mcp/transport/stdio-link-host.js +67 -0
  343. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  344. package/dist/mcp/transport/streamable-http.js +41 -1
  345. package/dist/native-worker/composition.d.ts +23 -0
  346. package/dist/native-worker/composition.js +77 -0
  347. package/dist/native-worker/docker-isolation.d.ts +65 -0
  348. package/dist/native-worker/docker-isolation.js +183 -0
  349. package/dist/native-worker/docker-launcher.d.ts +110 -0
  350. package/dist/native-worker/docker-launcher.js +297 -0
  351. package/dist/native-worker/gateway-server.d.ts +77 -0
  352. package/dist/native-worker/gateway-server.js +412 -0
  353. package/dist/native-worker/gateway.d.ts +70 -0
  354. package/dist/native-worker/gateway.js +263 -0
  355. package/dist/native-worker/http-server.d.ts +24 -0
  356. package/dist/native-worker/http-server.js +113 -0
  357. package/dist/native-worker/http-transport.d.ts +17 -0
  358. package/dist/native-worker/http-transport.js +88 -0
  359. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  360. package/dist/native-worker/kubernetes-isolation.js +218 -0
  361. package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
  362. package/dist/native-worker/kubernetes-launcher.js +375 -0
  363. package/dist/native-worker/launch.d.ts +62 -0
  364. package/dist/native-worker/launch.js +49 -0
  365. package/dist/native-worker/ledger.d.ts +125 -0
  366. package/dist/native-worker/ledger.js +245 -0
  367. package/dist/native-worker/loopback.d.ts +12 -0
  368. package/dist/native-worker/loopback.js +44 -0
  369. package/dist/native-worker/main.d.ts +8 -0
  370. package/dist/native-worker/main.js +85 -0
  371. package/dist/native-worker/protocol.d.ts +296 -0
  372. package/dist/native-worker/protocol.js +246 -0
  373. package/dist/native-worker/sandbox-executor.d.ts +83 -0
  374. package/dist/native-worker/sandbox-executor.js +284 -0
  375. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  376. package/dist/native-worker/stderr-redaction.js +237 -0
  377. package/dist/native-worker/stdio.d.ts +29 -0
  378. package/dist/native-worker/stdio.js +189 -0
  379. package/dist/native-worker/warm-delivery.d.ts +16 -0
  380. package/dist/native-worker/warm-delivery.js +33 -0
  381. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  382. package/dist/native-worker/warm-pool-ledger.js +73 -0
  383. package/dist/native-worker/warm-pool.d.ts +107 -0
  384. package/dist/native-worker/warm-pool.js +283 -0
  385. package/dist/native-worker/worker.d.ts +17 -0
  386. package/dist/native-worker/worker.js +141 -0
  387. package/dist/observability/metrics.js +6 -1
  388. package/dist/providers/auth/authorization-server.d.ts +3 -0
  389. package/dist/providers/auth/index.js +2 -0
  390. package/dist/providers/auth/self-hosted.d.ts +14 -2
  391. package/dist/providers/auth/self-hosted.js +54 -4
  392. package/dist/providers/chat/fake.d.ts +46 -0
  393. package/dist/providers/chat/fake.js +39 -0
  394. package/dist/providers/chat/index.d.ts +4 -0
  395. package/dist/providers/chat/index.js +8 -0
  396. package/dist/providers/chat/slack.d.ts +37 -0
  397. package/dist/providers/chat/slack.js +105 -0
  398. package/dist/providers/chat/types.d.ts +42 -0
  399. package/dist/providers/chat/types.js +19 -0
  400. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  401. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  402. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  403. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  404. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  405. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  406. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  407. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  408. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  409. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  410. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  411. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  412. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  413. package/dist/providers/coding-proxy/hold.js +86 -0
  414. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  415. package/dist/providers/coding-proxy/interrupted.js +104 -0
  416. package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
  417. package/dist/providers/coding-proxy/memory-ledger.js +84 -8
  418. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  419. package/dist/providers/coding-proxy/metering.js +27 -4
  420. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
  421. package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
  422. package/dist/providers/coding-proxy/proxy.d.ts +14 -1
  423. package/dist/providers/coding-proxy/proxy.js +166 -14
  424. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  425. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  426. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  427. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  428. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  429. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  430. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  431. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  432. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  433. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  434. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  435. package/dist/providers/coding-proxy/registry/service.js +579 -112
  436. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  437. package/dist/providers/coding-proxy/registry/store.js +54 -1
  438. package/dist/providers/coding-proxy/runtime.d.ts +4 -0
  439. package/dist/providers/coding-proxy/runtime.js +78 -16
  440. package/dist/providers/coding-proxy/server.d.ts +6 -1
  441. package/dist/providers/coding-proxy/server.js +45 -1
  442. package/dist/providers/coding-proxy/types.d.ts +65 -1
  443. package/dist/providers/datastore/types.d.ts +5 -0
  444. package/dist/providers/engine/types.d.ts +36 -2
  445. package/dist/providers/engine/types.js +39 -0
  446. package/dist/providers/executor/composition.d.ts +31 -1
  447. package/dist/providers/executor/composition.js +81 -8
  448. package/dist/providers/executor/container.d.ts +385 -9
  449. package/dist/providers/executor/container.js +1234 -99
  450. package/dist/providers/executor/dbos-status.d.ts +31 -0
  451. package/dist/providers/executor/dbos-status.js +64 -0
  452. package/dist/providers/executor/dbos.d.ts +91 -0
  453. package/dist/providers/executor/dbos.js +319 -26
  454. package/dist/providers/executor/deferred.d.ts +44 -0
  455. package/dist/providers/executor/deferred.js +100 -0
  456. package/dist/providers/executor/in-process.d.ts +9 -1
  457. package/dist/providers/executor/in-process.js +14 -4
  458. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  459. package/dist/providers/executor/linked-issue-reader.js +30 -0
  460. package/dist/providers/executor/routing.d.ts +39 -10
  461. package/dist/providers/executor/routing.js +77 -32
  462. package/dist/providers/executor/types.d.ts +25 -0
  463. package/dist/providers/index.d.ts +2 -1
  464. package/dist/providers/issue-tracker/types.d.ts +17 -0
  465. package/dist/providers/issue-tracker/types.js +39 -1
  466. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  467. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  468. package/dist/providers/jobs/docker-isolation.d.ts +8 -0
  469. package/dist/providers/jobs/docker-isolation.js +17 -0
  470. package/dist/providers/jobs/docker.d.ts +1 -0
  471. package/dist/providers/jobs/docker.js +29 -4
  472. package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
  473. package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
  474. package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
  475. package/dist/providers/jobs/kubernetes-api.js +17 -0
  476. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  477. package/dist/providers/jobs/kubernetes-client.js +61 -3
  478. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  479. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  480. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  481. package/dist/providers/jobs/kubernetes-isolation.js +23 -1
  482. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  483. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  484. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  485. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  486. package/dist/providers/jobs/kubernetes.d.ts +42 -2
  487. package/dist/providers/jobs/kubernetes.js +178 -19
  488. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  489. package/dist/providers/jobs/metadata-probes.js +13 -0
  490. package/dist/providers/jobs/types.d.ts +42 -0
  491. package/dist/providers/jobs/types.js +13 -1
  492. package/dist/providers/llm/anthropic.js +5 -1
  493. package/dist/providers/llm/bedrock.d.ts +0 -12
  494. package/dist/providers/llm/bedrock.js +4 -0
  495. package/dist/providers/llm/claude-messages.d.ts +3 -1
  496. package/dist/providers/llm/claude-messages.js +4 -1
  497. package/dist/providers/llm/claude-provider.d.ts +2 -2
  498. package/dist/providers/llm/claude-provider.js +2 -2
  499. package/dist/providers/llm/openai.d.ts +2 -2
  500. package/dist/providers/llm/openai.js +6 -2
  501. package/dist/providers/llm/routing.d.ts +2 -2
  502. package/dist/providers/llm/routing.js +2 -2
  503. package/dist/providers/llm/types.d.ts +12 -2
  504. package/dist/providers/review-host/github-events.d.ts +9 -1
  505. package/dist/providers/review-host/github-events.js +34 -12
  506. package/dist/providers/review-host/github.d.ts +39 -2
  507. package/dist/providers/review-host/github.js +274 -29
  508. package/dist/providers/review-host/local.d.ts +8 -4
  509. package/dist/providers/review-host/local.js +49 -31
  510. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  511. package/dist/providers/review-host/patch-pages.js +176 -0
  512. package/dist/providers/review-host/review-format.d.ts +19 -1
  513. package/dist/providers/review-host/review-format.js +38 -7
  514. package/dist/providers/review-host/types.d.ts +157 -2
  515. package/dist/providers/review-host/types.js +8 -0
  516. package/dist/providers/storage/gcs.d.ts +63 -0
  517. package/dist/providers/storage/gcs.js +69 -0
  518. package/dist/providers/storage/index.d.ts +15 -0
  519. package/dist/providers/storage/index.js +14 -0
  520. package/dist/providers/storage/local.d.ts +24 -0
  521. package/dist/providers/storage/local.js +92 -0
  522. package/dist/providers/storage/meter.d.ts +14 -0
  523. package/dist/providers/storage/meter.js +34 -0
  524. package/dist/providers/storage/s3.d.ts +41 -0
  525. package/dist/providers/storage/s3.js +107 -0
  526. package/dist/providers/storage/types.d.ts +37 -3
  527. package/dist/providers/storage/types.js +21 -4
  528. package/dist/providers/vcs/git.d.ts +33 -2
  529. package/dist/providers/vcs/git.js +324 -22
  530. package/dist/providers/vcs/github-remote.d.ts +26 -3
  531. package/dist/providers/vcs/github-remote.js +124 -14
  532. package/dist/providers/vcs/github.d.ts +246 -12
  533. package/dist/providers/vcs/github.js +521 -61
  534. package/dist/providers/vcs/index.js +8 -1
  535. package/dist/providers/vcs/pr-description.d.ts +127 -0
  536. package/dist/providers/vcs/pr-description.js +270 -0
  537. package/dist/providers/vcs/remote.d.ts +33 -1
  538. package/dist/providers/vcs/routing.d.ts +4 -2
  539. package/dist/providers/vcs/routing.js +6 -0
  540. package/dist/providers/vcs/types.d.ts +80 -3
  541. package/dist/quickstart/coding-seed.d.ts +21 -3
  542. package/dist/quickstart/coding-seed.js +283 -3
  543. package/dist/quickstart/images.d.ts +2 -0
  544. package/dist/quickstart/images.js +7 -1
  545. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  546. package/dist/quickstart/reviewer-prompt.js +6 -6
  547. package/dist/quickstart-images.json +1 -1
  548. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  549. package/dist/sandbox/brokered-fetch.js +37 -0
  550. package/dist/sandbox/generated/zod.bundle.js +62 -1
  551. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  552. package/dist/sandbox/host-functions.d.ts +35 -0
  553. package/dist/sandbox/host-functions.js +150 -91
  554. package/dist/sandbox/prelude.js +7 -1
  555. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  556. package/dist/sandbox/run-in-sandbox.js +28 -10
  557. package/dist/sandbox/safe-fetch.d.ts +2 -0
  558. package/dist/sandbox/safe-fetch.js +3 -1
  559. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  560. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  561. package/dist/sandbox/secret-broker.d.ts +34 -0
  562. package/dist/sandbox/secret-broker.js +161 -0
  563. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  564. package/dist/sandbox/user-tool.d.ts +14 -0
  565. package/dist/sandbox/user-tool.js +32 -0
  566. package/dist/sandbox/zod-params.d.ts +37 -5
  567. package/dist/sandbox/zod-params.js +181 -26
  568. package/dist/serve.js +25 -0
  569. package/dist/viewer/api-schema.d.ts +372 -2454
  570. package/dist/viewer/api-schema.js +29 -0
  571. package/dist/viewer/build-schemas.js +10 -3
  572. package/dist/viewer/event-bus.d.ts +6 -0
  573. package/dist/viewer/event-bus.js +16 -7
  574. package/dist/viewer/graph.d.ts +5 -2
  575. package/dist/viewer/graph.js +7 -2
  576. package/dist/viewer/http.d.ts +0 -1
  577. package/dist/viewer/http.js +2 -2
  578. package/dist/viewer/infra.js +25 -2
  579. package/dist/viewer/limits.d.ts +4 -0
  580. package/dist/viewer/limits.js +4 -0
  581. package/dist/viewer/openapi.d.ts +15 -0
  582. package/dist/viewer/openapi.js +170 -0
  583. package/dist/wardby-bin.js +10 -0
  584. package/docs/README.md +7 -0
  585. package/docs/agent-recipes.md +114 -27
  586. package/docs/architecture-runtime.md +16 -1
  587. package/docs/code-review-agents.md +689 -45
  588. package/docs/coding-agent-setup.md +602 -12
  589. package/docs/coding-packages.md +1037 -92
  590. package/docs/coding-services.md +30 -13
  591. package/docs/coding-worker-byo-images.md +218 -6
  592. package/docs/coding-worker-isolation.md +173 -44
  593. package/docs/getting-started-gke.md +332 -129
  594. package/docs/getting-started-identity-provider.md +31 -11
  595. package/docs/getting-started.md +14 -4
  596. package/docs/jira-agents.md +22 -9
  597. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  598. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  599. package/docs/knowledge/delegation-admission-slots.md +52 -0
  600. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  601. package/docs/knowledge/import-rename-target.md +52 -0
  602. package/docs/knowledge/index.md +57 -0
  603. package/docs/knowledge/log.md +9 -0
  604. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  605. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  606. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  607. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  608. package/docs/knowledge/overview-cli.md +74 -0
  609. package/docs/knowledge/overview-coding-proxy.md +72 -0
  610. package/docs/knowledge/overview-coding.md +72 -0
  611. package/docs/knowledge/overview-config.md +60 -0
  612. package/docs/knowledge/overview-core.md +72 -0
  613. package/docs/knowledge/overview-deploy.md +83 -0
  614. package/docs/knowledge/overview-mcp.md +61 -0
  615. package/docs/knowledge/overview-prisma.md +72 -0
  616. package/docs/knowledge/overview-providers.md +89 -0
  617. package/docs/knowledge/overview-sandbox.md +83 -0
  618. package/docs/knowledge/overview-surfaces.md +83 -0
  619. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  620. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  621. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  622. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  623. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  624. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  625. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  626. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  627. package/docs/knowledge/warm-input-publication.md +30 -0
  628. package/docs/knowledge/workspace-staging-failure.md +54 -0
  629. package/docs/knowledge.md +54 -14
  630. package/docs/native-sandbox.md +731 -0
  631. package/docs/observability.md +4 -0
  632. package/docs/release-verification.md +9 -0
  633. package/docs/security-deployment.md +146 -14
  634. package/docs/slack-notifications.md +268 -0
  635. package/docs/tool-secrets.md +284 -0
  636. package/docs/viewer-api.md +46 -5
  637. package/docs/viewer-api.openapi.yml +1404 -0
  638. package/help/admin-viewer.md +29 -3
  639. package/help/agent-recipes.md +27 -0
  640. package/help/architecture-agent.md +11 -6
  641. package/help/brokered-secrets.md +79 -0
  642. package/help/build-claude-code-image.md +131 -0
  643. package/help/build-worker-image.md +6 -7
  644. package/help/builder-agent.md +19 -6
  645. package/help/code-review-agents.md +243 -10
  646. package/help/coding-packages.md +156 -6
  647. package/help/cost-attribution.md +9 -5
  648. package/help/creating-agents.md +14 -1
  649. package/help/dependency-cache.md +143 -0
  650. package/help/deploy-gke.md +23 -9
  651. package/help/deployment-targets.md +25 -14
  652. package/help/errors/budget-exhausted.md +187 -0
  653. package/help/errors/budget-group-exhausted.md +5 -1
  654. package/help/errors/coding-provider-not-configured.md +2 -2
  655. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  656. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  657. package/help/errors/continuation-closed.md +9 -12
  658. package/help/errors/database-auth-invalid.md +28 -0
  659. package/help/errors/delegation-conflict.md +24 -0
  660. package/help/errors/file-list-truncated.md +45 -0
  661. package/help/errors/full-read-required.md +49 -0
  662. package/help/errors/github-account-not-allowed.md +29 -0
  663. package/help/errors/graph-incomplete.md +43 -0
  664. package/help/errors/graph-limit.md +43 -0
  665. package/help/errors/low-power-disabled.md +29 -0
  666. package/help/errors/low-power-scale-forbidden.md +35 -0
  667. package/help/errors/low-power-wake-timeout.md +30 -0
  668. package/help/errors/merge-conflict.md +49 -0
  669. package/help/errors/mobile-disabled.md +31 -0
  670. package/help/errors/native-sandbox-capacity.md +22 -0
  671. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  672. package/help/errors/native-sandbox-docker-failed.md +20 -0
  673. package/help/errors/native-sandbox-gateway-error.md +20 -0
  674. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  675. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  676. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  677. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  678. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  679. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  680. package/help/errors/native-sandbox-unavailable.md +19 -0
  681. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  682. package/help/errors/native-sandbox-worker-exited.md +21 -0
  683. package/help/errors/native-sandbox-worker-lost.md +20 -0
  684. package/help/errors/native-sandbox-worker-unready.md +22 -0
  685. package/help/errors/package-not-allowed-pending.md +52 -0
  686. package/help/errors/package-not-allowed.md +51 -0
  687. package/help/errors/package-refusals.md +43 -0
  688. package/help/errors/patch-cursor-malformed.md +31 -0
  689. package/help/errors/run-lost.md +39 -0
  690. package/help/errors/run-transcript-download.md +44 -0
  691. package/help/errors/secret-broker-body-invalid.md +26 -0
  692. package/help/errors/secret-broker-changed.md +20 -0
  693. package/help/errors/secret-broker-config-invalid.md +30 -0
  694. package/help/errors/secret-broker-conflict.md +27 -0
  695. package/help/errors/secret-broker-destination-denied.md +28 -0
  696. package/help/errors/secret-broker-value-invalid.md +28 -0
  697. package/help/errors/secret-brokered.md +24 -0
  698. package/help/errors/secret-in-value.md +69 -0
  699. package/help/errors/secret-not-brokered.md +25 -0
  700. package/help/errors/slack-auth-failed.md +48 -0
  701. package/help/errors/slack-channel-unreachable.md +39 -0
  702. package/help/errors/slack-not-configured.md +33 -0
  703. package/help/errors/target-merge.md +40 -0
  704. package/help/fix-merge-conflicts.md +73 -0
  705. package/help/getting-started.md +4 -5
  706. package/help/github-app-setup.md +132 -0
  707. package/help/github.md +40 -1
  708. package/help/identity-and-access.md +7 -1
  709. package/help/jira.md +23 -6
  710. package/help/knowledge.md +16 -7
  711. package/help/local-repositories.md +3 -4
  712. package/help/low-power-mode.md +131 -0
  713. package/help/merge-order-check.md +122 -0
  714. package/help/mobile-app.md +54 -0
  715. package/help/native-capabilities.md +29 -1
  716. package/help/native-sandbox.md +150 -0
  717. package/help/observability.md +8 -0
  718. package/help/operating-agents.md +5 -0
  719. package/help/package-audit-mode.md +91 -0
  720. package/help/related-pull-requests.md +80 -16
  721. package/help/repo-instructions-and-skills.md +91 -0
  722. package/help/resume-runs-locally.md +131 -0
  723. package/help/review-fix-rounds.md +43 -1
  724. package/help/sharing-agents.md +59 -0
  725. package/help/slack-notifications.md +76 -0
  726. package/help/status-comments.md +31 -0
  727. package/help/stop-run.md +58 -0
  728. package/help/troubleshooting/budgets.md +28 -0
  729. package/help/troubleshooting/coding-workers.md +99 -7
  730. package/package.json +27 -13
  731. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  732. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  733. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  734. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  735. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  736. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  737. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  738. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  739. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  740. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  741. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  742. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  743. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  744. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  745. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  746. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  747. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  748. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  749. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  750. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  751. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  752. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  753. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  754. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  755. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  756. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  757. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  758. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  759. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  760. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  761. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  762. package/prisma/schema.prisma +631 -146
  763. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -1,11 +1,20 @@
1
1
  /**
2
2
  * The pull requests that came from the same request as a run: every pull
3
3
  * request opened by a coding run in the same top-level run tree (a lead that
4
- * fanned out to several repositories), plus any recorded for the same tracker
5
- * issue (IssuePullRequest). Control-plane rows only.
6
- * Ordered by when each pull request's coding run was dispatched: the lead's
7
- * delegation order (for a lead with parallelDelegations, the order its
8
- * concurrent delegations were admitted, ties broken by repository#number).
4
+ * fanned out to several repositories), plus any recorded for the same Jira or
5
+ * GitHub issue (IssuePullRequest). Control-plane rows only.
6
+ * Ordered by the delegating agent's declared merge order when any entry has
7
+ * one (CodingRun.mergeOrder; nulls last), then by when each pull request's
8
+ * coding run was dispatched: the lead's delegation order (for a lead with
9
+ * parallelDelegations, the order its concurrent delegations were admitted,
10
+ * ties broken by repository#number). A pull request's mergeOrder is the
11
+ * newest non-null value set by its opener run or any later continuation
12
+ * that acted on it, so a lead that re-delegates with a different order
13
+ * after the fact is reflected here. When mergeOrder is set on any entry,
14
+ * every truncation cap below this collector (MAX_RELATED_GROUP here,
15
+ * MAX_SIBLING_HINTS on openSiblingsOf, MAX_RELATED_PULL_REQUESTS on
16
+ * renderRelatedSection) drops entries with no order first, since they sort
17
+ * last.
9
18
  * A PR opened while siblings were still running lists only the PRs opened
10
19
  * before it; updateRelatedPullRequests rewrites every open PR of the set
11
20
  * with the full list when the lead run ends. Continuations join
@@ -13,7 +22,7 @@
13
22
  * pull requests brings the original request's tree, and the original request
14
23
  * brings every later follow-up tree that continued one of its pull requests.
15
24
  */
16
- import { type PrismaClient, type Run } from "#prisma";
25
+ import { type PrismaClient, type Run, type RunStatus } from "#prisma";
17
26
  import { type IssueTrackerRegistry } from "../providers/issue-tracker/types.js";
18
27
  import type { ReviewHostRegistry } from "../providers/review-host/types.js";
19
28
  /** Most pull requests a group holds; the description shows fewer (MAX_RELATED_PULL_REQUESTS). */
@@ -28,15 +37,50 @@ export interface RelatedPullRequest {
28
37
  openedByRunId: string;
29
38
  /** Only when stored (IssuePullRequest.state, kept current by pr_closed); otherwise unknown. */
30
39
  state?: StoredPullRequestState;
40
+ /**
41
+ * Step in the delegating agent's merge order (CodingRun.mergeOrder, 1-99):
42
+ * the newest non-null value among the coding run that opened it and its
43
+ * continuations. Absent when none of them set one, or when the entry only
44
+ * came from IssuePullRequest (no CodingRun to read it from).
45
+ */
46
+ mergeOrder?: number;
31
47
  }
32
48
  export interface RelatedPullRequestGroup {
33
49
  pullRequests: RelatedPullRequest[];
34
- /** The first well-formed issue seen on the group's coding runs. */
50
+ /** The first well-formed issue (a Jira or GitHub issue) seen on the group's coding runs. */
35
51
  issue?: {
36
52
  provider: string;
37
53
  key: string;
38
54
  };
55
+ /**
56
+ * The top-level run of every run tree the walk visited (the original
57
+ * request and each follow-up tree that continued one of its pull
58
+ * requests), with its status; absent when none was read. `codingRun` is
59
+ * true when the root is itself a coding run (a top-level follow-up such
60
+ * as a review fix round or an @mention picked up by a coding link), not a
61
+ * native lead agent's run.
62
+ */
63
+ roots?: Array<{
64
+ id: string;
65
+ status: RunStatus;
66
+ codingRun: boolean;
67
+ }>;
39
68
  }
69
+ /**
70
+ * The top-level run of the tree a pull request's marker run belongs to,
71
+ * whatever its status: the marker's coding run (a continuation resolves to
72
+ * its root coding run first), then up its parents. Null when the marker
73
+ * names no coding run, or one recorded for a different repository than
74
+ * `repository` (compared case-insensitively; omit it to skip the check).
75
+ * `isOpener` is true when that root is the opening coding run itself (the
76
+ * pull request was not delegated). The single place this walk and its
77
+ * repository guard live (requestLeadRunId, the merge order check).
78
+ */
79
+ export declare function runTreeRoot(db: Pick<PrismaClient, "$queryRaw">, markerRunId: string, repository?: string): Promise<{
80
+ id: string;
81
+ status: RunStatus;
82
+ isOpener: boolean;
83
+ } | null>;
40
84
  export declare function collectRelatedPullRequests(db: RelatedPullRequestsDb, runId: string,
41
85
  /**
42
86
  * Scopes the issue join (and any tree row explicitly tagged for a
@@ -67,6 +111,14 @@ export interface OpenSibling {
67
111
  number: number;
68
112
  openedByRunId: string;
69
113
  }
114
+ /**
115
+ * The continuation hint for a ticket (a GitHub or Jira issue) that already has
116
+ * open wardby pull requests: one sentence per pull request (up to
117
+ * MAX_SIBLING_HINTS), then SIBLING_GUIDANCE once, as paragraphs. Built from
118
+ * stored rows only, with the run id, repository and number re-validated and the
119
+ * link built here, never taken from issue text. Empty when nothing is hintable.
120
+ */
121
+ export declare function openPullRequestHints(prs: readonly OpenSibling[]): string;
70
122
  /**
71
123
  * The group's pull requests a follow-up may continue: stored state "open", or
72
124
  * no stored state yet (a same-tree sibling not recorded for an issue), minus
@@ -1,11 +1,20 @@
1
1
  /**
2
2
  * The pull requests that came from the same request as a run: every pull
3
3
  * request opened by a coding run in the same top-level run tree (a lead that
4
- * fanned out to several repositories), plus any recorded for the same tracker
5
- * issue (IssuePullRequest). Control-plane rows only.
6
- * Ordered by when each pull request's coding run was dispatched: the lead's
7
- * delegation order (for a lead with parallelDelegations, the order its
8
- * concurrent delegations were admitted, ties broken by repository#number).
4
+ * fanned out to several repositories), plus any recorded for the same Jira or
5
+ * GitHub issue (IssuePullRequest). Control-plane rows only.
6
+ * Ordered by the delegating agent's declared merge order when any entry has
7
+ * one (CodingRun.mergeOrder; nulls last), then by when each pull request's
8
+ * coding run was dispatched: the lead's delegation order (for a lead with
9
+ * parallelDelegations, the order its concurrent delegations were admitted,
10
+ * ties broken by repository#number). A pull request's mergeOrder is the
11
+ * newest non-null value set by its opener run or any later continuation
12
+ * that acted on it, so a lead that re-delegates with a different order
13
+ * after the fact is reflected here. When mergeOrder is set on any entry,
14
+ * every truncation cap below this collector (MAX_RELATED_GROUP here,
15
+ * MAX_SIBLING_HINTS on openSiblingsOf, MAX_RELATED_PULL_REQUESTS on
16
+ * renderRelatedSection) drops entries with no order first, since they sort
17
+ * last.
9
18
  * A PR opened while siblings were still running lists only the PRs opened
10
19
  * before it; updateRelatedPullRequests rewrites every open PR of the set
11
20
  * with the full list when the lead run ends. Continuations join
@@ -15,7 +24,7 @@
15
24
  */
16
25
  import { Prisma } from "#prisma";
17
26
  import { CODING_CODE_PROVIDER, normalizeGitHubRepository } from "../coding/protocol.js";
18
- import { ISSUE_KEY, ISSUE_TRACKER_NAMES, } from "../providers/issue-tracker/types.js";
27
+ import { issueReference, } from "../providers/issue-tracker/types.js";
19
28
  import { renderRelatedSection } from "../providers/vcs/github.js";
20
29
  import { pullRequestOutcome } from "./host-status.js";
21
30
  import { logger } from "./logger.js";
@@ -36,17 +45,50 @@ async function treeCodingRuns(db, seeds) {
36
45
  UNION
37
46
  SELECT p."id", p."parentRunId" FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
38
47
  ), down AS (
39
- SELECT u."id" FROM up u WHERE u."parentRunId" IS NULL
48
+ SELECT u."id", u."id" AS "rootId" FROM up u WHERE u."parentRunId" IS NULL
40
49
  UNION
41
- SELECT c."id" FROM "Run" c JOIN down d ON c."parentRunId" = d."id"
50
+ SELECT c."id", d."rootId" FROM "Run" c JOIN down d ON c."parentRunId" = d."id"
42
51
  )
43
- SELECT cr."runId", cr."result", cr."rootCodingRunId", cr."issueProvider", cr."issueKey", r."startedAt"
52
+ SELECT cr."runId", cr."result", cr."rootCodingRunId", cr."issueProvider", cr."issueKey", cr."mergeOrder", r."startedAt",
53
+ d."rootId" AS "treeRootId", root."status"::text AS "treeRootStatus",
54
+ EXISTS (SELECT 1 FROM "CodingRun" rc WHERE rc."runId" = d."rootId") AS "treeRootIsCodingRun"
44
55
  FROM "CodingRun" cr
45
56
  JOIN down d ON cr."runId" = d."id"
46
57
  JOIN "Run" r ON r."id" = cr."runId"
58
+ JOIN "Run" root ON root."id" = d."rootId"
47
59
  ORDER BY r."startedAt" ASC, cr."runId" ASC
48
60
  LIMIT ${MAX_TREE_CODING_RUNS}`;
49
61
  }
62
+ /**
63
+ * The top-level run of the tree a pull request's marker run belongs to,
64
+ * whatever its status: the marker's coding run (a continuation resolves to
65
+ * its root coding run first), then up its parents. Null when the marker
66
+ * names no coding run, or one recorded for a different repository than
67
+ * `repository` (compared case-insensitively; omit it to skip the check).
68
+ * `isOpener` is true when that root is the opening coding run itself (the
69
+ * pull request was not delegated). The single place this walk and its
70
+ * repository guard live (requestLeadRunId, the merge order check).
71
+ */
72
+ export async function runTreeRoot(db, markerRunId, repository) {
73
+ const repo = repository ?? null;
74
+ // UNION, not UNION ALL: a parentRunId cycle (never written, but not a constraint) can't recurse forever.
75
+ const rows = await db.$queryRaw `
76
+ WITH RECURSIVE opener AS (
77
+ SELECT COALESCE(cr."rootCodingRunId", cr."runId") AS "id"
78
+ FROM "CodingRun" cr
79
+ WHERE cr."runId" = ${markerRunId}
80
+ AND (${repo}::text IS NULL OR lower(cr."repository") = lower(${repo}::text))
81
+ ), up AS (
82
+ SELECT r."id", r."parentRunId", r."status"::text AS "status" FROM "Run" r JOIN opener o ON r."id" = o."id"
83
+ UNION
84
+ SELECT p."id", p."parentRunId", p."status"::text FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
85
+ )
86
+ SELECT u."id", u."status", u."id" IN (SELECT "id" FROM opener) AS "isOpener"
87
+ FROM up u
88
+ WHERE u."parentRunId" IS NULL
89
+ LIMIT 1`;
90
+ return rows[0] ?? null;
91
+ }
50
92
  function safeRepository(value) {
51
93
  try {
52
94
  return normalizeGitHubRepository(value);
@@ -120,7 +162,8 @@ onlyIssueKey) {
120
162
  let issue;
121
163
  const issues = new Map();
122
164
  for (const r of rows) {
123
- if (r.issueProvider && r.issueKey && ISSUE_KEY.test(r.issueKey)) {
165
+ // A Jira issue and a GitHub issue join the same way: by provider and key, each key re-validated.
166
+ if (r.issueProvider && r.issueKey && issueReference(r.issueProvider, r.issueKey)) {
124
167
  const found = { provider: r.issueProvider, key: r.issueKey };
125
168
  issue ??= found;
126
169
  issues.set(`${found.provider}\0${found.key}`, found);
@@ -139,9 +182,40 @@ onlyIssueKey) {
139
182
  number: pr.pullRequestNumber,
140
183
  openedAt: new Date(r.startedAt),
141
184
  openedByRunId: r.runId,
185
+ ...(r.mergeOrder != null ? { mergeOrder: r.mergeOrder } : {}),
142
186
  });
143
187
  }
144
188
  }
189
+ // A continuation dispatched with its own mergeOrder overrides the opener's
190
+ // (one that omits it stores the value it inherited), and it starts after
191
+ // the opener; the entry's mergeOrder is the newest non-null
192
+ // value among the opener row and every continuation row (same PR key,
193
+ // "pull_request_opened" or "pull_request_updated") found in the tree walk.
194
+ const newestMergeOrder = new Map();
195
+ for (const r of rows) {
196
+ if (r.mergeOrder == null)
197
+ continue;
198
+ const pr = pullRequestOutcome(r.result);
199
+ if (pr?.outcome !== "pull_request_opened" && pr?.outcome !== "pull_request_updated")
200
+ continue;
201
+ if (onlyIssueKey && r.issueKey && (r.issueProvider !== onlyIssueKey.provider || r.issueKey !== onlyIssueKey.key)) {
202
+ continue;
203
+ }
204
+ const repository = safeRepository(pr.repository);
205
+ if (!repository)
206
+ continue;
207
+ const key = keyOf(repository, pr.pullRequestNumber);
208
+ const startedAt = new Date(r.startedAt);
209
+ const current = newestMergeOrder.get(key);
210
+ if (!current || startedAt.getTime() >= current.startedAt.getTime()) {
211
+ newestMergeOrder.set(key, { startedAt, mergeOrder: r.mergeOrder });
212
+ }
213
+ }
214
+ for (const [key, entry] of byKey) {
215
+ const newest = newestMergeOrder.get(key);
216
+ if (newest)
217
+ entry.mergeOrder = newest.mergeOrder;
218
+ }
145
219
  const issueFilter = onlyIssueKey
146
220
  ? new Map([[`${onlyIssueKey.provider}\0${onlyIssueKey.key}`, onlyIssueKey]])
147
221
  : issues;
@@ -177,25 +251,29 @@ onlyIssueKey) {
177
251
  });
178
252
  }
179
253
  }
254
+ const order = (e) => e.mergeOrder ?? Number.POSITIVE_INFINITY;
180
255
  const pullRequests = [...byKey.values()]
181
- .sort((a, b) => a.openedAt.getTime() - b.openedAt.getTime() ||
256
+ .sort((a, b) => order(a) - order(b) ||
257
+ a.openedAt.getTime() - b.openedAt.getTime() ||
182
258
  `${a.repository}#${a.number}`.localeCompare(`${b.repository}#${b.number}`))
183
259
  .slice(0, MAX_RELATED_GROUP);
184
- return { pullRequests, ...(issue ? { issue } : {}) };
260
+ const roots = new Map();
261
+ for (const r of rows) {
262
+ if (r.treeRootId && r.treeRootStatus) {
263
+ roots.set(r.treeRootId, { status: r.treeRootStatus, codingRun: r.treeRootIsCodingRun === true });
264
+ }
265
+ }
266
+ return {
267
+ pullRequests,
268
+ ...(issue ? { issue } : {}),
269
+ ...(roots.size > 0 ? { roots: [...roots].map(([id, root]) => ({ id, ...root })) } : {}),
270
+ };
185
271
  }
186
272
  function issueFor(group, trackers) {
187
273
  if (!group.issue)
188
274
  return undefined;
189
- const provider = group.issue.provider;
190
- let url;
191
- try {
192
- url = trackers?.[provider]?.issueUrl(group.issue.key);
193
- }
194
- catch {
195
- url = undefined;
196
- }
197
- const trackerName = Object.hasOwn(ISSUE_TRACKER_NAMES, provider) ? ISSUE_TRACKER_NAMES[provider] : undefined;
198
- return { key: group.issue.key, ...(url ? { url } : {}), ...(trackerName ? { trackerName } : {}) };
275
+ const tracker = trackers?.[group.issue.provider];
276
+ return issueReference(group.issue.provider, group.issue.key, tracker ? (key) => tracker.issueUrl(key) : undefined);
199
277
  }
200
278
  /**
201
279
  * After a native run ends, rewrites the Related pull requests section on
@@ -219,7 +297,12 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
219
297
  for (const pr of group.pullRequests) {
220
298
  // A stored merged/closed state is final and such a PR is never edited: no host read.
221
299
  if (pr.state === "merged" || pr.state === "closed") {
222
- live.push({ repository: pr.repository, number: pr.number, state: pr.state });
300
+ live.push({
301
+ repository: pr.repository,
302
+ number: pr.number,
303
+ state: pr.state,
304
+ ...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
305
+ });
223
306
  continue;
224
307
  }
225
308
  try {
@@ -240,12 +323,23 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
240
323
  if (opener && opener.repository.toLowerCase() === pr.repository)
241
324
  markerRunId = origin.markerRunId;
242
325
  }
243
- live.push({ repository: pr.repository, number: pr.number, state, ...(markerRunId ? { markerRunId } : {}) });
326
+ live.push({
327
+ repository: pr.repository,
328
+ number: pr.number,
329
+ state,
330
+ ...(markerRunId ? { markerRunId } : {}),
331
+ ...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
332
+ });
244
333
  }
245
334
  catch (err) {
246
335
  log.warn({ err, runId: run.id, repository: pr.repository, number: pr.number }, "could not read a related pull request");
247
336
  // The stored state (issue-recorded PRs) is better than none; never edited without a live read.
248
- live.push({ repository: pr.repository, number: pr.number, ...(pr.state ? { state: pr.state } : {}) });
337
+ live.push({
338
+ repository: pr.repository,
339
+ number: pr.number,
340
+ ...(pr.state ? { state: pr.state } : {}),
341
+ ...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
342
+ });
249
343
  }
250
344
  }
251
345
  const issue = issueFor(group, trackers);
@@ -258,6 +352,7 @@ export async function updateRelatedPullRequests(db, run, hosts, trackers) {
258
352
  number: pr.number,
259
353
  ...(pr.state ? { state: pr.state } : {}),
260
354
  ...(pr === target ? { self: true } : {}),
355
+ ...(pr.mergeOrder !== undefined ? { mergeOrder: pr.mergeOrder } : {}),
261
356
  })),
262
357
  ...(issue ? { issue } : {}),
263
358
  });
@@ -286,6 +381,26 @@ const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
286
381
  export const SIBLING_GUIDANCE = "Continue the pull request you were asked about, and a listed open one only when the change requires it. " +
287
382
  "Never open a new pull request in a repository that already has an open pull request listed here. Merged or " +
288
383
  "closed pull requests are not listed: a change there needs a new pull request.";
384
+ const HINT_REPOSITORY = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
385
+ /**
386
+ * The continuation hint for a ticket (a GitHub or Jira issue) that already has
387
+ * open wardby pull requests: one sentence per pull request (up to
388
+ * MAX_SIBLING_HINTS), then SIBLING_GUIDANCE once, as paragraphs. Built from
389
+ * stored rows only, with the run id, repository and number re-validated and the
390
+ * link built here, never taken from issue text. Empty when nothing is hintable.
391
+ */
392
+ export function openPullRequestHints(prs) {
393
+ const lines = prs
394
+ .filter((p) => SAFE_RUN_ID.test(p.openedByRunId) &&
395
+ HINT_REPOSITORY.test(p.repository) &&
396
+ Number.isSafeInteger(p.number) &&
397
+ p.number > 0)
398
+ .slice(0, MAX_SIBLING_HINTS)
399
+ .map((p) => `This issue already has an open pull request wardby opened: ${p.repository}#${p.number} ` +
400
+ `(https://github.com/${p.repository}/pull/${p.number}). ` +
401
+ `To revise it, delegate with continuePriorRun set to exactly "${p.openedByRunId}".`);
402
+ return lines.length > 0 ? [...lines, SIBLING_GUIDANCE].join("\n\n") : "";
403
+ }
289
404
  /**
290
405
  * The group's pull requests a follow-up may continue: stored state "open", or
291
406
  * no stored state yet (a same-tree sibling not recorded for an issue), minus
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Splits an agent's reply into comment-sized parts, so a long reply (a plan
3
+ * posted to an issue, say) can go out in full as numbered follow-up comments
4
+ * instead of being cut. Pure: numbering, headers and the cut note are the
5
+ * caller's job; each part is a raw slice of the defused text.
6
+ */
7
+ export interface ReplyParts {
8
+ parts: string[];
9
+ truncated: boolean;
10
+ }
11
+ /** "@" + U+200B before a word character, so a quoted reply pings nobody. */
12
+ export declare function defuseMentions(text: string): string;
13
+ /**
14
+ * Splits `text` into at most `maxParts` parts of at most `maxChars` each, preferring Markdown heading
15
+ * boundaries, then blank lines (paragraphs), then single newlines, then a hard cut. Defuses @-mentions.
16
+ * Never splits inside a fenced code block unless one block alone exceeds maxChars (then hard-cut it).
17
+ */
18
+ export declare function splitReply(text: string, opts: {
19
+ maxChars: number;
20
+ maxParts: number;
21
+ }): ReplyParts;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Splits an agent's reply into comment-sized parts, so a long reply (a plan
3
+ * posted to an issue, say) can go out in full as numbered follow-up comments
4
+ * instead of being cut. Pure: numbering, headers and the cut note are the
5
+ * caller's job; each part is a raw slice of the defused text.
6
+ */
7
+ /** "@" + U+200B before a word character, so a quoted reply pings nobody. */
8
+ export function defuseMentions(text) {
9
+ return text.replace(/@(?=[\w-])/g, "@\u200b");
10
+ }
11
+ const FENCE_LINE = /^\s{0,3}(```|~~~)/;
12
+ const HEADING_LINE = /^#{1,6}\s/;
13
+ /** [open, close) offsets of each fenced code block; a cut strictly inside one would break it. */
14
+ function fenceSpans(text) {
15
+ const spans = [];
16
+ let open = -1;
17
+ let offset = 0;
18
+ for (const line of text.split("\n")) {
19
+ const end = offset + line.length + 1;
20
+ if (FENCE_LINE.test(line)) {
21
+ if (open < 0)
22
+ open = offset;
23
+ else {
24
+ spans.push([open, Math.min(end, text.length)]);
25
+ open = -1;
26
+ }
27
+ }
28
+ offset = end;
29
+ }
30
+ if (open >= 0)
31
+ spans.push([open, text.length]);
32
+ return spans;
33
+ }
34
+ /**
35
+ * Splits `text` into at most `maxParts` parts of at most `maxChars` each, preferring Markdown heading
36
+ * boundaries, then blank lines (paragraphs), then single newlines, then a hard cut. Defuses @-mentions.
37
+ * Never splits inside a fenced code block unless one block alone exceeds maxChars (then hard-cut it).
38
+ */
39
+ export function splitReply(text, opts) {
40
+ const maxChars = Math.max(1, Math.floor(opts.maxChars));
41
+ const maxParts = Math.max(1, Math.floor(opts.maxParts));
42
+ const defused = defuseMentions(text);
43
+ if (defused.length <= maxChars)
44
+ return { parts: [defused], truncated: false };
45
+ const spans = fenceSpans(defused);
46
+ const inFence = (at) => spans.some(([open, close]) => at > open && at < close);
47
+ const lineStart = (at) => defused[at - 1] === "\n";
48
+ const tiers = [
49
+ (at) => lineStart(at) && HEADING_LINE.test(defused.slice(at, at + 7)),
50
+ (at) => lineStart(at) && defused[at - 2] === "\n",
51
+ lineStart,
52
+ ];
53
+ /** The furthest cut in (start, start + maxChars]: the best tier wins, then a hard cut. */
54
+ const cutAfter = (start) => {
55
+ const limit = start + maxChars;
56
+ for (const tier of tiers) {
57
+ for (let at = limit; at > start; at--)
58
+ if (!inFence(at) && tier(at))
59
+ return at;
60
+ }
61
+ // A surrogate pair is one character to a reader; keep it whole when we can.
62
+ const code = defused.charCodeAt(limit - 1);
63
+ return code >= 0xd800 && code <= 0xdbff && limit - 1 > start ? limit - 1 : limit;
64
+ };
65
+ const parts = [];
66
+ let start = 0;
67
+ while (start < defused.length && parts.length < maxParts) {
68
+ const end = defused.length - start <= maxChars ? defused.length : cutAfter(start);
69
+ parts.push(defused.slice(start, end));
70
+ start = end;
71
+ }
72
+ return { parts, truncated: start < defused.length };
73
+ }
@@ -23,6 +23,8 @@ export declare const AUTHORIZED_VIA: readonly AuthorizedVia[];
23
23
  export type RepoAccessDenial = "owner_required" | "not_authorized" | "identity_not_linked" | "insufficient_permission" | "check_failed"
24
24
  /** A `local:` repository that is not inside the current trusted roots (LOCAL_REPO_ROOTS). */
25
25
  | "local_repo_not_allowed"
26
+ /** A GitHub repository whose owner is neither the App's owner nor in WARDBY_GITHUB_ALLOWED_ACCOUNTS. */
27
+ | "github_account_not_allowed"
26
28
  /** In-flight use only: the host was unreachable or rate-limited, even after one retry. */
27
29
  | "check_unavailable";
28
30
  export type RepoAccessDecision = {
@@ -78,6 +80,8 @@ export interface RepoAccessGate {
78
80
  required: HostPermission;
79
81
  fresh?: boolean;
80
82
  }): Promise<RepoAccessDecision>;
83
+ /** Is this repository's account served by the GitHub App? undefined = yes (or not a GitHub repository). */
84
+ checkAccount?(provider: string, repository: string): Promise<RepoAccessDecision | undefined>;
81
85
  }
82
86
  export interface RepoAccessGateOptions {
83
87
  db: Pick<PrismaClient, "hostIdentity">;
@@ -92,9 +96,20 @@ export interface RepoAccessGateOptions {
92
96
  /** Delay before the one retry of a transient error (default 1s). */
93
97
  retryDelayMs?: number;
94
98
  sleep?: (ms: number) => Promise<void>;
99
+ /**
100
+ * The served GitHub accounts (default: the App owner from hosts.github plus
101
+ * WARDBY_GITHUB_ALLOWED_ACCOUNTS). undefined = no GitHub App, nothing to guard.
102
+ * Throwing = fail closed.
103
+ */
104
+ trustedAccounts?: () => Promise<ReadonlySet<string> | undefined>;
95
105
  }
96
106
  /** 5xx, rate limits (403/429), and transport failures: worth one retry for a run already under way. */
97
107
  export declare function isTransientHostError(err: unknown): boolean;
108
+ /**
109
+ * Why the trusted GitHub accounts could not be read, as a fixed string: every
110
+ * branch returns a literal, so nothing from the error itself reaches a log.
111
+ */
112
+ export declare function trustedAccountsFailure(err: unknown): string;
98
113
  export declare const DEFAULT_REPO_ACCESS_TTL_MS: number;
99
114
  export declare function createRepoAccessGate(options: RepoAccessGateOptions): RepoAccessGate;
100
115
  /** Actionable, non-leaking text for a denial, for tool results and run errors. */
@@ -1,5 +1,6 @@
1
1
  import { HOST_PERMISSION_RANK, ReviewHostError, } from "../providers/review-host/types.js";
2
2
  import { LocalRepoError, isLocalRepository, loadLocalRepoRoots, resolveLocalRepository } from "../coding/local-repo.js";
3
+ import { githubAccountOf, isGitHubAccountAllowed, loadGitHubAllowedAccounts, trustedAccounts as trustedAccountSet, } from "../config/github-allowed-accounts.js";
3
4
  import { logger } from "./logger.js";
4
5
  const log = logger.child({ module: "repo-access" });
5
6
  export const AUTHORIZED_VIA = ["host_permission", "admin", "grandfathered", "local_root"];
@@ -20,6 +21,24 @@ export function isTransientHostError(err) {
20
21
  return false;
21
22
  return err.message === "github_api_unavailable" || /^github_api_error:(5\d\d|429|403)(:|$)/.test(err.message);
22
23
  }
24
+ /**
25
+ * Why the trusted GitHub accounts could not be read, as a fixed string: every
26
+ * branch returns a literal, so nothing from the error itself reaches a log.
27
+ */
28
+ export function trustedAccountsFailure(err) {
29
+ const message = err instanceof Error ? err.message : "";
30
+ if (message === "github_allowed_accounts_invalid")
31
+ return "github_allowed_accounts_invalid";
32
+ if (message === "github_api_unavailable")
33
+ return "github_api_unavailable";
34
+ if (message === "github_api_invalid_response")
35
+ return "github_api_invalid_response";
36
+ if (message === "github_app_private_key_invalid")
37
+ return "github_app_private_key_invalid";
38
+ if (message.startsWith("github_api_error:"))
39
+ return "github_api_error";
40
+ return "unexpected_error";
41
+ }
23
42
  const defaultLocalRoots = () => loadLocalRepoRoots(process.env).roots;
24
43
  export const DEFAULT_REPO_ACCESS_TTL_MS = 5 * 60_000;
25
44
  export function createRepoAccessGate(options) {
@@ -29,6 +48,41 @@ export function createRepoAccessGate(options) {
29
48
  const retryDelayMs = options.retryDelayMs ?? 1000;
30
49
  const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
31
50
  const cache = new Map();
51
+ const readTrusted = options.trustedAccounts ??
52
+ (async () => {
53
+ const host = options.hosts.github;
54
+ if (!host?.appOwnerLogin)
55
+ return undefined;
56
+ let extra;
57
+ try {
58
+ extra = loadGitHubAllowedAccounts();
59
+ }
60
+ catch {
61
+ // A fixed code: the parse error quotes the raw value, which must not reach the log.
62
+ throw new Error("github_allowed_accounts_invalid");
63
+ }
64
+ return trustedAccountSet(await host.appOwnerLogin(), extra);
65
+ });
66
+ /** A server-wide boundary, checked before any stamp, owner, or host call. Local repositories are exempt. */
67
+ async function checkAccount(provider, repository) {
68
+ if (provider !== "github" || isLocalRepository(repository))
69
+ return undefined;
70
+ let trusted;
71
+ try {
72
+ trusted = await readTrusted();
73
+ }
74
+ catch (err) {
75
+ // Only a fixed code is logged, never the error: its message may carry
76
+ // WARDBY_GITHUB_ALLOWED_ACCOUNTS's value (CodeQL js/clear-text-logging).
77
+ log.warn({ code: trustedAccountsFailure(err) }, "could not read the GitHub App's trusted accounts; denying");
78
+ return { ok: false, reason: "check_failed" };
79
+ }
80
+ if (trusted === undefined)
81
+ return undefined;
82
+ return isGitHubAccountAllowed(trusted, githubAccountOf(repository))
83
+ ? undefined
84
+ : { ok: false, reason: "github_account_not_allowed" };
85
+ }
32
86
  /** The user's level, or why it could not be determined (host missing or failing). */
33
87
  async function levelOf(provider, repository, user, fresh, retryTransient) {
34
88
  const key = `${provider}\u0000${repository}\u0000${user.id}`;
@@ -69,6 +123,9 @@ export function createRepoAccessGate(options) {
69
123
  return atLeast(level, required) ? { ok: true, level } : { ok: false, reason: "insufficient_permission", level };
70
124
  }
71
125
  async function authorizePrincipal(input) {
126
+ const denied = await checkAccount(input.provider, input.repository);
127
+ if (denied)
128
+ return denied;
72
129
  let identity;
73
130
  try {
74
131
  identity = await options.db.hostIdentity.findUnique({
@@ -108,6 +165,9 @@ export function createRepoAccessGate(options) {
108
165
  return { ok: false, reason: "local_repo_not_allowed" };
109
166
  }
110
167
  }
168
+ const denied = await checkAccount(input.provider, input.repository);
169
+ if (denied)
170
+ return denied;
111
171
  if (!input.ownerId)
112
172
  return { ok: false, reason: "owner_required" };
113
173
  if (input.authorizedVia === "admin" || input.authorizedVia === "grandfathered")
@@ -124,11 +184,15 @@ export function createRepoAccessGate(options) {
124
184
  },
125
185
  authorizePrincipal,
126
186
  async authorizeHostUser(input) {
187
+ const denied = await checkAccount(input.provider, input.repository);
188
+ if (denied)
189
+ return denied;
127
190
  const answer = await levelOf(input.provider, input.repository, input.user, input.fresh === true, false);
128
191
  if (!answer.ok)
129
192
  return unavailable(answer);
130
193
  return decide(answer.level, input.required);
131
194
  },
195
+ checkAccount,
132
196
  };
133
197
  }
134
198
  /** Actionable, non-leaking text for a denial, for tool results and run errors. */
@@ -144,6 +208,8 @@ export function describeDenial(decision, repository) {
144
208
  return `The agent owner's GitHub account has ${decision.level ?? "no"} access to ${repository}, which is not enough.`;
145
209
  case "local_repo_not_allowed":
146
210
  return `local_repo_not_allowed: ${repository} is not a git repository inside the configured local roots (LOCAL_REPO_ROOTS).`;
211
+ case "github_account_not_allowed":
212
+ return `github_account_not_allowed: ${repository} belongs to a GitHub account this server does not serve (the App's owner and WARDBY_GITHUB_ALLOWED_ACCOUNTS).`;
147
213
  case "check_failed":
148
214
  return `Could not verify access to ${repository} right now; try again later.`;
149
215
  case "check_unavailable":