@wardby/cli 0.2.0 → 0.3.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 (491) hide show
  1. package/.env.example +34 -4
  2. package/README.md +183 -71
  3. package/dist/claude-coding-worker/driver.d.ts +7 -1
  4. package/dist/claude-coding-worker/driver.js +31 -2
  5. package/dist/claude-coding-worker/main.js +5 -2
  6. package/dist/claude-coding-worker/tool-socket.d.ts +9 -0
  7. package/dist/claude-coding-worker/tool-socket.js +26 -0
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +13 -4
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +219 -29
  12. package/dist/coding/collect-exclude.d.ts +25 -0
  13. package/dist/coding/collect-exclude.js +76 -0
  14. package/dist/coding/profile.d.ts +67 -22
  15. package/dist/coding/profile.js +58 -25
  16. package/dist/coding/protected-path-wording.d.ts +24 -0
  17. package/dist/coding/protected-path-wording.js +55 -0
  18. package/dist/coding/protected-paths.d.ts +31 -0
  19. package/dist/coding/protected-paths.js +48 -0
  20. package/dist/coding/protocol.d.ts +99 -3
  21. package/dist/coding/protocol.js +155 -4
  22. package/dist/coding/registry/adapters.d.ts +2 -0
  23. package/dist/coding/registry/adapters.js +9 -0
  24. package/dist/coding/registry/allowlist.d.ts +9 -0
  25. package/dist/coding/registry/allowlist.js +28 -0
  26. package/dist/coding/registry/json-scan.d.ts +55 -0
  27. package/dist/coding/registry/json-scan.js +191 -0
  28. package/dist/coding/registry/lockfiles.d.ts +6 -0
  29. package/dist/coding/registry/lockfiles.js +89 -0
  30. package/dist/coding/registry/npm-lockfile.d.ts +9 -0
  31. package/dist/coding/registry/npm-lockfile.js +73 -0
  32. package/dist/coding/registry/npm-plan.d.ts +29 -0
  33. package/dist/coding/registry/npm-plan.js +289 -0
  34. package/dist/coding/registry/npm.d.ts +7 -0
  35. package/dist/coding/registry/npm.js +252 -0
  36. package/dist/coding/registry/pypi.d.ts +4 -0
  37. package/dist/coding/registry/pypi.js +210 -0
  38. package/dist/coding/registry/report.d.ts +37 -0
  39. package/dist/coding/registry/report.js +31 -0
  40. package/dist/coding/registry/token.d.ts +4 -0
  41. package/dist/coding/registry/token.js +7 -0
  42. package/dist/coding/registry/types.d.ts +286 -0
  43. package/dist/coding/registry/types.js +19 -0
  44. package/dist/coding/registry/worker-config.d.ts +14 -0
  45. package/dist/coding/registry/worker-config.js +31 -0
  46. package/dist/coding/services/builtins.d.ts +22 -0
  47. package/dist/coding/services/builtins.js +85 -0
  48. package/dist/coding/services/catalog.d.ts +443 -0
  49. package/dist/coding/services/catalog.js +159 -0
  50. package/dist/coding/services/declaration.d.ts +11 -0
  51. package/dist/coding/services/declaration.js +114 -0
  52. package/dist/coding/services/note.d.ts +8 -0
  53. package/dist/coding/services/note.js +15 -0
  54. package/dist/coding/services/resolve.d.ts +25 -0
  55. package/dist/coding/services/resolve.js +50 -0
  56. package/dist/coding/services/wording.d.ts +25 -0
  57. package/dist/coding/services/wording.js +70 -0
  58. package/dist/coding-proxy/main.js +24 -4
  59. package/dist/coding-worker/artifact.d.ts +18 -0
  60. package/dist/coding-worker/artifact.js +48 -6
  61. package/dist/coding-worker/debug-trace.d.ts +37 -0
  62. package/dist/coding-worker/debug-trace.js +117 -0
  63. package/dist/coding-worker/driver.d.ts +14 -1
  64. package/dist/coding-worker/driver.js +106 -14
  65. package/dist/coding-worker/errors.d.ts +7 -0
  66. package/dist/coding-worker/errors.js +26 -0
  67. package/dist/coding-worker/main.js +13 -4
  68. package/dist/coding-worker/sdk.d.ts +2 -2
  69. package/dist/coding-worker/sdk.js +7 -2
  70. package/dist/coding-worker/types.d.ts +3 -0
  71. package/dist/config/providers.d.ts +41 -0
  72. package/dist/config/providers.js +66 -0
  73. package/dist/core/budget-groups.d.ts +109 -6
  74. package/dist/core/budget-groups.js +125 -19
  75. package/dist/core/budget-wording.d.ts +22 -0
  76. package/dist/core/budget-wording.js +55 -0
  77. package/dist/core/coding-queue.d.ts +1 -1
  78. package/dist/core/datastores.d.ts +1 -1
  79. package/dist/core/datastores.js +18 -2
  80. package/dist/core/db.d.ts +40 -2
  81. package/dist/core/db.js +75 -2
  82. package/dist/core/dispatch.d.ts +49 -7
  83. package/dist/core/dispatch.js +290 -45
  84. package/dist/core/engine-native.js +27 -10
  85. package/dist/core/grants.d.ts +86 -0
  86. package/dist/core/grants.js +126 -0
  87. package/dist/core/host-events.d.ts +49 -0
  88. package/dist/core/host-events.js +257 -0
  89. package/dist/core/host-identity-links.d.ts +54 -0
  90. package/dist/core/host-identity-links.js +189 -0
  91. package/dist/core/host-status.d.ts +61 -0
  92. package/dist/core/host-status.js +211 -0
  93. package/dist/core/http-runtime.js +3 -4
  94. package/dist/core/in-flight-runs.d.ts +8 -0
  95. package/dist/core/in-flight-runs.js +56 -0
  96. package/dist/core/lease.d.ts +1 -1
  97. package/dist/core/private-directory.d.ts +20 -0
  98. package/dist/core/private-directory.js +36 -0
  99. package/dist/core/provider-wording.d.ts +12 -0
  100. package/dist/core/provider-wording.js +44 -0
  101. package/dist/core/reconciler.d.ts +39 -3
  102. package/dist/core/reconciler.js +86 -2
  103. package/dist/core/repo-access.d.ts +99 -0
  104. package/dist/core/repo-access.js +136 -0
  105. package/dist/core/review-host-checks.d.ts +11 -0
  106. package/dist/core/review-host-checks.js +41 -0
  107. package/dist/core/review-host-tools.d.ts +47 -0
  108. package/dist/core/review-host-tools.js +347 -0
  109. package/dist/core/run-heartbeat.d.ts +27 -0
  110. package/dist/core/run-heartbeat.js +54 -0
  111. package/dist/core/runner.d.ts +31 -9
  112. package/dist/core/runner.js +237 -40
  113. package/dist/core/scheduler.d.ts +1 -1
  114. package/dist/core/secrets.d.ts +12 -3
  115. package/dist/core/secrets.js +25 -6
  116. package/dist/core/subagent-memory-tools.d.ts +2 -2
  117. package/dist/core/subagent-memory-tools.js +16 -3
  118. package/dist/core/tool-admin.d.ts +81 -0
  119. package/dist/core/tool-admin.js +129 -0
  120. package/dist/core/tool-names.d.ts +42 -0
  121. package/dist/core/tool-names.js +64 -0
  122. package/dist/core/untrusted-content.d.ts +32 -0
  123. package/dist/core/untrusted-content.js +72 -0
  124. package/dist/core/webhooks.d.ts +9 -2
  125. package/dist/core/webhooks.js +23 -2
  126. package/dist/generated/prisma/browser.d.ts +328 -0
  127. package/dist/generated/prisma/browser.js +17 -0
  128. package/dist/generated/prisma/client.d.ts +347 -0
  129. package/dist/generated/prisma/client.js +34 -0
  130. package/dist/generated/prisma/commonInputTypes.d.ts +839 -0
  131. package/dist/generated/prisma/commonInputTypes.js +10 -0
  132. package/dist/generated/prisma/enums.d.ts +59 -0
  133. package/dist/generated/prisma/enums.js +59 -0
  134. package/dist/generated/prisma/internal/class.d.ts +605 -0
  135. package/dist/generated/prisma/internal/class.js +49 -0
  136. package/dist/generated/prisma/internal/prismaNamespace.d.ts +4494 -0
  137. package/dist/generated/prisma/internal/prismaNamespace.js +628 -0
  138. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +635 -0
  139. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +599 -0
  140. package/dist/generated/prisma/models/Agent.d.ts +3560 -0
  141. package/dist/generated/prisma/models/Agent.js +1 -0
  142. package/dist/generated/prisma/models/AgentDatastore.d.ts +1210 -0
  143. package/dist/generated/prisma/models/AgentDatastore.js +1 -0
  144. package/dist/generated/prisma/models/AgentMemory.d.ts +986 -0
  145. package/dist/generated/prisma/models/AgentMemory.js +1 -0
  146. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  147. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  148. package/dist/generated/prisma/models/AgentSecret.d.ts +1212 -0
  149. package/dist/generated/prisma/models/AgentSecret.js +1 -0
  150. package/dist/generated/prisma/models/AgentSubAgent.d.ts +1217 -0
  151. package/dist/generated/prisma/models/AgentSubAgent.js +1 -0
  152. package/dist/generated/prisma/models/AgentTool.d.ts +1403 -0
  153. package/dist/generated/prisma/models/AgentTool.js +1 -0
  154. package/dist/generated/prisma/models/AuthFormChallenge.d.ts +1298 -0
  155. package/dist/generated/prisma/models/AuthFormChallenge.js +1 -0
  156. package/dist/generated/prisma/models/AuthLoginKey.d.ts +1245 -0
  157. package/dist/generated/prisma/models/AuthLoginKey.js +1 -0
  158. package/dist/generated/prisma/models/AuthRateLimit.d.ts +979 -0
  159. package/dist/generated/prisma/models/AuthRateLimit.js +1 -0
  160. package/dist/generated/prisma/models/AuthSession.d.ts +1376 -0
  161. package/dist/generated/prisma/models/AuthSession.js +1 -0
  162. package/dist/generated/prisma/models/AuthUser.d.ts +1700 -0
  163. package/dist/generated/prisma/models/AuthUser.js +1 -0
  164. package/dist/generated/prisma/models/BudgetGroup.d.ts +1548 -0
  165. package/dist/generated/prisma/models/BudgetGroup.js +1 -0
  166. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +1681 -0
  167. package/dist/generated/prisma/models/CodingAgentProfile.js +1 -0
  168. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +1749 -0
  169. package/dist/generated/prisma/models/CodingProxyRequest.js +1 -0
  170. package/dist/generated/prisma/models/CodingProxySession.d.ts +1626 -0
  171. package/dist/generated/prisma/models/CodingProxySession.js +1 -0
  172. package/dist/generated/prisma/models/CodingRun.d.ts +3583 -0
  173. package/dist/generated/prisma/models/CodingRun.js +1 -0
  174. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  175. package/dist/generated/prisma/models/CodingService.js +1 -0
  176. package/dist/generated/prisma/models/Datastore.d.ts +1434 -0
  177. package/dist/generated/prisma/models/Datastore.js +1 -0
  178. package/dist/generated/prisma/models/DatastoreEntry.d.ts +1314 -0
  179. package/dist/generated/prisma/models/DatastoreEntry.js +1 -0
  180. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  181. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  182. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  183. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  184. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  185. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  186. package/dist/generated/prisma/models/OAuthAuthorizationCode.d.ts +1526 -0
  187. package/dist/generated/prisma/models/OAuthAuthorizationCode.js +1 -0
  188. package/dist/generated/prisma/models/OAuthAuthorizationRequest.d.ts +1350 -0
  189. package/dist/generated/prisma/models/OAuthAuthorizationRequest.js +1 -0
  190. package/dist/generated/prisma/models/OAuthClient.d.ts +1289 -0
  191. package/dist/generated/prisma/models/OAuthClient.js +1 -0
  192. package/dist/generated/prisma/models/OAuthFamily.d.ts +1540 -0
  193. package/dist/generated/prisma/models/OAuthFamily.js +1 -0
  194. package/dist/generated/prisma/models/OAuthGrant.d.ts +1280 -0
  195. package/dist/generated/prisma/models/OAuthGrant.js +1 -0
  196. package/dist/generated/prisma/models/Principal.d.ts +2245 -0
  197. package/dist/generated/prisma/models/Principal.js +1 -0
  198. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  199. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  200. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  201. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  202. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  203. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  204. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  205. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  206. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  207. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  208. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  209. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  210. package/dist/generated/prisma/models/Run.d.ts +2669 -0
  211. package/dist/generated/prisma/models/Run.js +1 -0
  212. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  213. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  214. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  215. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  216. package/dist/generated/prisma/models/SchedulerLease.d.ts +970 -0
  217. package/dist/generated/prisma/models/SchedulerLease.js +1 -0
  218. package/dist/generated/prisma/models/Secret.d.ts +1399 -0
  219. package/dist/generated/prisma/models/Secret.js +1 -0
  220. package/dist/generated/prisma/models/SecretElicitationOutcome.d.ts +973 -0
  221. package/dist/generated/prisma/models/SecretElicitationOutcome.js +1 -0
  222. package/dist/generated/prisma/models/Task.d.ts +1176 -0
  223. package/dist/generated/prisma/models/Task.js +1 -0
  224. package/dist/generated/prisma/models/Tool.d.ts +1490 -0
  225. package/dist/generated/prisma/models/Tool.js +1 -0
  226. package/dist/generated/prisma/models/Webhook.d.ts +1386 -0
  227. package/dist/generated/prisma/models/Webhook.js +1 -0
  228. package/dist/generated/prisma/models.d.ts +45 -0
  229. package/dist/generated/prisma/models.js +1 -0
  230. package/dist/help/build.d.ts +1 -0
  231. package/dist/help/build.js +9 -0
  232. package/dist/help/catalog.d.ts +24 -0
  233. package/dist/help/catalog.js +160 -0
  234. package/dist/help/cli.d.ts +2 -0
  235. package/dist/help/cli.js +65 -0
  236. package/dist/help/runtime.d.ts +3 -0
  237. package/dist/help/runtime.js +44 -0
  238. package/dist/help/search.d.ts +9 -0
  239. package/dist/help/search.js +104 -0
  240. package/dist/help-index.json +660 -0
  241. package/dist/import/cli-args.js +3 -2
  242. package/dist/import/create.d.ts +6 -1
  243. package/dist/import/create.js +68 -14
  244. package/dist/import/index.d.ts +1 -1
  245. package/dist/import/index.js +19 -9
  246. package/dist/import/neutral-schema.d.ts +11 -11
  247. package/dist/mcp/auth/access.d.ts +70 -0
  248. package/dist/mcp/auth/access.js +58 -0
  249. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  250. package/dist/mcp/auth/grants-cli.js +518 -0
  251. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  252. package/dist/mcp/auth/host-account-cli.js +47 -0
  253. package/dist/mcp/auth/ownership.d.ts +37 -63
  254. package/dist/mcp/auth/ownership.js +19 -14
  255. package/dist/mcp/auth/principal.d.ts +1 -1
  256. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  257. package/dist/mcp/auth/repo-authorization.js +51 -0
  258. package/dist/mcp/auth/resource-server.d.ts +32 -3
  259. package/dist/mcp/auth/resource-server.js +84 -3
  260. package/dist/mcp/auth/self-hosted/browser.js +22 -8
  261. package/dist/mcp/auth/self-hosted/cli.d.ts +1 -1
  262. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  263. package/dist/mcp/auth/self-hosted/credentials.d.ts +21 -3
  264. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  265. package/dist/mcp/auth/self-hosted/rate-limit.d.ts +1 -1
  266. package/dist/mcp/auth/self-hosted/session.d.ts +3 -2
  267. package/dist/mcp/context.d.ts +28 -2
  268. package/dist/mcp/errors.d.ts +25 -6
  269. package/dist/mcp/errors.js +98 -0
  270. package/dist/mcp/host-events/github-ingress.d.ts +36 -0
  271. package/dist/mcp/host-events/github-ingress.js +92 -0
  272. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  273. package/dist/mcp/host-events/github-user-callback.js +50 -0
  274. package/dist/mcp/index.d.ts +8 -1
  275. package/dist/mcp/index.js +106 -16
  276. package/dist/mcp/server.d.ts +1 -1
  277. package/dist/mcp/server.js +27 -9
  278. package/dist/mcp/shared/page-style.d.ts +16 -0
  279. package/dist/mcp/shared/page-style.js +129 -0
  280. package/dist/mcp/tasks/manager.d.ts +1 -1
  281. package/dist/mcp/tools/agents.js +447 -49
  282. package/dist/mcp/tools/budget-groups.js +3 -3
  283. package/dist/mcp/tools/datastore.js +23 -16
  284. package/dist/mcp/tools/grants.d.ts +2 -0
  285. package/dist/mcp/tools/grants.js +239 -0
  286. package/dist/mcp/tools/help.d.ts +5 -0
  287. package/dist/mcp/tools/help.js +67 -0
  288. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  289. package/dist/mcp/tools/host-accounts.js +114 -0
  290. package/dist/mcp/tools/memory.d.ts +7 -1
  291. package/dist/mcp/tools/memory.js +5 -5
  292. package/dist/mcp/tools/repositories.d.ts +2 -0
  293. package/dist/mcp/tools/repositories.js +181 -0
  294. package/dist/mcp/tools/runs.d.ts +6 -0
  295. package/dist/mcp/tools/runs.js +60 -6
  296. package/dist/mcp/tools/scheduling.js +4 -7
  297. package/dist/mcp/tools/secret-elicitation-form.d.ts +1 -1
  298. package/dist/mcp/tools/secret-elicitation-form.js +10 -28
  299. package/dist/mcp/tools/secret-elicitation.d.ts +1 -1
  300. package/dist/mcp/tools/secrets.js +18 -6
  301. package/dist/mcp/tools/services.d.ts +2 -0
  302. package/dist/mcp/tools/services.js +222 -0
  303. package/dist/mcp/tools/subagents.js +53 -17
  304. package/dist/mcp/tools/tools.d.ts +41 -0
  305. package/dist/mcp/tools/tools.js +202 -41
  306. package/dist/mcp/tools/trigger.js +36 -6
  307. package/dist/mcp/tools/webhooks.js +15 -4
  308. package/dist/mcp/transport/streamable-http.d.ts +11 -1
  309. package/dist/mcp/transport/streamable-http.js +32 -2
  310. package/dist/mcp/unattended-schedules.d.ts +1 -1
  311. package/dist/mcp/webhooks/ingress.d.ts +1 -1
  312. package/dist/providers/auth/delegating.d.ts +19 -0
  313. package/dist/providers/auth/delegating.js +71 -0
  314. package/dist/providers/auth/index.d.ts +3 -1
  315. package/dist/providers/auth/index.js +11 -0
  316. package/dist/providers/auth/self-hosted.d.ts +4 -3
  317. package/dist/providers/auth/self-hosted.js +16 -4
  318. package/dist/providers/auth/types.d.ts +6 -0
  319. package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
  320. package/dist/providers/coding-proxy/memory-ledger.js +21 -2
  321. package/dist/providers/coding-proxy/metering.d.ts +4 -0
  322. package/dist/providers/coding-proxy/metering.js +28 -2
  323. package/dist/providers/coding-proxy/prisma-ledger.d.ts +18 -1
  324. package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
  325. package/dist/providers/coding-proxy/proxy.d.ts +13 -0
  326. package/dist/providers/coding-proxy/proxy.js +479 -18
  327. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  328. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  329. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  330. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  331. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  332. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  333. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  334. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  335. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  336. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  337. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  338. package/dist/providers/coding-proxy/registry/store.js +70 -0
  339. package/dist/providers/coding-proxy/runtime.d.ts +18 -1
  340. package/dist/providers/coding-proxy/runtime.js +63 -0
  341. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  342. package/dist/providers/coding-proxy/server.d.ts +11 -0
  343. package/dist/providers/coding-proxy/server.js +163 -0
  344. package/dist/providers/coding-proxy/types.d.ts +15 -0
  345. package/dist/providers/datastore/postgres.d.ts +1 -1
  346. package/dist/providers/engine/types.d.ts +10 -0
  347. package/dist/providers/executor/build.d.ts +3 -3
  348. package/dist/providers/executor/composition.d.ts +4 -1
  349. package/dist/providers/executor/composition.js +19 -0
  350. package/dist/providers/executor/container.d.ts +106 -4
  351. package/dist/providers/executor/container.js +305 -22
  352. package/dist/providers/executor/dbos.d.ts +3 -4
  353. package/dist/providers/executor/in-process.d.ts +2 -3
  354. package/dist/providers/executor/routing.d.ts +7 -0
  355. package/dist/providers/executor/routing.js +13 -0
  356. package/dist/providers/executor/types.d.ts +22 -0
  357. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  358. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  359. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  360. package/dist/providers/jobs/collect-prune.js +27 -0
  361. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  362. package/dist/providers/jobs/docker-isolation.js +213 -22
  363. package/dist/providers/jobs/docker-services.d.ts +35 -0
  364. package/dist/providers/jobs/docker-services.js +191 -0
  365. package/dist/providers/jobs/docker.d.ts +60 -2
  366. package/dist/providers/jobs/docker.js +313 -50
  367. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  368. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  369. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  370. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  371. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  372. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  373. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  374. package/dist/providers/jobs/kubernetes.d.ts +21 -2
  375. package/dist/providers/jobs/kubernetes.js +117 -31
  376. package/dist/providers/jobs/types.d.ts +20 -0
  377. package/dist/providers/llm/anthropic.js +6 -2
  378. package/dist/providers/llm/bedrock.js +2 -1
  379. package/dist/providers/llm/claude-messages.d.ts +5 -1
  380. package/dist/providers/llm/claude-messages.js +1 -0
  381. package/dist/providers/llm/claude-provider.d.ts +3 -1
  382. package/dist/providers/llm/claude-provider.js +5 -1
  383. package/dist/providers/llm/index.d.ts +1 -1
  384. package/dist/providers/llm/index.js +1 -1
  385. package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
  386. package/dist/providers/llm/pricing-anthropic.js +32 -14
  387. package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
  388. package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
  389. package/dist/providers/llm/routing.d.ts +10 -1
  390. package/dist/providers/llm/routing.js +18 -0
  391. package/dist/providers/llm/types.d.ts +12 -0
  392. package/dist/providers/llm/types.js +8 -1
  393. package/dist/providers/memory/postgres.d.ts +1 -1
  394. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  395. package/dist/providers/review-host/diff-lines.js +59 -0
  396. package/dist/providers/review-host/github-events.d.ts +6 -0
  397. package/dist/providers/review-host/github-events.js +180 -0
  398. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  399. package/dist/providers/review-host/github-user-auth.js +128 -0
  400. package/dist/providers/review-host/github.d.ts +57 -0
  401. package/dist/providers/review-host/github.js +567 -0
  402. package/dist/providers/review-host/index.d.ts +12 -0
  403. package/dist/providers/review-host/index.js +30 -0
  404. package/dist/providers/review-host/review-format.d.ts +19 -0
  405. package/dist/providers/review-host/review-format.js +59 -0
  406. package/dist/providers/review-host/types.d.ts +284 -0
  407. package/dist/providers/review-host/types.js +24 -0
  408. package/dist/providers/vcs/git.d.ts +16 -6
  409. package/dist/providers/vcs/git.js +79 -14
  410. package/dist/providers/vcs/github.d.ts +74 -3
  411. package/dist/providers/vcs/github.js +195 -15
  412. package/dist/providers/vcs/types.d.ts +42 -4
  413. package/dist/quickstart/index.js +34 -32
  414. package/dist/quickstart/migrate.d.ts +23 -0
  415. package/dist/quickstart/migrate.js +125 -0
  416. package/dist/sandbox/fetch-policy.d.ts +20 -2
  417. package/dist/sandbox/fetch-policy.js +64 -3
  418. package/dist/sandbox/host-functions.d.ts +9 -1
  419. package/dist/sandbox/host-functions.js +12 -5
  420. package/dist/serve.js +1 -1
  421. package/dist/wardby-bin.js +6 -0
  422. package/docs/README.md +30 -0
  423. package/docs/architecture-runtime.md +90 -0
  424. package/docs/assets/brand/wardby-icon-512.png +0 -0
  425. package/docs/assets/brand/wardby-icon.svg +16 -0
  426. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  427. package/docs/assets/brand/wardby-mascot.png +0 -0
  428. package/docs/assets/brand/wardby-mascot.svg +5 -0
  429. package/docs/assets/wardby-workflow.svg +106 -0
  430. package/docs/code-review-agents.md +481 -0
  431. package/docs/coding-agent-setup.md +172 -0
  432. package/docs/coding-packages.md +455 -0
  433. package/docs/coding-services.md +300 -0
  434. package/docs/coding-worker-byo-images.md +98 -0
  435. package/docs/coding-worker-isolation.md +1061 -0
  436. package/docs/getting-started-gke.md +615 -0
  437. package/docs/getting-started-identity-provider.md +308 -0
  438. package/docs/getting-started.md +133 -0
  439. package/docs/observability.md +53 -0
  440. package/docs/release-verification.md +66 -0
  441. package/docs/security-deployment.md +657 -0
  442. package/help/code-review-agents.md +31 -0
  443. package/help/coding-packages.md +31 -0
  444. package/help/coding-services.md +71 -0
  445. package/help/creating-agents.md +68 -0
  446. package/help/deploy-gke.md +39 -0
  447. package/help/deployment-targets.md +39 -0
  448. package/help/errors/budget-group-exhausted.md +25 -0
  449. package/help/errors/docker-isolation-unsupported.md +26 -0
  450. package/help/errors/protected-path.md +45 -0
  451. package/help/errors/repo-access.md +27 -0
  452. package/help/errors/service-declaration-invalid.md +27 -0
  453. package/help/errors/service-declaration-unavailable.md +25 -0
  454. package/help/errors/service-launcher-unsupported.md +30 -0
  455. package/help/errors/service-not-allowed.md +27 -0
  456. package/help/errors/service-unknown.md +23 -0
  457. package/help/errors/service-unready.md +49 -0
  458. package/help/getting-started.md +31 -0
  459. package/help/github.md +30 -0
  460. package/help/identity-and-access.md +39 -0
  461. package/help/mcp.md +30 -0
  462. package/help/native-capabilities.md +30 -0
  463. package/help/observability.md +41 -0
  464. package/help/operating-agents.md +30 -0
  465. package/help/security.md +27 -0
  466. package/help/troubleshooting/budgets.md +26 -0
  467. package/help/troubleshooting/coding-workers.md +47 -0
  468. package/help/troubleshooting/repository-access.md +27 -0
  469. package/package.json +30 -11
  470. package/prisma/migrate.config.mjs +20 -0
  471. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  472. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  473. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  474. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  475. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  476. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  477. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  478. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  479. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  480. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  481. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  482. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  483. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  484. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  485. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  486. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  487. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  488. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  489. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  490. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  491. package/prisma/schema.prisma +417 -23
@@ -0,0 +1,59 @@
1
+ /** Agent ids are cuids; anything else could break out of the HTML comment. */
2
+ export const SAFE_AGENT_MARKER = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
3
+ const SAFE_SHA = /^[0-9a-f]{40}$/;
4
+ const MARKER_PREFIX = "<!-- wardby:review:";
5
+ function assertMarker(agentMarker) {
6
+ if (!SAFE_AGENT_MARKER.test(agentMarker))
7
+ throw new Error("review_marker_invalid");
8
+ }
9
+ export function reviewMarker(agentMarker, headSha) {
10
+ assertMarker(agentMarker);
11
+ if (!SAFE_SHA.test(headSha))
12
+ throw new Error("review_marker_invalid");
13
+ return `${MARKER_PREFIX}${agentMarker} sha=${headSha} -->`;
14
+ }
15
+ export function hasReviewMarker(body, agentMarker) {
16
+ assertMarker(agentMarker);
17
+ return body.includes(`${MARKER_PREFIX}${agentMarker} sha=`);
18
+ }
19
+ export function parseReviewMarker(body, agentMarker) {
20
+ assertMarker(agentMarker);
21
+ const match = new RegExp(`${MARKER_PREFIX}${agentMarker} sha=([0-9a-f]{40}) -->`).exec(body);
22
+ return match ? match[1] : null;
23
+ }
24
+ export function verdictConclusion(verdict) {
25
+ if (verdict === "APPROVE")
26
+ return "success";
27
+ if (verdict === "CHANGES_REQUESTED")
28
+ return "failure";
29
+ return "neutral";
30
+ }
31
+ const BADGES = {
32
+ APPROVE: "✅ **Approved**",
33
+ CHANGES_REQUESTED: "❌ **Changes requested**",
34
+ COMMENT: "💬 **Comments**",
35
+ };
36
+ const FINDING_PREFIX = "<!-- wardby:finding:";
37
+ /** Tags an inline comment with the agent that wrote it, so only that agent resolves its thread. */
38
+ export function findingMarker(agentMarker) {
39
+ assertMarker(agentMarker);
40
+ return `${FINDING_PREFIX}${agentMarker} -->`;
41
+ }
42
+ export function hasFindingMarker(body, agentMarker) {
43
+ return body.includes(findingMarker(agentMarker));
44
+ }
45
+ export function renderInlineComment(comment, agentMarker) {
46
+ return `**[${comment.severity}]** ${comment.body}\n\n${findingMarker(agentMarker)}`;
47
+ }
48
+ export function renderSummaryComment(input) {
49
+ const sections = [
50
+ reviewMarker(input.agentMarker, input.headSha),
51
+ `${BADGES[input.verdict]} — reviewed \`${input.headSha.slice(0, 7)}\``,
52
+ input.summary,
53
+ input.body,
54
+ ];
55
+ if (input.outside.length > 0) {
56
+ sections.push(["## Outside the diff", ...input.outside.map((c) => `- **[${c.severity}] ${c.path}:${c.line}** ${c.body}`)].join("\n"));
57
+ }
58
+ return sections.join("\n\n");
59
+ }
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Host-neutral code-review surface for native agents. GitHub is the first
3
+ * implementation (./github.ts); Bitbucket Cloud is anticipated. Every method
4
+ * takes the repository and mints its own least-permission credential — no
5
+ * method accepts a token or a permission. See
6
+ * docs/private/2026-09-25-code-review-host-design.md §5.
7
+ */
8
+ export type ReviewHostProvider = "github";
9
+ export declare const REVIEW_HOST_PROVIDERS: readonly ReviewHostProvider[];
10
+ export type ReviewVerdict = "APPROVE" | "CHANGES_REQUESTED" | "COMMENT";
11
+ export type CheckConclusion = "success" | "failure" | "neutral";
12
+ export type CommentSide = "LEFT" | "RIGHT";
13
+ export interface PullRequestFileView {
14
+ filename: string;
15
+ status: string;
16
+ additions: number;
17
+ deletions: number;
18
+ previousFilename?: string;
19
+ patch: string;
20
+ patchTruncated: boolean;
21
+ }
22
+ /** One of this agent's own review threads that is still unresolved. */
23
+ export interface ReviewThreadView {
24
+ /** Opaque host id; pass it back in PublishReviewInput.resolveThreadIds. */
25
+ id: string;
26
+ path: string;
27
+ /** The line in the current head, or null when the thread is outdated (its line no longer exists). */
28
+ line: number | null;
29
+ outdated: boolean;
30
+ /** The finding as posted, without its marker, capped at 1,000 characters. */
31
+ body: string;
32
+ }
33
+ export interface PullRequestView {
34
+ number: number;
35
+ title: string;
36
+ body: string;
37
+ author: string | null;
38
+ state: string;
39
+ merged: boolean;
40
+ draft: boolean;
41
+ baseRef: string;
42
+ headRef: string;
43
+ headSha: string;
44
+ isFork: boolean;
45
+ htmlUrl: string;
46
+ /** Head sha recorded in this agent's summary comment, if it reviewed before. */
47
+ lastReviewedSha: string | null;
48
+ /** Set when `files` is the compare of `comparedFrom...headSha` rather than the whole PR. */
49
+ comparedFrom: string | null;
50
+ /**
51
+ * The base branch was merged into the PR since `comparedFrom`: `files` is
52
+ * then the PR's own diff (against its base), limited to files that changed
53
+ * since `comparedFrom`, so base-branch changes are left out.
54
+ */
55
+ baseMergedSince: boolean;
56
+ files: PullRequestFileView[];
57
+ /** This agent's own unresolved review threads on the PR (the first 100 threads are searched). */
58
+ openThreads: ReviewThreadView[];
59
+ }
60
+ export interface PullRequestHead {
61
+ headSha: string;
62
+ isFork: boolean;
63
+ state: string;
64
+ }
65
+ export type FileReadResult = {
66
+ kind: "file";
67
+ path: string;
68
+ ref: string;
69
+ totalLines: number;
70
+ startLine: number;
71
+ endLine: number;
72
+ truncated: boolean;
73
+ content: string;
74
+ } | {
75
+ kind: "directory";
76
+ path: string;
77
+ entries: string[];
78
+ } | {
79
+ kind: "not_found";
80
+ path: string;
81
+ };
82
+ export interface FileListView {
83
+ ref: string;
84
+ count: number;
85
+ truncated: boolean;
86
+ files: string[];
87
+ }
88
+ export interface InlineComment {
89
+ path: string;
90
+ line: number;
91
+ side: CommentSide;
92
+ severity: string;
93
+ body: string;
94
+ }
95
+ export interface PublishReviewInput {
96
+ prNumber: number;
97
+ headSha: string;
98
+ verdict: ReviewVerdict;
99
+ summary: string;
100
+ body: string;
101
+ comments: InlineComment[];
102
+ /** Identifies this agent's summary comment; the agent id. */
103
+ agentMarker: string;
104
+ /**
105
+ * Names a completed check to create when no checkId is supplied (a run not
106
+ * started by a host event). With neither, no check is created.
107
+ */
108
+ checkName?: string;
109
+ /** The run's own in-progress check, when the control plane started one. */
110
+ checkId?: string;
111
+ /**
112
+ * Threads to resolve because this head fixes them. Only this agent's own
113
+ * unresolved threads on this PR are resolved; any other id is skipped.
114
+ */
115
+ resolveThreadIds?: string[];
116
+ }
117
+ export type PublishReviewResult = {
118
+ published: true;
119
+ reviewUrl: string | null;
120
+ summaryCommentUrl: string;
121
+ /** Null when no check was completed or created (neither checkId nor checkName). */
122
+ checkId: string | null;
123
+ /** The verdict's check mapping — informational when checkId is null. */
124
+ checkConclusion: CheckConclusion;
125
+ inlineCount: number;
126
+ outsideDiffCount: number;
127
+ resolvedThreadIds: string[];
128
+ /** Requested ids that were not resolved: not this agent's open thread on this PR, or the host refused. */
129
+ skippedThreadIds: string[];
130
+ } | {
131
+ published: false;
132
+ reason: "stale_head";
133
+ currentHeadSha: string;
134
+ };
135
+ export interface CommentInput {
136
+ number: number;
137
+ body: string;
138
+ replyToReviewCommentId?: string;
139
+ }
140
+ /** A comment the App wrote, to edit later: a conversation comment or a reply in a review thread. */
141
+ export interface EditCommentInput {
142
+ kind: "conversation" | "inline";
143
+ id: string;
144
+ body: string;
145
+ }
146
+ export interface CommentRef {
147
+ /**
148
+ * "conversation" = a top-level comment on an issue/PR conversation; "inline" = a comment on a diff line (review
149
+ * thread); "subject" = the issue or PR itself (its title/description), with `id` its number.
150
+ */
151
+ kind: "conversation" | "inline" | "subject";
152
+ id: string;
153
+ }
154
+ export interface StartCheckInput {
155
+ headSha: string;
156
+ name: string;
157
+ }
158
+ export interface CompleteCheckInput {
159
+ checkId: string;
160
+ conclusion: CheckConclusion;
161
+ title: string;
162
+ summary: string;
163
+ text?: string;
164
+ detailsUrl?: string;
165
+ }
166
+ /**
167
+ * A user's effective permission on one repository, host-neutral and ranked
168
+ * none < read < triage < write < maintain < admin. GitHub maps its
169
+ * collaborator permission onto these directly; GitLab would map reporter ->
170
+ * read, developer -> write, maintainer -> maintain, owner -> admin.
171
+ */
172
+ export type HostPermission = "none" | "read" | "triage" | "write" | "maintain" | "admin";
173
+ export declare const HOST_PERMISSION_RANK: Readonly<Record<HostPermission, number>>;
174
+ /** A host user, by its immutable numeric id (as text) and its current login. */
175
+ export interface HostUser {
176
+ id: string;
177
+ login: string;
178
+ }
179
+ export interface CodeReviewHost {
180
+ readonly provider: ReviewHostProvider;
181
+ /**
182
+ * The user's effective permission on `repository`, asked with the App's own
183
+ * installation credential (never a user token). Answers only for the user
184
+ * with this id: a login that now names someone else is re-resolved by id,
185
+ * and `login` in the result is the user's current login.
186
+ */
187
+ repositoryPermission(repository: string, user: HostUser): Promise<{
188
+ level: HostPermission;
189
+ login: string;
190
+ }>;
191
+ readPullRequest(repository: string, prNumber: number, opts: {
192
+ sinceSha?: string;
193
+ maxPatchChars: number;
194
+ agentMarker: string;
195
+ }): Promise<PullRequestView>;
196
+ pullRequestHead(repository: string, prNumber: number): Promise<PullRequestHead>;
197
+ readFile(repository: string, path: string, ref: string | undefined, window: {
198
+ startLine: number;
199
+ maxLines: number;
200
+ }): Promise<FileReadResult>;
201
+ listFiles(repository: string, ref: string | undefined, pathPrefix?: string): Promise<FileListView>;
202
+ publishReview(repository: string, input: PublishReviewInput): Promise<PublishReviewResult>;
203
+ /** `id` identifies the new comment for editComment; a reply is an "inline" comment, anything else "conversation". */
204
+ comment(repository: string, input: CommentInput): Promise<{
205
+ url: string;
206
+ id: string;
207
+ }>;
208
+ /** Replaces the body of a comment the App wrote. */
209
+ editComment(repository: string, input: EditCommentInput): Promise<void>;
210
+ /** Marks a comment as picked up (GitHub: a 👀 reaction); a host without reactions may do nothing. */
211
+ acknowledge(repository: string, target: CommentRef): Promise<void>;
212
+ startCheck(repository: string, input: StartCheckInput): Promise<{
213
+ checkId: string;
214
+ }>;
215
+ completeCheck(repository: string, input: CompleteCheckInput): Promise<void>;
216
+ }
217
+ export type ReviewHostErrorCode = "host_not_installed" | "host_permission_missing" | "host_api_error" | "host_invalid_response";
218
+ export declare class ReviewHostError extends Error {
219
+ readonly code: ReviewHostErrorCode;
220
+ constructor(code: ReviewHostErrorCode, message?: string);
221
+ }
222
+ export type ReviewHostRegistry = Partial<Record<ReviewHostProvider, CodeReviewHost>>;
223
+ /**
224
+ * A host's user-authorization (OAuth web) flow, used only to learn who a
225
+ * wardby principal is on the host. Implementations never store or return the
226
+ * user token: `complete` reads the user and revokes the token at once.
227
+ */
228
+ export interface HostUserAuthorizer {
229
+ readonly provider: ReviewHostProvider;
230
+ authorizeUrl(input: {
231
+ state: string;
232
+ codeChallenge: string;
233
+ redirectUri: string;
234
+ }): string;
235
+ complete(input: {
236
+ code: string;
237
+ codeVerifier: string;
238
+ redirectUri: string;
239
+ }): Promise<{
240
+ hostUserId: string;
241
+ login: string;
242
+ }>;
243
+ }
244
+ export type HostUserAuthorizerRegistry = Partial<Record<ReviewHostProvider, HostUserAuthorizer>>;
245
+ /**
246
+ * Host-neutral shape a webhook adapter (github-events.ts) normalises its
247
+ * provider payload into, for src/core/host-events.ts to route.
248
+ */
249
+ export type HostEvent = {
250
+ kind: "pr_updated";
251
+ provider: ReviewHostProvider;
252
+ repository: string;
253
+ prNumber: number;
254
+ headSha: string;
255
+ isFork: boolean;
256
+ } | {
257
+ kind: "check_rerun";
258
+ provider: ReviewHostProvider;
259
+ repository: string;
260
+ prNumber: number;
261
+ headSha: string;
262
+ checkName: string;
263
+ } | {
264
+ kind: "mention";
265
+ provider: ReviewHostProvider;
266
+ repository: string;
267
+ number: number;
268
+ isPullRequest: boolean;
269
+ comment: CommentRef;
270
+ /** Set when the mention is inside an inline review thread. */
271
+ replyToReviewCommentId?: string;
272
+ /** The comment text; for a "subject" mention, the issue/PR description. */
273
+ body: string;
274
+ author: string;
275
+ /** The author's immutable numeric host user id, as text; their permission is checked by it. */
276
+ authorId: string;
277
+ /** The issue or PR the mention is on, when the payload carries it. */
278
+ subject?: {
279
+ title: string;
280
+ body: string;
281
+ };
282
+ /** The run that opened this PR, when its description carries a valid run marker. */
283
+ priorRunId?: string;
284
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Host-neutral code-review surface for native agents. GitHub is the first
3
+ * implementation (./github.ts); Bitbucket Cloud is anticipated. Every method
4
+ * takes the repository and mints its own least-permission credential — no
5
+ * method accepts a token or a permission. See
6
+ * docs/private/2026-09-25-code-review-host-design.md §5.
7
+ */
8
+ export const REVIEW_HOST_PROVIDERS = ["github"];
9
+ export const HOST_PERMISSION_RANK = {
10
+ none: 0,
11
+ read: 1,
12
+ triage: 2,
13
+ write: 3,
14
+ maintain: 4,
15
+ admin: 5,
16
+ };
17
+ export class ReviewHostError extends Error {
18
+ code;
19
+ constructor(code, message = code) {
20
+ super(message);
21
+ this.code = code;
22
+ this.name = "ReviewHostError";
23
+ }
24
+ }
@@ -1,5 +1,5 @@
1
- import { type GitHubRepositoryAccess } from "./github.js";
2
- import type { FinalizeChangesDetails, FinalizeChangesResult, PreparedWorkspace, VcsPrepareInput, VcsProvider } from "./types.js";
1
+ import { type GitHubRepositoryAccess, type RepositoryFileInput } from "./github.js";
2
+ import type { ContinuationFinishedDetails, ContinuationOutcome, FinalizeChangesDetails, FinalizeChangesResult, PreparedWorkspace, VcsPrepareInput, VcsProvider } from "./types.js";
3
3
  export declare const DEFAULT_MAX_CHANGED_FILES = 1000;
4
4
  export declare const DEFAULT_MAX_DIFF_BYTES: number;
5
5
  export interface GitCommandOptions {
@@ -43,6 +43,18 @@ export interface GitVcsProviderOptions {
43
43
  /** Test-only transport override; production composition always uses github.com. */
44
44
  cloneUrlForRepository?: (repository: string) => string;
45
45
  }
46
+ /**
47
+ * Whether a changed path is protected, in this order: the WARDBY_PROTECTED_PATHS
48
+ * baseline's exception (.wardby/services.yaml, which a builder may propose; it
49
+ * takes effect only after merge, docs/coding-services.md) is never protected;
50
+ * anything else under the baseline (.wardby/**) always is, whatever the agent's
51
+ * exceptions say; any other path is protected when it matches one of the
52
+ * agent's `patterns` and is not one of its exceptions (entries with a leading
53
+ * "!", each a literal path, so order does not matter). The baseline is applied
54
+ * here, at enforcement, rather than stored, so every existing agent and
55
+ * in-flight run gets it.
56
+ */
57
+ export declare function protectedPathMatcher(patterns: readonly string[]): (path: string) => boolean;
46
58
  export declare class GitVcsProvider implements VcsProvider {
47
59
  private readonly options;
48
60
  private readonly rootDir;
@@ -74,10 +86,8 @@ export declare class GitVcsProvider implements VcsProvider {
74
86
  * github.ts). Safe to call more than once for the same run. Same
75
87
  * never-throw contract as notifyContinuationStarted.
76
88
  */
77
- notifyContinuationFinished(workspace: PreparedWorkspace, outcome: "succeeded" | "failed", details?: {
78
- summary?: string;
79
- agentName?: string;
80
- }): Promise<void>;
89
+ notifyContinuationFinished(workspace: PreparedWorkspace, outcome: ContinuationOutcome, details?: ContinuationFinishedDetails): Promise<void>;
90
+ readRepositoryFile(input: RepositoryFileInput): Promise<string | null>;
81
91
  private validateInput;
82
92
  private expectedPaths;
83
93
  private validatePrepared;
@@ -2,6 +2,9 @@ import { spawn } from "node:child_process";
2
2
  import { lstat, mkdir, opendir, readFile, readlink, realpath, rm } from "node:fs/promises";
3
3
  import { isAbsolute, resolve, sep } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { gitExcludePathspecs, normalizeCollectExclusions } from "../../coding/collect-exclude.js";
6
+ import { WARDBY_PROTECTED_PATHS, isProtectedPathException, isWellFormedProtectedPath, protectedPathBody, protectsSomePath, } from "../../coding/protected-paths.js";
7
+ import { ensurePrivateDirectory } from "../../core/private-directory.js";
5
8
  import { MAX_REDACTED_SPAN, redactTokenShapedValues, normalizeGitHubRepository, normalizeGitRef, } from "../../coding/protocol.js";
6
9
  import { isSafeGitHubInstallationToken } from "./github.js";
7
10
  export const DEFAULT_MAX_CHANGED_FILES = 1_000;
@@ -138,14 +141,10 @@ export class NodeGitCommandRunner {
138
141
  });
139
142
  }
140
143
  }
144
+ /** Validates one protectedPaths entry; a leading "!" makes it an exception (see protectedPathMatcher). */
141
145
  function validateProtectedPath(value) {
142
146
  const path = value.trim();
143
- if (!path ||
144
- Buffer.byteLength(path, "utf8") > 512 ||
145
- path.startsWith("/") ||
146
- path.startsWith("./") ||
147
- path.includes("\\") ||
148
- path.split("/").some((part) => !part || part === "." || part === "..")) {
147
+ if (Buffer.byteLength(path, "utf8") > 512 || !isWellFormedProtectedPath(path)) {
149
148
  throw new Error("vcs_protected_path_invalid");
150
149
  }
151
150
  return path;
@@ -172,6 +171,33 @@ function globRegex(pattern) {
172
171
  }
173
172
  return new RegExp(`${source}$`);
174
173
  }
174
+ /** The fixed baseline, split once: its literal exceptions and its protected globs. */
175
+ const WARDBY_UNPROTECTED = new Set(WARDBY_PROTECTED_PATHS.filter(isProtectedPathException).map(protectedPathBody));
176
+ const WARDBY_PROTECTED = WARDBY_PROTECTED_PATHS.filter((pattern) => !isProtectedPathException(pattern)).map((pattern) => globRegex(pattern));
177
+ /**
178
+ * Whether a changed path is protected, in this order: the WARDBY_PROTECTED_PATHS
179
+ * baseline's exception (.wardby/services.yaml, which a builder may propose; it
180
+ * takes effect only after merge, docs/coding-services.md) is never protected;
181
+ * anything else under the baseline (.wardby/**) always is, whatever the agent's
182
+ * exceptions say; any other path is protected when it matches one of the
183
+ * agent's `patterns` and is not one of its exceptions (entries with a leading
184
+ * "!", each a literal path, so order does not matter). The baseline is applied
185
+ * here, at enforcement, rather than stored, so every existing agent and
186
+ * in-flight run gets it.
187
+ */
188
+ export function protectedPathMatcher(patterns) {
189
+ const exceptions = new Set(patterns.filter(isProtectedPathException).map(protectedPathBody));
190
+ const protectedPatterns = patterns
191
+ .filter((pattern) => !isProtectedPathException(pattern))
192
+ .map((pattern) => globRegex(pattern));
193
+ return (path) => {
194
+ if (WARDBY_UNPROTECTED.has(path))
195
+ return false;
196
+ if (WARDBY_PROTECTED.some((matcher) => matcher.test(path)))
197
+ return true;
198
+ return protectedPatterns.some((matcher) => matcher.test(path)) && !exceptions.has(path);
199
+ };
200
+ }
175
201
  function validateChangedPath(path) {
176
202
  if (!path ||
177
203
  isAbsolute(path) ||
@@ -220,7 +246,7 @@ export class GitVcsProvider {
220
246
  }
221
247
  async prepareWorkspace(input) {
222
248
  const normalized = this.validateInput(input);
223
- await mkdir(this.rootDir, { recursive: true, mode: 0o700 });
249
+ await ensurePrivateDirectory(this.rootDir);
224
250
  await mkdir(resolve(this.rootDir, ".home"), { recursive: true, mode: 0o700 });
225
251
  const runRoot = resolve(this.rootDir, normalized.runId);
226
252
  if (!directChild(this.rootDir, runRoot))
@@ -351,7 +377,15 @@ export class GitVcsProvider {
351
377
  await this.inspectWorkspace(prepared.workspacePath);
352
378
  await this.assertRemote(prepared);
353
379
  await this.assertSafeLocalConfig(prepared.gitMetadataPath);
354
- await this.gitFor(prepared, ["add", "--all", "--", ":/"]);
380
+ // Excluded paths (src/coding/collect-exclude.ts) are never collected from the worker, so
381
+ // they are also neither added nor deleted here: tracked files under them stay untouched.
382
+ await this.gitFor(prepared, [
383
+ "add",
384
+ "--all",
385
+ "--",
386
+ ":/",
387
+ ...gitExcludePathspecs(normalizeCollectExclusions(prepared.collectExclude)),
388
+ ]);
355
389
  const changed = nullSeparated((await this.gitFor(prepared, [
356
390
  "diff",
357
391
  "--cached",
@@ -363,8 +397,7 @@ export class GitVcsProvider {
363
397
  ])).stdout);
364
398
  if (changed.length > this.maxChangedFiles)
365
399
  throw new Error("vcs_changed_file_limit");
366
- const protectedMatchers = prepared.protectedPaths.map((path) => ({ path, matcher: globRegex(path) }));
367
- const protectedChange = changed.find((path) => protectedMatchers.some(({ matcher }) => matcher.test(path)));
400
+ const protectedChange = changed.find(protectedPathMatcher(prepared.protectedPaths));
368
401
  if (protectedChange)
369
402
  throw new Error(`vcs_protected_path:${protectedChange}`);
370
403
  let diff;
@@ -411,15 +444,20 @@ export class GitVcsProvider {
411
444
  // run's id), not this run's own -- this finds the existing open PR and
412
445
  // returns it rather than creating a new one, since headRef/baseRef
413
446
  // already match it exactly. No other change needed here: pushing a new
414
- // commit onto that branch already updates the PR natively.
447
+ // commit onto that branch already updates the PR natively -- which is
448
+ // also why a PR a person has since marked ready for review is accepted
449
+ // (acceptReadyForReview) rather than failing an already-pushed run.
415
450
  const pullRequest = await this.options.github.createOrFindDraftPullRequest({
416
451
  runId: prepared.continuation?.rootRunId ?? prepared.runId,
452
+ ...(prepared.continuation ? { acceptReadyForReview: true } : {}),
417
453
  repository: prepared.repository,
418
454
  baseRef: prepared.baseRef,
419
455
  headRef: prepared.headRef,
420
456
  summary: details?.summary,
421
457
  tests: details?.tests,
422
458
  tag: details?.tag,
459
+ packages: details?.packages,
460
+ packageRefusals: details?.packageRefusals,
423
461
  });
424
462
  return {
425
463
  outcome: prepared.continuation ? "pull_request_updated" : "pull_request_opened",
@@ -497,14 +535,25 @@ export class GitVcsProvider {
497
535
  };
498
536
  const label = runLabel(details?.agentName, workspace.runId);
499
537
  const summarySuffix = details?.summary ? `\n\n${details.summary}` : "";
500
- const body = outcome === "succeeded" ? `✅ ${label} finished.${summarySuffix}` : `❌ ${label} failed.${summarySuffix}`;
538
+ const budgetSuffix = details?.budgetSentence ? ` ${details.budgetSentence}` : "";
539
+ const body = outcome === "succeeded"
540
+ ? `✅ ${label} finished.${summarySuffix}`
541
+ : outcome === "budget_exhausted"
542
+ ? `❌ ${label} ran out of budget.${budgetSuffix}${summarySuffix}`
543
+ : details?.serviceSentence
544
+ ? `❌ ${label} could not start: ${details.serviceSentence}${summarySuffix}`
545
+ : details?.providerSentence
546
+ ? `❌ ${label} could not run: ${details.providerSentence}${summarySuffix}`
547
+ : details?.protectedPathSentence
548
+ ? `❌ ${label} could not open its changes: ${details.protectedPathSentence}${summarySuffix}`
549
+ : `❌ ${label} failed.${summarySuffix}`;
501
550
  await Promise.allSettled([
502
551
  this.options.github.updateContinuationStatusComment({ ...identity, body }),
503
552
  this.options.github.completeContinuationCheckRun({
504
553
  repository: workspace.repository,
505
554
  headSha: workspace.baseCommit,
506
555
  runId: workspace.runId,
507
- outcome,
556
+ outcome: outcome === "succeeded" ? "succeeded" : "failed",
508
557
  }),
509
558
  ]);
510
559
  }
@@ -512,6 +561,17 @@ export class GitVcsProvider {
512
561
  // Best-effort observability only -- must never affect the real run.
513
562
  }
514
563
  }
564
+ async readRepositoryFile(input) {
565
+ const github = this.options.github;
566
+ if (!github.readFileAtRef)
567
+ throw new Error("vcs_read_file_unsupported");
568
+ return github.readFileAtRef({
569
+ repository: normalizeGitHubRepository(input.repository),
570
+ ref: normalizeGitRef(input.ref),
571
+ path: validateChangedPath(input.path),
572
+ maxBytes: input.maxBytes,
573
+ });
574
+ }
515
575
  validateInput(input) {
516
576
  if (!SAFE_RUN_ID.test(input.runId))
517
577
  throw new Error("vcs_run_id_invalid");
@@ -539,7 +599,10 @@ export class GitVcsProvider {
539
599
  const protectedPaths = [...new Set(input.protectedPaths.map(validateProtectedPath))];
540
600
  if (protectedPaths.length === 0 || protectedPaths.length > 128)
541
601
  throw new Error("vcs_protected_paths_invalid");
542
- return { runId: input.runId, repository, baseRef, headRef, protectedPaths, continuation };
602
+ if (!protectsSomePath(protectedPaths))
603
+ throw new Error("vcs_protected_paths_invalid");
604
+ const collectExclude = [...normalizeCollectExclusions(input.collectExclude ?? []).paths];
605
+ return { runId: input.runId, repository, baseRef, headRef, protectedPaths, collectExclude, continuation };
543
606
  }
544
607
  expectedPaths(runId) {
545
608
  if (!SAFE_RUN_ID.test(runId))
@@ -565,6 +628,8 @@ export class GitVcsProvider {
565
628
  workspace.gitMetadataPath !== expected.gitMetadataPath ||
566
629
  workspace.protectedPaths.length !== normalized.protectedPaths.length ||
567
630
  workspace.protectedPaths.some((path, index) => path !== normalized.protectedPaths[index]) ||
631
+ workspace.collectExclude.length !== normalized.collectExclude.length ||
632
+ workspace.collectExclude.some((path, index) => path !== normalized.collectExclude[index]) ||
568
633
  workspace.continuation?.rootRunId !== normalized.continuation?.rootRunId) {
569
634
  throw new Error("vcs_workspace_handle_invalid");
570
635
  }