@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,14 @@
1
1
  import { spawn } from "node:child_process";
2
- import { lstat, mkdir, opendir, readFile, readlink, realpath, rm } from "node:fs/promises";
2
+ import { constants as fsConstants } from "node:fs";
3
+ import { lstat, mkdir, open, opendir, readFile, readlink, realpath, rm, writeFile, } from "node:fs/promises";
3
4
  import { isAbsolute, resolve, sep } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { gitExcludePathspecs, normalizeCollectExclusions } from "../../coding/collect-exclude.js";
6
7
  import { WARDBY_PROTECTED_PATHS, isProtectedPathException, isWellFormedProtectedPath, protectedPathBody, protectsSomePath, } from "../../coding/protected-paths.js";
7
8
  import { ensurePrivateDirectory } from "../../core/private-directory.js";
9
+ import { simulatorGitEnvironment } from "../../config/test-simulators.js";
8
10
  import { globRegex } from "../../core/glob.js";
11
+ import { redactExactSecretValues } from "../../core/secret-spans.js";
9
12
  import { MAX_REDACTED_SPAN, redactTokenShapedValues, normalizeGitRef } from "../../coding/protocol.js";
10
13
  import { isSafeGitHubInstallationToken } from "./github.js";
11
14
  export const DEFAULT_MAX_CHANGED_FILES = 1_000;
@@ -14,6 +17,24 @@ const MAX_GIT_OUTPUT_BYTES = 2 * 1024 * 1024;
14
17
  const MAX_WORKSPACE_ENTRIES = 100_000;
15
18
  const SAFE_COMMIT_SHA = /^[0-9a-f]{40}$/;
16
19
  const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
20
+ /** Where a continuation's target branch is fetched to (never under refs/remotes, so baseCommit's ref is untouched). */
21
+ const MERGE_TARGET_REF = "refs/wardby/merge-target";
22
+ /** Where the head branch is re-fetched while deepening history (see fetchMergeTarget). */
23
+ const MERGE_HEAD_REF = "refs/wardby/merge-head";
24
+ /**
25
+ * The trusted automatic merge of the target branch, recorded at prepare time:
26
+ * a commit whose tree is the merge result (markers in conflicted files), whose
27
+ * parents are baseCommit and the target commit, and whose message carries the
28
+ * target ref and the conflicted paths as JSON. Recovery and finalize read it
29
+ * back; the agent's changes are measured against its tree.
30
+ */
31
+ const MERGE_STATE_REF = "refs/wardby/merge-state";
32
+ const MERGE_STATE_SUBJECT = "wardby merge state";
33
+ /** How far `fetch --deepen` goes, step by step, looking for a merge base in a depth-1 clone. */
34
+ const MERGE_BASE_DEEPEN_STEPS = [64, 256, 1024, 4096];
35
+ /** A conflict marker pair at the start of a line: git writes 7 characters (any longer run counts too), then a space or the line end. */
36
+ const CONFLICT_MARKER_START = /^<{7,}(?: |\r?$)/m;
37
+ const CONFLICT_MARKER_END = /^>{7,}(?: |\r?$)/m;
17
38
  const HARDENED_GIT_CONFIG = [
18
39
  "-c",
19
40
  "core.hooksPath=/dev/null",
@@ -41,11 +62,10 @@ export function redactGitOutput(value, secrets = []) {
41
62
  // MAX_REDACTED_SPAN of margin rather than on all 2 MiB git may have produced
42
63
  // (see redactAndTruncate: the margin is what keeps truncation safe). The rest
43
64
  // is discarded here and never reaches a log or the database.
44
- let output = value.slice(0, GIT_OUTPUT_DISPLAY_BYTES + MAX_REDACTED_SPAN);
45
- for (const secret of secrets) {
46
- if (secret)
47
- output = output.split(secret).join("[REDACTED]");
48
- }
65
+ // The shared span-union redactor; any non-empty value counts here, as it always has.
66
+ const output = redactExactSecretValues(value.slice(0, GIT_OUTPUT_DISPLAY_BYTES + MAX_REDACTED_SPAN), secrets, {
67
+ minLength: 1,
68
+ });
49
69
  return redactTokenShapedValues(output).slice(0, GIT_OUTPUT_DISPLAY_BYTES);
50
70
  }
51
71
  /** Runs Git without a shell or inherited application secrets. */
@@ -79,6 +99,8 @@ export class NodeGitCommandRunner {
79
99
  GIT_ASKPASS: options.authToken ? this.askPassPath : "/bin/false",
80
100
  SSH_ASKPASS: "/bin/false",
81
101
  GIT_LFS_SKIP_SMUDGE: "1",
102
+ // WARDBY_TEST_SIMULATORS (test only): the simulator's throwaway CA; empty otherwise.
103
+ ...simulatorGitEnvironment(),
82
104
  };
83
105
  const maxBytes = options.maxOutputBytes ?? MAX_GIT_OUTPUT_BYTES;
84
106
  const secrets = options.authToken ? [options.authToken] : [];
@@ -133,7 +155,7 @@ export class NodeGitCommandRunner {
133
155
  stdout: Buffer.concat(stdout).toString("utf8"),
134
156
  stderr: redactGitOutput(Buffer.concat(stderr).toString("utf8"), secrets),
135
157
  };
136
- if (code !== 0) {
158
+ if (code !== 0 && (code === null || !options.acceptExitCodes?.includes(code))) {
137
159
  rejectPromise(new GitCommandError(code, result.stderr.trim()));
138
160
  return;
139
161
  }
@@ -192,6 +214,26 @@ function nullSeparated(value) {
192
214
  values.pop();
193
215
  return values.map(validateChangedPath);
194
216
  }
217
+ function safeGitRef(value) {
218
+ try {
219
+ return normalizeGitRef(value);
220
+ }
221
+ catch {
222
+ return null;
223
+ }
224
+ }
225
+ /** The merge state's message: a fixed subject, then the target ref and conflicted paths as JSON. */
226
+ function mergeStateMessage(targetMerge) {
227
+ return `${MERGE_STATE_SUBJECT}\n\n${JSON.stringify({ ref: targetMerge.ref, conflicted: targetMerge.conflictedPaths })}\n`;
228
+ }
229
+ function sameTargetMerge(left, right) {
230
+ if (!left || !right)
231
+ return left === right;
232
+ return (left.ref === right.ref &&
233
+ left.targetCommit === right.targetCommit &&
234
+ left.conflictedPaths.length === right.conflictedPaths.length &&
235
+ left.conflictedPaths.every((path, index) => path === right.conflictedPaths[index]));
236
+ }
195
237
  function directChild(root, child) {
196
238
  return child.startsWith(`${root}${sep}`) && !child.slice(root.length + 1).includes(sep);
197
239
  }
@@ -244,6 +286,11 @@ export class GitVcsProvider {
244
286
  // baseCommit already means exactly what it needs to: "where this
245
287
  // round started."
246
288
  const cloneBranch = normalized.continuation ? normalized.headRef : normalized.baseRef;
289
+ // A continuation is first brought up to date with the branch its pull
290
+ // request targets now (a person may have retargeted it since the root run).
291
+ const target = normalized.continuation ? await this.remote.pullRequestBase?.(normalized) : null;
292
+ const mergeRef = target ? safeGitRef(target.ref) : null;
293
+ let mergeFetched = false;
247
294
  try {
248
295
  await this.remote.withAccess(normalized.repository, async (token) => {
249
296
  const auth = token !== undefined ? { authToken: token } : {};
@@ -280,6 +327,9 @@ export class GitVcsProvider {
280
327
  cloneUrl,
281
328
  workspacePath,
282
329
  ], { cwd: runRoot, ...auth });
330
+ if (mergeRef && mergeRef !== normalized.headRef) {
331
+ mergeFetched = await this.fetchMergeTarget(gitMetadataPath, workspacePath, cloneBranch, mergeRef, auth);
332
+ }
283
333
  });
284
334
  await rm(resolve(workspacePath, ".git"), { force: true });
285
335
  const baseCommit = await this.revParseRaw(gitMetadataPath, workspacePath, `refs/remotes/origin/${cloneBranch}^{commit}`);
@@ -307,7 +357,15 @@ export class GitVcsProvider {
307
357
  "HEAD",
308
358
  `refs/heads/${normalized.headRef}`,
309
359
  ]);
310
- await this.gitForPaths(gitMetadataPath, workspacePath, ["read-tree", "--reset", "-u", baseCommit]);
360
+ const merged = mergeFetched && mergeRef
361
+ ? await this.mergeTargetBranch(gitMetadataPath, workspacePath, baseCommit, mergeRef)
362
+ : null;
363
+ await this.gitForPaths(gitMetadataPath, workspacePath, [
364
+ "read-tree",
365
+ "--reset",
366
+ "-u",
367
+ merged?.tree ?? baseCommit,
368
+ ]);
311
369
  await this.inspectWorkspace(workspacePath);
312
370
  return {
313
371
  id: `vcs-${normalized.runId}`,
@@ -315,6 +373,7 @@ export class GitVcsProvider {
315
373
  baseCommit,
316
374
  workspacePath,
317
375
  gitMetadataPath,
376
+ ...(merged ? { targetMerge: merged.targetMerge } : {}),
318
377
  };
319
378
  }
320
379
  catch (error) {
@@ -351,19 +410,30 @@ export class GitVcsProvider {
351
410
  const symbolicHead = (await this.gitFor(prepared, ["symbolic-ref", "--short", "HEAD"])).stdout.trim();
352
411
  if (symbolicHead !== prepared.headRef)
353
412
  throw new Error("vcs_head_ref_mismatch");
413
+ const merge = await this.readMergeState(prepared);
354
414
  const currentHead = await this.revParse(prepared, "HEAD");
355
415
  if (currentHead !== prepared.baseCommit) {
356
416
  const parent = await this.revParse(prepared, "HEAD^");
357
417
  if (parent !== prepared.baseCommit)
358
418
  throw new Error("vcs_commit_history_invalid");
419
+ if (merge && (await this.revParse(prepared, "HEAD^2")) !== merge.targetCommit) {
420
+ throw new Error("vcs_commit_history_invalid");
421
+ }
359
422
  }
360
- return prepared;
423
+ if (!merge)
424
+ return prepared;
425
+ const { stateCommit: _stateCommit, ...targetMerge } = merge;
426
+ return { ...prepared, targetMerge };
361
427
  }
362
428
  async finalizeChanges(workspace, details) {
363
429
  const prepared = await this.validatePrepared(workspace);
364
430
  await this.inspectWorkspace(prepared.workspacePath);
365
431
  await this.assertRemote(prepared);
366
432
  await this.assertSafeLocalConfig(prepared.gitMetadataPath);
433
+ // The merge state on disk is the trusted record; the handle must agree with it.
434
+ const merge = await this.readMergeState(prepared);
435
+ if (!sameTargetMerge(merge, prepared.targetMerge))
436
+ throw new Error("vcs_workspace_handle_invalid");
367
437
  // Excluded paths (src/coding/collect-exclude.ts) are never collected from the worker, so
368
438
  // they are also neither added nor deleted here: tracked files under them stay untouched.
369
439
  await this.gitFor(prepared, [
@@ -373,15 +443,12 @@ export class GitVcsProvider {
373
443
  ":/",
374
444
  ...gitExcludePathspecs(normalizeCollectExclusions(prepared.collectExclude)),
375
445
  ]);
376
- const changed = nullSeparated((await this.gitFor(prepared, [
377
- "diff",
378
- "--cached",
379
- "--name-only",
380
- "-z",
381
- "--no-renames",
382
- prepared.baseCommit,
383
- "--",
384
- ])).stdout);
446
+ // Every check below applies to the agent's own changes: against baseCommit, or, after a
447
+ // merge, against the trusted automatic merge result (so the target branch's own changes,
448
+ // protected paths included, pass, while any agent edit -- a conflict it resolved, a
449
+ // target change it reverted -- is checked).
450
+ const comparedTo = merge?.stateCommit ?? prepared.baseCommit;
451
+ const changed = nullSeparated((await this.gitFor(prepared, ["diff", "--cached", "--name-only", "-z", "--no-renames", comparedTo, "--"])).stdout);
385
452
  if (changed.length > this.maxChangedFiles)
386
453
  throw new Error("vcs_changed_file_limit");
387
454
  const protectedChange = changed.find(protectedPathMatcher(prepared.protectedPaths));
@@ -389,7 +456,7 @@ export class GitVcsProvider {
389
456
  throw new Error(`vcs_protected_path:${protectedChange}`);
390
457
  let diff;
391
458
  try {
392
- diff = (await this.gitFor(prepared, ["diff", "--cached", "--binary", "--no-ext-diff", "--no-textconv", prepared.baseCommit, "--"], { maxOutputBytes: this.maxDiffBytes })).stdout;
459
+ diff = (await this.gitFor(prepared, ["diff", "--cached", "--binary", "--no-ext-diff", "--no-textconv", comparedTo, "--"], { maxOutputBytes: this.maxDiffBytes })).stdout;
393
460
  }
394
461
  catch (error) {
395
462
  if (error instanceof GitCommandError && error.message.includes("git_output_limit")) {
@@ -399,8 +466,12 @@ export class GitVcsProvider {
399
466
  }
400
467
  if (Buffer.byteLength(diff, "utf8") > this.maxDiffBytes)
401
468
  throw new Error("vcs_diff_size_limit");
469
+ // After the size limits, so a conflicted file is never read past what the diff limit allows.
470
+ if (merge)
471
+ await this.assertConflictsResolved(prepared.workspacePath, merge.conflictedPaths);
402
472
  const currentHead = await this.revParse(prepared, "HEAD");
403
- if (changed.length === 0 && currentHead === prepared.baseCommit) {
473
+ // A merge with no agent edits still has the merge itself to push.
474
+ if (!merge && changed.length === 0 && currentHead === prepared.baseCommit) {
404
475
  return {
405
476
  outcome: "no_changes",
406
477
  repository: prepared.repository,
@@ -412,7 +483,10 @@ export class GitVcsProvider {
412
483
  if (symbolicHead !== prepared.headRef)
413
484
  throw new Error("vcs_head_ref_mismatch");
414
485
  let commitSha;
415
- if (currentHead === prepared.baseCommit) {
486
+ if (currentHead === prepared.baseCommit && merge) {
487
+ commitSha = await this.commitMerge(prepared, merge);
488
+ }
489
+ else if (currentHead === prepared.baseCommit) {
416
490
  await this.gitFor(prepared, ["commit", "--no-verify", "--no-gpg-sign", "-m", `Wardby run ${prepared.runId}`]);
417
491
  commitSha = await this.revParse(prepared, "HEAD");
418
492
  }
@@ -420,14 +494,21 @@ export class GitVcsProvider {
420
494
  const parent = await this.revParse(prepared, "HEAD^");
421
495
  if (parent !== prepared.baseCommit)
422
496
  throw new Error("vcs_commit_history_invalid");
497
+ if (merge && (await this.revParse(prepared, "HEAD^2")) !== merge.targetCommit) {
498
+ throw new Error("vcs_commit_history_invalid");
499
+ }
423
500
  const afterCommitChanges = nullSeparated((await this.gitFor(prepared, ["diff", "--cached", "--name-only", "-z", "HEAD", "--"])).stdout);
424
501
  if (afterCommitChanges.length > 0)
425
502
  throw new Error("vcs_finalized_workspace_changed");
426
503
  commitSha = currentHead;
427
504
  }
428
505
  await this.remote.assertContinuationOpen(prepared);
506
+ // Before the push: a description comment must already exist when the push starts a review.
507
+ await this.remote
508
+ .proposeDescriptionBeforePush?.({ workspace: prepared, details, changedPaths: changed, commitSha })
509
+ .catch(() => undefined);
429
510
  await this.pushOnce(prepared, commitSha);
430
- const published = await this.remote.publish({ workspace: prepared, details, changedPaths: changed });
511
+ const published = await this.remote.publish({ workspace: prepared, details, changedPaths: changed, commitSha });
431
512
  if (published.kind === "branch") {
432
513
  if (published.branch !== prepared.headRef)
433
514
  throw new Error("vcs_head_ref_mismatch");
@@ -449,8 +530,47 @@ export class GitVcsProvider {
449
530
  commitSha,
450
531
  pullRequestNumber: published.number,
451
532
  pullRequestUrl: published.url,
533
+ ...(published.description ? { description: published.description } : {}),
534
+ ...(merge && prepared.continuation
535
+ ? {
536
+ targetMerge: {
537
+ ref: merge.ref,
538
+ targetCommit: merge.targetCommit,
539
+ conflicts: merge.conflictedPaths.length,
540
+ },
541
+ }
542
+ : {}),
452
543
  };
453
544
  }
545
+ /** The two-parent merge commit (baseCommit, the target) of the staged tree, as the Wardby identity. */
546
+ async commitMerge(prepared, merge) {
547
+ const tree = (await this.gitFor(prepared, ["write-tree"])).stdout.trim();
548
+ if (!SAFE_COMMIT_SHA.test(tree))
549
+ throw new Error("vcs_commit_sha_invalid");
550
+ const commitSha = (await this.gitFor(prepared, [
551
+ "commit-tree",
552
+ tree,
553
+ "-p",
554
+ prepared.baseCommit,
555
+ "-p",
556
+ merge.targetCommit,
557
+ "-m",
558
+ `Merge ${merge.ref} into ${prepared.headRef} (Wardby run ${prepared.runId})`,
559
+ ])).stdout.trim();
560
+ if (!SAFE_COMMIT_SHA.test(commitSha))
561
+ throw new Error("vcs_commit_sha_invalid");
562
+ await this.gitFor(prepared, ["update-ref", `refs/heads/${prepared.headRef}`, commitSha, prepared.baseCommit]);
563
+ return commitSha;
564
+ }
565
+ /** Re-derive a continuation's PR description without a push, delegated to the remote; never throws. */
566
+ async refreshPullRequestDescription(workspace, details) {
567
+ try {
568
+ return await this.remote.refreshDescription?.(workspace, details);
569
+ }
570
+ catch {
571
+ return { kind: "skipped", reason: "error" };
572
+ }
573
+ }
454
574
  async cleanup(workspace) {
455
575
  const expected = this.expectedPaths(workspace.runId);
456
576
  if (workspace.id !== `vcs-${workspace.runId}` ||
@@ -465,6 +585,15 @@ export class GitVcsProvider {
465
585
  * delegated to the remote; a remote without one is a no-op. Wrapped so
466
586
  * this can NEVER throw or otherwise affect the real coding run.
467
587
  */
588
+ /** Delegated to the remote; never throws (undefined on any failure). */
589
+ async continuationPullRequestDraft(workspace) {
590
+ try {
591
+ return await this.remote.continuationPullRequestDraft?.(workspace);
592
+ }
593
+ catch {
594
+ return undefined;
595
+ }
596
+ }
468
597
  async notifyContinuationStarted(workspace, details) {
469
598
  try {
470
599
  await this.remote.notifyContinuationStarted?.(workspace, details);
@@ -561,6 +690,179 @@ export class GitVcsProvider {
561
690
  }
562
691
  return { ...workspace, ...normalized };
563
692
  }
693
+ /**
694
+ * Fetches a continuation's target branch from the same `origin` the clone
695
+ * came from (never another URL, so never a fork) and deepens the depth-1
696
+ * clone step by step until the head and the target share a merge base.
697
+ * Returns true once they do; throws vcs_target_merge_failed when the fetch
698
+ * fails or no merge base turns up within MERGE_BASE_DEEPEN_STEPS.
699
+ */
700
+ async fetchMergeTarget(gitMetadataPath, workspacePath, cloneBranch, ref, auth) {
701
+ const fetch = (depth, refspec) => this.gitForPaths(gitMetadataPath, workspacePath, [...this.remote.gitConfig, "fetch", "--no-tags", "--no-write-fetch-head", ...depth, "origin", refspec], auth);
702
+ const target = `+refs/heads/${ref}:${MERGE_TARGET_REF}`;
703
+ // The head is deepened through its own ref under refs/wardby, so the clone's
704
+ // refs/remotes/origin/<head> (baseCommit) never moves.
705
+ const head = `+refs/heads/${cloneBranch}:${MERGE_HEAD_REF}`;
706
+ try {
707
+ await fetch(["--depth", "1"], target);
708
+ for (const step of [0, ...MERGE_BASE_DEEPEN_STEPS]) {
709
+ if (step > 0) {
710
+ // One fetch per side: newer git deepens only the refs a fetch names
711
+ // (older git deepened every shallow boundary), and a fetch naming
712
+ // both deepens only one of them.
713
+ await fetch([`--deepen=${step}`], head);
714
+ await fetch([`--deepen=${step}`], target);
715
+ }
716
+ const base = await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-base", `refs/remotes/origin/${cloneBranch}`, MERGE_TARGET_REF], { acceptExitCodes: [1] });
717
+ if (base.stdout.trim())
718
+ return true;
719
+ }
720
+ }
721
+ catch (error) {
722
+ throw new Error("vcs_target_merge_failed", { cause: error });
723
+ }
724
+ throw new Error("vcs_target_merge_failed");
725
+ }
726
+ /**
727
+ * Merges the fetched target into baseCommit without touching the index or
728
+ * the working tree (`merge-tree --write-tree`: no MERGE_HEAD, no hooks, no
729
+ * merge drivers -- none are configured), and records the result as the merge
730
+ * state. Null when the target is already part of the branch (nothing to merge).
731
+ */
732
+ async mergeTargetBranch(gitMetadataPath, workspacePath, baseCommit, ref) {
733
+ const targetCommit = await this.revParseRaw(gitMetadataPath, workspacePath, `${MERGE_TARGET_REF}^{commit}`);
734
+ const mergeBase = (await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-base", baseCommit, targetCommit])).stdout.trim();
735
+ if (mergeBase === targetCommit)
736
+ return null;
737
+ // The clone is --no-checkout and nothing is read into the index or the
738
+ // working tree until after this merge, so no repository .gitattributes
739
+ // (a marker size, `-merge`, `merge=union`) can steer it.
740
+ let output;
741
+ try {
742
+ output = (await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-tree", "--write-tree", "-z", "--name-only", "--no-messages", baseCommit, targetCommit], { acceptExitCodes: [1] })).stdout;
743
+ }
744
+ catch (error) {
745
+ throw new Error("vcs_target_merge_failed", { cause: error });
746
+ }
747
+ const [tree, ...paths] = output.split("\0");
748
+ if (!SAFE_COMMIT_SHA.test(tree))
749
+ throw new Error("vcs_target_merge_failed");
750
+ const conflictedPaths = [...new Set(paths.filter(Boolean))].map(validateChangedPath);
751
+ if (conflictedPaths.length > this.maxChangedFiles)
752
+ throw new Error("vcs_target_merge_failed");
753
+ const targetMerge = { ref, targetCommit, conflictedPaths };
754
+ // The message goes through a file: a long conflicted-path list could pass an argument's size limit.
755
+ const messagePath = resolve(gitMetadataPath, "WARDBY_MERGE_STATE_MSG");
756
+ await writeFile(messagePath, mergeStateMessage(targetMerge), { mode: 0o600 });
757
+ try {
758
+ const stateCommit = (await this.gitForPaths(gitMetadataPath, workspacePath, [
759
+ "commit-tree",
760
+ tree,
761
+ "-p",
762
+ baseCommit,
763
+ "-p",
764
+ targetCommit,
765
+ "-F",
766
+ messagePath,
767
+ ])).stdout.trim();
768
+ if (!SAFE_COMMIT_SHA.test(stateCommit))
769
+ throw new Error("vcs_commit_sha_invalid");
770
+ await this.gitForPaths(gitMetadataPath, workspacePath, ["update-ref", MERGE_STATE_REF, stateCommit]);
771
+ }
772
+ finally {
773
+ await rm(messagePath, { force: true });
774
+ }
775
+ return { tree, targetMerge };
776
+ }
777
+ /** The recorded merge state (see MERGE_STATE_REF), validated, or undefined when the workspace merged nothing. */
778
+ async readMergeState(workspace) {
779
+ const { gitMetadataPath, workspacePath } = workspace;
780
+ const stateCommit = (await this.gitForPaths(gitMetadataPath, workspacePath, [
781
+ "for-each-ref",
782
+ "--format=%(objectname)",
783
+ MERGE_STATE_REF,
784
+ ])).stdout.trim();
785
+ if (!stateCommit)
786
+ return undefined;
787
+ if (!SAFE_COMMIT_SHA.test(stateCommit))
788
+ throw new Error("vcs_merge_state_invalid");
789
+ const raw = (await this.gitForPaths(gitMetadataPath, workspacePath, ["cat-file", "commit", stateCommit])).stdout;
790
+ const split = raw.indexOf("\n\n");
791
+ if (split < 0)
792
+ throw new Error("vcs_merge_state_invalid");
793
+ const parents = raw
794
+ .slice(0, split)
795
+ .split("\n")
796
+ .filter((line) => line.startsWith("parent "))
797
+ .map((line) => line.slice("parent ".length));
798
+ const message = raw.slice(split + 2);
799
+ if (parents.length !== 2 ||
800
+ parents[0] !== workspace.baseCommit ||
801
+ !SAFE_COMMIT_SHA.test(parents[1]) ||
802
+ !message.startsWith(`${MERGE_STATE_SUBJECT}\n\n`)) {
803
+ throw new Error("vcs_merge_state_invalid");
804
+ }
805
+ let parsed;
806
+ try {
807
+ parsed = JSON.parse(message.slice(MERGE_STATE_SUBJECT.length + 2));
808
+ }
809
+ catch (error) {
810
+ throw new Error("vcs_merge_state_invalid", { cause: error });
811
+ }
812
+ const state = parsed;
813
+ if (typeof state.ref !== "string" ||
814
+ !Array.isArray(state.conflicted) ||
815
+ state.conflicted.length > this.maxChangedFiles ||
816
+ state.conflicted.some((path) => typeof path !== "string")) {
817
+ throw new Error("vcs_merge_state_invalid");
818
+ }
819
+ const ref = safeGitRef(state.ref);
820
+ if (!ref)
821
+ throw new Error("vcs_merge_state_invalid");
822
+ return {
823
+ ref,
824
+ targetCommit: parents[1],
825
+ conflictedPaths: state.conflicted.map(validateChangedPath),
826
+ stateCommit,
827
+ };
828
+ }
829
+ /**
830
+ * Refuses to finalize while a file the merge left conflicted still holds a
831
+ * conflict marker pair. Only those files are read: elsewhere a line of
832
+ * `<<<<<<<` may be legitimate content (a fixture, a doc about merging).
833
+ */
834
+ async assertConflictsResolved(workspacePath, conflictedPaths) {
835
+ for (const path of conflictedPaths) {
836
+ const fullPath = resolve(workspacePath, path);
837
+ if (!fullPath.startsWith(`${workspacePath}${sep}`))
838
+ throw new Error("vcs_changed_path_invalid");
839
+ // One no-follow open, then stat and read through that handle: nothing can swap the file in between.
840
+ let handle;
841
+ try {
842
+ handle = await open(fullPath, fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0));
843
+ }
844
+ catch (error) {
845
+ const code = error.code;
846
+ // Deleted while resolving, or a symlink (ELOOP): nothing left to hold a marker.
847
+ if (code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP")
848
+ continue;
849
+ throw error;
850
+ }
851
+ let content;
852
+ try {
853
+ // Not a regular file (a directory now stands there): nothing to scan.
854
+ if (!(await handle.stat()).isFile())
855
+ continue;
856
+ content = await handle.readFile("utf8");
857
+ }
858
+ finally {
859
+ await handle.close();
860
+ }
861
+ if (CONFLICT_MARKER_START.test(content) && CONFLICT_MARKER_END.test(content)) {
862
+ throw new Error(`vcs_conflict_markers_remain:${path}`);
863
+ }
864
+ }
865
+ }
564
866
  async inspectWorkspace(workspacePath) {
565
867
  const rootStat = await lstat(workspacePath);
566
868
  if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
@@ -1,6 +1,6 @@
1
1
  import { type GitHubRepositoryAccess, type RepositoryFileInput } from "./github.js";
2
2
  import type { GitRemote, PublishInput, PublishResult } from "./remote.js";
3
- import type { ContinuationFinishedDetails, ContinuationOutcome, PreparedWorkspace } from "./types.js";
3
+ import type { ContinuationFinishedDetails, ContinuationOutcome, ContinuationTarget, DescriptionWriteOutcome, FinalizeChangesDetails, PreparedWorkspace } from "./types.js";
4
4
  export interface GitHubRemoteOptions {
5
5
  github: GitHubRepositoryAccess;
6
6
  /** Test-only transport override; production composition always uses github.com. */
@@ -42,7 +42,30 @@ export declare class GitHubRemote implements GitRemote {
42
42
  rootRunId: string;
43
43
  };
44
44
  }): Promise<void>;
45
- publish({ workspace: prepared, details, changedPaths }: PublishInput): Promise<PublishResult>;
45
+ /** See GitRemote.pullRequestBase: the root run's open PR's current base branch. Never throws. */
46
+ pullRequestBase(input: {
47
+ runId: string;
48
+ repository: string;
49
+ baseRef: string;
50
+ headRef: string;
51
+ continuation?: {
52
+ rootRunId: string;
53
+ };
54
+ }): Promise<{
55
+ ref: string;
56
+ } | null>;
57
+ /** See VcsProvider.continuationPullRequestDraft: GitHub's draft flag on the root run's open PR. Never throws. */
58
+ continuationPullRequestDraft(workspace: PreparedWorkspace): Promise<boolean | undefined>;
59
+ /** A continuation's description comment, written before the push (see GitRemote.proposeDescriptionBeforePush). Never throws. */
60
+ proposeDescriptionBeforePush({ workspace: prepared, details, changedPaths, commitSha, }: PublishInput & {
61
+ commitSha: string;
62
+ }): Promise<void>;
63
+ publish({ workspace: prepared, details, changedPaths, commitSha }: PublishInput): Promise<PublishResult>;
64
+ /** The no-push path: a fix round that changed nothing still re-derives its PR description. */
65
+ refreshDescription(workspace: ContinuationTarget, details: FinalizeChangesDetails): Promise<DescriptionWriteOutcome | undefined>;
66
+ /** Never throws: a description problem must not fail an already-pushed run. */
67
+ private updateDescription;
68
+ private descriptionInput;
46
69
  /**
47
70
  * Best-effort "wardby is working on this PR" signal (see VcsProvider) --
48
71
  * whole body wrapped so this can NEVER throw or otherwise affect the
@@ -62,6 +85,6 @@ export declare class GitHubRemote implements GitRemote {
62
85
  * github.ts). Safe to call more than once for the same run. Same
63
86
  * never-throw contract as notifyContinuationStarted.
64
87
  */
65
- notifyContinuationFinished(workspace: PreparedWorkspace, outcome: ContinuationOutcome, details?: ContinuationFinishedDetails): Promise<void>;
88
+ notifyContinuationFinished(workspace: ContinuationTarget, outcome: ContinuationOutcome, details?: ContinuationFinishedDetails): Promise<void>;
66
89
  readRepositoryFile(input: RepositoryFileInput): Promise<string | null>;
67
90
  }