@wardby/cli 0.3.0 → 0.4.1

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 (275) hide show
  1. package/.env.example +22 -3
  2. package/README.md +11 -9
  3. package/dist/cli-help.d.ts +1 -1
  4. package/dist/cli-help.js +1 -0
  5. package/dist/cli.js +68 -10
  6. package/dist/coding/base-commit.d.ts +6 -0
  7. package/dist/coding/base-commit.js +12 -0
  8. package/dist/coding/protocol.d.ts +17 -1
  9. package/dist/coding/protocol.js +17 -6
  10. package/dist/coding/provider.d.ts +6 -1
  11. package/dist/coding/provider.js +16 -9
  12. package/dist/config/providers.d.ts +25 -0
  13. package/dist/config/providers.js +71 -0
  14. package/dist/core/attribution.d.ts +101 -0
  15. package/dist/core/attribution.js +208 -0
  16. package/dist/core/budget-groups.d.ts +17 -10
  17. package/dist/core/budget-groups.js +15 -12
  18. package/dist/core/coding-queue.d.ts +3 -0
  19. package/dist/core/coding-queue.js +6 -2
  20. package/dist/core/coding-service-status.d.ts +11 -0
  21. package/dist/core/coding-service-status.js +17 -0
  22. package/dist/core/cost-report.d.ts +88 -0
  23. package/dist/core/cost-report.js +248 -0
  24. package/dist/core/dispatch.d.ts +42 -2
  25. package/dist/core/dispatch.js +144 -26
  26. package/dist/core/engine-native.js +17 -4
  27. package/dist/core/glob.d.ts +10 -0
  28. package/dist/core/glob.js +33 -0
  29. package/dist/core/host-events.d.ts +24 -1
  30. package/dist/core/host-events.js +341 -1
  31. package/dist/core/host-status.d.ts +19 -2
  32. package/dist/core/host-status.js +47 -30
  33. package/dist/core/issue-bridge.d.ts +60 -0
  34. package/dist/core/issue-bridge.js +189 -0
  35. package/dist/core/issue-dedupe.d.ts +70 -0
  36. package/dist/core/issue-dedupe.js +255 -0
  37. package/dist/core/issue-events.d.ts +42 -0
  38. package/dist/core/issue-events.js +155 -0
  39. package/dist/core/issue-status.d.ts +29 -0
  40. package/dist/core/issue-status.js +241 -0
  41. package/dist/core/issue-tracker-tools.d.ts +64 -0
  42. package/dist/core/issue-tracker-tools.js +850 -0
  43. package/dist/core/model-usage.d.ts +10 -0
  44. package/dist/core/model-usage.js +24 -0
  45. package/dist/core/reconciler.d.ts +8 -4
  46. package/dist/core/reconciler.js +15 -4
  47. package/dist/core/review-host-tools.js +10 -3
  48. package/dist/core/run-pricing.d.ts +61 -0
  49. package/dist/core/run-pricing.js +56 -0
  50. package/dist/core/runner.d.ts +5 -2
  51. package/dist/core/runner.js +178 -27
  52. package/dist/core/scheduler.d.ts +4 -1
  53. package/dist/core/scheduler.js +3 -2
  54. package/dist/core/self-defects.d.ts +80 -0
  55. package/dist/core/self-defects.js +180 -0
  56. package/dist/core/tool-names.js +3 -0
  57. package/dist/core/webhooks.d.ts +9 -1
  58. package/dist/core/webhooks.js +19 -1
  59. package/dist/env.js +6 -1
  60. package/dist/generated/prisma/browser.d.ts +66 -0
  61. package/dist/generated/prisma/client.d.ts +66 -0
  62. package/dist/generated/prisma/commonInputTypes.d.ts +122 -52
  63. package/dist/generated/prisma/enums.d.ts +7 -0
  64. package/dist/generated/prisma/enums.js +6 -0
  65. package/dist/generated/prisma/internal/class.d.ts +99 -0
  66. package/dist/generated/prisma/internal/class.js +4 -4
  67. package/dist/generated/prisma/internal/prismaNamespace.d.ts +826 -1
  68. package/dist/generated/prisma/internal/prismaNamespace.js +135 -2
  69. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +142 -0
  70. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -2
  71. package/dist/generated/prisma/models/Agent.d.ts +389 -1
  72. package/dist/generated/prisma/models/AgentIssueProject.d.ts +1838 -0
  73. package/dist/generated/prisma/models/AgentIssueProject.js +1 -0
  74. package/dist/generated/prisma/models/AgentRepository.d.ts +1 -1
  75. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  76. package/dist/generated/prisma/models/CodingProxySession.d.ts +73 -1
  77. package/dist/generated/prisma/models/CodingRun.d.ts +130 -1
  78. package/dist/generated/prisma/models/CodingRunServiceStatus.d.ts +1404 -0
  79. package/dist/generated/prisma/models/CodingRunServiceStatus.js +1 -0
  80. package/dist/generated/prisma/models/IssueFingerprint.d.ts +1183 -0
  81. package/dist/generated/prisma/models/IssueFingerprint.js +1 -0
  82. package/dist/generated/prisma/models/IssuePullRequest.d.ts +1255 -0
  83. package/dist/generated/prisma/models/IssuePullRequest.js +1 -0
  84. package/dist/generated/prisma/models/ModelCatalogEntry.d.ts +1322 -0
  85. package/dist/generated/prisma/models/ModelCatalogEntry.js +1 -0
  86. package/dist/generated/prisma/models/Run.d.ts +933 -1
  87. package/dist/generated/prisma/models/RunAttribution.d.ts +1259 -0
  88. package/dist/generated/prisma/models/RunAttribution.js +1 -0
  89. package/dist/generated/prisma/models/RunIssueStatus.d.ts +1199 -0
  90. package/dist/generated/prisma/models/RunIssueStatus.js +1 -0
  91. package/dist/generated/prisma/models/RunModelUsage.d.ts +1316 -0
  92. package/dist/generated/prisma/models/RunModelUsage.js +1 -0
  93. package/dist/generated/prisma/models/WorkItem.d.ts +1408 -0
  94. package/dist/generated/prisma/models/WorkItem.js +1 -0
  95. package/dist/generated/prisma/models.d.ts +9 -0
  96. package/dist/help-index.json +355 -16
  97. package/dist/import/neutral-schema.d.ts +16 -16
  98. package/dist/knowledge/check.d.ts +13 -0
  99. package/dist/knowledge/check.js +69 -0
  100. package/dist/knowledge/cli.d.ts +14 -0
  101. package/dist/knowledge/cli.js +67 -0
  102. package/dist/knowledge/concept.d.ts +54 -0
  103. package/dist/knowledge/concept.js +78 -0
  104. package/dist/knowledge/note.d.ts +11 -0
  105. package/dist/knowledge/note.js +39 -0
  106. package/dist/knowledge/relevance.d.ts +11 -0
  107. package/dist/knowledge/relevance.js +14 -0
  108. package/dist/knowledge/span-hash.d.ts +3 -0
  109. package/dist/knowledge/span-hash.js +16 -0
  110. package/dist/mcp/auth/access.d.ts +4 -2
  111. package/dist/mcp/auth/ownership.d.ts +9 -9
  112. package/dist/mcp/auth/resource-server.d.ts +3 -1
  113. package/dist/mcp/auth/resource-server.js +18 -3
  114. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  115. package/dist/mcp/auth/self-hosted/session.d.ts +5 -5
  116. package/dist/mcp/context.d.ts +3 -0
  117. package/dist/mcp/host-events/deliveries.d.ts +9 -0
  118. package/dist/mcp/host-events/deliveries.js +17 -0
  119. package/dist/mcp/host-events/github-ingress.d.ts +4 -2
  120. package/dist/mcp/host-events/github-ingress.js +4 -13
  121. package/dist/mcp/host-events/jira-ingress.d.ts +29 -0
  122. package/dist/mcp/host-events/jira-ingress.js +92 -0
  123. package/dist/mcp/index.d.ts +2 -0
  124. package/dist/mcp/index.js +87 -9
  125. package/dist/mcp/server.js +5 -2
  126. package/dist/mcp/tools/agents.js +74 -3
  127. package/dist/mcp/tools/cost-report.d.ts +8 -0
  128. package/dist/mcp/tools/cost-report.js +60 -0
  129. package/dist/mcp/tools/issue-projects.d.ts +2 -0
  130. package/dist/mcp/tools/issue-projects.js +238 -0
  131. package/dist/mcp/tools/model-catalog.d.ts +22 -0
  132. package/dist/mcp/tools/model-catalog.js +423 -0
  133. package/dist/mcp/tools/repositories.js +2 -1
  134. package/dist/mcp/tools/tools.d.ts +2 -2
  135. package/dist/mcp/tools/trigger.js +33 -5
  136. package/dist/mcp/transport/streamable-http.d.ts +5 -0
  137. package/dist/mcp/transport/streamable-http.js +23 -1
  138. package/dist/mcp/webhooks/ingress.d.ts +2 -1
  139. package/dist/mcp/webhooks/ingress.js +9 -2
  140. package/dist/providers/auth/self-hosted.d.ts +8 -1
  141. package/dist/providers/auth/self-hosted.js +39 -2
  142. package/dist/providers/coding-proxy/memory-ledger.d.ts +1 -1
  143. package/dist/providers/coding-proxy/memory-ledger.js +10 -1
  144. package/dist/providers/coding-proxy/metering.d.ts +2 -1
  145. package/dist/providers/coding-proxy/metering.js +13 -2
  146. package/dist/providers/coding-proxy/prisma-ledger.js +59 -6
  147. package/dist/providers/coding-proxy/proxy.d.ts +12 -2
  148. package/dist/providers/coding-proxy/proxy.js +92 -30
  149. package/dist/providers/coding-proxy/types.d.ts +18 -1
  150. package/dist/providers/coding-proxy/types.js +12 -1
  151. package/dist/providers/engine/types.d.ts +19 -0
  152. package/dist/providers/executor/composition.js +9 -1
  153. package/dist/providers/executor/container.d.ts +30 -2
  154. package/dist/providers/executor/container.js +98 -17
  155. package/dist/providers/executor/dbos.d.ts +2 -0
  156. package/dist/providers/executor/dbos.js +7 -5
  157. package/dist/providers/executor/routing.d.ts +6 -0
  158. package/dist/providers/executor/routing.js +5 -0
  159. package/dist/providers/executor/types.d.ts +12 -0
  160. package/dist/providers/issue-tracker/adf.d.ts +31 -0
  161. package/dist/providers/issue-tracker/adf.js +181 -0
  162. package/dist/providers/issue-tracker/index.d.ts +5 -0
  163. package/dist/providers/issue-tracker/index.js +12 -0
  164. package/dist/providers/issue-tracker/jira-client.d.ts +41 -0
  165. package/dist/providers/issue-tracker/jira-client.js +151 -0
  166. package/dist/providers/issue-tracker/jira-events.d.ts +3 -0
  167. package/dist/providers/issue-tracker/jira-events.js +98 -0
  168. package/dist/providers/issue-tracker/jira.d.ts +116 -0
  169. package/dist/providers/issue-tracker/jira.js +502 -0
  170. package/dist/providers/issue-tracker/types.d.ts +269 -0
  171. package/dist/providers/issue-tracker/types.js +16 -0
  172. package/dist/providers/jobs/docker.d.ts +5 -1
  173. package/dist/providers/jobs/docker.js +61 -33
  174. package/dist/providers/jobs/kubernetes.d.ts +3 -0
  175. package/dist/providers/jobs/kubernetes.js +44 -4
  176. package/dist/providers/jobs/service-state.d.ts +22 -0
  177. package/dist/providers/jobs/service-state.js +17 -0
  178. package/dist/providers/llm/anthropic.d.ts +3 -3
  179. package/dist/providers/llm/anthropic.js +3 -9
  180. package/dist/providers/llm/bedrock.d.ts +3 -3
  181. package/dist/providers/llm/bedrock.js +3 -9
  182. package/dist/providers/llm/catalog-lookup.d.ts +10 -0
  183. package/dist/providers/llm/catalog-lookup.js +15 -0
  184. package/dist/providers/llm/catalog-shipped.d.ts +18 -0
  185. package/dist/providers/llm/catalog-shipped.js +197 -0
  186. package/dist/providers/llm/catalog-store.d.ts +58 -0
  187. package/dist/providers/llm/catalog-store.js +138 -0
  188. package/dist/providers/llm/catalog-types.d.ts +66 -0
  189. package/dist/providers/llm/catalog-types.js +64 -0
  190. package/dist/providers/llm/catalog.d.ts +61 -0
  191. package/dist/providers/llm/catalog.js +147 -0
  192. package/dist/providers/llm/claude-provider.d.ts +10 -14
  193. package/dist/providers/llm/claude-provider.js +11 -6
  194. package/dist/providers/llm/index.d.ts +9 -6
  195. package/dist/providers/llm/index.js +8 -5
  196. package/dist/providers/llm/openai.d.ts +14 -5
  197. package/dist/providers/llm/openai.js +24 -14
  198. package/dist/providers/llm/pricing-core.d.ts +5 -3
  199. package/dist/providers/llm/registration.js +8 -12
  200. package/dist/providers/llm/routing.d.ts +18 -17
  201. package/dist/providers/llm/routing.js +40 -24
  202. package/dist/providers/review-host/github-events.js +47 -1
  203. package/dist/providers/review-host/github.js +7 -6
  204. package/dist/providers/review-host/types.d.ts +25 -0
  205. package/dist/providers/vcs/git.js +2 -22
  206. package/dist/providers/vcs/github.d.ts +20 -0
  207. package/dist/providers/vcs/github.js +28 -2
  208. package/dist/providers/vcs/types.d.ts +6 -0
  209. package/dist/quickstart/index.d.ts +8 -0
  210. package/dist/quickstart/index.js +34 -34
  211. package/dist/serve.js +8 -2
  212. package/dist/viewer/api-schema.d.ts +2757 -0
  213. package/dist/viewer/api-schema.js +165 -0
  214. package/dist/viewer/build-schemas.d.ts +2 -0
  215. package/dist/viewer/build-schemas.js +18 -0
  216. package/dist/viewer/event-bus.d.ts +38 -0
  217. package/dist/viewer/event-bus.js +232 -0
  218. package/dist/viewer/graph.d.ts +40 -0
  219. package/dist/viewer/graph.js +243 -0
  220. package/dist/viewer/http.d.ts +30 -0
  221. package/dist/viewer/http.js +133 -0
  222. package/dist/viewer/run-detail.d.ts +4 -0
  223. package/dist/viewer/run-detail.js +61 -0
  224. package/dist/wardby-bin.js +5 -0
  225. package/docs/README.md +10 -0
  226. package/docs/agent-recipes.md +383 -0
  227. package/docs/code-review-agents.md +29 -2
  228. package/docs/coding-agent-setup.md +3 -0
  229. package/docs/coding-worker-isolation.md +39 -5
  230. package/docs/getting-started-gke.md +28 -11
  231. package/docs/getting-started-identity-provider.md +49 -38
  232. package/docs/getting-started.md +14 -0
  233. package/docs/jira-agents.md +649 -0
  234. package/docs/knowledge.md +387 -0
  235. package/docs/models.md +221 -0
  236. package/docs/security-deployment.md +19 -9
  237. package/docs/viewer-api.md +142 -0
  238. package/help/admin-viewer.md +39 -0
  239. package/help/agent-recipes.md +173 -0
  240. package/help/architecture-agent.md +189 -0
  241. package/help/builder-agent.md +80 -0
  242. package/help/code-review-agents.md +6 -0
  243. package/help/cost-attribution.md +67 -0
  244. package/help/creating-agents.md +22 -0
  245. package/help/deploy-gke.md +6 -0
  246. package/help/errors/model-unavailable.md +63 -0
  247. package/help/getting-started.md +1 -0
  248. package/help/github.md +18 -0
  249. package/help/identity-and-access.md +8 -3
  250. package/help/jira.md +135 -0
  251. package/help/knowledge.md +47 -0
  252. package/help/models.md +90 -0
  253. package/help/operating-agents.md +7 -1
  254. package/help/troubleshooting/budgets.md +6 -0
  255. package/package.json +5 -2
  256. package/prisma/migrations/20260930000000_jira_issue_projects/migration.sql +34 -0
  257. package/prisma/migrations/20261001000000_jira_phase2_allowlists/migration.sql +3 -0
  258. package/prisma/migrations/20261001010000_jira_link_types_allowlist/migration.sql +2 -0
  259. package/prisma/migrations/20261002000000_jira_coding_bridge/migration.sql +28 -0
  260. package/prisma/migrations/20261002010000_jira_issue_creation/migration.sql +25 -0
  261. package/prisma/migrations/20261003000000_issue_cost_attribution/migration.sql +56 -0
  262. package/prisma/migrations/20261003010000_coding_run_service_status/migration.sql +23 -0
  263. package/prisma/migrations/20261003020000_viewer_notify/migration.sql +54 -0
  264. package/prisma/migrations/20261003030000_viewer_notify_fixes/migration.sql +47 -0
  265. package/prisma/migrations/20261003040000_viewer_indexes/migration.sql +12 -0
  266. package/prisma/migrations/20261004000000_model_catalog/migration.sql +26 -0
  267. package/prisma/schema.prisma +258 -2
  268. package/dist/mcp/tools/models.d.ts +0 -8
  269. package/dist/mcp/tools/models.js +0 -15
  270. package/dist/providers/llm/pricing-anthropic.d.ts +0 -14
  271. package/dist/providers/llm/pricing-anthropic.js +0 -48
  272. package/dist/providers/llm/pricing-bedrock-claude.d.ts +0 -20
  273. package/dist/providers/llm/pricing-bedrock-claude.js +0 -46
  274. package/dist/providers/llm/pricing.d.ts +0 -30
  275. package/dist/providers/llm/pricing.js +0 -74
@@ -0,0 +1,383 @@
1
+ # Agent recipes
2
+
3
+ Two complete agent setups you can ask your MCP client to build, made only from
4
+ shipped Wardby features:
5
+
6
+ - [Recipe A: an architecture keeper](#recipe-a-an-architecture-keeper), three
7
+ cooperating agents that keep a repository's architecture knowledge accurate.
8
+ - [Recipe B: a builder per language](#recipe-b-a-builder-per-language), a
9
+ coding agent that turns an `@mention` into a draft pull request, with notes for
10
+ Node/TypeScript, Python, and other languages.
11
+
12
+ Each recipe gives the one-paragraph ask you paste into Claude or Codex, the
13
+ configuration that results, and what it produces. Both use `your-org/your-repo`
14
+ as a placeholder repository.
15
+
16
+ Agent names are unique across the whole instance, so the examples use
17
+ repo-scoped names such as `<repo>-architect`. The sub-agent bound names
18
+ (`architect`, `builder`) stay fixed so the delegate tools keep their names.
19
+
20
+ ## Before you start
21
+
22
+ These recipes go beyond the quickstart. Check each item.
23
+
24
+ 1. **Version.** The recipes require Wardby 0.4.0 or later. The knowledge note in
25
+ coding runs, `wardby knowledge check`, and the `push` trigger are not in
26
+ earlier releases.
27
+ 2. **Coding-agent setup.** The quickstart runs native agents only: it does not
28
+ install a GitHub App or build worker images. Both recipes use coding agents,
29
+ so complete [Coding-agent setup](coding-agent-setup.md) first: a GitHub App
30
+ installed on the repository, a worker image, the coding proxy, and a Docker or
31
+ Kubernetes job launcher. Run `wardby coding preflight` to check it. For a
32
+ hosted deployment, [Getting started on GKE](getting-started-gke.md) covers
33
+ this.
34
+ 3. **A GitHub account link.** Link your GitHub account once with
35
+ `link_host_account`. Creating a coding agent or linking a repository checks
36
+ that you have write access to the repository
37
+ ([details](code-review-agents.md#who-may-give-an-agent-a-repository)).
38
+ 4. **A public HTTPS URL for GitHub webhooks.** The event triggers (`push` for the
39
+ merge watcher, `pull_request` for the reviewer, `mention` for the router) work
40
+ only when GitHub can deliver webhooks to your Wardby instance. Set the App's
41
+ webhook URL to `https://<your-host>/hosts/github/events` and its webhook
42
+ secret to the value of `GITHUB_APP_WEBHOOK_SECRET`
43
+ ([registering the App](code-review-agents.md#registering-the-github-app)). A
44
+ laptop install is not reachable from GitHub by default, so it needs a public
45
+ HTTPS endpoint in front of it (the
46
+ [runtime architecture](architecture-runtime.md) diagram shows an HTTPS tunnel
47
+ in front of the local server) or a hosted deployment such as
48
+ [GKE](getting-started-gke.md). Scheduled and manually triggered runs need no
49
+ webhook.
50
+ 5. **App events.** Tick the events each trigger needs in the App's settings:
51
+ Pull request and Check run for reviews; Issue comment, Pull request review
52
+ comment, and Issues for mentions; and **Push** for the merge watcher. Each is
53
+ its own checkbox
54
+ ([registering the App](code-review-agents.md#registering-the-github-app)).
55
+ 6. **Models.** Pick ids from `list_models` ([Models and pricing](models.md)). The
56
+ examples use `claude-sonnet-5` for the capable coding model and
57
+ `claude-haiku-4-5` for the small fast one; use whatever your deployment has
58
+ enabled. A coding agent's model must be supported by its coding provider.
59
+
60
+ ## Recipe A: an architecture keeper
61
+
62
+ **What it does.** Keeps `docs/knowledge/` (see
63
+ [Architecture knowledge bundles](knowledge.md)) accurate and growing, and lets
64
+ coding agents and reviewers use it. **Triggers:** the architect runs weekly on a
65
+ schedule; the merge watcher runs on every merge to the default branch; the
66
+ reviewer step runs on every pull request.
67
+
68
+ ### The MCP ask
69
+
70
+ > Set up an architecture keeper for `your-org/your-repo`. Create a Claude Code
71
+ > coding agent called `<repo>-architect` with the reference architecture-agent prompt
72
+ > from the Wardby knowledge guide and a $3 per-run budget. Trigger it once and
73
+ > show me the run; don't schedule it yet. After I've reviewed its first pull
74
+ > request, schedule it for Mondays at 6:00 AM. Then create a small, cheap native
75
+ > agent called `<repo>-merge-watcher` with the reference watcher prompt, attach
76
+ > `architect` to it as a sub-agent named `architect`, and link it to the
77
+ > repository with the `push` trigger. Finally, add the reviewer step to my
78
+ > existing code-review agent's prompt.
79
+
80
+ ### The resulting configuration
81
+
82
+ Do the steps in this order; each depends on the one before.
83
+
84
+ 1. **Create the architect.**
85
+ 2. **Trigger it once by hand** (`trigger_agent`) and review the draft pull
86
+ request it opens.
87
+ 3. **Schedule it** (`set_schedule`).
88
+ 4. **Create the watcher**, attach the architect, tick **Push** in the App's
89
+ events, and link it with `push`.
90
+ 5. **Add the reviewer step** to your review agent's prompt.
91
+
92
+ <details>
93
+ <summary>Architect (coding agent)</summary>
94
+
95
+ | Setting | Value |
96
+ | ----------------- | -------------------------------------------------------------------------------------------------------- |
97
+ | `name` | `<repo>-architect` |
98
+ | `kind` | `coding` |
99
+ | `model` | a capable coding model, for example `claude-sonnet-5` with `provider: "claude-code"` |
100
+ | `budgetUsd` | `3` per run (docs-only work) |
101
+ | `codingProfile` | `provider`, `repository: "your-org/your-repo"`, `baseRef` (your default branch), and `defaultTask` below |
102
+ | `schedule` | `0 6 * * 1` with your `timezone`, set after the first manual run (`set_schedule`) |
103
+ | Tools, sub-agents | None |
104
+ | Repository checks | May be skipped; the work is docs-only |
105
+ | System prompt | The architect prompt in [Architecture knowledge bundles](knowledge.md#set-up-an-architecture-agent) |
106
+
107
+ `defaultTask`, required before a coding agent can be scheduled:
108
+
109
+ ```text
110
+ Weekly knowledge review. Run the full cycle described in your instructions for
111
+ this repository. Your file changes are collected into a pull request for review;
112
+ don't try to commit or open one yourself.
113
+ ```
114
+
115
+ The prompt is published once, in the knowledge guide, so this page cannot drift
116
+ from it. Copy it from there, unchanged, as the agent's `systemPrompt`.
117
+
118
+ </details>
119
+
120
+ <details>
121
+ <summary>Merge watcher (native agent)</summary>
122
+
123
+ | Setting | Value |
124
+ | ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
125
+ | `name` | `<repo>-merge-watcher` |
126
+ | `kind` | `native` |
127
+ | `model` | a small fast model, for example `claude-haiku-4-5` |
128
+ | `budgetUsd` | Sized for the architect's per-run cost: the run tree shares one budget, so at least `3` plus a little for the watcher itself |
129
+ | Sub-agent | `attach_subagent` with `parentAgentId` the watcher, `childAgentId` the architect, `boundName: "architect"` |
130
+ | Link | `link_repository` with `access: "write"`, `triggers: ["push"]`, no `checkName` |
131
+ | System prompt | The reference watcher prompt in [Drift runs on merge](knowledge.md#set-up-the-merge-watcher), copied unchanged from that guide |
132
+
133
+ The bound name gives the watcher a `delegate_to_architect` tool, which the
134
+ reference prompt calls.
135
+
136
+ ```json
137
+ {
138
+ "agentId": "<watcher agent id>",
139
+ "repository": "your-org/your-repo",
140
+ "access": "write",
141
+ "triggers": ["push"]
142
+ }
143
+ ```
144
+
145
+ Only pushes to the default branch start it. If the watcher already has a run
146
+ pending or running, the next merge starts nothing; the weekly run catches up.
147
+
148
+ </details>
149
+
150
+ <details>
151
+ <summary>Reviewer knowledge step</summary>
152
+
153
+ Append the "Reviewer step" section from
154
+ [Architecture knowledge bundles](knowledge.md#reviewer-step) to the system
155
+ prompt of a code-review agent ([Code-review agents](code-review-agents.md)). No
156
+ other setting changes. It makes reviews read the bundle's index, apply the
157
+ concepts that match the changed files, and report stale citations on knowledge
158
+ pull requests as suggestions only.
159
+
160
+ </details>
161
+
162
+ ### What it produces
163
+
164
+ - A weekly draft pull request that touches only `docs/knowledge/` and an
165
+ `AGENTS.md` pointer, adding cited concepts and re-anchoring stale ones. A
166
+ person reviews and merges it.
167
+ - After each merge that touches a concept's files, a drift run limited to the
168
+ affected concepts, as another draft pull request.
169
+ - Reviews that cite the relevant concepts.
170
+ - Every later coding run for the repository (Recipe B) receives the knowledge
171
+ index and base commit automatically.
172
+
173
+ Run `wardby knowledge check` locally or in CI to validate the bundle. The
174
+ format, the check's codes, and drift behavior are in
175
+ [Architecture knowledge bundles](knowledge.md).
176
+
177
+ ## Recipe B: a builder per language
178
+
179
+ **What it does.** Turns an `@mention` on an issue or pull request into a draft
180
+ pull request. A native router agent reads the request and delegates to a coding
181
+ builder agent. **Trigger:** the router is linked with `mention`; only people with
182
+ write access to the repository can start it.
183
+
184
+ ### The MCP ask
185
+
186
+ > For `your-org/your-repo`, create a Codex coding agent called `<repo>-builder` with a
187
+ > $5 per-run budget and a 30 minute timeout, starting from the default branch.
188
+ > Allow it to install these packages from the registry: (your dependencies).
189
+ > Then create a small native agent called `<repo>-router` with a $6 budget, attach
190
+ > `builder` to it as a sub-agent named `builder`, and link it to the repository
191
+ > with the `mention` trigger. The router should ask for details when a request is
192
+ > unclear and otherwise delegate one precise task to the builder. Never merge
193
+ > anything.
194
+
195
+ Pick the language section below for the toolchain and package settings.
196
+
197
+ ### Common configuration
198
+
199
+ <details>
200
+ <summary>Router (native agent)</summary>
201
+
202
+ | Setting | Value |
203
+ | ----------- | ------------------------------------------------------------------------------------------------------ |
204
+ | `name` | `<repo>-router` |
205
+ | `kind` | `native` |
206
+ | `model` | a small fast model, for example `claude-haiku-4-5` |
207
+ | `budgetUsd` | The builder's budget plus a little: the run tree shares one budget |
208
+ | Sub-agent | `attach_subagent` with `parentAgentId` the router, `childAgentId` the builder, `boundName: "builder"` |
209
+ | Link | `link_repository` with `access: "write"`, `triggers: ["mention"]` (one `mention` agent per repository) |
210
+
211
+ ```json
212
+ {
213
+ "agentId": "<router agent id>",
214
+ "repository": "your-org/your-repo",
215
+ "access": "write",
216
+ "triggers": ["mention"]
217
+ }
218
+ ```
219
+
220
+ System prompt:
221
+
222
+ The prompt is published once, in the [builder-agent help article](../help/builder-agent.md#router-prompt). Copy it unchanged as the agent's `systemPrompt`.
223
+
224
+ The router's final reply is posted where the mention was, so never instruct it
225
+ to include secrets or internal details. See
226
+ [What the mention agent receives](code-review-agents.md#what-the-mention-agent-receives).
227
+
228
+ </details>
229
+
230
+ <details>
231
+ <summary>Builder (coding agent) fields that matter</summary>
232
+
233
+ | Field (`codingProfile`) | What to set |
234
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
235
+ | `model` (agent field) | A capable coding model the chosen provider supports, for example `gpt-5.6-terra` with `codex` or `claude-sonnet-5` with `claude-code`; a mismatch is refused |
236
+ | `provider` | `codex` or `claude-code`; the agent's `model` must be one that provider supports |
237
+ | `repository` | `your-org/your-repo`; your linked GitHub account needs write access |
238
+ | `baseRef` | The branch runs start from, usually your default branch |
239
+ | `toolchain` | `node` or `node-python` (per language below) |
240
+ | `toolchainVersion` | `"3.12"` for `node-python`; omit for `node` |
241
+ | `packageAllowlist` | Top-level packages per ecosystem (`npm`, `pypi`). Needs `packages:approve` or `agents:admin` |
242
+ | `packagePolicy` | Optional `minReleaseAgeDays` (0 to 30) |
243
+ | `services` | Catalog service names the agent may start, for example `["postgres"]`; see [Services](coding-services.md) |
244
+ | `protectedPaths` | Globs a run may not change, for example `[".github/**", "CODEOWNERS"]`. `.wardby/**` is always protected except `.wardby/services.yaml` |
245
+ | `timeoutSec` | 60 to 7200; for example `1800` |
246
+ | `workerImageRef` | Digest-pinned custom image; needs `agents:admin` (see "Other languages") |
247
+ | `defaultTask` | Needed only to schedule the agent |
248
+ | Agent `budgetUsd` | Per-run budget, reserved at dispatch, for example `5` |
249
+
250
+ The agent's `systemPrompt` is placed ahead of each request as standing
251
+ instructions. The template below is generic.
252
+
253
+ </details>
254
+
255
+ <details>
256
+ <summary>Builder system prompt template</summary>
257
+
258
+ The prompt is published once, in the [builder-agent help article](../help/builder-agent.md#builder-prompt), so this page cannot drift from it. Copy it unchanged as the agent's `systemPrompt`.
259
+
260
+ Adjust the numbered rules to your project; keep rules 1, 5, and 6.
261
+
262
+ </details>
263
+
264
+ Package error codes are in [Installing packages in coding runs](coding-packages.md).
265
+ Make sure the repository's `AGENTS.md` lists the test and lint commands, because
266
+ the builder takes them from there.
267
+
268
+ ### Node / TypeScript
269
+
270
+ Use the stock worker image: `toolchain: "node"`, no `toolchainVersion`. The
271
+ agent runs `npm ci` or `npm install` through the registry proxy, so enable the
272
+ packages your project needs (top-level entries only; the dependency graph is
273
+ added automatically):
274
+
275
+ ```json
276
+ {
277
+ "provider": "codex",
278
+ "repository": "your-org/your-repo",
279
+ "baseRef": "main",
280
+ "toolchain": "node",
281
+ "timeoutSec": 1800,
282
+ "packageAllowlist": {
283
+ "npm": ["react@^19", "vitest", "@testing-library/*"]
284
+ },
285
+ "packagePolicy": { "minReleaseAgeDays": 3 },
286
+ "protectedPaths": [".github/**", "CODEOWNERS"]
287
+ }
288
+ ```
289
+
290
+ Test commands come from `AGENTS.md` (for example `npm test` and `npm run lint`).
291
+ Lockfile installs are verified against the registry before npm runs; see
292
+ [Installing packages in coding runs](coding-packages.md).
293
+
294
+ ### Python
295
+
296
+ Use the `node-python` toolchain with version `3.12`, which adds Python 3 with
297
+ `pytest` and `ruff` next to Node. Pip installs go through the registry proxy
298
+ into a virtual environment, and only wheels are served (source distributions are
299
+ refused), so allow packages that publish wheels. Extras such as `[binary]` are not accepted in an allowlist entry; list the wheel package's own name instead (`psycopg-binary`, not `psycopg[binary]`):
300
+
301
+ ```json
302
+ {
303
+ "provider": "codex",
304
+ "repository": "your-org/your-repo",
305
+ "baseRef": "main",
306
+ "toolchain": "node-python",
307
+ "toolchainVersion": "3.12",
308
+ "timeoutSec": 1800,
309
+ "packageAllowlist": {
310
+ "pypi": ["flask>=3", "sqlalchemy>=2", "psycopg-binary>=3"]
311
+ },
312
+ "services": ["postgres"]
313
+ }
314
+ ```
315
+
316
+ `services` is optional. When the tests need a database, commit
317
+ `.wardby/services.yaml` to the base branch:
318
+
319
+ ```yaml
320
+ services:
321
+ postgres: "16"
322
+ ```
323
+
324
+ Each run then gets a fresh, empty PostgreSQL instance and a `DATABASE_URL`
325
+ variable; say so in `AGENTS.md` so tests read it. See
326
+ [Services for coding runs](coding-services.md) for the catalog, variables, and
327
+ errors. For Claude Code on `node-python`, the operator also sets
328
+ `CODING_CLAUDE_TOOL_RUNNER_IMAGE_NODE_PYTHON_3_12` (see
329
+ [Coding-agent setup](coding-agent-setup.md)).
330
+
331
+ ### Other languages (Go, Java, Rust, ...)
332
+
333
+ Wardby ships worker images only for `node` and `node-python`. For any other
334
+ toolchain, build your own image on Wardby's driver base image and point the
335
+ agent at it with `workerImageRef`, a digest-pinned reference (a mutable tag is
336
+ rejected). Setting it needs the `agents:admin` scope and the admin role. The
337
+ Dockerfile shape, the driver image, and what Wardby does and does not verify are
338
+ in [Bring-your-own worker images](coding-worker-byo-images.md).
339
+
340
+ ```json
341
+ {
342
+ "provider": "codex",
343
+ "repository": "your-org/your-repo",
344
+ "baseRef": "main",
345
+ "toolchain": "node",
346
+ "workerImageRef": "registry.example.com/your-org/worker-go@sha256:<64 hex>",
347
+ "timeoutSec": 1800
348
+ }
349
+ ```
350
+
351
+ `toolchain` is still required; the worker image's own toolchain is what runs.
352
+
353
+ What the package registry covers: only **npm and PyPI** are mediated. A Go,
354
+ Maven, Cargo, or other ecosystem has no registry proxy, and the worker has no
355
+ direct network access, so those dependencies must be baked into your image or
356
+ already vendored in the repository. The registry still applies to any npm or
357
+ pip use inside the same run, and `packageAllowlist` has no entry for other
358
+ ecosystems. If services are allowed, the image must be built on driver v11 or
359
+ later.
360
+
361
+ ### Together with Recipe A
362
+
363
+ Coding runs automatically receive the repository's knowledge index and base
364
+ commit when `docs/knowledge/index.md` exists on the base branch
365
+ ([how coding runs use the bundle](knowledge.md#how-coding-runs-use-the-bundle)),
366
+ so the builder works from recorded pitfalls and invariants. Recipe A keeps that
367
+ bundle current.
368
+
369
+ ### What it produces
370
+
371
+ A mention from someone with write access gets a "Working on it" status comment
372
+ from the App. The router either asks a question or delegates, the builder
373
+ pushes a unique branch and opens at most one draft pull request, and the App
374
+ edits the status comment with the pull request link or the failure. A person
375
+ reviews and merges; Wardby never merges for you. A later mention on that pull
376
+ request continues the same branch.
377
+
378
+ ## Next steps
379
+
380
+ - [Architecture knowledge bundles](knowledge.md)
381
+ - [Code-review agents](code-review-agents.md)
382
+ - [Coding-agent setup](coding-agent-setup.md)
383
+ - [Models and pricing](models.md)
@@ -136,6 +136,14 @@ PR description:
136
136
  the same GitHub App that receives the mention. A router agent that
137
137
  delegates coding work can pass that run id on so the existing branch and
138
138
  PR are continued rather than a new one being opened.
139
+ - Before the mention runs, wardby checks that the marker's run is one this
140
+ deployment recorded, in the same repository, and that it opened this PR.
141
+ When it is not (most often because another wardby deployment sharing the
142
+ same GitHub App opened the PR), no run starts: the App replies that this
143
+ deployment cannot continue the PR, so ask the deployment that opened it.
144
+ If a router agent passes a `continuePriorRun` id that this deployment
145
+ cannot continue, the delegation returns a `continuation_refused` tool
146
+ error to the agent instead of failing its run.
139
147
  - The header reads `[GitHub issue #<n>]` on an issue. For a mention inside an
140
148
  inline review thread, the `Requested by` line ends with
141
149
  `(in review thread <id>)`.
@@ -273,8 +281,10 @@ with:
273
281
  below) — generate it with `openssl rand -hex 32` or similar; the ingress
274
282
  endpoint answers 404 until this is set.
275
283
  - **Subscribe to events**: Pull request, Issue comment, Pull request review
276
- comment, Check run, and Issues (needed for mentions in a newly opened or
277
- edited issue; without it only comment mentions are seen).
284
+ comment, Check run, Issues (needed for mentions in a newly opened or
285
+ edited issue; without it only comment mentions are seen), and Push (needed
286
+ for the `push` trigger, which starts merge-watcher agents; it is its own
287
+ checkbox, separate from the others, and must be ticked explicitly).
278
288
  - **Repository permissions**:
279
289
 
280
290
  | Permission | Access |
@@ -386,6 +396,23 @@ review command:
386
396
  }
387
397
  ```
388
398
 
399
+ **A merge watcher**, which starts on every merge to the repository's default
400
+ branch (see [Drift runs on merge](knowledge.md#drift-runs-on-merge)):
401
+
402
+ ```json
403
+ {
404
+ "agentId": "<agent-id>",
405
+ "repository": "owner/name",
406
+ "access": "write",
407
+ "triggers": ["push"]
408
+ }
409
+ ```
410
+
411
+ The `push` trigger is for native agents only and takes no `checkName`. Unlike
412
+ `mention`, several agents may hold it on one repository, but one watcher per
413
+ repository is the recommended shape. Only pushes to the default branch start a
414
+ run; tags, other branches, and branch deletions are ignored.
415
+
389
416
  Only one agent per repository may hold the `mention` trigger, and only one
390
417
  link per repository may use a given `checkName` (whatever its triggers; the
391
418
  database enforces it); linking a second agent the same way returns a 409
@@ -131,6 +131,9 @@ terminal cleanup; investigate any retained resource as a cleanup failure.
131
131
 
132
132
  See [release verification](release-verification.md) for the complete gate.
133
133
 
134
+ If the repository has `docs/knowledge/index.md`, every coding run's prompt
135
+ includes it. See [Architecture knowledge bundles](knowledge.md).
136
+
134
137
  ## Budgets
135
138
 
136
139
  A coding run's budget is reserved when it is dispatched: the agent's own
@@ -125,7 +125,9 @@ deeply to process is refused with `request_nesting_too_deep`.
125
125
 
126
126
  - **Anthropic Messages** (`parseAnthropicRequest`): a fixed set of keys,
127
127
  text/`tool_use`/`tool_result`/thinking blocks, exactly the two Wardby tool
128
- names, and the reviewed beta values.
128
+ names, the reviewed beta values, the thinking mode the run's model catalog
129
+ entry names, and only effort levels that entry lists in `efforts` (top-level,
130
+ or on an effort-only system message for models that change effort per turn).
129
131
  - **OpenAI Responses** (`parseOpenAiRequest`), built from what the pinned
130
132
  Codex CLI actually sends (recorded in
131
133
  `src/providers/coding-proxy/fixtures/codex-<version>-responses-requests.json`
@@ -166,10 +168,37 @@ deeply to process is refused with `request_nesting_too_deep`.
166
168
  forces `store: false` and `background: false` and adds a
167
169
  `max_output_tokens` ceiling when Codex omits it.
168
170
 
169
- Upgrading the pinned `@openai/codex-sdk` means re-recording that fixture
170
- against a local fake upstream and rerunning the compatibility test. A Codex
171
- release that sends a new key or item type fails closed at the proxy rather
172
- than silently widening what reaches OpenAI.
171
+ A Codex release that sends a new key or item type fails closed at the proxy
172
+ rather than silently widening what reaches OpenAI. Upgrading the pinned
173
+ `@openai/codex-sdk` is therefore one command plus a review:
174
+
175
+ 1. Change the pin in `src/coding-worker/package.json` (a dependency bot's
176
+ pull request does this). Until the fixture is re-recorded, the "pinned
177
+ Codex version" test fails with `Codex SDK bump detected (...)`.
178
+ 2. On that branch, run `npm run codex:rerecord` on a machine where npm
179
+ installs the host's Codex binary. It sets the root devDependency
180
+ `@openai/codex-sdk` to the worker's pin and installs it, drives the pinned
181
+ Codex CLI through a fixed set of scenarios (responses-lite and classic tool
182
+ layouts, code-mode `exec` with `view_image` and `apply_patch`, namespaced
183
+ tool calls, a spawned sub-agent, local context compaction) against a local
184
+ fake of the proxy's `/v1/responses` endpoint — nothing is sent to OpenAI —
185
+ and writes `codex-<version>-responses-requests.json`, replacing the
186
+ previous version's fixture. Paths, ids, timestamps and long prompt texts
187
+ are normalized so a re-record of the same version is byte-identical. It
188
+ then runs the compatibility test (the real Codex through the real proxy)
189
+ and the proxy's fixture-replay tests, and prints a request-shape diff
190
+ against the previous fixture: new or removed top-level keys, input item
191
+ and content types, tool types, `include`/`reasoning`/`text`/`tool_choice`/
192
+ `service_tier` values and `client_metadata` keys.
193
+ 3. Review that diff. If the tests pass and the diff is empty or shows only
194
+ shapes the allowlist already accepts, commit the new fixture with
195
+ `package.json` and `package-lock.json`. If the proxy refuses a request
196
+ (an `openai_*_not_allowed` code in the test output), do not widen the
197
+ allowlist to make it pass: first find out what the new key, item, tool
198
+ type or value does (Codex's changelog and source) and whether it can
199
+ reach anything outside the worker or bill outside the metered tokens,
200
+ then widen `parseOpenAiRequest` only for what that review accepts, and
201
+ document it in the list above.
173
202
 
174
203
  The proxy also binds a second listener, the **deny port** (`8788`,
175
204
  `CODING_PROXY_DENY_PORT`), which serves nothing: it accepts a connection,
@@ -413,6 +442,11 @@ Operating the queue across replicas:
413
442
  (`--depth 1`); the worker never receives Git history and finalization needs
414
443
  only the base commit.
415
444
 
445
+ Every wardby process also polls the model catalog on
446
+ `WARDBY_MODEL_CATALOG_REFRESH_SECONDS` (default `45`), which decides whether
447
+ a coding run's model is still available and how it is priced at dispatch; see
448
+ [Models and pricing](models.md).
449
+
416
450
  The GitHub adapter requires `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY`; the
417
451
  App installation is checked while preparing the workspace, before the
418
452
  billable proxy session is created. Upstream keys remain behind
@@ -40,7 +40,7 @@ Install and authenticate:
40
40
 
41
41
  - Google Cloud CLI (`gcloud`)
42
42
  - Terraform 1.10 or newer
43
- - Docker with `linux/amd64` build support
43
+ - Docker with the `buildx` plugin and `linux/amd64` build support
44
44
  - `kubectl`
45
45
  - Helm 3 or later (installs External Secrets Operator)
46
46
  - Node.js 24 and npm
@@ -255,16 +255,20 @@ through the Cloud SQL Auth Proxy, via Workload Identity from one Kubernetes
255
255
  service account. What each may do inside the database comes from a `NOLOGIN`
256
256
  group role in `deploy/gke/database-grants.sql`:
257
257
 
258
- | Workload | Google service account | Kubernetes service account | May do |
259
- | ------------- | ------------------------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
260
- | 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 |
261
- | Coding proxy | `<name_prefix>-proxy` | `wardby-coding-proxy` | `wardby_proxy`: only its budget ledger — `CodingProxySession`/`CodingProxyRequest`, plus update `tokensIn`, `tokensOut` and `costUsd` on `Run`, and read only its `id` |
262
- | 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 |
258
+ | Workload | Google service account | Kubernetes service account | May do |
259
+ | ------------- | ------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
260
+ | 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 |
261
+ | 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` |
262
+ | 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 |
263
263
 
264
264
  `deploy/gke/bootstrap-database-iam.sh` applies the grants as the built-in
265
265
  owner, from a short-lived Job inside the cluster. Run it whenever
266
- `database-grants.sql` changes, and as part of the orders below. The grants run
267
- in one transaction, so a statement the database refuses leaves nothing applied.
266
+ `database-grants.sql` changes, before deploying the release that needs the new
267
+ grants (`bootstrap-database-iam.sh --check`, then `bootstrap-database-iam.sh`,
268
+ then `up.sh`), and as part of the orders below. A release deployed ahead of its
269
+ grants fails with "permission denied" wherever it uses one it doesn't have yet.
270
+ The grants run in one transaction, so a statement the database refuses leaves
271
+ nothing applied.
268
272
 
269
273
  The built-in owner is not a Terraform resource: `bootstrap-database-iam.sh`
270
274
  creates it if it's missing, sets a one-time password on it through the Cloud
@@ -300,6 +304,12 @@ own role, for every privilege `database-grants.sql` gives `wardby_proxy`
300
304
  grants instead of letting the proxy fail registry requests with "permission
301
305
  denied".
302
306
 
307
+ After upgrading an existing deployment to a release with cost attribution,
308
+ re-run `bootstrap-database-iam.sh` so the coding proxy can record per-model
309
+ usage for coding runs (used by the `cost_report` tool's `model` grouping).
310
+ Until then coding runs still work, but their per-model breakdown isn't
311
+ recorded.
312
+
303
313
  `bootstrap-database-iam.sh --check` runs the grants inside a transaction that
304
314
  is then rolled back, and reports success or the exact statement the database
305
315
  refused, without changing anything. Run it before the real run on a live
@@ -397,9 +407,10 @@ server answers `415`, because it checks the content type before the token.
397
407
  Create the first self-hosted login credential. It is printed once.
398
408
  `--role admin` makes this operator account an admin. Only admins can use all
399
409
  the privileged operations: `make_owner`, BYO `workerImageRef`, package
400
- approval, and service catalog changes. A `package-approver` can approve
401
- packages only, and a `service-manager` can change the service catalog only.
402
- Users created without `--role` have no roles. See
410
+ approval, service catalog changes, and model catalog changes. A
411
+ `package-approver` can approve packages only, a `service-manager` can change
412
+ the service catalog only, and a `model-manager` can change the model catalog
413
+ only. Users created without `--role` have no roles. See
403
414
  [roles and privileged operations](security-deployment.md#roles-and-privileged-operations).
404
415
 
405
416
  ```sh
@@ -443,6 +454,12 @@ images, pushes them, substitutes immutable digests, leaves Secret Manager values
443
454
  as they are, waits for rollouts, and then checks the public endpoint: discovery
444
455
  must answer `200` and an unauthenticated MCP request `401`, or the deploy fails.
445
456
 
457
+ `up.sh` builds every image in one `docker buildx bake` run
458
+ (`deploy/gke/docker-bake.hcl`), so Docker's `buildx` plugin is required (Docker
459
+ Desktop includes it). The images build concurrently, and the stages that only
460
+ compile JavaScript run on your machine's own architecture, so building the
461
+ `linux/amd64` images from an arm64 machine emulates only what actually ships.
462
+
446
463
  A control-plane restart is designed not to drop requests, at the cost of a
447
464
  slower rollout. A new pod must stay Ready for three minutes before the old one
448
465
  is retired, because the load balancer can take well over a minute to start