@wardby/cli 0.2.1 → 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 (407) hide show
  1. package/.env.example +34 -4
  2. package/README.md +41 -4
  3. package/dist/claude-coding-worker/driver.d.ts +6 -1
  4. package/dist/claude-coding-worker/driver.js +27 -1
  5. package/dist/claude-coding-worker/main.js +2 -0
  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 +75 -4
  21. package/dist/coding/protocol.js +107 -7
  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 +6 -0
  60. package/dist/coding-worker/debug-trace.d.ts +37 -0
  61. package/dist/coding-worker/debug-trace.js +117 -0
  62. package/dist/coding-worker/driver.d.ts +13 -1
  63. package/dist/coding-worker/driver.js +102 -13
  64. package/dist/coding-worker/errors.js +8 -0
  65. package/dist/coding-worker/main.js +10 -2
  66. package/dist/coding-worker/sdk.d.ts +2 -2
  67. package/dist/coding-worker/sdk.js +7 -2
  68. package/dist/coding-worker/types.d.ts +3 -0
  69. package/dist/config/providers.d.ts +41 -0
  70. package/dist/config/providers.js +66 -0
  71. package/dist/core/budget-groups.d.ts +108 -5
  72. package/dist/core/budget-groups.js +125 -19
  73. package/dist/core/budget-wording.d.ts +22 -0
  74. package/dist/core/budget-wording.js +55 -0
  75. package/dist/core/datastores.js +18 -2
  76. package/dist/core/db.d.ts +5 -1
  77. package/dist/core/db.js +8 -2
  78. package/dist/core/dispatch.d.ts +33 -6
  79. package/dist/core/dispatch.js +260 -43
  80. package/dist/core/engine-native.js +27 -10
  81. package/dist/core/grants.d.ts +86 -0
  82. package/dist/core/grants.js +126 -0
  83. package/dist/core/host-events.d.ts +49 -0
  84. package/dist/core/host-events.js +257 -0
  85. package/dist/core/host-identity-links.d.ts +54 -0
  86. package/dist/core/host-identity-links.js +189 -0
  87. package/dist/core/host-status.d.ts +61 -0
  88. package/dist/core/host-status.js +211 -0
  89. package/dist/core/in-flight-runs.d.ts +8 -0
  90. package/dist/core/in-flight-runs.js +56 -0
  91. package/dist/core/provider-wording.d.ts +12 -0
  92. package/dist/core/provider-wording.js +44 -0
  93. package/dist/core/reconciler.d.ts +38 -2
  94. package/dist/core/reconciler.js +86 -2
  95. package/dist/core/repo-access.d.ts +99 -0
  96. package/dist/core/repo-access.js +136 -0
  97. package/dist/core/review-host-checks.d.ts +11 -0
  98. package/dist/core/review-host-checks.js +41 -0
  99. package/dist/core/review-host-tools.d.ts +47 -0
  100. package/dist/core/review-host-tools.js +347 -0
  101. package/dist/core/run-heartbeat.d.ts +27 -0
  102. package/dist/core/run-heartbeat.js +54 -0
  103. package/dist/core/runner.d.ts +30 -8
  104. package/dist/core/runner.js +237 -40
  105. package/dist/core/secrets.d.ts +11 -2
  106. package/dist/core/secrets.js +25 -6
  107. package/dist/core/subagent-memory-tools.d.ts +1 -1
  108. package/dist/core/subagent-memory-tools.js +16 -3
  109. package/dist/core/tool-admin.d.ts +81 -0
  110. package/dist/core/tool-admin.js +129 -0
  111. package/dist/core/tool-names.d.ts +42 -0
  112. package/dist/core/tool-names.js +64 -0
  113. package/dist/core/untrusted-content.d.ts +32 -0
  114. package/dist/core/untrusted-content.js +72 -0
  115. package/dist/core/webhooks.d.ts +8 -1
  116. package/dist/core/webhooks.js +23 -2
  117. package/dist/generated/prisma/browser.d.ts +100 -0
  118. package/dist/generated/prisma/client.d.ts +100 -0
  119. package/dist/generated/prisma/commonInputTypes.d.ts +30 -0
  120. package/dist/generated/prisma/enums.d.ts +6 -0
  121. package/dist/generated/prisma/enums.js +6 -1
  122. package/dist/generated/prisma/internal/class.d.ts +143 -0
  123. package/dist/generated/prisma/internal/class.js +4 -4
  124. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1746 -577
  125. package/dist/generated/prisma/internal/prismaNamespace.js +179 -6
  126. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +186 -0
  127. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +179 -6
  128. package/dist/generated/prisma/models/Agent.d.ts +294 -1
  129. package/dist/generated/prisma/models/AgentRepository.d.ts +1425 -0
  130. package/dist/generated/prisma/models/AgentRepository.js +1 -0
  131. package/dist/generated/prisma/models/AgentTool.d.ts +95 -1
  132. package/dist/generated/prisma/models/AuthUser.d.ts +56 -1
  133. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +258 -7
  134. package/dist/generated/prisma/models/CodingProxySession.d.ts +123 -2
  135. package/dist/generated/prisma/models/CodingRun.d.ts +1276 -95
  136. package/dist/generated/prisma/models/CodingService.d.ts +1348 -0
  137. package/dist/generated/prisma/models/CodingService.js +1 -0
  138. package/dist/generated/prisma/models/HostEventDelivery.d.ts +946 -0
  139. package/dist/generated/prisma/models/HostEventDelivery.js +1 -0
  140. package/dist/generated/prisma/models/HostIdentity.d.ts +1232 -0
  141. package/dist/generated/prisma/models/HostIdentity.js +1 -0
  142. package/dist/generated/prisma/models/HostIdentityLinkRequest.d.ts +1473 -0
  143. package/dist/generated/prisma/models/HostIdentityLinkRequest.js +1 -0
  144. package/dist/generated/prisma/models/Principal.d.ts +455 -0
  145. package/dist/generated/prisma/models/RegistryAllowance.d.ts +1148 -0
  146. package/dist/generated/prisma/models/RegistryAllowance.js +1 -0
  147. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +1219 -0
  148. package/dist/generated/prisma/models/RegistryApprovedVersion.js +1 -0
  149. package/dist/generated/prisma/models/RegistryFetch.d.ts +1428 -0
  150. package/dist/generated/prisma/models/RegistryFetch.js +1 -0
  151. package/dist/generated/prisma/models/RegistryPlanRefusal.d.ts +1294 -0
  152. package/dist/generated/prisma/models/RegistryPlanRefusal.js +1 -0
  153. package/dist/generated/prisma/models/RegistryVersionFact.d.ts +1085 -0
  154. package/dist/generated/prisma/models/RegistryVersionFact.js +1 -0
  155. package/dist/generated/prisma/models/ResourceGrant.d.ts +1437 -0
  156. package/dist/generated/prisma/models/ResourceGrant.js +1 -0
  157. package/dist/generated/prisma/models/Run.d.ts +389 -1
  158. package/dist/generated/prisma/models/RunHostCheck.d.ts +1239 -0
  159. package/dist/generated/prisma/models/RunHostCheck.js +1 -0
  160. package/dist/generated/prisma/models/RunHostStatus.d.ts +1315 -0
  161. package/dist/generated/prisma/models/RunHostStatus.js +1 -0
  162. package/dist/generated/prisma/models/Tool.d.ts +15 -3
  163. package/dist/generated/prisma/models.d.ts +13 -0
  164. package/dist/help/build.d.ts +1 -0
  165. package/dist/help/build.js +9 -0
  166. package/dist/help/catalog.d.ts +24 -0
  167. package/dist/help/catalog.js +160 -0
  168. package/dist/help/cli.d.ts +2 -0
  169. package/dist/help/cli.js +65 -0
  170. package/dist/help/runtime.d.ts +3 -0
  171. package/dist/help/runtime.js +44 -0
  172. package/dist/help/search.d.ts +9 -0
  173. package/dist/help/search.js +104 -0
  174. package/dist/help-index.json +660 -0
  175. package/dist/import/cli-args.js +3 -2
  176. package/dist/import/create.d.ts +5 -0
  177. package/dist/import/create.js +67 -13
  178. package/dist/import/index.js +19 -9
  179. package/dist/import/neutral-schema.d.ts +11 -11
  180. package/dist/mcp/auth/access.d.ts +70 -0
  181. package/dist/mcp/auth/access.js +58 -0
  182. package/dist/mcp/auth/grants-cli.d.ts +149 -0
  183. package/dist/mcp/auth/grants-cli.js +518 -0
  184. package/dist/mcp/auth/host-account-cli.d.ts +2 -0
  185. package/dist/mcp/auth/host-account-cli.js +47 -0
  186. package/dist/mcp/auth/ownership.d.ts +26 -52
  187. package/dist/mcp/auth/ownership.js +19 -14
  188. package/dist/mcp/auth/repo-authorization.d.ts +22 -0
  189. package/dist/mcp/auth/repo-authorization.js +51 -0
  190. package/dist/mcp/auth/resource-server.d.ts +31 -2
  191. package/dist/mcp/auth/resource-server.js +84 -3
  192. package/dist/mcp/auth/self-hosted/browser.js +2 -2
  193. package/dist/mcp/auth/self-hosted/cli.js +47 -13
  194. package/dist/mcp/auth/self-hosted/credentials.d.ts +20 -2
  195. package/dist/mcp/auth/self-hosted/credentials.js +62 -4
  196. package/dist/mcp/auth/self-hosted/session.d.ts +2 -1
  197. package/dist/mcp/context.d.ts +27 -1
  198. package/dist/mcp/errors.d.ts +25 -6
  199. package/dist/mcp/errors.js +98 -0
  200. package/dist/mcp/host-events/github-ingress.d.ts +36 -0
  201. package/dist/mcp/host-events/github-ingress.js +92 -0
  202. package/dist/mcp/host-events/github-user-callback.d.ts +18 -0
  203. package/dist/mcp/host-events/github-user-callback.js +50 -0
  204. package/dist/mcp/index.d.ts +8 -1
  205. package/dist/mcp/index.js +106 -16
  206. package/dist/mcp/server.js +27 -9
  207. package/dist/mcp/tools/agents.js +446 -48
  208. package/dist/mcp/tools/budget-groups.js +3 -3
  209. package/dist/mcp/tools/datastore.js +22 -15
  210. package/dist/mcp/tools/grants.d.ts +2 -0
  211. package/dist/mcp/tools/grants.js +239 -0
  212. package/dist/mcp/tools/help.d.ts +5 -0
  213. package/dist/mcp/tools/help.js +67 -0
  214. package/dist/mcp/tools/host-accounts.d.ts +2 -0
  215. package/dist/mcp/tools/host-accounts.js +114 -0
  216. package/dist/mcp/tools/memory.d.ts +7 -1
  217. package/dist/mcp/tools/memory.js +5 -5
  218. package/dist/mcp/tools/repositories.d.ts +2 -0
  219. package/dist/mcp/tools/repositories.js +181 -0
  220. package/dist/mcp/tools/runs.d.ts +6 -0
  221. package/dist/mcp/tools/runs.js +60 -6
  222. package/dist/mcp/tools/scheduling.js +3 -6
  223. package/dist/mcp/tools/secrets.js +18 -6
  224. package/dist/mcp/tools/services.d.ts +2 -0
  225. package/dist/mcp/tools/services.js +222 -0
  226. package/dist/mcp/tools/subagents.js +52 -16
  227. package/dist/mcp/tools/tools.d.ts +41 -0
  228. package/dist/mcp/tools/tools.js +201 -40
  229. package/dist/mcp/tools/trigger.js +36 -6
  230. package/dist/mcp/tools/webhooks.js +15 -4
  231. package/dist/mcp/transport/streamable-http.d.ts +10 -0
  232. package/dist/mcp/transport/streamable-http.js +32 -2
  233. package/dist/providers/auth/delegating.d.ts +19 -0
  234. package/dist/providers/auth/delegating.js +71 -0
  235. package/dist/providers/auth/index.d.ts +2 -0
  236. package/dist/providers/auth/index.js +11 -0
  237. package/dist/providers/auth/self-hosted.d.ts +2 -1
  238. package/dist/providers/auth/self-hosted.js +16 -4
  239. package/dist/providers/auth/types.d.ts +6 -0
  240. package/dist/providers/coding-proxy/memory-ledger.d.ts +3 -0
  241. package/dist/providers/coding-proxy/memory-ledger.js +21 -2
  242. package/dist/providers/coding-proxy/metering.d.ts +4 -0
  243. package/dist/providers/coding-proxy/metering.js +28 -2
  244. package/dist/providers/coding-proxy/prisma-ledger.d.ts +17 -0
  245. package/dist/providers/coding-proxy/prisma-ledger.js +50 -5
  246. package/dist/providers/coding-proxy/proxy.d.ts +13 -0
  247. package/dist/providers/coding-proxy/proxy.js +479 -18
  248. package/dist/providers/coding-proxy/registry/audit.d.ts +131 -0
  249. package/dist/providers/coding-proxy/registry/audit.js +380 -0
  250. package/dist/providers/coding-proxy/registry/bounded-fetch.d.ts +16 -0
  251. package/dist/providers/coding-proxy/registry/bounded-fetch.js +77 -0
  252. package/dist/providers/coding-proxy/registry/plan.d.ts +58 -0
  253. package/dist/providers/coding-proxy/registry/plan.js +304 -0
  254. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +34 -0
  255. package/dist/providers/coding-proxy/registry/prisma-store.js +151 -0
  256. package/dist/providers/coding-proxy/registry/service.d.ts +213 -0
  257. package/dist/providers/coding-proxy/registry/service.js +1137 -0
  258. package/dist/providers/coding-proxy/registry/store.d.ts +127 -0
  259. package/dist/providers/coding-proxy/registry/store.js +70 -0
  260. package/dist/providers/coding-proxy/runtime.d.ts +17 -0
  261. package/dist/providers/coding-proxy/runtime.js +63 -0
  262. package/dist/providers/coding-proxy/secure-fetch.js +0 -1
  263. package/dist/providers/coding-proxy/server.d.ts +11 -0
  264. package/dist/providers/coding-proxy/server.js +163 -0
  265. package/dist/providers/coding-proxy/types.d.ts +15 -0
  266. package/dist/providers/engine/types.d.ts +10 -0
  267. package/dist/providers/executor/build.d.ts +2 -2
  268. package/dist/providers/executor/composition.d.ts +3 -0
  269. package/dist/providers/executor/composition.js +19 -0
  270. package/dist/providers/executor/container.d.ts +105 -3
  271. package/dist/providers/executor/container.js +296 -20
  272. package/dist/providers/executor/dbos.d.ts +2 -3
  273. package/dist/providers/executor/in-process.d.ts +2 -3
  274. package/dist/providers/executor/routing.d.ts +7 -0
  275. package/dist/providers/executor/routing.js +13 -0
  276. package/dist/providers/executor/types.d.ts +22 -0
  277. package/dist/providers/jobs/claude-tool-setup.d.ts +23 -0
  278. package/dist/providers/jobs/claude-tool-setup.js +50 -0
  279. package/dist/providers/jobs/collect-prune.d.ts +7 -0
  280. package/dist/providers/jobs/collect-prune.js +27 -0
  281. package/dist/providers/jobs/docker-isolation.d.ts +48 -3
  282. package/dist/providers/jobs/docker-isolation.js +213 -22
  283. package/dist/providers/jobs/docker-services.d.ts +35 -0
  284. package/dist/providers/jobs/docker-services.js +191 -0
  285. package/dist/providers/jobs/docker.d.ts +49 -2
  286. package/dist/providers/jobs/docker.js +279 -32
  287. package/dist/providers/jobs/fake-kubernetes-api.d.ts +1 -0
  288. package/dist/providers/jobs/fake-kubernetes-api.js +12 -3
  289. package/dist/providers/jobs/kubernetes-isolation.d.ts +17 -2
  290. package/dist/providers/jobs/kubernetes-isolation.js +238 -57
  291. package/dist/providers/jobs/kubernetes-platform.d.ts +10 -4
  292. package/dist/providers/jobs/kubernetes-platform.js +11 -5
  293. package/dist/providers/jobs/kubernetes-preflight.js +3 -0
  294. package/dist/providers/jobs/kubernetes.d.ts +21 -2
  295. package/dist/providers/jobs/kubernetes.js +112 -21
  296. package/dist/providers/jobs/types.d.ts +18 -0
  297. package/dist/providers/llm/anthropic.js +6 -2
  298. package/dist/providers/llm/bedrock.js +2 -1
  299. package/dist/providers/llm/claude-messages.d.ts +5 -1
  300. package/dist/providers/llm/claude-messages.js +1 -0
  301. package/dist/providers/llm/claude-provider.d.ts +3 -1
  302. package/dist/providers/llm/claude-provider.js +5 -1
  303. package/dist/providers/llm/index.d.ts +1 -1
  304. package/dist/providers/llm/index.js +1 -1
  305. package/dist/providers/llm/pricing-anthropic.d.ts +10 -0
  306. package/dist/providers/llm/pricing-anthropic.js +32 -14
  307. package/dist/providers/llm/pricing-bedrock-claude.d.ts +8 -0
  308. package/dist/providers/llm/pricing-bedrock-claude.js +9 -0
  309. package/dist/providers/llm/routing.d.ts +10 -1
  310. package/dist/providers/llm/routing.js +18 -0
  311. package/dist/providers/llm/types.d.ts +12 -0
  312. package/dist/providers/llm/types.js +8 -1
  313. package/dist/providers/review-host/diff-lines.d.ts +16 -0
  314. package/dist/providers/review-host/diff-lines.js +59 -0
  315. package/dist/providers/review-host/github-events.d.ts +6 -0
  316. package/dist/providers/review-host/github-events.js +180 -0
  317. package/dist/providers/review-host/github-user-auth.d.ts +38 -0
  318. package/dist/providers/review-host/github-user-auth.js +128 -0
  319. package/dist/providers/review-host/github.d.ts +57 -0
  320. package/dist/providers/review-host/github.js +567 -0
  321. package/dist/providers/review-host/index.d.ts +12 -0
  322. package/dist/providers/review-host/index.js +30 -0
  323. package/dist/providers/review-host/review-format.d.ts +19 -0
  324. package/dist/providers/review-host/review-format.js +59 -0
  325. package/dist/providers/review-host/types.d.ts +284 -0
  326. package/dist/providers/review-host/types.js +24 -0
  327. package/dist/providers/vcs/git.d.ts +16 -6
  328. package/dist/providers/vcs/git.js +77 -13
  329. package/dist/providers/vcs/github.d.ts +74 -3
  330. package/dist/providers/vcs/github.js +195 -15
  331. package/dist/providers/vcs/types.d.ts +42 -4
  332. package/dist/quickstart/index.js +13 -2
  333. package/dist/sandbox/fetch-policy.d.ts +20 -2
  334. package/dist/sandbox/fetch-policy.js +64 -3
  335. package/dist/sandbox/host-functions.d.ts +9 -1
  336. package/dist/sandbox/host-functions.js +12 -5
  337. package/dist/serve.js +1 -1
  338. package/dist/wardby-bin.js +6 -0
  339. package/docs/README.md +30 -0
  340. package/docs/architecture-runtime.md +90 -0
  341. package/docs/assets/brand/wardby-icon-512.png +0 -0
  342. package/docs/assets/brand/wardby-icon.svg +16 -0
  343. package/docs/assets/brand/wardby-mascot-profile-512.png +0 -0
  344. package/docs/assets/brand/wardby-mascot.png +0 -0
  345. package/docs/assets/brand/wardby-mascot.svg +5 -0
  346. package/docs/assets/wardby-workflow.svg +106 -0
  347. package/docs/code-review-agents.md +481 -0
  348. package/docs/coding-agent-setup.md +172 -0
  349. package/docs/coding-packages.md +455 -0
  350. package/docs/coding-services.md +300 -0
  351. package/docs/coding-worker-byo-images.md +98 -0
  352. package/docs/coding-worker-isolation.md +1061 -0
  353. package/docs/getting-started-gke.md +615 -0
  354. package/docs/getting-started-identity-provider.md +308 -0
  355. package/docs/getting-started.md +133 -0
  356. package/docs/observability.md +53 -0
  357. package/docs/release-verification.md +66 -0
  358. package/docs/security-deployment.md +657 -0
  359. package/help/code-review-agents.md +31 -0
  360. package/help/coding-packages.md +31 -0
  361. package/help/coding-services.md +71 -0
  362. package/help/creating-agents.md +68 -0
  363. package/help/deploy-gke.md +39 -0
  364. package/help/deployment-targets.md +39 -0
  365. package/help/errors/budget-group-exhausted.md +25 -0
  366. package/help/errors/docker-isolation-unsupported.md +26 -0
  367. package/help/errors/protected-path.md +45 -0
  368. package/help/errors/repo-access.md +27 -0
  369. package/help/errors/service-declaration-invalid.md +27 -0
  370. package/help/errors/service-declaration-unavailable.md +25 -0
  371. package/help/errors/service-launcher-unsupported.md +30 -0
  372. package/help/errors/service-not-allowed.md +27 -0
  373. package/help/errors/service-unknown.md +23 -0
  374. package/help/errors/service-unready.md +49 -0
  375. package/help/getting-started.md +31 -0
  376. package/help/github.md +30 -0
  377. package/help/identity-and-access.md +39 -0
  378. package/help/mcp.md +30 -0
  379. package/help/native-capabilities.md +30 -0
  380. package/help/observability.md +41 -0
  381. package/help/operating-agents.md +30 -0
  382. package/help/security.md +27 -0
  383. package/help/troubleshooting/budgets.md +26 -0
  384. package/help/troubleshooting/coding-workers.md +47 -0
  385. package/help/troubleshooting/repository-access.md +27 -0
  386. package/package.json +12 -3
  387. package/prisma/migrations/20260925010000_coding_collect_exclude/migration.sql +8 -0
  388. package/prisma/migrations/20260925015000_allowed_egress_default/migration.sql +8 -0
  389. package/prisma/migrations/20260925020000_coding_package_registry/migration.sql +55 -0
  390. package/prisma/migrations/20260925030000_tool_name_per_owner/migration.sql +11 -0
  391. package/prisma/migrations/20260926010000_run_trigger_host_event/migration.sql +7 -0
  392. package/prisma/migrations/20260926020000_code_review_hosts/migration.sql +53 -0
  393. package/prisma/migrations/20260926030000_auth_user_roles/migration.sql +9 -0
  394. package/prisma/migrations/20260926040000_agent_effort/migration.sql +6 -0
  395. package/prisma/migrations/20260926050000_registry_lockfile_plan/migration.sql +32 -0
  396. package/prisma/migrations/20260926050000_repo_access_authorization/migration.sql +82 -0
  397. package/prisma/migrations/20260926060000_registry_plan_refusal/migration.sql +19 -0
  398. package/prisma/migrations/20260926100000_registry_plan_refusal_published_at/migration.sql +5 -0
  399. package/prisma/migrations/20260926190000_run_host_status/migration.sql +18 -0
  400. package/prisma/migrations/20260926210000_run_host_status_at_dispatch/migration.sql +5 -0
  401. package/prisma/migrations/20260927010000_resource_grants/migration.sql +72 -0
  402. package/prisma/migrations/20260927020000_proxy_session_budget_exhausted/migration.sql +3 -0
  403. package/prisma/migrations/20260927030000_coding_debug_trace/migration.sql +4 -0
  404. package/prisma/migrations/20260927040000_proxy_session_upstream_failure/migration.sql +3 -0
  405. package/prisma/migrations/20260927050000_coding_run_services/migration.sql +74 -0
  406. package/prisma/migrations/20260928000000_coding_run_tool_image/migration.sql +5 -0
  407. package/prisma/schema.prisma +407 -21
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Minimal CLI.
4
4
  *
5
- * wardby agent create --name <n> --model <m> --prompt <p> --budget <usd> [--schedule "<cron>"] [--timezone <tz>] [--memory-enabled]
5
+ * wardby agent create --name <n> --model <m> --prompt <p> --budget <usd> [--schedule "<cron>"] [--timezone <tz>] [--memory-enabled] [--effort <level>]
6
6
  * wardby agent list
7
7
  * wardby agent schedule <name> --cron "<expr>" [--timezone <tz>] [--disable]
8
8
  * wardby run <name>
@@ -20,31 +20,40 @@ import { readFileSync } from "node:fs";
20
20
  import { execFile as execFileCallback } from "node:child_process";
21
21
  import { parseArgs } from "node:util";
22
22
  import { promisify } from "node:util";
23
- import { loadCodingConcurrencyConfig, loadContainerExecutorConfig, loadKubernetesJobConfig, loadProviderConfig, } from "./config/providers.js";
23
+ import { loadCodingConcurrencyConfig, loadContainerExecutorConfig, loadKubernetesJobConfig, loadMcpConfig, loadProviderConfig, } from "./config/providers.js";
24
24
  import { drainCodingQueue } from "./core/coding-queue.js";
25
25
  import { isImmutableDockerImage } from "./providers/jobs/docker-isolation.js";
26
26
  import { ClientNodeKubernetesApi } from "./providers/jobs/kubernetes-client.js";
27
27
  import { describePreflightFailure, kubernetesPreflight } from "./providers/jobs/kubernetes-preflight.js";
28
- import { RoutingLlmProvider, resolveLlmRegistrations } from "./providers/llm/index.js";
28
+ import { RoutingLlmProvider, isLlmEffort, modelSupportedEfforts, resolveLlmRegistrations, } from "./providers/llm/index.js";
29
29
  import { buildConfiguredExecutor, buildExecutor } from "./providers/executor/index.js";
30
30
  import { PostgresDatastore } from "./providers/datastore/index.js";
31
31
  import { PostgresAgentMemory } from "./providers/memory/index.js";
32
32
  import { buildSecretCipher } from "./providers/secrets/index.js";
33
33
  import { prisma } from "./core/db.js";
34
34
  import { runAgent } from "./core/runner.js";
35
+ import { cancelRunOnSignal } from "./core/run-heartbeat.js";
36
+ import { buildReviewHosts } from "./providers/review-host/index.js";
37
+ import { createRepoAccessGate } from "./core/repo-access.js";
35
38
  import { validateCronExpression } from "./core/cron.js";
36
39
  import { startScheduler } from "./core/scheduler.js";
37
40
  import { startReconciler } from "./core/reconciler.js";
38
41
  import { NativeEngine } from "./core/engine-native.js";
39
42
  import { logger } from "./core/logger.js";
40
43
  import { deriveJsonSchema } from "./sandbox/zod-params.js";
44
+ import { findSameNamedAttachedTool, reservedToolNameReason, resolveToolRef } from "./core/tool-names.js";
45
+ import { ToolAttachedError, deleteToolGuarded, formatAttachedAgents, formatToolLine, hasToolChanges, prepareToolUpdate, updateToolGuarded, } from "./core/tool-admin.js";
41
46
  import { ToolCapabilitiesPatchSchema } from "./sandbox/tool-capabilities.js";
42
47
  import { startMcp } from "./mcp/index.js";
43
48
  import { startServe } from "./serve.js";
44
49
  import { authCommand } from "./mcp/auth/self-hosted/cli.js";
50
+ import { hostAccountCommand } from "./mcp/auth/host-account-cli.js";
51
+ import { grantsCommand, resolveCliAgentOwner } from "./mcp/auth/grants-cli.js";
52
+ import { everyoneGrantData } from "./core/grants.js";
45
53
  import { parseImportArgs } from "./import/cli-args.js";
46
54
  import { runImport } from "./import/index.js";
47
55
  import { CLI_USAGE } from "./cli-help.js";
56
+ import { helpCommand } from "./help/cli.js";
48
57
  const cliLog = logger.child({ module: "cli" });
49
58
  const RUN_STATUSES = [
50
59
  "pending",
@@ -106,6 +115,9 @@ async function agentCreate(args) {
106
115
  timezone: { type: "string" },
107
116
  "max-turns": { type: "string" },
108
117
  "memory-enabled": { type: "boolean" },
118
+ effort: { type: "string" },
119
+ owner: { type: "string" },
120
+ public: { type: "boolean" },
109
121
  },
110
122
  });
111
123
  if (!values.name || !values.model || !values.prompt || !values.budget) {
@@ -128,17 +140,41 @@ async function agentCreate(args) {
128
140
  fail(`invalid --schedule/--timezone: ${err instanceof Error ? err.message : String(err)}`);
129
141
  }
130
142
  }
131
- const agent = await prisma.agent.create({
132
- data: {
133
- name: values.name,
134
- model: values.model,
135
- systemPrompt: values.prompt,
136
- budgetUsd,
137
- schedule: values.schedule ?? null,
138
- timezone,
139
- maxTurns,
140
- memoryEnabled: values["memory-enabled"] ?? false,
141
- },
143
+ if (values.effort !== undefined) {
144
+ const accepted = modelSupportedEfforts(values.model);
145
+ if (!isLlmEffort(values.effort) || !accepted.includes(values.effort)) {
146
+ fail(`model "${values.model}" does not accept --effort "${values.effort}"` +
147
+ (accepted.length > 0 ? ` (accepted: ${accepted.join(", ")}).` : " (it accepts no effort setting)."));
148
+ }
149
+ }
150
+ // Owned by --owner or the local operator; never owner-less (resource-
151
+ // sharing grants spec §3.8). --public shares it with everyone at execute.
152
+ let ownerId;
153
+ try {
154
+ ownerId = await resolveCliAgentOwner(prisma, values.owner, loadMcpConfig().localPrincipal);
155
+ }
156
+ catch (err) {
157
+ fail(err instanceof Error ? err.message : String(err));
158
+ }
159
+ const agent = await prisma.$transaction(async (tx) => {
160
+ const created = await tx.agent.create({
161
+ data: {
162
+ name: values.name,
163
+ model: values.model,
164
+ systemPrompt: values.prompt,
165
+ budgetUsd,
166
+ schedule: values.schedule ?? null,
167
+ timezone,
168
+ maxTurns,
169
+ memoryEnabled: values["memory-enabled"] ?? false,
170
+ effort: values.effort ?? null,
171
+ ownerId: ownerId,
172
+ },
173
+ });
174
+ if (values.public) {
175
+ await tx.resourceGrant.create({ data: everyoneGrantData("agent", created.id, "execute", "operator") });
176
+ }
177
+ return created;
142
178
  });
143
179
  console.log(agent.id);
144
180
  }
@@ -155,6 +191,9 @@ async function toolCreate(args) {
155
191
  if (!values.name || !values.description || !values.params || !values.code) {
156
192
  fail("tool create requires --name, --description, --params <file>, and --code <file>.");
157
193
  }
194
+ const reserved = reservedToolNameReason(values.name);
195
+ if (reserved)
196
+ fail(reserved);
158
197
  let paramsZod;
159
198
  let code;
160
199
  try {
@@ -170,12 +209,19 @@ async function toolCreate(args) {
170
209
  fail(`could not read --code file "${values.code}": ${err instanceof Error ? err.message : String(err)}`);
171
210
  }
172
211
  // Fails at registration, not at call time: a malformed schema never gets
173
- // persisted. The derived schema is cached on the row (no "update tool"
174
- // path exists, so it can never go stale) rather than re-derived per run.
212
+ // persisted. The derived schema is cached on the row rather than
213
+ // re-derived per run; MCP update_tool re-derives it whenever paramsZod
214
+ // changes, so it never goes stale.
175
215
  const schemaResult = await deriveJsonSchema(paramsZod);
176
216
  if (!schemaResult.ok) {
177
217
  fail(`invalid --params schema: ${schemaResult.errorMessage}`);
178
218
  }
219
+ // CLI tools are public (no owner), and the (ownerId, name) unique index
220
+ // treats NULL owners as distinct, so it can't stop a second public tool
221
+ // with this name -- check here instead.
222
+ if (await prisma.tool.findFirst({ where: { ownerId: null, name: values.name } })) {
223
+ fail(`a public tool named "${values.name}" already exists.`);
224
+ }
179
225
  const tool = await prisma.tool.create({
180
226
  data: {
181
227
  name: values.name,
@@ -203,11 +249,14 @@ async function toolAttach(args, detach) {
203
249
  });
204
250
  const [toolName, agentName] = positionals;
205
251
  if (!toolName || !agentName) {
206
- fail(`tool ${detach ? "detach" : "attach"} requires <tool-name> <agent-name>.`);
207
- }
208
- const tool = await prisma.tool.findUnique({ where: { name: toolName } });
209
- if (!tool)
210
- fail(`unknown tool "${toolName}".`);
252
+ fail(`tool ${detach ? "detach" : "attach"} requires <tool-name|tool-id> <agent-name>.`);
253
+ }
254
+ // Tool names are unique per owner, not globally: an ambiguous name fails
255
+ // with the candidate ids, and an id is accepted in its place.
256
+ const resolved = await resolveToolRef(prisma, toolName);
257
+ if (!resolved.ok)
258
+ fail(resolved.error);
259
+ const tool = resolved.tool;
211
260
  const agent = await prisma.agent.findUnique({ where: { name: agentName } });
212
261
  if (!agent)
213
262
  fail(`unknown agent "${agentName}".`);
@@ -229,6 +278,14 @@ async function toolAttach(args, detach) {
229
278
  (allowedSharedDatastorePrefixes[boundName] ??= []).push(prefix);
230
279
  }
231
280
  }
281
+ // Same guard as MCP attach_tool: one agent never holds two tools with the
282
+ // same name, since the runtime dispatches by name. Operator-only, so unlike
283
+ // attach_tool this check-then-upsert is not one Serializable transaction
284
+ // (the runner's load-time duplicate check still catches a race).
285
+ const clash = await findSameNamedAttachedTool(prisma, agent.id, tool);
286
+ if (clash) {
287
+ fail(`agent "${agentName}" already has a different tool named "${tool.name}" attached (${clash.id}); detach it first.`);
288
+ }
232
289
  const patch = ToolCapabilitiesPatchSchema.safeParse({
233
290
  allowedSecrets: values["allow-secret"],
234
291
  allowedDatastorePrefixes: values["allow-datastore-prefix"],
@@ -238,6 +295,10 @@ async function toolAttach(args, detach) {
238
295
  if (!patch.success) {
239
296
  fail(`invalid tool capabilities: ${patch.error.issues.map((i) => i.message).join("; ")}`);
240
297
  }
298
+ // The operator is trusted with the database, so it grants these
299
+ // capabilities in the agent owner's name: the runner honours them only
300
+ // with the owner's consent stamp (resource-sharing grants spec §3.4.2).
301
+ // An owner-less agent has no owner to stamp: its capabilities stay inert.
241
302
  await prisma.agentTool.upsert({
242
303
  where: { agentId_toolId: { agentId: agent.id, toolId: tool.id } },
243
304
  create: {
@@ -247,8 +308,10 @@ async function toolAttach(args, detach) {
247
308
  allowedDatastorePrefixes: patch.data.allowedDatastorePrefixes ?? [],
248
309
  allowedHosts: patch.data.allowedHosts ?? [],
249
310
  allowedSharedDatastorePrefixes: patch.data.allowedSharedDatastorePrefixes ?? {},
311
+ capabilitiesGrantedById: agent.ownerId,
250
312
  },
251
313
  update: {
314
+ capabilitiesGrantedById: agent.ownerId,
252
315
  ...(patch.data.allowedSecrets !== undefined ? { allowedSecrets: patch.data.allowedSecrets } : {}),
253
316
  ...(patch.data.allowedDatastorePrefixes !== undefined
254
317
  ? { allowedDatastorePrefixes: patch.data.allowedDatastorePrefixes }
@@ -273,16 +336,116 @@ async function toolList(args) {
273
336
  return;
274
337
  }
275
338
  for (const a of attached)
276
- console.log(`${a.tool.name} ${a.tool.description}`);
339
+ console.log(formatToolLine(a.tool));
277
340
  return;
278
341
  }
279
- const tools = await prisma.tool.findMany({ orderBy: { name: "asc" } });
342
+ const tools = await prisma.tool.findMany({ orderBy: [{ name: "asc" }, { id: "asc" }] });
280
343
  if (tools.length === 0) {
281
344
  console.log("no tools registered.");
282
345
  return;
283
346
  }
284
347
  for (const t of tools)
285
- console.log(`${t.name} ${t.description}`);
348
+ console.log(formatToolLine(t));
349
+ }
350
+ /**
351
+ * The operator may change any tool, public ones included; only a row that
352
+ * vanished since it was resolved is refused. Thrown rather than fail()ed:
353
+ * it runs inside the transaction, which must roll back, not exit mid-way.
354
+ */
355
+ function operatorAuthorize(ref) {
356
+ return (tool) => {
357
+ if (!tool)
358
+ throw new Error(`unknown tool "${ref}".`);
359
+ };
360
+ }
361
+ /**
362
+ * `wardby tool update <tool-name|tool-id>` -- the operator's counterpart of
363
+ * MCP update_tool, and the only way to change a public tool. Same
364
+ * validation (jsonSchema re-derived from --params) and the same attachment
365
+ * rule, judged against the tool's owner (core/tool-admin.ts).
366
+ */
367
+ async function toolUpdate(args) {
368
+ const { values, positionals } = parseArgs({
369
+ args,
370
+ allowPositionals: true,
371
+ options: {
372
+ description: { type: "string" },
373
+ params: { type: "string" },
374
+ code: { type: "string" },
375
+ },
376
+ });
377
+ const [ref] = positionals;
378
+ if (!ref)
379
+ fail("tool update requires <tool-name|tool-id>.");
380
+ const readFile = (flag, path) => {
381
+ if (path === undefined)
382
+ return undefined;
383
+ try {
384
+ return readFileSync(path, "utf8");
385
+ }
386
+ catch (err) {
387
+ fail(`could not read ${flag} file "${path}": ${err instanceof Error ? err.message : String(err)}`);
388
+ }
389
+ };
390
+ const changes = {
391
+ description: values.description,
392
+ paramsZod: readFile("--params", values.params),
393
+ code: readFile("--code", values.code),
394
+ };
395
+ if (!hasToolChanges(changes)) {
396
+ fail("tool update requires at least one of --description, --params <file>, --code <file>.");
397
+ }
398
+ const resolved = await resolveToolRef(prisma, ref);
399
+ if (!resolved.ok)
400
+ fail(resolved.error);
401
+ const prepared = await prepareToolUpdate(changes);
402
+ if (!prepared.ok)
403
+ fail(`invalid --params schema: ${prepared.errorMessage}`);
404
+ try {
405
+ await updateToolGuarded(prisma, resolved.tool.id, prepared.data, operatorAuthorize(ref));
406
+ }
407
+ catch (err) {
408
+ if (err instanceof ToolAttachedError) {
409
+ fail(`tool "${ref}" is attached to agents with a different owner: ${formatAttachedAgents(err.agents)}. Detach it from those agents first, or create a new tool.`);
410
+ }
411
+ throw err;
412
+ }
413
+ console.log(`updated tool ${resolved.tool.id}.`);
414
+ }
415
+ /** `wardby tool delete <tool-name|tool-id> [--detach]` -- MCP delete_tool's rules, public tools included. */
416
+ async function toolDelete(args) {
417
+ const { values, positionals } = parseArgs({
418
+ args,
419
+ allowPositionals: true,
420
+ options: { detach: { type: "boolean" } },
421
+ });
422
+ const [ref] = positionals;
423
+ if (!ref)
424
+ fail("tool delete requires <tool-name|tool-id>.");
425
+ const resolved = await resolveToolRef(prisma, ref);
426
+ if (!resolved.ok)
427
+ fail(resolved.error);
428
+ let detachedFrom;
429
+ try {
430
+ detachedFrom = await deleteToolGuarded(prisma, resolved.tool.id, {
431
+ detach: values.detach ?? false,
432
+ authorize: operatorAuthorize(ref),
433
+ });
434
+ }
435
+ catch (err) {
436
+ if (!(err instanceof ToolAttachedError))
437
+ throw err;
438
+ if (err.reason === "other_owners") {
439
+ fail(`tool "${ref}" is attached to agents with a different owner: ${formatAttachedAgents(err.agents)}. Detach it from those agents first (wardby tool detach).`);
440
+ }
441
+ if (err.reason === "needs_detach") {
442
+ fail(`tool "${ref}" is still attached to ${formatAttachedAgents(err.agents)}. Pass --detach to detach it and delete it.`);
443
+ }
444
+ fail(`tool "${ref}" is still attached to an agent; nothing was deleted.`);
445
+ }
446
+ console.log(detachedFrom.length > 0
447
+ ? `deleted tool ${resolved.tool.id} (detached from ${detachedFrom.join(", ")}).`
448
+ : `deleted tool ${resolved.tool.id}.`);
286
449
  }
287
450
  async function agentSchedule(args) {
288
451
  const [name, ...rest] = args;
@@ -353,14 +516,22 @@ async function run(name) {
353
516
  const datastore = buildDatastore(secrets);
354
517
  const memory = buildMemory();
355
518
  let run;
519
+ // Ctrl-C (or a SIGTERM) records the run as cancelled rather than leaving a
520
+ // `running` row behind.
521
+ let removeSignalHandlers;
356
522
  try {
357
- run = await runAgent(name, { llm, engine, datastore, secrets, memory }, prisma, (delta) => {
523
+ run = await runAgent(name, { llm, engine, datastore, secrets, memory, reviewHosts: buildReviewHosts() }, prisma, (delta) => {
358
524
  process.stdout.write(delta);
525
+ }, (created) => {
526
+ removeSignalHandlers = cancelRunOnSignal(prisma, created.id);
359
527
  });
360
528
  }
361
529
  catch (err) {
362
530
  fail(err instanceof Error ? err.message : String(err));
363
531
  }
532
+ finally {
533
+ removeSignalHandlers?.();
534
+ }
364
535
  process.stdout.write("\n");
365
536
  const completedAgent = await prisma.agent.findUnique({ where: { id: run.agentId } });
366
537
  const budgetUsd = completedAgent ? Number(completedAgent.budgetUsd) : NaN;
@@ -492,10 +663,13 @@ async function scheduler(args) {
492
663
  const secrets = buildSecrets();
493
664
  const datastore = buildDatastore(secrets);
494
665
  const memory = buildMemory();
495
- const nativeExecutor = buildExecutor(config, { llm, engine, datastore, secrets, memory }, prisma);
496
- const executor = buildConfiguredExecutor({ native: nativeExecutor, db: prisma, providerConfig: config });
666
+ const reviewHosts = buildReviewHosts();
667
+ // One repository-access gate (and cache) for native repo_* calls and coding runs.
668
+ const repoAccess = createRepoAccessGate({ db: prisma, hosts: reviewHosts });
669
+ const nativeExecutor = buildExecutor(config, { llm, engine, datastore, secrets, memory, reviewHosts, repoAccess }, prisma);
670
+ const executor = buildConfiguredExecutor({ native: nativeExecutor, db: prisma, providerConfig: config, repoAccess });
497
671
  await executor.launch?.();
498
- const reconciler = startReconciler({ db: prisma, executor });
672
+ const reconciler = startReconciler({ db: prisma, executor, reviewHosts });
499
673
  const sched = startScheduler({
500
674
  executor,
501
675
  db: prisma,
@@ -570,9 +744,19 @@ async function importCommand(rest) {
570
744
  async function main() {
571
745
  const [command, ...rest] = process.argv.slice(2);
572
746
  try {
573
- if (command === "auth") {
747
+ if (command === "auth" && rest[0] === "host-account") {
748
+ // Both auth modes: keyed on Principal, not the self-hosted AuthUser.
749
+ await hostAccountCommand(rest.slice(1), prisma);
750
+ }
751
+ else if (command === "grants") {
752
+ await grantsCommand(rest, prisma);
753
+ }
754
+ else if (command === "auth") {
574
755
  await authCommand(rest, prisma, process.env.AUTH_CREDENTIAL_HASH_KEY ?? "");
575
756
  }
757
+ else if (command === "help") {
758
+ await helpCommand(rest);
759
+ }
576
760
  else if (command === "agent" && rest[0] === "create") {
577
761
  await agentCreate(rest.slice(1));
578
762
  }
@@ -591,6 +775,12 @@ async function main() {
591
775
  else if (command === "tool" && rest[0] === "detach") {
592
776
  await toolAttach(rest.slice(1), true);
593
777
  }
778
+ else if (command === "tool" && rest[0] === "update") {
779
+ await toolUpdate(rest.slice(1));
780
+ }
781
+ else if (command === "tool" && rest[0] === "delete") {
782
+ await toolDelete(rest.slice(1));
783
+ }
594
784
  else if (command === "tool" && rest[0] === "list") {
595
785
  await toolList(rest.slice(1));
596
786
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Paths a coding run's workspace never sends back: dependency and cache folders
3
+ * (matched by name at any depth) plus per-agent repository-relative paths. The
4
+ * same set is rendered three ways so the Kubernetes keeper's tar, the Docker
5
+ * staging prune, and Git staging all agree on what "excluded" means.
6
+ */
7
+ export declare const BUILTIN_COLLECT_EXCLUDE_NAMES: readonly ["node_modules", ".venv", "venv", "__pycache__", ".pytest_cache", ".ruff_cache", ".mypy_cache", ".tox", ".vite", ".cache"];
8
+ export declare const MAX_COLLECT_EXCLUDE_PATHS = 64;
9
+ export interface CollectExclusions {
10
+ names: readonly string[];
11
+ paths: readonly string[];
12
+ }
13
+ export declare function validateCollectExcludePath(value: string): string;
14
+ export declare function collectExclusions(paths: readonly string[]): CollectExclusions;
15
+ /** For values read back from the database or a job record, which are untrusted shapes. */
16
+ export declare function normalizeCollectExclusions(value: unknown): CollectExclusions;
17
+ export declare function isCollectExcluded(relativePath: string, exclusions: CollectExclusions): boolean;
18
+ /**
19
+ * GNU tar options for `tar -C <workspace> -cf - .`, whose member names start with
20
+ * "./". Names are unanchored (they match any path component); paths are anchored
21
+ * to the archive root. An excluded directory's contents are skipped with it.
22
+ */
23
+ export declare function tarExcludeArgs(exclusions: CollectExclusions): string[];
24
+ /** Git exclude pathspecs, appended after ":/" when staging. */
25
+ export declare function gitExcludePathspecs(exclusions: CollectExclusions): string[];
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Paths a coding run's workspace never sends back: dependency and cache folders
3
+ * (matched by name at any depth) plus per-agent repository-relative paths. The
4
+ * same set is rendered three ways so the Kubernetes keeper's tar, the Docker
5
+ * staging prune, and Git staging all agree on what "excluded" means.
6
+ */
7
+ export const BUILTIN_COLLECT_EXCLUDE_NAMES = [
8
+ "node_modules",
9
+ ".venv",
10
+ "venv",
11
+ "__pycache__",
12
+ ".pytest_cache",
13
+ ".ruff_cache",
14
+ ".mypy_cache",
15
+ ".tox",
16
+ ".vite",
17
+ ".cache",
18
+ ];
19
+ export const MAX_COLLECT_EXCLUDE_PATHS = 64;
20
+ const MAX_PATH_BYTES = 512;
21
+ const CONTROL = /[\u0000-\u001F\u007F]/;
22
+ const GLOB = /[*?[\]]/;
23
+ export function validateCollectExcludePath(value) {
24
+ const path = value.trim();
25
+ const valid = path.length > 0 &&
26
+ Buffer.byteLength(path, "utf8") <= MAX_PATH_BYTES &&
27
+ !CONTROL.test(path) &&
28
+ !GLOB.test(path) &&
29
+ !path.includes("\\") &&
30
+ !path.startsWith("/") &&
31
+ !path.startsWith("./") &&
32
+ !path.split("/").some((part) => part === "" || part === "." || part === "..");
33
+ if (!valid)
34
+ throw new Error("collect_exclude_path_invalid");
35
+ return path;
36
+ }
37
+ export function collectExclusions(paths) {
38
+ if (paths.length > MAX_COLLECT_EXCLUDE_PATHS)
39
+ throw new Error("collect_exclude_path_invalid");
40
+ return { names: [...BUILTIN_COLLECT_EXCLUDE_NAMES], paths: [...new Set(paths.map(validateCollectExcludePath))] };
41
+ }
42
+ /** For values read back from the database or a job record, which are untrusted shapes. */
43
+ export function normalizeCollectExclusions(value) {
44
+ if (value === undefined || value === null)
45
+ return collectExclusions([]);
46
+ if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) {
47
+ throw new Error("collect_exclude_invalid");
48
+ }
49
+ return collectExclusions(value);
50
+ }
51
+ export function isCollectExcluded(relativePath, exclusions) {
52
+ const segments = relativePath.split("/");
53
+ if (segments.some((segment) => exclusions.names.includes(segment)))
54
+ return true;
55
+ return exclusions.paths.some((path) => relativePath === path || relativePath.startsWith(`${path}/`));
56
+ }
57
+ /**
58
+ * GNU tar options for `tar -C <workspace> -cf - .`, whose member names start with
59
+ * "./". Names are unanchored (they match any path component); paths are anchored
60
+ * to the archive root. An excluded directory's contents are skipped with it.
61
+ */
62
+ export function tarExcludeArgs(exclusions) {
63
+ return [
64
+ "--no-anchored",
65
+ ...exclusions.names.map((name) => `--exclude=${name}`),
66
+ "--anchored",
67
+ ...exclusions.paths.map((path) => `--exclude=./${path}`),
68
+ ];
69
+ }
70
+ /** Git exclude pathspecs, appended after ":/" when staging. */
71
+ export function gitExcludePathspecs(exclusions) {
72
+ return [
73
+ ...exclusions.names.flatMap((name) => [`:(exclude,glob)**/${name}`, `:(exclude,glob)**/${name}/**`]),
74
+ ...exclusions.paths.map((path) => `:(exclude,literal)${path}`),
75
+ ];
76
+ }
@@ -1,9 +1,8 @@
1
1
  import { z } from "zod";
2
2
  export declare const MIN_CODING_TIMEOUT_SEC = 60;
3
3
  export declare const MAX_CODING_TIMEOUT_SEC = 7200;
4
- export declare const MAX_ALLOWED_EGRESS_HOSTS = 64;
5
4
  export declare const MAX_PROTECTED_PATHS = 128;
6
- export declare const DEFAULT_PROTECTED_PATHS: readonly [".github/workflows/**", ".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS"];
5
+ export declare const DEFAULT_PROTECTED_PATHS: readonly [".github/workflows/**", ".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS", ".wardby/**", "!.wardby/services.yaml"];
7
6
  export declare const CodingProfileSchema: z.ZodObject<{
8
7
  provider: z.ZodDefault<z.ZodEnum<["codex", "claude-code"]>>;
9
8
  repository: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
@@ -11,38 +10,61 @@ export declare const CodingProfileSchema: z.ZodObject<{
11
10
  defaultTask: z.ZodDefault<z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>>>;
12
11
  allowWebhookTaskOverride: z.ZodDefault<z.ZodBoolean>;
13
12
  timeoutSec: z.ZodDefault<z.ZodNumber>;
14
- allowedEgress: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>>;
15
- protectedPaths: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>>;
13
+ protectedPaths: z.ZodDefault<z.ZodEffects<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>, string[], string[]>>;
14
+ collectExclude: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">, string[], string[]>>;
16
15
  toolchain: z.ZodDefault<z.ZodEnum<["node", "node-python"]>>;
17
16
  toolchainVersion: z.ZodDefault<z.ZodNullable<z.ZodString>>;
18
17
  workerImageRef: z.ZodDefault<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
19
18
  workspaceDiskMb: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
19
+ packageAllowlist: z.ZodDefault<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>, Record<string, string[]>, Record<string, string[]>>>;
20
+ packagePolicy: z.ZodDefault<z.ZodEffects<z.ZodObject<{
21
+ minReleaseAgeDays: z.ZodOptional<z.ZodNumber>;
22
+ }, "strict", z.ZodTypeAny, {
23
+ minReleaseAgeDays?: number | undefined;
24
+ }, {
25
+ minReleaseAgeDays?: number | undefined;
26
+ }>, {
27
+ minReleaseAgeDays?: number | undefined;
28
+ }, {
29
+ minReleaseAgeDays?: number | undefined;
30
+ }>>;
31
+ services: z.ZodDefault<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>>;
20
32
  }, "strict", z.ZodTypeAny, {
21
33
  repository: string;
22
34
  baseRef: string;
35
+ services: string[];
23
36
  provider: "codex" | "claude-code";
24
- defaultTask: string | null;
25
- allowWebhookTaskOverride: boolean;
26
37
  timeoutSec: number;
27
- allowedEgress: string[];
28
38
  protectedPaths: string[];
39
+ collectExclude: string[];
40
+ workspaceDiskMb: number | null;
41
+ packageAllowlist: Record<string, string[]>;
42
+ packagePolicy: {
43
+ minReleaseAgeDays?: number | undefined;
44
+ };
45
+ defaultTask: string | null;
46
+ allowWebhookTaskOverride: boolean;
29
47
  toolchain: "node-python" | "node";
30
48
  toolchainVersion: string | null;
31
49
  workerImageRef: string | null;
32
- workspaceDiskMb: number | null;
33
50
  }, {
34
51
  repository: string;
35
52
  baseRef?: string | undefined;
53
+ services?: string[] | undefined;
36
54
  provider?: "codex" | "claude-code" | undefined;
37
- defaultTask?: string | null | undefined;
38
- allowWebhookTaskOverride?: boolean | undefined;
39
55
  timeoutSec?: number | undefined;
40
- allowedEgress?: string[] | undefined;
41
56
  protectedPaths?: string[] | undefined;
57
+ collectExclude?: string[] | undefined;
58
+ workspaceDiskMb?: number | null | undefined;
59
+ packageAllowlist?: Record<string, string[]> | undefined;
60
+ packagePolicy?: {
61
+ minReleaseAgeDays?: number | undefined;
62
+ } | undefined;
63
+ defaultTask?: string | null | undefined;
64
+ allowWebhookTaskOverride?: boolean | undefined;
42
65
  toolchain?: "node-python" | "node" | undefined;
43
66
  toolchainVersion?: string | null | undefined;
44
67
  workerImageRef?: string | null | undefined;
45
- workspaceDiskMb?: number | null | undefined;
46
68
  }>;
47
69
  export declare const CodingProfilePatchSchema: z.ZodObject<{
48
70
  provider: z.ZodOptional<z.ZodEnum<["codex", "claude-code"]>>;
@@ -51,38 +73,61 @@ export declare const CodingProfilePatchSchema: z.ZodObject<{
51
73
  defaultTask: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>>>;
52
74
  allowWebhookTaskOverride: z.ZodOptional<z.ZodBoolean>;
53
75
  timeoutSec: z.ZodOptional<z.ZodNumber>;
54
- allowedEgress: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>>;
55
- protectedPaths: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>>;
76
+ protectedPaths: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, "many">, string[], string[]>, string[], string[]>>;
77
+ collectExclude: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">, string[], string[]>>;
56
78
  toolchain: z.ZodOptional<z.ZodEnum<["node", "node-python"]>>;
57
79
  toolchainVersion: z.ZodOptional<z.ZodNullable<z.ZodString>>;
58
80
  workerImageRef: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
59
81
  workspaceDiskMb: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
82
+ packageAllowlist: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>, Record<string, string[]>, Record<string, string[]>>>;
83
+ packagePolicy: z.ZodOptional<z.ZodEffects<z.ZodObject<{
84
+ minReleaseAgeDays: z.ZodOptional<z.ZodNumber>;
85
+ }, "strict", z.ZodTypeAny, {
86
+ minReleaseAgeDays?: number | undefined;
87
+ }, {
88
+ minReleaseAgeDays?: number | undefined;
89
+ }>, {
90
+ minReleaseAgeDays?: number | undefined;
91
+ }, {
92
+ minReleaseAgeDays?: number | undefined;
93
+ }>>;
94
+ services: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>>;
60
95
  }, "strict", z.ZodTypeAny, {
61
96
  repository?: string | undefined;
62
97
  baseRef?: string | undefined;
98
+ services?: string[] | undefined;
63
99
  provider?: "codex" | "claude-code" | undefined;
64
- defaultTask?: string | null | undefined;
65
- allowWebhookTaskOverride?: boolean | undefined;
66
100
  timeoutSec?: number | undefined;
67
- allowedEgress?: string[] | undefined;
68
101
  protectedPaths?: string[] | undefined;
102
+ collectExclude?: string[] | undefined;
103
+ workspaceDiskMb?: number | null | undefined;
104
+ packageAllowlist?: Record<string, string[]> | undefined;
105
+ packagePolicy?: {
106
+ minReleaseAgeDays?: number | undefined;
107
+ } | undefined;
108
+ defaultTask?: string | null | undefined;
109
+ allowWebhookTaskOverride?: boolean | undefined;
69
110
  toolchain?: "node-python" | "node" | undefined;
70
111
  toolchainVersion?: string | null | undefined;
71
112
  workerImageRef?: string | null | undefined;
72
- workspaceDiskMb?: number | null | undefined;
73
113
  }, {
74
114
  repository?: string | undefined;
75
115
  baseRef?: string | undefined;
116
+ services?: string[] | undefined;
76
117
  provider?: "codex" | "claude-code" | undefined;
77
- defaultTask?: string | null | undefined;
78
- allowWebhookTaskOverride?: boolean | undefined;
79
118
  timeoutSec?: number | undefined;
80
- allowedEgress?: string[] | undefined;
81
119
  protectedPaths?: string[] | undefined;
120
+ collectExclude?: string[] | undefined;
121
+ workspaceDiskMb?: number | null | undefined;
122
+ packageAllowlist?: Record<string, string[]> | undefined;
123
+ packagePolicy?: {
124
+ minReleaseAgeDays?: number | undefined;
125
+ } | undefined;
126
+ defaultTask?: string | null | undefined;
127
+ allowWebhookTaskOverride?: boolean | undefined;
82
128
  toolchain?: "node-python" | "node" | undefined;
83
129
  toolchainVersion?: string | null | undefined;
84
130
  workerImageRef?: string | null | undefined;
85
- workspaceDiskMb?: number | null | undefined;
86
131
  }>;
87
132
  export type CodingProfile = z.infer<typeof CodingProfileSchema>;
88
133
  export type CodingProfilePatch = z.infer<typeof CodingProfilePatchSchema>;