@open-mercato/cezar 0.9.3 → 0.10.0-pr892.1298

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 (253) hide show
  1. package/README.md +165 -36
  2. package/dist/agent-config/account-identity.d.ts +44 -0
  3. package/dist/agent-config/account-identity.js +128 -0
  4. package/dist/agent-config/account-identity.js.map +1 -0
  5. package/dist/agent-config/catalog.d.ts +8 -0
  6. package/dist/agent-config/catalog.js +18 -0
  7. package/dist/agent-config/catalog.js.map +1 -1
  8. package/dist/agent-config/model-settings/claude.d.ts +2 -0
  9. package/dist/agent-config/model-settings/claude.js +11 -0
  10. package/dist/agent-config/model-settings/claude.js.map +1 -0
  11. package/dist/agent-config/model-settings/codex.d.ts +2 -0
  12. package/dist/agent-config/model-settings/codex.js +16 -0
  13. package/dist/agent-config/model-settings/codex.js.map +1 -0
  14. package/dist/agent-config/model-settings/opencode.d.ts +2 -0
  15. package/dist/agent-config/model-settings/opencode.js +8 -0
  16. package/dist/agent-config/model-settings/opencode.js.map +1 -0
  17. package/dist/agent-config/model-settings/pi.d.ts +12 -0
  18. package/dist/agent-config/model-settings/pi.js +18 -0
  19. package/dist/agent-config/model-settings/pi.js.map +1 -0
  20. package/dist/agent-config/model-settings/shared.d.ts +9 -0
  21. package/dist/agent-config/model-settings/shared.js +93 -0
  22. package/dist/agent-config/model-settings/shared.js.map +1 -0
  23. package/dist/agent-config/model-settings/types.d.ts +9 -0
  24. package/dist/agent-config/model-settings/types.js +2 -0
  25. package/dist/agent-config/model-settings/types.js.map +1 -0
  26. package/dist/agent-config/models.d.ts +9 -0
  27. package/dist/agent-config/models.js +32 -0
  28. package/dist/agent-config/models.js.map +1 -0
  29. package/dist/agent-config/service.js +4 -4
  30. package/dist/agent-config/service.js.map +1 -1
  31. package/dist/automations/types.d.ts +4 -0
  32. package/dist/automations/types.js +2 -1
  33. package/dist/automations/types.js.map +1 -1
  34. package/dist/config.d.ts +10 -1
  35. package/dist/config.js +48 -5
  36. package/dist/config.js.map +1 -1
  37. package/dist/contract/agent-config.d.ts +2 -0
  38. package/dist/contract/agent-profiles.d.ts +347 -0
  39. package/dist/contract/automations.d.ts +24 -0
  40. package/dist/contract/events.d.ts +59 -0
  41. package/dist/contract/github.d.ts +88 -0
  42. package/dist/contract/health.d.ts +5 -1
  43. package/dist/contract/index.d.ts +1 -0
  44. package/dist/contract/index.js +981 -544
  45. package/dist/contract/projects.d.ts +33 -5
  46. package/dist/contract/runs.d.ts +247 -0
  47. package/dist/contract/skills.d.ts +7 -0
  48. package/dist/contract/workflows.d.ts +6 -0
  49. package/dist/contract/workspace.d.ts +137 -2
  50. package/dist/core/agent-env.js +41 -16
  51. package/dist/core/agent-env.js.map +1 -1
  52. package/dist/core/agent-model-policy.d.ts +10 -0
  53. package/dist/core/agent-model-policy.js +36 -0
  54. package/dist/core/agent-model-policy.js.map +1 -0
  55. package/dist/core/agent-profiles.d.ts +62 -0
  56. package/dist/core/agent-profiles.js +90 -0
  57. package/dist/core/agent-profiles.js.map +1 -0
  58. package/dist/core/agent-runner.d.ts +37 -6
  59. package/dist/core/agent-runner.js +35 -3
  60. package/dist/core/agent-runner.js.map +1 -1
  61. package/dist/core/backend-detect.d.ts +5 -5
  62. package/dist/core/backend-detect.js +44 -7
  63. package/dist/core/backend-detect.js.map +1 -1
  64. package/dist/core/claude-cli-runner.js +10 -5
  65. package/dist/core/claude-cli-runner.js.map +1 -1
  66. package/dist/core/codex-app-server-runner.js +13 -3
  67. package/dist/core/codex-app-server-runner.js.map +1 -1
  68. package/dist/core/codex-app-server-transport.js +7 -2
  69. package/dist/core/codex-app-server-transport.js.map +1 -1
  70. package/dist/core/model-identity.d.ts +23 -11
  71. package/dist/core/model-identity.js +41 -24
  72. package/dist/core/model-identity.js.map +1 -1
  73. package/dist/core/model-presets.d.ts +8 -2
  74. package/dist/core/model-presets.js +51 -8
  75. package/dist/core/model-presets.js.map +1 -1
  76. package/dist/core/opencode-model-catalog.d.ts +32 -0
  77. package/dist/core/opencode-model-catalog.js +153 -0
  78. package/dist/core/opencode-model-catalog.js.map +1 -0
  79. package/dist/core/opencode-server-runner.d.ts +2 -0
  80. package/dist/core/opencode-server-runner.js +42 -11
  81. package/dist/core/opencode-server-runner.js.map +1 -1
  82. package/dist/core/pi-runner.d.ts +24 -0
  83. package/dist/core/pi-runner.js +349 -0
  84. package/dist/core/pi-runner.js.map +1 -0
  85. package/dist/core/pi-ui-mapper.d.ts +34 -0
  86. package/dist/core/pi-ui-mapper.js +270 -0
  87. package/dist/core/pi-ui-mapper.js.map +1 -0
  88. package/dist/core/provider-auth.d.ts +95 -3
  89. package/dist/core/provider-auth.js +234 -15
  90. package/dist/core/provider-auth.js.map +1 -1
  91. package/dist/core/provider-availability.d.ts +1 -1
  92. package/dist/core/provider-availability.js +2 -1
  93. package/dist/core/provider-availability.js.map +1 -1
  94. package/dist/core/runner-factory.js +3 -0
  95. package/dist/core/runner-factory.js.map +1 -1
  96. package/dist/core/shell-env.d.ts +28 -0
  97. package/dist/core/shell-env.js +56 -0
  98. package/dist/core/shell-env.js.map +1 -0
  99. package/dist/core/ui-events.d.ts +1 -1
  100. package/dist/core/usage-limit.d.ts +42 -0
  101. package/dist/core/usage-limit.js +209 -0
  102. package/dist/core/usage-limit.js.map +1 -0
  103. package/dist/index.js +3 -2
  104. package/dist/index.js.map +1 -1
  105. package/dist/paths.d.ts +53 -5
  106. package/dist/paths.js +63 -9
  107. package/dist/paths.js.map +1 -1
  108. package/dist/planner.js +6 -0
  109. package/dist/planner.js.map +1 -1
  110. package/dist/release/snapshot.d.ts +13 -2
  111. package/dist/release/snapshot.js +25 -1
  112. package/dist/release/snapshot.js.map +1 -1
  113. package/dist/runs/agent-tmpdir.d.ts +41 -0
  114. package/dist/runs/agent-tmpdir.js +183 -0
  115. package/dist/runs/agent-tmpdir.js.map +1 -0
  116. package/dist/runs/auto-name.js +6 -1
  117. package/dist/runs/auto-name.js.map +1 -1
  118. package/dist/runs/event-history.d.ts +50 -0
  119. package/dist/runs/event-history.js +613 -0
  120. package/dist/runs/event-history.js.map +1 -0
  121. package/dist/runs/run-index.d.ts +19 -0
  122. package/dist/runs/run-index.js +43 -0
  123. package/dist/runs/run-index.js.map +1 -0
  124. package/dist/runs/store.d.ts +78 -19
  125. package/dist/runs/store.js +175 -43
  126. package/dist/runs/store.js.map +1 -1
  127. package/dist/server/forge/github.d.ts +169 -0
  128. package/dist/server/forge/github.js +511 -0
  129. package/dist/server/forge/github.js.map +1 -1
  130. package/dist/server/forge/index.d.ts +9 -0
  131. package/dist/server/forge/index.js +14 -0
  132. package/dist/server/forge/index.js.map +1 -1
  133. package/dist/server/github.d.ts +2 -2
  134. package/dist/server/github.js +1 -1
  135. package/dist/server/github.js.map +1 -1
  136. package/dist/server/open-in-app.d.ts +2 -1
  137. package/dist/server/open-in-app.js +3 -1
  138. package/dist/server/open-in-app.js.map +1 -1
  139. package/dist/server/open-in-terminal.d.ts +46 -1
  140. package/dist/server/open-in-terminal.js +72 -13
  141. package/dist/server/open-in-terminal.js.map +1 -1
  142. package/dist/server/provider-action-gate.js +3 -1
  143. package/dist/server/provider-action-gate.js.map +1 -1
  144. package/dist/server/server.d.ts +2199 -428
  145. package/dist/server/server.js +1171 -139
  146. package/dist/server/server.js.map +1 -1
  147. package/dist/server-install/engine.js +5 -18
  148. package/dist/server-install/engine.js.map +1 -1
  149. package/dist/server-install/steps.js +6 -2
  150. package/dist/server-install/steps.js.map +1 -1
  151. package/dist/skills.js +4 -0
  152. package/dist/skills.js.map +1 -1
  153. package/dist/workflows/run.d.ts +202 -2
  154. package/dist/workflows/run.js +782 -115
  155. package/dist/workflows/run.js.map +1 -1
  156. package/dist/workflows/types.d.ts +3 -0
  157. package/dist/workflows/types.js +11 -2
  158. package/dist/workflows/types.js.map +1 -1
  159. package/dist/workspace/agent-accounts.d.ts +153 -0
  160. package/dist/workspace/agent-accounts.js +304 -0
  161. package/dist/workspace/agent-accounts.js.map +1 -0
  162. package/dist/workspace/agent-profiles.d.ts +78 -0
  163. package/dist/workspace/agent-profiles.js +115 -0
  164. package/dist/workspace/agent-profiles.js.map +1 -0
  165. package/dist/workspace/config.d.ts +19 -1
  166. package/dist/workspace/config.js +56 -2
  167. package/dist/workspace/config.js.map +1 -1
  168. package/dist/workspace/projects-cli.js +54 -4
  169. package/dist/workspace/projects-cli.js.map +1 -1
  170. package/dist/workspace/projects.d.ts +19 -1
  171. package/dist/workspace/projects.js +34 -1
  172. package/dist/workspace/projects.js.map +1 -1
  173. package/dist/workspace/semaphore.d.ts +39 -0
  174. package/dist/workspace/semaphore.js +31 -0
  175. package/dist/workspace/semaphore.js.map +1 -1
  176. package/package.json +3 -3
  177. package/scripts/mock-claude.mjs +20 -0
  178. package/scripts/mock-pi-rpc.mjs +83 -0
  179. package/web/dist/assets/{alert-dialog-V9cigyAO.js → alert-dialog-Byp42_IG.js} +1 -1
  180. package/web/dist/assets/arrow-down-CGDbDYKD.js +1 -0
  181. package/web/dist/assets/arrow-left-ESCjr1Hq.js +1 -0
  182. package/web/dist/assets/centered-state-LfAW-igm.js +43 -0
  183. package/web/dist/assets/chevron-right-Du-P1IUd.js +1 -0
  184. package/web/dist/assets/{collapsible-BlF-7CeC.js → collapsible-CBiiqDJM.js} +1 -1
  185. package/web/dist/assets/{commit-list-D2mKElUx.js → commit-list-6PPve7PE.js} +1 -1
  186. package/web/dist/assets/{compare-variants-CFBY16Rc.js → compare-variants-BDnp6mXJ.js} +1 -1
  187. package/web/dist/assets/{diff-DE6u5dTe.js → diff-_jK0OWpF.js} +2 -2
  188. package/web/dist/assets/{diff-stat-B1j6L7C6.js → diff-stat-CIrTu4Ym.js} +1 -1
  189. package/web/dist/assets/{diff-view-Gb2kk3Le.js → diff-view-COA_5IyY.js} +1 -1
  190. package/web/dist/assets/dropdown-menu-BofYpFFw.js +1 -0
  191. package/web/dist/assets/editable-title-_J0zFDl-.js +1 -0
  192. package/web/dist/assets/{ellipsis-vertical-BbxtXb6s.js → ellipsis-vertical-BeMR-l62.js} +1 -1
  193. package/web/dist/assets/{file-j5O4NryU.js → file-DY996Pee.js} +1 -1
  194. package/web/dist/assets/{folder-w9Lwj9x9.js → folder-NO3Ec-TY.js} +1 -1
  195. package/web/dist/assets/git-toolbar-BqJeUWcD.js +1 -0
  196. package/web/dist/assets/github-C96HPV9E.js +1 -0
  197. package/web/dist/assets/{image-preview-CcFdkZXW.js → image-preview-D9cCDfKQ.js} +1 -1
  198. package/web/dist/assets/index-Bx-grqa9.css +2 -0
  199. package/web/dist/assets/index-DoVvGDfW.js +7 -0
  200. package/web/dist/assets/{markdown-q9lm7kQ2.js → markdown-DDzk11zj.js} +1 -1
  201. package/web/dist/assets/new-task-form-BNLLgC6P.js +1 -0
  202. package/web/dist/assets/pill-CVM1EmV4.js +1 -0
  203. package/web/dist/assets/{project-router-DudOmkHf.js → project-router-LRCtP48W.js} +1 -1
  204. package/web/dist/assets/prompt-templates-DFOvYgtW.js +15 -0
  205. package/web/dist/assets/{refresh-cw-_C2EGJK5.js → refresh-cw-D1ys6QY2.js} +1 -1
  206. package/web/dist/assets/repo-git-CzUnsgWY.js +1 -0
  207. package/web/dist/assets/{run-diff-BLoKEnTx.js → run-diff-BlnqwfSS.js} +2 -2
  208. package/web/dist/assets/run-header-Bn7cN0Z1.js +1 -0
  209. package/web/dist/assets/{search-x-BgxaJgro.js → search-x-D6FSpxId.js} +1 -1
  210. package/web/dist/assets/{skill-empty-hint-D5MOmycv.js → skill-empty-hint-iwpCcqgI.js} +1 -1
  211. package/web/dist/assets/skills-CezbOaol.js +1 -0
  212. package/web/dist/assets/{sparkles-ANSka5bH.js → sparkles-MrQrgCI9.js} +1 -1
  213. package/web/dist/assets/{square-terminal-qojq20cH.js → square-terminal-TTH64lO7.js} +1 -1
  214. package/web/dist/assets/tab-link-FYksz037.js +1 -0
  215. package/web/dist/assets/task-changes-ClWlnzBL.js +1 -0
  216. package/web/dist/assets/{task-commits-yXmDrCoE.js → task-commits-Crbrl86b.js} +1 -1
  217. package/web/dist/assets/{task-files-BDRmCCPN.js → task-files-uSCWyD0-.js} +2 -2
  218. package/web/dist/assets/task-thread-DPmamBA1.js +9 -0
  219. package/web/dist/assets/{textarea-DVO7pg8Y.js → textarea-B9Ahj4E4.js} +1 -1
  220. package/web/dist/assets/thread-loading-BH_ypQoy.js +1 -0
  221. package/web/dist/assets/{trash-2-DKcnmg6e.js → trash-2-D8S3V3fu.js} +1 -1
  222. package/web/dist/assets/{triangle-alert-CPUEVSZ3.js → triangle-alert-bB7p9n5E.js} +1 -1
  223. package/web/dist/assets/{upload-D5Jrq7QK.js → upload-Bd5oRLPV.js} +1 -1
  224. package/web/dist/assets/{use-desktop-CXae6uyk.js → use-desktop-BNvbRBeZ.js} +1 -1
  225. package/web/dist/assets/{use-submit-shortcut-RKJLKdsW.js → use-submit-shortcut-B-xhu4Bf.js} +1 -1
  226. package/web/dist/assets/utils-BhpbVMwN.js +64 -0
  227. package/web/dist/assets/{workflows-CGyTdyds.js → workflows-RmfbM9Vy.js} +3 -3
  228. package/web/dist/assets/{zoomable-image-hcqwUIlQ.js → zoomable-image-BCW6ZBV0.js} +1 -1
  229. package/web/dist/index.html +24 -23
  230. package/web/dist/assets/arrow-down-DflHdNlN.js +0 -1
  231. package/web/dist/assets/arrow-left-IIL4uR-C.js +0 -1
  232. package/web/dist/assets/centered-state-BkAJVLJE.js +0 -43
  233. package/web/dist/assets/chevron-right-CxAoD1eD.js +0 -1
  234. package/web/dist/assets/circle-check-CdwcIbkx.js +0 -1
  235. package/web/dist/assets/circle-x-Cnc43xJ2.js +0 -1
  236. package/web/dist/assets/dropdown-menu-Ns-rY6sm.js +0 -1
  237. package/web/dist/assets/editable-title-BGuiDxFT.js +0 -1
  238. package/web/dist/assets/git-pull-request-DlSop3Ch.js +0 -1
  239. package/web/dist/assets/git-toolbar-BdJ8XSxI.js +0 -1
  240. package/web/dist/assets/github-CCLn2OAU.js +0 -1
  241. package/web/dist/assets/index-BmHHLbwc.js +0 -6
  242. package/web/dist/assets/index-u8OAnq0r.css +0 -2
  243. package/web/dist/assets/new-task-form-BuYxAWN7.js +0 -1
  244. package/web/dist/assets/pill-t97MvPW_.js +0 -1
  245. package/web/dist/assets/prompt-templates-C5iO3Lda.js +0 -15
  246. package/web/dist/assets/repo-git-DqQzj33d.js +0 -1
  247. package/web/dist/assets/run-header-Dho4eurS.js +0 -1
  248. package/web/dist/assets/skills-B5g064CC.js +0 -1
  249. package/web/dist/assets/tab-link-CIcwFJtC.js +0 -1
  250. package/web/dist/assets/task-changes-yRfsEsnh.js +0 -1
  251. package/web/dist/assets/task-thread-C9AnIz4Z.js +0 -9
  252. package/web/dist/assets/thread-loading-DJDl701Z.js +0 -1
  253. package/web/dist/assets/utils-Wtkd5E6j.js +0 -64
@@ -6,6 +6,37 @@ var runEventSchema = z.looseObject({
6
6
  stepId: z.string().optional(),
7
7
  type: z.string()
8
8
  });
9
+ var RUN_HISTORY_PAGE_ITEMS = 100;
10
+ var runIdParamSchema = z.object({
11
+ id: z.string().min(1).max(128).regex(/^[A-Za-z0-9._-]+$/)
12
+ });
13
+ var runHistoryCursorSchema = z.string().min(1).max(2048);
14
+ var runHistoryQuerySchema = z.object({
15
+ cursor: runHistoryCursorSchema.optional()
16
+ });
17
+ var runEventsQuerySchema = z.object({
18
+ cursor: runHistoryCursorSchema.optional(),
19
+ afterSeq: z.coerce.number().int().nonnegative().optional()
20
+ });
21
+ var runHistoryEventSchema = z.object({
22
+ seq: z.number(),
23
+ ts: z.string(),
24
+ stepId: z.string().optional(),
25
+ type: z.string()
26
+ }).catchall(z.any());
27
+ var runHistoryPageSchema = z.object({
28
+ events: z.array(runHistoryEventSchema),
29
+ itemCount: z.number().int().min(0).max(RUN_HISTORY_PAGE_ITEMS),
30
+ olderCursor: runHistoryCursorSchema.optional(),
31
+ newerCursor: runHistoryCursorSchema.optional(),
32
+ liveCursor: runHistoryCursorSchema,
33
+ asOfSeq: z.number().int().nonnegative(),
34
+ hasOlder: z.boolean()
35
+ });
36
+ var runHistoryContextSchema = z.object({
37
+ contextEvents: z.array(runHistoryEventSchema),
38
+ asOfSeq: z.number().int().nonnegative()
39
+ });
9
40
  var checkoutProgressEventSchema = z.object({
10
41
  checkoutId: z.string().optional(),
11
42
  name: z.string(),
@@ -16,14 +47,14 @@ var checkoutProgressEventSchema = z.object({
16
47
 
17
48
  // ../contract/src/health.ts
18
49
  import { z as z2 } from "zod";
19
- var runnerSchema = z2.enum(["claude", "codex", "opencode"]);
50
+ var runnerSchema = z2.enum(["claude", "codex", "opencode", "pi"]);
20
51
  var repoInfoSchema = z2.object({
21
52
  root: z2.string(),
22
53
  branch: z2.string(),
23
54
  remote: z2.string().optional()
24
55
  });
25
56
  var backendCheckSchema = z2.object({
26
- name: z2.enum(["claude", "codex", "opencode", "gh", "git"]),
57
+ name: z2.enum(["claude", "codex", "opencode", "pi", "gh", "git"]),
27
58
  available: z2.boolean(),
28
59
  version: z2.string().optional(),
29
60
  hint: z2.string().optional()
@@ -88,78 +119,268 @@ var healthResponseSchema = z2.object({
88
119
  });
89
120
 
90
121
  // ../contract/src/runs.ts
91
- import { z as z4 } from "zod";
122
+ import { z as z5 } from "zod";
92
123
 
93
- // ../contract/src/workflows.ts
124
+ // ../contract/src/github.ts
94
125
  import { z as z3 } from "zod";
95
- var workflowStepDefSchema = z3.object({
96
- id: z3.string().min(1),
97
- name: z3.string().optional(),
126
+ var checksGlyphSchema = z3.enum(["passing", "failing", "pending"]).nullable();
127
+ var githubItemSchema = z3.object({
128
+ kind: z3.enum(["issue", "pr"]),
129
+ number: z3.number(),
130
+ title: z3.string(),
131
+ author: z3.string(),
132
+ createdAt: z3.string(),
133
+ labels: z3.array(z3.string()),
134
+ body: z3.string(),
135
+ url: z3.string(),
136
+ comments: z3.number(),
137
+ /** PRs only. */
138
+ isDraft: z3.boolean().optional(),
139
+ additions: z3.number().optional(),
140
+ deletions: z3.number().optional(),
141
+ checks: checksGlyphSchema.optional()
142
+ });
143
+ var githubDataSchema = z3.object({
144
+ available: z3.boolean(),
145
+ /** Why it is unavailable (`gh` missing, no remote, offline…). Never an error — a hint. */
146
+ reason: z3.string().optional(),
147
+ /** owner/name, when known. */
148
+ repo: z3.string().optional(),
149
+ syncedAt: z3.string().optional(),
150
+ issues: z3.array(githubItemSchema),
151
+ prs: z3.array(githubItemSchema),
152
+ /** Repo-wide label name → 6-hex color (no `#`); lets chips tint like GitHub. Additive. */
153
+ labelColors: z3.record(z3.string(), z3.string()).optional()
154
+ });
155
+ var githubChecksDataSchema = z3.discriminatedUnion("available", [
156
+ z3.object({
157
+ available: z3.literal(true),
158
+ checks: z3.record(z3.number(), checksGlyphSchema)
159
+ }),
160
+ z3.object({
161
+ available: z3.literal(false),
162
+ reason: z3.string()
163
+ })
164
+ ]);
165
+ var referenceStatusSchema = z3.enum([
166
+ "draft",
167
+ "review-required",
168
+ "changes-requested",
169
+ "checks-pending",
170
+ "checks-failing",
171
+ "ready",
172
+ "merged",
173
+ "closed",
174
+ "open",
175
+ "completed",
176
+ "not-planned"
177
+ ]);
178
+ var recheckAfterMsSchema = z3.number().nullable();
179
+ var REFERENCE_STATUS_MAX = 100;
180
+ var githubRefStatusDataSchema = z3.discriminatedUnion("available", [
181
+ z3.object({
182
+ available: z3.literal(true),
183
+ prs: z3.record(z3.number(), referenceStatusSchema),
184
+ issues: z3.record(z3.number(), referenceStatusSchema),
185
+ recheckAfterMs: recheckAfterMsSchema
186
+ }),
187
+ z3.object({
188
+ available: z3.literal(false),
189
+ reason: z3.string(),
190
+ recheckAfterMs: recheckAfterMsSchema
191
+ })
192
+ ]);
193
+ var githubCommentSchema = z3.object({
194
+ id: z3.number(),
195
+ /** Author login, `'?'` fallback when gh omits the user. */
196
+ author: z3.string(),
197
+ avatarUrl: z3.string().optional(),
198
+ createdAt: z3.string(),
199
+ body: z3.string(),
200
+ kind: z3.enum(["comment", "review"]),
201
+ /** Reviews only — drives the state chip. */
202
+ reviewState: z3.enum(["approved", "changes_requested", "commented", "dismissed"]).optional(),
203
+ url: z3.string()
204
+ });
205
+ var githubTimelineEventKindSchema = z3.enum([
206
+ "committed",
207
+ "labeled",
208
+ "unlabeled",
209
+ "assigned",
210
+ "unassigned",
211
+ "merged",
212
+ "closed",
213
+ "reopened",
214
+ "head_ref_force_pushed",
215
+ "cross-referenced",
216
+ "renamed"
217
+ ]);
218
+ var githubTimelineEventSchema = z3.object({
219
+ id: z3.string(),
220
+ kind: githubTimelineEventKindSchema,
221
+ /** Login — or the git author name for `committed`, which carries no GitHub actor. */
222
+ actor: z3.string(),
223
+ /** Absent for `committed`. */
224
+ avatarUrl: z3.string().optional(),
225
+ createdAt: z3.string(),
226
+ url: z3.string().optional(),
227
+ /** `committed` — full 40-char SHA. */
228
+ sha: z3.string().optional(),
229
+ /** `committed` — first line, capped at 120 chars. */
230
+ message: z3.string().optional(),
231
+ /** `committed` — **absent** (lookup failed/skipped) and **`null`** (no CI configured) both
232
+ * render no glyph, but stay distinct values. */
233
+ checks: checksGlyphSchema.optional(),
234
+ label: z3.object({ name: z3.string(), color: z3.string().optional() }).optional(),
235
+ /** `assigned`/`unassigned` login, or the new title for `renamed`. */
236
+ subject: z3.string().optional(),
237
+ refNumber: z3.number().optional(),
238
+ refTitle: z3.string().optional(),
239
+ refIsPr: z3.boolean().optional()
240
+ });
241
+ var githubCommentsDataSchema = z3.object({
242
+ available: z3.boolean(),
243
+ reason: z3.string().optional(),
244
+ /** Chronological, oldest first. */
245
+ comments: z3.array(githubCommentSchema),
246
+ /** True when either stream hit its cap, or the timeline fetch stopped short. */
247
+ truncated: z3.boolean().optional(),
248
+ /** Timeline events (#525) — additive; absent when the server degraded to the legacy
249
+ * comments-only fetch. Capped independently of `comments`. */
250
+ events: z3.array(githubTimelineEventSchema).optional()
251
+ });
252
+ var githubMergeMethodSchema = z3.enum(["merge", "squash", "rebase"]);
253
+ var githubPrCheckSchema = z3.object({
254
+ name: z3.string(),
255
+ state: z3.enum(["passing", "failing", "pending", "unknown"]),
256
+ required: z3.boolean().nullable(),
257
+ url: z3.string().optional()
258
+ });
259
+ var githubPrMergeStateSchema = z3.object({
260
+ number: z3.number(),
261
+ title: z3.string(),
262
+ url: z3.string(),
263
+ state: z3.enum(["open", "closed", "merged"]),
264
+ isDraft: z3.boolean(),
265
+ headRef: z3.string(),
266
+ baseRef: z3.string(),
267
+ headSha: z3.string(),
268
+ mergeable: z3.enum(["mergeable", "conflicting", "unknown"]),
269
+ reviewDecision: z3.enum(["approved", "changes-requested", "review-required", "unknown"]),
270
+ checks: z3.array(githubPrCheckSchema),
271
+ methods: z3.array(githubMergeMethodSchema),
272
+ defaultMethod: githubMergeMethodSchema.nullable(),
273
+ eligibility: z3.enum(["ready", "blocked", "pending", "unauthorized", "terminal", "unknown"]),
274
+ blockers: z3.array(z3.object({ code: z3.string(), message: z3.string() })),
275
+ canMerge: z3.boolean(),
276
+ canOverride: z3.boolean()
277
+ });
278
+ var githubPrMergeStateResponseSchema = z3.discriminatedUnion("available", [
279
+ z3.object({ available: z3.literal(true), mergeState: githubPrMergeStateSchema }),
280
+ z3.object({ available: z3.literal(false), reason: z3.string() })
281
+ ]);
282
+ var githubMergeResponseSchema = z3.object({
283
+ merged: z3.literal(true),
284
+ number: z3.number(),
285
+ url: z3.string(),
286
+ method: githubMergeMethodSchema,
287
+ mergeCommitSha: z3.string().optional()
288
+ });
289
+ var githubPrChangeSchema = z3.object({
290
+ path: z3.string(),
291
+ previousPath: z3.string().optional(),
292
+ status: z3.enum(["added", "modified", "removed", "renamed", "copied", "changed"]),
293
+ additions: z3.number(),
294
+ deletions: z3.number(),
295
+ patch: z3.string().optional(),
296
+ patchUnavailableReason: z3.enum(["binary", "too-large", "not-provided"]).optional(),
297
+ truncated: z3.boolean().optional()
298
+ });
299
+ var githubPrChangesDataSchema = z3.discriminatedUnion("available", [
300
+ z3.object({
301
+ available: z3.literal(true),
302
+ number: z3.number(),
303
+ headSha: z3.string(),
304
+ files: z3.array(githubPrChangeSchema),
305
+ additions: z3.number(),
306
+ deletions: z3.number(),
307
+ truncated: z3.boolean(),
308
+ /** Present when the payload is complete but partial in some other way (a capped patch). */
309
+ reason: z3.string().optional()
310
+ }),
311
+ z3.object({ available: z3.literal(false), reason: z3.string() })
312
+ ]);
313
+
314
+ // ../contract/src/workflows.ts
315
+ import { z as z4 } from "zod";
316
+ var workflowStepDefSchema = z4.object({
317
+ id: z4.string().min(1),
318
+ name: z4.string().optional(),
98
319
  // agent step
99
- prompt: z3.string().optional(),
100
- skill: z3.string().optional(),
101
- model: z3.string().optional(),
320
+ prompt: z4.string().optional(),
321
+ skill: z4.string().optional(),
322
+ model: z4.string().optional(),
102
323
  /** Per-step agent backend override (falls back to the task / config default). */
103
324
  runner: runnerSchema.optional(),
104
- allowedTools: z3.array(z3.string()).optional(),
105
- bashAllowlist: z3.array(z3.string()).optional(),
325
+ allowedTools: z4.array(z4.string()).optional(),
326
+ bashAllowlist: z4.array(z4.string()).optional(),
106
327
  // check step
107
- command: z3.string().optional(),
108
- onFail: z3.object({
109
- retry: z3.string().min(1),
110
- max: z3.number().int().positive().default(2)
328
+ command: z4.string().optional(),
329
+ onFail: z4.object({
330
+ retry: z4.string().min(1),
331
+ max: z4.number().int().positive().default(2)
111
332
  }).optional()
112
333
  }).refine((s) => Boolean(s.command) !== Boolean(s.prompt ?? s.skill), {
113
334
  message: "a step is either an agent step (prompt/skill) or a check step (command), not both"
114
335
  });
115
- var workflowDefSchema = z3.object({
116
- name: z3.string(),
117
- description: z3.string().optional(),
118
- steps: z3.array(workflowStepDefSchema),
119
- source: z3.enum(["built-in", "file"]),
336
+ var workflowDefSchema = z4.object({
337
+ name: z4.string(),
338
+ description: z4.string().optional(),
339
+ steps: z4.array(workflowStepDefSchema),
340
+ source: z4.enum(["built-in", "file"]),
120
341
  /** Absent on built-ins — which is exactly what makes them undeletable. */
121
- path: z3.string().optional()
342
+ path: z4.string().optional()
122
343
  });
123
- var workflowLoadIssueSchema = z3.object({
124
- path: z3.string(),
125
- message: z3.string()
126
- });
127
- var workflowsResponseSchema = z3.object({
128
- workflows: z3.array(workflowDefSchema),
129
- issues: z3.array(workflowLoadIssueSchema)
130
- });
131
- var saveWorkflowInputSchema = z3.object({
132
- name: z3.string().trim().min(1).max(80),
133
- description: z3.string().max(2e3, "must be at most 2000 characters").optional(),
134
- steps: z3.array(workflowStepDefSchema).min(1).max(8).optional(),
135
- skills: z3.array(z3.string().trim().min(1)).min(1).max(8).optional(),
136
- overwrite: z3.boolean().optional()
344
+ var workflowLoadIssueSchema = z4.object({
345
+ path: z4.string(),
346
+ message: z4.string()
347
+ });
348
+ var workflowsResponseSchema = z4.object({
349
+ workflows: z4.array(workflowDefSchema),
350
+ issues: z4.array(workflowLoadIssueSchema)
351
+ });
352
+ var saveWorkflowInputSchema = z4.object({
353
+ name: z4.string().trim().min(1).max(80),
354
+ description: z4.string().max(2e3, "must be at most 2000 characters").optional(),
355
+ steps: z4.array(workflowStepDefSchema).min(1).max(8).optional(),
356
+ skills: z4.array(z4.string().trim().min(1)).min(1).max(8).optional(),
357
+ overwrite: z4.boolean().optional()
137
358
  }).refine((b) => Boolean(b.steps) !== Boolean(b.skills), {
138
359
  message: 'provide either "steps" or "skills", not both'
139
360
  });
140
- var saveWorkflowResponseSchema = z3.object({
141
- path: z3.string(),
142
- name: z3.string()
361
+ var saveWorkflowResponseSchema = z4.object({
362
+ path: z4.string(),
363
+ name: z4.string()
143
364
  });
144
- var parsedWorkflowSchema = z3.object({
145
- name: z3.string(),
146
- description: z3.string().optional(),
147
- steps: z3.array(workflowStepDefSchema)
365
+ var parsedWorkflowSchema = z4.object({
366
+ name: z4.string(),
367
+ description: z4.string().optional(),
368
+ steps: z4.array(workflowStepDefSchema)
148
369
  });
149
- var deleteWorkflowResponseSchema = z3.object({
150
- ok: z3.literal(true),
151
- path: z3.string()
370
+ var deleteWorkflowResponseSchema = z4.object({
371
+ ok: z4.literal(true),
372
+ path: z4.string()
152
373
  });
153
- var planResponseSchema = z3.object({
374
+ var planResponseSchema = z4.object({
154
375
  /** The kebab-case workflow title the planner proposed. Absent on the degraded fallback. */
155
- name: z3.string().optional(),
156
- steps: z3.array(workflowStepDefSchema),
157
- rationale: z3.string(),
158
- fallback: z3.boolean()
376
+ name: z4.string().optional(),
377
+ steps: z4.array(workflowStepDefSchema),
378
+ rationale: z4.string(),
379
+ fallback: z4.boolean()
159
380
  });
160
381
 
161
382
  // ../contract/src/runs.ts
162
- var runStatusSchema = z4.enum([
383
+ var runStatusSchema = z5.enum([
163
384
  "queued",
164
385
  "running",
165
386
  "waiting",
@@ -168,8 +389,8 @@ var runStatusSchema = z4.enum([
168
389
  "failed",
169
390
  "cancelled"
170
391
  ]);
171
- var runActivitySchema = z4.enum(["monitoring"]);
172
- var stepStatusSchema = z4.enum([
392
+ var runActivitySchema = z5.enum(["monitoring"]);
393
+ var stepStatusSchema = z5.enum([
173
394
  "pending",
174
395
  "running",
175
396
  "waiting",
@@ -179,14 +400,14 @@ var stepStatusSchema = z4.enum([
179
400
  "cancelled",
180
401
  "skipped"
181
402
  ]);
182
- var usageCounterSchema = z4.number().finite().nonnegative();
183
- var stepStateSchema = z4.object({
184
- id: z4.string(),
185
- name: z4.string(),
186
- kind: z4.enum(["agent", "check"]),
403
+ var usageCounterSchema = z5.number().finite().nonnegative();
404
+ var stepStateSchema = z5.object({
405
+ id: z5.string(),
406
+ name: z5.string(),
407
+ kind: z5.enum(["agent", "check"]),
187
408
  status: stepStatusSchema,
188
- iterations: z4.number(),
189
- tokensUsed: z4.number(),
409
+ iterations: z5.number(),
410
+ tokensUsed: z5.number(),
190
411
  inputTokens: usageCounterSchema.optional(),
191
412
  outputTokens: usageCounterSchema.optional(),
192
413
  usageInvocationsStarted: usageCounterSchema.optional(),
@@ -194,66 +415,74 @@ var stepStateSchema = z4.object({
194
415
  usageTurnsStarted: usageCounterSchema.optional(),
195
416
  usageTurnsRecorded: usageCounterSchema.optional(),
196
417
  usageInvocationEpoch: usageCounterSchema.optional(),
197
- startedAt: z4.string().optional(),
198
- finishedAt: z4.string().optional(),
199
- error: z4.string().optional(),
418
+ startedAt: z5.string().optional(),
419
+ finishedAt: z5.string().optional(),
420
+ error: z5.string().optional(),
200
421
  /** Latest agent session id — `claude --resume <id>` and friends. */
201
- sessionId: z4.string().optional(),
422
+ sessionId: z5.string().optional(),
202
423
  /** Backend that owns `sessionId`; absent on records written before backend affinity. */
203
424
  backend: runnerSchema.optional(),
204
- costUsd: z4.number().optional()
205
- });
206
- var diffStatSchema = z4.object({
207
- adds: z4.number(),
208
- dels: z4.number(),
209
- files: z4.number(),
425
+ /** Agent account (spec 2026-07-29-agent-profiles) that owns `sessionId` — `default`, or a
426
+ * stored profile id. The two are a PAIR: a session id only resolves inside the config dir
427
+ * that created it, so resume and Continue read this rather than the project's current
428
+ * selection. Absent on records written before accounts existed. */
429
+ profileId: z5.string().optional(),
430
+ costUsd: z5.number().optional()
431
+ });
432
+ var diffStatSchema = z5.object({
433
+ adds: z5.number(),
434
+ dels: z5.number(),
435
+ files: z5.number(),
210
436
  /** Additive since #751, and present ONLY when true: the numbers were measured against a
211
437
  * branch the agent checked out into the task's worktree, as the run found it, because the
212
438
  * worktree's HEAD had been repointed off the task's own branch (every review/QA run does
213
439
  * this) and the merge-base anchor would otherwise have reported that branch's entire diff
214
440
  * as this task's. Absent on every normal run and on every record written before #751 — a
215
441
  * consumer that ignores it sees exactly the old shape. */
216
- repointed: z4.boolean().optional()
442
+ repointed: z5.boolean().optional()
217
443
  });
218
- var queuedMessageSchema = z4.object({
219
- id: z4.string(),
220
- text: z4.string(),
444
+ var queuedMessageSchema = z5.object({
445
+ id: z5.string(),
446
+ text: z5.string(),
221
447
  /** `/api/v1/runs/:id/images/…` URLs — attachments are persisted, never inlined. */
222
- images: z4.array(z4.string()).optional(),
223
- createdAt: z4.string()
448
+ images: z5.array(z5.string()).optional(),
449
+ createdAt: z5.string()
224
450
  });
225
- var processUsageSchema = z4.object({
451
+ var processUsageSchema = z5.object({
226
452
  /** Sum of `%cpu` across the tree — can exceed 100 on multi-core work. */
227
- cpuPct: z4.number(),
228
- rssBytes: z4.number(),
229
- procCount: z4.number()
453
+ cpuPct: z5.number(),
454
+ rssBytes: z5.number(),
455
+ procCount: z5.number()
230
456
  });
231
- var runRecordSchema = z4.object({
232
- id: z4.string(),
233
- title: z4.string(),
457
+ var runRecordSchema = z5.object({
458
+ id: z5.string(),
459
+ title: z5.string(),
234
460
  /** Display title (#389): auto-derived from the first agent turn, or the user's inline edit
235
461
  * (`PATCH /runs/:id` sets it together with `title`). Show `titleSummary ?? title`. */
236
- titleSummary: z4.string().optional(),
462
+ titleSummary: z5.string().optional(),
237
463
  /** Refreshed on every turn-end; absent until the first turn ends (and on worktree-less runs). */
238
464
  diffStat: diffStatSchema.optional(),
239
- workflow: z4.string(),
240
- task: z4.string(),
465
+ workflow: z5.string(),
466
+ task: z5.string(),
241
467
  /** Prompt messages stacked onto the run while it waited for a free agent slot (#472). Folded
242
468
  * into the prompt at dequeue — never delivered as their own turns. Absent on pre-#472 runs. */
243
- queuedMessages: z4.array(queuedMessageSchema).optional(),
469
+ queuedMessages: z5.array(queuedMessageSchema).optional(),
244
470
  /** URLs of images attached to the initial task prompt (#image-display). */
245
- taskImages: z4.array(z4.string()).optional(),
246
- model: z4.string().optional(),
471
+ taskImages: z5.array(z5.string()).optional(),
472
+ model: z5.string().optional(),
247
473
  /** Normalized provider/model identity used for attribution and reproducible replay. */
248
- modelIdentity: z4.string().optional(),
474
+ modelIdentity: z5.string().optional(),
249
475
  runner: runnerSchema.optional(),
476
+ /** The composer's per-task agent account (spec 2026-07-29-agent-profiles), applying to steps
477
+ * on `runner`. Absent = the run follows the project's own selection. */
478
+ agentProfile: z5.string().optional(),
250
479
  /** Echo of the extra system prompt the run used (POST override or config default). */
251
- systemPrompt: z4.string().optional(),
480
+ systemPrompt: z5.string().optional(),
252
481
  /** false when the run deliberately disabled follow-up todo generation. Absent means enabled. */
253
- generateFollowups: z4.boolean().optional(),
482
+ generateFollowups: z5.boolean().optional(),
254
483
  /** Autonomous mode (#autonomous): the run never parks at `waiting` or the terminal `review`
255
484
  * gate. Absent = falsy = not autonomous. */
256
- autonomous: z4.boolean().optional(),
485
+ autonomous: z5.boolean().optional(),
257
486
  /**
258
487
  * Provenance for a task a project GitHub automation launched (#694). Absent on every ordinary
259
488
  * run, which is what makes it additive — the cockpit shows the "from automation" link only when
@@ -263,76 +492,83 @@ var runRecordSchema = z4.object({
263
492
  * launching definition matched, recorded on the run for the audit trail, and `src/runs/store.ts`
264
493
  * persists it as free text so an older cezar can still read a record written by a newer one.
265
494
  */
266
- automation: z4.object({
267
- automationId: z4.string(),
268
- automationRevision: z4.number(),
269
- receiptId: z4.string(),
270
- event: z4.string(),
271
- githubUrl: z4.string()
495
+ automation: z5.object({
496
+ automationId: z5.string(),
497
+ automationRevision: z5.number(),
498
+ receiptId: z5.string(),
499
+ event: z5.string(),
500
+ githubUrl: z5.string()
272
501
  }).optional(),
273
502
  status: runStatusSchema,
274
503
  /** `monitoring` while `status === 'running'` and the agent is working on downstream work.
275
504
  * Absent on old runs; cleared on resume/end. */
276
505
  activity: runActivitySchema.optional(),
277
506
  /** Exact ISO-8601 deadline for the next automatic monitoring check. */
278
- monitoringWakeAt: z4.string().optional(),
507
+ monitoringWakeAt: z5.string().optional(),
279
508
  /** The current live monitoring epoch exhausted its 40 automatic checks. */
280
- monitoringWakeCapReached: z4.boolean().optional(),
281
- createdAt: z4.string(),
282
- startedAt: z4.string().optional(),
283
- finishedAt: z4.string().optional(),
284
- tokensUsed: z4.number(),
509
+ monitoringWakeCapReached: z5.boolean().optional(),
510
+ /** Exact ISO-8601 instant this run resumes itself after a provider usage limit stopped it
511
+ * (spec 2026-08-03-auto-resume-after-usage-limit). Present only on a `failed` run with a
512
+ * pending automatic resume — its absence is what "no resume is scheduled" looks like. */
513
+ autoResumeAt: z5.string().optional(),
514
+ /** Consecutive automatic resumes since the last human turn, against the safety cap. */
515
+ autoResumeAttempts: z5.number().optional(),
516
+ createdAt: z5.string(),
517
+ startedAt: z5.string().optional(),
518
+ finishedAt: z5.string().optional(),
519
+ tokensUsed: z5.number(),
285
520
  inputTokens: usageCounterSchema.optional(),
286
521
  outputTokens: usageCounterSchema.optional(),
287
- costUsd: z4.number().optional(),
288
- pullRequestUrl: z4.string().optional(),
522
+ costUsd: z5.number().optional(),
523
+ pullRequestUrl: z5.string().optional(),
289
524
  /** The PR this task is ABOUT (#407) — auto-discovered from conversation references. Display
290
525
  * tier only: `pullRequestUrl` (the PR this task CREATED) wins, and the action gates ignore it. */
291
- referencedPullRequestUrl: z4.string().optional(),
526
+ referencedPullRequestUrl: z5.string().optional(),
292
527
  /** The PR/issue number this task is ABOUT (task auto-naming spec) — display tier only. */
293
- prNumber: z4.number().optional(),
294
- issueNumber: z4.number().optional(),
528
+ prNumber: z5.number().optional(),
529
+ issueNumber: z5.number().optional(),
295
530
  /** Server-side provenance: referenced-issue discovery currently owns `issueNumber`. */
296
- referencedIssueNumberSeeded: z4.boolean().optional(),
531
+ referencedIssueNumberSeeded: z5.boolean().optional(),
297
532
  /** 'user' = renamed via PATCH, never auto-overwritten; 'marker' = agent-declared via
298
533
  * CEZ:TITLE (spec 2026-07-18-task-ref-markers); 'auto' = namer-owned. */
299
- titleOrigin: z4.enum(["user", "auto", "marker"]).optional(),
534
+ titleOrigin: z5.enum(["user", "auto", "marker"]).optional(),
300
535
  /** References the agent declared via CEZ:PR/CEZ:ISSUE markers — authoritative over the namer
301
536
  * for the matching kind. */
302
- markerRefs: z4.object({ pr: z4.number().optional(), issue: z4.number().optional() }).optional(),
537
+ markerRefs: z5.object({ pr: z5.number().optional(), issue: z5.number().optional() }).optional(),
303
538
  /** The referenced tier's working set (distinct PR URLs spotted, capped server-side). */
304
- referencedPrCandidates: z4.array(z4.string()).optional(),
539
+ referencedPrCandidates: z5.array(z5.string()).optional(),
305
540
  /** The issue this task is ABOUT (spec 2026-07-21-report-ref-discovery). Display-only. */
306
- referencedIssueUrl: z4.string().optional(),
541
+ referencedIssueUrl: z5.string().optional(),
307
542
  /** The referenced-issue working set, persisted like `referencedPrCandidates`. Capped. */
308
- referencedIssueCandidates: z4.array(z4.string()).optional(),
543
+ referencedIssueCandidates: z5.array(z5.string()).optional(),
309
544
  /** Explicit execution policy. `false` means the run intentionally uses the repo root;
310
545
  * absent on older runs and for the default isolated-worktree mode. */
311
- worktree: z4.literal(false).optional(),
546
+ worktree: z5.literal(false).optional(),
312
547
  /** Absent for in-place runs and after an isolated worktree is removed. */
313
- worktreePath: z4.string().optional(),
314
- branch: z4.string().optional(),
548
+ worktreePath: z5.string().optional(),
549
+ branch: z5.string().optional(),
315
550
  /** Stable baseline for session git views: a worktree's fork ref, or an in-place run's starting commit. */
316
- baseBranch: z4.string().optional(),
551
+ baseBranch: z5.string().optional(),
317
552
  /** Set when count-based retention (#483) reclaimed the worktree DIRECTORY (the branch is
318
553
  * kept): the dir is gone but recoverable. */
319
- worktreeReclaimedAt: z4.string().optional(),
554
+ worktreeReclaimedAt: z5.string().optional(),
320
555
  /** Parallel variants (spec 010): runs sharing a groupId are one group. */
321
- groupId: z4.string().optional(),
556
+ groupId: z5.string().optional(),
322
557
  /** Variant letter within the group — 'A' | 'B' | 'C'. */
323
- variant: z4.string().optional(),
324
- peakRssBytes: z4.number().optional(),
325
- peakProcCount: z4.number().optional(),
326
- archived: z4.boolean(),
327
- archivedAt: z4.string().optional(),
558
+ variant: z5.string().optional(),
559
+ peakRssBytes: z5.number().optional(),
560
+ peakProcCount: z5.number().optional(),
561
+ archived: z5.boolean(),
562
+ archivedAt: z5.string().optional(),
328
563
  /** Read receipt (#unread-done-items): ISO time the cockpit last opened this run's
329
564
  * thread. A finished (`done`/`failed`) run reads as *unread* until seen since it
330
565
  * finished — see `isUnread()` in the cockpit's `lib/read-state.ts`. Absent on old
331
- * runs and on any run not yet opened, both of which count as unread. */
332
- seenAt: z4.string().optional(),
333
- currentStepId: z4.string().optional(),
334
- error: z4.string().optional(),
335
- steps: z4.array(stepStateSchema),
566
+ * runs, on any run not yet opened, and on one deliberately put back to unread via
567
+ * `POST /runs/:id/unread` (#775) — all three count as unread. */
568
+ seenAt: z5.string().optional(),
569
+ currentStepId: z5.string().optional(),
570
+ error: z5.string().optional(),
571
+ steps: z5.array(stepStateSchema),
336
572
  /**
337
573
  * The persisted workflow definition, so a `queued` run survives a restart — including the ad-hoc
338
574
  * "(planned)" chains that exist nowhere else.
@@ -350,206 +586,299 @@ var runRecordSchema = z4.object({
350
586
  var apiRunSchema = runRecordSchema.extend({
351
587
  usage: processUsageSchema.optional()
352
588
  });
353
- var createRunResponseSchema = z4.union([
589
+ var runIndexEntrySchema = z5.object({
590
+ /** The registered project this run belongs to. Joins against `GET /projects`. */
591
+ projectId: z5.string(),
592
+ id: z5.string(),
593
+ title: z5.string(),
594
+ titleSummary: z5.string().optional(),
595
+ titleOrigin: z5.enum(["user", "auto", "marker"]).optional(),
596
+ status: runStatusSchema,
597
+ activity: runActivitySchema.optional(),
598
+ createdAt: z5.string(),
599
+ finishedAt: z5.string().optional(),
600
+ /** With `status`/`finishedAt`/`archived`, the four inputs `isUnread` reads — what lets the
601
+ * palette lead with "finished while you weren't looking" across every project, not just the
602
+ * one you happen to be standing in. */
603
+ seenAt: z5.string().optional(),
604
+ /** Always present, like `RunRecord.archived`: absent would read as "not archived", and the
605
+ * unread rule treats archiving as a stronger "done with this" than reading. */
606
+ archived: z5.boolean(),
607
+ /** A run parked by a provider usage limit is `failed` on the record with a resume booked
608
+ * (spec 2026-08-03-auto-resume-after-usage-limit). Both `deriveAttention` and `isUnread` read
609
+ * it, so without it here a cross-project row would show a red "failed" dot and land in
610
+ * Recently finished for work that is simply waiting for its appointment. */
611
+ autoResumeAt: z5.string().optional(),
612
+ /** The workflow the run executes — the global Tasks page shows it in a column and groups by
613
+ * it. Always present on the record (`RunRecord.workflow`), so required here; the display
614
+ * refinement `workflowLabel` applies needs `steps[]`, which this row deliberately omits, so
615
+ * a `(planned)` chain reads as itself here rather than as its first agent's name. */
616
+ workflow: z5.string(),
617
+ /** The task's branch, when it has one — a column on the global page, and the one field that
618
+ * makes a cross-project row identifiable at a glance without opening it. */
619
+ branch: z5.string().optional(),
620
+ /** When the agent actually started, as opposed to when the task was created. The global page's
621
+ * age column prefers it and falls back to `createdAt`, exactly as the per-project table does. */
622
+ startedAt: z5.string().optional(),
623
+ /**
624
+ * The six fields `taskReference()` (`web/src/lib/tasks-table.ts`) reads to decide a task's PR
625
+ * or issue chip. Carried verbatim rather than pre-resolved into a `{kind, number, url}` on the
626
+ * server, because the rule that picks between them is subtle (#407, #526: a run that REVIEWED
627
+ * a PR must not claim it as its own, an issue-subject run must not adopt an incidental
628
+ * transcript PR) and it already exists, tested, on the client. Resolving it a second time
629
+ * server-side would be a second rule, and the two would drift.
630
+ *
631
+ * Six scalars is still the slim row this schema exists to keep: `steps[]` and `workflowDef`,
632
+ * the expensive half, stay off it.
633
+ */
634
+ pullRequestUrl: z5.string().optional(),
635
+ referencedPullRequestUrl: z5.string().optional(),
636
+ prNumber: z5.number().optional(),
637
+ issueNumber: z5.number().optional(),
638
+ referencedIssueUrl: z5.string().optional(),
639
+ markerRefs: z5.object({ pr: z5.number().optional(), issue: z5.number().optional() }).optional(),
640
+ /** What the run has cost so far. Absent means nothing was recorded, which is NOT `$0` — the
641
+ * cockpit prints an em dash rather than claiming a measurement that never happened. */
642
+ costUsd: z5.number().optional(),
643
+ /** The persisted high-water marks a FINISHED run leaves behind. `usage` below stops existing
644
+ * the moment the process tree does, so without these a finished row could say nothing at all
645
+ * about what it took to run. */
646
+ peakRssBytes: z5.number().optional(),
647
+ peakProcCount: z5.number().optional(),
648
+ /**
649
+ * The live CPU/RSS sample of this run's process tree, attached on the way out exactly as
650
+ * `GET /runs` attaches it (`withUsage`) — never persisted.
651
+ *
652
+ * It can ride a WORKSPACE-level answer because the sampler is process-wide: one cezar process
653
+ * runs every project's agents, so `currentUsage(runId)` knows about a run whatever project it
654
+ * belongs to. That is what lets a cross-project table show live usage without opening one
655
+ * event stream per project (it could not — the run stream is project-scoped).
656
+ */
657
+ usage: processUsageSchema.optional()
658
+ });
659
+ var referenceStatusesByProjectSchema = z5.record(
660
+ z5.string(),
661
+ z5.object({
662
+ prs: z5.record(z5.number(), referenceStatusSchema),
663
+ issues: z5.record(z5.number(), referenceStatusSchema)
664
+ })
665
+ );
666
+ var runsIndexResponseSchema = z5.object({
667
+ /** Newest first, across every registered project. Archived runs are included — `GET /runs`
668
+ * carries them for the project you are standing in, and a finder that dropped them elsewhere
669
+ * would make a task vanish the moment you left its project. */
670
+ runs: z5.array(runIndexEntrySchema),
671
+ /** Additive: absent statuses mean "nothing warm", never "nothing to show". */
672
+ referenceStatuses: referenceStatusesByProjectSchema,
673
+ /** The per-project cap that produced this list. */
674
+ perProjectLimit: z5.number(),
675
+ /** Ids of the projects that had more runs than the cap allowed. */
676
+ truncated: z5.array(z5.string())
677
+ });
678
+ var createRunResponseSchema = z5.union([
354
679
  runRecordSchema,
355
- z4.object({ runs: z4.array(runRecordSchema) })
680
+ z5.object({ runs: z5.array(runRecordSchema) })
356
681
  ]);
357
- var cancelResponseSchema = z4.object({ cancelled: z4.boolean() });
358
- var archiveFinishedResponseSchema = z4.object({ archived: z4.number() });
359
- var markAllReadResponseSchema = z4.object({ read: z4.number() });
360
- var deleteRunResponseSchema = z4.object({ deleted: z4.literal(true) });
361
- var finishResponseSchema = z4.object({ finished: z4.literal(true) });
362
- var continueResponseSchema = z4.object({ continued: z4.literal(true) });
363
- var createPrResponseSchema = z4.object({
364
- url: z4.string(),
365
- dryRun: z4.boolean()
366
- });
367
- var messageResponseSchema = z4.union([
368
- z4.object({ delivered: z4.literal(true) }),
369
- z4.object({ queued: z4.literal(true), message: queuedMessageSchema }),
370
- z4.object({ deferred: z4.literal(true) })
682
+ var cancelResponseSchema = z5.object({ cancelled: z5.boolean() });
683
+ var cancelAutoResumeResponseSchema = z5.object({ cancelled: z5.literal(true) });
684
+ var archiveFinishedResponseSchema = z5.object({ archived: z5.number() });
685
+ var markAllReadResponseSchema = z5.object({ read: z5.number() });
686
+ var deleteRunResponseSchema = z5.object({ deleted: z5.literal(true) });
687
+ var finishResponseSchema = z5.object({ finished: z5.literal(true) });
688
+ var continueResponseSchema = z5.object({ continued: z5.literal(true) });
689
+ var createPrResponseSchema = z5.object({
690
+ url: z5.string(),
691
+ dryRun: z5.boolean()
692
+ });
693
+ var messageResponseSchema = z5.union([
694
+ z5.object({ delivered: z5.literal(true) }),
695
+ z5.object({ queued: z5.literal(true), message: queuedMessageSchema }),
696
+ z5.object({ deferred: z5.literal(true) })
371
697
  ]);
372
- var editQueuedMessageResponseSchema = z4.object({ message: queuedMessageSchema });
373
- var removeQueuedMessageResponseSchema = z4.object({ removed: z4.literal(true) });
374
- var openInCliResponseSchema = z4.object({
375
- opened: z4.literal(true),
376
- command: z4.string()
377
- });
378
- var removeWorktreeResponseSchema = z4.object({ removed: z4.literal(true) });
379
- var gitCommitResponseSchema = z4.object({
380
- committed: z4.literal(true),
381
- sha: z4.string()
382
- });
383
- var gitPushResponseSchema = z4.object({
384
- pushed: z4.literal(true),
385
- branch: z4.string(),
386
- remote: z4.string(),
387
- upstreamSet: z4.boolean()
388
- });
389
- var runCommitSchema = z4.object({
390
- sha: z4.string(),
391
- subject: z4.string(),
392
- author: z4.string(),
698
+ var editQueuedMessageResponseSchema = z5.object({ message: queuedMessageSchema });
699
+ var removeQueuedMessageResponseSchema = z5.object({ removed: z5.literal(true) });
700
+ var openInCliResponseSchema = z5.object({
701
+ opened: z5.literal(true),
702
+ command: z5.string()
703
+ });
704
+ var removeWorktreeResponseSchema = z5.object({ removed: z5.literal(true) });
705
+ var gitCommitResponseSchema = z5.object({
706
+ committed: z5.literal(true),
707
+ sha: z5.string()
708
+ });
709
+ var gitPushResponseSchema = z5.object({
710
+ pushed: z5.literal(true),
711
+ branch: z5.string(),
712
+ remote: z5.string(),
713
+ upstreamSet: z5.boolean()
714
+ });
715
+ var runCommitSchema = z5.object({
716
+ sha: z5.string(),
717
+ subject: z5.string(),
718
+ author: z5.string(),
393
719
  /** Relative time ("3 hours ago") — git's `%cr`. */
394
- when: z4.string()
720
+ when: z5.string()
395
721
  });
396
- var runCommitsResponseSchema = z4.object({ commits: z4.array(runCommitSchema) });
397
- var groupVariantSchema = z4.object({
398
- id: z4.string(),
722
+ var runCommitsResponseSchema = z5.object({ commits: z5.array(runCommitSchema) });
723
+ var groupVariantSchema = z5.object({
724
+ id: z5.string(),
399
725
  /** 'A' | 'B' | 'C' in practice; `'?'` for a record that lost its letter. */
400
- variant: z4.string(),
401
- title: z4.string(),
726
+ variant: z5.string(),
727
+ title: z5.string(),
402
728
  status: runStatusSchema,
403
- archived: z4.boolean(),
404
- tokensUsed: z4.number(),
729
+ archived: z5.boolean(),
730
+ tokensUsed: z5.number(),
405
731
  inputTokens: usageCounterSchema.optional(),
406
732
  outputTokens: usageCounterSchema.optional(),
407
- costUsd: z4.number().optional(),
408
- diffStat: z4.string(),
733
+ costUsd: z5.number().optional(),
734
+ diffStat: z5.string(),
409
735
  /** First lines of the handoff journal's "## Progress log" section, as markdown. */
410
- handoffExcerpt: z4.string()
736
+ handoffExcerpt: z5.string()
411
737
  });
412
- var groupResponseSchema = z4.object({
413
- groupId: z4.string(),
414
- runs: z4.array(groupVariantSchema)
738
+ var groupResponseSchema = z5.object({
739
+ groupId: z5.string(),
740
+ runs: z5.array(groupVariantSchema)
415
741
  });
416
- var pickVariantResponseSchema = z4.object({
742
+ var pickVariantResponseSchema = z5.object({
417
743
  winner: runRecordSchema.optional()
418
744
  });
419
- var imageInputSchema = z4.object({
420
- mediaType: z4.string().regex(/^image\//),
421
- data: z4.string().min(1).max(7e6)
745
+ var imageInputSchema = z5.object({
746
+ mediaType: z5.string().regex(/^image\//),
747
+ data: z5.string().min(1).max(7e6)
422
748
  });
423
- var createRunInputBaseSchema = z4.object({
424
- workflow: z4.string().min(1).optional(),
749
+ var createRunInputBaseSchema = z5.object({
750
+ workflow: z5.string().min(1).optional(),
425
751
  /** An inline chain (spec 008 — an approved plan runs as an ad-hoc workflow, never written to
426
752
  * a file). The catalog's own step shape, not a copy of it. */
427
- steps: z4.array(workflowStepDefSchema).min(1).max(8).optional(),
428
- task: z4.string().min(1).max(1e5, "must be at most 100000 characters"),
429
- model: z4.string().optional(),
753
+ steps: z5.array(workflowStepDefSchema).min(1).max(8).optional(),
754
+ task: z5.string().min(1).max(1e5, "must be at most 100000 characters"),
755
+ model: z5.string().optional(),
430
756
  runner: runnerSchema.optional(),
757
+ /** Agent account for this task (spec 2026-07-29-agent-profiles). Omit to follow the
758
+ * project's own selection; an id that no longer exists is a 400, not a silent default. */
759
+ agentProfile: z5.string().max(64).optional(),
431
760
  /** 1–3. Above 1 the response is `{ runs }` rather than a single record. */
432
- variants: z4.number().int().min(1).max(3).optional(),
761
+ variants: z5.number().int().min(1).max(3).optional(),
433
762
  /** false → run in the repo working tree instead of an isolated worktree (read-only skills).
434
763
  * Omit for the default. Ignored server-side when variants > 1. */
435
- worktree: z4.boolean().optional(),
764
+ worktree: z5.boolean().optional(),
436
765
  /** true → autonomous run: never parks at "waiting"; auto-continues until done. */
437
- autonomous: z4.boolean().optional(),
766
+ autonomous: z5.boolean().optional(),
438
767
  /** false → keep the handoff journal but do not expose or request a follow-up todos file.
439
768
  * Omit for the default (enabled); a server with the capability off pins it to false. */
440
- generateFollowups: z4.boolean().optional(),
769
+ generateFollowups: z5.boolean().optional(),
441
770
  /** Per-run system-prompt override (R2 2.3) — programmatic callers only. Wins over the
442
771
  * config.json default; whitespace-only degrades to absent. */
443
- systemPrompt: z4.string().trim().max(2e4, "must be at most 20000 characters").optional().transform((s) => s ? s : void 0),
772
+ systemPrompt: z5.string().trim().max(2e4, "must be at most 20000 characters").optional().transform((s) => s ? s : void 0),
444
773
  /** Screenshots pasted into the new-task form; delivered with the first agent step. */
445
- images: z4.array(imageInputSchema).max(4).optional(),
774
+ images: z5.array(imageInputSchema).max(4).optional(),
446
775
  /** The inbox entry this task came from (#374). Best-effort bookkeeping: an unknown or
447
776
  * already-started id never fails the run. For ×2/×3 the FIRST variant is recorded. */
448
- todoId: z4.string().min(1).max(200, "must be at most 200 characters").optional()
777
+ todoId: z5.string().min(1).max(200, "must be at most 200 characters").optional()
449
778
  });
450
779
  var createRunInputSchema = createRunInputBaseSchema.refine(
451
780
  (b) => Boolean(b.workflow) !== Boolean(b.steps),
452
781
  { message: 'provide either "workflow" or "steps", not both' }
453
782
  );
454
- var messageInputSchema = z4.object({
455
- text: z4.string().max(1e5).default(""),
456
- images: z4.array(imageInputSchema).max(4).default([])
783
+ var messageInputSchema = z5.object({
784
+ text: z5.string().max(1e5).default(""),
785
+ images: z5.array(imageInputSchema).max(4).default([])
457
786
  }).refine((m) => m.text.trim().length > 0 || m.images.length > 0, {
458
787
  message: "message needs text or at least one image"
459
788
  });
460
- var patchRunInputSchema = z4.object({
461
- title: z4.string().trim().min(1).max(300).optional(),
462
- task: z4.string().trim().min(1).max(1e5).optional()
789
+ var patchRunInputSchema = z5.object({
790
+ title: z5.string().trim().min(1).max(300).optional(),
791
+ task: z5.string().trim().min(1).max(1e5).optional()
463
792
  });
464
793
 
465
794
  // ../contract/src/repo.ts
466
- import { z as z5 } from "zod";
467
- var statusEntrySchema = z5.object({
468
- status: z5.string(),
469
- path: z5.string()
795
+ import { z as z6 } from "zod";
796
+ var statusEntrySchema = z6.object({
797
+ status: z6.string(),
798
+ path: z6.string()
470
799
  });
471
- var logEntrySchema = z5.object({
472
- hash: z5.string(),
473
- subject: z5.string(),
474
- author: z5.string(),
475
- when: z5.string()
800
+ var logEntrySchema = z6.object({
801
+ hash: z6.string(),
802
+ subject: z6.string(),
803
+ author: z6.string(),
804
+ when: z6.string()
476
805
  });
477
- var repoResponseSchema = z5.union([
478
- z5.object({
479
- info: z5.null(),
480
- status: z5.array(z5.never()),
481
- log: z5.array(z5.never()),
482
- branches: z5.array(z5.never()),
483
- baseBranch: z5.null()
806
+ var repoResponseSchema = z6.union([
807
+ z6.object({
808
+ info: z6.null(),
809
+ status: z6.array(z6.never()),
810
+ log: z6.array(z6.never()),
811
+ branches: z6.array(z6.never()),
812
+ baseBranch: z6.null()
484
813
  }),
485
- z5.object({
814
+ z6.object({
486
815
  info: repoInfoSchema,
487
- status: z5.array(statusEntrySchema),
488
- log: z5.array(logEntrySchema),
489
- branches: z5.array(z5.string()),
490
- baseBranch: z5.string().nullable()
816
+ status: z6.array(statusEntrySchema),
817
+ log: z6.array(logEntrySchema),
818
+ branches: z6.array(z6.string()),
819
+ baseBranch: z6.string().nullable()
491
820
  })
492
821
  ]);
493
- var repoBranchResponseSchema = z5.object({
494
- branch: z5.string(),
495
- created: z5.boolean()
822
+ var repoBranchResponseSchema = z6.object({
823
+ branch: z6.string(),
824
+ created: z6.boolean()
496
825
  });
497
- var diffStatSchema2 = z5.object({
498
- adds: z5.number(),
499
- dels: z5.number(),
500
- files: z5.number()
826
+ var diffStatSchema2 = z6.object({
827
+ adds: z6.number(),
828
+ dels: z6.number(),
829
+ files: z6.number()
501
830
  });
502
- var changedFileSchema = z5.object({
503
- path: z5.string(),
831
+ var changedFileSchema = z6.object({
832
+ path: z6.string(),
504
833
  /** Rename/copy source — present only when `status` is renamed/copied. */
505
- oldPath: z5.string().optional(),
506
- status: z5.enum(["added", "modified", "deleted", "renamed", "copied"]),
507
- adds: z5.number(),
508
- dels: z5.number(),
834
+ oldPath: z6.string().optional(),
835
+ status: z6.enum(["added", "modified", "deleted", "renamed", "copied"]),
836
+ adds: z6.number(),
837
+ dels: z6.number(),
509
838
  /** Binary per numstat — there is no text patch to render. */
510
- binary: z5.boolean(),
839
+ binary: z6.boolean(),
511
840
  /** True when the path is one the raw-bytes route serves as an `<img>` (#365) — present only
512
841
  * when true, so old clients that never read it stay correct. */
513
- image: z5.boolean().optional(),
842
+ image: z6.boolean().optional(),
514
843
  /** This file's unified-diff section; possibly `… (patch truncated)`, possibly empty. */
515
- patch: z5.string()
844
+ patch: z6.string()
516
845
  });
517
- var changesPayloadSchema = z5.object({
518
- files: z5.array(changedFileSchema),
846
+ var changesPayloadSchema = z6.object({
847
+ files: z6.array(changedFileSchema),
519
848
  stat: diffStatSchema2,
520
849
  /** Additive context for review tasks whose worktree HEAD no longer matches their own branch. */
521
- repointedHead: z5.object({ headBranch: z5.string(), taskBranch: z5.string() }).optional()
850
+ repointedHead: z6.object({ headBranch: z6.string(), taskBranch: z6.string() }).optional()
522
851
  });
523
- var repoCommitPayloadSchema = z5.object({
524
- sha: z5.string(),
525
- subject: z5.string(),
526
- author: z5.string(),
852
+ var repoCommitPayloadSchema = z6.object({
853
+ sha: z6.string(),
854
+ subject: z6.string(),
855
+ author: z6.string(),
527
856
  /** Relative time ("3 hours ago") — same `%cr` format as the /api/v1/repo log. */
528
- when: z5.string(),
529
- files: z5.array(changedFileSchema),
857
+ when: z6.string(),
858
+ files: z6.array(changedFileSchema),
530
859
  stat: diffStatSchema2
531
860
  });
532
- var worktreeDirEntrySchema = z5.object({
533
- name: z5.string(),
534
- type: z5.enum(["dir", "file"]),
535
- size: z5.number().optional()
861
+ var worktreeDirEntrySchema = z6.object({
862
+ name: z6.string(),
863
+ type: z6.enum(["dir", "file"]),
864
+ size: z6.number().optional()
536
865
  });
537
- var worktreeEntrySchema = z5.discriminatedUnion("type", [
538
- z5.object({
539
- type: z5.literal("dir"),
540
- path: z5.string(),
541
- entries: z5.array(worktreeDirEntrySchema)
866
+ var worktreeEntrySchema = z6.discriminatedUnion("type", [
867
+ z6.object({
868
+ type: z6.literal("dir"),
869
+ path: z6.string(),
870
+ entries: z6.array(worktreeDirEntrySchema)
542
871
  }),
543
- z5.object({
544
- type: z5.literal("file"),
545
- path: z5.string(),
546
- size: z5.number(),
547
- binary: z5.boolean(),
548
- tooLarge: z5.boolean(),
549
- content: z5.string().optional()
872
+ z6.object({
873
+ type: z6.literal("file"),
874
+ path: z6.string(),
875
+ size: z6.number(),
876
+ binary: z6.boolean(),
877
+ tooLarge: z6.boolean(),
878
+ content: z6.string().optional()
550
879
  })
551
880
  ]);
552
- var worktreeRunStatusSchema = z5.enum([
881
+ var worktreeRunStatusSchema = z6.enum([
553
882
  "queued",
554
883
  "running",
555
884
  "waiting",
@@ -558,185 +887,23 @@ var worktreeRunStatusSchema = z5.enum([
558
887
  "failed",
559
888
  "cancelled"
560
889
  ]);
561
- var worktreeInfoSchema = z5.object({
562
- runId: z5.string(),
563
- title: z5.string(),
564
- status: worktreeRunStatusSchema,
565
- branch: z5.string().nullable(),
566
- sizeBytes: z5.number().nullable(),
567
- finishedAt: z5.string().nullable(),
568
- reclaimable: z5.boolean()
569
- });
570
- var worktreesResponseSchema = z5.object({
571
- worktrees: z5.array(worktreeInfoSchema),
572
- totalBytes: z5.number().nullable(),
573
- keep: z5.number()
574
- });
575
- var reclaimWorktreesResponseSchema = z5.object({
576
- reclaimed: z5.array(z5.string())
577
- });
578
-
579
- // ../contract/src/github.ts
580
- import { z as z6 } from "zod";
581
- var checksGlyphSchema = z6.enum(["passing", "failing", "pending"]).nullable();
582
- var githubItemSchema = z6.object({
583
- kind: z6.enum(["issue", "pr"]),
584
- number: z6.number(),
890
+ var worktreeInfoSchema = z6.object({
891
+ runId: z6.string(),
585
892
  title: z6.string(),
586
- author: z6.string(),
587
- createdAt: z6.string(),
588
- labels: z6.array(z6.string()),
589
- body: z6.string(),
590
- url: z6.string(),
591
- comments: z6.number(),
592
- /** PRs only. */
593
- isDraft: z6.boolean().optional(),
594
- additions: z6.number().optional(),
595
- deletions: z6.number().optional(),
596
- checks: checksGlyphSchema.optional()
597
- });
598
- var githubDataSchema = z6.object({
599
- available: z6.boolean(),
600
- /** Why it is unavailable (`gh` missing, no remote, offline…). Never an error — a hint. */
601
- reason: z6.string().optional(),
602
- /** owner/name, when known. */
603
- repo: z6.string().optional(),
604
- syncedAt: z6.string().optional(),
605
- issues: z6.array(githubItemSchema),
606
- prs: z6.array(githubItemSchema),
607
- /** Repo-wide label name → 6-hex color (no `#`); lets chips tint like GitHub. Additive. */
608
- labelColors: z6.record(z6.string(), z6.string()).optional()
609
- });
610
- var githubChecksDataSchema = z6.discriminatedUnion("available", [
611
- z6.object({
612
- available: z6.literal(true),
613
- checks: z6.record(z6.number(), checksGlyphSchema)
614
- }),
615
- z6.object({
616
- available: z6.literal(false),
617
- reason: z6.string()
618
- })
619
- ]);
620
- var githubCommentSchema = z6.object({
621
- id: z6.number(),
622
- /** Author login, `'?'` fallback when gh omits the user. */
623
- author: z6.string(),
624
- avatarUrl: z6.string().optional(),
625
- createdAt: z6.string(),
626
- body: z6.string(),
627
- kind: z6.enum(["comment", "review"]),
628
- /** Reviews only — drives the state chip. */
629
- reviewState: z6.enum(["approved", "changes_requested", "commented", "dismissed"]).optional(),
630
- url: z6.string()
631
- });
632
- var githubTimelineEventKindSchema = z6.enum([
633
- "committed",
634
- "labeled",
635
- "unlabeled",
636
- "assigned",
637
- "unassigned",
638
- "merged",
639
- "closed",
640
- "reopened",
641
- "head_ref_force_pushed",
642
- "cross-referenced",
643
- "renamed"
644
- ]);
645
- var githubTimelineEventSchema = z6.object({
646
- id: z6.string(),
647
- kind: githubTimelineEventKindSchema,
648
- /** Login — or the git author name for `committed`, which carries no GitHub actor. */
649
- actor: z6.string(),
650
- /** Absent for `committed`. */
651
- avatarUrl: z6.string().optional(),
652
- createdAt: z6.string(),
653
- url: z6.string().optional(),
654
- /** `committed` — full 40-char SHA. */
655
- sha: z6.string().optional(),
656
- /** `committed` — first line, capped at 120 chars. */
657
- message: z6.string().optional(),
658
- /** `committed` — **absent** (lookup failed/skipped) and **`null`** (no CI configured) both
659
- * render no glyph, but stay distinct values. */
660
- checks: checksGlyphSchema.optional(),
661
- label: z6.object({ name: z6.string(), color: z6.string().optional() }).optional(),
662
- /** `assigned`/`unassigned` login, or the new title for `renamed`. */
663
- subject: z6.string().optional(),
664
- refNumber: z6.number().optional(),
665
- refTitle: z6.string().optional(),
666
- refIsPr: z6.boolean().optional()
667
- });
668
- var githubCommentsDataSchema = z6.object({
669
- available: z6.boolean(),
670
- reason: z6.string().optional(),
671
- /** Chronological, oldest first. */
672
- comments: z6.array(githubCommentSchema),
673
- /** True when either stream hit its cap, or the timeline fetch stopped short. */
674
- truncated: z6.boolean().optional(),
675
- /** Timeline events (#525) — additive; absent when the server degraded to the legacy
676
- * comments-only fetch. Capped independently of `comments`. */
677
- events: z6.array(githubTimelineEventSchema).optional()
893
+ status: worktreeRunStatusSchema,
894
+ branch: z6.string().nullable(),
895
+ sizeBytes: z6.number().nullable(),
896
+ finishedAt: z6.string().nullable(),
897
+ reclaimable: z6.boolean()
678
898
  });
679
- var githubMergeMethodSchema = z6.enum(["merge", "squash", "rebase"]);
680
- var githubPrCheckSchema = z6.object({
681
- name: z6.string(),
682
- state: z6.enum(["passing", "failing", "pending", "unknown"]),
683
- required: z6.boolean().nullable(),
684
- url: z6.string().optional()
899
+ var worktreesResponseSchema = z6.object({
900
+ worktrees: z6.array(worktreeInfoSchema),
901
+ totalBytes: z6.number().nullable(),
902
+ keep: z6.number()
685
903
  });
686
- var githubPrMergeStateSchema = z6.object({
687
- number: z6.number(),
688
- title: z6.string(),
689
- url: z6.string(),
690
- state: z6.enum(["open", "closed", "merged"]),
691
- isDraft: z6.boolean(),
692
- headRef: z6.string(),
693
- baseRef: z6.string(),
694
- headSha: z6.string(),
695
- mergeable: z6.enum(["mergeable", "conflicting", "unknown"]),
696
- reviewDecision: z6.enum(["approved", "changes-requested", "review-required", "unknown"]),
697
- checks: z6.array(githubPrCheckSchema),
698
- methods: z6.array(githubMergeMethodSchema),
699
- defaultMethod: githubMergeMethodSchema.nullable(),
700
- eligibility: z6.enum(["ready", "blocked", "pending", "unauthorized", "terminal", "unknown"]),
701
- blockers: z6.array(z6.object({ code: z6.string(), message: z6.string() })),
702
- canMerge: z6.boolean(),
703
- canOverride: z6.boolean()
704
- });
705
- var githubPrMergeStateResponseSchema = z6.discriminatedUnion("available", [
706
- z6.object({ available: z6.literal(true), mergeState: githubPrMergeStateSchema }),
707
- z6.object({ available: z6.literal(false), reason: z6.string() })
708
- ]);
709
- var githubMergeResponseSchema = z6.object({
710
- merged: z6.literal(true),
711
- number: z6.number(),
712
- url: z6.string(),
713
- method: githubMergeMethodSchema,
714
- mergeCommitSha: z6.string().optional()
904
+ var reclaimWorktreesResponseSchema = z6.object({
905
+ reclaimed: z6.array(z6.string())
715
906
  });
716
- var githubPrChangeSchema = z6.object({
717
- path: z6.string(),
718
- previousPath: z6.string().optional(),
719
- status: z6.enum(["added", "modified", "removed", "renamed", "copied", "changed"]),
720
- additions: z6.number(),
721
- deletions: z6.number(),
722
- patch: z6.string().optional(),
723
- patchUnavailableReason: z6.enum(["binary", "too-large", "not-provided"]).optional(),
724
- truncated: z6.boolean().optional()
725
- });
726
- var githubPrChangesDataSchema = z6.discriminatedUnion("available", [
727
- z6.object({
728
- available: z6.literal(true),
729
- number: z6.number(),
730
- headSha: z6.string(),
731
- files: z6.array(githubPrChangeSchema),
732
- additions: z6.number(),
733
- deletions: z6.number(),
734
- truncated: z6.boolean(),
735
- /** Present when the payload is complete but partial in some other way (a capped patch). */
736
- reason: z6.string().optional()
737
- }),
738
- z6.object({ available: z6.literal(false), reason: z6.string() })
739
- ]);
740
907
 
741
908
  // ../contract/src/projects.ts
742
909
  import { z as z7 } from "zod";
@@ -755,9 +922,31 @@ var projectListEntrySchema = z7.object({
755
922
  /** Which forge this project's remote belongs to (#698) — classified server-side from the
756
923
  * remote URL alone. Gates the project group's GitHub nav item; omitted = no forge remote. */
757
924
  forge: z7.literal("github").optional(),
925
+ /**
926
+ * The remote's web root, `https://github.com/owner/repo`. Rebuilt server-side from the parsed
927
+ * remote rather than passed through, so a remote carrying credentials cannot leak into the
928
+ * cockpit. Omitted when the project has no forge remote.
929
+ *
930
+ * It exists for the cross-project surfaces: a run often knows a PR or issue only by NUMBER, and
931
+ * the global Tasks page has one row per project, so it cannot use any single repo's base the
932
+ * way a project-scoped view can. With this, every reference it shows is a link.
933
+ */
934
+ repoUrl: z7.string().optional(),
758
935
  /** Per-project cap on concurrently running tasks (spec 2026-07-22). Omitted = inherit the
759
936
  * workspace `resources.maxParallel`; a number pins this project. */
760
- maxParallel: z7.number().optional()
937
+ maxParallel: z7.number().optional(),
938
+ /**
939
+ * Free-form labels grouping CONNECTED repositories — a `storefront` tag on the API, the web
940
+ * app and the design system says those three are one piece of work spread over three repos.
941
+ * The global Tasks page (`/tasks`) filters and groups by them.
942
+ *
943
+ * Omitted rather than `[]` when a project has none, exactly like `maxParallel`: the registry
944
+ * stores nothing for a project nobody has tagged, and an empty array on the wire would make
945
+ * "never tagged" indistinguishable from "tagged, then emptied" for no gain. Normalized
946
+ * server-side (trimmed, deduped case-insensitively, sorted), so a consumer may compare them
947
+ * directly.
948
+ */
949
+ tags: z7.array(z7.string()).optional()
761
950
  });
762
951
  var projectsResponseSchema = z7.object({
763
952
  projects: z7.array(projectListEntrySchema),
@@ -775,9 +964,15 @@ var removeProjectResponseSchema = z7.object({
775
964
  var updateProjectResponseSchema = z7.object({
776
965
  project: projectListEntrySchema
777
966
  });
967
+ var PROJECT_TAG_MAX_LENGTH = 32;
968
+ var PROJECT_TAGS_MAX = 20;
778
969
  var updateProjectInputSchema = z7.object({
779
- maxParallel: z7.number().int().min(1).max(16).nullable()
780
- });
970
+ maxParallel: z7.number().int().min(1).max(16).nullable().optional(),
971
+ tags: z7.array(z7.string().trim().min(1).max(PROJECT_TAG_MAX_LENGTH)).max(PROJECT_TAGS_MAX).nullable().optional()
972
+ }).refine(
973
+ (body) => body.maxParallel !== void 0 || body.tags !== void 0,
974
+ "specify maxParallel or tags"
975
+ );
781
976
  var checkoutProjectInputSchema = z7.object({
782
977
  url: z7.string().trim().min(1).max(512),
783
978
  name: z7.string().trim().max(128).optional(),
@@ -826,8 +1021,27 @@ var workspaceConfigResponseSchema = z8.object({
826
1021
  maxParallel: z8.number(),
827
1022
  maxMonitoringSessions: z8.number(),
828
1023
  monitoringWakeIntervalMinutes: z8.number().nullable(),
1024
+ /** Resume a run a provider usage limit stopped, once the limit resets. Default `true`. */
1025
+ autoResumeOnUsageLimit: z8.boolean(),
829
1026
  memoryLimitMb: z8.number().nullable(),
830
1027
  worktreeRetentionDefault: z8.number()
1028
+ }),
1029
+ /**
1030
+ * What a repo that has set none of its own runs (spec 2026-07-29-agent-profiles).
1031
+ *
1032
+ * Both keys are OPTIONAL on the wire, and that is load-bearing rather than lax: absent means
1033
+ * "this machine has no opinion, the built-in default applies", and it has to stay distinguishable
1034
+ * from a value someone chose or the fallback collapses into "always claude". Consulted only where
1035
+ * the repo's own `.ai/cezar/config.json` is silent — a repo that chose is never overruled.
1036
+ */
1037
+ agentDefaults: z8.object({
1038
+ runner: runnerSchema.optional(),
1039
+ models: z8.object({
1040
+ claude: z8.string().optional(),
1041
+ codex: z8.string().optional(),
1042
+ opencode: z8.string().optional(),
1043
+ pi: z8.string().optional()
1044
+ }).optional()
831
1045
  })
832
1046
  });
833
1047
  var setWorkspaceConfigInputSchema = z8.object({
@@ -838,17 +1052,34 @@ var setWorkspaceConfigInputSchema = z8.object({
838
1052
  autonomous: z8.boolean().nullable().optional(),
839
1053
  worktree: z8.boolean().nullable().optional()
840
1054
  }).optional(),
1055
+ /** Machine-wide agent defaults. `null` on a key CLEARS it back to "no opinion", which a bare
1056
+ * absent key cannot say in a partial patch. */
1057
+ agentDefaults: z8.object({
1058
+ runner: runnerSchema.nullable().optional(),
1059
+ models: z8.object({
1060
+ claude: z8.string().trim().min(1).max(200).nullable().optional(),
1061
+ codex: z8.string().trim().min(1).max(200).nullable().optional(),
1062
+ opencode: z8.string().trim().min(1).max(200).nullable().optional(),
1063
+ pi: z8.string().trim().min(1).max(200).nullable().optional()
1064
+ }).optional()
1065
+ }).optional(),
841
1066
  resources: z8.object({
842
1067
  maxParallel: z8.number().int().min(1).max(16).optional(),
843
1068
  maxMonitoringSessions: z8.number().int().min(0).max(16).optional(),
844
1069
  monitoringWakeIntervalMinutes: z8.number().int().min(1).max(60).nullable().optional(),
1070
+ autoResumeOnUsageLimit: z8.boolean().optional(),
845
1071
  memoryLimitMb: z8.number().int().min(0).max(1048576).nullable().optional(),
846
1072
  worktreeRetentionDefault: z8.number().int().min(0).max(1e3).optional()
847
1073
  }).optional()
848
1074
  });
849
1075
  var appearanceSchema = z8.object({
850
1076
  accent: z8.enum(["lime", "violet"]).optional(),
851
- density: z8.enum(["comfortable", "compact", "ultra"]).optional()
1077
+ density: z8.enum(["comfortable", "compact", "ultra"]).optional(),
1078
+ width: z8.enum(["narrow", "wide"]).optional()
1079
+ });
1080
+ var taskTableUiStateSchema = z8.looseObject({
1081
+ /** Explicit user choices only. Missing ids keep the registry-owned default. */
1082
+ expandedColumns: z8.record(z8.string(), z8.boolean()).optional()
852
1083
  });
853
1084
  var uiStateSchema = z8.looseObject({
854
1085
  lastTask: z8.object({ source: z8.enum(["workflow", "skill"]), ref: z8.string() }).optional(),
@@ -902,7 +1133,8 @@ var workspaceUiStateSchema = z8.looseObject({
902
1133
  dismissedProviderAuthFailures: z8.object({
903
1134
  claude: z8.string().optional(),
904
1135
  codex: z8.string().optional(),
905
- opencode: z8.string().optional()
1136
+ opencode: z8.string().optional(),
1137
+ pi: z8.string().optional()
906
1138
  }).optional(),
907
1139
  /** Settings → Appearance, GLOBAL since step 3.5: accent + density describe the person at the
908
1140
  * keyboard, not a repo. */
@@ -910,6 +1142,8 @@ var workspaceUiStateSchema = z8.looseObject({
910
1142
  /** Settings → Notifications, GLOBAL since step 3.5 — one answer for the whole workspace, since
911
1143
  * the delivering browser is one browser whichever project you are looking at. */
912
1144
  notifications: z8.looseObject({ enabled: z8.boolean().optional() }).optional(),
1145
+ /** Desktop Tasks-table density, shared across every project in this workspace. */
1146
+ taskTable: taskTableUiStateSchema.optional(),
913
1147
  /** LEGACY, exactly like `sidebar` above — the last settled project-scoped page, restored when
914
1148
  * entering at the exact bare root. The shape is unchanged and still accepted, but the current
915
1149
  * cockpit keeps it in localStorage (`packages/web/src/lib/last-location.ts`): stored here, the
@@ -920,16 +1154,48 @@ var workspaceUiStateSchema = z8.looseObject({
920
1154
  * show from that repo. */
921
1155
  importedSkills: z8.array(z8.string()).optional()
922
1156
  });
1157
+ var WORKSPACE_UI_STATE_MAX_KEYS = 200;
1158
+ var TASK_TABLE_MAX_COLUMNS = 50;
1159
+ var setWorkspaceUiStateInputSchema = z8.looseObject({
1160
+ ...workspaceUiStateSchema.shape,
1161
+ sidebar: z8.looseObject({
1162
+ collapsed: z8.record(z8.string().min(1).max(64), z8.boolean()).refine((map) => Object.keys(map).length <= WORKSPACE_UI_STATE_MAX_KEYS, {
1163
+ message: `sidebar.collapsed must have at most ${WORKSPACE_UI_STATE_MAX_KEYS} entries`
1164
+ }).optional()
1165
+ }).optional(),
1166
+ dismissedProviderAuthFailures: z8.strictObject({
1167
+ claude: z8.string().min(1).max(128).optional(),
1168
+ codex: z8.string().min(1).max(128).optional(),
1169
+ opencode: z8.string().min(1).max(128).optional(),
1170
+ pi: z8.string().min(1).max(128).optional()
1171
+ }).optional(),
1172
+ importedSkills: z8.array(z8.string().min(1).max(200)).max(WORKSPACE_UI_STATE_MAX_KEYS).optional(),
1173
+ taskTable: taskTableUiStateSchema.extend({
1174
+ expandedColumns: z8.record(z8.string().min(1).max(64), z8.boolean()).refine((map) => Object.keys(map).length <= TASK_TABLE_MAX_COLUMNS, {
1175
+ message: `taskTable.expandedColumns must have at most ${TASK_TABLE_MAX_COLUMNS} entries`
1176
+ }).optional()
1177
+ }).optional()
1178
+ }).superRefine((data, ctx) => {
1179
+ if (Object.keys(data).length > WORKSPACE_UI_STATE_MAX_KEYS) {
1180
+ ctx.addIssue({
1181
+ code: "custom",
1182
+ message: `ui-state has too many keys (max ${WORKSPACE_UI_STATE_MAX_KEYS})`
1183
+ });
1184
+ }
1185
+ });
923
1186
  var runnerModelsSchema = z8.object({
924
1187
  claude: z8.string().optional(),
925
1188
  codex: z8.string().optional(),
926
- opencode: z8.string().optional()
1189
+ opencode: z8.string().optional(),
1190
+ pi: z8.string().optional()
927
1191
  });
928
1192
  var configResponseSchema = z8.object({
929
1193
  baseBranch: z8.string().nullable(),
930
1194
  defaultRunner: runnerSchema,
931
1195
  systemPrompt: z8.string().nullable(),
932
1196
  defaultModels: runnerModelsSchema,
1197
+ /** True when native coding-agent settings are authoritative and model picks are read-only. */
1198
+ modelsLocked: z8.boolean(),
933
1199
  /** How many tasks run at once (1–16). */
934
1200
  maxParallel: z8.number(),
935
1201
  /** Per-task memory ceiling in MiB (whole process tree); null = no limit. */
@@ -951,7 +1217,8 @@ var setConfigInputSchema = z8.object({
951
1217
  defaultModels: z8.object({
952
1218
  claude: z8.string().trim().max(200).nullable().optional(),
953
1219
  codex: z8.string().trim().max(200).nullable().optional(),
954
- opencode: z8.string().trim().max(200).nullable().optional()
1220
+ opencode: z8.string().trim().max(200).nullable().optional(),
1221
+ pi: z8.string().trim().max(200).nullable().optional()
955
1222
  }).optional(),
956
1223
  maxParallel: z8.number().int().min(1).max(16).optional(),
957
1224
  /** null or 0 clears the ceiling back to "no limit". */
@@ -1003,7 +1270,12 @@ var providerStatusSchema = z8.object({
1003
1270
  status: providerConnectionStateSchema,
1004
1271
  enabled: z8.boolean().optional(),
1005
1272
  hint: z8.string().optional(),
1006
- authFailureId: z8.string().optional()
1273
+ authFailureId: z8.string().optional(),
1274
+ /** Which agent account this row describes (spec 2026-07-29-agent-profiles). ABSENT on
1275
+ * `GET /api/v1/providers/status`, which deliberately keeps answering exactly one row per
1276
+ * provider — the discovered default — so an older client sees no change at all. Per-account
1277
+ * rows are carried by `GET /api/v1/workspace/agent-profiles` instead. */
1278
+ profileId: z8.string().optional()
1007
1279
  });
1008
1280
  var providerStatusResponseSchema = z8.object({
1009
1281
  providers: z8.array(providerStatusSchema)
@@ -1012,6 +1284,11 @@ var providerConnectResponseSchema = z8.discriminatedUnion("opened", [
1012
1284
  z8.object({ opened: z8.literal(true), command: z8.string() }),
1013
1285
  z8.object({ opened: z8.literal(false), connected: z8.literal(true), command: z8.string() })
1014
1286
  ]);
1287
+ var modelDiscoveryRunnerSchema = z8.enum(["codex", "opencode"]);
1288
+ var MODEL_DISCOVERY_RUNNERS = modelDiscoveryRunnerSchema.options;
1289
+ function runnerDiscoversModels(runner) {
1290
+ return MODEL_DISCOVERY_RUNNERS.includes(runner);
1291
+ }
1015
1292
  var runnerModelOptionSchema = z8.object({
1016
1293
  id: z8.string(),
1017
1294
  label: z8.string(),
@@ -1034,6 +1311,14 @@ var openTargetSchema = z8.object({
1034
1311
  var openTargetsResponseSchema = z8.object({
1035
1312
  targets: z8.array(openTargetSchema)
1036
1313
  });
1314
+ var openProjectInSchema = z8.object({
1315
+ // A short bound (#429): matched against a downstream allowlist, so an app id is never long.
1316
+ target: z8.string().trim().min(1, "target required").max(200)
1317
+ });
1318
+ var openProjectInResponseSchema = z8.object({
1319
+ opened: z8.literal(true),
1320
+ path: z8.string()
1321
+ });
1037
1322
 
1038
1323
  // ../contract/src/skills.ts
1039
1324
  import { z as z9 } from "zod";
@@ -1144,69 +1429,182 @@ var setAgentConfigInputSchema = z10.object({
1144
1429
  version: z10.string().nullable()
1145
1430
  });
1146
1431
 
1147
- // ../contract/src/automations.ts
1432
+ // ../contract/src/agent-profiles.ts
1148
1433
  import { z as z11 } from "zod";
1149
- var automationEventSchema = z11.enum([
1434
+ var DEFAULT_AGENT_ACCOUNT_ID = "default";
1435
+ var agentAccountFileSchema = z11.object({
1436
+ id: z11.string(),
1437
+ /** e.g. `settings.json` — the file's own name, since the folder is shown once on the account. */
1438
+ label: z11.string(),
1439
+ /** Absolute, resolved inside this account's config folder. */
1440
+ path: z11.string(),
1441
+ exists: z11.boolean()
1442
+ });
1443
+ var agentProfileSchema = z11.object({
1444
+ /** `default` for the discovered profile, else the stored slug. */
1445
+ id: z11.string(),
1446
+ provider: providerIdSchema,
1447
+ label: z11.string(),
1448
+ /** As the user wrote it — a literal `~` is preserved, matching `browseRoot`/`projectsDir`. */
1449
+ configDir: z11.string(),
1450
+ /** Expanded absolute path. Same-origin route, like `ProjectListEntry.root`. */
1451
+ path: z11.string(),
1452
+ /** False for a dir the CLI has not created yet — legitimate, and NOT a reason to fall back
1453
+ * to another account at run time (that would silently bill the wrong subscription). */
1454
+ exists: z11.boolean(),
1455
+ /** Whether the dir carries this agent's own marker files. ADVISORY: an unrecognised dir is
1456
+ * still accepted, because "add profile → Connect → the CLI creates it" is the real flow. */
1457
+ looksValid: z11.boolean(),
1458
+ /** True for the profile cezar discovers from the environment. Never stored, never deletable. */
1459
+ isDefault: z11.boolean(),
1460
+ /** This account's own authentication state — two Claude logins answer independently.
1461
+ *
1462
+ * **Absent until the probe has warmed.** Every probe shells out to an agent CLI, and this
1463
+ * listing refuses to pay that (it would be one spawn per provider plus one per account, on
1464
+ * every cold load); it serves only what is already cached, exactly as `GET /api/v1/health`
1465
+ * serves a cached forge answer. Absent means "not determined yet" — NOT `unknown`, which is a
1466
+ * real probe result — and the cockpit fills it in from `…/:id/status`. */
1467
+ status: providerStatusSchema.optional(),
1468
+ /** This agent's own user-scope config files, resolved inside THIS account's folder — so a
1469
+ * second login's `settings.json` is the one you open, not the default account's. */
1470
+ files: z11.array(agentAccountFileSchema)
1471
+ });
1472
+ function agentAccountRouteId(profile) {
1473
+ return profile.isDefault ? `default:${profile.provider}` : profile.id;
1474
+ }
1475
+ var agentAccountSelectionSchema = z11.object({
1476
+ claude: z11.string().optional(),
1477
+ codex: z11.string().optional(),
1478
+ opencode: z11.string().optional(),
1479
+ pi: z11.string().optional()
1480
+ });
1481
+ var agentProfilesResponseSchema = z11.object({
1482
+ editable: z11.boolean(),
1483
+ profiles: z11.array(agentProfileSchema),
1484
+ /** Providers that can carry more than one account at all — what "Add account" is offered for.
1485
+ * OpenCode is absent: its credentials live in a SQLite DB behind a separate `OPENCODE_DB`, so
1486
+ * a config-dir profile would swap settings while still billing the other account. */
1487
+ profileCapableProviders: z11.array(providerIdSchema),
1488
+ /** Which account each project uses, keyed by the project's realpath'd ROOT.
1489
+ *
1490
+ * Served here rather than on `GET /api/v1/projects` because it is stored beside the accounts it
1491
+ * names (`~/.cezar/agent-accounts.json`) — one file, so deleting an account and scrubbing every
1492
+ * reference to it is one atomic write, and neither can be dropped by a cezar version that never
1493
+ * heard of accounts. Empty in hosted mode, where the whole family is withheld. */
1494
+ selections: z11.record(z11.string(), agentAccountSelectionSchema),
1495
+ /** The machine-wide fallback account per provider, used by any repo that has chosen none. */
1496
+ defaults: agentAccountSelectionSchema
1497
+ });
1498
+ var selectAgentProfileInputSchema = z11.object({
1499
+ /**
1500
+ * Registry slug, or the reserved `default` boot alias. Resolved to a root server-side.
1501
+ *
1502
+ * `null` targets the MACHINE-WIDE default instead of one repo — the account a repo that has
1503
+ * chosen nothing uses, so a second login is set up once rather than per checkout. A repo's own
1504
+ * choice always wins over it, which is what keeps this a default and not an override.
1505
+ */
1506
+ projectId: z11.string().min(1).max(64).nullable(),
1507
+ provider: providerIdSchema,
1508
+ profileId: z11.string().max(64).nullable()
1509
+ });
1510
+ var agentProfileSelectionsResponseSchema = z11.object({
1511
+ selections: z11.record(z11.string(), agentAccountSelectionSchema),
1512
+ /** The machine-wide fallback, for repos with no selection of their own. */
1513
+ defaults: agentAccountSelectionSchema
1514
+ });
1515
+ var agentAccountStatusResponseSchema = z11.object({ status: providerStatusSchema });
1516
+ var agentAccountDetailsResponseSchema = z11.object({
1517
+ available: z11.boolean(),
1518
+ reason: z11.string().optional(),
1519
+ fields: z11.array(z11.object({ label: z11.string(), value: z11.string() }))
1520
+ });
1521
+ var openAgentAccountFileInputSchema = z11.object({
1522
+ file: z11.string().min(1).max(200),
1523
+ target: z11.string().min(1).max(64).optional()
1524
+ });
1525
+ var openAgentAccountFileResponseSchema = z11.object({
1526
+ opened: z11.literal(true),
1527
+ path: z11.string()
1528
+ });
1529
+ var createAgentProfileInputSchema = z11.object({
1530
+ provider: providerIdSchema,
1531
+ label: z11.string().trim().max(200).optional(),
1532
+ /** Stored as written; validated absolute after `~` expansion, server-side. */
1533
+ configDir: z11.string().trim().min(1).max(4096)
1534
+ });
1535
+ var agentProfileResponseSchema = z11.object({ profile: agentProfileSchema });
1536
+ var updateAgentProfileInputSchema = z11.object({
1537
+ label: z11.string().trim().max(200).optional(),
1538
+ configDir: z11.string().trim().min(1).max(4096).optional()
1539
+ });
1540
+ var removeAgentProfileResponseSchema = z11.object({
1541
+ removed: z11.literal(true),
1542
+ id: z11.string()
1543
+ });
1544
+
1545
+ // ../contract/src/automations.ts
1546
+ import { z as z12 } from "zod";
1547
+ var automationEventSchema = z12.enum([
1150
1548
  "pull_request.opened",
1151
1549
  "issue.opened",
1152
1550
  "issue.labeled",
1153
1551
  "issue.unlabeled"
1154
1552
  ]);
1155
- var automationFiltersSchema = z11.object({
1156
- authors: z11.array(z11.string()).optional(),
1157
- assignees: z11.array(z11.string()).optional(),
1158
- allLabels: z11.array(z11.string()).optional(),
1159
- anyLabels: z11.array(z11.string()).optional(),
1160
- excludeLabels: z11.array(z11.string()).optional(),
1553
+ var automationFiltersSchema = z12.object({
1554
+ authors: z12.array(z12.string()).optional(),
1555
+ assignees: z12.array(z12.string()).optional(),
1556
+ allLabels: z12.array(z12.string()).optional(),
1557
+ anyLabels: z12.array(z12.string()).optional(),
1558
+ excludeLabels: z12.array(z12.string()).optional(),
1161
1559
  /** Required for the two label events — the server rejects a definition without it. */
1162
- changedLabels: z11.array(z11.string()).optional(),
1163
- lookbackDays: z11.number(),
1164
- maxRecords: z11.number()
1560
+ changedLabels: z12.array(z12.string()).optional(),
1561
+ lookbackDays: z12.number(),
1562
+ maxRecords: z12.number()
1165
1563
  });
1166
1564
  var automationTaskSchema = createRunInputBaseSchema.omit({ task: true, images: true, todoId: true, systemPrompt: true }).extend({
1167
1565
  /** The prompt template. `{{github.number}}`, `{{github.title}}`, `{{github.url}}` and
1168
1566
  * `{{github.labels}}` are substituted per match; GitHub content is appended as untrusted
1169
1567
  * context, never interpolated into instructions. */
1170
- prompt: z11.string(),
1171
- variants: z11.union([z11.literal(1), z11.literal(2), z11.literal(3)]).optional(),
1172
- systemPrompt: z11.string().optional()
1568
+ prompt: z12.string(),
1569
+ variants: z12.union([z12.literal(1), z12.literal(2), z12.literal(3)]).optional(),
1570
+ systemPrompt: z12.string().optional()
1173
1571
  });
1174
- var automationDefinitionSchema = z11.object({
1175
- id: z11.string(),
1572
+ var automationDefinitionSchema = z12.object({
1573
+ id: z12.string(),
1176
1574
  /** Bumped on every edit; a PUT must echo the revision it read (optimistic concurrency). */
1177
- revision: z11.number(),
1178
- name: z11.string(),
1179
- description: z11.string().optional(),
1575
+ revision: z12.number(),
1576
+ name: z12.string(),
1577
+ description: z12.string().optional(),
1180
1578
  /** Always present: the storage schema defaults it to `false`, so a definition is created
1181
1579
  * PAUSED and enabling it is a separate, baseline-establishing act. */
1182
- enabled: z11.boolean(),
1183
- events: z11.array(automationEventSchema),
1184
- intervalSeconds: z11.number(),
1580
+ enabled: z12.boolean(),
1581
+ events: z12.array(automationEventSchema),
1582
+ intervalSeconds: z12.number(),
1185
1583
  filters: automationFiltersSchema,
1186
1584
  task: automationTaskSchema,
1187
- createdAt: z11.string(),
1188
- updatedAt: z11.string()
1585
+ createdAt: z12.string(),
1586
+ updatedAt: z12.string()
1189
1587
  });
1190
- var automationCursorSchema = z11.object({
1191
- timestamp: z11.string(),
1192
- tieBreaker: z11.string().optional()
1588
+ var automationCursorSchema = z12.object({
1589
+ timestamp: z12.string(),
1590
+ tieBreaker: z12.string().optional()
1193
1591
  });
1194
- var automationRuntimeStateSchema = z11.object({
1592
+ var automationRuntimeStateSchema = z12.object({
1195
1593
  /** The definition revision this state belongs to; a bumped revision re-baselines. */
1196
- revision: z11.number().optional(),
1594
+ revision: z12.number().optional(),
1197
1595
  /** Enabling establishes a CURRENT-TIME baseline: records older than this never launch. */
1198
- baselineAt: z11.string().optional(),
1596
+ baselineAt: z12.string().optional(),
1199
1597
  cursor: automationCursorSchema.optional(),
1200
- frozenHighWatermark: automationCursorSchema.extend({ tieBreaker: z11.string() }).optional(),
1201
- backlogAfter: automationCursorSchema.extend({ tieBreaker: z11.string() }).optional(),
1202
- nextCheckAt: z11.string().optional(),
1203
- lastSuccessAt: z11.string().optional(),
1598
+ frozenHighWatermark: automationCursorSchema.extend({ tieBreaker: z12.string() }).optional(),
1599
+ backlogAfter: automationCursorSchema.extend({ tieBreaker: z12.string() }).optional(),
1600
+ nextCheckAt: z12.string().optional(),
1601
+ lastSuccessAt: z12.string().optional(),
1204
1602
  /** Per-query GitHub ETags, so an unchanged page costs no rate-limit budget. */
1205
- etags: z11.record(z11.string(), z11.string()).optional(),
1206
- backoffUntil: z11.string().optional(),
1207
- consecutiveFailures: z11.number().optional()
1603
+ etags: z12.record(z12.string(), z12.string()).optional(),
1604
+ backoffUntil: z12.string().optional(),
1605
+ consecutiveFailures: z12.number().optional()
1208
1606
  });
1209
- var automationLogResultSchema = z11.enum([
1607
+ var automationLogResultSchema = z12.enum([
1210
1608
  "launched",
1211
1609
  "no-match",
1212
1610
  "duplicate",
@@ -1215,80 +1613,91 @@ var automationLogResultSchema = z11.enum([
1215
1613
  "baseline",
1216
1614
  "preview"
1217
1615
  ]);
1218
- var automationLogRecordSchema = z11.object({
1219
- seq: z11.number(),
1220
- ts: z11.string(),
1221
- automationId: z11.string(),
1222
- revision: z11.number(),
1616
+ var automationLogRecordSchema = z12.object({
1617
+ seq: z12.number(),
1618
+ ts: z12.string(),
1619
+ automationId: z12.string(),
1620
+ revision: z12.number(),
1223
1621
  event: automationEventSchema.optional(),
1224
1622
  result: automationLogResultSchema,
1225
- reason: z11.string().optional(),
1226
- durationMs: z11.number().optional(),
1227
- receiptId: z11.string().optional(),
1228
- runId: z11.string().optional(),
1229
- githubNumber: z11.number().optional(),
1230
- githubTitle: z11.string().optional(),
1231
- githubUrl: z11.string().optional(),
1232
- rateLimit: z11.object({
1233
- bucket: z11.enum(["core", "search"]),
1234
- remaining: z11.number().optional(),
1235
- resetAt: z11.string().optional()
1623
+ reason: z12.string().optional(),
1624
+ durationMs: z12.number().optional(),
1625
+ receiptId: z12.string().optional(),
1626
+ runId: z12.string().optional(),
1627
+ githubNumber: z12.number().optional(),
1628
+ githubTitle: z12.string().optional(),
1629
+ githubUrl: z12.string().optional(),
1630
+ rateLimit: z12.object({
1631
+ bucket: z12.enum(["core", "search"]),
1632
+ remaining: z12.number().optional(),
1633
+ resetAt: z12.string().optional()
1236
1634
  }).optional()
1237
1635
  });
1238
- var automationCountsSchema = z11.object({
1239
- matches: z11.number(),
1240
- launched: z11.number(),
1241
- duplicates: z11.number(),
1242
- errors: z11.number()
1636
+ var automationCountsSchema = z12.object({
1637
+ matches: z12.number(),
1638
+ launched: z12.number(),
1639
+ duplicates: z12.number(),
1640
+ errors: z12.number()
1243
1641
  });
1244
1642
  var automationListEntrySchema = automationDefinitionSchema.extend({
1245
1643
  state: automationRuntimeStateSchema.optional(),
1246
1644
  latestLog: automationLogRecordSchema.optional(),
1247
1645
  counts: automationCountsSchema
1248
1646
  });
1249
- var automationsResponseSchema = z11.object({
1250
- available: z11.boolean(),
1251
- reason: z11.string().optional(),
1252
- scheduler: z11.object({
1253
- state: z11.enum(["scheduled", "idle"]),
1254
- nextDue: z11.string().optional()
1647
+ var automationsResponseSchema = z12.object({
1648
+ available: z12.boolean(),
1649
+ reason: z12.string().optional(),
1650
+ scheduler: z12.object({
1651
+ state: z12.enum(["scheduled", "idle"]),
1652
+ nextDue: z12.string().optional()
1255
1653
  }),
1256
- automations: z11.array(automationListEntrySchema)
1654
+ automations: z12.array(automationListEntrySchema)
1257
1655
  });
1258
- var automationResponseSchema = z11.object({ automation: automationDefinitionSchema });
1259
- var automationDetailResponseSchema = z11.object({
1656
+ var automationResponseSchema = z12.object({ automation: automationDefinitionSchema });
1657
+ var automationDetailResponseSchema = z12.object({
1260
1658
  automation: automationDefinitionSchema,
1261
1659
  state: automationRuntimeStateSchema.optional(),
1262
1660
  latestLog: automationLogRecordSchema.optional()
1263
1661
  });
1264
- var automationCheckSchema = z11.object({
1265
- id: z11.string(),
1266
- automationId: z11.string(),
1267
- mode: z11.enum(["preview", "execute"]),
1268
- status: z11.enum(["queued", "running", "complete", "error"]),
1269
- createdAt: z11.string(),
1270
- completedAt: z11.string().optional(),
1271
- matches: z11.number().optional(),
1272
- truncated: z11.boolean().optional(),
1273
- error: z11.string().optional()
1274
- });
1275
- var automationCheckQueuedResponseSchema = z11.object({ checkId: z11.string() });
1276
- var automationLogResponseSchema = z11.object({
1277
- records: z11.array(automationLogRecordSchema)
1278
- });
1279
- var automationRetryResponseSchema = z11.object({
1280
- receiptId: z11.string(),
1281
- runId: z11.string()
1282
- });
1283
- var createAutomationInputSchema = automationDefinitionSchema.omit({ id: true, revision: true, createdAt: true, updatedAt: true, enabled: true }).extend({ enable: z11.boolean().optional() });
1662
+ var automationCheckSchema = z12.object({
1663
+ id: z12.string(),
1664
+ automationId: z12.string(),
1665
+ mode: z12.enum(["preview", "execute"]),
1666
+ status: z12.enum(["queued", "running", "complete", "error"]),
1667
+ createdAt: z12.string(),
1668
+ completedAt: z12.string().optional(),
1669
+ matches: z12.number().optional(),
1670
+ truncated: z12.boolean().optional(),
1671
+ error: z12.string().optional()
1672
+ });
1673
+ var automationCheckQueuedResponseSchema = z12.object({ checkId: z12.string() });
1674
+ var automationLogResponseSchema = z12.object({
1675
+ records: z12.array(automationLogRecordSchema)
1676
+ });
1677
+ var automationRetryResponseSchema = z12.object({
1678
+ receiptId: z12.string(),
1679
+ runId: z12.string()
1680
+ });
1681
+ var createAutomationInputSchema = automationDefinitionSchema.omit({ id: true, revision: true, createdAt: true, updatedAt: true, enabled: true }).extend({ enable: z12.boolean().optional() });
1284
1682
  var updateAutomationInputSchema = createAutomationInputSchema.omit({ enable: true }).extend({
1285
- enabled: z11.boolean().optional(),
1286
- expectedRevision: z11.number()
1683
+ enabled: z12.boolean().optional(),
1684
+ expectedRevision: z12.number()
1287
1685
  });
1288
- var automationCheckInputSchema = z11.object({
1289
- mode: z11.enum(["preview", "execute"])
1686
+ var automationCheckInputSchema = z12.object({
1687
+ mode: z12.enum(["preview", "execute"])
1290
1688
  });
1291
1689
  export {
1690
+ DEFAULT_AGENT_ACCOUNT_ID,
1691
+ MODEL_DISCOVERY_RUNNERS,
1692
+ PROJECT_TAGS_MAX,
1693
+ PROJECT_TAG_MAX_LENGTH,
1694
+ REFERENCE_STATUS_MAX,
1695
+ RUN_HISTORY_PAGE_ITEMS,
1696
+ agentAccountDetailsResponseSchema,
1697
+ agentAccountFileSchema,
1698
+ agentAccountRouteId,
1699
+ agentAccountSelectionSchema,
1700
+ agentAccountStatusResponseSchema,
1292
1701
  agentConfigFileContentSchema,
1293
1702
  agentConfigFileSchema,
1294
1703
  agentConfigFormatSchema,
@@ -1296,6 +1705,10 @@ export {
1296
1705
  agentConfigListingSchema,
1297
1706
  agentConfigScopeSchema,
1298
1707
  agentConfigTrackedSchema,
1708
+ agentProfileResponseSchema,
1709
+ agentProfileSchema,
1710
+ agentProfileSelectionsResponseSchema,
1711
+ agentProfilesResponseSchema,
1299
1712
  apiRunSchema,
1300
1713
  archiveFinishedResponseSchema,
1301
1714
  automationCheckInputSchema,
@@ -1317,6 +1730,7 @@ export {
1317
1730
  automationTaskSchema,
1318
1731
  automationsResponseSchema,
1319
1732
  backendCheckSchema,
1733
+ cancelAutoResumeResponseSchema,
1320
1734
  cancelResponseSchema,
1321
1735
  capabilitiesSchema,
1322
1736
  changedFileSchema,
@@ -1325,6 +1739,7 @@ export {
1325
1739
  checkoutProjectInputSchema,
1326
1740
  configResponseSchema,
1327
1741
  continueResponseSchema,
1742
+ createAgentProfileInputSchema,
1328
1743
  createAutomationInputSchema,
1329
1744
  createPrResponseSchema,
1330
1745
  createRunInputBaseSchema,
@@ -1352,6 +1767,7 @@ export {
1352
1767
  githubPrCheckSchema,
1353
1768
  githubPrMergeStateResponseSchema,
1354
1769
  githubPrMergeStateSchema,
1770
+ githubRefStatusDataSchema,
1355
1771
  githubTimelineEventKindSchema,
1356
1772
  githubTimelineEventSchema,
1357
1773
  groupResponseSchema,
@@ -1364,7 +1780,12 @@ export {
1364
1780
  markAllReadResponseSchema,
1365
1781
  messageInputSchema,
1366
1782
  messageResponseSchema,
1783
+ modelDiscoveryRunnerSchema,
1784
+ openAgentAccountFileInputSchema,
1785
+ openAgentAccountFileResponseSchema,
1367
1786
  openInCliResponseSchema,
1787
+ openProjectInResponseSchema,
1788
+ openProjectInSchema,
1368
1789
  openTargetSchema,
1369
1790
  openTargetsResponseSchema,
1370
1791
  parsedWorkflowSchema,
@@ -1381,7 +1802,10 @@ export {
1381
1802
  providerStatusSchema,
1382
1803
  queuedMessageSchema,
1383
1804
  reclaimWorktreesResponseSchema,
1805
+ referenceStatusSchema,
1806
+ referenceStatusesByProjectSchema,
1384
1807
  registerProjectResponseSchema,
1808
+ removeAgentProfileResponseSchema,
1385
1809
  removeProjectResponseSchema,
1386
1810
  removeQueuedMessageResponseSchema,
1387
1811
  removeTodoResponseSchema,
@@ -1394,18 +1818,30 @@ export {
1394
1818
  runCommitSchema,
1395
1819
  runCommitsResponseSchema,
1396
1820
  runEventSchema,
1821
+ runEventsQuerySchema,
1822
+ runHistoryContextSchema,
1823
+ runHistoryCursorSchema,
1824
+ runHistoryEventSchema,
1825
+ runHistoryPageSchema,
1826
+ runHistoryQuerySchema,
1827
+ runIdParamSchema,
1828
+ runIndexEntrySchema,
1397
1829
  runRecordSchema,
1398
1830
  runStatusSchema,
1831
+ runnerDiscoversModels,
1399
1832
  runnerModelCatalogResponseSchema,
1400
1833
  runnerModelOptionSchema,
1401
1834
  runnerModelsSchema,
1402
1835
  runnerSchema,
1836
+ runsIndexResponseSchema,
1403
1837
  saveWorkflowInputSchema,
1404
1838
  saveWorkflowResponseSchema,
1839
+ selectAgentProfileInputSchema,
1405
1840
  setAgentConfigInputSchema,
1406
1841
  setConfigInputSchema,
1407
1842
  setConfigResponseSchema,
1408
1843
  setWorkspaceConfigInputSchema,
1844
+ setWorkspaceUiStateInputSchema,
1409
1845
  skillSchema,
1410
1846
  skillsUpdateScopeStateSchema,
1411
1847
  skillsUpdateStateSchema,
@@ -1416,6 +1852,7 @@ export {
1416
1852
  stepStatusSchema,
1417
1853
  todoItemSchema,
1418
1854
  uiStateSchema,
1855
+ updateAgentProfileInputSchema,
1419
1856
  updateAutomationInputSchema,
1420
1857
  updateProjectInputSchema,
1421
1858
  updateProjectResponseSchema,