@intentic/sandbox-contract 1.168.0 → 1.170.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 (46) hide show
  1. package/dist/agent-catalog.d.ts.map +1 -1
  2. package/dist/agent-catalog.js +1 -1
  3. package/dist/agent-catalog.js.map +1 -1
  4. package/dist/contracts/agent.contract.d.ts +11 -0
  5. package/dist/contracts/agent.contract.d.ts.map +1 -1
  6. package/dist/contracts/agent.contract.js +2 -1
  7. package/dist/contracts/agent.contract.js.map +1 -1
  8. package/dist/contracts/extensions.contract.d.ts +7 -0
  9. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  10. package/dist/contracts/extensions.contract.js +2 -1
  11. package/dist/contracts/extensions.contract.js.map +1 -1
  12. package/dist/contracts/prepush.contract.d.ts +25 -0
  13. package/dist/contracts/prepush.contract.d.ts.map +1 -0
  14. package/dist/contracts/prepush.contract.js +8 -0
  15. package/dist/contracts/prepush.contract.js.map +1 -0
  16. package/dist/contracts/settings.contract.d.ts +8 -8
  17. package/dist/index.d.ts +51 -55
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/quick-model.d.ts +1 -0
  22. package/dist/quick-model.d.ts.map +1 -1
  23. package/dist/quick-model.js +1 -1
  24. package/dist/quick-model.js.map +1 -1
  25. package/dist/schemas.d.ts +36 -46
  26. package/dist/schemas.d.ts.map +1 -1
  27. package/dist/schemas.js +16 -23
  28. package/dist/schemas.js.map +1 -1
  29. package/dist/workspace-state.d.ts.map +1 -1
  30. package/dist/workspace-state.js +4 -10
  31. package/dist/workspace-state.js.map +1 -1
  32. package/package.json +2 -2
  33. package/src/agent-catalog.ts +10 -7
  34. package/src/contracts/agent.contract.ts +14 -1
  35. package/src/contracts/extensions.contract.ts +5 -0
  36. package/src/contracts/prepush.contract.ts +16 -0
  37. package/src/index.ts +3 -3
  38. package/src/quick-model.ts +4 -2
  39. package/src/schemas.test.ts +11 -10
  40. package/src/schemas.ts +88 -102
  41. package/src/workspace-state.ts +8 -10
  42. package/dist/contracts/gate.contract.d.ts +0 -47
  43. package/dist/contracts/gate.contract.d.ts.map +0 -1
  44. package/dist/contracts/gate.contract.js +0 -9
  45. package/dist/contracts/gate.contract.js.map +0 -1
  46. package/src/contracts/gate.contract.ts +0 -19
package/src/schemas.ts CHANGED
@@ -414,7 +414,7 @@ export type UsageWindow = z.infer<typeof UsageWindowSchema>;
414
414
  // An account's headroom: EVERY window the provider reports, read together, plus when the reading was taken.
415
415
  // All of them, not the binding one, because "which pool is binding" changes between turns and a reader
416
416
  // comparing accounts needs the same pools on every row. How the reading is TAKEN is per provider and stops at
417
- // the daemon's readers: Claude's rides the turn's own stream, ChatGPT's and Google's are pulled through
417
+ // the daemon's readers: Claude's rides the turn's own stream, ChatGPT's, Google's and Kimi's are pulled through
418
418
  // CLIProxyAPI's credential-scoped management call. All of them are control requests, so none costs tokens.
419
419
  //
420
420
  // Within one window utilization only climbs, so an un-reset window stays a valid FLOOR however old it is; past
@@ -426,13 +426,45 @@ export const AccountUsageSchema = z.object({
426
426
  });
427
427
  export type AccountUsage = z.infer<typeof AccountUsageSchema>;
428
428
 
429
+ /* THE LAST TIME A PROVIDER ACTUALLY REFUSED A TURN — the other half of "can I run on this", and the half no
430
+ * meter can supply.
431
+ *
432
+ * A snapshot above is POLLED and therefore always a floor: read at turn end (Claude) or on a five-minute sweep
433
+ * (the routed subscriptions), and account-wide, so every other client on the plan spends the same pools without
434
+ * this sandbox hearing about it. A refusal is the opposite kind of fact — observed, exact, and timestamped by
435
+ * the only event that proves the plan said no. Between them they answer a question neither can alone: a green
436
+ * meter beside "refused a turn 4 minutes ago" means the reading is stale, not that the account has room.
437
+ *
438
+ * Keyed by PROVIDER rather than by account, because that is the resolution the daemon honestly has. A native
439
+ * Claude turn knows which account served it and names it; a routed turn does not — CLIProxyAPI picks the auth
440
+ * file itself and only refuses once every credential it holds is cooling down, which makes the refusal a fact
441
+ * about the provider in the first place.
442
+ *
443
+ * `kind` is read off what the provider SAID, not off the frame code the harness filed it under, because those
444
+ * two disagree: Kimi answers a spent plan with `403 You've reached your usage limit for this billing cycle`,
445
+ * which the CLI prints under "Failed to authenticate" and the stream codes as a refused credential. Sending
446
+ * someone to reconnect a perfectly good account is the cost of believing the code over the sentence. */
447
+ export const ProviderRefusalSchema = z.object({
448
+ // Epoch MS, matching AccountUsage.measuredAt — the two are read side by side.
449
+ at: z.number(),
450
+ kind: z.enum(["limit", "auth"]),
451
+ // The provider's own sentence, verbatim. It is the only part that says WHICH pool or WHICH credential.
452
+ message: z.string(),
453
+ // The account that was serving, when the daemon knows it (native turns only — see above).
454
+ account: z.string().optional(),
455
+ });
456
+ export type ProviderRefusal = z.infer<typeof ProviderRefusalSchema>;
457
+
458
+ export const ProviderRefusalsSchema = z.object({ refusals: z.record(z.string(), ProviderRefusalSchema) });
459
+ export type ProviderRefusals = z.infer<typeof ProviderRefusalsSchema>;
460
+
429
461
  // One connected subscription in the translator. `name` is CLIProxyAPI's auth-file name — the stable store key a
430
462
  // disconnect addresses — and `label` the sign-in identity it reported (the account email, else the file name).
431
463
  export const TranslatorAccountSchema = z.object({
432
464
  name: z.string(),
433
465
  label: z.string(),
434
466
  // The same headroom an OauthAccount carries, on the same field, for the same reason: the account rows are
435
- // one list to the reader. Optional because a provider whose quota this sandbox cannot read (Grok, Kimi) —
467
+ // one list to the reader. Optional because a provider whose quota this sandbox cannot read (Grok) —
436
468
  // or one that did not answer — must still render as the connected account it is, with a dot instead of a
437
469
  // ring.
438
470
  usage: AccountUsageSchema.optional(),
@@ -781,34 +813,26 @@ export const SandboxSettingsSchema = z.object({
781
813
  * OFF still records the interruption: the fleet card reads `interrupted` (see AgentStatusSchema) and an
782
814
  * automation's row shows an `interrupted` run — nothing is re-run, but nothing is silently lost either. */
783
815
  autoResumeOnRestart: z.boolean().default(true),
784
- /* THE LANDING GATE — the check command run over the COMPOSITE of landed work after a landing debounce.
785
- * Empty ⇒ no gate at all, which is the default: only the owner knows what verifies this workspace, and a
786
- * guessed command that fails on a fresh clone would read as the gate finding a bug on its first run.
816
+ /* THE PRE-PUSH CHECK — the command run when the user pushes, before anything leaves the machine.
817
+ * Empty ⇒ no check at all, which is the default: only the owner knows what verifies this workspace, and a
818
+ * guessed command that fails on a fresh clone would read as the check finding a bug on its first run.
787
819
  *
788
820
  * Configuring it is the opt-in, which is why there is no separate enable flag to disagree with it. The
789
- * command runs in the workspace root through `sh -c`, exactly as a terminal would run it (see gate/gate.ts
790
- * for why this is NOT an automation guard: a suite outlives GUARD_TIMEOUT_MS, and a timed-out guard reads
791
- * as "skipped" a silent green over a suite that never finished). */
792
- gateCommand: z.string().max(500).default(""),
793
- /* How long after a land the gate waits before running. A landing burst is the case this exists for: five
794
- * agents finishing within a minute of each other are five lands, and a gate that ran per land would spend
795
- * five suites to answer about four trees nobody will ever push. Every land re-arms the timer, so the run
796
- * happens once, on the tree the user is about to review.
821
+ * command runs in the workspace root through `sh -c`, exactly as a terminal would run it. */
822
+ prepushCommand: z.string().max(500).default(""),
823
+ // Ceiling on one run, after which the child's whole process group is killed and the result is `failed` with
824
+ // `timedOut`. Never a pass: a suite that did not finish has said nothing about the tree, and the one thing
825
+ // this check exists to prevent is a green light nobody earned.
826
+ prepushTimeoutMs: z.number().min(60_000).max(3_600_000).default(900_000),
827
+ /* WHAT THE SUGGESTED FIX SESSION RUNS ON when the check fails `${provider}:${model}` (quickModelKey), and
828
+ * the reasoning effort beside it. Both empty ⇒ whatever the chat composer would have started with, which is
829
+ * the right default precisely because it is the model the user already chose to work with.
797
830
  *
798
- * It counts from the last LAND and nothing else explicitly not "until the fleet is idle". Agents here run
799
- * for hours, so a fleet of twenty with one long runner would never present a quiet moment, and a gate that
800
- * waited for one would only ever fire when clicked (gate/gate.ts). */
801
- gateQuietMs: z.number().min(0).max(600_000).default(20_000),
802
- // Ceiling on one gate run, after which the child is killed and the verdict is `failed` with `timedOut`.
803
- // Never a pass: a suite that did not finish has not said anything about the tree, and the one thing this
804
- // gate exists to prevent is a green light nobody earned.
805
- gateTimeoutMs: z.number().min(60_000).max(3_600_000).default(900_000),
806
- /* Wake a fixer automatically when the gate goes red, instead of only lighting the badge. ON with a
807
- * configured command, and the difference from the unattended spend a usage limit refuses is
808
- * that the spend here is the POINT: a red gate whose fix waits for the user to notice has moved the CI
809
- * round-trip into the workspace without removing it from the user's day. One attempt per verdict, so a
810
- * command that fails for a reason no agent can fix costs one turn, not a loop (gate/gate.ts). */
811
- gateAutoFix: z.boolean().default(true),
831
+ * Pinned here rather than resolved cheapest-first like `quickModel`: this is not a one-click helper, it is a
832
+ * turn that has to read a failing suite and repair it, so the choice is the user's and worth stating. The
833
+ * suggestion dialog seeds from these and stays editable the setting decides where the dialog OPENS. */
834
+ prepushFixModel: z.string().default(""),
835
+ prepushFixEffort: z.string().default(""),
812
836
  });
813
837
  export type SandboxSettings = z.infer<typeof SandboxSettingsSchema>;
814
838
 
@@ -1969,6 +1993,10 @@ export const ExtensionSummarySchema = z.object({
1969
1993
  // Image-baked first-party extension (no git checkout, not removable) vs a git-installed capability — the
1970
1994
  // web hides the uninstall affordance for baked ones.
1971
1995
  builtin: z.boolean(),
1996
+ // The owner's switch (.intentic/extension-enablement.json). A disabled extension is still listed — that's
1997
+ // what makes it switchable back on — but the daemon wires none of its contributions up and the web host
1998
+ // doesn't activate it.
1999
+ enabled: z.boolean(),
1972
2000
  });
1973
2001
  export type ExtensionSummary = z.infer<typeof ExtensionSummarySchema>;
1974
2002
  export const ExtensionsListSchema = z.object({ extensions: z.array(ExtensionSummarySchema) });
@@ -1985,6 +2013,9 @@ export const ExtensionSettingsInputSchema = z.object({
1985
2013
  id: z.string(),
1986
2014
  settings: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
1987
2015
  });
2016
+ // Flip one extension on or off. Persisted by publisher.name (like settings), so the choice outlives the
2017
+ // checkout; the daemon's immediate half of the flip — declared processes — converges in the same handler.
2018
+ export const ExtensionEnabledInputSchema = z.object({ id: z.string(), enabled: z.boolean() });
1988
2019
  // One declared background process (contributes.processes) — status/start/stop, addressed by the capability
1989
2020
  // entry id + the manifest's process name. Undeclared names are NOT_FOUND, the manifest-honesty rule again.
1990
2021
  export const ExtensionProcessParamSchema = z.object({ id: z.string(), name: z.string() });
@@ -2243,95 +2274,51 @@ export type CiRunParam = z.infer<typeof CiRunParamSchema>;
2243
2274
  export const CiFixResponseSchema = z.object({ conversationId: z.string() });
2244
2275
  export type CiFixResponse = z.infer<typeof CiFixResponseSchema>;
2245
2276
 
2246
- /* ---- the landing gate: the workspace's own verdict on the composite of landed work ----
2247
- *
2248
- * WHERE THIS SITS, and why it is not one of the four other places it could:
2277
+ /* ---- the pre-push check: the workspace's own answer to "would this push go red" ----
2249
2278
  *
2250
- * A fleet of 5-20 agents lands work into the main tree as UNCOMMITTED changes (agents/land.ts), the user
2251
- * reviews and commits it by parts, pushes, and CI answers minutes later. This gate front-runs that answer by
2252
- * asking the same question of the same artifact, before the push.
2279
+ * WHERE THIS SITS. A fleet of 5-20 agents lands work into the main tree, the user reviews and commits it by
2280
+ * parts, pushes, and CI answers minutes later. The check front-runs that answer at the push itself — the last
2281
+ * moment before the work leaves the machine, and the first moment at which what will be pushed is finally
2282
+ * settled.
2253
2283
  *
2254
- * NOT inside an agent's turn. An isolated worktree's `node_modules` reads as the MAIN checkout's, so a
2255
- * monorepo's workspace links resolve cross-package imports to /work's sources rather than the worktree's edited
2256
- * ones (agents/worktrees.ts). A suite run in a worktree therefore tests the agent's edits against everyone
2257
- * else's UNEDITED siblings: it invents failures that don't exist and passes changes that break on the
2258
- * composite, and two agents editing one contract each go green alone and red together. The composite is the
2259
- * only honest artifact, and it exists in exactly one place — the main working tree.
2284
+ * WHY THE PUSH AND NOT THE LAND, which is where this used to run. A post-land verdict is about a tree that
2285
+ * keeps moving: the user commits by parts, another agent lands, an edit arrives — so the verdict spent its life
2286
+ * either stale or being recomputed, and needed a content fingerprint, a staleness rule and a badge to say which.
2287
+ * All of that machinery existed to answer a question the push asks for free, because at the push there is
2288
+ * exactly one artifact and the user is standing in front of it waiting.
2260
2289
  *
2261
- * NOT at commit. The user commits BY PARTS, and a suite reads the worktree, not the index so a verdict taken
2262
- * at a partial commit describes a tree that never gets pushed as such. Commit is where a verdict is DISPLAYED
2263
- * (ReviewPanel's badge), computed earlier.
2264
- *
2265
- * NOT at push. By then HEAD has moved, per-path attribution has expired (agents/origins.ts), and the agents may
2266
- * be archived with their worktrees reclaimed — so the fix starts cold, in the same position `/ci/fix` is in.
2267
- * That saves the CI round-trip and none of the context switch.
2268
- *
2269
- * So: after the land, before the staging — the one window where the artifact is what CI will see, attribution
2270
- * is still live, and nobody is waiting on it. */
2290
+ * SO THERE IS NO STORED VERDICT AND NOTHING IS POLLED AT REST. A run exists while it runs, reports to the
2291
+ * dialog that started it, and is gone. Nothing survives a daemon restart because nothing needs to: the next
2292
+ * push asks again. */
2271
2293
 
2272
- /* What the gate has to say about the tree right now.
2294
+ /* Where a run is.
2273
2295
  *
2274
- * idle — no command configured, or nothing has run yet.
2275
- * armed — work landed; the quiet period is counting down (see gateQuietMs).
2296
+ * idle — nothing has run in this daemon's life, or the last run was cleared.
2276
2297
  * running — the check is live. `output` grows as it streams.
2277
- * passed — exited 0 over `fingerprint`.
2278
- * failed — exited non-zero, or was killed by gateTimeoutMs (`timedOut`). The state a fix answers.
2279
- * error — the gate itself could not run: the command was not spawnable. NOT a fix-able failure, because
2280
- * there is nothing wrong with the code — the gate is misconfigured, and saying "tests failed"
2298
+ * passed — exited 0. The push goes.
2299
+ * failed — exited non-zero, or was killed by prepushTimeoutMs (`timedOut`). The state a fix answers.
2300
+ * error — the check could not run at all: the command was not spawnable. NOT a fix-able failure, because
2301
+ * there is nothing wrong with the code — the command is misconfigured, and saying "tests failed"
2281
2302
  * would send an agent hunting a bug that isn't there.
2282
- * cancelled — the user stopped the run, or the tree moved under it.
2303
+ * cancelled — the user stopped the run.
2283
2304
  */
2284
- export const GateStatusSchema = z.enum(["idle", "armed", "running", "passed", "failed", "error", "cancelled"]);
2285
- export type GateStatus = z.infer<typeof GateStatusSchema>;
2286
-
2287
- // An agent whose landed work the failure implicates. `paths` are its attributed files that the check's own
2288
- // output NAMED — empty when the output named none of them, which is the honest shape for a failure that could
2289
- // not be pinpointed (an integration break between two deltas, a suite that prints no paths at all): the agent
2290
- // is listed because its work is in the tree under test, not because anything accused it.
2291
- export const GateAgentSchema = z.object({
2292
- agentId: z.string(),
2293
- title: z.string().optional(),
2294
- provider: AgentProviderSchema.optional(),
2295
- paths: z.array(z.string()),
2296
- });
2297
- export type GateAgent = z.infer<typeof GateAgentSchema>;
2298
-
2299
- // The fix turn one red verdict got. It is a workspace conversation because the composite it must reproduce
2300
- // lives as uncommitted content in the main working tree; it still has the same stable registry identity as any
2301
- // other conversation.
2302
- export const GateFixSchema = z.object({
2303
- startedAt: z.number(),
2304
- conversationId: z.string(),
2305
- // `running` while the turn streams; `done` when it ended cleanly, whatever the re-check then said;
2306
- // `error` when the turn itself failed (a provider outage, no credential), which is worth distinguishing
2307
- // because it is the one case where re-running the fix could still help.
2308
- outcome: z.enum(["running", "done", "error"]),
2309
- detail: z.string().optional(),
2310
- });
2311
- export type GateFix = z.infer<typeof GateFixSchema>;
2305
+ export const PrepushStatusSchema = z.enum(["idle", "running", "passed", "failed", "error", "cancelled"]);
2306
+ export type PrepushStatus = z.infer<typeof PrepushStatusSchema>;
2312
2307
 
2313
- export const GateVerdictSchema = z.object({
2314
- status: GateStatusSchema,
2315
- // The command this verdict ran, echoed rather than read back from settings: a verdict read after the
2308
+ export const PrepushRunSchema = z.object({
2309
+ status: PrepushStatusSchema,
2310
+ // The command this run executed, echoed rather than read back from settings: a result read after the
2316
2311
  // setting changed still has to say what produced it.
2317
2312
  command: z.string(),
2318
2313
  startedAt: z.number().optional(),
2319
2314
  finishedAt: z.number().optional(),
2320
2315
  exitCode: z.number().optional(),
2321
2316
  timedOut: z.boolean().optional(),
2322
- // The check's own output, tail-capped (GATE_OUTPUT_BYTES). The tail, not the head: a suite's verdict and
2317
+ // The check's own output, tail-capped (PREPUSH_OUTPUT_BYTES). The TAIL, not the head: a suite's verdict and
2323
2318
  // its failure summary are at the end, and a head-capped buffer of a chatty build is all progress lines.
2324
2319
  output: z.string(),
2325
- /* WHICH TREE this verdict is about — HEAD plus the shape of every repo's uncommitted content. Recomputed
2326
- * on read: when it no longer matches, the verdict is `stale` and the badge says so instead of asserting a
2327
- * green light over a tree that has since moved. This is what keeps a passed verdict from outliving its
2328
- * subject when the user edits, discards, or commits half of it. */
2329
- fingerprint: z.string(),
2330
- stale: z.boolean(),
2331
- implicated: z.array(GateAgentSchema),
2332
- fix: GateFixSchema.optional(),
2333
2320
  });
2334
- export type GateVerdict = z.infer<typeof GateVerdictSchema>;
2321
+ export type PrepushRun = z.infer<typeof PrepushRunSchema>;
2335
2322
 
2336
2323
  // ---- drafts: agent-proposed posts awaiting owner approval (.intentic/drafts/<id>.json) ----
2337
2324
  // One JSON file per draft. The AGENT creates drafts with its normal file tools — it can't call daemon routes,
@@ -2479,10 +2466,9 @@ export type PortForwardResult = z.infer<typeof PortForwardResultSchema>;
2479
2466
  // it lists from /system/browsers with the pages it has open (BrowserSessionSchema below).
2480
2467
  //
2481
2468
  // `activityAt` (epoch ms of the session's last output) and `exitCode` (the LAST window's exit status, absent
2482
- // while that pane still lives) are what let a finished session be READ rather than merely listed: the panel's
2483
- // Recent-terminals popover orders by the one and reports the other ("exit 1 · 1h ago"), and the daemon's
2484
- // retention sweep ages sessions out by the same clock. 0 is "tmux didn't say" — treated as unknown by both,
2485
- // never as 1970.
2469
+ // while that pane still lives) describe a session beyond "it exists": the panel's work popover orders its live
2470
+ // rows by the one and dates them off it, and the daemon's retention sweep ages sessions out by the same clock.
2471
+ // 0 is "tmux didn't say" — treated as unknown by both, never as 1970.
2486
2472
  export const TerminalSessionSchema = z.object({
2487
2473
  name: z.string(),
2488
2474
  label: z.string().optional(),
@@ -82,6 +82,14 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
82
82
  invalidates: [],
83
83
  why: "Held in a module-level shallowRef store per extension (web's extensionSettingsStore) with no query observer, and deliberately so: api.settings.get must answer SYNCHRONOUSLY from an extension's first activate() line, and the store outlives every component scope. A module-level QueryObserver is the one shape that would make invalidation refetch, and this app already ruled it out — it detaches on the queryClient.clear() at logout (see useSandbox's sandbox-list mirror). So a remote member's setting edit reaches this browser on its next load, not live.",
84
84
  },
85
+ /* Unlike the settings file above it, the on/off switch IS observed by a query — the Extensions tab's list,
86
+ * which carries each row's switch position — so a flip made elsewhere (another member, the agent writing the
87
+ * file) shows up here live. It does not re-run the host: activating or retiring an extension is the loader's
88
+ * reconcile, which the tab's own toggle triggers, so a remote flip takes effect on this browser's next load. */
89
+ {
90
+ path: ".intentic/extension-enablement.json",
91
+ invalidates: ["extensions"],
92
+ },
85
93
  {
86
94
  path: ".intentic/members.json",
87
95
  invalidates: [],
@@ -89,16 +97,6 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
89
97
  },
90
98
 
91
99
  // ---- daemon-owned, nothing derives from watching them ----
92
- {
93
- path: ".intentic/gate.json",
94
- invalidates: [],
95
- why: "The landing gate's verdict is POLLED on purpose (web's useGate). Its fingerprint pass rewrites this file every couple of seconds while a check runs, and pushing that back would refetch the review set — the daemon's most expensive read — on every poll.",
96
- },
97
- {
98
- path: ".intentic/gate-index/",
99
- invalidates: [],
100
- why: "The gate's per-repo git index. Machine state, rewritten continuously by the fingerprint pass.",
101
- },
102
100
  /* Agent session transcripts, rewritten on every streamed token.
103
101
  *
104
102
  * The memory notes under it (`projects/<slug>/memory/**`) ARE user-facing and the /memory view polls them
@@ -1,47 +0,0 @@
1
- export declare const gateContract: {
2
- verdict: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
3
- status: import("zod").ZodEnum<{
4
- armed: "armed";
5
- cancelled: "cancelled";
6
- error: "error";
7
- failed: "failed";
8
- idle: "idle";
9
- passed: "passed";
10
- running: "running";
11
- }>;
12
- command: import("zod").ZodString;
13
- startedAt: import("zod").ZodOptional<import("zod").ZodNumber>;
14
- finishedAt: import("zod").ZodOptional<import("zod").ZodNumber>;
15
- exitCode: import("zod").ZodOptional<import("zod").ZodNumber>;
16
- timedOut: import("zod").ZodOptional<import("zod").ZodBoolean>;
17
- output: import("zod").ZodString;
18
- fingerprint: import("zod").ZodString;
19
- stale: import("zod").ZodBoolean;
20
- implicated: import("zod").ZodArray<import("zod").ZodObject<{
21
- agentId: import("zod").ZodString;
22
- title: import("zod").ZodOptional<import("zod").ZodString>;
23
- provider: import("zod").ZodOptional<import("zod").ZodString>;
24
- paths: import("zod").ZodArray<import("zod").ZodString>;
25
- }, import("zod/v4/core").$strip>>;
26
- fix: import("zod").ZodOptional<import("zod").ZodObject<{
27
- startedAt: import("zod").ZodNumber;
28
- conversationId: import("zod").ZodString;
29
- outcome: import("zod").ZodEnum<{
30
- done: "done";
31
- error: "error";
32
- running: "running";
33
- }>;
34
- detail: import("zod").ZodOptional<import("zod").ZodString>;
35
- }, import("zod/v4/core").$strip>>;
36
- }, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
37
- run: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
38
- ok: import("zod").ZodLiteral<true>;
39
- }, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
40
- cancel: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
41
- ok: import("zod").ZodLiteral<true>;
42
- }, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
43
- fix: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
44
- ok: import("zod").ZodLiteral<true>;
45
- }, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
46
- };
47
- //# sourceMappingURL=gate.contract.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gate.contract.d.ts","sourceRoot":"","sources":["../../src/contracts/gate.contract.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,YAAY;IACrB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IACP,GAAG;;;IACH,MAAM;;;IACN,GAAG;;;CACN,CAAC"}
@@ -1,9 +0,0 @@
1
- import { oc } from "@orpc/contract";
2
- import { GateVerdictSchema, OkSchema } from "../schemas.js";
3
- export const gateContract = {
4
- verdict: oc.route({ method: "GET", path: "/gate/verdict" }).output(GateVerdictSchema),
5
- run: oc.route({ method: "POST", path: "/gate/run" }).output(OkSchema),
6
- cancel: oc.route({ method: "POST", path: "/gate/cancel" }).output(OkSchema),
7
- fix: oc.route({ method: "POST", path: "/gate/fix" }).output(OkSchema),
8
- };
9
- //# sourceMappingURL=gate.contract.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gate.contract.js","sourceRoot":"","sources":["../../src/contracts/gate.contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAY5D,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACrF,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IACrE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC3E,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;CACxE,CAAC"}
@@ -1,19 +0,0 @@
1
- import { oc } from "@orpc/contract";
2
- import { GateVerdictSchema, OkSchema } from "../schemas.js";
3
-
4
- // The landing gate — the check command run over the composite of landed work once the fleet goes quiet (see
5
- // GateVerdictSchema for where this sits and why). Four verbs, all about ONE verdict: the gate answers about the
6
- // main working tree, of which there is exactly one, so nothing here is addressed by id.
7
- //
8
- // `verdict` is the one read, and the panel polls it; it recomputes staleness per call, so a passed verdict stops
9
- // claiming a green light the moment the tree moves under it. The three writes answer `ok` and nothing else —
10
- // each starts work that outlives the request, so there is no result to return and the poll is what reports.
11
- // `run` arms nothing and waits for nothing: it starts the check now, the user's own "I'm about to commit, check
12
- // this". `fix` opens a seeded workspace conversation for a red verdict; it has the same registry lifecycle as
13
- // /ci/fix, minus the isolated worktree it must not have.
14
- export const gateContract = {
15
- verdict: oc.route({ method: "GET", path: "/gate/verdict" }).output(GateVerdictSchema),
16
- run: oc.route({ method: "POST", path: "/gate/run" }).output(OkSchema),
17
- cancel: oc.route({ method: "POST", path: "/gate/cancel" }).output(OkSchema),
18
- fix: oc.route({ method: "POST", path: "/gate/fix" }).output(OkSchema),
19
- };