@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,9 +1,10 @@
1
1
  import { type Readable } from "node:stream";
2
2
  import type { KubernetesJobConfig } from "../../config/providers.js";
3
+ import { type Power } from "../../core/power.js";
3
4
  import { type KubernetesApi } from "./kubernetes-api.js";
4
5
  import { type ServiceStateReporter } from "./service-state.js";
5
6
  import type { CodingProvider } from "../../coding/provider.js";
6
- import type { JobHandle, JobResult, JobSpec, JobStatus, WorkspaceJobLauncher } from "./types.js";
7
+ import { type JobHandle, type JobResult, type JobSpec, type JobStatus, type WorkspaceJobLauncher } from "./types.js";
7
8
  export interface KubernetesClusterInfo {
8
9
  /** The proxy Service's ClusterIP: the enforcement witness's address (8787 reachable, 8788 not). */
9
10
  proxyIp: string;
@@ -19,6 +20,11 @@ export interface KubernetesJobLauncherOptions {
19
20
  * the gate probes the address `provision` re-reads for that launch, not this memoized one.
20
21
  */
21
22
  preflight?: () => Promise<KubernetesClusterInfo | void>;
23
+ /**
24
+ * Low-power mode: `launch()` wakes the (possibly scaled-to-zero) coding proxy before its preflight,
25
+ * and `warmUp()` defers the preflight while the proxy is asleep. Default `DISABLED_POWER` (no-op).
26
+ */
27
+ power?: Power;
22
28
  now?: () => number;
23
29
  sleep?: (milliseconds: number) => Promise<void>;
24
30
  readyTimeoutMs?: number;
@@ -67,6 +73,7 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
67
73
  /** Timeout of one streak exec: ENFORCEMENT_BLOCKED_STREAK probes plus the gaps between them. */
68
74
  private readonly streakExecTimeoutMs;
69
75
  private preflightResult?;
76
+ private readonly power;
70
77
  constructor(options: KubernetesJobLauncherOptions);
71
78
  /**
72
79
  * Services run as native sidecars in the run pod (kubernetes-isolation.ts), for either provider:
@@ -94,7 +101,35 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
94
101
  materializeWorkspace(handle: JobHandle, destination: string): Promise<void>;
95
102
  stop(handle: JobHandle, _reason?: string): Promise<void>;
96
103
  remove(handle: JobHandle): Promise<void>;
97
- /** Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher. */
104
+ /**
105
+ * Low-power mode: whether the proxy is scaled to zero. A failed check is logged by code only (the
106
+ * leading reason code, else the error's class name -- never the raw message, which could carry
107
+ * cluster detail) and counts as awake, so warm-up runs the preflight as it would without the mode.
108
+ */
109
+ private proxyAsleep;
110
+ /**
111
+ * Starts the memoized cluster preflight (`runPreflight`) right away, instead of waiting for the
112
+ * first `launch()`, so a long-running server process's own start-up pays the preflight's cost (a
113
+ * canary pod on `kind`: ~20s) rather than that process's first coding run. Never throws: it only
114
+ * reports the outcome (an info line on success, a warning naming the failure code otherwise) so
115
+ * an operator sees a misconfigured cluster at boot. Any `launch()` already awaiting this same
116
+ * attempt (concurrent with this call) still fails exactly as it does today when the preflight
117
+ * failed — it shares the same rejected promise. But unlike a preflight `launch()` starts on its
118
+ * own, a start-up failure here is **not** left stuck memoized: a transient cluster problem at
119
+ * process start must not fail every coding run until restart, so the failed attempt is cleared
120
+ * (only if nothing has already started a newer one — compared by identity, never by state) and
121
+ * the *next* `launch()` runs the preflight fresh. A successful warm-up stays memoized as always.
122
+ * In low-power mode, while the proxy is asleep, warm-up is skipped (the memo stays unset) rather
123
+ * than waking the proxy only for the preflight; the first `launch()` wakes it and runs the preflight.
124
+ */
125
+ warmUp(): Promise<void>;
126
+ /**
127
+ * Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher —
128
+ * including its failure, which stays memoized and fails every subsequent `launch()` immediately,
129
+ * for a preflight `launch()` itself started (there was no `warmUp()`, or `warmUp()`'s own failed
130
+ * attempt was already cleared). `warmUp()` is the one caller that clears a failed attempt instead
131
+ * of leaving it stuck; see its own doc comment.
132
+ */
98
133
  private runPreflight;
99
134
  /**
100
135
  * Waits until the run's NetworkPolicy is enforced on this pod: the keeper (same network namespace
@@ -130,6 +165,10 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
130
165
  * must not open the gate at the initial proof either.
131
166
  */
132
167
  private waitForPolicyEnforcement;
168
+ /** True when `found` is a requeued record for this spec, which launch() replaces with a fresh one. */
169
+ private isRequeued;
170
+ /** Tells the operator once that a quota refused a pod while no quota is configured for the pre-launch check. */
171
+ private hintQuotaUnconfigured;
133
172
  private existingLaunch;
134
173
  private provision;
135
174
  private createIfMissing;
@@ -143,6 +182,7 @@ export declare class KubernetesJobLauncher implements WorkspaceJobLauncher {
143
182
  private refresh;
144
183
  /** Reads only a fixed diagnostic code from a failed worker's bounded log tail; never keeps anything else. */
145
184
  private readWorkerDiagnostic;
185
+ readTranscript(handle: JobHandle, maxBytes: number): Promise<string | undefined>;
146
186
  private readResultArtifact;
147
187
  /**
148
188
  * Streams the keeper's workspace through the strict extractor into `staging`.
@@ -29,10 +29,11 @@ import { finished } from "node:stream/promises";
29
29
  import { createHash } from "node:crypto";
30
30
  import { isIP } from "node:net";
31
31
  import { logger } from "../../core/logger.js";
32
- import { MAX_CODING_ARTIFACT_BYTES, MAX_DEBUG_TRACE_LINE_BYTES, parseCodingAgentOutputJson, } from "../../coding/protocol.js";
32
+ import { DISABLED_POWER, wakeTimeoutMs } from "../../core/power.js";
33
+ import { MAX_CODING_ARTIFACT_BYTES, MAX_CODING_INPUT_BYTES, MAX_DEBUG_TRACE_LINE_BYTES, parseCodingWorkerOutputJson, } from "../../coding/protocol.js";
33
34
  import { CODING_PROXY_DENY_PORT, CODING_PROXY_PORT } from "./docker-isolation.js";
34
35
  import { parseWorkerDiagnosticLine } from "./docker.js";
35
- import { KubernetesAlreadyExistsError, KubernetesConflictError } from "./kubernetes-api.js";
36
+ import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesQuotaExceededError, } from "./kubernetes-api.js";
36
37
  import { ENFORCEMENT_PROBE_DENY_REACHABLE, ENFORCEMENT_PROBE_PROVEN, ENFORCEMENT_PROBE_DENY_REFUSED, ENFORCEMENT_PROBE_PROXY_UNREACHABLE, KEEPER_CONTAINER, KEEPER_SEEDED_MARKER, KUBERNETES_ISOLATION_ERROR, STORAGE_ROOT, TOOL_RUNNER_CONTAINER, WORKER_CONTAINER, assertRunNetworkPolicyMatches, assertRunPodMatches, buildCapabilitySecret, buildRunNetworkPolicy, buildRunPod, enforcementStreakScript, kubernetesRunNames, kubernetesRunNamesForToken, runLabels, serviceContainerName, validateKubernetesSpec, } from "./kubernetes-isolation.js";
37
38
  import { claudeToolSetup } from "./claude-tool-setup.js";
38
39
  import { podQuotaUsage, quotaShortfall } from "./kubernetes-quota.js";
@@ -40,6 +41,7 @@ import { readProxyWitness } from "./kubernetes-witness.js";
40
41
  import { safeExtract } from "./safe-extract.js";
41
42
  import { reportServiceState, } from "./service-state.js";
42
43
  import { serviceUnreadyError } from "../../coding/services/wording.js";
44
+ import { JobCapacityError, } from "./types.js";
43
45
  import { replaceDirectoryFromStaging } from "./workspace-swap.js";
44
46
  import { collectExclusions, normalizeCollectExclusions, tarExcludeArgs, } from "../../coding/collect-exclude.js";
45
47
  const BACKEND = "kubernetes";
@@ -183,10 +185,22 @@ const TOKEN = /^[a-f0-9]{20}$/;
183
185
  const WORKSPACE_STORAGE = `${STORAGE_ROOT}/workspace`;
184
186
  const INPUT_STORAGE = `${STORAGE_ROOT}/input`;
185
187
  const RESULT_PATH = `${STORAGE_ROOT}/output/result.json`;
188
+ const TRANSCRIPT_PATH = `${STORAGE_ROOT}/output/session.jsonl`;
186
189
  /** Stands in for the proxy ClusterIP when building a pod only to count its resources. */
187
190
  const QUOTA_PROBE_PROXY_IP = "10.0.0.1";
191
+ /** A Kubernetes object name (RFC 1123 subdomain). */
192
+ const DNS_1123_NAME = /^[a-z0-9]([-a-z0-9.]{0,251}[a-z0-9])?$/;
188
193
  const kubernetesLog = logger.child({ module: "kubernetes-jobs" });
189
- const PHASES = new Set(["provisioning", "active", "succeeded", "failed", "stopped", "lost", "removed"]);
194
+ const PHASES = new Set([
195
+ "provisioning",
196
+ "requeued",
197
+ "active",
198
+ "succeeded",
199
+ "failed",
200
+ "stopped",
201
+ "lost",
202
+ "removed",
203
+ ]);
190
204
  const TERMINAL_PHASES = new Set(["succeeded", "failed", "stopped", "lost", "removed"]);
191
205
  // ---------------------------------------------------------------------------
192
206
  // Pure helpers: the lifecycle rules.
@@ -205,6 +219,8 @@ function statusFor(record) {
205
219
  switch (record.phase) {
206
220
  case "provisioning":
207
221
  return { state: "pending" };
222
+ case "requeued":
223
+ return { state: "pending", capacityRefused: true };
208
224
  case "active":
209
225
  return { state: "running" };
210
226
  case "succeeded":
@@ -386,9 +402,11 @@ export class KubernetesJobLauncher {
386
402
  /** Timeout of one streak exec: ENFORCEMENT_BLOCKED_STREAK probes plus the gaps between them. */
387
403
  streakExecTimeoutMs;
388
404
  preflightResult;
405
+ power;
389
406
  constructor(options) {
390
407
  this.options = options;
391
408
  this.api = options.api;
409
+ this.power = options.power ?? DISABLED_POWER;
392
410
  this.namespace = options.config.namespace;
393
411
  this.workspaceRoot = resolve(options.workspaceRoot);
394
412
  if (this.workspaceRoot === resolve("/"))
@@ -495,13 +513,19 @@ export class KubernetesJobLauncher {
495
513
  this.warn(`kubernetes_spec_rejected: ${error.message}`);
496
514
  throw error;
497
515
  }
516
+ // Low-power mode: the proxy may be scaled to zero; wake it before the preflight reads it. Guarded
517
+ // (not just a no-op await) so mode off keeps launch() joining an in-flight warm-up synchronously.
518
+ if (this.power.enabled) {
519
+ await this.power.ensureAwake("proxy", { timeoutMs: wakeTimeoutMs(this.readyTimeoutMs), runId: spec.runId });
520
+ }
498
521
  await this.runPreflight();
499
522
  const names = kubernetesRunNames(spec.runId);
500
523
  const handle = { backend: BACKEND, id: `${this.namespace}/${names.token}` };
501
524
  const specHash = stableSpecHash(spec);
502
525
  const existing = await this.readRecord(names);
503
- if (existing)
526
+ if (existing && !this.isRequeued(existing, specHash)) {
504
527
  return this.existingLaunch(existing.record, specHash, handle);
528
+ }
505
529
  const createdAt = this.now();
506
530
  const record = {
507
531
  schemaVersion: RECORD_SCHEMA_VERSION,
@@ -513,22 +537,54 @@ export class KubernetesJobLauncher {
513
537
  phase: "provisioning",
514
538
  collectExclude: spec.collectExclude ?? collectExclusions([]),
515
539
  };
516
- try {
517
- // The record is the idempotency fence before any other cluster side effect.
518
- await this.api.createConfigMap(this.namespace, this.recordConfigMap(names, record));
540
+ if (existing) {
541
+ // Replaces the requeued record; a conflict means another replica got there first.
542
+ try {
543
+ await this.api.replaceConfigMap(this.namespace, names.record, this.recordConfigMap(names, record, existing.resourceVersion));
544
+ }
545
+ catch (error) {
546
+ if (!(error instanceof KubernetesConflictError))
547
+ throw error;
548
+ const raced = await this.readRecord(names);
549
+ if (!raced)
550
+ throw error;
551
+ if (!this.isRequeued(raced, specHash))
552
+ return this.existingLaunch(raced.record, specHash, handle);
553
+ // Requeued again by the other replica (its attempt was refused too): start over from that record.
554
+ return this.launch(spec);
555
+ }
519
556
  }
520
- catch (error) {
521
- if (!(error instanceof KubernetesAlreadyExistsError))
522
- throw error;
523
- const raced = await this.readRecord(names);
524
- if (!raced)
525
- throw error;
526
- return this.existingLaunch(raced.record, specHash, handle);
557
+ else {
558
+ try {
559
+ // The record is the idempotency fence before any other cluster side effect. A quota refusing
560
+ // this create itself (a count/configmaps quota) is not a capacity refusal: it fails the run.
561
+ await this.api.createConfigMap(this.namespace, this.recordConfigMap(names, record));
562
+ }
563
+ catch (error) {
564
+ if (!(error instanceof KubernetesAlreadyExistsError))
565
+ throw error;
566
+ const raced = await this.readRecord(names);
567
+ if (!raced)
568
+ throw error;
569
+ if (!this.isRequeued(raced, specHash))
570
+ return this.existingLaunch(raced.record, specHash, handle);
571
+ // Another replica requeued it between our read and create: start over from the requeued record.
572
+ return this.launch(spec);
573
+ }
527
574
  }
528
575
  try {
529
576
  await this.provision(spec, names, record);
530
577
  }
531
578
  catch (error) {
579
+ if (error instanceof KubernetesQuotaExceededError) {
580
+ // Capacity, not failure: leave a record a later launch() provisions afresh.
581
+ await this.updateRecord(names, () => ({ phase: "requeued" })).catch(() => undefined);
582
+ await this.cleanupRun(names, 0);
583
+ this.hintQuotaUnconfigured(error.quotaName);
584
+ throw new JobCapacityError("kubernetes_quota_exceeded: the namespace ResourceQuota has no room for this run", {
585
+ cause: error,
586
+ });
587
+ }
532
588
  // Record the failure before deleting the pod, so a replica that observes "no pod" in between
533
589
  // can't record `lost` first and have this more specific outcome dropped.
534
590
  await this.updateRecord(names, () => ({
@@ -618,7 +674,69 @@ export class KubernetesJobLauncher {
618
674
  }
619
675
  // -------------------------------------------------------------------------
620
676
  // Launch
621
- /** Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher. */
677
+ /**
678
+ * Low-power mode: whether the proxy is scaled to zero. A failed check is logged by code only (the
679
+ * leading reason code, else the error's class name -- never the raw message, which could carry
680
+ * cluster detail) and counts as awake, so warm-up runs the preflight as it would without the mode.
681
+ */
682
+ async proxyAsleep() {
683
+ try {
684
+ return await this.power.isAsleep("proxy");
685
+ }
686
+ catch (error) {
687
+ const code = (error instanceof Error && /^[a-z][a-z0-9_]*(?=:)/.exec(error.message)?.[0]) ||
688
+ (error instanceof Error ? error.name : "unknown");
689
+ this.warn(`kubernetes_preflight_power_check_failed: ${code}`);
690
+ return false;
691
+ }
692
+ }
693
+ /**
694
+ * Starts the memoized cluster preflight (`runPreflight`) right away, instead of waiting for the
695
+ * first `launch()`, so a long-running server process's own start-up pays the preflight's cost (a
696
+ * canary pod on `kind`: ~20s) rather than that process's first coding run. Never throws: it only
697
+ * reports the outcome (an info line on success, a warning naming the failure code otherwise) so
698
+ * an operator sees a misconfigured cluster at boot. Any `launch()` already awaiting this same
699
+ * attempt (concurrent with this call) still fails exactly as it does today when the preflight
700
+ * failed — it shares the same rejected promise. But unlike a preflight `launch()` starts on its
701
+ * own, a start-up failure here is **not** left stuck memoized: a transient cluster problem at
702
+ * process start must not fail every coding run until restart, so the failed attempt is cleared
703
+ * (only if nothing has already started a newer one — compared by identity, never by state) and
704
+ * the *next* `launch()` runs the preflight fresh. A successful warm-up stays memoized as always.
705
+ * In low-power mode, while the proxy is asleep, warm-up is skipped (the memo stays unset) rather
706
+ * than waking the proxy only for the preflight; the first `launch()` wakes it and runs the preflight.
707
+ */
708
+ async warmUp() {
709
+ if (this.power.enabled && (await this.proxyAsleep())) {
710
+ kubernetesLog.info("kubernetes_preflight_deferred: proxy asleep (low-power mode); the first coding run runs the preflight");
711
+ return;
712
+ }
713
+ const attempt = this.runPreflight();
714
+ try {
715
+ await attempt;
716
+ kubernetesLog.info("kubernetes_preflight_warm_up_succeeded: cluster preflight passed at start-up");
717
+ }
718
+ catch (error) {
719
+ // Only clear the memo if it still holds this exact attempt: a concurrent launch() or warmUp()
720
+ // may have already seen this same rejection and started a fresh one (which must survive), and
721
+ // nothing else could have replaced this attempt with anything but a newer one, since
722
+ // runPreflight() never overwrites an already-set, still-pending-or-resolved promise.
723
+ if (this.preflightResult === attempt)
724
+ this.preflightResult = undefined;
725
+ // Same code-only convention as every other failure this launcher logs (e.g. launch()'s
726
+ // kubernetes_spec_rejected above): the error's own message is the fixed reason code set by
727
+ // runPreflight's errorWithCode (KUBERNETES_ISOLATION_ERROR) — never the raw cause, which could
728
+ // carry cluster detail.
729
+ const code = error instanceof Error ? error.message : String(error);
730
+ this.warn(`kubernetes_preflight_warm_up_failed: ${code}`);
731
+ }
732
+ }
733
+ /**
734
+ * Memoized: the preflight (or, without one, a single proxy-witness read) runs once per launcher —
735
+ * including its failure, which stays memoized and fails every subsequent `launch()` immediately,
736
+ * for a preflight `launch()` itself started (there was no `warmUp()`, or `warmUp()`'s own failed
737
+ * attempt was already cleared). `warmUp()` is the one caller that clears a failed attempt instead
738
+ * of leaving it stuck; see its own doc comment.
739
+ */
622
740
  runPreflight() {
623
741
  this.preflightResult ??= (async () => {
624
742
  try {
@@ -688,6 +806,22 @@ export class KubernetesJobLauncher {
688
806
  await this.sleep(ENFORCEMENT_POLL_MS);
689
807
  }
690
808
  }
809
+ /** True when `found` is a requeued record for this spec, which launch() replaces with a fresh one. */
810
+ isRequeued(found, specHash) {
811
+ if (found.record.phase !== "requeued")
812
+ return false;
813
+ if (found.record.specHash !== specHash)
814
+ throw new Error("job_spec_conflict");
815
+ return true;
816
+ }
817
+ /** Tells the operator once that a quota refused a pod while no quota is configured for the pre-launch check. */
818
+ hintQuotaUnconfigured(refusedQuota) {
819
+ if (this.options.config.resourceQuota)
820
+ return;
821
+ const name = refusedQuota !== undefined && DNS_1123_NAME.test(refusedQuota) ? refusedQuota : undefined;
822
+ this.warnOnce(`kubernetes_resource_quota_unconfigured: a pod was refused by ${name ? `ResourceQuota ${name}` : "a ResourceQuota"}; ` +
823
+ `set KUBERNETES_RESOURCE_QUOTA=${name ?? "<name>"} and grant the launcher get on that ResourceQuota so runs wait before they start`);
824
+ }
691
825
  existingLaunch(record, specHash, handle) {
692
826
  if (record.specHash !== specHash)
693
827
  throw new Error("job_spec_conflict");
@@ -862,14 +996,14 @@ export class KubernetesJobLauncher {
862
996
  const staging = await mkdtemp(join(tmpdir(), "wardby-k8s-input-"));
863
997
  try {
864
998
  const source = await lstat(inputArtifact);
865
- if (!source.isFile() || source.size > MAX_CODING_ARTIFACT_BYTES) {
999
+ if (!source.isFile() || source.size > MAX_CODING_INPUT_BYTES) {
866
1000
  throw new Error("kubernetes_input_artifact_invalid");
867
1001
  }
868
1002
  const copy = join(staging, "input.json");
869
1003
  await copyFile(inputArtifact, copy);
870
1004
  // Re-check the copy: the source could have changed between lstat and copy.
871
1005
  const copied = await lstat(copy);
872
- if (!copied.isFile() || copied.size > MAX_CODING_ARTIFACT_BYTES) {
1006
+ if (!copied.isFile() || copied.size > MAX_CODING_INPUT_BYTES) {
873
1007
  throw new Error("kubernetes_input_artifact_invalid");
874
1008
  }
875
1009
  await this.seedDirectory(names, staging, INPUT_STORAGE, timeoutMs);
@@ -887,7 +1021,8 @@ export class KubernetesJobLauncher {
887
1021
  // Observation and collection
888
1022
  /** Observes a non-terminal run against its pod and persists any transition; returns the stored record. */
889
1023
  async refresh(names, record) {
890
- if (isTerminal(record.phase))
1024
+ // A requeued run has no pod by design; observing it would record it lost.
1025
+ if (isTerminal(record.phase) || record.phase === "requeued")
891
1026
  return record;
892
1027
  const pod = await this.api.readPod(this.namespace, names.pod);
893
1028
  const observed = observePod(pod, record, this.now(), this.readyTimeoutMs);
@@ -915,6 +1050,30 @@ export class KubernetesJobLauncher {
915
1050
  }
916
1051
  return undefined;
917
1052
  }
1053
+ async readTranscript(handle, maxBytes) {
1054
+ const names = this.namesFor(handle);
1055
+ const found = names && (await this.readRecord(names));
1056
+ if (!names || !found)
1057
+ return undefined;
1058
+ const collector = new BoundedCollector(maxBytes);
1059
+ let exitCode;
1060
+ try {
1061
+ exitCode = await this.api.exec(this.namespace, names.pod, KEEPER_CONTAINER, ["head", "-c", String(maxBytes + 1), TRANSCRIPT_PATH], { stdout: collector, timeoutMs: SHORT_EXEC_TIMEOUT_MS });
1062
+ if (!collector.writableEnded)
1063
+ collector.end();
1064
+ await finished(collector);
1065
+ }
1066
+ catch {
1067
+ // The pod is gone (a stopped run) or unreachable: there is nothing to collect.
1068
+ collector.destroy();
1069
+ return undefined;
1070
+ }
1071
+ if (exitCode !== 0)
1072
+ return undefined;
1073
+ if (collector.exceeded)
1074
+ throw new Error("transcript_too_large");
1075
+ return collector.text();
1076
+ }
918
1077
  async readResultArtifact(names, runId) {
919
1078
  const collector = new BoundedCollector(MAX_CODING_ARTIFACT_BYTES);
920
1079
  let raw;
@@ -935,7 +1094,7 @@ export class KubernetesJobLauncher {
935
1094
  }
936
1095
  let output;
937
1096
  try {
938
- output = parseCodingAgentOutputJson(raw);
1097
+ output = parseCodingWorkerOutputJson(raw);
939
1098
  }
940
1099
  catch (error) {
941
1100
  throw errorWithCode("kubernetes_result_artifact_invalid", error);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Cloud metadata endpoints a coding or native worker pod must never reach: they hand out node or
3
+ * workload credentials. The instance metadata service (GCE, EC2 IPv4), the EKS Pod Identity agent (IPv4
4
+ * and IPv6), and EC2's IPv6 IMDS endpoint. Probed on port 80, where every one of them serves. A pod without
5
+ * IPv6 fails the last connect immediately, which counts as unreachable — correct either way.
6
+ * src/sandbox/fetch-policy.ts blocks the same addresses for in-process fetches.
7
+ */
8
+ export declare const CLOUD_METADATA_PROBES: readonly {
9
+ host: string;
10
+ port: number;
11
+ }[];
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Cloud metadata endpoints a coding or native worker pod must never reach: they hand out node or
3
+ * workload credentials. The instance metadata service (GCE, EC2 IPv4), the EKS Pod Identity agent (IPv4
4
+ * and IPv6), and EC2's IPv6 IMDS endpoint. Probed on port 80, where every one of them serves. A pod without
5
+ * IPv6 fails the last connect immediately, which counts as unreachable — correct either way.
6
+ * src/sandbox/fetch-policy.ts blocks the same addresses for in-process fetches.
7
+ */
8
+ export const CLOUD_METADATA_PROBES = Object.freeze([
9
+ Object.freeze({ host: "169.254.169.254", port: 80 }),
10
+ Object.freeze({ host: "169.254.170.23", port: 80 }),
11
+ Object.freeze({ host: "fd00:ec2::254", port: 80 }),
12
+ Object.freeze({ host: "fd00:ec2::23", port: 80 }),
13
+ ]);
@@ -21,6 +21,14 @@ export interface JobSpec {
21
21
  /** Required only for Claude's credential-free repository tool container. */
22
22
  toolImage?: string;
23
23
  inputArtifact: string;
24
+ /** Set only when the run's dependency cache is on (CodingRun.dependencyCache); absent otherwise, never false. */
25
+ dependencyCache?: true;
26
+ /**
27
+ * Claude Code only, set only when the run keeps its session (CodingRun.sessionResume); absent otherwise,
28
+ * never false. The worker's SDK config dir, where the session file grows, gets its own size-limited
29
+ * scratch so a long session never fills the worker's shared /tmp.
30
+ */
31
+ sessionResume?: true;
24
32
  timeoutSec: number;
25
33
  limits: JobResourceLimits;
26
34
  labels: Record<string, string>;
@@ -42,6 +50,12 @@ export interface JobHandle {
42
50
  }
43
51
  export type JobStatus = {
44
52
  state: "pending" | "running";
53
+ /**
54
+ * Only ever on `pending`: the backend refused this job's launch for capacity (JobCapacityError)
55
+ * and nothing of it is running, nor will it start on its own. A caller that finds its job so
56
+ * may return the run to its queue and later `launch` the same spec again.
57
+ */
58
+ capacityRefused?: true;
45
59
  } | {
46
60
  state: "succeeded";
47
61
  } | {
@@ -61,11 +75,24 @@ export interface JobResult {
61
75
  /** Output-schema failure locations (`path:code`) that passed SAFE_CODING_OUTPUT_ISSUE; never values. */
62
76
  diagnosticIssues?: string[];
63
77
  }
78
+ /**
79
+ * The backend has no room for this job right now (Kubernetes: the namespace ResourceQuota). No
80
+ * workload of the job is left running; the backend may keep a record of the refusal (Kubernetes
81
+ * does: its run record, which `status` then reports as `pending` with `capacityRefused`). The
82
+ * caller may launch the same spec again later.
83
+ */
84
+ export declare class JobCapacityError extends Error {
85
+ readonly code = "coding_capacity_exceeded";
86
+ constructor(message: string, options?: ErrorOptions);
87
+ }
64
88
  /**
65
89
  * Lifecycle invariants implemented by every launcher:
66
90
  *
67
91
  * - `launch` is idempotent by runId for an identical spec and rejects a
68
92
  * different spec for the same runId.
93
+ * - `launch` may reject with JobCapacityError when the backend has no room for
94
+ * the job; nothing of it is then left running, and a later `launch` of the
95
+ * same spec provisions it afresh.
69
96
  * - pending may become running or terminal; running may become terminal;
70
97
  * terminal states never change.
71
98
  * - `collect` is repeatable for a terminal job until `remove` succeeds.
@@ -88,9 +115,24 @@ export interface JobLauncher {
88
115
  * itself stays the authority.
89
116
  */
90
117
  hasCapacityFor?: (spec: JobSpec) => Promise<boolean>;
118
+ /**
119
+ * Starts any one-time start-up check (e.g. Kubernetes's memoized cluster preflight) right away,
120
+ * instead of waiting for the first `launch()`. Never throws — a failure is only logged — and
121
+ * `launch()` still runs and reports the same check itself, memoized exactly as if this had never
122
+ * been called. Composition roots call this, fire-and-forget, only from a long-running server
123
+ * process's own start-up (`wardby serve`, the MCP server, `wardby scheduler`); never from a
124
+ * one-shot CLI command. Absent on a launcher with nothing to warm up (e.g. Docker).
125
+ */
126
+ warmUp?: () => Promise<void>;
91
127
  launch: (spec: JobSpec) => Promise<JobHandle>;
92
128
  status: (handle: JobHandle) => Promise<JobStatus>;
93
129
  collect: (handle: JobHandle) => Promise<JobResult>;
130
+ /**
131
+ * The run's session transcript file (the worker's session.jsonl), at most `maxBytes`; undefined
132
+ * when there is none or the job's storage is gone (a stopped job). Throws `transcript_too_large`
133
+ * when larger. Never cached in the job record: it is not redacted yet. Call before `remove`.
134
+ */
135
+ readTranscript?: (handle: JobHandle, maxBytes: number) => Promise<string | undefined>;
94
136
  stop: (handle: JobHandle, reason?: string) => Promise<void>;
95
137
  remove: (handle: JobHandle) => Promise<void>;
96
138
  }
@@ -3,4 +3,16 @@
3
3
  * values are carried in a versioned input artifact, never expanded into an
4
4
  * arbitrary environment map or shell command.
5
5
  */
6
- export {};
6
+ /**
7
+ * The backend has no room for this job right now (Kubernetes: the namespace ResourceQuota). No
8
+ * workload of the job is left running; the backend may keep a record of the refusal (Kubernetes
9
+ * does: its run record, which `status` then reports as `pending` with `capacityRefused`). The
10
+ * caller may launch the same spec again later.
11
+ */
12
+ export class JobCapacityError extends Error {
13
+ code = "coding_capacity_exceeded";
14
+ constructor(message, options) {
15
+ super(message, options);
16
+ this.name = "JobCapacityError";
17
+ }
18
+ }
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import Anthropic from "@anthropic-ai/sdk";
8
8
  import { ClaudeLlmProvider } from "./claude-provider.js";
9
+ import { simulatorModelClientOptions } from "../../config/test-simulators.js";
9
10
  export function anthropicCredentialsPresent(env = process.env) {
10
11
  return Boolean(env.ANTHROPIC_API_KEY);
11
12
  }
@@ -14,6 +15,9 @@ export class AnthropicLlmProvider extends ClaudeLlmProvider {
14
15
  if (!client && !apiKey) {
15
16
  throw new Error("ANTHROPIC_API_KEY is not set — required by the Anthropic LlmProvider adapter.");
16
17
  }
17
- super(client ?? new Anthropic({ apiKey }), lookup);
18
+ // WARDBY_TEST_SIMULATORS (test only): the scripted model, with a placeholder key the
19
+ // credential-free fetch drops; the real key never goes there.
20
+ const simulator = client ? null : simulatorModelClientOptions("anthropic");
21
+ super(client ?? new Anthropic(simulator ?? { apiKey }), lookup);
18
22
  }
19
23
  }
@@ -1,15 +1,3 @@
1
- /**
2
- * Bedrock-Claude adapter for the LlmProvider seam. `@anthropic-ai/bedrock-sdk`
3
- * is imported only here; all protocol/pricing-dispatch logic lives in the
4
- * shared ClaudeLlmProvider base class (claude-provider.ts) — AnthropicBedrock
5
- * exposes the identical .messages.stream() surface as @anthropic-ai/sdk, so
6
- * this file's only job is constructing the right client.
7
- *
8
- * Named BedrockClaudeLlmProvider, not BedrockLlmProvider: Bedrock hosts
9
- * multiple model vendors, and this adapter only ever speaks the
10
- * Anthropic-native protocol for Claude models. A future non-Claude Bedrock
11
- * adapter gets its own name, not a rename of this one.
12
- */
13
1
  import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
14
2
  import { ClaudeLlmProvider } from "./claude-provider.js";
15
3
  import type { CatalogLookup } from "./catalog-lookup.js";
@@ -10,6 +10,7 @@
10
10
  * Anthropic-native protocol for Claude models. A future non-Claude Bedrock
11
11
  * adapter gets its own name, not a rename of this one.
12
12
  */
13
+ import { refuseBedrockUnderTestSimulators } from "../../config/test-simulators.js";
13
14
  import { AnthropicBedrock } from "@anthropic-ai/bedrock-sdk";
14
15
  import { ClaudeLlmProvider } from "./claude-provider.js";
15
16
  export function bedrockCredentialsPresent(env = process.env) {
@@ -23,6 +24,9 @@ export class BedrockClaudeLlmProvider extends ClaudeLlmProvider {
23
24
  if (!client && !region) {
24
25
  throw new Error("BEDROCK_REGION (or AWS_REGION) is required by the Bedrock Claude LlmProvider adapter.");
25
26
  }
27
+ // WARDBY_TEST_SIMULATORS (test only) refuses Bedrock: AWS-signed calls cannot go to the simulator.
28
+ if (!client)
29
+ refuseBedrockUnderTestSimulators();
26
30
  super(client ?? new AnthropicBedrock({ awsRegion: region }), lookup);
27
31
  }
28
32
  }
@@ -106,5 +106,7 @@ export type ClaudeStreamEvent = {
106
106
  } | {
107
107
  type: "message_stop";
108
108
  };
109
- export declare function mapClaudeStream(events: AsyncIterable<ClaudeStreamEvent>, priceUsd: (usage: LlmUsage) => number): AsyncIterable<LlmStreamEvent>;
109
+ export declare function mapClaudeStream(events: AsyncIterable<ClaudeStreamEvent>, priceUsd: (usage: LlmUsage) => number,
110
+ /** Called at message_start: the response has started, and output may be billed from here on. */
111
+ onResponseStarted?: () => void): AsyncIterable<LlmStreamEvent>;
110
112
  export {};
@@ -98,7 +98,9 @@ export function withCacheBreakpoints(req) {
98
98
  });
99
99
  return { ...req, ...(system ? { system } : {}), messages };
100
100
  }
101
- export async function* mapClaudeStream(events, priceUsd) {
101
+ export async function* mapClaudeStream(events, priceUsd,
102
+ /** Called at message_start: the response has started, and output may be billed from here on. */
103
+ onResponseStarted) {
102
104
  const toolBuffers = new Map();
103
105
  let start = {};
104
106
  let outputTokens = 0;
@@ -106,6 +108,7 @@ export async function* mapClaudeStream(events, priceUsd) {
106
108
  for await (const ev of events) {
107
109
  switch (ev.type) {
108
110
  case "message_start":
111
+ onResponseStarted?.();
109
112
  start = ev.message.usage ?? {};
110
113
  outputTokens = ev.message.usage?.output_tokens ?? 0;
111
114
  break;
@@ -5,7 +5,7 @@
5
5
  * stays exactly what each concrete adapter (anthropic.ts, bedrock.ts) has in
6
6
  * common, and nothing more.
7
7
  */
8
- import type { LlmMessage, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
8
+ import type { LlmMessage, LlmRequest, LlmStreamEvent, LlmStreamHooks, LlmToolDef } from "./types.js";
9
9
  import { type CatalogLookup } from "./catalog-lookup.js";
10
10
  import type { CatalogEntry } from "./catalog-types.js";
11
11
  import type { CatalogLlmAdapter } from "./routing.js";
@@ -27,7 +27,7 @@ export declare class ClaudeLlmProvider implements CatalogLlmAdapter {
27
27
  private readonly lookup;
28
28
  constructor(client: ClaudeMessagesClient, lookup?: CatalogLookup);
29
29
  withEntry(entry: CatalogEntry): ClaudeLlmProvider;
30
- stream(req: LlmRequest, signal?: AbortSignal): AsyncIterable<LlmStreamEvent>;
30
+ stream(req: LlmRequest, signal?: AbortSignal, hooks?: LlmStreamHooks): AsyncIterable<LlmStreamEvent>;
31
31
  countTokens(model: string, messages: LlmMessage[], tools?: LlmToolDef[]): Promise<number>;
32
32
  priceUsd(model: string, usage: {
33
33
  inputTokens: number;
@@ -21,14 +21,14 @@ export class ClaudeLlmProvider {
21
21
  withEntry(entry) {
22
22
  return new ClaudeLlmProvider(this.client, pinnedLookup(entry));
23
23
  }
24
- async *stream(req, signal) {
24
+ async *stream(req, signal, hooks) {
25
25
  // Defence in depth behind config-time validation: a level the model
26
26
  // doesn't accept would fail the whole call, so it is dropped here.
27
27
  const { effort, ...rest } = req;
28
28
  const accepted = effort && this.lookup(req.model).efforts.includes(effort);
29
29
  const claudeReq = withCacheBreakpoints(toClaudeRequest(accepted ? { ...rest, effort } : rest, DEFAULT_MAX_TOKENS));
30
30
  const raw = this.client.messages.stream({ model: req.model, ...claudeReq }, { signal });
31
- yield* mapClaudeStream(raw, (usage) => this.priceUsd(req.model, usage));
31
+ yield* mapClaudeStream(raw, (usage) => this.priceUsd(req.model, usage), hooks?.onResponseStarted);
32
32
  }
33
33
  async countTokens(model, messages, tools) {
34
34
  this.lookup(model); // fail-closed on a model the catalog does not serve