@wardby/cli 0.5.2 → 0.6.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 (411) hide show
  1. package/.env.example +33 -0
  2. package/README.md +25 -14
  3. package/dist/claude-coding-worker/context.d.ts +22 -0
  4. package/dist/claude-coding-worker/context.js +92 -0
  5. package/dist/claude-coding-worker/driver.d.ts +7 -1
  6. package/dist/claude-coding-worker/driver.js +38 -5
  7. package/dist/claude-coding-worker/sdk.js +13 -4
  8. package/dist/cli-help.d.ts +1 -1
  9. package/dist/cli-help.js +5 -2
  10. package/dist/cli-native-mode.d.ts +9 -0
  11. package/dist/cli-native-mode.js +20 -0
  12. package/dist/cli.d.ts +3 -1
  13. package/dist/cli.js +141 -5
  14. package/dist/coding/claude-context.d.ts +45 -0
  15. package/dist/coding/claude-context.js +434 -0
  16. package/dist/coding/local-git.js +9 -1
  17. package/dist/coding/profile.d.ts +12 -0
  18. package/dist/coding/profile.js +6 -0
  19. package/dist/coding/protocol.d.ts +104 -0
  20. package/dist/coding/protocol.js +87 -3
  21. package/dist/coding/registry/pypi.d.ts +25 -1
  22. package/dist/coding/registry/pypi.js +140 -16
  23. package/dist/coding/registry/types.d.ts +17 -3
  24. package/dist/coding-worker/artifact.d.ts +8 -0
  25. package/dist/coding-worker/artifact.js +2 -2
  26. package/dist/coding-worker/driver.js +2 -0
  27. package/dist/coding-worker/sdk.d.ts +6 -0
  28. package/dist/coding-worker/sdk.js +1 -0
  29. package/dist/coding-worker/skills.d.ts +23 -0
  30. package/dist/coding-worker/skills.js +117 -0
  31. package/dist/coding-worker/types.d.ts +2 -0
  32. package/dist/config/github-allowed-accounts.d.ts +15 -0
  33. package/dist/config/github-allowed-accounts.js +36 -0
  34. package/dist/config/low-power.d.ts +12 -0
  35. package/dist/config/low-power.js +18 -0
  36. package/dist/config/mobile.d.ts +12 -0
  37. package/dist/config/mobile.js +18 -0
  38. package/dist/config/providers.d.ts +56 -2
  39. package/dist/config/providers.js +92 -6
  40. package/dist/core/db.d.ts +16 -6
  41. package/dist/core/db.js +12 -10
  42. package/dist/core/dispatch.d.ts +11 -0
  43. package/dist/core/dispatch.js +36 -1
  44. package/dist/core/engine-native.js +9 -5
  45. package/dist/core/host-events.d.ts +49 -3
  46. package/dist/core/host-events.js +289 -15
  47. package/dist/core/http-runtime.js +13 -6
  48. package/dist/core/issue-bridge.js +42 -2
  49. package/dist/core/issue-events.js +12 -1
  50. package/dist/core/issue-status.js +14 -3
  51. package/dist/core/merge-order-check.d.ts +129 -0
  52. package/dist/core/merge-order-check.js +336 -0
  53. package/dist/core/notification-dispatcher.d.ts +70 -0
  54. package/dist/core/notification-dispatcher.js +368 -0
  55. package/dist/core/notification-templates.d.ts +25 -0
  56. package/dist/core/notification-templates.js +105 -0
  57. package/dist/core/notifications.d.ts +10 -0
  58. package/dist/core/notifications.js +38 -0
  59. package/dist/core/pg-auth.d.ts +22 -0
  60. package/dist/core/pg-auth.js +152 -0
  61. package/dist/core/power-composition.d.ts +16 -0
  62. package/dist/core/power-composition.js +37 -0
  63. package/dist/core/power-idle.d.ts +14 -0
  64. package/dist/core/power-idle.js +30 -0
  65. package/dist/core/power.d.ts +71 -0
  66. package/dist/core/power.js +202 -0
  67. package/dist/core/reconciler.d.ts +4 -2
  68. package/dist/core/reconciler.js +29 -5
  69. package/dist/core/related-pull-requests.d.ts +48 -4
  70. package/dist/core/related-pull-requests.js +113 -11
  71. package/dist/core/repo-access.d.ts +15 -0
  72. package/dist/core/repo-access.js +66 -0
  73. package/dist/core/review-fix.d.ts +37 -0
  74. package/dist/core/review-fix.js +207 -6
  75. package/dist/core/review-host-tools.d.ts +20 -0
  76. package/dist/core/review-host-tools.js +58 -2
  77. package/dist/core/runner.d.ts +336 -3
  78. package/dist/core/runner.js +894 -317
  79. package/dist/core/secret-broker-config.d.ts +103 -0
  80. package/dist/core/secret-broker-config.js +112 -0
  81. package/dist/core/secrets.d.ts +39 -4
  82. package/dist/core/secrets.js +148 -40
  83. package/dist/core/workflow-event-recorder.d.ts +14 -0
  84. package/dist/core/workflow-event-recorder.js +120 -0
  85. package/dist/core/workflow-events.d.ts +82 -0
  86. package/dist/core/workflow-events.js +44 -0
  87. package/dist/core/workflow-run-events.d.ts +16 -0
  88. package/dist/core/workflow-run-events.js +40 -0
  89. package/dist/generated/prisma/browser.d.ts +58 -0
  90. package/dist/generated/prisma/client.d.ts +58 -0
  91. package/dist/generated/prisma/commonInputTypes.d.ts +150 -0
  92. package/dist/generated/prisma/enums.d.ts +27 -0
  93. package/dist/generated/prisma/enums.js +23 -0
  94. package/dist/generated/prisma/internal/class.d.ts +88 -0
  95. package/dist/generated/prisma/internal/class.js +4 -4
  96. package/dist/generated/prisma/internal/prismaNamespace.d.ts +772 -1
  97. package/dist/generated/prisma/internal/prismaNamespace.js +135 -4
  98. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +139 -0
  99. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -4
  100. package/dist/generated/prisma/models/Agent.d.ts +360 -1
  101. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +73 -1
  102. package/dist/generated/prisma/models/CodingRun.d.ts +205 -1
  103. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  104. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1675 -0
  105. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  106. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1517 -0
  107. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  108. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  109. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  110. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  111. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  112. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  113. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  114. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  115. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  116. package/dist/generated/prisma/models/Run.d.ts +826 -1
  117. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  118. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  119. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  120. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  121. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  122. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  123. package/dist/generated/prisma/models.d.ts +8 -0
  124. package/dist/help/build.js +4 -2
  125. package/dist/help/catalog.d.ts +1 -1
  126. package/dist/help/catalog.js +31 -6
  127. package/dist/help-index.json +1492 -113
  128. package/dist/import/create.js +17 -0
  129. package/dist/import/neutral-schema.d.ts +6 -2
  130. package/dist/import/neutral-schema.js +2 -0
  131. package/dist/mcp/auth/access.d.ts +1 -0
  132. package/dist/mcp/auth/ownership.d.ts +1 -1
  133. package/dist/mcp/auth/repo-authorization.js +14 -0
  134. package/dist/mcp/auth/resource-server.d.ts +2 -1
  135. package/dist/mcp/auth/resource-server.js +7 -2
  136. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  137. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  138. package/dist/mcp/context.d.ts +6 -0
  139. package/dist/mcp/host-events/github-ingress.d.ts +23 -1
  140. package/dist/mcp/host-events/github-ingress.js +68 -0
  141. package/dist/mcp/index.d.ts +13 -0
  142. package/dist/mcp/index.js +59 -10
  143. package/dist/mcp/tools/agents.js +83 -12
  144. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  145. package/dist/mcp/tools/notification-channels.js +293 -0
  146. package/dist/mcp/tools/power.d.ts +2 -0
  147. package/dist/mcp/tools/power.js +77 -0
  148. package/dist/mcp/tools/runs.d.ts +0 -6
  149. package/dist/mcp/tools/runs.js +7 -2
  150. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  151. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  152. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  153. package/dist/mcp/tools/secret-elicitation-form.js +200 -10
  154. package/dist/mcp/tools/secret-elicitation-server.js +8 -1
  155. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  156. package/dist/mcp/tools/secret-elicitation.js +110 -12
  157. package/dist/mcp/tools/secrets.js +184 -7
  158. package/dist/mcp/tools/tools.d.ts +1 -1
  159. package/dist/mcp/tools/tools.js +22 -2
  160. package/dist/native-worker/composition.d.ts +23 -0
  161. package/dist/native-worker/composition.js +77 -0
  162. package/dist/native-worker/docker-isolation.d.ts +65 -0
  163. package/dist/native-worker/docker-isolation.js +183 -0
  164. package/dist/native-worker/docker-launcher.d.ts +74 -0
  165. package/dist/native-worker/docker-launcher.js +237 -0
  166. package/dist/native-worker/gateway-server.d.ts +39 -0
  167. package/dist/native-worker/gateway-server.js +315 -0
  168. package/dist/native-worker/gateway.d.ts +44 -0
  169. package/dist/native-worker/gateway.js +197 -0
  170. package/dist/native-worker/http-server.d.ts +22 -0
  171. package/dist/native-worker/http-server.js +109 -0
  172. package/dist/native-worker/http-transport.d.ts +17 -0
  173. package/dist/native-worker/http-transport.js +88 -0
  174. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  175. package/dist/native-worker/kubernetes-isolation.js +218 -0
  176. package/dist/native-worker/kubernetes-launcher.d.ts +102 -0
  177. package/dist/native-worker/kubernetes-launcher.js +335 -0
  178. package/dist/native-worker/launch.d.ts +45 -0
  179. package/dist/native-worker/launch.js +44 -0
  180. package/dist/native-worker/ledger.d.ts +109 -0
  181. package/dist/native-worker/ledger.js +192 -0
  182. package/dist/native-worker/loopback.d.ts +12 -0
  183. package/dist/native-worker/loopback.js +49 -0
  184. package/dist/native-worker/main.d.ts +7 -0
  185. package/dist/native-worker/main.js +74 -0
  186. package/dist/native-worker/protocol.d.ts +744 -0
  187. package/dist/native-worker/protocol.js +200 -0
  188. package/dist/native-worker/sandbox-executor.d.ts +68 -0
  189. package/dist/native-worker/sandbox-executor.js +210 -0
  190. package/dist/native-worker/stdio.d.ts +29 -0
  191. package/dist/native-worker/stdio.js +188 -0
  192. package/dist/native-worker/warm-delivery.d.ts +16 -0
  193. package/dist/native-worker/warm-delivery.js +33 -0
  194. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  195. package/dist/native-worker/warm-pool-ledger.js +73 -0
  196. package/dist/native-worker/warm-pool.d.ts +107 -0
  197. package/dist/native-worker/warm-pool.js +283 -0
  198. package/dist/native-worker/worker.d.ts +17 -0
  199. package/dist/native-worker/worker.js +115 -0
  200. package/dist/providers/auth/authorization-server.d.ts +3 -0
  201. package/dist/providers/auth/index.js +2 -0
  202. package/dist/providers/auth/self-hosted.d.ts +13 -1
  203. package/dist/providers/auth/self-hosted.js +54 -4
  204. package/dist/providers/chat/fake.d.ts +46 -0
  205. package/dist/providers/chat/fake.js +39 -0
  206. package/dist/providers/chat/index.d.ts +4 -0
  207. package/dist/providers/chat/index.js +8 -0
  208. package/dist/providers/chat/slack.d.ts +37 -0
  209. package/dist/providers/chat/slack.js +105 -0
  210. package/dist/providers/chat/types.d.ts +42 -0
  211. package/dist/providers/chat/types.js +19 -0
  212. package/dist/providers/coding-proxy/mock-upstream.d.ts +33 -0
  213. package/dist/providers/coding-proxy/mock-upstream.js +116 -0
  214. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +3 -0
  215. package/dist/providers/coding-proxy/registry/prisma-store.js +17 -0
  216. package/dist/providers/coding-proxy/registry/service.d.ts +4 -0
  217. package/dist/providers/coding-proxy/registry/service.js +20 -3
  218. package/dist/providers/coding-proxy/registry/store.d.ts +18 -1
  219. package/dist/providers/coding-proxy/registry/store.js +33 -0
  220. package/dist/providers/coding-proxy/runtime.js +12 -1
  221. package/dist/providers/coding-proxy/types.d.ts +2 -0
  222. package/dist/providers/engine/types.d.ts +19 -0
  223. package/dist/providers/engine/types.js +22 -0
  224. package/dist/providers/executor/composition.d.ts +24 -1
  225. package/dist/providers/executor/composition.js +39 -6
  226. package/dist/providers/executor/container.d.ts +24 -1
  227. package/dist/providers/executor/container.js +101 -11
  228. package/dist/providers/executor/dbos.d.ts +42 -0
  229. package/dist/providers/executor/dbos.js +118 -12
  230. package/dist/providers/executor/deferred.d.ts +56 -0
  231. package/dist/providers/executor/deferred.js +119 -0
  232. package/dist/providers/executor/routing.d.ts +37 -10
  233. package/dist/providers/executor/routing.js +73 -32
  234. package/dist/providers/executor/types.d.ts +12 -0
  235. package/dist/providers/jobs/docker.js +3 -3
  236. package/dist/providers/jobs/fake-kubernetes-api.d.ts +21 -2
  237. package/dist/providers/jobs/fake-kubernetes-api.js +42 -1
  238. package/dist/providers/jobs/kubernetes-api.d.ts +17 -1
  239. package/dist/providers/jobs/kubernetes-api.js +7 -0
  240. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  241. package/dist/providers/jobs/kubernetes-client.js +52 -3
  242. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  243. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  244. package/dist/providers/jobs/kubernetes-isolation.d.ts +16 -1
  245. package/dist/providers/jobs/kubernetes-isolation.js +58 -5
  246. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  247. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  248. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  249. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  250. package/dist/providers/jobs/kubernetes.d.ts +56 -7
  251. package/dist/providers/jobs/kubernetes.js +117 -36
  252. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  253. package/dist/providers/jobs/metadata-probes.js +13 -0
  254. package/dist/providers/jobs/types.d.ts +9 -0
  255. package/dist/providers/llm/openai.js +0 -1
  256. package/dist/providers/review-host/github.d.ts +11 -1
  257. package/dist/providers/review-host/github.js +50 -0
  258. package/dist/providers/review-host/types.d.ts +23 -0
  259. package/dist/providers/vcs/github.d.ts +32 -6
  260. package/dist/providers/vcs/github.js +74 -16
  261. package/dist/quickstart/coding-db.js +14 -2
  262. package/dist/quickstart/coding-doctor.d.ts +3 -0
  263. package/dist/quickstart/coding-doctor.js +3 -0
  264. package/dist/quickstart/coding-images.d.ts +9 -0
  265. package/dist/quickstart/coding-images.js +39 -0
  266. package/dist/quickstart/coding-seed.d.ts +20 -1
  267. package/dist/quickstart/coding-seed.js +96 -7
  268. package/dist/quickstart/coding.d.ts +2 -0
  269. package/dist/quickstart/coding.js +75 -3
  270. package/dist/quickstart/config.d.ts +2 -0
  271. package/dist/quickstart/config.js +4 -0
  272. package/dist/quickstart/images.d.ts +13 -0
  273. package/dist/quickstart/images.js +80 -12
  274. package/dist/quickstart/index.d.ts +0 -2
  275. package/dist/quickstart/index.js +10 -14
  276. package/dist/quickstart/manifests.d.ts +56 -0
  277. package/dist/quickstart/manifests.js +523 -0
  278. package/dist/quickstart/python-detect.d.ts +10 -0
  279. package/dist/quickstart/python-detect.js +32 -0
  280. package/dist/quickstart/repo-packages.d.ts +10 -0
  281. package/dist/quickstart/repo-packages.js +132 -0
  282. package/dist/quickstart/reviewer-prompt.d.ts +12 -0
  283. package/dist/quickstart/reviewer-prompt.js +84 -0
  284. package/dist/quickstart/scenarios.d.ts +19 -0
  285. package/dist/quickstart/scenarios.js +28 -0
  286. package/dist/quickstart/sync-reviewer-prompt.d.ts +1 -0
  287. package/dist/quickstart/sync-reviewer-prompt.js +10 -0
  288. package/dist/quickstart-images.json +1 -1
  289. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  290. package/dist/sandbox/brokered-fetch.js +37 -0
  291. package/dist/sandbox/host-functions.d.ts +34 -0
  292. package/dist/sandbox/host-functions.js +144 -80
  293. package/dist/sandbox/prelude.js +7 -1
  294. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  295. package/dist/sandbox/run-in-sandbox.js +28 -10
  296. package/dist/sandbox/safe-fetch.d.ts +2 -0
  297. package/dist/sandbox/safe-fetch.js +3 -1
  298. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  299. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  300. package/dist/sandbox/secret-broker.d.ts +34 -0
  301. package/dist/sandbox/secret-broker.js +162 -0
  302. package/dist/sandbox/user-tool.d.ts +14 -0
  303. package/dist/sandbox/user-tool.js +32 -0
  304. package/dist/serve.js +18 -0
  305. package/dist/viewer/api-schema.d.ts +214 -18
  306. package/dist/viewer/api-schema.js +22 -0
  307. package/dist/viewer/build-schemas.js +4 -1
  308. package/dist/viewer/event-bus.d.ts +6 -0
  309. package/dist/viewer/event-bus.js +16 -7
  310. package/dist/viewer/graph.d.ts +5 -2
  311. package/dist/viewer/graph.js +7 -2
  312. package/dist/viewer/http.d.ts +0 -1
  313. package/dist/viewer/http.js +2 -2
  314. package/dist/viewer/infra.js +25 -2
  315. package/dist/viewer/limits.d.ts +4 -0
  316. package/dist/viewer/limits.js +4 -0
  317. package/dist/viewer/openapi.d.ts +15 -0
  318. package/dist/viewer/openapi.js +172 -0
  319. package/docs/README.md +7 -0
  320. package/docs/agent-recipes.md +57 -8
  321. package/docs/architecture-runtime.md +16 -1
  322. package/docs/code-review-agents.md +139 -5
  323. package/docs/coding-agent-setup.md +127 -2
  324. package/docs/coding-packages.md +105 -5
  325. package/docs/coding-services.md +3 -1
  326. package/docs/coding-worker-byo-images.md +239 -2
  327. package/docs/coding-worker-isolation.md +88 -23
  328. package/docs/getting-started-gke.md +225 -9
  329. package/docs/getting-started-identity-provider.md +21 -10
  330. package/docs/getting-started.md +140 -11
  331. package/docs/jira-agents.md +5 -1
  332. package/docs/knowledge.md +11 -0
  333. package/docs/native-sandbox.md +635 -0
  334. package/docs/release-verification.md +9 -0
  335. package/docs/security-deployment.md +113 -12
  336. package/docs/slack-notifications.md +252 -0
  337. package/docs/tool-secrets.md +252 -0
  338. package/docs/viewer-api.md +46 -5
  339. package/docs/viewer-api.openapi.yml +1404 -0
  340. package/help/admin-viewer.md +6 -2
  341. package/help/agent-recipes.md +27 -0
  342. package/help/architecture-agent.md +136 -0
  343. package/help/brokered-secrets.md +79 -0
  344. package/help/build-claude-code-image.md +131 -0
  345. package/help/build-worker-image.md +195 -0
  346. package/help/code-review-agents.md +68 -6
  347. package/help/coding-packages.md +31 -2
  348. package/help/creating-agents.md +14 -0
  349. package/help/deploy-gke.md +37 -6
  350. package/help/deployment-targets.md +24 -13
  351. package/help/errors/coding-provider-not-configured.md +2 -2
  352. package/help/errors/database-auth-invalid.md +28 -0
  353. package/help/errors/github-account-not-allowed.md +25 -0
  354. package/help/errors/low-power-disabled.md +29 -0
  355. package/help/errors/low-power-scale-forbidden.md +35 -0
  356. package/help/errors/low-power-wake-timeout.md +30 -0
  357. package/help/errors/mobile-disabled.md +31 -0
  358. package/help/errors/native-sandbox-capacity.md +22 -0
  359. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  360. package/help/errors/native-sandbox-docker-failed.md +20 -0
  361. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  362. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  363. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  364. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  365. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  366. package/help/errors/native-sandbox-unavailable.md +19 -0
  367. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  368. package/help/errors/native-sandbox-worker-exited.md +20 -0
  369. package/help/errors/native-sandbox-worker-lost.md +20 -0
  370. package/help/errors/native-sandbox-worker-unready.md +22 -0
  371. package/help/errors/secret-broker-body-invalid.md +26 -0
  372. package/help/errors/secret-broker-changed.md +20 -0
  373. package/help/errors/secret-broker-config-invalid.md +30 -0
  374. package/help/errors/secret-broker-conflict.md +27 -0
  375. package/help/errors/secret-broker-destination-denied.md +28 -0
  376. package/help/errors/secret-broker-value-invalid.md +28 -0
  377. package/help/errors/secret-brokered.md +24 -0
  378. package/help/errors/secret-not-brokered.md +25 -0
  379. package/help/errors/slack-auth-failed.md +48 -0
  380. package/help/errors/slack-channel-unreachable.md +39 -0
  381. package/help/errors/slack-not-configured.md +33 -0
  382. package/help/getting-started.md +18 -0
  383. package/help/github.md +18 -1
  384. package/help/identity-and-access.md +5 -1
  385. package/help/local-repositories.md +35 -5
  386. package/help/low-power-mode.md +125 -0
  387. package/help/merge-order-check.md +117 -0
  388. package/help/mobile-app.md +54 -0
  389. package/help/native-sandbox.md +136 -0
  390. package/help/observability.md +8 -0
  391. package/help/related-pull-requests.md +70 -9
  392. package/help/repo-instructions-and-skills.md +91 -0
  393. package/help/review-fix-rounds.md +10 -0
  394. package/help/slack-notifications.md +62 -0
  395. package/help/troubleshooting/coding-workers.md +21 -0
  396. package/package.json +13 -5
  397. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  398. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  399. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  400. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  401. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  402. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  403. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  404. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  405. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  406. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  407. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  408. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  409. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  410. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  411. package/prisma/schema.prisma +362 -91
@@ -3,6 +3,9 @@
3
3
  This is the supported Google Cloud deployment path for Wardby. It creates a
4
4
  GKE Autopilot cluster, Artifact Registry, private-IP Cloud SQL for PostgreSQL,
5
5
  isolated coding workers, an HTTPS Gateway, and the Wardby control plane.
6
+ Before accepting production work, complete the
7
+ [release verification](release-verification.md) and
8
+ [security deployment](security-deployment.md) checks.
6
9
 
7
10
  The older `deploy/gcp` Cloud Run module is deprecated. New deployments should
8
11
  use `deploy/gke` and the `gke-autopilot` Kubernetes overlay described here.
@@ -14,7 +17,10 @@ use `deploy/gke` and the `gke-autopilot` Kubernetes overlay described here.
14
17
  ## Architecture
15
18
 
16
19
  - The Wardby control plane and coding proxy run in GKE Autopilot.
17
- - Each Codex coding run uses an ephemeral gVisor-backed pod.
20
+ - Each Codex or Claude Code coding run uses an ephemeral gVisor-backed pod;
21
+ Claude Code adds a tool-runner sidecar in that pod.
22
+ - Native agents set to sandbox mode run in single-use gVisor pods behind the
23
+ native gateway (see "Native sandbox" below).
18
24
  - Cloud SQL PostgreSQL has no public IP and is reached through private services
19
25
  access on the cluster's VPC.
20
26
  - Runtime, migration, and worker images are stored in Artifact Registry and
@@ -176,6 +182,34 @@ seeded: add it to the control plane's `env` in
176
182
  `deploy/kind-coding/manifests/overlays/gke-autopilot/control-plane.yaml` if you
177
183
  need it.
178
184
 
185
+ To post [workflow notifications to Slack](slack-notifications.md), also add the
186
+ Slack app's bot token. This requires Wardby 0.6.0 or later. It is optional:
187
+
188
+ ```dotenv
189
+ WARDBY_SLACK_BOT_TOKEN="xoxb-..."
190
+ ```
191
+
192
+ When it is in Secret Manager, `up.sh` syncs it into a separate Secret,
193
+ `wardby-slack-env`, that only the control plane reads; when it is not, it
194
+ leaves that Secret out and Slack stays off. `WARDBY_SLACK_CUSTOMIZE` and
195
+ `WARDBY_SLACK_API_BASE_URL` are not secrets and are not seeded: add them to the
196
+ control plane's `env` in the same `control-plane.yaml` if you need them. If you
197
+ later remove the bot token, remove these two entries too: the control plane
198
+ refuses to start with either one set and no token.
199
+
200
+ `WARDBY_GITHUB_ALLOWED_ACCOUNTS` (optional, not a secret) adds GitHub accounts
201
+ the App serves besides its owner. Pass it to `up.sh` on every run, for example
202
+ `WARDBY_GITHUB_ALLOWED_ACCOUNTS=acme-labs WARDBY_HOSTNAME=app.example.com deploy/gke/up.sh`;
203
+ a run without it serves only the App's owner. See
204
+ [Which accounts the App serves](code-review-agents.md#which-accounts-the-app-serves-wardby_github_allowed_accounts).
205
+
206
+ `WARDBY_MOBILE_ENABLED=true` (optional, not a secret) lets the Wardby mobile app
207
+ sign in to the self-hosted OAuth server. Pass it to `up.sh` on every run, the
208
+ same way as `WARDBY_GITHUB_ALLOWED_ACCOUNTS`; a run without it turns mobile
209
+ sign-in off. It works for normal and low-power deploys. White-label builds that
210
+ use their own redirect URI add `WARDBY_MOBILE_REDIRECT_URI` to the control
211
+ plane's `env` themselves. See the help article `mobile-app`.
212
+
179
213
  Generate `SECRET_APP_KEY` with:
180
214
 
181
215
  ```sh
@@ -189,6 +223,13 @@ on. A value already in Secret Manager is never overwritten, so after the first
189
223
  deployment Secret Manager is the source of truth. You can then remove the
190
224
  production values from `.env.local`.
191
225
 
226
+ External Secrets Operator runs as three small pods in the `external-secrets`
227
+ namespace. `deploy/gke/eso-values.yaml` requests 100m CPU and 256 MiB of
228
+ memory for each (memory limited to the same), because Autopilot bills a pod
229
+ that requests nothing at 500m CPU and 2 GiB. If one is ever restarted for
230
+ exceeding its memory limit, raise the limit and request together in that file
231
+ and re-run `up.sh`; the Secrets it already synced are unaffected.
232
+
192
233
  Redeploying onto a cluster that already runs Wardby carries its existing
193
234
  `SECRET_APP_KEY` and login signing keys over, so stored credentials still
194
235
  decrypt and nobody has to sign in again.
@@ -249,9 +290,20 @@ The deployment script is idempotent. It converges Terraform, builds and pushes
249
290
  renders the GKE overlay, and waits for the proxy and control plane:
250
291
 
251
292
  ```sh
252
- HOSTNAME=wardby.example.com deploy/gke/up.sh
293
+ WARDBY_HOSTNAME=wardby.example.com deploy/gke/up.sh
253
294
  ```
254
295
 
296
+ Set `WARDBY_HOSTNAME`, not `HOSTNAME`: shells set `HOSTNAME` to the machine's own
297
+ name, so the script no longer reads it. It refuses a hostname with no dot, or a
298
+ local name such as `*.lan`, `*.local`, or `*.internal`. If you deployed with an
299
+ earlier version using `HOSTNAME=...`, pass the same value as `WARDBY_HOSTNAME`.
300
+
301
+ If the cluster is already published on a different hostname, the script stops
302
+ before building anything: moving the hostname breaks DNS, every client's
303
+ configured endpoint, and every issued token. In a terminal it asks you to type
304
+ the new hostname; elsewhere, set `WARDBY_HOSTNAME_CHANGE` to the new hostname to
305
+ confirm the move.
306
+
255
307
  Point the hostname's public A record at the reserved address:
256
308
 
257
309
  ```sh
@@ -275,11 +327,12 @@ through the Cloud SQL Auth Proxy, via Workload Identity from one Kubernetes
275
327
  service account. What each may do inside the database comes from a `NOLOGIN`
276
328
  group role in `deploy/gke/database-grants.sql`:
277
329
 
278
- | Workload | Google service account | Kubernetes service account | May do |
279
- | ------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
280
- | Control plane | `<name_prefix>-app` | `wardby-control-plane` | `wardby_app`: read/write every table, including the durable executor's in schema `dbos`; never change a schema |
281
- | Coding proxy | `<name_prefix>-proxy` | `wardby-coding-proxy` | `wardby_proxy`: only its budget ledger — `CodingProxySession`/`CodingProxyRequest`/`RunModelUsage`, plus update `tokensIn`, `tokensOut`, `costUsd` and `turns` on `Run`, and read only its `id` |
282
- | Migrations | `<name_prefix>-migrator` | `wardby-migrator` | Acts as the table owner (`SET ROLE`), so `prisma migrate deploy` and `dbos schema` can alter and create tables |
330
+ | Workload | Google service account | Kubernetes service account | May do |
331
+ | -------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | Control plane | `<name_prefix>-app` | `wardby-control-plane` | `wardby_app`: read/write every table, including the durable executor's in schema `dbos`; never change a schema |
333
+ | Coding proxy | `<name_prefix>-proxy` | `wardby-coding-proxy` | `wardby_proxy`: only its budget ledger — `CodingProxySession`/`CodingProxyRequest`/`RunModelUsage`, plus update `tokensIn`, `tokensOut`, `costUsd` and `turns` on `Run`, and read only its `id` |
334
+ | Native gateway | `<name_prefix>-gateway` | `wardby-native-gateway` | Member of `wardby_app`: the same data access as the control plane, under its own login (see [Native sandbox](#native-sandbox)) |
335
+ | Migrations | `<name_prefix>-migrator` | `wardby-migrator` | Acts as the table owner (`SET ROLE`), so `prisma migrate deploy` and `dbos schema` can alter and create tables |
283
336
 
284
337
  `deploy/gke/bootstrap-database-iam.sh` applies the grants as the built-in
285
338
  owner, from a short-lived Job inside the cluster. Run it whenever
@@ -296,10 +349,16 @@ SQL Admin API, uses that password once to apply the grants, and resets it to
296
349
  a value nobody holds on every exit, including a failed grant. No password is
297
350
  ever stored, printed, or passed as a process argument.
298
351
 
352
+ A deployment that already runs and then gains the native gateway identity from
353
+ `terraform apply` runs `deploy/gke/bootstrap-database-iam.sh` once, so the
354
+ gateway's user gets its `wardby_app` membership, and then `deploy/gke/up.sh`.
355
+ `up.sh`'s database check also tests the native gateway and says so if the
356
+ grant is missing.
357
+
299
358
  A brand-new project runs, in this order:
300
359
 
301
360
  1. `terraform -chdir=deploy/gke apply` — creates the cluster, the instance
302
- and the three IAM database users. Run it yourself rather than through
361
+ and the four IAM database users. Run it yourself rather than through
303
362
  `up.sh`, which would go on to the migrations before the migrator has its
304
363
  grants.
305
364
  2. `deploy/gke/bootstrap-database-iam.sh` (default mode) — fetches the
@@ -568,6 +627,160 @@ it, set `replicas: 0` in
568
627
  A PriorityClass's value and preemption policy cannot be changed in place:
569
628
  delete the class and re-run `up.sh` to change them.
570
629
 
630
+ ### Native sandbox
631
+
632
+ Native sandbox requires Wardby 0.5.4 or later.
633
+
634
+ `up.sh` deploys everything the [native sandbox](native-sandbox.md) needs on
635
+ this cluster. It builds and pushes the `native-worker` image, checks it (Node is
636
+ present; `curl`, `wget`, `nc` and `ssh` are not), and pins it by digest as
637
+ `NATIVE_SANDBOX_WORKER_IMAGE`. It syncs the gateway's ExternalSecret, rolls out
638
+ `wardby-native-gateway`, waits for it, and checks its database round trip. The
639
+ control plane is configured with `NATIVE_SANDBOX_LAUNCHER=kubernetes`,
640
+ `NATIVE_SANDBOX_CPUS=0.5`, `NATIVE_SANDBOX_MEMORY_MB=512`,
641
+ `NATIVE_SANDBOX_MAX_CONCURRENT=4`, `NATIVE_SANDBOX_READY_TIMEOUT_MS=600000`
642
+ (a cold gVisor node takes about two minutes), and
643
+ `NATIVE_SANDBOX_ENFORCEMENT_TIMEOUT_MS=60000`. Worker pods use the gVisor runtime
644
+ class, `KUBERNETES_PLATFORM=gke-autopilot`, and the run priority class.
645
+
646
+ - **One-time bootstrap.** The gateway has its own database login. After
647
+ `terraform apply` adds its identity to an existing deployment, run
648
+ `deploy/gke/bootstrap-database-iam.sh` once, then `deploy/gke/up.sh`; see
649
+ [Database login](#database-login).
650
+ - **Enable per agent.** Nothing runs in the sandbox until you opt an agent in:
651
+ set its `nativeExecutionMode` to `sandbox` with the `update_agent` MCP tool
652
+ (native agents only).
653
+ - **Capacity.** At most `NATIVE_SANDBOX_MAX_CONCURRENT` sandbox runs are active
654
+ at once; a start past that fails with `native_sandbox_capacity` rather than
655
+ queuing. The `wardby-coding` ResourceQuota (26 pods, 11 CPU, 20Gi memory)
656
+ already covers the gateway's two replicas and that many 500m / 512Mi worker
657
+ pods. Raise the quota together with `NATIVE_SANDBOX_MAX_CONCURRENT` or
658
+ `CODING_MAX_CONCURRENT`.
659
+ - **Warm pool.** To keep idle, already-isolated workers ready so runs skip pod
660
+ scheduling and the isolation probe, set `NATIVE_SANDBOX_WARM_POOL_SIZE` (0 to
661
+ 50, default 0) in the control-plane manifest and raise the `wardby-coding`
662
+ ResourceQuota by that many 500m / 512Mi pods. Each idle worker is billed
663
+ continuously. See [Warm pool](native-sandbox.md#warm-pool).
664
+ - **Check isolation.** `npm run test:native-cluster` runs launcher-only
665
+ isolation checks against the deployed gateway; set `NATIVE_TEST_WORKER_IMAGE`
666
+ to the worker digest and `NATIVE_TEST_FORBIDDEN` to the database's private
667
+ `host:port` (for example `10.0.0.5:3307`).
668
+ - **Roll back.** Set an agent back to `control-plane` with `update_agent`; this
669
+ affects only new runs, and runs already started in sandbox mode finish there.
670
+ To undo a bad gateway release, run
671
+ `kubectl -n wardby-coding rollout undo deploy/wardby-native-gateway`.
672
+
673
+ ### Low-power mode
674
+
675
+ Low-power mode requires Wardby 0.6.0 or later.
676
+
677
+ Low-power mode cuts the idle cost of a deployment that runs agents only now and
678
+ then. The coding proxy and the native gateway scale to zero replicas when
679
+ nothing needs them, and wake on demand; the headroom placeholder is turned off;
680
+ and the control plane runs 1 copy, scaling to 2 under load. The database and
681
+ edge are unchanged.
682
+
683
+ Turn it on by deploying with the flag:
684
+
685
+ ```sh
686
+ WARDBY_HOSTNAME=wardby.example.com WARDBY_LOW_POWER=1 deploy/gke/up.sh
687
+ ```
688
+
689
+ To turn it off, re-run `up.sh` without the flag. That removes the autoscaler
690
+ (HorizontalPodAutoscaler `wardby-control-plane`) and the Role and RoleBinding
691
+ `wardby-power`, and restores the normal sizes: proxy 1, gateway 2, headroom 1,
692
+ control plane 1.
693
+
694
+ | Variable | Where it is set | Values | Meaning |
695
+ | ------------------------ | ---------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
696
+ | `WARDBY_LOW_POWER` | `up.sh` environment; control plane | unset, `0` (off) or `1` (on) | Anything else fails `up.sh` and stops the control plane at start-up. Needs `JOB_LAUNCHER=kubernetes`, else it logs `low_power_ignored` and does nothing. |
697
+ | `LOW_POWER_IDLE_MINUTES` | Control-plane Deployment | integer 5 to 1440, default `30` | How long a target must be unused before it sleeps. Read only when `WARDBY_LOW_POWER=1`. |
698
+
699
+ **Sleeping.** Every minute the scheduler leader scales the coding proxy
700
+ (`wardby-coding-proxy`) to 0 when no coding run is pending or running and none
701
+ finished within the idle window. It scales the native gateway
702
+ (`wardby-native-gateway`) to 0 when no sandbox native run is pending, running or
703
+ recently finished and the gateway has no active session. Either target sleeps
704
+ only once at least one idle window has passed since it was last woken (recorded
705
+ in its `wardby.io/power-woke-at` annotation) and since the control plane
706
+ started, whichever is later. The condition is checked again immediately before
707
+ scaling. The control plane
708
+ logs `power: proxy slept (idle 30m)`.
709
+
710
+ **Waking.** Starting a coding run scales the proxy to 1 and waits for a ready
711
+ endpoint. Starting a sandbox run does the same for the gateway. The wait is at
712
+ least 5 minutes, because a cold Autopilot node can add 1 to 2 minutes of
713
+ start-up; a `KUBERNETES_READY_TIMEOUT_MS` (proxy) or
714
+ `NATIVE_SANDBOX_READY_TIMEOUT_MS` (gateway) above 5 minutes, set on the
715
+ control-plane Deployment, raises it to that value. The first coding run after a
716
+ control-plane restart also runs the cluster preflight canary, because start-up
717
+ preflight is deferred while the proxy sleeps (`kubernetes_preflight_deferred`).
718
+
719
+ **Deploys.** Every `up.sh` run marks the proxy and gateway as just woken before
720
+ it applies the manifests, which bring them back up. That includes a run that
721
+ turns low-power mode off: the control plane being replaced still runs in
722
+ low-power mode until its rollout ends, and the mark stops it scaling them back
723
+ down. With the mode on they stay up through the deploy (its database checks
724
+ need them) and sleep one idle window later if nothing uses them.
725
+
726
+ **Sleeping now.** To skip the idle window (for example right after a test), an
727
+ admin calls the MCP tool `power_sleep`, optionally with `target` set to `proxy`
728
+ or `gateway` (default both). It scales the target to 0 at once, but never stops
729
+ a run: a target with a pending or running run, or for the gateway an active
730
+ gateway session, is left up and its run ids are returned under `blocked`.
731
+ Recently finished runs do not block it. The next run wakes the target as usual.
732
+ `power_status` shows each target's replicas, readiness, last wake time and
733
+ blocking run ids. Both tools need the `power:manage` scope, which only the
734
+ `admin` role grants; with the mode off, `power_sleep` fails with
735
+ `409 low_power_disabled` and `power_status` returns `{ "enabled": false }`.
736
+ Each `power_sleep` is logged as `event: "power.sleep"` with the caller's
737
+ principal.
738
+
739
+ **Control-plane autoscaling.** The control plane scales between 1 and 2 copies
740
+ on CPU (20% target, scale-down after 10 minutes). A run executes on
741
+ the copy that started it, so scheduled runs stay on the scheduler leader, while
742
+ runs started by a webhook or over MCP spread across copies. While the mode is on
743
+ the autoscaler owns the replica count, so do not set it by hand.
744
+
745
+ **Trade-offs.**
746
+
747
+ - Headroom is off, so the control plane has less protection against being
748
+ preempted when the cluster is short of capacity (see
749
+ [Pod priority and headroom](#pod-priority-and-headroom)).
750
+ - The gateway runs 1 replica instead of 2 while awake, so there is no
751
+ redundancy.
752
+ - `NATIVE_SANDBOX_WARM_POOL_SIZE` must be 0; the control plane refuses to start
753
+ otherwise, because a warm pool needs the gateway running.
754
+ - The gateway must be in the same namespace as `KUBERNETES_NAMESPACE`.
755
+ - The control plane needs the `wardby-power` Role: `get` and `patch` on the
756
+ proxy and gateway Deployments, and `get` on their Endpoints (to tell when a
757
+ woken target is ready). If any of it is missing, start-up warns
758
+ `low_power_scale_forbidden: missing ...` naming each permission, and waking,
759
+ `power_status` and `power_sleep` fail with that error; re-run `up.sh` with
760
+ the flag.
761
+
762
+ **Cost.** Autopilot bills Pod requests while a Pod exists. The table uses
763
+ us-central1 list prices of $0.0445 per vCPU-hour and $0.0049225 per GiB-hour and
764
+ 730 hours a month; substitute your region's current rates. Requests include the
765
+ Cloud SQL sidecar.
766
+
767
+ | Workload | Requests per replica | Per hour | Per month, always on | In low-power mode |
768
+ | ---------------------------- | --------------------- | -------- | -------------------- | --------------------------------------- |
769
+ | Control plane | 1.1 vCPU / 2.125 GiB | $0.0594 | $43.37 | 1 copy always; $0.0594/h per extra copy |
770
+ | Coding proxy | 1.1 vCPU / 3.125 GiB | $0.0643 | $46.96 | $0.0643/h only while awake |
771
+ | Native gateway (per replica) | 0.35 vCPU / 0.625 GiB | $0.0187 | $13.62 (x2 = $27.23) | 1 replica, $0.0187/h only while awake |
772
+ | Headroom placeholder | 0.25 vCPU / 0.5 GiB | $0.0136 | $9.92 | $0 |
773
+
774
+ With the mode off, those four workloads cost about $127.48 a month at these
775
+ rates. In low-power mode the control plane is still always on, and a fully
776
+ awake moment costs about $0.142 an hour for one control-plane copy, the proxy
777
+ and one gateway replica. Your total depends on how many hours the proxy and
778
+ gateway stay awake. Cloud SQL, the static address, load balancer, Cloud Armor
779
+ and any other always-on component are unchanged.
780
+
781
+ For error codes and log lines, see the
782
+ [low-power mode help article](../help/low-power-mode.md).
783
+
571
784
  ### Coding-run services
572
785
 
573
786
  A coding run whose agent allows [services](coding-services.md) waits for each
@@ -587,6 +800,7 @@ before. `up.sh` prints the previous digests at the end of every deploy.
587
800
  ```sh
588
801
  kubectl -n wardby-coding rollout undo deploy/wardby-control-plane
589
802
  kubectl -n wardby-coding rollout undo deploy/wardby-coding-proxy
803
+ kubectl -n wardby-coding rollout undo deploy/wardby-native-gateway
590
804
  ```
591
805
 
592
806
  `rollout undo` restores only the Deployments' images and pod templates — there
@@ -623,7 +837,9 @@ kubectl -n wardby-coding rollout restart deploy/wardby-coding-proxy deploy/wardb
623
837
 
624
838
  For a Jira setting, add the version to its `wardby-jira-*` secret, wait on
625
839
  `wardby-jira-env` instead, and restart only `deploy/wardby-control-plane`.
626
- Rotate the token and its `jira-api-token-expires-at` together.
840
+ Rotate the token and its `jira-api-token-expires-at` together. The Slack bot
841
+ token works the same way: add the version to `wardby-slack-bot-token`, wait on
842
+ `wardby-slack-env`, and restart only `deploy/wardby-control-plane`.
627
843
 
628
844
  Pods read their environment only at start, hence the restart. The LLM API
629
845
  keys and the database URL are read by both Deployments; the other secrets only
@@ -70,9 +70,10 @@ Create these scopes in the provider:
70
70
  | `memory:write` | Set and delete agent memory entries. |
71
71
  | `admin:view` | Read every owner's runs through the admin viewer API; admins only. |
72
72
  | `models:admin` | Add, override, disable and reset model catalog entries. |
73
+ | `power:manage` | Read low-power state and sleep the proxy/gateway now; admins only. |
73
74
 
74
75
  MCP clients discover this list from Wardby's protected-resource metadata and
75
- may request every advertised scope. Define all fourteen in the provider even when
76
+ may request every advertised scope. Define all fifteen in the provider even when
76
77
  policy grants a particular client or user only a subset. Ensure granted scopes
77
78
  are emitted in the access token's `scope` or `scp` claim; defining them only in
78
79
  the provider UI is not sufficient.
@@ -92,17 +93,21 @@ otherwise clients that request every advertised scope fail with `invalid_scope`.
92
93
  deployment, define it in the provider too; otherwise clients that request
93
94
  every advertised scope fail with `invalid_scope`.
94
95
 
96
+ `power:manage` was added after `models:admin`. When you upgrade an existing
97
+ deployment, define it in the provider too and map it like `agents:admin`;
98
+ otherwise clients that request every advertised scope fail with `invalid_scope`.
99
+
95
100
  ### Wardby roles
96
101
 
97
102
  A scope only delegates. `agents:admin`, `packages:approve`, `services:manage`,
98
- `admin:view` and `models:admin` take effect only for a caller who also holds a Wardby role that grants them:
103
+ `admin:view`, `models:admin` and `power:manage` take effect only for a caller who also holds a Wardby role that grants them:
99
104
 
100
- | Wardby role | Grants |
101
- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
102
- | `admin` | `agents:admin` (`make_owner`, BYO `workerImageRef`), `packages:approve`, `services:manage`, `admin:view` (read every owner's runs, see [viewer-api.md](viewer-api.md)) and `models:admin` (model catalog) |
103
- | `package-approver` | `packages:approve` (package allowlist and policy approval) |
104
- | `service-manager` | `services:manage` (coding-run service catalog changes) |
105
- | `model-manager` | `models:admin` (model catalog changes: `set_model`, `disable_model`, `reset_model`; see [models.md](models.md)) |
105
+ | Wardby role | Grants |
106
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
107
+ | `admin` | `agents:admin` (`make_owner`, BYO `workerImageRef`), `packages:approve`, `services:manage`, `admin:view` (read every owner's runs, see [viewer-api.md](viewer-api.md)), `models:admin` (model catalog) and `power:manage` (`power_status`, `power_sleep`; see [getting-started-gke.md](getting-started-gke.md#low-power-mode)) |
108
+ | `package-approver` | `packages:approve` (package allowlist and policy approval) |
109
+ | `service-manager` | `services:manage` (coding-run service catalog changes) |
110
+ | `model-manager` | `models:admin` (model catalog changes: `set_model`, `disable_model`, `reset_model`; see [models.md](models.md)) |
106
111
 
107
112
  The roles come from a claim in the caller's **access token**, which you map to
108
113
  Wardby roles:
@@ -162,7 +167,7 @@ Provider examples:
162
167
  to the access token, filtered to those groups. Set `AUTH_ROLE_CLAIM=groups` and
163
168
  `AUTH_ROLE_MAP=wardby-admin=admin,wardby-packages=package-approver,wardby-services=service-manager,wardby-models=model-manager`.
164
169
  Optionally, add access policy rules so only those groups can obtain
165
- `agents:admin`, `packages:approve`, `services:manage`, `admin:view` and `models:admin`.
170
+ `agents:admin`, `packages:approve`, `services:manage`, `admin:view`, `models:admin` and `power:manage`.
166
171
  - **FusionAuth:** create four application roles, `admin`,
167
172
  `package-approver`, `service-manager` and `model-manager`. They appear in the
168
173
  access token's top-level `roles` claim. Set `AUTH_ROLE_CLAIM=roles` and
@@ -188,6 +193,11 @@ that case, register the MCP client manually as a **public/native application**:
188
193
  - register the client's exact loopback callback URI; and
189
194
  - allow it to request the Wardby audience and scopes.
190
195
 
196
+ To let the Wardby mobile app sign in, also register its private-use redirect
197
+ URI, `com.wardby.mobile:/oauth` (or your white-label build's redirect, such as
198
+ `com.example.app:/oauth`), as an allowed redirect URI on the IdP client that
199
+ requests `admin:view`. Wardby needs no setting for this in delegating mode.
200
+
191
201
  For Claude Code, a fixed callback port makes the redirect URI predictable:
192
202
 
193
203
  ```sh
@@ -253,7 +263,7 @@ Confirm that:
253
263
 
254
264
  - `resource` is the canonical MCP URI;
255
265
  - `authorization_servers` contains the external issuer; and
256
- - `scopes_supported` contains all fourteen Wardby scopes.
266
+ - `scopes_supported` contains all fifteen Wardby scopes.
257
267
 
258
268
  An unauthenticated MCP request must return `401` with a `WWW-Authenticate`
259
269
  challenge pointing back to that metadata document.
@@ -310,6 +320,7 @@ test procedure and cleanup.
310
320
  | Wardby returns `403 insufficient_scope` | The token is valid but `scope`/`scp` lacks the operation's required permission. |
311
321
  | Client registration returns `403` | Anonymous dynamic registration is disabled; pre-register a public client. |
312
322
  | Browser flow rejects the redirect | The provider's registered loopback callback does not exactly match the client. |
323
+ | Mobile sign-in fails with a redirect error | The IdP client doesn't list the mobile redirect URI. |
313
324
  | Wardby cannot validate any newly issued token | The control plane cannot reach the JWKS URI, or provider key rotation is incomplete. |
314
325
  | One person appears as multiple principals | The provider is emitting different or pairwise `sub` values for different clients. |
315
326
 
@@ -49,11 +49,12 @@ The quickstart's sample agent is a native agent: it calls a model and nothing
49
49
  else. To have agents write code or review it, pick the path that matches what
50
50
  you have:
51
51
 
52
- | You want | You need | Path |
53
- | ------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------- |
54
- | A coding agent and a review agent, tried locally | Docker, an OpenAI **or** Anthropic key, a git repository on disk | [A](#path-a-local-repository-no-github-app) |
55
- | A coding agent that opens pull requests on GitHub | Path A's setup, plus a GitHub App installed on the repository | [B](#path-b-coding-agent-on-a-github-repository) |
56
- | A review agent that reviews GitHub pull requests | A GitHub App with webhooks, and Wardby reachable over public HTTPS | [C](#path-c-review-agent-on-github-pull-requests) |
52
+ | You want | You need | Path |
53
+ | ------------------------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- |
54
+ | A coding agent and a review agent, tried locally | Docker, an OpenAI **or** Anthropic key, a git repository on disk | [A](#path-a-local-repository-no-github-app) |
55
+ | A coding agent that opens pull requests on GitHub | Path A's setup, plus a GitHub App installed on the repository | [B](#path-b-coding-agent-on-a-github-repository) |
56
+ | A review agent that reviews GitHub pull requests | A GitHub App with webhooks, and Wardby reachable over public HTTPS | [C](#path-c-review-agent-on-github-pull-requests) |
57
+ | A coding agent for a language other than Node or Python | Path A's setup with Codex, and Docker to build an image | [D](#path-d-another-language-build-your-own-image) |
57
58
 
58
59
  Codex agents need only an OpenAI key and Claude Code agents only an Anthropic
59
60
  key; you don't need both.
@@ -70,7 +71,10 @@ key; you don't need both.
70
71
  Or run plain `quickstart` and answer **yes** to "Set up coding + review
71
72
  agents against a local git repo?". It asks for Codex or Claude Code, pulls
72
73
  only that provider's images, starts the coding proxy, and creates two agents:
73
- `local-builder` (writes code) and `local-reviewer` (reviews it).
74
+ `local-builder` (writes code) and `local-reviewer` (reviews it). If the
75
+ repository is a Python project, the builder gets a Node + Python 3.12
76
+ workspace so it can run the project's tests (see
77
+ [Python projects](#python-projects)).
74
78
 
75
79
  2. Ask your MCP client (the quickstart can register Wardby with Codex or Claude
76
80
  Code) to run the builder. The quickstart prints the exact call, for example:
@@ -153,6 +157,27 @@ or another host with a public URL.
153
157
  To try reviews before you have a public URL, use path A's `local-reviewer` on
154
158
  any local branch.
155
159
 
160
+ ### Path D: another language: build your own image
161
+
162
+ Wardby's worker images have Node, or Node and Python 3.12. For a Go, Java, Rust
163
+ or other project, build a worker image with that toolchain on Wardby's driver
164
+ base image, and point the builder at it with `codingProfile.workerImageRef`.
165
+ These steps are for a **Codex** builder. For a Claude Code builder, the image
166
+ starts from Wardby's tool runner image instead; see
167
+ [Codex and Claude Code](coding-worker-byo-images.md#codex-and-claude-code).
168
+
169
+ 1. Complete path A with Codex (`--coding-provider codex`).
170
+ 2. Run `npx @wardby/cli@latest doctor`. It prints the base image to build on:
171
+ "Base image for your own worker images: …@sha256:…".
172
+ 3. Write and build the Dockerfile as described in
173
+ [Bring-your-own worker images](coding-worker-byo-images.md), then set the
174
+ builder's `codingProfile.workerImageRef` with `update_agent` to the image's
175
+ local ID (`docker image inspect --format '{{.Id}}' <image>`).
176
+
177
+ Your MCP assistant can do these steps for you: ask it "Help me build a Wardby
178
+ worker image for Go" (or your language). It follows the `build-worker-image`
179
+ help article, checks the image, and runs a test task with it.
180
+
156
181
  ## Unattended setup
157
182
 
158
183
  Automation must explicitly accept the billed demo with `--yes`:
@@ -261,7 +286,10 @@ This step needs Docker, and an `OPENAI_API_KEY` (Codex) or `ANTHROPIC_API_KEY`
261
286
  `CODING_CLAUDE_TOOL_RUNNER_IMAGE`, to use images of your own;
262
287
  3. starts the coding proxy and runs the coding preflight;
263
288
  4. creates `local-builder` (a coding agent, $2 budget) and `local-reviewer` (a
264
- review agent, $1 budget) for a repository in the trusted folders (a trusted
289
+ review agent, $1.50 budget, on Claude Sonnet 5 or `gpt-5.6-terra` by default:
290
+ a step above the builder's model, so a review costs more per call but stays
291
+ within its budget; `--model` does not change it: change it with
292
+ `update_agent` — a quickstart re-run resets it) for a repository in the trusted folders (a trusted
265
293
  folder that is a git repository, or one directly inside it; with several,
266
294
  quickstart asks, or non-interactively uses the first in sorted order and
267
295
  prints it. Re-run with `--trust <repo>` to choose another: folders passed on
@@ -270,6 +298,14 @@ This step needs Docker, and an `OPENAI_API_KEY` (Codex) or `ANTHROPIC_API_KEY`
270
298
  other asks `local-reviewer` to review the branch `wardby/run-<run id>` the
271
299
  run pushed into your repository.
272
300
 
301
+ `local-reviewer` uses a thorough, repository-agnostic review prompt: it checks
302
+ correctness, security against the OWASP Top 10, performance, duplication,
303
+ modularity, AI-generated slop, code quality, test coverage and process, cites
304
+ your `docs/knowledge/` concepts when you have them, and ends with APPROVE or
305
+ CHANGES_REQUESTED. The prompt is quoted in the `architecture-agent` help
306
+ article. A re-run of quickstart moves a reviewer created by an earlier version
307
+ onto it; a `local-reviewer` you changed yourself is left alone.
308
+
273
309
  **Trust model.** Wardby only touches repositories inside the folders you trust.
274
310
  Agents see committed history only: untracked files such as `.env.local` never
275
311
  leave your machine. A run never changes your working tree or the branch you have
@@ -284,6 +320,79 @@ branch" for these agents is the branch checked out when quickstart runs. If the
284
320
  repository already has a services file, quickstart prints what it declares, or
285
321
  why it is invalid.
286
322
 
323
+ #### Python projects
324
+
325
+ Quickstart reads the committed root of the repository (never your working tree)
326
+ and treats it as a Python project when it holds `pyproject.toml`, `setup.py`,
327
+ `setup.cfg`, `Pipfile` or a `requirements*.txt` file. For a Python project it
328
+ prepares the Node + Python 3.12 workspace image for the provider you chose
329
+ (`toolchain: node-python`, version `3.12`) and creates `local-builder` on it, for
330
+ both Codex and Claude Code. The builder can then run the project's tests:
331
+ `pytest` and `ruff` are installed. Quickstart prints
332
+ "Python project detected: local-builder uses a Node + Python 3.12 workspace".
333
+
334
+ The image is recorded in `.wardby/.env`. To use your own build of it, set the
335
+ variable for your provider to an immutable digest (`repo@sha256:...`) or a local
336
+ image id before running quickstart:
337
+
338
+ | Provider | Variable |
339
+ | ----------- | -------------------------------------------------- |
340
+ | Codex | `CODING_WORKER_IMAGE_NODE_PYTHON_3_12` |
341
+ | Claude Code | `CODING_CLAUDE_TOOL_RUNNER_IMAGE_NODE_PYTHON_3_12` |
342
+
343
+ If your wardby version ships no Python workspace image, quickstart prints
344
+ "Python project detected, but this version has no Python workspace image" and
345
+ creates the builder on the default Node workspace: it can edit code but not run
346
+ Python tests. Upgrade, or set the variable above.
347
+
348
+ Other languages (Go, Rust, Java and so on) are not detected. Use a
349
+ bring-your-own image through `workerImageRef`; see
350
+ [Path D](#path-d-another-language-build-your-own-image) and
351
+ [Bring-your-own worker images](coding-worker-byo-images.md), for Codex or
352
+ Claude Code.
353
+
354
+ #### Packages the repository declares
355
+
356
+ Coding agents can install only the packages on their allowlist (see
357
+ [Installing packages in coding runs](coding-packages.md)), and a new agent's
358
+ allowlist is empty. So that `local-builder` can install the project's
359
+ dependencies, quickstart reads the ones the repository declares at the root of
360
+ the same commit (never your working tree):
361
+
362
+ - `package.json`: `dependencies`, `devDependencies` and `optionalDependencies`
363
+ (not peer dependencies) for npm;
364
+ - `pyproject.toml`: `[project] dependencies`, every
365
+ `[project.optional-dependencies]` group, `[tool.poetry.dependencies]`,
366
+ Poetry's dependency groups and the legacy `[tool.poetry.dev-dependencies]`
367
+ for PyPI, plus the packages pip needs to build the project:
368
+ `[build-system] requires` (such as `setuptools`, `hatchling` or
369
+ `poetry-core`), or `setuptools` and `wheel` when the file has no
370
+ `[build-system]` table (pip then uses the legacy setuptools backend);
371
+ - every `requirements*.txt` for PyPI. Options such as `-r`, `-c` and `-e`,
372
+ URLs and local paths are skipped; an included file (`-r other.txt`) is not
373
+ followed.
374
+
375
+ It keeps package names without versions (a Python requirement keeps the extras
376
+ it names, such as `psycopg[binary]`, so the packages those extras add can be
377
+ installed too), drops names that are not valid in their ecosystem, and skips non-registry sources (`file:`, `git`, URL and
378
+ path dependencies). It prints the counts and up to a dozen names, then asks
379
+ "Allow local-builder to install these packages through Wardby's registry?
380
+ [Y/n]". The allowed names go on the builder's `codingProfile.packageAllowlist`.
381
+ Versions still come from your lockfile or the package manager's resolver, and
382
+ every registry safeguard (release age, advisories, the record of what was
383
+ fetched) still applies.
384
+
385
+ - More than 200 names in one ecosystem: quickstart adds none from it and says
386
+ why.
387
+ - A manifest it cannot read (an unusual `pyproject.toml` layout, for example):
388
+ it prints a one-line note and skips that file.
389
+ - Answering no, or a `--non-interactive` run without `--allow-repo-packages`,
390
+ leaves the allowlist empty. Add packages later with `update_agent` and
391
+ `codingProfile.packageAllowlist`.
392
+ - A re-run sets an existing quickstart `local-builder`'s allowlist to what the
393
+ repository declares now (or empty if you decline), replacing entries you
394
+ added by hand.
395
+
287
396
  Options for unattended use:
288
397
 
289
398
  ```sh
@@ -291,7 +400,8 @@ OPENAI_API_KEY="..." npx --yes @wardby/cli@latest quickstart \
291
400
  --non-interactive --yes \
292
401
  --coding --trust ~/projects/my-repo \
293
402
  --coding-provider codex \
294
- --starter-services postgres
403
+ --starter-services postgres \
404
+ --allow-repo-packages
295
405
  ```
296
406
 
297
407
  - `--coding` runs the step without asking and `--no-coding` skips it. With
@@ -301,6 +411,9 @@ OPENAI_API_KEY="..." npx --yes @wardby/cli@latest quickstart \
301
411
  - `--coding-provider codex|claude-code` picks the coding agent; by default it
302
412
  uses the provider whose key is available.
303
413
  - `--starter-services postgres,redis|none` answers the starter-file question.
414
+ - `--allow-repo-packages` allows the repository's declared packages without
415
+ asking; `--no-allow-repo-packages` allows none. Non-interactive runs allow
416
+ none unless the flag is given.
304
417
 
305
418
  `doctor` and `status` then also report the trusted folders, the worker image,
306
419
  the coding proxy, and each local agent's repository, and `down` stops the proxy
@@ -319,9 +432,25 @@ and need the GitHub App, worker image, and job launcher from
319
432
  [Coding-agent setup](coding-agent-setup.md). Their event triggers need GitHub to
320
433
  reach your instance at a public HTTPS URL.
321
434
 
322
- The assistant the quickstart connected can walk you through either recipe. Ask it
323
- "Set up the Wardby architecture keeper for this repository" or "Set up a Wardby
324
- builder for this repository"; it follows the `agent-recipes` help article.
435
+ The quickstart ends with a short menu of things to ask the assistant it
436
+ connected, each with the help article the assistant follows:
437
+
438
+ 1. "Run local-builder with a task, then have local-reviewer review the branch"
439
+ (`local-repositories`; shown only when the coding step ran).
440
+ 2. "Let local-builder install more packages" (`coding-packages`).
441
+ 3. "Help me build a Wardby worker image for Go (or Java, Rust…)"
442
+ (`build-worker-image`).
443
+ 4. "Set up a scheduled Wardby agent" (`creating-agents`).
444
+ 5. "Set up a Wardby architecture reviewer and keeper for this repo"
445
+ (`architecture-agent`, which has a local-repository variant).
446
+ 6. "Help me plan out a GKE deployment" (`deploy-gke` and
447
+ `deployment-targets`).
448
+
449
+ Without an MCP client, read an article with
450
+ `npx @wardby/cli@latest help open <article>`. The GitHub setups above are not
451
+ in the menu; ask for one directly, for example "Set up the Wardby architecture
452
+ keeper for this repository", and the assistant follows the `agent-recipes`
453
+ help article.
325
454
 
326
455
  ## Next steps
327
456
 
@@ -24,7 +24,7 @@ Jira Cloud only. One Jira site per wardby deployment.
24
24
  properties are not allowlisted.
25
25
  - **Status comments.** When an event starts a run, wardby posts a short
26
26
  "working on it" comment on the issue and edits it with the outcome when the
27
- run ends, including a line such as `Agent spend: $0.0123` for the run and
27
+ run ends, including a line such as `Agent spend: $0.012` for the run and
28
28
  its direct sub-runs. That one comment is the reply: when the run succeeds
29
29
  it shows the agent's final answer, so the agent is told not to post the
30
30
  answer again with `jira_comment` (it uses `jira_comment` only for other
@@ -478,6 +478,10 @@ What happens:
478
478
  [`code-review-agents.md`](code-review-agents.md)). Without them the pull
479
479
  request is still linked, but the issue is not updated on merge.
480
480
 
481
+ To mirror this lifecycle in Slack — picked up, pull request open, review
482
+ verdict, merge — link a channel to the project or agent; see
483
+ [Send workflow updates to Slack](slack-notifications.md).
484
+
481
485
  ## Recipe: scheduled JQL sweeps
482
486
 
483
487
  An agent linked to a project can also run on a schedule with no issue event:
package/docs/knowledge.md CHANGED
@@ -366,6 +366,17 @@ Reply with one line: what you started and why, or "No action: <reason>".
366
366
  If the delegate call returns a failure, reply with a line beginning FAILED:.
367
367
  ```
368
368
 
369
+ ## Architecture agents on a local repository
370
+
371
+ For a `local:` repository (no GitHub App), such as the one the quickstart's
372
+ coding step sets up, the `architecture-agent` help article has a "Local
373
+ repository (no GitHub App)" section: the keeper is a scheduled coding agent
374
+ whose runs push knowledge updates to `wardby/run-<run id>` branches, and the
375
+ reviewer is a native agent linked with `link_repository` (`provider: "local"`)
376
+ that you start with `trigger_agent` and `review: {branch}`. There is no merge
377
+ watcher (the `push` trigger needs GitHub), and the schedule fires only while a
378
+ Wardby scheduler (`wardby scheduler` or `wardby serve`) is running.
379
+
369
380
  ## Reviewer step
370
381
 
371
382
  Add this section to the system prompt of a code-review agent (see