@wardby/cli 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (740) hide show
  1. package/.env.example +5 -5
  2. package/README.md +6 -1
  3. package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
  4. package/dist/claude-coding-worker/driver.d.ts +33 -3
  5. package/dist/claude-coding-worker/driver.js +151 -21
  6. package/dist/claude-coding-worker/main.js +38 -6
  7. package/dist/claude-coding-worker/sdk.js +29 -2
  8. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  9. package/dist/claude-coding-worker/tool-socket.js +111 -0
  10. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  11. package/dist/claude-coding-worker/transcript.js +77 -0
  12. package/dist/claude-plugin/command.d.ts +61 -0
  13. package/dist/claude-plugin/command.js +376 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +3 -1
  16. package/dist/cli.js +71 -13
  17. package/dist/coding/code-host.d.ts +16 -0
  18. package/dist/coding/code-host.js +60 -0
  19. package/dist/coding/continuation-wording.d.ts +35 -0
  20. package/dist/coding/continuation-wording.js +73 -0
  21. package/dist/coding/linked-issue-note.d.ts +23 -0
  22. package/dist/coding/linked-issue-note.js +47 -0
  23. package/dist/coding/mcp-token.d.ts +12 -0
  24. package/dist/coding/mcp-token.js +26 -0
  25. package/dist/coding/merge-wording.d.ts +28 -0
  26. package/dist/coding/merge-wording.js +78 -0
  27. package/dist/coding/pr-description-note.d.ts +9 -0
  28. package/dist/coding/pr-description-note.js +32 -0
  29. package/dist/coding/profile.d.ts +46 -126
  30. package/dist/coding/profile.js +45 -4
  31. package/dist/coding/protected-path-wording.d.ts +8 -0
  32. package/dist/coding/protected-path-wording.js +1 -1
  33. package/dist/coding/protocol.d.ts +264 -346
  34. package/dist/coding/protocol.js +237 -12
  35. package/dist/coding/redact.d.ts +3 -0
  36. package/dist/coding/redact.js +17 -0
  37. package/dist/coding/registry/allowlist.d.ts +12 -0
  38. package/dist/coding/registry/allowlist.js +14 -1
  39. package/dist/coding/registry/audit-mode.d.ts +153 -0
  40. package/dist/coding/registry/audit-mode.js +304 -0
  41. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  42. package/dist/coding/registry/lockfile-shared.js +128 -0
  43. package/dist/coding/registry/lockfiles.js +1 -1
  44. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  45. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  46. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  47. package/dist/coding/registry/npm-lockfile.js +4 -6
  48. package/dist/coding/registry/npm.js +78 -8
  49. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  50. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  51. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  52. package/dist/coding/registry/pypi-plan.js +406 -0
  53. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  54. package/dist/coding/registry/pypi-requirements.js +155 -0
  55. package/dist/coding/registry/pypi.d.ts +3 -27
  56. package/dist/coding/registry/pypi.js +40 -154
  57. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  58. package/dist/coding/registry/refusal-hints.js +61 -0
  59. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  60. package/dist/coding/registry/refusal-wording.js +56 -0
  61. package/dist/coding/registry/report.d.ts +70 -8
  62. package/dist/coding/registry/report.js +112 -5
  63. package/dist/coding/registry/types.d.ts +58 -8
  64. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  65. package/dist/coding/registry/yarn-lockfile.js +367 -0
  66. package/dist/coding/services/catalog.d.ts +37 -351
  67. package/dist/coding/transcript/claude-code.d.ts +13 -0
  68. package/dist/coding/transcript/claude-code.js +273 -0
  69. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  70. package/dist/coding/transcript/download-protocol.js +18 -0
  71. package/dist/coding/transcript/format.d.ts +20 -0
  72. package/dist/coding/transcript/format.js +32 -0
  73. package/dist/coding/transcript/recorder.d.ts +52 -0
  74. package/dist/coding/transcript/recorder.js +225 -0
  75. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  76. package/dist/coding/transcript/resume/checkout.js +203 -0
  77. package/dist/coding/transcript/resume/command.d.ts +17 -0
  78. package/dist/coding/transcript/resume/command.js +176 -0
  79. package/dist/coding/transcript/resume/download.d.ts +20 -0
  80. package/dist/coding/transcript/resume/download.js +153 -0
  81. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  82. package/dist/coding/transcript/resume/launch.js +128 -0
  83. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  84. package/dist/coding/transcript/resume/session-file.js +79 -0
  85. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  86. package/dist/coding/transcript/resume/stand-in.js +49 -0
  87. package/dist/coding-worker/artifact.d.ts +8 -3
  88. package/dist/coding-worker/artifact.js +3 -1
  89. package/dist/coding-worker/debug-trace.d.ts +9 -6
  90. package/dist/coding-worker/debug-trace.js +16 -19
  91. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  92. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  93. package/dist/coding-worker/driver.d.ts +4 -3
  94. package/dist/coding-worker/driver.js +124 -39
  95. package/dist/coding-worker/errors.d.ts +1 -0
  96. package/dist/coding-worker/errors.js +32 -0
  97. package/dist/coding-worker/main.js +5 -1
  98. package/dist/coding-worker/mcp-config.d.ts +27 -0
  99. package/dist/coding-worker/mcp-config.js +32 -0
  100. package/dist/coding-worker/sdk.d.ts +36 -0
  101. package/dist/coding-worker/sdk.js +28 -1
  102. package/dist/coding-worker/task-note.d.ts +11 -0
  103. package/dist/coding-worker/task-note.js +13 -0
  104. package/dist/coding-worker/types.d.ts +15 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/mcp-call-limit.d.ts +8 -0
  108. package/dist/config/mcp-call-limit.js +18 -0
  109. package/dist/config/mcp-servers.d.ts +8 -0
  110. package/dist/config/mcp-servers.js +12 -0
  111. package/dist/config/providers.d.ts +12 -3
  112. package/dist/config/providers.js +55 -5
  113. package/dist/config/test-simulators.d.ts +92 -0
  114. package/dist/config/test-simulators.js +333 -0
  115. package/dist/config/tool-timeout.d.ts +1 -0
  116. package/dist/config/tool-timeout.js +18 -0
  117. package/dist/core/async-context.d.ts +2 -0
  118. package/dist/core/async-context.js +12 -0
  119. package/dist/core/budget-events.d.ts +108 -0
  120. package/dist/core/budget-events.js +346 -0
  121. package/dist/core/budget-groups.d.ts +50 -1
  122. package/dist/core/budget-groups.js +236 -27
  123. package/dist/core/budget-stopped-head.d.ts +46 -0
  124. package/dist/core/budget-stopped-head.js +81 -0
  125. package/dist/core/budget-topup.d.ts +51 -0
  126. package/dist/core/budget-topup.js +156 -0
  127. package/dist/core/budget-wording.d.ts +16 -2
  128. package/dist/core/budget-wording.js +40 -2
  129. package/dist/core/coding-mcp.d.ts +36 -0
  130. package/dist/core/coding-mcp.js +253 -0
  131. package/dist/core/coding-queue.d.ts +2 -1
  132. package/dist/core/coding-queue.js +7 -0
  133. package/dist/core/coding-repository.d.ts +46 -0
  134. package/dist/core/coding-repository.js +92 -0
  135. package/dist/core/cron.d.ts +19 -1
  136. package/dist/core/cron.js +17 -0
  137. package/dist/core/datastores.js +1 -1
  138. package/dist/core/deferred-coding.d.ts +14 -0
  139. package/dist/core/deferred-coding.js +62 -0
  140. package/dist/core/delegation-child.d.ts +25 -0
  141. package/dist/core/delegation-child.js +37 -0
  142. package/dist/core/delegation-slots.d.ts +27 -0
  143. package/dist/core/delegation-slots.js +44 -0
  144. package/dist/core/dispatch.d.ts +48 -2
  145. package/dist/core/dispatch.js +166 -66
  146. package/dist/core/engine-native.js +1 -1
  147. package/dist/core/error-code.d.ts +38 -0
  148. package/dist/core/error-code.js +169 -0
  149. package/dist/core/grants.d.ts +46 -8
  150. package/dist/core/grants.js +99 -8
  151. package/dist/core/host-events.d.ts +18 -2
  152. package/dist/core/host-events.js +291 -27
  153. package/dist/core/host-status.d.ts +85 -3
  154. package/dist/core/host-status.js +300 -22
  155. package/dist/core/issue-bridge.d.ts +50 -6
  156. package/dist/core/issue-bridge.js +124 -33
  157. package/dist/core/issue-events.d.ts +1 -1
  158. package/dist/core/issue-events.js +4 -10
  159. package/dist/core/issue-status.d.ts +1 -1
  160. package/dist/core/issue-status.js +58 -29
  161. package/dist/core/logger.d.ts +5 -0
  162. package/dist/core/logger.js +14 -1
  163. package/dist/core/lost-run-children.d.ts +6 -0
  164. package/dist/core/lost-run-children.js +32 -0
  165. package/dist/core/mark-ready.d.ts +34 -0
  166. package/dist/core/mark-ready.js +152 -0
  167. package/dist/core/markdown-code.d.ts +8 -0
  168. package/dist/core/markdown-code.js +107 -0
  169. package/dist/core/mcp-client/client.d.ts +47 -0
  170. package/dist/core/mcp-client/client.js +141 -0
  171. package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
  172. package/dist/core/mcp-client/jsonrpc.js +54 -0
  173. package/dist/core/mcp-client/results.d.ts +13 -0
  174. package/dist/core/mcp-client/results.js +42 -0
  175. package/dist/core/mcp-servers.d.ts +90 -0
  176. package/dist/core/mcp-servers.js +230 -0
  177. package/dist/core/mcp-tools.d.ts +108 -0
  178. package/dist/core/mcp-tools.js +287 -0
  179. package/dist/core/memory-tools.js +7 -0
  180. package/dist/core/merge-order-check.d.ts +2 -1
  181. package/dist/core/merge-order-check.js +44 -18
  182. package/dist/core/notification-dispatcher.js +2 -1
  183. package/dist/core/notification-templates.d.ts +1 -7
  184. package/dist/core/notification-templates.js +36 -2
  185. package/dist/core/pull-request-state-sync.js +2 -2
  186. package/dist/core/reconciler.d.ts +4 -3
  187. package/dist/core/reconciler.js +8 -1
  188. package/dist/core/related-pull-requests.d.ts +11 -3
  189. package/dist/core/related-pull-requests.js +49 -20
  190. package/dist/core/reply-parts.d.ts +21 -0
  191. package/dist/core/reply-parts.js +73 -0
  192. package/dist/core/review-fix.d.ts +1 -1
  193. package/dist/core/review-fix.js +4 -3
  194. package/dist/core/review-host-checks.d.ts +1 -1
  195. package/dist/core/review-host-tools.d.ts +3 -0
  196. package/dist/core/review-host-tools.js +102 -14
  197. package/dist/core/review-reads.d.ts +55 -0
  198. package/dist/core/review-reads.js +233 -0
  199. package/dist/core/run-status.d.ts +12 -0
  200. package/dist/core/run-status.js +12 -0
  201. package/dist/core/runner.d.ts +145 -49
  202. package/dist/core/runner.js +719 -216
  203. package/dist/core/schedule-start.d.ts +12 -0
  204. package/dist/core/schedule-start.js +14 -0
  205. package/dist/core/secret-broker-config.d.ts +12 -74
  206. package/dist/core/secret-broker-config.js +1 -1
  207. package/dist/core/secret-guard.d.ts +49 -0
  208. package/dist/core/secret-guard.js +119 -0
  209. package/dist/core/secret-guarded-stores.d.ts +12 -0
  210. package/dist/core/secret-guarded-stores.js +41 -0
  211. package/dist/core/secret-spans.d.ts +50 -0
  212. package/dist/core/secret-spans.js +94 -0
  213. package/dist/core/secrets.d.ts +11 -1
  214. package/dist/core/secrets.js +27 -1
  215. package/dist/core/serializable-retry.d.ts +18 -0
  216. package/dist/core/serializable-retry.js +43 -0
  217. package/dist/core/stop-run.d.ts +46 -0
  218. package/dist/core/stop-run.js +61 -0
  219. package/dist/core/tool-admin.d.ts +5 -1
  220. package/dist/core/tool-admin.js +7 -2
  221. package/dist/core/tool-names.d.ts +13 -0
  222. package/dist/core/tool-names.js +20 -0
  223. package/dist/core/webhooks.d.ts +4 -0
  224. package/dist/core/webhooks.js +68 -49
  225. package/dist/core/workflow-events.d.ts +14 -2
  226. package/dist/core/workflow-events.js +4 -0
  227. package/dist/core/workflow-run-events.d.ts +5 -3
  228. package/dist/core/workflow-run-events.js +45 -9
  229. package/dist/core/zod-json-schema.d.ts +4 -0
  230. package/dist/core/zod-json-schema.js +39 -0
  231. package/dist/core/zod3-window.d.ts +35 -0
  232. package/dist/core/zod3-window.js +124 -0
  233. package/dist/generated/prisma/browser.d.ts +65 -3
  234. package/dist/generated/prisma/client.d.ts +65 -3
  235. package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
  236. package/dist/generated/prisma/enums.d.ts +10 -0
  237. package/dist/generated/prisma/enums.js +8 -0
  238. package/dist/generated/prisma/internal/class.d.ts +110 -0
  239. package/dist/generated/prisma/internal/class.js +4 -4
  240. package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
  241. package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
  242. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
  243. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
  244. package/dist/generated/prisma/models/Agent.d.ts +377 -8
  245. package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
  246. package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
  247. package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
  248. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  249. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
  250. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  251. package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
  252. package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
  253. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  254. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  255. package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
  256. package/dist/generated/prisma/models/HostProvider.js +1 -0
  257. package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
  258. package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
  259. package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
  260. package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
  261. package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
  262. package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
  263. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  264. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  265. package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
  266. package/dist/generated/prisma/models/McpServer.js +1 -0
  267. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
  268. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
  269. package/dist/generated/prisma/models/Principal.d.ts +167 -0
  270. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  271. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  272. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  273. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  274. package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
  275. package/dist/generated/prisma/models/Run.d.ts +738 -2
  276. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  277. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  278. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  279. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  280. package/dist/generated/prisma/models/Secret.d.ts +387 -0
  281. package/dist/generated/prisma/models/Tool.d.ts +223 -1
  282. package/dist/generated/prisma/models.d.ts +10 -0
  283. package/dist/help/search.js +12 -3
  284. package/dist/help-index.json +2033 -110
  285. package/dist/import/create.js +48 -4
  286. package/dist/import/neutral-schema.d.ts +51 -281
  287. package/dist/import/neutral-schema.js +7 -4
  288. package/dist/knowledge/check.d.ts +1 -1
  289. package/dist/knowledge/cli.d.ts +11 -1
  290. package/dist/knowledge/cli.js +37 -4
  291. package/dist/knowledge/concept.d.ts +3 -19
  292. package/dist/knowledge/location.d.ts +31 -0
  293. package/dist/knowledge/location.js +78 -0
  294. package/dist/mcp/auth/access.d.ts +10 -2
  295. package/dist/mcp/auth/access.js +15 -1
  296. package/dist/mcp/auth/grants-cli.d.ts +6 -4
  297. package/dist/mcp/auth/grants-cli.js +42 -3
  298. package/dist/mcp/auth/ownership.d.ts +7 -7
  299. package/dist/mcp/auth/resource-server.d.ts +3 -1
  300. package/dist/mcp/auth/resource-server.js +17 -2
  301. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  302. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  303. package/dist/mcp/context.d.ts +3 -0
  304. package/dist/mcp/host-events/github-ingress.d.ts +2 -0
  305. package/dist/mcp/host-events/github-ingress.js +2 -1
  306. package/dist/mcp/index.d.ts +6 -0
  307. package/dist/mcp/index.js +69 -10
  308. package/dist/mcp/server.d.ts +13 -0
  309. package/dist/mcp/server.js +33 -14
  310. package/dist/mcp/tools/agents.d.ts +4 -0
  311. package/dist/mcp/tools/agents.js +295 -28
  312. package/dist/mcp/tools/datastore.js +17 -8
  313. package/dist/mcp/tools/grants.js +73 -29
  314. package/dist/mcp/tools/host-providers.d.ts +2 -0
  315. package/dist/mcp/tools/host-providers.js +215 -0
  316. package/dist/mcp/tools/mcp-servers.d.ts +26 -0
  317. package/dist/mcp/tools/mcp-servers.js +481 -0
  318. package/dist/mcp/tools/memory.js +11 -1
  319. package/dist/mcp/tools/notification-channels.js +2 -2
  320. package/dist/mcp/tools/packages.d.ts +2 -0
  321. package/dist/mcp/tools/packages.js +195 -0
  322. package/dist/mcp/tools/repositories.js +65 -12
  323. package/dist/mcp/tools/run-access.d.ts +16 -0
  324. package/dist/mcp/tools/run-access.js +25 -0
  325. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  326. package/dist/mcp/tools/run-transcript-download.js +129 -0
  327. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  328. package/dist/mcp/tools/run-transcript.js +70 -0
  329. package/dist/mcp/tools/runs.js +209 -27
  330. package/dist/mcp/tools/scheduling.js +3 -1
  331. package/dist/mcp/tools/secret-elicitation-form.js +5 -0
  332. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  333. package/dist/mcp/tools/secret-elicitation-server.js +10 -61
  334. package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
  335. package/dist/mcp/tools/secret-elicitation.js +25 -2
  336. package/dist/mcp/tools/secrets.js +40 -6
  337. package/dist/mcp/tools/stop-run.d.ts +2 -0
  338. package/dist/mcp/tools/stop-run.js +82 -0
  339. package/dist/mcp/tools/subagents.js +2 -2
  340. package/dist/mcp/tools/tools.d.ts +7 -5
  341. package/dist/mcp/tools/tools.js +64 -16
  342. package/dist/mcp/tools/trigger.js +28 -6
  343. package/dist/mcp/transport/http-limits.d.ts +2 -0
  344. package/dist/mcp/transport/http-limits.js +6 -2
  345. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  346. package/dist/mcp/transport/stdio-link-host.js +67 -0
  347. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  348. package/dist/mcp/transport/streamable-http.js +41 -1
  349. package/dist/mcp/webhooks/ingress.js +10 -0
  350. package/dist/native-worker/docker-launcher.d.ts +38 -2
  351. package/dist/native-worker/docker-launcher.js +65 -5
  352. package/dist/native-worker/gateway-server.d.ts +55 -3
  353. package/dist/native-worker/gateway-server.js +152 -34
  354. package/dist/native-worker/gateway.d.ts +29 -1
  355. package/dist/native-worker/gateway.js +74 -4
  356. package/dist/native-worker/http-server.d.ts +7 -1
  357. package/dist/native-worker/http-server.js +62 -7
  358. package/dist/native-worker/http-transport.js +1 -1
  359. package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
  360. package/dist/native-worker/kubernetes-launcher.js +43 -3
  361. package/dist/native-worker/launch.d.ts +18 -1
  362. package/dist/native-worker/launch.js +6 -1
  363. package/dist/native-worker/ledger.d.ts +24 -4
  364. package/dist/native-worker/ledger.js +62 -8
  365. package/dist/native-worker/loopback.js +3 -8
  366. package/dist/native-worker/main.d.ts +2 -1
  367. package/dist/native-worker/main.js +14 -3
  368. package/dist/native-worker/protocol.d.ts +130 -577
  369. package/dist/native-worker/protocol.js +51 -2
  370. package/dist/native-worker/sandbox-executor.d.ts +17 -2
  371. package/dist/native-worker/sandbox-executor.js +78 -4
  372. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  373. package/dist/native-worker/stderr-redaction.js +237 -0
  374. package/dist/native-worker/stdio.d.ts +1 -1
  375. package/dist/native-worker/stdio.js +6 -5
  376. package/dist/native-worker/warm-pool.d.ts +2 -2
  377. package/dist/native-worker/warm-pool.js +4 -4
  378. package/dist/native-worker/worker.js +28 -2
  379. package/dist/observability/metrics.js +6 -1
  380. package/dist/providers/auth/self-hosted.d.ts +1 -1
  381. package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
  382. package/dist/providers/coding-proxy/capability-hash.js +5 -0
  383. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  384. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  385. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  386. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  387. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  388. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  389. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  390. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  391. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  392. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  393. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  394. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  395. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  396. package/dist/providers/coding-proxy/hold.js +86 -0
  397. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  398. package/dist/providers/coding-proxy/interrupted.js +104 -0
  399. package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
  400. package/dist/providers/coding-proxy/mcp-route.js +166 -0
  401. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
  402. package/dist/providers/coding-proxy/memory-ledger.js +99 -8
  403. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  404. package/dist/providers/coding-proxy/metering.js +27 -4
  405. package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
  406. package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
  407. package/dist/providers/coding-proxy/proxy.d.ts +21 -2
  408. package/dist/providers/coding-proxy/proxy.js +300 -48
  409. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  410. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  411. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  412. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  413. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  414. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  415. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  416. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  417. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  418. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  419. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  420. package/dist/providers/coding-proxy/registry/service.js +579 -112
  421. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  422. package/dist/providers/coding-proxy/registry/store.js +54 -1
  423. package/dist/providers/coding-proxy/runtime.d.ts +10 -0
  424. package/dist/providers/coding-proxy/runtime.js +109 -16
  425. package/dist/providers/coding-proxy/server.d.ts +9 -1
  426. package/dist/providers/coding-proxy/server.js +55 -1
  427. package/dist/providers/coding-proxy/types.d.ts +78 -1
  428. package/dist/providers/datastore/types.d.ts +5 -0
  429. package/dist/providers/engine/types.d.ts +17 -2
  430. package/dist/providers/engine/types.js +17 -0
  431. package/dist/providers/executor/composition.d.ts +10 -3
  432. package/dist/providers/executor/composition.js +52 -7
  433. package/dist/providers/executor/container.d.ts +394 -9
  434. package/dist/providers/executor/container.js +1210 -96
  435. package/dist/providers/executor/dbos-status.d.ts +31 -0
  436. package/dist/providers/executor/dbos-status.js +64 -0
  437. package/dist/providers/executor/dbos.d.ts +50 -1
  438. package/dist/providers/executor/dbos.js +207 -20
  439. package/dist/providers/executor/deferred.d.ts +12 -24
  440. package/dist/providers/executor/deferred.js +10 -29
  441. package/dist/providers/executor/in-process.d.ts +9 -1
  442. package/dist/providers/executor/in-process.js +14 -4
  443. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  444. package/dist/providers/executor/linked-issue-reader.js +30 -0
  445. package/dist/providers/executor/routing.d.ts +2 -0
  446. package/dist/providers/executor/routing.js +4 -0
  447. package/dist/providers/executor/types.d.ts +13 -0
  448. package/dist/providers/host-tools/invoke.d.ts +37 -0
  449. package/dist/providers/host-tools/invoke.js +117 -0
  450. package/dist/providers/host-tools/operations.d.ts +65 -0
  451. package/dist/providers/host-tools/operations.js +149 -0
  452. package/dist/providers/host-tools/registry.d.ts +79 -0
  453. package/dist/providers/host-tools/registry.js +362 -0
  454. package/dist/providers/host-tools/request-guard.d.ts +17 -0
  455. package/dist/providers/host-tools/request-guard.js +99 -0
  456. package/dist/providers/host-tools/self-test.d.ts +64 -0
  457. package/dist/providers/host-tools/self-test.js +142 -0
  458. package/dist/providers/index.d.ts +2 -1
  459. package/dist/providers/issue-tracker/types.d.ts +17 -0
  460. package/dist/providers/issue-tracker/types.js +39 -1
  461. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  462. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  463. package/dist/providers/jobs/docker-isolation.d.ts +10 -2
  464. package/dist/providers/jobs/docker-isolation.js +47 -8
  465. package/dist/providers/jobs/docker.d.ts +9 -0
  466. package/dist/providers/jobs/docker.js +60 -11
  467. package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
  468. package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
  469. package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
  470. package/dist/providers/jobs/kubernetes-api.js +10 -0
  471. package/dist/providers/jobs/kubernetes-client.js +10 -1
  472. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  473. package/dist/providers/jobs/kubernetes-isolation.js +32 -3
  474. package/dist/providers/jobs/kubernetes.d.ts +11 -1
  475. package/dist/providers/jobs/kubernetes.js +111 -17
  476. package/dist/providers/jobs/types.d.ts +39 -0
  477. package/dist/providers/jobs/types.js +13 -1
  478. package/dist/providers/llm/anthropic.js +5 -1
  479. package/dist/providers/llm/bedrock.d.ts +0 -12
  480. package/dist/providers/llm/bedrock.js +4 -0
  481. package/dist/providers/llm/claude-messages.d.ts +3 -1
  482. package/dist/providers/llm/claude-messages.js +4 -1
  483. package/dist/providers/llm/claude-provider.d.ts +2 -2
  484. package/dist/providers/llm/claude-provider.js +2 -2
  485. package/dist/providers/llm/openai.d.ts +2 -2
  486. package/dist/providers/llm/openai.js +6 -2
  487. package/dist/providers/llm/routing.d.ts +2 -2
  488. package/dist/providers/llm/routing.js +2 -2
  489. package/dist/providers/llm/types.d.ts +12 -2
  490. package/dist/providers/review-host/github-events.d.ts +9 -1
  491. package/dist/providers/review-host/github-events.js +34 -12
  492. package/dist/providers/review-host/github.d.ts +29 -2
  493. package/dist/providers/review-host/github.js +224 -29
  494. package/dist/providers/review-host/local.d.ts +8 -4
  495. package/dist/providers/review-host/local.js +49 -31
  496. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  497. package/dist/providers/review-host/patch-pages.js +176 -0
  498. package/dist/providers/review-host/review-format.d.ts +19 -1
  499. package/dist/providers/review-host/review-format.js +38 -7
  500. package/dist/providers/review-host/types.d.ts +140 -6
  501. package/dist/providers/review-host/types.js +9 -1
  502. package/dist/providers/storage/gcs.d.ts +63 -0
  503. package/dist/providers/storage/gcs.js +69 -0
  504. package/dist/providers/storage/index.d.ts +15 -0
  505. package/dist/providers/storage/index.js +14 -0
  506. package/dist/providers/storage/local.d.ts +24 -0
  507. package/dist/providers/storage/local.js +92 -0
  508. package/dist/providers/storage/meter.d.ts +14 -0
  509. package/dist/providers/storage/meter.js +34 -0
  510. package/dist/providers/storage/s3.d.ts +41 -0
  511. package/dist/providers/storage/s3.js +107 -0
  512. package/dist/providers/storage/types.d.ts +37 -3
  513. package/dist/providers/storage/types.js +21 -4
  514. package/dist/providers/vcs/git.d.ts +39 -4
  515. package/dist/providers/vcs/git.js +339 -26
  516. package/dist/providers/vcs/github-remote.d.ts +26 -3
  517. package/dist/providers/vcs/github-remote.js +124 -14
  518. package/dist/providers/vcs/github.d.ts +183 -44
  519. package/dist/providers/vcs/github.js +455 -56
  520. package/dist/providers/vcs/index.d.ts +1 -1
  521. package/dist/providers/vcs/index.js +9 -2
  522. package/dist/providers/vcs/pr-description.d.ts +127 -0
  523. package/dist/providers/vcs/pr-description.js +270 -0
  524. package/dist/providers/vcs/remote.d.ts +37 -1
  525. package/dist/providers/vcs/remote.js +7 -1
  526. package/dist/providers/vcs/routing.d.ts +16 -8
  527. package/dist/providers/vcs/routing.js +27 -6
  528. package/dist/providers/vcs/types.d.ts +150 -5
  529. package/dist/quickstart/coding-seed.d.ts +14 -3
  530. package/dist/quickstart/coding-seed.js +213 -4
  531. package/dist/quickstart/index.d.ts +5 -0
  532. package/dist/quickstart/index.js +21 -0
  533. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  534. package/dist/quickstart/reviewer-prompt.js +6 -6
  535. package/dist/quickstart-images.json +1 -1
  536. package/dist/sandbox/eval-core.d.ts +12 -2
  537. package/dist/sandbox/eval-core.js +20 -4
  538. package/dist/sandbox/generated/zod.bundle.js +62 -1
  539. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  540. package/dist/sandbox/host-functions.d.ts +5 -0
  541. package/dist/sandbox/host-functions.js +13 -13
  542. package/dist/sandbox/limits.d.ts +4 -1
  543. package/dist/sandbox/limits.js +4 -1
  544. package/dist/sandbox/run-in-sandbox.d.ts +6 -0
  545. package/dist/sandbox/run-in-sandbox.js +14 -2
  546. package/dist/sandbox/safe-fetch.d.ts +2 -0
  547. package/dist/sandbox/safe-fetch.js +1 -1
  548. package/dist/sandbox/secret-broker.d.ts +1 -0
  549. package/dist/sandbox/secret-broker.js +4 -5
  550. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  551. package/dist/sandbox/tool-timeout.d.ts +32 -0
  552. package/dist/sandbox/tool-timeout.js +52 -0
  553. package/dist/sandbox/user-tool.d.ts +8 -1
  554. package/dist/sandbox/user-tool.js +9 -3
  555. package/dist/sandbox/zod-params.d.ts +37 -5
  556. package/dist/sandbox/zod-params.js +181 -26
  557. package/dist/serve.js +8 -1
  558. package/dist/viewer/api-schema.d.ts +349 -2627
  559. package/dist/viewer/api-schema.js +7 -0
  560. package/dist/viewer/build-schemas.js +6 -2
  561. package/dist/viewer/graph.js +2 -1
  562. package/dist/viewer/openapi.js +2 -4
  563. package/dist/wardby-bin.js +15 -0
  564. package/docs/README.md +11 -1
  565. package/docs/agent-recipes.md +95 -24
  566. package/docs/architecture-runtime.md +1 -1
  567. package/docs/claude-code-plugin.md +164 -0
  568. package/docs/code-review-agents.md +557 -41
  569. package/docs/coding-agent-setup.md +566 -8
  570. package/docs/coding-packages.md +1033 -90
  571. package/docs/coding-services.md +27 -12
  572. package/docs/coding-worker-byo-images.md +24 -2
  573. package/docs/coding-worker-isolation.md +183 -37
  574. package/docs/debugging-agent-runs.md +242 -0
  575. package/docs/getting-started-gke.md +129 -141
  576. package/docs/getting-started-identity-provider.md +53 -38
  577. package/docs/getting-started.md +17 -0
  578. package/docs/host-providers.md +294 -0
  579. package/docs/jira-agents.md +17 -8
  580. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  581. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  582. package/docs/knowledge/delegation-admission-slots.md +52 -0
  583. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  584. package/docs/knowledge/import-rename-target.md +52 -0
  585. package/docs/knowledge/index.md +57 -0
  586. package/docs/knowledge/log.md +9 -0
  587. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  588. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  589. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  590. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  591. package/docs/knowledge/overview-cli.md +74 -0
  592. package/docs/knowledge/overview-coding-proxy.md +72 -0
  593. package/docs/knowledge/overview-coding.md +72 -0
  594. package/docs/knowledge/overview-config.md +60 -0
  595. package/docs/knowledge/overview-core.md +72 -0
  596. package/docs/knowledge/overview-deploy.md +83 -0
  597. package/docs/knowledge/overview-mcp.md +61 -0
  598. package/docs/knowledge/overview-prisma.md +72 -0
  599. package/docs/knowledge/overview-providers.md +89 -0
  600. package/docs/knowledge/overview-sandbox.md +83 -0
  601. package/docs/knowledge/overview-surfaces.md +83 -0
  602. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  603. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  604. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  605. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  606. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  607. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  608. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  609. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  610. package/docs/knowledge/warm-input-publication.md +30 -0
  611. package/docs/knowledge/workspace-staging-failure.md +54 -0
  612. package/docs/knowledge.md +54 -14
  613. package/docs/mcp-servers.md +254 -0
  614. package/docs/native-sandbox.md +143 -31
  615. package/docs/observability.md +4 -0
  616. package/docs/security-deployment.md +139 -29
  617. package/docs/slack-notifications.md +35 -19
  618. package/docs/tool-secrets.md +45 -10
  619. package/docs/viewer-api.md +6 -0
  620. package/docs/viewer-api.openapi.yml +1 -1
  621. package/help/admin-viewer.md +28 -2
  622. package/help/agent-recipes.md +33 -2
  623. package/help/architecture-agent.md +11 -6
  624. package/help/brokered-secrets.md +3 -0
  625. package/help/build-claude-code-image.md +1 -1
  626. package/help/build-worker-image.md +3 -1
  627. package/help/builder-agent.md +19 -6
  628. package/help/claude-code-run-pane.md +40 -0
  629. package/help/code-review-agents.md +177 -6
  630. package/help/coding-packages.md +156 -6
  631. package/help/cost-attribution.md +9 -5
  632. package/help/creating-agents.md +14 -1
  633. package/help/dependency-cache.md +143 -0
  634. package/help/deploy-gke.md +15 -8
  635. package/help/errors/budget-exhausted.md +187 -0
  636. package/help/errors/budget-group-exhausted.md +5 -1
  637. package/help/errors/coding-mcp-pins-unavailable.md +35 -0
  638. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  639. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  640. package/help/errors/continuation-closed.md +9 -12
  641. package/help/errors/database-auth-invalid.md +1 -1
  642. package/help/errors/delegation-conflict.md +24 -0
  643. package/help/errors/file-list-truncated.md +45 -0
  644. package/help/errors/full-read-required.md +49 -0
  645. package/help/errors/github-account-not-allowed.md +4 -0
  646. package/help/errors/graph-incomplete.md +43 -0
  647. package/help/errors/graph-limit.md +43 -0
  648. package/help/errors/host-provider-error.md +40 -0
  649. package/help/errors/host-tool-failed.md +36 -0
  650. package/help/errors/mcp-call-limit.md +22 -0
  651. package/help/errors/mcp-call-timeout.md +22 -0
  652. package/help/errors/mcp-server-auth-failed.md +22 -0
  653. package/help/errors/mcp-server-credentials-unavailable.md +45 -0
  654. package/help/errors/mcp-server-error.md +28 -0
  655. package/help/errors/mcp-server-unreachable.md +22 -0
  656. package/help/errors/mcp-servers-off.md +21 -0
  657. package/help/errors/mcp-tool-not-allowed.md +26 -0
  658. package/help/errors/mcp-tool-removed.md +22 -0
  659. package/help/errors/mcp-unavailable.md +25 -0
  660. package/help/errors/merge-conflict.md +49 -0
  661. package/help/errors/native-sandbox-capacity.md +1 -1
  662. package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
  663. package/help/errors/native-sandbox-docker-failed.md +1 -1
  664. package/help/errors/native-sandbox-gateway-error.md +20 -0
  665. package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
  666. package/help/errors/native-sandbox-image-not-pinned.md +1 -1
  667. package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
  668. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  669. package/help/errors/native-sandbox-network-unenforced.md +1 -1
  670. package/help/errors/native-sandbox-requires-catalog.md +1 -1
  671. package/help/errors/native-sandbox-unavailable.md +1 -1
  672. package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
  673. package/help/errors/native-sandbox-worker-exited.md +4 -3
  674. package/help/errors/native-sandbox-worker-lost.md +1 -1
  675. package/help/errors/native-sandbox-worker-unready.md +1 -1
  676. package/help/errors/package-not-allowed-pending.md +52 -0
  677. package/help/errors/package-not-allowed.md +51 -0
  678. package/help/errors/package-refusals.md +43 -0
  679. package/help/errors/patch-cursor-malformed.md +31 -0
  680. package/help/errors/repository-not-listed.md +36 -0
  681. package/help/errors/repository-required.md +36 -0
  682. package/help/errors/run-lost.md +39 -0
  683. package/help/errors/run-transcript-download.md +44 -0
  684. package/help/errors/secret-in-value.md +69 -0
  685. package/help/errors/target-merge.md +40 -0
  686. package/help/errors/tool-timeout.md +38 -0
  687. package/help/fix-merge-conflicts.md +73 -0
  688. package/help/github-app-setup.md +132 -0
  689. package/help/github.md +22 -0
  690. package/help/host-providers.md +40 -0
  691. package/help/identity-and-access.md +6 -1
  692. package/help/jira.md +23 -6
  693. package/help/knowledge.md +16 -7
  694. package/help/local-repositories.md +1 -1
  695. package/help/low-power-mode.md +7 -1
  696. package/help/mcp-servers.md +73 -0
  697. package/help/mcp.md +7 -2
  698. package/help/merge-order-check.md +5 -0
  699. package/help/native-capabilities.md +55 -1
  700. package/help/native-sandbox.md +16 -2
  701. package/help/operating-agents.md +21 -0
  702. package/help/package-audit-mode.md +91 -0
  703. package/help/related-pull-requests.md +17 -10
  704. package/help/repo-instructions-and-skills.md +3 -1
  705. package/help/resume-runs-locally.md +134 -0
  706. package/help/review-fix-rounds.md +33 -1
  707. package/help/sharing-agents.md +59 -0
  708. package/help/slack-notifications.md +19 -5
  709. package/help/status-comments.md +31 -0
  710. package/help/stop-run.md +58 -0
  711. package/help/troubleshooting/budgets.md +28 -0
  712. package/help/troubleshooting/coding-workers.md +86 -7
  713. package/help/troubleshooting/debugging-agent-runs.md +29 -0
  714. package/package.json +18 -10
  715. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  716. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  717. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  718. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  719. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  720. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  721. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  722. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  723. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  724. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  725. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  726. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  727. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  728. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  729. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  730. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  731. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  732. package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
  733. package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
  734. package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
  735. package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
  736. package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
  737. package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
  738. package/prisma/schema.prisma +468 -109
  739. package/scripts/git-askpass.sh +1 -1
  740. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -1,19 +1,41 @@
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
- import { isSafeGitHubInstallationToken } from "./github.js";
13
+ import { isSafeGitAuthToken } from "./remote.js";
11
14
  export const DEFAULT_MAX_CHANGED_FILES = 1_000;
12
15
  export const DEFAULT_MAX_DIFF_BYTES = 1024 * 1024;
13
16
  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}$/;
19
+ const SAFE_GIT_USERNAME = /^[A-Za-z0-9._-]{1,64}$/;
16
20
  const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
21
+ /** Where a continuation's target branch is fetched to (never under refs/remotes, so baseCommit's ref is untouched). */
22
+ const MERGE_TARGET_REF = "refs/wardby/merge-target";
23
+ /** Where the head branch is re-fetched while deepening history (see fetchMergeTarget). */
24
+ const MERGE_HEAD_REF = "refs/wardby/merge-head";
25
+ /**
26
+ * The trusted automatic merge of the target branch, recorded at prepare time:
27
+ * a commit whose tree is the merge result (markers in conflicted files), whose
28
+ * parents are baseCommit and the target commit, and whose message carries the
29
+ * target ref and the conflicted paths as JSON. Recovery and finalize read it
30
+ * back; the agent's changes are measured against its tree.
31
+ */
32
+ const MERGE_STATE_REF = "refs/wardby/merge-state";
33
+ const MERGE_STATE_SUBJECT = "wardby merge state";
34
+ /** How far `fetch --deepen` goes, step by step, looking for a merge base in a depth-1 clone. */
35
+ const MERGE_BASE_DEEPEN_STEPS = [64, 256, 1024, 4096];
36
+ /** 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. */
37
+ const CONFLICT_MARKER_START = /^<{7,}(?: |\r?$)/m;
38
+ const CONFLICT_MARKER_END = /^>{7,}(?: |\r?$)/m;
17
39
  const HARDENED_GIT_CONFIG = [
18
40
  "-c",
19
41
  "core.hooksPath=/dev/null",
@@ -41,11 +63,10 @@ export function redactGitOutput(value, secrets = []) {
41
63
  // MAX_REDACTED_SPAN of margin rather than on all 2 MiB git may have produced
42
64
  // (see redactAndTruncate: the margin is what keeps truncation safe). The rest
43
65
  // 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
- }
66
+ // The shared span-union redactor; any non-empty value counts here, as it always has.
67
+ const output = redactExactSecretValues(value.slice(0, GIT_OUTPUT_DISPLAY_BYTES + MAX_REDACTED_SPAN), secrets, {
68
+ minLength: 1,
69
+ });
49
70
  return redactTokenShapedValues(output).slice(0, GIT_OUTPUT_DISPLAY_BYTES);
50
71
  }
51
72
  /** Runs Git without a shell or inherited application secrets. */
@@ -62,9 +83,12 @@ export class NodeGitCommandRunner {
62
83
  options.askPassPath ?? fileURLToPath(new URL("../../../scripts/git-askpass.sh", import.meta.url));
63
84
  }
64
85
  async run(args, options = {}) {
65
- if (options.authToken !== undefined && !isSafeGitHubInstallationToken(options.authToken)) {
86
+ if (options.authToken !== undefined && !isSafeGitAuthToken(options.authToken)) {
66
87
  throw new Error("git_auth_token_invalid");
67
88
  }
89
+ if (options.authUsername !== undefined && !SAFE_GIT_USERNAME.test(options.authUsername)) {
90
+ throw new Error("git_auth_username_invalid");
91
+ }
68
92
  const env = {
69
93
  PATH: this.path,
70
94
  HOME: this.options.homeDir,
@@ -77,8 +101,11 @@ export class NodeGitCommandRunner {
77
101
  GIT_TERMINAL_PROMPT: "0",
78
102
  GCM_INTERACTIVE: "never",
79
103
  GIT_ASKPASS: options.authToken ? this.askPassPath : "/bin/false",
104
+ ...(options.authToken && options.authUsername ? { WARDBY_GIT_USERNAME: options.authUsername } : {}),
80
105
  SSH_ASKPASS: "/bin/false",
81
106
  GIT_LFS_SKIP_SMUDGE: "1",
107
+ // WARDBY_TEST_SIMULATORS (test only): the simulator's throwaway CA; empty otherwise.
108
+ ...simulatorGitEnvironment(),
82
109
  };
83
110
  const maxBytes = options.maxOutputBytes ?? MAX_GIT_OUTPUT_BYTES;
84
111
  const secrets = options.authToken ? [options.authToken] : [];
@@ -133,7 +160,7 @@ export class NodeGitCommandRunner {
133
160
  stdout: Buffer.concat(stdout).toString("utf8"),
134
161
  stderr: redactGitOutput(Buffer.concat(stderr).toString("utf8"), secrets),
135
162
  };
136
- if (code !== 0) {
163
+ if (code !== 0 && (code === null || !options.acceptExitCodes?.includes(code))) {
137
164
  rejectPromise(new GitCommandError(code, result.stderr.trim()));
138
165
  return;
139
166
  }
@@ -192,6 +219,26 @@ function nullSeparated(value) {
192
219
  values.pop();
193
220
  return values.map(validateChangedPath);
194
221
  }
222
+ function safeGitRef(value) {
223
+ try {
224
+ return normalizeGitRef(value);
225
+ }
226
+ catch {
227
+ return null;
228
+ }
229
+ }
230
+ /** The merge state's message: a fixed subject, then the target ref and conflicted paths as JSON. */
231
+ function mergeStateMessage(targetMerge) {
232
+ return `${MERGE_STATE_SUBJECT}\n\n${JSON.stringify({ ref: targetMerge.ref, conflicted: targetMerge.conflictedPaths })}\n`;
233
+ }
234
+ function sameTargetMerge(left, right) {
235
+ if (!left || !right)
236
+ return left === right;
237
+ return (left.ref === right.ref &&
238
+ left.targetCommit === right.targetCommit &&
239
+ left.conflictedPaths.length === right.conflictedPaths.length &&
240
+ left.conflictedPaths.every((path, index) => path === right.conflictedPaths[index]));
241
+ }
195
242
  function directChild(root, child) {
196
243
  return child.startsWith(`${root}${sep}`) && !child.slice(root.length + 1).includes(sep);
197
244
  }
@@ -244,9 +291,14 @@ export class GitVcsProvider {
244
291
  // baseCommit already means exactly what it needs to: "where this
245
292
  // round started."
246
293
  const cloneBranch = normalized.continuation ? normalized.headRef : normalized.baseRef;
294
+ // A continuation is first brought up to date with the branch its pull
295
+ // request targets now (a person may have retargeted it since the root run).
296
+ const target = normalized.continuation ? await this.remote.pullRequestBase?.(normalized) : null;
297
+ const mergeRef = target ? safeGitRef(target.ref) : null;
298
+ let mergeFetched = false;
247
299
  try {
248
300
  await this.remote.withAccess(normalized.repository, async (token) => {
249
- const auth = token !== undefined ? { authToken: token } : {};
301
+ const auth = this.gitAuth(token);
250
302
  if (this.remote.refNotFoundError) {
251
303
  const listed = await this.git.run([
252
304
  ...HARDENED_GIT_CONFIG,
@@ -280,6 +332,9 @@ export class GitVcsProvider {
280
332
  cloneUrl,
281
333
  workspacePath,
282
334
  ], { cwd: runRoot, ...auth });
335
+ if (mergeRef && mergeRef !== normalized.headRef) {
336
+ mergeFetched = await this.fetchMergeTarget(gitMetadataPath, workspacePath, cloneBranch, mergeRef, auth);
337
+ }
283
338
  });
284
339
  await rm(resolve(workspacePath, ".git"), { force: true });
285
340
  const baseCommit = await this.revParseRaw(gitMetadataPath, workspacePath, `refs/remotes/origin/${cloneBranch}^{commit}`);
@@ -307,7 +362,15 @@ export class GitVcsProvider {
307
362
  "HEAD",
308
363
  `refs/heads/${normalized.headRef}`,
309
364
  ]);
310
- await this.gitForPaths(gitMetadataPath, workspacePath, ["read-tree", "--reset", "-u", baseCommit]);
365
+ const merged = mergeFetched && mergeRef
366
+ ? await this.mergeTargetBranch(gitMetadataPath, workspacePath, baseCommit, mergeRef)
367
+ : null;
368
+ await this.gitForPaths(gitMetadataPath, workspacePath, [
369
+ "read-tree",
370
+ "--reset",
371
+ "-u",
372
+ merged?.tree ?? baseCommit,
373
+ ]);
311
374
  await this.inspectWorkspace(workspacePath);
312
375
  return {
313
376
  id: `vcs-${normalized.runId}`,
@@ -315,6 +378,7 @@ export class GitVcsProvider {
315
378
  baseCommit,
316
379
  workspacePath,
317
380
  gitMetadataPath,
381
+ ...(merged ? { targetMerge: merged.targetMerge } : {}),
318
382
  };
319
383
  }
320
384
  catch (error) {
@@ -351,19 +415,30 @@ export class GitVcsProvider {
351
415
  const symbolicHead = (await this.gitFor(prepared, ["symbolic-ref", "--short", "HEAD"])).stdout.trim();
352
416
  if (symbolicHead !== prepared.headRef)
353
417
  throw new Error("vcs_head_ref_mismatch");
418
+ const merge = await this.readMergeState(prepared);
354
419
  const currentHead = await this.revParse(prepared, "HEAD");
355
420
  if (currentHead !== prepared.baseCommit) {
356
421
  const parent = await this.revParse(prepared, "HEAD^");
357
422
  if (parent !== prepared.baseCommit)
358
423
  throw new Error("vcs_commit_history_invalid");
424
+ if (merge && (await this.revParse(prepared, "HEAD^2")) !== merge.targetCommit) {
425
+ throw new Error("vcs_commit_history_invalid");
426
+ }
359
427
  }
360
- return prepared;
428
+ if (!merge)
429
+ return prepared;
430
+ const { stateCommit: _stateCommit, ...targetMerge } = merge;
431
+ return { ...prepared, targetMerge };
361
432
  }
362
433
  async finalizeChanges(workspace, details) {
363
434
  const prepared = await this.validatePrepared(workspace);
364
435
  await this.inspectWorkspace(prepared.workspacePath);
365
436
  await this.assertRemote(prepared);
366
437
  await this.assertSafeLocalConfig(prepared.gitMetadataPath);
438
+ // The merge state on disk is the trusted record; the handle must agree with it.
439
+ const merge = await this.readMergeState(prepared);
440
+ if (!sameTargetMerge(merge, prepared.targetMerge))
441
+ throw new Error("vcs_workspace_handle_invalid");
367
442
  // Excluded paths (src/coding/collect-exclude.ts) are never collected from the worker, so
368
443
  // they are also neither added nor deleted here: tracked files under them stay untouched.
369
444
  await this.gitFor(prepared, [
@@ -373,15 +448,12 @@ export class GitVcsProvider {
373
448
  ":/",
374
449
  ...gitExcludePathspecs(normalizeCollectExclusions(prepared.collectExclude)),
375
450
  ]);
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);
451
+ // Every check below applies to the agent's own changes: against baseCommit, or, after a
452
+ // merge, against the trusted automatic merge result (so the target branch's own changes,
453
+ // protected paths included, pass, while any agent edit -- a conflict it resolved, a
454
+ // target change it reverted -- is checked).
455
+ const comparedTo = merge?.stateCommit ?? prepared.baseCommit;
456
+ const changed = nullSeparated((await this.gitFor(prepared, ["diff", "--cached", "--name-only", "-z", "--no-renames", comparedTo, "--"])).stdout);
385
457
  if (changed.length > this.maxChangedFiles)
386
458
  throw new Error("vcs_changed_file_limit");
387
459
  const protectedChange = changed.find(protectedPathMatcher(prepared.protectedPaths));
@@ -389,7 +461,7 @@ export class GitVcsProvider {
389
461
  throw new Error(`vcs_protected_path:${protectedChange}`);
390
462
  let diff;
391
463
  try {
392
- diff = (await this.gitFor(prepared, ["diff", "--cached", "--binary", "--no-ext-diff", "--no-textconv", prepared.baseCommit, "--"], { maxOutputBytes: this.maxDiffBytes })).stdout;
464
+ diff = (await this.gitFor(prepared, ["diff", "--cached", "--binary", "--no-ext-diff", "--no-textconv", comparedTo, "--"], { maxOutputBytes: this.maxDiffBytes })).stdout;
393
465
  }
394
466
  catch (error) {
395
467
  if (error instanceof GitCommandError && error.message.includes("git_output_limit")) {
@@ -399,8 +471,12 @@ export class GitVcsProvider {
399
471
  }
400
472
  if (Buffer.byteLength(diff, "utf8") > this.maxDiffBytes)
401
473
  throw new Error("vcs_diff_size_limit");
474
+ // After the size limits, so a conflicted file is never read past what the diff limit allows.
475
+ if (merge)
476
+ await this.assertConflictsResolved(prepared.workspacePath, merge.conflictedPaths);
402
477
  const currentHead = await this.revParse(prepared, "HEAD");
403
- if (changed.length === 0 && currentHead === prepared.baseCommit) {
478
+ // A merge with no agent edits still has the merge itself to push.
479
+ if (!merge && changed.length === 0 && currentHead === prepared.baseCommit) {
404
480
  return {
405
481
  outcome: "no_changes",
406
482
  repository: prepared.repository,
@@ -412,7 +488,10 @@ export class GitVcsProvider {
412
488
  if (symbolicHead !== prepared.headRef)
413
489
  throw new Error("vcs_head_ref_mismatch");
414
490
  let commitSha;
415
- if (currentHead === prepared.baseCommit) {
491
+ if (currentHead === prepared.baseCommit && merge) {
492
+ commitSha = await this.commitMerge(prepared, merge);
493
+ }
494
+ else if (currentHead === prepared.baseCommit) {
416
495
  await this.gitFor(prepared, ["commit", "--no-verify", "--no-gpg-sign", "-m", `Wardby run ${prepared.runId}`]);
417
496
  commitSha = await this.revParse(prepared, "HEAD");
418
497
  }
@@ -420,14 +499,21 @@ export class GitVcsProvider {
420
499
  const parent = await this.revParse(prepared, "HEAD^");
421
500
  if (parent !== prepared.baseCommit)
422
501
  throw new Error("vcs_commit_history_invalid");
502
+ if (merge && (await this.revParse(prepared, "HEAD^2")) !== merge.targetCommit) {
503
+ throw new Error("vcs_commit_history_invalid");
504
+ }
423
505
  const afterCommitChanges = nullSeparated((await this.gitFor(prepared, ["diff", "--cached", "--name-only", "-z", "HEAD", "--"])).stdout);
424
506
  if (afterCommitChanges.length > 0)
425
507
  throw new Error("vcs_finalized_workspace_changed");
426
508
  commitSha = currentHead;
427
509
  }
428
510
  await this.remote.assertContinuationOpen(prepared);
511
+ // Before the push: a description comment must already exist when the push starts a review.
512
+ await this.remote
513
+ .proposeDescriptionBeforePush?.({ workspace: prepared, details, changedPaths: changed, commitSha })
514
+ .catch(() => undefined);
429
515
  await this.pushOnce(prepared, commitSha);
430
- const published = await this.remote.publish({ workspace: prepared, details, changedPaths: changed });
516
+ const published = await this.remote.publish({ workspace: prepared, details, changedPaths: changed, commitSha });
431
517
  if (published.kind === "branch") {
432
518
  if (published.branch !== prepared.headRef)
433
519
  throw new Error("vcs_head_ref_mismatch");
@@ -449,8 +535,47 @@ export class GitVcsProvider {
449
535
  commitSha,
450
536
  pullRequestNumber: published.number,
451
537
  pullRequestUrl: published.url,
538
+ ...(published.description ? { description: published.description } : {}),
539
+ ...(merge && prepared.continuation
540
+ ? {
541
+ targetMerge: {
542
+ ref: merge.ref,
543
+ targetCommit: merge.targetCommit,
544
+ conflicts: merge.conflictedPaths.length,
545
+ },
546
+ }
547
+ : {}),
452
548
  };
453
549
  }
550
+ /** The two-parent merge commit (baseCommit, the target) of the staged tree, as the Wardby identity. */
551
+ async commitMerge(prepared, merge) {
552
+ const tree = (await this.gitFor(prepared, ["write-tree"])).stdout.trim();
553
+ if (!SAFE_COMMIT_SHA.test(tree))
554
+ throw new Error("vcs_commit_sha_invalid");
555
+ const commitSha = (await this.gitFor(prepared, [
556
+ "commit-tree",
557
+ tree,
558
+ "-p",
559
+ prepared.baseCommit,
560
+ "-p",
561
+ merge.targetCommit,
562
+ "-m",
563
+ `Merge ${merge.ref} into ${prepared.headRef} (Wardby run ${prepared.runId})`,
564
+ ])).stdout.trim();
565
+ if (!SAFE_COMMIT_SHA.test(commitSha))
566
+ throw new Error("vcs_commit_sha_invalid");
567
+ await this.gitFor(prepared, ["update-ref", `refs/heads/${prepared.headRef}`, commitSha, prepared.baseCommit]);
568
+ return commitSha;
569
+ }
570
+ /** Re-derive a continuation's PR description without a push, delegated to the remote; never throws. */
571
+ async refreshPullRequestDescription(workspace, details) {
572
+ try {
573
+ return await this.remote.refreshDescription?.(workspace, details);
574
+ }
575
+ catch {
576
+ return { kind: "skipped", reason: "error" };
577
+ }
578
+ }
454
579
  async cleanup(workspace) {
455
580
  const expected = this.expectedPaths(workspace.runId);
456
581
  if (workspace.id !== `vcs-${workspace.runId}` ||
@@ -465,6 +590,15 @@ export class GitVcsProvider {
465
590
  * delegated to the remote; a remote without one is a no-op. Wrapped so
466
591
  * this can NEVER throw or otherwise affect the real coding run.
467
592
  */
593
+ /** Delegated to the remote; never throws (undefined on any failure). */
594
+ async continuationPullRequestDraft(workspace) {
595
+ try {
596
+ return await this.remote.continuationPullRequestDraft?.(workspace);
597
+ }
598
+ catch {
599
+ return undefined;
600
+ }
601
+ }
468
602
  async notifyContinuationStarted(workspace, details) {
469
603
  try {
470
604
  await this.remote.notifyContinuationStarted?.(workspace, details);
@@ -561,6 +695,179 @@ export class GitVcsProvider {
561
695
  }
562
696
  return { ...workspace, ...normalized };
563
697
  }
698
+ /**
699
+ * Fetches a continuation's target branch from the same `origin` the clone
700
+ * came from (never another URL, so never a fork) and deepens the depth-1
701
+ * clone step by step until the head and the target share a merge base.
702
+ * Returns true once they do; throws vcs_target_merge_failed when the fetch
703
+ * fails or no merge base turns up within MERGE_BASE_DEEPEN_STEPS.
704
+ */
705
+ async fetchMergeTarget(gitMetadataPath, workspacePath, cloneBranch, ref, auth) {
706
+ const fetch = (depth, refspec) => this.gitForPaths(gitMetadataPath, workspacePath, [...this.remote.gitConfig, "fetch", "--no-tags", "--no-write-fetch-head", ...depth, "origin", refspec], auth);
707
+ const target = `+refs/heads/${ref}:${MERGE_TARGET_REF}`;
708
+ // The head is deepened through its own ref under refs/wardby, so the clone's
709
+ // refs/remotes/origin/<head> (baseCommit) never moves.
710
+ const head = `+refs/heads/${cloneBranch}:${MERGE_HEAD_REF}`;
711
+ try {
712
+ await fetch(["--depth", "1"], target);
713
+ for (const step of [0, ...MERGE_BASE_DEEPEN_STEPS]) {
714
+ if (step > 0) {
715
+ // One fetch per side: newer git deepens only the refs a fetch names
716
+ // (older git deepened every shallow boundary), and a fetch naming
717
+ // both deepens only one of them.
718
+ await fetch([`--deepen=${step}`], head);
719
+ await fetch([`--deepen=${step}`], target);
720
+ }
721
+ const base = await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-base", `refs/remotes/origin/${cloneBranch}`, MERGE_TARGET_REF], { acceptExitCodes: [1] });
722
+ if (base.stdout.trim())
723
+ return true;
724
+ }
725
+ }
726
+ catch (error) {
727
+ throw new Error("vcs_target_merge_failed", { cause: error });
728
+ }
729
+ throw new Error("vcs_target_merge_failed");
730
+ }
731
+ /**
732
+ * Merges the fetched target into baseCommit without touching the index or
733
+ * the working tree (`merge-tree --write-tree`: no MERGE_HEAD, no hooks, no
734
+ * merge drivers -- none are configured), and records the result as the merge
735
+ * state. Null when the target is already part of the branch (nothing to merge).
736
+ */
737
+ async mergeTargetBranch(gitMetadataPath, workspacePath, baseCommit, ref) {
738
+ const targetCommit = await this.revParseRaw(gitMetadataPath, workspacePath, `${MERGE_TARGET_REF}^{commit}`);
739
+ const mergeBase = (await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-base", baseCommit, targetCommit])).stdout.trim();
740
+ if (mergeBase === targetCommit)
741
+ return null;
742
+ // The clone is --no-checkout and nothing is read into the index or the
743
+ // working tree until after this merge, so no repository .gitattributes
744
+ // (a marker size, `-merge`, `merge=union`) can steer it.
745
+ let output;
746
+ try {
747
+ output = (await this.gitForPaths(gitMetadataPath, workspacePath, ["merge-tree", "--write-tree", "-z", "--name-only", "--no-messages", baseCommit, targetCommit], { acceptExitCodes: [1] })).stdout;
748
+ }
749
+ catch (error) {
750
+ throw new Error("vcs_target_merge_failed", { cause: error });
751
+ }
752
+ const [tree, ...paths] = output.split("\0");
753
+ if (!SAFE_COMMIT_SHA.test(tree))
754
+ throw new Error("vcs_target_merge_failed");
755
+ const conflictedPaths = [...new Set(paths.filter(Boolean))].map(validateChangedPath);
756
+ if (conflictedPaths.length > this.maxChangedFiles)
757
+ throw new Error("vcs_target_merge_failed");
758
+ const targetMerge = { ref, targetCommit, conflictedPaths };
759
+ // The message goes through a file: a long conflicted-path list could pass an argument's size limit.
760
+ const messagePath = resolve(gitMetadataPath, "WARDBY_MERGE_STATE_MSG");
761
+ await writeFile(messagePath, mergeStateMessage(targetMerge), { mode: 0o600 });
762
+ try {
763
+ const stateCommit = (await this.gitForPaths(gitMetadataPath, workspacePath, [
764
+ "commit-tree",
765
+ tree,
766
+ "-p",
767
+ baseCommit,
768
+ "-p",
769
+ targetCommit,
770
+ "-F",
771
+ messagePath,
772
+ ])).stdout.trim();
773
+ if (!SAFE_COMMIT_SHA.test(stateCommit))
774
+ throw new Error("vcs_commit_sha_invalid");
775
+ await this.gitForPaths(gitMetadataPath, workspacePath, ["update-ref", MERGE_STATE_REF, stateCommit]);
776
+ }
777
+ finally {
778
+ await rm(messagePath, { force: true });
779
+ }
780
+ return { tree, targetMerge };
781
+ }
782
+ /** The recorded merge state (see MERGE_STATE_REF), validated, or undefined when the workspace merged nothing. */
783
+ async readMergeState(workspace) {
784
+ const { gitMetadataPath, workspacePath } = workspace;
785
+ const stateCommit = (await this.gitForPaths(gitMetadataPath, workspacePath, [
786
+ "for-each-ref",
787
+ "--format=%(objectname)",
788
+ MERGE_STATE_REF,
789
+ ])).stdout.trim();
790
+ if (!stateCommit)
791
+ return undefined;
792
+ if (!SAFE_COMMIT_SHA.test(stateCommit))
793
+ throw new Error("vcs_merge_state_invalid");
794
+ const raw = (await this.gitForPaths(gitMetadataPath, workspacePath, ["cat-file", "commit", stateCommit])).stdout;
795
+ const split = raw.indexOf("\n\n");
796
+ if (split < 0)
797
+ throw new Error("vcs_merge_state_invalid");
798
+ const parents = raw
799
+ .slice(0, split)
800
+ .split("\n")
801
+ .filter((line) => line.startsWith("parent "))
802
+ .map((line) => line.slice("parent ".length));
803
+ const message = raw.slice(split + 2);
804
+ if (parents.length !== 2 ||
805
+ parents[0] !== workspace.baseCommit ||
806
+ !SAFE_COMMIT_SHA.test(parents[1]) ||
807
+ !message.startsWith(`${MERGE_STATE_SUBJECT}\n\n`)) {
808
+ throw new Error("vcs_merge_state_invalid");
809
+ }
810
+ let parsed;
811
+ try {
812
+ parsed = JSON.parse(message.slice(MERGE_STATE_SUBJECT.length + 2));
813
+ }
814
+ catch (error) {
815
+ throw new Error("vcs_merge_state_invalid", { cause: error });
816
+ }
817
+ const state = parsed;
818
+ if (typeof state.ref !== "string" ||
819
+ !Array.isArray(state.conflicted) ||
820
+ state.conflicted.length > this.maxChangedFiles ||
821
+ state.conflicted.some((path) => typeof path !== "string")) {
822
+ throw new Error("vcs_merge_state_invalid");
823
+ }
824
+ const ref = safeGitRef(state.ref);
825
+ if (!ref)
826
+ throw new Error("vcs_merge_state_invalid");
827
+ return {
828
+ ref,
829
+ targetCommit: parents[1],
830
+ conflictedPaths: state.conflicted.map(validateChangedPath),
831
+ stateCommit,
832
+ };
833
+ }
834
+ /**
835
+ * Refuses to finalize while a file the merge left conflicted still holds a
836
+ * conflict marker pair. Only those files are read: elsewhere a line of
837
+ * `<<<<<<<` may be legitimate content (a fixture, a doc about merging).
838
+ */
839
+ async assertConflictsResolved(workspacePath, conflictedPaths) {
840
+ for (const path of conflictedPaths) {
841
+ const fullPath = resolve(workspacePath, path);
842
+ if (!fullPath.startsWith(`${workspacePath}${sep}`))
843
+ throw new Error("vcs_changed_path_invalid");
844
+ // One no-follow open, then stat and read through that handle: nothing can swap the file in between.
845
+ let handle;
846
+ try {
847
+ handle = await open(fullPath, fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0));
848
+ }
849
+ catch (error) {
850
+ const code = error.code;
851
+ // Deleted while resolving, or a symlink (ELOOP): nothing left to hold a marker.
852
+ if (code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP")
853
+ continue;
854
+ throw error;
855
+ }
856
+ let content;
857
+ try {
858
+ // Not a regular file (a directory now stands there): nothing to scan.
859
+ if (!(await handle.stat()).isFile())
860
+ continue;
861
+ content = await handle.readFile("utf8");
862
+ }
863
+ finally {
864
+ await handle.close();
865
+ }
866
+ if (CONFLICT_MARKER_START.test(content) && CONFLICT_MARKER_END.test(content)) {
867
+ throw new Error(`vcs_conflict_markers_remain:${path}`);
868
+ }
869
+ }
870
+ }
564
871
  async inspectWorkspace(workspacePath) {
565
872
  const rootStat = await lstat(workspacePath);
566
873
  if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
@@ -635,10 +942,16 @@ export class GitVcsProvider {
635
942
  throw new Error("vcs_git_config_unsafe");
636
943
  }
637
944
  }
945
+ /** The git credentials for a remote's access token; none when the remote needs no token. */
946
+ gitAuth(token) {
947
+ if (token === undefined)
948
+ return {};
949
+ return { authToken: token, ...(this.remote.gitUsername ? { authUsername: this.remote.gitUsername } : {}) };
950
+ }
638
951
  async pushOnce(workspace, commitSha) {
639
952
  this.remote.assertPushRef?.(workspace.headRef);
640
953
  await this.remote.withAccess(workspace.repository, async (token) => {
641
- const auth = token !== undefined ? { authToken: token } : {};
954
+ const auth = this.gitAuth(token);
642
955
  const remote = await this.remoteHead(workspace, auth);
643
956
  if (remote === commitSha)
644
957
  return;
@@ -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
  }