@claudexor/schema 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/dist/agent-capabilities.d.ts +88 -16
  2. package/dist/agent-capabilities.d.ts.map +1 -1
  3. package/dist/agent-capabilities.js +49 -18
  4. package/dist/agent-capabilities.js.map +1 -1
  5. package/dist/apply-eligibility.d.ts.map +1 -1
  6. package/dist/apply-eligibility.js +22 -6
  7. package/dist/apply-eligibility.js.map +1 -1
  8. package/dist/attachment.d.ts +113 -48
  9. package/dist/attachment.d.ts.map +1 -1
  10. package/dist/attachment.js +60 -45
  11. package/dist/attachment.js.map +1 -1
  12. package/dist/auth.d.ts +1423 -0
  13. package/dist/auth.d.ts.map +1 -0
  14. package/dist/auth.js +317 -0
  15. package/dist/auth.js.map +1 -0
  16. package/dist/budget.d.ts +133 -16
  17. package/dist/budget.d.ts.map +1 -1
  18. package/dist/budget.js +65 -22
  19. package/dist/budget.js.map +1 -1
  20. package/dist/config.d.ts +449 -115
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +114 -41
  23. package/dist/config.js.map +1 -1
  24. package/dist/context.d.ts +6 -6
  25. package/dist/context.d.ts.map +1 -1
  26. package/dist/context.js +31 -7
  27. package/dist/context.js.map +1 -1
  28. package/dist/control-operation-responses.d.ts +1172 -0
  29. package/dist/control-operation-responses.d.ts.map +1 -0
  30. package/dist/control-operation-responses.js +35 -0
  31. package/dist/control-operation-responses.js.map +1 -0
  32. package/dist/control-run-detail.d.ts +443 -242
  33. package/dist/control-run-detail.d.ts.map +1 -1
  34. package/dist/control-run-detail.js +72 -17
  35. package/dist/control-run-detail.js.map +1 -1
  36. package/dist/control-run-retry.d.ts +88 -0
  37. package/dist/control-run-retry.d.ts.map +1 -0
  38. package/dist/control-run-retry.js +40 -0
  39. package/dist/control-run-retry.js.map +1 -0
  40. package/dist/control-run-scope.d.ts +25 -0
  41. package/dist/control-run-scope.d.ts.map +1 -0
  42. package/dist/control-run-scope.js +22 -0
  43. package/dist/control-run-scope.js.map +1 -0
  44. package/dist/control-secret.d.ts +90 -0
  45. package/dist/control-secret.d.ts.map +1 -0
  46. package/dist/control-secret.js +35 -0
  47. package/dist/control-secret.js.map +1 -0
  48. package/dist/control-spec.d.ts +592 -0
  49. package/dist/control-spec.d.ts.map +1 -0
  50. package/dist/control-spec.js +85 -0
  51. package/dist/control-spec.js.map +1 -0
  52. package/dist/control-thread-apply.d.ts +175 -0
  53. package/dist/control-thread-apply.d.ts.map +1 -0
  54. package/dist/control-thread-apply.js +31 -0
  55. package/dist/control-thread-apply.js.map +1 -0
  56. package/dist/control-trust.d.ts +74 -10
  57. package/dist/control-trust.d.ts.map +1 -1
  58. package/dist/control-trust.js +31 -11
  59. package/dist/control-trust.js.map +1 -1
  60. package/dist/control.d.ts +1391 -878
  61. package/dist/control.d.ts.map +1 -1
  62. package/dist/control.js +468 -310
  63. package/dist/control.js.map +1 -1
  64. package/dist/decision.d.ts +10 -10
  65. package/dist/decision.d.ts.map +1 -1
  66. package/dist/decision.js +62 -15
  67. package/dist/decision.js.map +1 -1
  68. package/dist/delivery.d.ts +99 -0
  69. package/dist/delivery.d.ts.map +1 -0
  70. package/dist/delivery.js +19 -0
  71. package/dist/delivery.js.map +1 -0
  72. package/dist/events.d.ts +25 -2
  73. package/dist/events.d.ts.map +1 -1
  74. package/dist/events.js +25 -4
  75. package/dist/events.js.map +1 -1
  76. package/dist/gate.d.ts +2 -2
  77. package/dist/gate.d.ts.map +1 -1
  78. package/dist/gate.js +25 -5
  79. package/dist/gate.js.map +1 -1
  80. package/dist/harness.d.ts +558 -175
  81. package/dist/harness.d.ts.map +1 -1
  82. package/dist/harness.js +207 -82
  83. package/dist/harness.js.map +1 -1
  84. package/dist/index.d.ts +15 -0
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +15 -0
  87. package/dist/index.js.map +1 -1
  88. package/dist/operation.d.ts +185 -0
  89. package/dist/operation.d.ts.map +1 -0
  90. package/dist/operation.js +50 -0
  91. package/dist/operation.js.map +1 -0
  92. package/dist/orchestrate.d.ts +127 -22
  93. package/dist/orchestrate.d.ts.map +1 -1
  94. package/dist/orchestrate.js +61 -7
  95. package/dist/orchestrate.js.map +1 -1
  96. package/dist/primitives.d.ts.map +1 -1
  97. package/dist/primitives.js +4 -1
  98. package/dist/primitives.js.map +1 -1
  99. package/dist/problem.d.ts +29 -0
  100. package/dist/problem.d.ts.map +1 -0
  101. package/dist/problem.js +17 -0
  102. package/dist/problem.js.map +1 -0
  103. package/dist/project.d.ts +97 -0
  104. package/dist/project.d.ts.map +1 -0
  105. package/dist/project.js +27 -0
  106. package/dist/project.js.map +1 -0
  107. package/dist/quota.d.ts +251 -0
  108. package/dist/quota.d.ts.map +1 -0
  109. package/dist/quota.js +46 -0
  110. package/dist/quota.js.map +1 -0
  111. package/dist/raw.d.ts +195 -0
  112. package/dist/raw.d.ts.map +1 -0
  113. package/dist/raw.js +58 -0
  114. package/dist/raw.js.map +1 -0
  115. package/dist/recovery.d.ts +515 -0
  116. package/dist/recovery.d.ts.map +1 -0
  117. package/dist/recovery.js +93 -0
  118. package/dist/recovery.js.map +1 -0
  119. package/dist/request-requirements.d.ts +36 -0
  120. package/dist/request-requirements.d.ts.map +1 -0
  121. package/dist/request-requirements.js +26 -0
  122. package/dist/request-requirements.js.map +1 -0
  123. package/dist/review.d.ts +26 -26
  124. package/dist/review.d.ts.map +1 -1
  125. package/dist/review.js +50 -10
  126. package/dist/review.js.map +1 -1
  127. package/dist/route.d.ts +10 -10
  128. package/dist/route.d.ts.map +1 -1
  129. package/dist/route.js +19 -4
  130. package/dist/route.js.map +1 -1
  131. package/dist/setup.d.ts +9766 -0
  132. package/dist/setup.d.ts.map +1 -0
  133. package/dist/setup.js +450 -0
  134. package/dist/setup.js.map +1 -0
  135. package/dist/spec.d.ts +174 -57
  136. package/dist/spec.d.ts.map +1 -1
  137. package/dist/spec.js +69 -16
  138. package/dist/spec.js.map +1 -1
  139. package/dist/surface-run-controls.d.ts.map +1 -1
  140. package/dist/surface-run-controls.js +25 -21
  141. package/dist/surface-run-controls.js.map +1 -1
  142. package/dist/task.d.ts +1560 -58
  143. package/dist/task.d.ts.map +1 -1
  144. package/dist/task.js +97 -18
  145. package/dist/task.js.map +1 -1
  146. package/dist/telemetry.d.ts +233 -60
  147. package/dist/telemetry.d.ts.map +1 -1
  148. package/dist/telemetry.js +97 -15
  149. package/dist/telemetry.js.map +1 -1
  150. package/dist/thread.d.ts +68 -41
  151. package/dist/thread.d.ts.map +1 -1
  152. package/dist/thread.js +45 -11
  153. package/dist/thread.js.map +1 -1
  154. package/dist/workproduct.d.ts +3 -3
  155. package/dist/workproduct.d.ts.map +1 -1
  156. package/dist/workproduct.js.map +1 -1
  157. package/dist/workspace.d.ts +1 -1
  158. package/dist/workspace.d.ts.map +1 -1
  159. package/dist/workspace.js +12 -3
  160. package/dist/workspace.js.map +1 -1
  161. package/generated/AgentCapabilityCatalog.schema.json +53 -11
  162. package/generated/BudgetLease.schema.json +55 -6
  163. package/generated/BudgetObservation.schema.json +28 -7
  164. package/generated/ConformanceReport.schema.json +49 -0
  165. package/generated/ControlApplyCheckResponse.schema.json +34 -0
  166. package/generated/ControlArtifactListResponse.schema.json +57 -0
  167. package/generated/ControlAuthReadinessRefreshRequest.schema.json +38 -0
  168. package/generated/ControlAuthReadinessRefreshResponse.schema.json +85 -0
  169. package/generated/ControlDeliveryResponse.schema.json +136 -0
  170. package/generated/ControlHandshakeRequest.schema.json +26 -0
  171. package/generated/ControlHandshakeResponse.schema.json +30 -0
  172. package/generated/ControlHarnessListResponse.schema.json +103 -12
  173. package/generated/ControlHarnessSettingsPatch.schema.json +0 -12
  174. package/generated/ControlJournalEvent.schema.json +42 -0
  175. package/generated/ControlJournalExportReceipt.schema.json +49 -0
  176. package/generated/ControlJournalInspection.schema.json +149 -0
  177. package/generated/ControlJournalQuarantineReceipt.schema.json +55 -0
  178. package/generated/ControlJournalQuarantineRequest.schema.json +24 -0
  179. package/generated/ControlJournalValidation.schema.json +181 -0
  180. package/generated/ControlOperationCatalog.schema.json +128 -0
  181. package/generated/ControlOperationDescriptor.schema.json +110 -0
  182. package/generated/ControlProblem.schema.json +59 -0
  183. package/generated/ControlProject.schema.json +42 -0
  184. package/generated/ControlProjectListResponse.schema.json +54 -0
  185. package/generated/ControlProjectRegisterRequest.schema.json +19 -0
  186. package/generated/ControlProjectRelinkRequest.schema.json +19 -0
  187. package/generated/ControlQueuedRunInfo.schema.json +4 -2
  188. package/generated/ControlQuotaResponse.schema.json +176 -0
  189. package/generated/ControlResource.schema.json +59 -0
  190. package/generated/ControlRunAgainDraft.schema.json +499 -0
  191. package/generated/ControlRunDetail.schema.json +197 -30
  192. package/generated/ControlRunListResponse.schema.json +797 -0
  193. package/generated/ControlRunRetryResponse.schema.json +54 -0
  194. package/generated/ControlRunStartRequest.schema.json +83 -55
  195. package/generated/ControlRunStartResponse.schema.json +78 -0
  196. package/generated/ControlRunSummary.schema.json +140 -20
  197. package/generated/ControlSecretListResponse.schema.json +8 -14
  198. package/generated/ControlSecretMutationResponse.schema.json +32 -0
  199. package/generated/ControlSecretSetRequest.schema.json +27 -0
  200. package/generated/ControlSettingsSnapshot.schema.json +118 -44
  201. package/generated/ControlSettingsUpdateRequest.schema.json +110 -40
  202. package/generated/ControlSetupJob.schema.json +763 -65
  203. package/generated/ControlSetupJobCreateRequest.schema.json +11 -13
  204. package/generated/ControlSetupJobEvent.schema.json +861 -5
  205. package/generated/ControlSetupJobListFilter.schema.json +35 -0
  206. package/generated/ControlSetupJobListResponse.schema.json +763 -65
  207. package/generated/ControlSetupJobSnapshot.schema.json +870 -0
  208. package/generated/ControlSpecAnswersRequest.schema.json +74 -0
  209. package/generated/ControlSpecQuestionsRequest.schema.json +128 -2
  210. package/generated/ControlSpecSession.schema.json +249 -0
  211. package/generated/ControlSpecSessionListResponse.schema.json +261 -0
  212. package/generated/ControlThread.schema.json +20 -2
  213. package/generated/ControlThreadApplyResponse.schema.json +139 -0
  214. package/generated/ControlThreadDetail.schema.json +32 -4
  215. package/generated/ControlThreadListResponse.schema.json +20 -2
  216. package/generated/ControlThreadTurnRequest.schema.json +373 -0
  217. package/generated/ControlThreadTurnResponse.schema.json +73 -0
  218. package/generated/ControlThreadUpdateRequest.schema.json +1 -1
  219. package/generated/ControlTrustListResponse.schema.json +6 -0
  220. package/generated/ControlTrustState.schema.json +6 -0
  221. package/generated/ControlTrustUpdateRequest.schema.json +65 -3
  222. package/generated/ControlUploadCreateRequest.schema.json +37 -0
  223. package/generated/ControlUploadFinalizeRequest.schema.json +17 -0
  224. package/generated/ControlUploadStatus.schema.json +40 -0
  225. package/generated/DecisionRecord.schema.json +6 -3
  226. package/generated/GlobalConfig.schema.json +105 -58
  227. package/generated/HarnessEvent.schema.json +201 -10
  228. package/generated/HarnessManifest.schema.json +63 -12
  229. package/generated/HarnessStatusDto.schema.json +103 -12
  230. package/generated/OrchestrateContract.schema.json +32 -6
  231. package/generated/OrchestratePlan.schema.json +20 -0
  232. package/generated/OrchestratePlanProgress.schema.json +61 -0
  233. package/generated/PaidBudget.schema.json +42 -0
  234. package/generated/Project.schema.json +45 -0
  235. package/generated/ProjectConfig.schema.json +45 -18
  236. package/generated/RawContextPacket.schema.json +184 -0
  237. package/generated/RawGitPatchEnvelope.schema.json +70 -0
  238. package/generated/RunTelemetry.schema.json +80 -0
  239. package/generated/SecretMetadata.schema.json +4 -7
  240. package/generated/SpecPack.schema.json +118 -7
  241. package/generated/TaskContract.schema.json +159 -26
  242. package/generated/TestCommandInvocation.schema.json +45 -0
  243. package/generated/Thread.schema.json +62 -6
  244. package/generated/ThreadTurn.schema.json +24 -11
  245. package/generated/TrustConfig.schema.json +77 -0
  246. package/package.json +1 -1
  247. package/generated/ControlSetupJobConfirmRequest.schema.json +0 -18
  248. package/generated/ControlSpecFreezeRequest.schema.json +0 -83
package/dist/control.js CHANGED
@@ -1,34 +1,22 @@
1
1
  import { z } from "zod";
2
2
  import { AccessProfile, AuthPreference, ContentHash, ExternalContextPolicy, Id, ModeKind, NonBlankString, OutputReadyState, ProviderFamily, } from "./primitives.js";
3
- import { Portfolio } from "./budget.js";
3
+ import { PaidBudget, PaidFallback, QualityTierSet, RoutingGoal } from "./budget.js";
4
+ export { ControlQuotaResponse } from "./quota.js";
5
+ import { AuthSourceReadiness } from "./auth.js";
4
6
  import { AdapterStatus, ConformanceCheck, EffortHint, HarnessManifest, HarnessModel, InteractionQuestion, } from "./harness.js";
5
7
  import { ThreadState, ThreadTurnKind, WorkspaceMode } from "./thread.js";
6
8
  import { OrchestrateAutonomy } from "./orchestrate.js";
7
- import { AttachmentInput } from "./attachment.js";
8
- import { ProtectedPathApproval } from "./task.js";
9
- /** Project context depth. The "deep" tier never shipped a distinct behavior
10
- * (v0.15 triage): auto is the only mode; off exists solely on projections of
11
- * no-project runs. */
12
- export const RunScopeContext = z.enum(["auto"]).describe("Project context depth; auto is the only mode.");
13
- export const RunScope = z
14
- .discriminatedUnion("kind", [
15
- z
16
- .object({
17
- kind: z.literal("project"),
18
- root: z.string().describe("Absolute path of the project root."),
19
- context: RunScopeContext.default("auto"),
20
- })
21
- .strict()
22
- .describe("Run anchored to a project."),
23
- z.object({ kind: z.literal("none") }).strict().describe("Run with no project (pure ask)."),
24
- ])
25
- .describe("What the run operates on: a project (with root) or nothing.");
9
+ import { ResourceAttachmentRef } from "./attachment.js";
10
+ import { RequestRequirementResolution } from "./request-requirements.js";
11
+ import { ProtectedPathApproval, TestCommandInvocation } from "./task.js";
12
+ import { RunScope } from "./control-run-scope.js";
13
+ import { makeControlRunRetrySchemas } from "./control-run-retry.js";
26
14
  export const RunExecution = z
27
15
  .object({
28
16
  isolation: z
29
17
  .enum(["envelope", "live"])
30
18
  .default("envelope")
31
- .describe("Run isolation: envelope (isolated worktree under .claudexor/workspaces, the default) or live (the project tree itself)."),
19
+ .describe("Run isolation: envelope (isolated worktree in the external per-project runtime namespace, the default) or live (the project tree itself)."),
32
20
  })
33
21
  .strict()
34
22
  .describe("Execution isolation settings for a run.");
@@ -47,18 +35,20 @@ export const ControlReviewerPanelEntry = z
47
35
  export const ControlRunStartRequest = z
48
36
  .object({
49
37
  prompt: z.string().default("").describe("The user's prompt for the run."),
50
- /** Inbound files/images for this turn; the daemon resolves each to a scoped
51
- * on-disk Attachment before the run spec is built. */
38
+ /** Immutable daemon resource ids; upload/finalize happens before enqueue. */
52
39
  attachments: z
53
- .array(AttachmentInput)
40
+ .array(ResourceAttachmentRef)
54
41
  .optional()
55
- .describe("Inbound files/images for this turn; the daemon resolves each to a scoped on-disk attachment before the run spec is built."),
42
+ .describe("Immutable daemon resource ids returned by upload finalize; paths and inline bytes are not accepted."),
56
43
  mode: ModeKind.default("agent"),
57
44
  scope: RunScope.default({ kind: "none" }),
58
45
  execution: RunExecution.default({ isolation: "envelope" }),
59
- harnesses: z.array(NonBlankString).optional().describe("Eligible harness pool for the run; omitted = engine auto-pools."),
46
+ harnesses: z
47
+ .array(NonBlankString)
48
+ .optional()
49
+ .describe("Eligible harness pool for the run; omitted = engine auto-pools."),
60
50
  primaryHarness: NonBlankString.optional().describe("Primary harness the run should prefer."),
61
- portfolio: Portfolio.optional(),
51
+ routingGoal: RoutingGoal.optional(),
62
52
  /** Scalar model convenience: expands to the RESOLVED PRIMARY harness only
63
53
  * (never the pool). With a multi-harness pool and no primary it is
64
54
  * rejected — use `models` instead (INV-103). */
@@ -79,10 +69,24 @@ export const ControlRunStartRequest = z
79
69
  .record(ProviderFamily, EffortHint)
80
70
  .optional()
81
71
  .describe("Per-provider-family reviewer effort overrides (legacy; reviewerPanel wins when present)."),
82
- n: z.number().int().positive().optional().describe("Race width: number of best-of-N candidates."),
83
- attempts: z.number().int().positive().nullable().optional().describe("Cap on convergence attempts; null = engine default."),
72
+ n: z
73
+ .number()
74
+ .int()
75
+ .positive()
76
+ .optional()
77
+ .describe("Race width: number of best-of-N candidates."),
78
+ attempts: z
79
+ .number()
80
+ .int()
81
+ .positive()
82
+ .nullable()
83
+ .optional()
84
+ .describe("Cap on convergence attempts; null = engine default."),
84
85
  /** agent flag: iterate until the convergence predicate is clean (no fixed cap). */
85
- untilClean: z.boolean().optional().describe("Agent flag: iterate until the convergence predicate is clean (no fixed cap)."),
86
+ untilClean: z
87
+ .boolean()
88
+ .optional()
89
+ .describe("Agent flag: iterate until the convergence predicate is clean (no fixed cap)."),
86
90
  /** audit flag: bounded read-only research swarm (the old `explore`). */
87
91
  swarm: z.boolean().optional().describe("Audit flag: bounded read-only research swarm."),
88
92
  /** agent flag: create-from-scratch intent (the old `create` mode). */
@@ -94,18 +98,20 @@ export const ControlRunStartRequest = z
94
98
  .enum(["auto", "always", "never"])
95
99
  .optional()
96
100
  .describe("Best-of-N synthesis policy: auto only synthesizes an extra candidate when n>=3 and candidates genuinely complement; always/never force it."),
97
- maxUsd: z.number().nonnegative().nullable().optional().describe("USD cap for the run; null = no cap."),
101
+ paidBudget: PaidBudget.optional().describe("Explicit incremental-cash budget for the run."),
98
102
  /** Requested access profile. Effective access is derived by the engine and never client-supplied. */
99
103
  access: AccessProfile.optional().describe("Requested access profile; effective access is derived by the engine and never client-supplied."),
100
104
  web: ExternalContextPolicy.optional().describe("Web policy for the run (alias of externalContextPolicy; must match when both set)."),
101
105
  externalContextPolicy: ExternalContextPolicy.optional().describe("External web/context policy for the run."),
102
- /** Opt this run into the agent-driven browser (Playwright MCP). Honored only
103
- * for browser-capable harnesses when web policy is not `off`. */
106
+ /** Opt this run into the agent-driven browser (Playwright MCP). */
104
107
  browser: z
105
108
  .boolean()
106
109
  .optional()
107
- .describe("Opt this run into the agent-driven browser; honored only for browser-capable harnesses when web policy is not off."),
108
- tests: z.array(NonBlankString).optional().describe("Test commands to run as deterministic gates."),
110
+ .describe("Request the agent-driven browser; preflight records per-lane effectiveness and refuses when no selected lane can receive it."),
111
+ tests: z
112
+ .array(TestCommandInvocation)
113
+ .optional()
114
+ .describe("Typed-argv commands to run as deterministic gates."),
109
115
  /** Typed per-run approval for changing auto-protected gate/test paths. This
110
116
  * does not bypass built-in critical/security path human gates. */
111
117
  protectedPathApprovals: z
@@ -123,6 +129,7 @@ export const ControlRunStartRequest = z
123
129
  * lineage; POST /threads/:id/turns is the public turn surface. */
124
130
  turnId: Id.optional().describe("Internal daemon handoff only; rejected (400) when supplied by a client on POST /runs — use POST /threads/:id/turns instead."),
125
131
  parentRunId: Id.optional().describe("Run this turn follows up on."),
132
+ retryOf: Id.optional().describe("Server-owned Exact Retry lineage; direct POST /runs rejects it."),
126
133
  /** When set, this turn implements an approved plan: the engine prefixes the
127
134
  * parent plan run's final/plan.md into the prompt (mode is forced to agent). */
128
135
  planRunId: Id.optional().describe("Internal daemon handoff only; rejected (400) on POST /runs. When set, the turn implements an approved plan from that run."),
@@ -151,127 +158,10 @@ export const ControlRunStartRequest = z
151
158
  })
152
159
  .strict()
153
160
  .describe("Request body for POST /runs: prompt, mode, scope, routing, strategy flags, budget, policies, and spec/thread linkage.");
154
- /** Harness ids that have a managed setup flow (shared by the async setup-jobs path). */
155
- export const ControlHarnessSetupHarness = z
156
- .enum(["codex", "claude", "cursor", "opencode", "raw"])
157
- .describe("Harness ids that have a managed setup flow.");
158
- export const ControlSetupJobAction = z
159
- .enum(["install", "login", "doctor", "store_key"])
160
- .describe("Setup action to perform: install the vendor CLI, log in, run the doctor, or store an API key.");
161
- export const ControlSetupJobState = z
162
- .enum(["queued", "running", "waiting_for_input", "succeeded", "failed", "cancelled", "not_supported"])
163
- .describe("Lifecycle state of a setup job, including waiting_for_input (needs user confirmation/input) and not_supported.");
164
- export const ControlSetupJobCreateRequest = z
165
- .object({
166
- harness: ControlHarnessSetupHarness,
167
- action: ControlSetupJobAction,
168
- })
169
- .strict()
170
- .describe("Request body to create a harness setup job.");
171
- export const ControlSetupJob = z
172
- .object({
173
- jobId: Id.describe("Setup job id."),
174
- harness: ControlHarnessSetupHarness,
175
- action: ControlSetupJobAction,
176
- state: ControlSetupJobState,
177
- command: z.string().nullable().default(null).describe("Shell command the job runs, when applicable."),
178
- guideUrl: z.string().url().nullable().default(null).describe("Vendor guide URL for manual steps, when applicable."),
179
- logPath: z.string().nullable().default(null).describe("On-disk log path for the job's output."),
180
- message: z.string().describe("Human-readable status message."),
181
- riskFlags: z.array(z.string()).default([]).describe("Risk flags for the action (e.g. network_download, shell_pipe), surfaced before confirmation."),
182
- requiresConfirmation: z.boolean().default(false).describe("Whether the job waits for explicit user confirmation before running."),
183
- createdAt: z.string().describe("When the job was created."),
184
- startedAt: z.string().nullable().default(null).describe("When the job started running."),
185
- firstOutputAt: z.string().nullable().default(null).describe("When the job produced its first output."),
186
- lastOutputAt: z.string().nullable().default(null).describe("When the job last produced output."),
187
- finishedAt: z.string().nullable().default(null).describe("When the job finished."),
188
- retryCount: z.number().int().nonnegative().default(0).describe("How many times the job was retried."),
189
- })
190
- .strict()
191
- .describe("One managed harness setup job (install/login/doctor/store_key) with its lifecycle timestamps.");
192
- export const ControlSetupJobEvent = z
193
- .object({
194
- jobId: Id.describe("Setup job the event belongs to."),
195
- seq: z.number().int().nonnegative().describe("Monotonic event sequence within the job."),
196
- time: z.string().describe("Event timestamp."),
197
- /** Only "status" is ever produced (v0.15 triage: the log/end kinds had no
198
- * producer; SSE stream end is a transport frame, not a payload kind). */
199
- kind: z.enum(["status"]).describe("Event kind; only status is ever produced."),
200
- state: ControlSetupJobState.optional(),
201
- message: z.string().describe("Human-readable status message."),
202
- })
203
- .strict()
204
- .describe("Status event on a setup job's event stream.");
205
- export const ControlSetupJobListResponse = z
206
- .object({
207
- jobs: z.array(ControlSetupJob).describe("All known setup jobs."),
208
- })
209
- .describe("Response for listing setup jobs.");
210
- export const ControlSetupJobConfirmRequest = z
211
- .object({
212
- confirmed: z.boolean().default(true).describe("Whether the user confirmed the pending action."),
213
- })
214
- .strict()
215
- .describe("Request body confirming a setup job that waits for user confirmation.");
216
- export const ControlSpecQuestionsRequest = z
217
- .object({
218
- prompt: z.string().describe("The user's request the interview is clarifying."),
219
- scope: z
220
- .object({
221
- kind: z.literal("project"),
222
- root: z.string().describe("Absolute path of the project root."),
223
- context: RunScopeContext.default("auto"),
224
- })
225
- .strict()
226
- .describe("Project the spec is about."),
227
- harnesses: z.array(NonBlankString).optional().describe("Harnesses eligible to generate the questions."),
228
- /** Already-answered decisions from prior tiers; carried so each round goes
229
- * DEEPER instead of re-asking (multi-tier adaptive interview). */
230
- priorDecisions: z
231
- .array(z.object({
232
- question: z.string().describe("Question asked in a prior tier."),
233
- answer: z.string().describe("The user's answer."),
234
- }))
235
- .optional()
236
- .describe("Already-answered decisions from prior tiers, carried so each round goes deeper instead of re-asking."),
237
- })
238
- .strict()
239
- .describe("Request body to generate the next tier of spec interview questions.");
240
- export const ControlSpecFreezeRequest = z
241
- .object({
242
- prompt: z.string().describe("The user's request the spec captures."),
243
- scope: z
244
- .object({
245
- kind: z.literal("project"),
246
- root: z.string().describe("Absolute path of the project root."),
247
- context: RunScopeContext.default("auto"),
248
- })
249
- .strict()
250
- .describe("Project the spec is about."),
251
- planDir: z.string().optional().describe("Directory to write the frozen spec artifacts into."),
252
- plan: z.string().optional().describe("Plan text to fold into the spec."),
253
- answers: z.array(z.unknown()).optional().describe("Interview answers for the current tier."),
254
- /** Accumulated prior-tier interview decisions. Folded into the frozen
255
- * SpecPack's decided_tradeoffs so a MULTI-TIER spec carries every tier, not
256
- * just the last (mirror of ControlSpecQuestionsRequest.priorDecisions). */
257
- priorDecisions: z
258
- .array(z.object({
259
- question: z.string().describe("Question asked in a prior tier."),
260
- answer: z.string().describe("The user's answer."),
261
- }))
262
- .optional()
263
- .describe("Accumulated prior-tier interview decisions, folded into the frozen SpecPack's decided tradeoffs."),
264
- })
265
- .strict()
266
- .describe("Request body to freeze a SpecPack from the interview.");
267
- export const ControlRunStartInfo = z
268
- .object({
269
- jobId: z.string().optional().describe("Daemon job id backing the run."),
270
- runId: z.string().describe("Run id."),
271
- taskId: z.string().optional().describe("Task id, when already allocated."),
272
- runDir: z.string().describe("On-disk run artifact directory."),
273
- })
274
- .describe("Response for a successfully enqueued run.");
161
+ const RunRetrySchemas = makeControlRunRetrySchemas(ControlRunStartRequest);
162
+ export const ControlRunStartInfo = RunRetrySchemas.startInfo;
163
+ export const ControlRunRetryResponse = RunRetrySchemas.response;
164
+ export const ControlRunAgainDraft = RunRetrySchemas.draft;
275
165
  export const ControlRunState = z
276
166
  .enum([
277
167
  "queued",
@@ -283,12 +173,14 @@ export const ControlRunState = z
283
173
  "review_not_run",
284
174
  "failed",
285
175
  "cancelled",
286
- "interrupted",
176
+ "interrupted_unknown",
177
+ "cost_unverifiable",
178
+ "exhausted_overshoot",
287
179
  "exhausted",
288
180
  "not_converged",
289
181
  "stuck_no_progress",
290
182
  ])
291
- .describe("Control-plane run state: queued/running while live; blocked awaiting a human; then a terminal outcome (succeeded, no_op, ungated, review_not_run, failed, cancelled, interrupted, exhausted, not_converged, stuck_no_progress).");
183
+ .describe("Control-plane run state: queued/running while live, then an honest success, block, failure, interruption, cost, exhaustion, non-convergence, or cancellation terminal.");
292
184
  export const ControlQueuedRunInfo = z
293
185
  .object({
294
186
  jobId: z.string().describe("Daemon job id."),
@@ -314,22 +206,50 @@ export const RunFailure = z
314
206
  ])
315
207
  .default("unknown")
316
208
  .describe("Typed failure category (validation, project, auth, harness, budget, policy, cancelled, internal, unknown)."),
317
- harnessId: z.string().nullable().default(null).describe("Harness involved in the failure, when known."),
318
- attemptId: z.string().nullable().default(null).describe("Attempt involved in the failure, when known."),
209
+ harnessId: z
210
+ .string()
211
+ .nullable()
212
+ .default(null)
213
+ .describe("Harness involved in the failure, when known."),
214
+ attemptId: z
215
+ .string()
216
+ .nullable()
217
+ .default(null)
218
+ .describe("Attempt involved in the failure, when known."),
319
219
  safeMessage: z.string().describe("Redacted human-readable failure message."),
320
- rawDetailRef: z.string().nullable().default(null).describe("Artifact path holding the raw (redacted) failure detail."),
321
- logRefs: z.array(z.string()).default([]).describe("Log artifact paths relevant to the failure."),
322
- eventRefs: z.array(z.string()).default([]).describe("Event references relevant to the failure."),
220
+ rawDetailRef: z
221
+ .string()
222
+ .nullable()
223
+ .default(null)
224
+ .describe("Artifact path holding the raw (redacted) failure detail."),
225
+ logRefs: z
226
+ .array(z.string())
227
+ .default([])
228
+ .describe("Log artifact paths relevant to the failure."),
229
+ eventRefs: z
230
+ .array(z.string())
231
+ .default([])
232
+ .describe("Event references relevant to the failure."),
323
233
  runDir: z.string().nullable().default(null).describe("Run artifact directory."),
324
234
  nextActions: z.array(z.string()).default([]).describe("Suggested operator next actions."),
325
235
  })
326
236
  .describe("Typed failure record for a run: phase, category, evidence references, and suggested next actions.");
327
237
  export const ControlProjectMetadata = z
328
238
  .object({
329
- kind: z.enum(["project", "none"]).default("none").describe("Whether the run was anchored to a project."),
239
+ kind: z
240
+ .enum(["project", "none"])
241
+ .default("none")
242
+ .describe("Whether the run was anchored to a project."),
330
243
  root: z.string().nullable().default(null).describe("Project root, when anchored."),
331
- projectName: z.string().nullable().default(null).describe("Project display name, when anchored."),
332
- context: z.enum(["off", "auto"]).default("off").describe("Project context depth used for the run."),
244
+ projectName: z
245
+ .string()
246
+ .nullable()
247
+ .default(null)
248
+ .describe("Project display name, when anchored."),
249
+ context: z
250
+ .enum(["off", "auto"])
251
+ .default("off")
252
+ .describe("Project context depth used for the run."),
333
253
  })
334
254
  .describe("Project metadata projected onto a run summary.");
335
255
  export const ControlWebEvidence = z
@@ -340,15 +260,34 @@ export const ControlWebEvidence = z
340
260
  /** Mode the selected route actually executed (disclosed upgrades, e.g. claude cached->live). */
341
261
  effectiveMode: ExternalContextPolicy.default("auto").describe("Policy the selected route actually executed (disclosed upgrades, e.g. cached to live)."),
342
262
  attempted: z.boolean().default(false).describe("Whether any web activity was attempted."),
343
- satisfied: z.boolean().default(false).describe("Whether the web-evidence requirement was satisfied."),
263
+ satisfied: z
264
+ .boolean()
265
+ .default(false)
266
+ .describe("Whether the web-evidence requirement was satisfied."),
344
267
  status: z
345
268
  .enum(["none", "attempted", "satisfied", "failed", "unverified"])
346
269
  .default("none")
347
270
  .describe("Web-evidence verdict for the run."),
348
- tool: z.string().nullable().default(null).describe("Web tool that produced the evidence, when any."),
349
- target: z.string().nullable().default(null).describe("Redacted target (query/url) of the web activity, when any."),
350
- errorSummary: z.string().nullable().default(null).describe("Redacted error detail when web activity failed."),
351
- rawDetailRef: z.string().nullable().default(null).describe("Artifact path holding the raw (redacted) evidence detail."),
271
+ tool: z
272
+ .string()
273
+ .nullable()
274
+ .default(null)
275
+ .describe("Web tool that produced the evidence, when any."),
276
+ target: z
277
+ .string()
278
+ .nullable()
279
+ .default(null)
280
+ .describe("Redacted target (query/url) of the web activity, when any."),
281
+ errorSummary: z
282
+ .string()
283
+ .nullable()
284
+ .default(null)
285
+ .describe("Redacted error detail when web activity failed."),
286
+ rawDetailRef: z
287
+ .string()
288
+ .nullable()
289
+ .default(null)
290
+ .describe("Artifact path holding the raw (redacted) evidence detail."),
352
291
  /** False when the run predates telemetry.yaml; surfaces must render "telemetry unavailable". */
353
292
  available: z
354
293
  .boolean()
@@ -364,7 +303,11 @@ export const ControlWebEvidence = z
364
303
  export const ControlRouteInfo = z
365
304
  .object({
366
305
  requestedModel: z.string().nullable().default(null).describe("Model requested for the run."),
367
- observedModel: z.string().nullable().default(null).describe("Model the harness stream actually reported."),
306
+ observedModel: z
307
+ .string()
308
+ .nullable()
309
+ .default(null)
310
+ .describe("Model the harness stream actually reported."),
368
311
  harnessId: z.string().nullable().default(null).describe("Harness that ran the final attempt."),
369
312
  verified: z
370
313
  .boolean()
@@ -408,7 +351,12 @@ export const ControlRunResult = z
408
351
  .nullable()
409
352
  .default(null)
410
353
  .describe("Diff statistics; null unless a patch exists."),
411
- blockers: z.number().int().nonnegative().default(0).describe("Count of accepted blocking review findings."),
354
+ blockers: z
355
+ .number()
356
+ .int()
357
+ .nonnegative()
358
+ .default(0)
359
+ .describe("Count of accepted blocking review findings."),
412
360
  /** True when the live in-place tree was mutated this turn (regardless of review). */
413
361
  adopted: z
414
362
  .boolean()
@@ -417,21 +365,19 @@ export const ControlRunResult = z
417
365
  .describe("True when the live in-place tree was mutated this turn (regardless of review); null when unknown."),
418
366
  /** Honest application state (decoupled from clean-terminal). */
419
367
  applyState: RunApplyState.default("not_applied"),
420
- /** Tree SHA before this turn mutated the in-place tree (revert restore target). */
421
368
  preTurnSha: z
422
369
  .string()
423
370
  .nullable()
424
371
  .default(null)
425
372
  .describe("Tree SHA before this turn mutated the in-place tree (revert restore target)."),
426
- /** Tree SHA right after this turn's mutation (revert divergence fence: refuse
427
- * to revert if the working tree has diverged from this since). */
428
373
  postTurnSha: z
429
374
  .string()
430
375
  .nullable()
431
376
  .default(null)
432
377
  .describe("Tree SHA right after this turn's mutation; revert refuses if the working tree has diverged from this since."),
378
+ revertAnchorId: z.string().nullable().default(null).describe("GC-independent revert anchor."),
433
379
  /** Revert metadata is available (the turn mutated the live tree in place and
434
- * pre/post-turn snapshots were recorded), so a Revert affordance may be offered.
380
+ * an external patch anchor was recorded), so a Revert affordance may be offered.
435
381
  * This is NOT a live-safe guarantee: the server re-checks tree divergence at
436
382
  * revert time and refuses (fail loud) if the working tree changed since. */
437
383
  revertable: z
@@ -448,7 +394,9 @@ export const ControlRunSummary = z
448
394
  state: ControlRunState,
449
395
  runDir: z.string().optional().describe("On-disk run artifact directory."),
450
396
  error: z.string().optional().describe("Error message, when the run failed."),
451
- failure: RunFailure.nullable().default(null).describe("Typed failure record; null unless the run failed."),
397
+ failure: RunFailure.nullable()
398
+ .default(null)
399
+ .describe("Typed failure record; null unless the run failed."),
452
400
  project: ControlProjectMetadata.default({}),
453
401
  mode: ModeKind.optional(),
454
402
  /** v0.9 engine strategy on the mode (flags, not modes): race width / repair caps / swarm / create. */
@@ -460,14 +408,23 @@ export const ControlRunSummary = z
460
408
  prompt: z.string().optional().describe("The user's prompt for the run."),
461
409
  harnesses: z.array(z.string()).optional().describe("Harness pool the run used."),
462
410
  primaryHarness: z.string().optional().describe("Primary harness the run preferred."),
463
- portfolio: Portfolio.optional(),
411
+ routingGoal: RoutingGoal.optional(),
464
412
  model: z.string().optional().describe("Scalar model requested for the run."),
465
- reviewerPanel: z.array(ControlReviewerPanelEntry).optional().describe("Explicit reviewer panel used for the run."),
466
- protectedPathApprovals: z.array(ProtectedPathApproval).optional().describe("Per-run protected-path approvals supplied."),
413
+ reviewerPanel: z
414
+ .array(ControlReviewerPanelEntry)
415
+ .optional()
416
+ .describe("Explicit reviewer panel used for the run."),
417
+ protectedPathApprovals: z
418
+ .array(ProtectedPathApproval)
419
+ .optional()
420
+ .describe("Per-run protected-path approvals supplied."),
467
421
  n: z.number().int().optional().describe("Race width, when the run was a race."),
468
- maxUsd: z.number().nullable().optional().describe("USD cap for the run; null = no cap."),
422
+ paidBudget: PaidBudget.optional().describe("Explicit incremental-cash budget for the run."),
469
423
  spendUsd: z.number().nullable().optional().describe("Settled spend in USD; null when unknown."),
470
- spendEstimated: z.boolean().optional().describe("True when spend is token-derived rather than natively reported."),
424
+ spendEstimated: z
425
+ .boolean()
426
+ .optional()
427
+ .describe("True when spend is token-derived rather than natively reported."),
471
428
  access: AccessProfile.optional().describe("Access profile of the run: the effective profile when known, else the requested one (prefer requestedAccess/effectiveAccess)."),
472
429
  requestedAccess: AccessProfile.optional().describe("Access profile the caller requested."),
473
430
  effectiveAccess: AccessProfile.optional().describe("Access profile actually enforced by the engine."),
@@ -475,7 +432,14 @@ export const ControlRunSummary = z
475
432
  webRequired: z.boolean().optional().describe("Whether the run required web evidence."),
476
433
  webMode: ExternalContextPolicy.optional().describe("Web policy actually executed by the selected route."),
477
434
  webEvidence: ControlWebEvidence.default({}),
478
- toolPermissionPolicy: z.record(z.string(), z.unknown()).optional().describe("Tool allow/deny policy applied to the run."),
435
+ requestRequirements: z
436
+ .array(RequestRequirementResolution)
437
+ .default([])
438
+ .describe("Engine-computed requested/effective capability receipts for selected harness lanes."),
439
+ toolPermissionPolicy: z
440
+ .record(z.string(), z.unknown())
441
+ .optional()
442
+ .describe("Tool allow/deny policy applied to the run."),
479
443
  outputReadyState: OutputReadyState.default("pending"),
480
444
  /** Non-blocking tool warnings projected from final/telemetry.yaml. */
481
445
  toolWarningsTotal: z
@@ -487,10 +451,15 @@ export const ControlRunSummary = z
487
451
  /** Honest terminal outcome (what the turn did): patch/answer/plan/report/none. */
488
452
  result: ControlRunResult.default({}),
489
453
  /** True while at least one interaction.requested has no answered/timeout. */
490
- waitingOnUser: z.boolean().default(false).describe("True while at least one interactive question is awaiting the user's answer."),
454
+ waitingOnUser: z
455
+ .boolean()
456
+ .default(false)
457
+ .describe("True while at least one interactive question is awaiting the user's answer."),
491
458
  /** Route evidence from telemetry; null when no telemetry exists (legacy). */
492
- route: ControlRouteInfo.nullable().default(null).describe("Route evidence from telemetry; null when no telemetry exists (legacy runs)."),
493
- tests: z.array(z.string()).optional().describe("Test commands configured as gates."),
459
+ route: ControlRouteInfo.nullable()
460
+ .default(null)
461
+ .describe("Route evidence from telemetry; null when no telemetry exists (legacy runs)."),
462
+ tests: z.array(TestCommandInvocation).optional().describe("Typed argv gates."),
494
463
  specId: z.string().optional().describe("SpecPack id the run was held to."),
495
464
  specHash: ContentHash.optional().describe("Content hash of the SpecPack the run was held to."),
496
465
  createdAt: z.string().optional().describe("When the run was created."),
@@ -516,19 +485,41 @@ export const ControlTimelineEvent = z
516
485
  attemptId: z.string().nullable().default(null).describe("Attempt involved, when any."),
517
486
  title: z.string().describe("Human-readable event title."),
518
487
  detail: z.string().nullable().default(null).describe("Human-readable event detail."),
519
- severity: z.enum(["info", "warning", "error"]).default("info").describe("Display severity of the event."),
488
+ severity: z
489
+ .enum(["info", "warning", "error"])
490
+ .default("info")
491
+ .describe("Display severity of the event."),
520
492
  toolName: z.string().nullable().default(null).describe("Tool name for tool events."),
521
493
  target: z.string().nullable().default(null).describe("Redacted tool target for tool events."),
522
- errorSummary: z.string().nullable().default(null).describe("Redacted error detail for error events."),
523
- rawRef: z.string().nullable().default(null).describe("Reference to the raw underlying event/artifact."),
494
+ errorSummary: z
495
+ .string()
496
+ .nullable()
497
+ .default(null)
498
+ .describe("Redacted error detail for error events."),
499
+ rawRef: z
500
+ .string()
501
+ .nullable()
502
+ .default(null)
503
+ .describe("Reference to the raw underlying event/artifact."),
524
504
  })
525
505
  .describe("One projected timeline row of a run for display.");
526
506
  export const ControlBudgetSnapshot = z
527
507
  .object({
528
- maxUsd: z.number().nullable().default(null).describe("USD cap for the run; null = no cap."),
529
- spendUsd: z.number().nullable().default(null).describe("Spend so far in USD; null when unknown."),
530
- remainingUsd: z.number().nullable().default(null).describe("Remaining budget in USD; null when no cap or unknown spend."),
531
- estimated: z.boolean().default(false).describe("True when spend is token-derived rather than natively reported."),
508
+ paidBudget: PaidBudget.default({ kind: "unlimited" }),
509
+ spendUsd: z
510
+ .number()
511
+ .nullable()
512
+ .default(null)
513
+ .describe("Spend so far in USD; null when unknown."),
514
+ remainingUsd: z
515
+ .number()
516
+ .nullable()
517
+ .default(null)
518
+ .describe("Remaining budget in USD; null when no cap or unknown spend."),
519
+ estimated: z
520
+ .boolean()
521
+ .default(false)
522
+ .describe("True when spend is token-derived rather than natively reported."),
532
523
  source: z
533
524
  .enum(["decision", "events", "settings", "unknown"])
534
525
  .default("unknown")
@@ -539,11 +530,19 @@ export const ControlArtifactInfo = z
539
530
  .object({
540
531
  path: z.string().describe("Artifact path relative to the run directory."),
541
532
  kind: z.enum(["file", "directory"]).describe("Whether the artifact is a file or a directory."),
542
- bytes: z.number().int().nonnegative().optional().describe("Size in bytes; absent for directories."),
533
+ bytes: z
534
+ .number()
535
+ .int()
536
+ .nonnegative()
537
+ .optional()
538
+ .describe("Size in bytes; absent for directories."),
543
539
  /** Clean MIME type derived from the extension (e.g. `image/png`, `text/plain`,
544
540
  * `application/pdf`); lets a gallery render text vs image vs pdf. Absent for
545
541
  * directories. */
546
- mime: z.string().optional().describe("MIME type derived from the extension; absent for directories."),
542
+ mime: z
543
+ .string()
544
+ .optional()
545
+ .describe("MIME type derived from the extension; absent for directories."),
547
546
  })
548
547
  .describe("One artifact in the run's artifact tree.");
549
548
  /** A live interaction awaiting the user's answer (snapshot projection). */
@@ -551,12 +550,24 @@ export const ControlPendingInteraction = z
551
550
  .object({
552
551
  interactionId: Id.describe("Interaction id used to answer."),
553
552
  runId: Id.describe("Run the interaction belongs to."),
554
- attemptId: z.string().nullable().default(null).describe("Attempt the interaction was raised in, when known."),
553
+ attemptId: z
554
+ .string()
555
+ .nullable()
556
+ .default(null)
557
+ .describe("Attempt the interaction was raised in, when known."),
555
558
  harnessId: z.string().nullable().default(null).describe("Harness that raised the interaction."),
556
- sourceTool: z.string().nullable().default(null).describe("Native tool that raised the request."),
559
+ sourceTool: z
560
+ .string()
561
+ .nullable()
562
+ .default(null)
563
+ .describe("Native tool that raised the request."),
557
564
  questions: z.array(InteractionQuestion).default([]).describe("Questions awaiting answers."),
558
565
  requestedAt: z.string().describe("When the interaction was requested."),
559
- timeoutAt: z.string().nullable().default(null).describe("When the interaction times out into a benign decline; null = no timeout."),
566
+ timeoutAt: z
567
+ .string()
568
+ .nullable()
569
+ .default(null)
570
+ .describe("When the interaction times out into a benign decline; null = no timeout."),
560
571
  })
561
572
  .describe("A live interactive question awaiting the user's answer (snapshot projection).");
562
573
  export const ControlInteractionAnswerRequest = z
@@ -565,8 +576,15 @@ export const ControlInteractionAnswerRequest = z
565
576
  .array(z
566
577
  .object({
567
578
  questionId: Id.describe("Id of the question being answered."),
568
- selectedLabels: z.array(z.string()).default([]).describe("Labels of the selected options."),
569
- freeText: z.string().nullable().default(null).describe("Free-text answer; null when only options were selected."),
579
+ selectedLabels: z
580
+ .array(z.string())
581
+ .default([])
582
+ .describe("Labels of the selected options."),
583
+ freeText: z
584
+ .string()
585
+ .nullable()
586
+ .default(null)
587
+ .describe("Free-text answer; null when only options were selected."),
570
588
  })
571
589
  .strict())
572
590
  .default([])
@@ -618,9 +636,15 @@ export const ControlRunControlResponse = z
618
636
  .describe("Response to a run control request.");
619
637
  export const ApplyTarget = z
620
638
  .discriminatedUnion("kind", [
621
- z.object({ kind: z.literal("original_project") }).strict().describe("Apply to the project the run originally came from."),
622
639
  z
623
- .object({ kind: z.literal("project"), root: z.string().describe("Absolute path of the target project root.") })
640
+ .object({ kind: z.literal("original_project") })
641
+ .strict()
642
+ .describe("Apply to the project the run originally came from."),
643
+ z
644
+ .object({
645
+ kind: z.literal("project"),
646
+ root: z.string().describe("Absolute path of the target project root."),
647
+ })
624
648
  .strict()
625
649
  .describe("Apply to an explicitly named project root."),
626
650
  ])
@@ -663,11 +687,17 @@ export const ControlRunDecisionRequest = z
663
687
  .object({
664
688
  action: RunDecisionAction,
665
689
  /** Findings the decision targets (override/accept_risk). */
666
- findingIds: z.array(Id).default([]).describe("Findings the decision targets (override/accept_risk)."),
690
+ findingIds: z
691
+ .array(Id)
692
+ .default([])
693
+ .describe("Findings the decision targets (override/accept_risk)."),
667
694
  /** Reviewer feedback to seed a rerun turn. */
668
695
  feedback: z.string().optional().describe("Reviewer feedback to seed a rerun turn."),
669
696
  /** Risk reasons being explicitly accepted (recorded, never silent). */
670
- acceptedRisks: z.array(z.string()).default([]).describe("Risk reasons being explicitly accepted (recorded, never silent)."),
697
+ acceptedRisks: z
698
+ .array(z.string())
699
+ .default([])
700
+ .describe("Risk reasons being explicitly accepted (recorded, never silent)."),
671
701
  /** Apply mode + target for accept_clean_patch. */
672
702
  applyMode: z
673
703
  .enum(["artifact_only", "apply", "branch", "commit", "pr"])
@@ -693,19 +723,37 @@ export const ControlThread = z
693
723
  .object({
694
724
  id: Id.describe("Thread id."),
695
725
  title: z.string().nullable().default(null).describe("Thread title; null until set."),
696
- repoRoot: z.string().nullable().default(null).describe("Project root the thread is anchored to; null for a no-project thread."),
726
+ repoRoot: z
727
+ .string()
728
+ .nullable()
729
+ .default(null)
730
+ .describe("Project root the thread is anchored to; null for a no-project thread."),
697
731
  mode: ModeKind.optional().describe("Default mode for new turns."),
698
732
  /** How turns touch files (in-place live tree vs isolated worktree). */
699
733
  workspaceMode: WorkspaceMode.default("in_place"),
700
734
  authPreference: AuthPreference.default("auto"),
701
- primaryHarness: z.string().nullable().default(null).describe("Sticky primary harness for the thread; null = engine routing."),
735
+ primaryHarness: z
736
+ .string()
737
+ .nullable()
738
+ .default(null)
739
+ .describe("Sticky primary harness for the thread; null = engine routing."),
702
740
  /** Sticky eligible pool for the thread (empty => engine auto-pools). */
703
- eligibleHarnesses: z.array(z.string()).default([]).describe("Sticky eligible harness pool; empty = the engine auto-pools."),
741
+ eligibleHarnesses: z
742
+ .array(z.string())
743
+ .default([])
744
+ .describe("Sticky eligible harness pool; empty = the engine auto-pools."),
704
745
  state: ThreadState.default("active"),
746
+ trashedAt: z.string().nullable().default(null).describe("When the thread entered trash."),
747
+ purgeAfter: z.string().nullable().default(null).describe("When trash retention expires."),
705
748
  runIds: z.array(Id).default([]).describe("Ordered run lineage of the thread."),
706
- headRunId: Id.nullable().default(null).describe("Most recent run of the thread; null before the first turn runs."),
749
+ headRunId: Id.nullable()
750
+ .default(null)
751
+ .describe("Most recent run of the thread; null before the first turn runs."),
707
752
  /** True when the head turn is blocked on a human decision (needs-me inbox). */
708
- needsHuman: z.boolean().default(false).describe("True when the head turn is blocked on a human decision (needs-me inbox)."),
753
+ needsHuman: z
754
+ .boolean()
755
+ .default(false)
756
+ .describe("True when the head turn is blocked on a human decision (needs-me inbox)."),
709
757
  createdAt: z.string().describe("When the thread was created."),
710
758
  updatedAt: z.string().describe("When the thread was last updated."),
711
759
  })
@@ -715,9 +763,20 @@ export const ControlSession = z
715
763
  id: Id.describe("Session id."),
716
764
  threadId: Id.describe("Thread the session belongs to."),
717
765
  harnessId: Id.describe("Harness the session is bound to."),
718
- nativeSessionId: z.string().nullable().default(null).describe("The vendor CLI session id; null when none exists."),
719
- observedModel: z.string().nullable().default(null).describe("Model last observed on the session's stream."),
720
- state: z.enum(["live", "stale", "rebound"]).default("live").describe("Session cache state: live, stale, or rebound."),
766
+ nativeSessionId: z
767
+ .string()
768
+ .nullable()
769
+ .default(null)
770
+ .describe("The vendor CLI session id; null when none exists."),
771
+ observedModel: z
772
+ .string()
773
+ .nullable()
774
+ .default(null)
775
+ .describe("Model last observed on the session's stream."),
776
+ state: z
777
+ .enum(["live", "stale", "rebound"])
778
+ .default("live")
779
+ .describe("Session cache state: live, stale, or rebound."),
721
780
  })
722
781
  .describe("Control-plane projection of a vendor CLI session bound to a thread.");
723
782
  /**
@@ -737,8 +796,15 @@ export const ControlTurnRunCard = z
737
796
  result: ControlRunResult.default({}),
738
797
  spendUsd: z.number().nullable().optional().describe("Settled spend in USD; null when unknown."),
739
798
  outputReadyState: OutputReadyState.default("pending"),
740
- waitingOnUser: z.boolean().default(false).describe("True while an interactive question is awaiting the user's answer."),
741
- finishedAt: z.string().nullable().default(null).describe("When the run finished; null while live."),
799
+ waitingOnUser: z
800
+ .boolean()
801
+ .default(false)
802
+ .describe("True while an interactive question is awaiting the user's answer."),
803
+ finishedAt: z
804
+ .string()
805
+ .nullable()
806
+ .default(null)
807
+ .describe("When the run finished; null while live."),
742
808
  })
743
809
  .describe("Compact run state embedded on a turn so a chat surface renders the whole conversation from one thread fetch.");
744
810
  export const ControlThreadTurn = z
@@ -748,11 +814,15 @@ export const ControlThreadTurn = z
748
814
  runId: Id.nullable().default(null).describe("Run backing this turn; null while unbound."),
749
815
  parentRunId: Id.nullable().default(null).describe("Run this turn follows up on, when any."),
750
816
  /** Set when this turn implements an approved plan from an earlier run. */
751
- planRunId: Id.nullable().default(null).describe("Set when this turn implements an approved plan from an earlier run."),
817
+ planRunId: Id.nullable()
818
+ .default(null)
819
+ .describe("Set when this turn implements an approved plan from an earlier run."),
752
820
  kind: ThreadTurnKind.default("followup"),
753
821
  prompt: z.string().default("").describe("The user's message for this turn."),
754
822
  /** Embedded run card (outcome/state) so the chat renders without N+1 fetches. */
755
- run: ControlTurnRunCard.nullable().default(null).describe("Embedded run card (outcome/state); null while no run is bound."),
823
+ run: ControlTurnRunCard.nullable()
824
+ .default(null)
825
+ .describe("Embedded run card (outcome/state); null while no run is bound."),
756
826
  /** Why this turn has NO run (enqueue/preflight refusal, e.g. the trust
757
827
  * gate) — surfaces render it as an inline failure card with the remedy;
758
828
  * null once a run binds (retry clears it). `code` is the typed throw's
@@ -762,7 +832,11 @@ export const ControlThreadTurn = z
762
832
  enqueueError: z
763
833
  .object({
764
834
  message: z.string().describe("Human-readable refusal message."),
765
- code: z.string().nullable().default(null).describe("Machine-readable refusal code; remedies key on it, never on the message text."),
835
+ code: z
836
+ .string()
837
+ .nullable()
838
+ .default(null)
839
+ .describe("Machine-readable refusal code; remedies key on it, never on the message text."),
766
840
  retryable: z
767
841
  .boolean()
768
842
  .default(true)
@@ -784,7 +858,10 @@ export const ControlThreadCreateRequest = z
784
858
  authPreference: AuthPreference.optional().describe("Per-thread auth preference override."),
785
859
  primaryHarness: NonBlankString.optional().describe("Sticky primary harness for the thread."),
786
860
  /** Sticky eligible pool for the thread; turns inherit it when unset. */
787
- eligibleHarnesses: z.array(NonBlankString).optional().describe("Sticky eligible harness pool; turns inherit it when unset."),
861
+ eligibleHarnesses: z
862
+ .array(NonBlankString)
863
+ .optional()
864
+ .describe("Sticky eligible harness pool; turns inherit it when unset."),
788
865
  })
789
866
  .strict()
790
867
  .describe("Request body for POST /threads.");
@@ -793,35 +870,17 @@ export const ControlThreadCreateRequest = z
793
870
  export const ControlThreadUpdateRequest = z
794
871
  .object({
795
872
  title: z.string().optional().describe("New thread title."),
796
- state: ThreadState.optional().describe("New thread state (active/closed)."),
797
- primaryHarness: NonBlankString.nullable().optional().describe("New sticky primary harness; null clears back to engine routing."),
798
- eligibleHarnesses: z.array(NonBlankString).optional().describe("New sticky eligible harness pool."),
873
+ state: z.enum(["active", "closed"]).optional().describe("New open/archive state."),
874
+ primaryHarness: NonBlankString.nullable()
875
+ .optional()
876
+ .describe("New sticky primary harness; null clears back to engine routing."),
877
+ eligibleHarnesses: z
878
+ .array(NonBlankString)
879
+ .optional()
880
+ .describe("New sticky eligible harness pool."),
799
881
  })
800
882
  .strict()
801
883
  .describe("Request body for PATCH /threads/:id: rename, archive, or switch sticky routing.");
802
- /** Apply an isolated thread's accumulated worktree diff to the project. */
803
- export const ControlThreadApplyRequest = z
804
- .object({
805
- mode: z
806
- .enum(["apply", "branch", "commit", "pr"])
807
- .default("apply")
808
- .describe("Delivery mode: apply to the tree, or as a branch, commit, or PR."),
809
- branch: z.string().optional().describe("Branch name for branch/pr modes."),
810
- message: z.string().optional().describe("Commit message for commit/pr modes."),
811
- })
812
- .strict()
813
- .describe("Request body applying an isolated thread's accumulated worktree diff to the project.");
814
- export const ControlThreadApplyResponse = z
815
- .object({
816
- applied: z.boolean().describe("Whether anything was delivered."),
817
- status: z
818
- .enum(["applied", "branched", "committed", "pr_opened", "empty", "conflict", "rejected"])
819
- .describe("Delivery outcome: applied, branched, committed, pr_opened, empty (no diff), conflict, or rejected."),
820
- /** True when the project HEAD moved past the thread base since the thread started. */
821
- headMoved: z.boolean().default(false).describe("True when the project HEAD moved past the thread base since the thread started."),
822
- detail: z.string().nullable().default(null).describe("Human-readable detail."),
823
- })
824
- .describe("Response to a thread apply.");
825
884
  export const ControlThreadListResponse = z
826
885
  .object({
827
886
  threads: z.array(ControlThread).default([]).describe("All threads."),
@@ -838,20 +897,42 @@ export const HarnessStatusDto = z
838
897
  .object({
839
898
  id: z.string().describe("Harness id."),
840
899
  status: AdapterStatus,
841
- manifest: HarnessManifest.nullable().optional().describe("The harness's declared manifest, when available."),
842
- enabledIntents: z.array(z.string()).default([]).describe("Intents the gateway will route to this harness."),
900
+ manifest: HarnessManifest.nullable()
901
+ .optional()
902
+ .describe("The harness's declared manifest, when available."),
903
+ enabledIntents: z
904
+ .array(z.string())
905
+ .default([])
906
+ .describe("Intents the gateway will route to this harness."),
843
907
  disabledIntents: z.array(z.string()).default([]).describe("Intents the doctor disabled."),
844
908
  checks: z.array(ConformanceCheck).default([]).describe("Doctor probe results."),
845
- reasons: z.array(z.string()).default([]).describe("Human-readable reasons for degraded/unavailable status."),
909
+ reasons: z
910
+ .array(z.string())
911
+ .default([])
912
+ .describe("Human-readable reasons for degraded/unavailable status."),
913
+ authSources: z
914
+ .array(AuthSourceReadiness)
915
+ .default([])
916
+ .describe("Doctor-backed readiness by authentication source; an empty array means readiness was not reported."),
846
917
  /** The user's configured per-harness default model, if any. */
847
- configuredModel: z.string().nullable().default(null).describe("The user's configured per-harness default model, if any."),
918
+ configuredModel: z
919
+ .string()
920
+ .nullable()
921
+ .default(null)
922
+ .describe("The user's configured per-harness default model, if any."),
848
923
  /** Strict truth-source check of `configuredModel`: null when no model
849
924
  * is configured; a rejection carries the actionable message so UIs render
850
925
  * the same honesty `claudexor doctor` prints. */
851
926
  configuredModelCheck: z
852
927
  .object({
853
- status: z.enum(["ok", "rejected"]).describe("Whether the configured model passes the strict truth-source check."),
854
- message: z.string().nullable().default(null).describe("Actionable rejection message, when rejected."),
928
+ status: z
929
+ .enum(["ok", "rejected"])
930
+ .describe("Whether the configured model passes the strict truth-source check."),
931
+ message: z
932
+ .string()
933
+ .nullable()
934
+ .default(null)
935
+ .describe("Actionable rejection message, when rejected."),
855
936
  })
856
937
  .nullable()
857
938
  .default(null)
@@ -860,7 +941,10 @@ export const HarnessStatusDto = z
860
941
  .describe("Doctor-backed status row for one harness: status, intents, checks, and configured-model validity.");
861
942
  export const ControlHarnessListResponse = z
862
943
  .object({
863
- harnesses: z.array(HarnessStatusDto).default([]).describe("Status rows for all known harnesses."),
944
+ harnesses: z
945
+ .array(HarnessStatusDto)
946
+ .default([])
947
+ .describe("Status rows for all known harnesses."),
864
948
  })
865
949
  .describe("Response for GET /harnesses.");
866
950
  /**
@@ -873,7 +957,10 @@ export const ControlHarnessListResponse = z
873
957
  export const ControlHarnessModelsResponse = z
874
958
  .object({
875
959
  harnessId: z.string().describe("Harness the models belong to."),
876
- models: z.array(HarnessModel).default([]).describe("Enumerable models; empty when the harness has no model truth source."),
960
+ models: z
961
+ .array(HarnessModel)
962
+ .default([])
963
+ .describe("Enumerable models; empty when the harness has no model truth source."),
877
964
  source: z
878
965
  .enum(["api", "manifest", "none"])
879
966
  .describe("Provenance of the list: api (a live vendor enumeration), manifest (the manifest's known-good hint set), or none (no model truth source; explicit models are refused)."),
@@ -888,8 +975,10 @@ export const ControlHarnessModelsResponse = z
888
975
  .describe("Models enumerable for one harness, with honest provenance.");
889
976
  export const ControlSettingsSnapshot = z
890
977
  .object({
891
- sources: z.array(z.string()).default([]).describe("Config file paths that contributed to the snapshot."),
892
- defaultPortfolio: Portfolio.default("subscription-first").describe("Budget portfolio used when a run does not specify one."),
978
+ sources: z
979
+ .array(z.string())
980
+ .default([])
981
+ .describe("Config file paths that contributed to the snapshot."),
893
982
  /** How long a run waits for an interactive answer before a benign decline. */
894
983
  interactionTimeoutMs: z
895
984
  .number()
@@ -899,26 +988,44 @@ export const ControlSettingsSnapshot = z
899
988
  .describe("How long a run waits for an interactive answer before a benign decline, in milliseconds."),
900
989
  routing: z
901
990
  .object({
902
- defaultPolicy: z.enum(["auto", "primary"]).default("auto").describe("Default routing policy."),
903
- primaryHarness: z.string().nullable().default(null).describe("Global default primary harness; null = engine decides."),
904
- eligibleHarnesses: z.array(z.string()).default([]).describe("Harness pool eligible for routing/races; empty = all available."),
991
+ defaultPolicy: z
992
+ .enum(["auto", "primary"])
993
+ .default("auto")
994
+ .describe("Default routing policy."),
995
+ primaryHarness: z
996
+ .string()
997
+ .nullable()
998
+ .default(null)
999
+ .describe("Global default primary harness; null = engine decides."),
1000
+ eligibleHarnesses: z
1001
+ .array(z.string())
1002
+ .default([])
1003
+ .describe("Harness pool eligible for routing/races; empty = all available."),
905
1004
  envInheritance: z
906
1005
  .enum(["mirror_native", "clean"])
907
1006
  .default("mirror_native")
908
1007
  .describe("How the child harness env is built: mirror_native inherits the shell env; clean spawns from a minimal allowlist."),
909
1008
  authPreference: AuthPreference.default("auto"),
1009
+ goal: RoutingGoal.default("auto"),
1010
+ paidFallback: PaidFallback.default("when_unavailable"),
1011
+ qualityTiers: QualityTierSet,
910
1012
  })
911
1013
  .default({})
912
1014
  .describe("Global routing settings."),
913
1015
  budget: z
914
1016
  .object({
915
- maxUsdPerRun: z.number().nullable().default(null).describe("Global USD cap per run; null = no cap."),
1017
+ paidBudgetPerRun: PaidBudget.default({ kind: "unlimited" }),
916
1018
  })
917
1019
  .default({})
918
1020
  .describe("Global budget limits."),
919
1021
  runtime: z
920
1022
  .object({
921
- reviewerTimeoutMs: z.number().int().positive().default(600_000).describe("Wall-clock timeout for a reviewer run, in milliseconds."),
1023
+ reviewerTimeoutMs: z
1024
+ .number()
1025
+ .int()
1026
+ .positive()
1027
+ .default(600_000)
1028
+ .describe("Wall-clock timeout for a reviewer run, in milliseconds."),
922
1029
  harnessInactivityTimeoutMs: z
923
1030
  .number()
924
1031
  .int()
@@ -927,9 +1034,24 @@ export const ControlSettingsSnapshot = z
927
1034
  .describe("Inactivity watchdog for harness streams, in milliseconds."),
928
1035
  transientRetry: z
929
1036
  .object({
930
- maxRetries: z.number().int().nonnegative().default(2).describe("Maximum retries for a transient failure."),
931
- initialDelayMs: z.number().int().nonnegative().default(1_000).describe("Initial retry delay in milliseconds."),
932
- maxDelayMs: z.number().int().nonnegative().default(10_000).describe("Maximum retry delay in milliseconds."),
1037
+ maxRetries: z
1038
+ .number()
1039
+ .int()
1040
+ .nonnegative()
1041
+ .default(2)
1042
+ .describe("Maximum retries for a transient failure."),
1043
+ initialDelayMs: z
1044
+ .number()
1045
+ .int()
1046
+ .nonnegative()
1047
+ .default(1_000)
1048
+ .describe("Initial retry delay in milliseconds."),
1049
+ maxDelayMs: z
1050
+ .number()
1051
+ .int()
1052
+ .nonnegative()
1053
+ .default(10_000)
1054
+ .describe("Maximum retry delay in milliseconds."),
933
1055
  })
934
1056
  .default({})
935
1057
  .describe("Bounded retry policy for transient failures."),
@@ -939,15 +1061,45 @@ export const ControlSettingsSnapshot = z
939
1061
  harnesses: z
940
1062
  .record(z.string(), z
941
1063
  .object({
942
- enabled: z.boolean().default(true).describe("Whether the harness participates in routing."),
943
- defaultModel: z.string().nullable().default(null).describe("Per-harness default model; null = the harness's own default."),
944
- effort: EffortHint.nullable().default(null).describe("Default reasoning effort; null = harness default."),
945
- maxTurns: z.number().int().positive().nullable().default(null).describe("Default max agent turns; null = no limit."),
946
- maxRounds: z.number().int().positive().nullable().default(null).describe("Default max convergence rounds; null = engine default."),
947
- maxUsd: z.number().nonnegative().nullable().default(null).describe("Per-harness USD cap; null = no cap."),
948
- toolsAllow: z.array(z.string()).default([]).describe("Tool names allowed for this harness."),
949
- toolsDeny: z.array(z.string()).default([]).describe("Tool names denied for this harness."),
950
- fallbackModel: z.string().nullable().default(null).describe("Model to fall back to on typed fallback signals; null = none."),
1064
+ enabled: z
1065
+ .boolean()
1066
+ .default(true)
1067
+ .describe("Whether the harness participates in routing."),
1068
+ defaultModel: z
1069
+ .string()
1070
+ .nullable()
1071
+ .default(null)
1072
+ .describe("Per-harness default model; null = the harness's own default."),
1073
+ effort: EffortHint.nullable()
1074
+ .default(null)
1075
+ .describe("Default reasoning effort; null = harness default."),
1076
+ maxTurns: z
1077
+ .number()
1078
+ .int()
1079
+ .positive()
1080
+ .nullable()
1081
+ .default(null)
1082
+ .describe("Default max agent turns; null = no limit."),
1083
+ maxRounds: z
1084
+ .number()
1085
+ .int()
1086
+ .positive()
1087
+ .nullable()
1088
+ .default(null)
1089
+ .describe("Default max convergence rounds; null = engine default."),
1090
+ toolsAllow: z
1091
+ .array(z.string())
1092
+ .default([])
1093
+ .describe("Tool names allowed for this harness."),
1094
+ toolsDeny: z
1095
+ .array(z.string())
1096
+ .default([])
1097
+ .describe("Tool names denied for this harness."),
1098
+ fallbackModel: z
1099
+ .string()
1100
+ .nullable()
1101
+ .default(null)
1102
+ .describe("Model to fall back to on typed fallback signals; null = none."),
951
1103
  web: ExternalContextPolicy.default("auto").describe("Default web policy for this harness."),
952
1104
  authPreference: AuthPreference.default("auto"),
953
1105
  })
@@ -963,14 +1115,31 @@ export const ControlSettingsSnapshot = z
963
1115
  export const ControlHarnessSettingsPatch = z
964
1116
  .object({
965
1117
  enabled: z.boolean().optional().describe("Enable/disable the harness for routing."),
966
- defaultModel: NonBlankString.nullable().optional().describe("New per-harness default model; null clears it."),
967
- effort: EffortHint.nullable().optional().describe("New default reasoning effort; null clears it."),
968
- maxTurns: z.number().int().positive().nullable().optional().describe("New max agent turns; null clears the limit."),
969
- maxRounds: z.number().int().positive().nullable().optional().describe("New max convergence rounds; null clears it."),
970
- maxUsd: z.number().nonnegative().nullable().optional().describe("New per-harness USD cap; null clears it."),
1118
+ defaultModel: NonBlankString.nullable()
1119
+ .optional()
1120
+ .describe("New per-harness default model; null clears it."),
1121
+ effort: EffortHint.nullable()
1122
+ .optional()
1123
+ .describe("New default reasoning effort; null clears it."),
1124
+ maxTurns: z
1125
+ .number()
1126
+ .int()
1127
+ .positive()
1128
+ .nullable()
1129
+ .optional()
1130
+ .describe("New max agent turns; null clears the limit."),
1131
+ maxRounds: z
1132
+ .number()
1133
+ .int()
1134
+ .positive()
1135
+ .nullable()
1136
+ .optional()
1137
+ .describe("New max convergence rounds; null clears it."),
971
1138
  toolsAllow: z.array(NonBlankString).optional().describe("New tool allowlist."),
972
1139
  toolsDeny: z.array(NonBlankString).optional().describe("New tool denylist."),
973
- fallbackModel: NonBlankString.nullable().optional().describe("New fallback model; null clears it."),
1140
+ fallbackModel: NonBlankString.nullable()
1141
+ .optional()
1142
+ .describe("New fallback model; null clears it."),
974
1143
  web: ExternalContextPolicy.optional().describe("New default web policy."),
975
1144
  authPreference: AuthPreference.optional().describe("New auth route preference."),
976
1145
  })
@@ -978,14 +1147,28 @@ export const ControlHarnessSettingsPatch = z
978
1147
  .describe("Partial per-harness settings patch; absent fields keep their stored value, and a typoed key 400s (strict).");
979
1148
  export const ControlSettingsUpdateRequest = z
980
1149
  .object({
981
- defaultPortfolio: Portfolio.optional(),
982
- interactionTimeoutMs: z.number().int().positive().optional().describe("New interactive-answer timeout, in milliseconds."),
1150
+ routingGoal: RoutingGoal.optional(),
1151
+ paidFallback: PaidFallback.optional(),
1152
+ qualityTiers: QualityTierSet.optional(),
1153
+ interactionTimeoutMs: z
1154
+ .number()
1155
+ .int()
1156
+ .positive()
1157
+ .optional()
1158
+ .describe("New interactive-answer timeout, in milliseconds."),
983
1159
  routingPolicy: z.enum(["auto", "primary"]).optional().describe("New default routing policy."),
984
- primaryHarness: NonBlankString.nullable().optional().describe("New global primary harness; null clears back to engine routing."),
985
- eligibleHarnesses: z.array(NonBlankString).optional().describe("New global eligible harness pool."),
986
- envInheritance: z.enum(["mirror_native", "clean"]).optional().describe("New child harness env composition mode."),
987
- maxUsdPerRun: z.number().nonnegative().optional().describe("New global USD cap per run (mutually exclusive with clearMaxUsdPerRun)."),
988
- clearMaxUsdPerRun: z.boolean().optional().describe("Clear the global USD cap per run (mutually exclusive with maxUsdPerRun)."),
1160
+ primaryHarness: NonBlankString.nullable()
1161
+ .optional()
1162
+ .describe("New global primary harness; null clears back to engine routing."),
1163
+ eligibleHarnesses: z
1164
+ .array(NonBlankString)
1165
+ .optional()
1166
+ .describe("New global eligible harness pool."),
1167
+ envInheritance: z
1168
+ .enum(["mirror_native", "clean"])
1169
+ .optional()
1170
+ .describe("New child harness env composition mode."),
1171
+ paidBudgetPerRun: PaidBudget.optional().describe("New global incremental-cash budget per run."),
989
1172
  authPreference: AuthPreference.optional().describe("New global auth route preference."),
990
1173
  harnesses: z
991
1174
  .record(NonBlankString, ControlHarnessSettingsPatch)
@@ -993,30 +1176,5 @@ export const ControlSettingsUpdateRequest = z
993
1176
  .describe("Per-harness settings patches keyed by harness id."),
994
1177
  })
995
1178
  .strict()
996
- .superRefine((value, ctx) => {
997
- if (value.maxUsdPerRun !== undefined && value.clearMaxUsdPerRun === true) {
998
- ctx.addIssue({
999
- code: z.ZodIssueCode.custom,
1000
- path: ["maxUsdPerRun"],
1001
- message: "maxUsdPerRun and clearMaxUsdPerRun are mutually exclusive",
1002
- });
1003
- }
1004
- })
1005
1179
  .describe("Request body for PATCH /settings; absent fields keep their stored values.");
1006
- /** Secret list row: exactly what the store's list() can honestly produce
1007
- * (the never-populated harnesses/env/description fields were retired in the
1008
- * v0.15 triage). */
1009
- export const SecretMetadata = z
1010
- .object({
1011
- name: z.string().describe("Secret name/label."),
1012
- backend: z.enum(["keychain", "file"]).describe("Where the secret is stored: the OS keychain or a file store."),
1013
- present: z.boolean().default(true).describe("Whether a value is actually stored."),
1014
- })
1015
- .describe("Secret list row: name, storage backend, and presence — never the value.");
1016
- export const ControlSecretListResponse = z
1017
- .object({
1018
- backend: z.enum(["keychain", "file"]).describe("Active secret store backend."),
1019
- secrets: z.array(SecretMetadata).default([]).describe("Stored secrets (metadata only, never values)."),
1020
- })
1021
- .describe("Response for listing stored secrets (metadata only).");
1022
1180
  //# sourceMappingURL=control.js.map