@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
@@ -1,19 +1,23 @@
1
- import { isIP } from "node:net";
2
1
  import { z } from "zod";
3
2
  import { isImmutableDockerImage } from "../providers/jobs/docker-isolation.js";
4
3
  import { MAX_CODING_TASK_BYTES, normalizeGitHubRepository, normalizeGitRef } from "./protocol.js";
4
+ import { MAX_COLLECT_EXCLUDE_PATHS, validateCollectExcludePath } from "./collect-exclude.js";
5
5
  import { CODING_PROVIDERS } from "./provider.js";
6
+ import { WARDBY_PROTECTED_PATHS, isWellFormedProtectedPath, protectsSomePath } from "./protected-paths.js";
7
+ import { parseAllowlist, resolvePolicy } from "./registry/allowlist.js";
8
+ import { REGISTRY_ADAPTERS } from "./registry/adapters.js";
9
+ import { AllowedServiceNamesSchema } from "./services/catalog.js";
6
10
  export const MIN_CODING_TIMEOUT_SEC = 60;
7
11
  export const MAX_CODING_TIMEOUT_SEC = 7200;
8
- export const MAX_ALLOWED_EGRESS_HOSTS = 64;
9
12
  export const MAX_PROTECTED_PATHS = 128;
10
13
  export const DEFAULT_PROTECTED_PATHS = [
11
14
  ".github/workflows/**",
12
15
  ".github/CODEOWNERS",
13
16
  "CODEOWNERS",
14
17
  "docs/CODEOWNERS",
18
+ // Enforced for every run anyway (providers/vcs/git.ts protectedPathMatcher); listed so new agents show it.
19
+ ...WARDBY_PROTECTED_PATHS,
15
20
  ];
16
- const MAX_HOST_BYTES = 253;
17
21
  const MAX_PROTECTED_PATH_BYTES = 512;
18
22
  const INVALID_MULTILINE_CONTROL = /[\u0000\u000B\u000C\u000E-\u001F\u007F]/;
19
23
  const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
@@ -50,27 +54,21 @@ const defaultTaskSchema = z
50
54
  .refine((value) => !INVALID_MULTILINE_CONTROL.test(value), "must not contain control characters")
51
55
  .refine((value) => value.trim().length > 0, "must not be blank")
52
56
  .nullable();
53
- const egressHostSchema = z
54
- .string()
55
- .transform((value) => value.trim().toLowerCase())
56
- .refine((value) => value.length > 0 && byteLength(value) <= MAX_HOST_BYTES, "must be a bounded hostname")
57
- .refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters")
58
- .refine((value) => isIP(value) === 0, "IP addresses and CIDRs are not allowed")
59
- .refine((value) => !/^\d+(?:\.\d+){3}$/.test(value), "IP-like hostnames are not allowed")
60
- .refine((value) => !value.includes("://") &&
61
- !value.includes("/") &&
62
- !value.includes("@") &&
63
- !value.includes(":") &&
64
- !value.includes("*"), "must be an exact hostname")
65
- .refine((value) => value !== "localhost" && value.includes("."), "must be a fully qualified hostname")
66
- .refine((value) => value.split(".").every((label) => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label)), "must be a valid ASCII hostname");
67
57
  const protectedPathSchema = z
68
58
  .string()
69
59
  .transform((value) => value.trim())
70
60
  .refine((value) => value.length > 0 && byteLength(value) <= MAX_PROTECTED_PATH_BYTES, "must be a bounded path")
71
61
  .refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters")
72
- .refine((value) => !value.startsWith("/") && !value.startsWith("./") && !value.includes("\\"), "must be a repository-relative POSIX path")
73
- .refine((value) => !value.split("/").some((part) => part === "" || part === "." || part === ".."), "must not contain empty or traversal components");
62
+ .refine(isWellFormedProtectedPath, "must be a repository-relative POSIX path without empty or traversal components, or ! and a literal file path (no wildcards) for an exception");
63
+ const collectExcludePathSchema = z.string().transform((value, ctx) => {
64
+ try {
65
+ return validateCollectExcludePath(value);
66
+ }
67
+ catch {
68
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "must be a repository-relative path without wildcards" });
69
+ return z.NEVER;
70
+ }
71
+ });
74
72
  const KNOWN_TOOLCHAINS = ["node", "node-python"];
75
73
  const toolchainSchema = z.enum(KNOWN_TOOLCHAINS);
76
74
  const toolchainVersionSchema = z.string().trim().min(1).max(32).nullable();
@@ -82,6 +80,30 @@ const workerImageRefSchema = z
82
80
  .refine(isImmutableDockerImage, "must be an immutable repository digest")
83
81
  .nullable();
84
82
  const workspaceDiskMbSchema = z.number().int().min(64).max(32_768).nullable();
83
+ const packageAllowlistSchema = z
84
+ .record(z.string(), z.array(z.string().min(1).max(256)).max(256))
85
+ .superRefine((value, ctx) => {
86
+ try {
87
+ parseAllowlist(value, REGISTRY_ADAPTERS);
88
+ }
89
+ catch (error) {
90
+ ctx.addIssue({
91
+ code: z.ZodIssueCode.custom,
92
+ message: error instanceof Error ? error.message : "invalid allowlist",
93
+ });
94
+ }
95
+ });
96
+ const packagePolicySchema = z
97
+ .object({ minReleaseAgeDays: z.number().int().min(0).max(30).optional() })
98
+ .strict()
99
+ .superRefine((value, ctx) => {
100
+ try {
101
+ resolvePolicy(value);
102
+ }
103
+ catch {
104
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "invalid package policy" });
105
+ }
106
+ });
85
107
  const codingProfileFields = {
86
108
  provider: z.enum(CODING_PROVIDERS),
87
109
  repository: repositorySchema,
@@ -93,15 +115,20 @@ const codingProfileFields = {
93
115
  toolchainVersion: toolchainVersionSchema,
94
116
  workerImageRef: workerImageRefSchema,
95
117
  workspaceDiskMb: workspaceDiskMbSchema,
96
- allowedEgress: z
97
- .array(egressHostSchema)
98
- .max(MAX_ALLOWED_EGRESS_HOSTS)
99
- .transform((hosts) => [...new Set(hosts)]),
100
118
  protectedPaths: z
101
119
  .array(protectedPathSchema)
102
120
  .min(1)
103
121
  .max(MAX_PROTECTED_PATHS)
122
+ .refine(protectsSomePath, "must protect at least one path; entries starting with ! are only exceptions")
123
+ .transform((paths) => [...new Set(paths)]),
124
+ collectExclude: z
125
+ .array(collectExcludePathSchema)
126
+ .max(MAX_COLLECT_EXCLUDE_PATHS)
104
127
  .transform((paths) => [...new Set(paths)]),
128
+ packageAllowlist: packageAllowlistSchema,
129
+ packagePolicy: packagePolicySchema,
130
+ /** Coding-run services this agent's runs may start: catalog names, any version (docs/coding-services.md). */
131
+ services: AllowedServiceNamesSchema,
105
132
  };
106
133
  export const CodingProfileSchema = z
107
134
  .object({
@@ -111,12 +138,15 @@ export const CodingProfileSchema = z
111
138
  defaultTask: codingProfileFields.defaultTask.default(null),
112
139
  allowWebhookTaskOverride: codingProfileFields.allowWebhookTaskOverride.default(false),
113
140
  timeoutSec: codingProfileFields.timeoutSec.default(1800),
114
- allowedEgress: codingProfileFields.allowedEgress.default([]),
115
141
  protectedPaths: codingProfileFields.protectedPaths.default([...DEFAULT_PROTECTED_PATHS]),
142
+ collectExclude: codingProfileFields.collectExclude.default([]),
116
143
  toolchain: codingProfileFields.toolchain.default("node"),
117
144
  toolchainVersion: codingProfileFields.toolchainVersion.default(null),
118
145
  workerImageRef: codingProfileFields.workerImageRef.default(null),
119
146
  workspaceDiskMb: codingProfileFields.workspaceDiskMb.default(null),
147
+ packageAllowlist: codingProfileFields.packageAllowlist.default({}),
148
+ packagePolicy: codingProfileFields.packagePolicy.default({}),
149
+ services: codingProfileFields.services.default([]),
120
150
  })
121
151
  .strict();
122
152
  export const CodingProfilePatchSchema = z
@@ -127,11 +157,14 @@ export const CodingProfilePatchSchema = z
127
157
  defaultTask: codingProfileFields.defaultTask.optional(),
128
158
  allowWebhookTaskOverride: codingProfileFields.allowWebhookTaskOverride.optional(),
129
159
  timeoutSec: codingProfileFields.timeoutSec.optional(),
130
- allowedEgress: codingProfileFields.allowedEgress.optional(),
131
160
  protectedPaths: codingProfileFields.protectedPaths.optional(),
161
+ collectExclude: codingProfileFields.collectExclude.optional(),
132
162
  toolchain: codingProfileFields.toolchain.optional(),
133
163
  toolchainVersion: codingProfileFields.toolchainVersion.optional(),
134
164
  workerImageRef: codingProfileFields.workerImageRef.optional(),
135
165
  workspaceDiskMb: codingProfileFields.workspaceDiskMb.optional(),
166
+ packageAllowlist: codingProfileFields.packageAllowlist.optional(),
167
+ packagePolicy: codingProfileFields.packagePolicy.optional(),
168
+ services: codingProfileFields.services.optional(),
136
169
  })
137
170
  .strict();
@@ -0,0 +1,24 @@
1
+ /**
2
+ * What a host (a builder continuation comment, a mention status comment) is
3
+ * told when a coding run's changes touched a path this agent may not edit
4
+ * (protectedPathMatcher in src/providers/vcs/git.ts). Public repositories
5
+ * read these, so the path -- taken from the run's own diff -- is treated as
6
+ * untrusted text: it never carries a backtick, a control character, or more
7
+ * than MAX_PATH_CHARS.
8
+ */
9
+ /** CodingRun.failureCategory for a run whose collected changes touched a protected path. */
10
+ export declare const PROTECTED_PATH_CATEGORY = "protected_path";
11
+ /** The path a `vcs_protected_path:<path>` error names, or null for any other error. */
12
+ export declare function protectedPathFromError(error: unknown): string | null;
13
+ /**
14
+ * The host sentence for a run stopped because its changes touched a
15
+ * protected path. Named the file when `path` sanitises to something usable;
16
+ * otherwise falls back to a sentence that doesn't try to name it.
17
+ */
18
+ export declare function protectedPathSentence(path: string | null | undefined): string;
19
+ /**
20
+ * The fixed line for a mention status comment naming a failed protected_path
21
+ * sub-run (host-status.ts). That comment reads children from the database,
22
+ * which has no path -- only the category -- so this line never names a file.
23
+ */
24
+ export declare const PROTECTED_PATH_HOST_LINE = "A sub-run could not open its changes: it changed a file its agent may not edit, so none of its changes were kept.";
@@ -0,0 +1,55 @@
1
+ /**
2
+ * What a host (a builder continuation comment, a mention status comment) is
3
+ * told when a coding run's changes touched a path this agent may not edit
4
+ * (protectedPathMatcher in src/providers/vcs/git.ts). Public repositories
5
+ * read these, so the path -- taken from the run's own diff -- is treated as
6
+ * untrusted text: it never carries a backtick, a control character, or more
7
+ * than MAX_PATH_CHARS.
8
+ */
9
+ /** CodingRun.failureCategory for a run whose collected changes touched a protected path. */
10
+ export const PROTECTED_PATH_CATEGORY = "protected_path";
11
+ /** git.ts's finalizeChanges throws this when the collected diff touches a protected path. */
12
+ const PROTECTED_PATH_ERROR_PREFIX = "vcs_protected_path:";
13
+ /** The path a `vcs_protected_path:<path>` error names, or null for any other error. */
14
+ export function protectedPathFromError(error) {
15
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
16
+ if (!message.startsWith(PROTECTED_PATH_ERROR_PREFIX))
17
+ return null;
18
+ const path = message.slice(PROTECTED_PATH_ERROR_PREFIX.length);
19
+ return path.length > 0 ? path : null;
20
+ }
21
+ const MAX_PATH_CHARS = 200;
22
+ /**
23
+ * A single-line, backtick-free rendering of a repository path safe to drop
24
+ * into one Markdown code span: control characters and backticks (which would
25
+ * otherwise close the span early) are neutralised, runs of whitespace
26
+ * collapse to one line, and the result is capped with an ellipsis. Null when
27
+ * nothing usable is left.
28
+ */
29
+ function sanitizePath(path) {
30
+ // eslint-disable-next-line no-control-regex -- deliberately stripping C0/DEL control characters.
31
+ const withoutControls = path.replace(/[\u0000-\u001f\u007f]+/g, " ");
32
+ const oneLine = withoutControls.replace(/\s+/g, " ").trim();
33
+ const withoutBackticks = oneLine.replace(/`/g, "'");
34
+ if (withoutBackticks.length === 0)
35
+ return null;
36
+ return withoutBackticks.length > MAX_PATH_CHARS ? `${withoutBackticks.slice(0, MAX_PATH_CHARS)}…` : withoutBackticks;
37
+ }
38
+ /**
39
+ * The host sentence for a run stopped because its changes touched a
40
+ * protected path. Named the file when `path` sanitises to something usable;
41
+ * otherwise falls back to a sentence that doesn't try to name it.
42
+ */
43
+ export function protectedPathSentence(path) {
44
+ const safe = path ? sanitizePath(path) : null;
45
+ const named = safe
46
+ ? `its changes include \`${safe}\`, which this agent may not edit`
47
+ : "its changes include a file this agent may not edit";
48
+ return `${named}, so none of its changes were kept. Ask again without changing that file, or have the repository owner make that change.`;
49
+ }
50
+ /**
51
+ * The fixed line for a mention status comment naming a failed protected_path
52
+ * sub-run (host-status.ts). That comment reads children from the database,
53
+ * which has no path -- only the category -- so this line never names a file.
54
+ */
55
+ export const PROTECTED_PATH_HOST_LINE = "A sub-run could not open its changes: it changed a file its agent may not edit, so none of its changes were kept.";
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Protected for every coding run, whatever an agent's own protectedPaths say
3
+ * (docs/coding-services.md): wardby's own configuration under .wardby/, except
4
+ * the service declaration, which any builder may propose in its pull request
5
+ * (it takes effect only after a person merges it, since dispatch reads it from
6
+ * the base branch). Part of DEFAULT_PROTECTED_PATHS so new agents show it, and
7
+ * always added by protectedPathMatcher (providers/vcs/git.ts) so agents created
8
+ * before it existed get it too. The matcher applies it ahead of the agent's own
9
+ * list: the declaration is never protected, and nothing else under .wardby/ can
10
+ * be unprotected by an agent's exceptions.
11
+ */
12
+ export declare const WARDBY_PROTECTED_PATHS: readonly [".wardby/**", "!.wardby/services.yaml"];
13
+ /**
14
+ * A leading "!" makes a protectedPaths entry an exception (providers/vcs/git.ts
15
+ * protectedPathMatcher): one literal file path carved out of the agent's own
16
+ * patterns. Exceptions take no wildcards, so "!**" or "!.github/**" cannot
17
+ * switch a whole protected tree off.
18
+ */
19
+ export declare const PROTECTED_PATH_EXCEPTION = "!";
20
+ export declare function isProtectedPathException(path: string): boolean;
21
+ /** The glob of a protectedPaths entry: the entry itself, or what follows an exception's leading "!". */
22
+ export declare function protectedPathBody(path: string): string;
23
+ /**
24
+ * Whether a trimmed protectedPaths entry has a valid shape: a repository-relative
25
+ * POSIX glob with no empty or traversal components, or, behind one leading "!",
26
+ * such a path with no glob metacharacters. Length and control-character bounds
27
+ * are the caller's.
28
+ */
29
+ export declare function isWellFormedProtectedPath(path: string): boolean;
30
+ /** Exceptions only carve paths out; a list of nothing but exceptions protects nothing. */
31
+ export declare function protectsSomePath(paths: readonly string[]): boolean;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Protected for every coding run, whatever an agent's own protectedPaths say
3
+ * (docs/coding-services.md): wardby's own configuration under .wardby/, except
4
+ * the service declaration, which any builder may propose in its pull request
5
+ * (it takes effect only after a person merges it, since dispatch reads it from
6
+ * the base branch). Part of DEFAULT_PROTECTED_PATHS so new agents show it, and
7
+ * always added by protectedPathMatcher (providers/vcs/git.ts) so agents created
8
+ * before it existed get it too. The matcher applies it ahead of the agent's own
9
+ * list: the declaration is never protected, and nothing else under .wardby/ can
10
+ * be unprotected by an agent's exceptions.
11
+ */
12
+ export const WARDBY_PROTECTED_PATHS = [".wardby/**", "!.wardby/services.yaml"];
13
+ /**
14
+ * A leading "!" makes a protectedPaths entry an exception (providers/vcs/git.ts
15
+ * protectedPathMatcher): one literal file path carved out of the agent's own
16
+ * patterns. Exceptions take no wildcards, so "!**" or "!.github/**" cannot
17
+ * switch a whole protected tree off.
18
+ */
19
+ export const PROTECTED_PATH_EXCEPTION = "!";
20
+ export function isProtectedPathException(path) {
21
+ return path.startsWith(PROTECTED_PATH_EXCEPTION);
22
+ }
23
+ /** The glob of a protectedPaths entry: the entry itself, or what follows an exception's leading "!". */
24
+ export function protectedPathBody(path) {
25
+ return isProtectedPathException(path) ? path.slice(PROTECTED_PATH_EXCEPTION.length) : path;
26
+ }
27
+ /** Glob metacharacters an exception may not contain: it names one literal file. */
28
+ const EXCEPTION_GLOB_CHARACTERS = /[*?[\]{}]/;
29
+ /**
30
+ * Whether a trimmed protectedPaths entry has a valid shape: a repository-relative
31
+ * POSIX glob with no empty or traversal components, or, behind one leading "!",
32
+ * such a path with no glob metacharacters. Length and control-character bounds
33
+ * are the caller's.
34
+ */
35
+ export function isWellFormedProtectedPath(path) {
36
+ const body = protectedPathBody(path);
37
+ return (body.length > 0 &&
38
+ !isProtectedPathException(body) &&
39
+ !(isProtectedPathException(path) && EXCEPTION_GLOB_CHARACTERS.test(body)) &&
40
+ !body.startsWith("/") &&
41
+ !body.startsWith("./") &&
42
+ !body.includes("\\") &&
43
+ !body.split("/").some((part) => part === "" || part === "." || part === ".."));
44
+ }
45
+ /** Exceptions only carve paths out; a list of nothing but exceptions protects nothing. */
46
+ export function protectsSomePath(paths) {
47
+ return paths.some((path) => !isProtectedPathException(path));
48
+ }
@@ -6,6 +6,18 @@ export declare const MAX_CODING_SUMMARY_BYTES: number;
6
6
  export declare const MAX_CODING_TESTS = 64;
7
7
  export declare const MAX_CODING_TEST_COMMAND_BYTES: number;
8
8
  export declare const MAX_TAG_BYTES = 32;
9
+ /**
10
+ * Coding-run services (docs/coding-services.md): the catalog name and version
11
+ * grammar, shared by the repository's .wardby/services.yaml, the catalog, and
12
+ * the worker input.
13
+ */
14
+ export declare const CODING_SERVICE_NAME: RegExp;
15
+ export declare const CODING_SERVICE_VERSION: RegExp;
16
+ export declare const MAX_CODING_SERVICES = 5;
17
+ /** A variable a service hands the agent's shells (DATABASE_URL, PGHOST, REDIS_URL, ...). */
18
+ export declare const CODING_SERVICE_ENV_NAME: RegExp;
19
+ export declare const MAX_CODING_SERVICE_ENV = 16;
20
+ export declare const MAX_CODING_SERVICE_ENV_VALUE_BYTES = 1024;
9
21
  /**
10
22
  * A worker's output-schema failure, reduced to where and how it failed, never
11
23
  * what the model wrote: `<path>:<zod issue code>`, where the path is dot-joined
@@ -14,6 +26,11 @@ export declare const MAX_TAG_BYTES = 32;
14
26
  */
15
27
  export declare const MAX_CODING_OUTPUT_ISSUES = 8;
16
28
  export declare const SAFE_CODING_OUTPUT_ISSUE: RegExp;
29
+ export declare const INVALID_SINGLE_LINE_CONTROL: RegExp;
30
+ export declare function byteLength(value: string): number;
31
+ export declare function isReservedServiceEnvName(name: string): boolean;
32
+ /** The variables one service hands the agent's shells: upper-case names wardby does not reserve. */
33
+ export declare const CodingServiceTestEnvSchema: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>, Record<string, string>, Record<string, string>>;
17
34
  export declare function normalizeGitHubRepository(value: string): string;
18
35
  export declare function normalizeGitRef(value: string): string;
19
36
  export declare const CodingBaseRefSchema: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
@@ -21,11 +38,12 @@ export declare const CodingTaskOverrideSchema: z.ZodEffects<z.ZodEffects<z.ZodEf
21
38
  /**
22
39
  * A coding worker receives only its task text, so a coding agent's own
23
40
  * instructions (its systemPrompt) travel inside that text, ahead of the
24
- * request. Blank instructions leave the task unchanged. The combination must
25
- * still fit MAX_CODING_TASK_BYTES; exceeding it is an error naming both parts
26
- * rather than a silent truncation of either.
41
+ * request, followed by any note wardby generates for the run (the services it
42
+ * started: src/coding/services/note.ts). Blank instructions and no note leave
43
+ * the task unchanged. The combination must still fit MAX_CODING_TASK_BYTES;
44
+ * exceeding it is an error naming both parts rather than a silent truncation.
27
45
  */
28
- export declare function composeCodingTask(instructions: string | null | undefined, task: string): string;
46
+ export declare function composeCodingTask(instructions: string | null | undefined, task: string, note?: string): string;
29
47
  /**
30
48
  * The tag only labels a pull request title, so a model's malformed tag must not
31
49
  * sink an otherwise finished run. A tag that already passes is kept as-is; any
@@ -35,6 +53,8 @@ export declare function composeCodingTask(instructions: string | null | undefine
35
53
  * re-validates whatever survives.
36
54
  */
37
55
  export declare function normalizeCodingTag(value: unknown): string | null | undefined;
56
+ /** Longest line a debug-traced worker writes to its log (src/coding-worker/debug-trace.ts). */
57
+ export declare const MAX_DEBUG_TRACE_LINE_BYTES: number;
38
58
  export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
39
59
  schemaVersion: z.ZodLiteral<1>;
40
60
  runId: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>;
@@ -60,6 +80,33 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
60
80
  }, {
61
81
  runId: string;
62
82
  }>>;
83
+ /**
84
+ * Admin-requested debug trace (CodingAgentProfile.debugTraceUntil): the
85
+ * worker writes its full stream trace to its own log. Absent means off;
86
+ * the control plane writes the key only when true, so an input for an
87
+ * untraced run is unchanged for workers that predate it.
88
+ */
89
+ debugTrace: z.ZodOptional<z.ZodBoolean>;
90
+ /**
91
+ * Coding-run services started next to this run (docs/coding-services.md):
92
+ * each one's catalog name and version, and the variables the agent's shells
93
+ * receive. Absent means none; the control plane writes the key only when a
94
+ * run has services, so every other input is unchanged for workers that
95
+ * predate it.
96
+ */
97
+ services: z.ZodOptional<z.ZodArray<z.ZodObject<{
98
+ name: z.ZodString;
99
+ version: z.ZodString;
100
+ testEnv: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>, Record<string, string>, Record<string, string>>;
101
+ }, "strict", z.ZodTypeAny, {
102
+ name: string;
103
+ version: string;
104
+ testEnv: Record<string, string>;
105
+ }, {
106
+ name: string;
107
+ version: string;
108
+ testEnv: Record<string, string>;
109
+ }>, "many">>;
63
110
  }, "strict", z.ZodTypeAny, {
64
111
  repository: string;
65
112
  schemaVersion: 1;
@@ -73,6 +120,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
73
120
  continuationOf?: {
74
121
  runId: string;
75
122
  } | undefined;
123
+ debugTrace?: boolean | undefined;
124
+ services?: {
125
+ name: string;
126
+ version: string;
127
+ testEnv: Record<string, string>;
128
+ }[] | undefined;
76
129
  }, {
77
130
  repository: string;
78
131
  schemaVersion: 1;
@@ -86,6 +139,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
86
139
  continuationOf?: {
87
140
  runId: string;
88
141
  } | undefined;
142
+ debugTrace?: boolean | undefined;
143
+ services?: {
144
+ name: string;
145
+ version: string;
146
+ testEnv: Record<string, string>;
147
+ }[] | undefined;
89
148
  }>, {
90
149
  repository: string;
91
150
  schemaVersion: 1;
@@ -99,6 +158,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
99
158
  continuationOf?: {
100
159
  runId: string;
101
160
  } | undefined;
161
+ debugTrace?: boolean | undefined;
162
+ services?: {
163
+ name: string;
164
+ version: string;
165
+ testEnv: Record<string, string>;
166
+ }[] | undefined;
102
167
  }, {
103
168
  repository: string;
104
169
  schemaVersion: 1;
@@ -112,6 +177,12 @@ export declare const CodingTaskInputSchema: z.ZodEffects<z.ZodObject<{
112
177
  continuationOf?: {
113
178
  runId: string;
114
179
  } | undefined;
180
+ debugTrace?: boolean | undefined;
181
+ services?: {
182
+ name: string;
183
+ version: string;
184
+ testEnv: Record<string, string>;
185
+ }[] | undefined;
115
186
  }>;
116
187
  export declare const CodingAgentOutputSchema: z.ZodEffects<z.ZodObject<{
117
188
  schemaVersion: z.ZodLiteral<1>;
@@ -6,6 +6,18 @@ export const MAX_CODING_SUMMARY_BYTES = 8 * 1024;
6
6
  export const MAX_CODING_TESTS = 64;
7
7
  export const MAX_CODING_TEST_COMMAND_BYTES = 2 * 1024;
8
8
  export const MAX_TAG_BYTES = 32;
9
+ /**
10
+ * Coding-run services (docs/coding-services.md): the catalog name and version
11
+ * grammar, shared by the repository's .wardby/services.yaml, the catalog, and
12
+ * the worker input.
13
+ */
14
+ export const CODING_SERVICE_NAME = /^[a-z][a-z0-9-]{0,39}$/;
15
+ export const CODING_SERVICE_VERSION = /^[0-9A-Za-z][0-9A-Za-z._-]{0,19}$/;
16
+ export const MAX_CODING_SERVICES = 5;
17
+ /** A variable a service hands the agent's shells (DATABASE_URL, PGHOST, REDIS_URL, ...). */
18
+ export const CODING_SERVICE_ENV_NAME = /^[A-Z][A-Z0-9_]{0,63}$/;
19
+ export const MAX_CODING_SERVICE_ENV = 16;
20
+ export const MAX_CODING_SERVICE_ENV_VALUE_BYTES = 1024;
9
21
  /**
10
22
  * A worker's output-schema failure, reduced to where and how it failed, never
11
23
  * what the model wrote: `<path>:<zod issue code>`, where the path is dot-joined
@@ -21,8 +33,8 @@ const MAX_RUN_ID_BYTES = 128;
21
33
  const MAX_COST_USD = 1_000_000;
22
34
  const MAX_JSON_NESTING_DEPTH = 64;
23
35
  const INVALID_MULTILINE_CONTROL = /[\u0000\u000B\u000C\u000E-\u001F\u007F]/;
24
- const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
25
- function byteLength(value) {
36
+ export const INVALID_SINGLE_LINE_CONTROL = /[\u0000-\u001F\u007F]/;
37
+ export function byteLength(value) {
26
38
  return Buffer.byteLength(value, "utf8");
27
39
  }
28
40
  function boundedText(maxBytes, singleLine = false) {
@@ -33,6 +45,72 @@ function boundedText(maxBytes, singleLine = false) {
33
45
  .refine((value) => !invalidControl.test(value), "must not contain control characters")
34
46
  .refine((value) => value.trim().length > 0, "must not be blank");
35
47
  }
48
+ /**
49
+ * Names the worker owns: its shell basics, anything that would redirect a
50
+ * process's loader or network proxy, and the registry proxy's and Wardby's own
51
+ * settings. No service may set one, whatever its catalog entry says.
52
+ */
53
+ const RESERVED_SERVICE_ENV_NAMES = new Set([
54
+ "HOME",
55
+ "LANG",
56
+ "LC_ALL",
57
+ "PATH",
58
+ "SHELL",
59
+ "TMPDIR",
60
+ "USER",
61
+ "LD_PRELOAD",
62
+ "LD_LIBRARY_PATH",
63
+ "NODE_OPTIONS",
64
+ "NODE_PATH",
65
+ "PYTHONPATH",
66
+ "PYTHONHOME",
67
+ "HTTP_PROXY",
68
+ "HTTPS_PROXY",
69
+ "NO_PROXY",
70
+ "ALL_PROXY",
71
+ "SSL_CERT_FILE",
72
+ "SSL_CERT_DIR",
73
+ ]);
74
+ const RESERVED_SERVICE_ENV_PREFIXES = [
75
+ "WARDBY_",
76
+ "CODEX_",
77
+ "OPENAI_",
78
+ "ANTHROPIC_",
79
+ "PIP_",
80
+ "NPM_CONFIG_",
81
+ "UV_",
82
+ "GIT_",
83
+ ];
84
+ export function isReservedServiceEnvName(name) {
85
+ return (RESERVED_SERVICE_ENV_NAMES.has(name) || RESERVED_SERVICE_ENV_PREFIXES.some((prefix) => name.startsWith(prefix)));
86
+ }
87
+ const serviceEnvValueSchema = z
88
+ .string()
89
+ .refine((value) => byteLength(value) <= MAX_CODING_SERVICE_ENV_VALUE_BYTES, `must be at most ${MAX_CODING_SERVICE_ENV_VALUE_BYTES} UTF-8 bytes`)
90
+ .refine((value) => !INVALID_SINGLE_LINE_CONTROL.test(value), "must not contain control characters");
91
+ /** The variables one service hands the agent's shells: upper-case names wardby does not reserve. */
92
+ export const CodingServiceTestEnvSchema = z.record(z.string(), serviceEnvValueSchema).superRefine((env, ctx) => {
93
+ const names = Object.keys(env);
94
+ if (names.length > MAX_CODING_SERVICE_ENV) {
95
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: `must have at most ${MAX_CODING_SERVICE_ENV} variables` });
96
+ }
97
+ for (const name of names) {
98
+ if (!CODING_SERVICE_ENV_NAME.test(name) || isReservedServiceEnvName(name)) {
99
+ ctx.addIssue({
100
+ code: z.ZodIssueCode.custom,
101
+ path: [name],
102
+ message: "must be an upper-case variable name wardby does not reserve",
103
+ });
104
+ }
105
+ }
106
+ });
107
+ const workerServiceSchema = z
108
+ .object({
109
+ name: z.string().regex(CODING_SERVICE_NAME),
110
+ version: z.string().regex(CODING_SERVICE_VERSION),
111
+ testEnv: CodingServiceTestEnvSchema,
112
+ })
113
+ .strict();
36
114
  function repositoryParts(value) {
37
115
  if (byteLength(value) > MAX_REPOSITORY_INPUT_BYTES || INVALID_SINGLE_LINE_CONTROL.test(value)) {
38
116
  throw new Error("invalid GitHub repository");
@@ -119,12 +197,13 @@ export const CodingTaskOverrideSchema = boundedText(MAX_CODING_TASK_BYTES);
119
197
  /**
120
198
  * A coding worker receives only its task text, so a coding agent's own
121
199
  * instructions (its systemPrompt) travel inside that text, ahead of the
122
- * request. Blank instructions leave the task unchanged. The combination must
123
- * still fit MAX_CODING_TASK_BYTES; exceeding it is an error naming both parts
124
- * rather than a silent truncation of either.
200
+ * request, followed by any note wardby generates for the run (the services it
201
+ * started: src/coding/services/note.ts). Blank instructions and no note leave
202
+ * the task unchanged. The combination must still fit MAX_CODING_TASK_BYTES;
203
+ * exceeding it is an error naming both parts rather than a silent truncation.
125
204
  */
126
- export function composeCodingTask(instructions, task) {
127
- const standing = instructions?.trim();
205
+ export function composeCodingTask(instructions, task, note) {
206
+ const standing = [instructions?.trim(), note?.trim()].filter((part) => Boolean(part)).join("\n\n");
128
207
  if (!standing)
129
208
  return task;
130
209
  const composed = `Standing instructions for this coding agent:\n${standing}\n\nRequest:\n${task}`;
@@ -186,6 +265,8 @@ const testResultSchema = z
186
265
  outcome: z.enum(["passed", "failed", "skipped"]),
187
266
  })
188
267
  .strict();
268
+ /** Longest line a debug-traced worker writes to its log (src/coding-worker/debug-trace.ts). */
269
+ export const MAX_DEBUG_TRACE_LINE_BYTES = 16 * 1024;
189
270
  export const CodingTaskInputSchema = z
190
271
  .object({
191
272
  schemaVersion: z.literal(CODING_PROTOCOL_VERSION),
@@ -206,6 +287,21 @@ export const CodingTaskInputSchema = z
206
287
  * only enforces that headRef is internally consistent with it.
207
288
  */
208
289
  continuationOf: z.object({ runId: runIdSchema }).strict().optional(),
290
+ /**
291
+ * Admin-requested debug trace (CodingAgentProfile.debugTraceUntil): the
292
+ * worker writes its full stream trace to its own log. Absent means off;
293
+ * the control plane writes the key only when true, so an input for an
294
+ * untraced run is unchanged for workers that predate it.
295
+ */
296
+ debugTrace: z.boolean().optional(),
297
+ /**
298
+ * Coding-run services started next to this run (docs/coding-services.md):
299
+ * each one's catalog name and version, and the variables the agent's shells
300
+ * receive. Absent means none; the control plane writes the key only when a
301
+ * run has services, so every other input is unchanged for workers that
302
+ * predate it.
303
+ */
304
+ services: z.array(workerServiceSchema).min(1).max(MAX_CODING_SERVICES).optional(),
209
305
  })
210
306
  .strict()
211
307
  .superRefine((value, ctx) => {
@@ -217,6 +313,10 @@ export const CodingTaskInputSchema = z
217
313
  message: "must match wardby/run-<runId> (or wardby/run-<continuationOf.runId>)",
218
314
  });
219
315
  }
316
+ const names = (value.services ?? []).map((service) => service.name);
317
+ if (new Set(names).size !== names.length) {
318
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["services"], message: "must name each service once" });
319
+ }
220
320
  });
221
321
  export const CodingAgentOutputSchema = z
222
322
  .object({
@@ -0,0 +1,2 @@
1
+ import type { EcosystemId, RegistryAdapter } from "./types.js";
2
+ export declare const REGISTRY_ADAPTERS: ReadonlyMap<EcosystemId, RegistryAdapter>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The registry adapter map: every ecosystem the coding package registry
3
+ * proxies, keyed by its EcosystemId. Adding a new ecosystem means adding it
4
+ * here (and to the allowlist/profile validation that reads this map) --
5
+ * nothing else in the registry core hardcodes "npm" or "pypi".
6
+ */
7
+ import { npmAdapter } from "./npm.js";
8
+ import { pypiAdapter } from "./pypi.js";
9
+ export const REGISTRY_ADAPTERS = new Map([npmAdapter, pypiAdapter].map((adapter) => [adapter.id, adapter]));
@@ -0,0 +1,9 @@
1
+ import type { AllowlistEntry, RegistryAdapter } from "./types.js";
2
+ export type PackageAllowlist = Readonly<Record<string, readonly string[]>>;
3
+ export interface PackagePolicy {
4
+ minReleaseAgeDays: number;
5
+ }
6
+ export declare const DEFAULT_MIN_RELEASE_AGE_DAYS = 3;
7
+ export declare function resolvePolicy(value: unknown): PackagePolicy;
8
+ export declare function parseAllowlist(allowlist: PackageAllowlist, adapters: ReadonlyMap<string, RegistryAdapter>): Map<string, AllowlistEntry[]>;
9
+ export declare function matchRoot(entries: readonly AllowlistEntry[], normalizedName: string): AllowlistEntry | undefined;