@intentic/sandbox-contract 1.222.0 → 1.224.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 (86) hide show
  1. package/dist/chores/chores.js +1 -1
  2. package/dist/chores/chores.js.map +1 -1
  3. package/dist/chores/prompt.d.ts.map +1 -1
  4. package/dist/chores/prompt.js +3 -3
  5. package/dist/chores/prompt.js.map +1 -1
  6. package/dist/contracts/ports.contract.d.ts +11 -0
  7. package/dist/contracts/ports.contract.d.ts.map +1 -1
  8. package/dist/index.d.ts +11 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/schemas.d.ts +22 -0
  11. package/dist/schemas.d.ts.map +1 -1
  12. package/dist/schemas.js +3 -0
  13. package/dist/schemas.js.map +1 -1
  14. package/package.json +4 -4
  15. package/src/agent-catalog.ts +78 -78
  16. package/src/agent-run-model.ts +8 -8
  17. package/src/capability-env.ts +3 -3
  18. package/src/capability-secrets.ts +5 -5
  19. package/src/chores/chores.ts +67 -67
  20. package/src/chores/digest.ts +3 -3
  21. package/src/chores/extension-update.ts +3 -3
  22. package/src/chores/fix-deps.ts +3 -3
  23. package/src/chores/probes.ts +16 -16
  24. package/src/chores/prompt.ts +9 -9
  25. package/src/chores/stack.ts +17 -17
  26. package/src/chores/verdict.ts +23 -23
  27. package/src/contract-lock.ts +7 -7
  28. package/src/contracts/activity.contract.ts +1 -1
  29. package/src/contracts/agent.contract.ts +2 -2
  30. package/src/contracts/agents.contract.ts +11 -11
  31. package/src/contracts/automations.contract.ts +5 -5
  32. package/src/contracts/capabilities.contract.ts +7 -7
  33. package/src/contracts/chores.contract.ts +3 -3
  34. package/src/contracts/ci.contract.ts +2 -2
  35. package/src/contracts/claude.contract.ts +3 -3
  36. package/src/contracts/drafts.contract.ts +1 -1
  37. package/src/contracts/endpoints.contract.ts +2 -2
  38. package/src/contracts/extensions.contract.ts +8 -8
  39. package/src/contracts/git.contract.ts +6 -6
  40. package/src/contracts/grok.contract.ts +4 -4
  41. package/src/contracts/host.contract.ts +5 -5
  42. package/src/contracts/intentic.contract.ts +2 -2
  43. package/src/contracts/logs.contract.ts +1 -1
  44. package/src/contracts/loops.contract.ts +8 -8
  45. package/src/contracts/personas.contract.ts +8 -8
  46. package/src/contracts/ports.contract.ts +1 -1
  47. package/src/contracts/prepush.contract.ts +2 -2
  48. package/src/contracts/providers.contract.ts +4 -4
  49. package/src/contracts/public.contract.ts +1 -1
  50. package/src/contracts/push.contract.ts +2 -2
  51. package/src/contracts/secrets.contract.ts +2 -2
  52. package/src/contracts/sessions.contract.ts +2 -2
  53. package/src/contracts/settings.contract.ts +3 -3
  54. package/src/contracts/share.contract.ts +1 -1
  55. package/src/contracts/skills.contract.ts +2 -2
  56. package/src/contracts/system.contract.ts +9 -9
  57. package/src/contracts/usage.contract.ts +1 -1
  58. package/src/contracts/vpn.contract.ts +5 -5
  59. package/src/contracts/workflows.contract.ts +12 -12
  60. package/src/contracts/workspace.contract.ts +13 -13
  61. package/src/conversation-ids.ts +7 -7
  62. package/src/events.ts +136 -136
  63. package/src/history-state.ts +12 -12
  64. package/src/host-protocol.ts +7 -7
  65. package/src/hostnames.ts +15 -15
  66. package/src/index.ts +8 -8
  67. package/src/listener-protocol.ts +12 -12
  68. package/src/model-order.ts +30 -30
  69. package/src/output-fields.ts +9 -9
  70. package/src/path-refs.ts +6 -6
  71. package/src/publish-drafts.ts +6 -6
  72. package/src/quick-model.ts +15 -15
  73. package/src/routes.ts +19 -19
  74. package/src/runtime-state.ts +22 -22
  75. package/src/schemas.ts +930 -918
  76. package/src/search-globs.ts +6 -6
  77. package/src/session-names.ts +5 -5
  78. package/src/share-paths.ts +7 -7
  79. package/src/sse.ts +1 -1
  80. package/src/state-portability.ts +8 -8
  81. package/src/terminal-protocol.ts +3 -3
  82. package/src/title.ts +20 -20
  83. package/src/tunnel-ids.ts +7 -7
  84. package/src/versions.ts +5 -5
  85. package/src/workflow-faults.ts +11 -11
  86. package/src/workspace-state.ts +119 -119
@@ -11,14 +11,14 @@ import {
11
11
  } from "../schemas.js";
12
12
 
13
13
  // The sandbox's automations manifest (scheduled agent wake-ups). `list` returns each automation with its recent
14
- // runs + next fire time. `upsert` adds or edits by id (nothing to provision the scheduler picks it up on its
14
+ // runs + next fire time. `upsert` adds or edits by id (nothing to provision, the scheduler picks it up on its
15
15
  // next poll); `setEnabled` changes only the switch, so a list-row action never has to reconstruct the record.
16
16
  // `remove` deletes.
17
17
  // The `pending*` routes are the owner's approval queue: a `requireApproval` automation holds each fire here
18
18
  // instead of waking; `approve` runs the held wake, `reject` drops it.
19
19
  export const automationsContract = {
20
20
  list: oc.route({ method: "GET", path: "/automations" }).output(AutomationsListSchema),
21
- /* WHAT CAN WAKE AN AGENT HERE, and what to start from the daemon's own sources and templates merged with
21
+ /* WHAT CAN WAKE AN AGENT HERE, and what to start from, the daemon's own sources and templates merged with
22
22
  * every installed extension's. The composer's entire vocabulary, so that adding a trigger to an area is a
23
23
  * change to that area and to nothing else. `upsert` below validates against the same merge, which is what
24
24
  * keeps the surface and the daemon from disagreeing about what is allowed. */
@@ -26,18 +26,18 @@ export const automationsContract = {
26
26
  upsert: oc.route({ method: "POST", path: "/automations" }).input(AutomationSchema).output(OkSchema),
27
27
  setEnabled: oc.route({ method: "POST", path: "/automations/{id}/enabled" }).input(AutomationEnabledInputSchema).output(OkSchema),
28
28
  remove: oc.route({ method: "DELETE", path: "/automations/{id}" }).input(AutomationIdParamSchema).output(OkSchema),
29
- /* Fire one automation NOW, by hand the answer to "I wrote a 3 a.m. cron and I have no way to try it".
29
+ /* Fire one automation NOW, by hand, the answer to "I wrote a 3 a.m. cron and I have no way to try it".
30
30
  * It runs the SAME path the real trigger runs: a schedule stays a headless main-tree wake, because a
31
31
  * test-fire that proves an isolated worktree works proves nothing about the fire it is standing in for. The
32
32
  * guard runs too ("skipped by guard" is the most useful thing this can report); only the approval gate is
33
33
  * skipped, since pressing the button IS the owner's approval.
34
34
  *
35
- * Owner-explicit, so a DISABLED automation fires as well trying a prompt before switching it on is the
35
+ * Owner-explicit, so a DISABLED automation fires as well, trying a prompt before switching it on is the
36
36
  * main reason to press this, and unlike the /automations/{id}/fire webhook there is no outside sender here to
37
37
  * fail closed against.
38
38
  *
39
39
  * NOT FOR A LISTENER, which is the one trigger whose fire is nothing without the thing that fired it. A
40
- * listener's prompt is a brief about handling the events riding with it, and by hand there are none so the
40
+ * listener's prompt is a brief about handling the events riding with it, and by hand there are none, so the
41
41
  * button could only ever produce an agent told to handle events, handed none, asking where they went. Worse,
42
42
  * that pointless run took the automation's turn: a real mention arriving while it ran had to wait behind it.
43
43
  * Refused here rather than hidden in the UI alone, because the honest answer to "how do I test this" is to
@@ -19,14 +19,14 @@ import {
19
19
  /* The sandbox's unified capability manifest. `list` returns each active capability with its live status, the
20
20
  * non-secret echo of its config, and the NAMES of the credentials it holds. `add` upserts a capability and
21
21
  * STREAMS its apply (devops scaffolding / service provisioning emit ndjson progress; mcp/integration emit a
22
- * terminal frame), mirroring the /intentic runner. `remove` tears it down (devops refuses deleting the repos
22
+ * terminal frame), mirroring the /intentic runner. `remove` tears it down (devops refuses, deleting the repos
23
23
  * is data loss). `status` re-probes a single capability for a lazy UI refresh. `marketplace` resolves a Claude
24
24
  * Code plugin marketplace repo into installable plugin-capability configs.
25
25
  *
26
26
  * `add` IS ALSO THE EDIT, because the write is an upsert: the same id with a changed config changes that
27
27
  * connection. A caller editing one has never been shown its credentials, so it sends VAULTED
28
28
  * (capability-secrets.ts) for each it is leaving alone and the daemon resolves those from what is stored before
29
- * anything runs the only way to change one setting on a tunnel without re-typing its key. A marker with
29
+ * anything runs, the only way to change one setting on a tunnel without re-typing its key. A marker with
30
30
  * nothing behind it is refused rather than written. */
31
31
  export const capabilitiesContract = {
32
32
  list: oc.route({ method: "GET", path: "/capabilities" }).output(CapabilitiesListSchema),
@@ -34,24 +34,24 @@ export const capabilitiesContract = {
34
34
  remove: oc.route({ method: "DELETE", path: "/capabilities/{id}" }).input(CapabilityIdParamSchema).output(OkSchema),
35
35
  /* Give a connection a different name, carrying what the old one keyed: a browser profile with its logins,
36
36
  * a connected machine's enrollment, an extension's checkout. The name is the agent's handle for the thing,
37
- * so this is a migration add + remove would lose exactly the state that makes the connection worth
37
+ * so this is a migration, add + remove would lose exactly the state that makes the connection worth
38
38
  * keeping. A kind whose name is part of what it IS (the scaffolders, the one-per-sandbox cards) refuses. */
39
39
  rename: oc.route({ method: "POST", path: "/capabilities/{id}/rename" }).input(CapabilityRenameSchema).output(OkSchema),
40
40
  // Replace just the secret in a capability's config (the /secrets page's edit) and re-run its apply.
41
41
  setSecret: oc.route({ method: "POST", path: "/capabilities/{id}/secret" }).input(CapabilitySecretInputSchema).output(OkSchema),
42
42
  status: oc.route({ method: "GET", path: "/capabilities/{id}/status" }).input(CapabilityIdParamSchema).output(CapabilityStatusSchema),
43
- /* One capability's stored config, secrets included how an extension BACKEND dials the service behind a
43
+ /* One capability's stored config, secrets included, how an extension BACKEND dials the service behind a
44
44
  * connected capability (ext-deployments reads its Komodo's key pair through this). Never a browser's: the
45
45
  * handler refuses any caller with a member identity, so only the daemon's header grants reach it, and an
46
- * extension's grant reaches it only when its manifest declares the route in `permissions.daemon` which
46
+ * extension's grant reaches it only when its manifest declares the route in `permissions.daemon`, which
47
47
  * is the install dialog saying, in one line, "this extension can read connected credentials". */
48
48
  connection: oc.route({ method: "GET", path: "/capabilities/{id}/connection" }).input(CapabilityIdParamSchema).output(CapabilityConnectionSchema),
49
49
  marketplace: oc.route({ method: "POST", path: "/capabilities/marketplace" }).input(MarketplaceRequestSchema).output(MarketplaceSchema),
50
50
  // "Not needed": stop offering this card until the workspace evidence behind it changes. Nothing is torn
51
- // down and nothing is remembered about the card itself only the evidence it was declined against.
51
+ // down and nothing is remembered about the card itself, only the evidence it was declined against.
52
52
  dismiss: oc.route({ method: "DELETE", path: "/capabilities/recommendations/{card}" }).input(CapabilityCardParamSchema).output(OkSchema),
53
53
  // Start an agent-kind capability's interactive login (its declared loginCommand) in a visible terminal
54
- // session the user types into device-code sign-in flows. Returns the session the panel attaches to.
54
+ // session the user types into, device-code sign-in flows. Returns the session the panel attaches to.
55
55
  login: oc.route({ method: "POST", path: "/capabilities/{id}/login" }).input(CapabilityIdParamSchema).output(CapabilityLoginSchema),
56
56
  // Mint one TOTP code from the capability's stored seed (a field its card marks `totp`). The one capability
57
57
  // read the agent token is admitted to (see auth/grants): a code expires within its period and never reveals
@@ -2,19 +2,19 @@ import { oc } from "@orpc/contract";
2
2
  import { ChoreLedgerWriteSchema, ChoreProbeRequestSchema, ChoresReportSchema, OkSchema } from "../schemas.js";
3
3
 
4
4
  /* Maintenance evidence: what every repo under /work currently measures, and what has already been done about it.
5
- * Three routes, because there are exactly three things the surface does read the evidence, ask for a
5
+ * Three routes, because there are exactly three things the surface does, read the evidence, ask for a
6
6
  * measurement to be retaken, and record what a turn concluded.
7
7
  *
8
8
  * There is no `GET /chores/{id}` and no "run this chore" route on purpose. A chore RUN is an ordinary isolated
9
9
  * fleet agent (`POST /agent` with a derived conversation id), the same as an acceptance run or a documentation
10
- * generation so the worktree, the live status, the cost, the transcript and the /agents/<id> page already
10
+ * generation, so the worktree, the live status, the cost, the transcript and the /agents/<id> page already
11
11
  * exist, and adding a bespoke launcher here would be a second way to start a turn that has to be kept in step
12
12
  * with the first. */
13
13
  export const choresContract = {
14
14
  // Every repo's standing evidence in one read: cached probe results (with their age and state), the cheap
15
15
  // resident signals, the ledger, and the daemon's node version. The rail badge polls this; so does the panel.
16
16
  list: oc.route({ method: "GET", path: "/chores" }).output(ChoresReportSchema),
17
- // Re-run one repo's probe now, ignoring its TTL the panel's per-probe refresh. An ack: the runner works in
17
+ // Re-run one repo's probe now, ignoring its TTL, the panel's per-probe refresh. An ack: the runner works in
18
18
  // the background and the result arrives on the next `list`, because a jscpd sweep outlives any sane request.
19
19
  probe: oc.route({ method: "POST", path: "/chores/probe" }).input(ChoreProbeRequestSchema).output(OkSchema),
20
20
  // Record what a chore turn concluded, or snooze one. Upsert by repo+chore: a chore has one current verdict,
@@ -12,7 +12,7 @@ import {
12
12
  // Pipelines on the workspace repos' github/gitlab remotes. `runs` serves the Pipelines rail view (cache +
13
13
  // on-demand backfill; per-repo webhook warnings ride along); `rerun`/`cancel` proxy to the vendor; `fix`
14
14
  // opens an isolated agent conversation seeded with the failure context. The public webhook receiver
15
- // (/ci/webhook/:host) is a plain Hono route vendors can't do Google ID tokens so it lives outside this
15
+ // (/ci/webhook/:host) is a plain Hono route, vendors can't do Google ID tokens, so it lives outside this
16
16
  // contract, like /automations/{id}/fire.
17
17
  export const ciContract = {
18
18
  runs: oc.route({ method: "GET", path: "/ci/runs" }).output(CiRunsResponseSchema),
@@ -20,7 +20,7 @@ export const ciContract = {
20
20
  cancel: oc.route({ method: "POST", path: "/ci/runs/cancel" }).input(CiRunParamSchema).output(OkSchema),
21
21
  jobs: oc.route({ method: "POST", path: "/ci/runs/jobs" }).input(CiRunParamSchema).output(CiJobsResponseSchema),
22
22
  fix: oc.route({ method: "POST", path: "/ci/fix" }).input(CiFixParamSchema).output(CiFixResponseSchema),
23
- // "I have looked at the pipelines" what silences the rail badge for breakages already read. No input:
23
+ // "I have looked at the pipelines", what silences the rail badge for breakages already read. No input:
24
24
  // the surface is read as a whole, and the daemon stamps its own clock so a skewed browser can't mark
25
25
  // future failures as already seen.
26
26
  seen: oc.route({ method: "POST", path: "/ci/seen" }).output(CiSeenResponseSchema),
@@ -10,18 +10,18 @@ import {
10
10
  OkSchema,
11
11
  } from "../schemas.js";
12
12
 
13
- // Claude subscription OAuth the sandbox owns the credential. `start` hands the browser the authorize URL +
13
+ // Claude subscription OAuth, the sandbox owns the credential. `start` hands the browser the authorize URL +
14
14
  // PKCE material; `exchange` stores the resulting tokens as a new account and returns it; `accounts` lists the
15
15
  // connected accounts; `rename` renames one; `disconnect` clears the one named by id. A sandbox can hold several
16
16
  // Claude accounts.
17
17
  //
18
18
  // The model catalog is NOT here: it is the one thing every provider answers identically, so it lives on the
19
19
  // shared /providers/{provider}/models route (providers.contract.ts). What is left is what is genuinely Claude's
20
- // an account handshake no other provider has.
20
+ //, an account handshake no other provider has.
21
21
  export const claudeContract = {
22
22
  start: oc.route({ method: "POST", path: "/claude/oauth/start" }).output(AuthorizeChallengeSchema),
23
23
  exchange: oc.route({ method: "POST", path: "/claude/oauth/exchange" }).input(OauthExchangeSchema).output(OauthAccountSchema),
24
- // Each account carries its plan-limit reading. `force` re-measures before answering see
24
+ // Each account carries its plan-limit reading. `force` re-measures before answering, see
25
25
  // AccountListQuerySchema, and USAGE_WAIT_MS in claude.routes.ts for what an ordinary read waits.
26
26
  accounts: oc.route({ method: "GET", path: "/claude/accounts" }).input(AccountListQuerySchema).output(OauthAccountListSchema),
27
27
  rename: oc.route({ method: "POST", path: "/claude/account/rename" }).input(AccountRenameSchema).output(OauthAccountSchema),
@@ -2,7 +2,7 @@ import { oc } from "@orpc/contract";
2
2
  import { DraftIdParamSchema, DraftsListSchema, DraftSummarySchema, OkSchema } from "../schemas.js";
3
3
 
4
4
  // The sandbox's post-drafts queue (agent-proposed posts awaiting approval). The agent creates draft files
5
- // directly these routes are the OWNER's side: `list` is the approval inbox, `upsert` covers approve / edit /
5
+ // directly, these routes are the OWNER's side: `list` is the approval inbox, `upsert` covers approve / edit /
6
6
  // retry (all a plain re-post with a field changed, like the automations enabled toggle), `remove` is reject.
7
7
  export const draftsContract = {
8
8
  list: oc.route({ method: "GET", path: "/drafts" }).output(DraftsListSchema),
@@ -2,12 +2,12 @@ import { oc } from "@orpc/contract";
2
2
  import { z } from "zod";
3
3
  import { CapabilityIdParamSchema, ModelsSchema } from "../schemas.js";
4
4
 
5
- // An `endpoint` capability's picker catalog the models the configured server itself publishes, read from its
5
+ // An `endpoint` capability's picker catalog, the models the configured server itself publishes, read from its
6
6
  // own /v1/models. Every other provider's catalog is one fixed route because there is one of each; endpoints are
7
7
  // user-created and unbounded, so the id rides in the path. There is no seed floor and no static list: what a
8
8
  // model API serves is knowable only by asking it, and an empty answer is the honest report that we could not.
9
9
 
10
- /* The free trial's remaining allowance, on the endpoints contract because the trial IS an endpoint the one
10
+ /* The free trial's remaining allowance, on the endpoints contract because the trial IS an endpoint, the one
11
11
  * the daemon provisions rather than the user (agent-catalog.ts TRIAL_ENDPOINT_ID). It is a separate read from
12
12
  * the catalog above because it answers a different question and changes on a different clock: the model list is
13
13
  * a property of the upstream, while this is a property of the ACCOUNT and moves with every message sent.
@@ -19,7 +19,7 @@ import {
19
19
  WorkspaceExtensionCreateSchema,
20
20
  } from "../schemas.js";
21
21
 
22
- // Installed extensions resolved to their approved manifests what the web extension host boots from. The
22
+ // Installed extensions resolved to their approved manifests, what the web extension host boots from. The
23
23
  // bundle itself is a plain Hono route (GET /extensions/{id}/bundle): raw ESM bytes are not an oRPC payload.
24
24
  // `settings`/`setSettings` carry the extension's own contributes.settings values; keys the manifest never
25
25
  // declared are refused, the same honesty rule the host applies to runtime view/command registrations.
@@ -27,28 +27,28 @@ export const extensionsContract = {
27
27
  list: oc.route({ method: "GET", path: "/extensions" }).output(ExtensionsListSchema),
28
28
  // Author a new extension in place: writes a running one into .intentic/config/workspace-extensions/<name>/. The only
29
29
  // creating route here, and it exists because that directory is otherwise reachable exclusively through an
30
- // agent's file tools which is a fine way to CHANGE an extension and a poor way to meet the idea of one.
30
+ // agent's file tools, which is a fine way to CHANGE an extension and a poor way to meet the idea of one.
31
31
  create: oc.route({ method: "POST", path: "/extensions/workspace" }).input(WorkspaceExtensionCreateSchema).output(WorkspaceExtensionCreatedSchema),
32
32
  settings: oc.route({ method: "GET", path: "/extensions/{id}/settings" }).input(CapabilityIdParamSchema).output(ExtensionSettingsSchema),
33
33
  setSettings: oc.route({ method: "POST", path: "/extensions/{id}/settings" }).input(ExtensionSettingsInputSchema).output(OkSchema),
34
34
  // The owner's on/off switch. Disabling stops the extension's declared processes here and now; its agent
35
35
  // plugin dir and PATH entry are rebuilt per turn, and an `environment` fragment only at the next image
36
- // rebuild the Extensions tab states which of those an extension actually has.
36
+ // rebuild, the Extensions tab states which of those an extension actually has.
37
37
  setEnabled: oc.route({ method: "POST", path: "/extensions/{id}/enabled" }).input(ExtensionEnabledInputSchema).output(OkSchema),
38
38
  // The host reporting which declared routes it just let through. Written by the browser because that is where
39
- // the permission gate runs (apiImpl.ts) the daemon sees an extension's traffic as ordinary authenticated
39
+ // the permission gate runs (apiImpl.ts), the daemon sees an extension's traffic as ordinary authenticated
40
40
  // requests and cannot tell which extension, or which declared entry, any of it belongs to.
41
41
  recordUsage: oc.route({ method: "POST", path: "/extensions/{id}/usage" }).input(ExtensionUsageInputSchema).output(OkSchema),
42
- /* Whether this extension is fit for somebody else to run the checks answerable from its files alone. Read
42
+ /* Whether this extension is fit for somebody else to run, the checks answerable from its files alone. Read
43
43
  * on demand rather than carried on the list: it reads the bundle off disk per extension, and it is looked at
44
44
  * when an author is about to publish, not every time the tab renders. */
45
45
  readiness: oc.route({ method: "GET", path: "/extensions/{id}/readiness" }).input(CapabilityIdParamSchema).output(ExtensionReadinessSchema),
46
46
  /* The update lifecycle for a GIT-INSTALLED extension. The list carries what the periodic registry check
47
47
  * found (update/advisory/health per row); these are the verbs around it. `checkUpdates` runs the comparison
48
48
  * now (the tab's "check now"). `updatePreview` stages the offered sha and answers with the version story +
49
- * the mechanical powers diff the read BEFORE the click, costing one throwaway clone like a registry
49
+ * the mechanical powers diff, the read BEFORE the click, costing one throwaway clone like a registry
50
50
  * browse. `applyUpdate` is the transaction: re-clone, validate, quiesce, swap (keeping the outgoing
51
- * checkout one back), restart, health-watch on the EXISTING capability config, so a private-source token
51
+ * checkout one back), restart, health-watch, on the EXISTING capability config, so a private-source token
52
52
  * survives what a bare re-add would lose. `revert` swaps the kept-previous checkout back. Update and revert
53
53
  * change the code that runs, so like install they are owner-only. */
54
54
  checkUpdates: oc.route({ method: "POST", path: "/extensions/updates/check" }).output(ExtensionUpdatesCheckedSchema),
@@ -61,7 +61,7 @@ export const extensionsContract = {
61
61
  .input(ExtensionUpdateActionSchema)
62
62
  .output(ExtensionUpdateAppliedSchema),
63
63
  revert: oc.route({ method: "POST", path: "/extensions/{id}/revert" }).input(CapabilityIdParamSchema).output(ExtensionUpdateAppliedSchema),
64
- // The owner's standing answer per extension (notify / agent / auto, and the advisory opt-out) see
64
+ // The owner's standing answer per extension (notify / agent / auto, and the advisory opt-out), see
65
65
  // ExtensionUpdatePolicySchema for what each rung means.
66
66
  setUpdatePolicy: oc.route({ method: "POST", path: "/extensions/{id}/update-policy" }).input(ExtensionUpdatePolicyInputSchema).output(OkSchema),
67
67
  // Declared background processes (contributes.processes): tmux-managed through the panel machinery
@@ -54,9 +54,9 @@ export const gitContract = {
54
54
  changes: oc.route({ method: "GET", path: "/git/changes" }).output(GitChangesSchema),
55
55
  // The git-history graph over one repo's real commits: the repo list (for the tree affordance + switcher),
56
56
  // one repo's commit log, and lazy per-commit detail (changed files, then a file's before/after AT the
57
- // commit). Read-only commit/discard on the working tree stay the write path (above).
57
+ // commit). Read-only, commit/discard on the working tree stay the write path (above).
58
58
  repos: oc.route({ method: "GET", path: "/git/repos" }).output(GitReposSchema),
59
- // The same repos with the host + project their remote names how a caller recognises a workspace repo in a
59
+ // The same repos with the host + project their remote names, how a caller recognises a workspace repo in a
60
60
  // list of `owner/name` strings that came from somewhere else. Kept off `repos` (a `git remote -v` per repo).
61
61
  remoteRepos: oc.route({ method: "GET", path: "/git/remote-repos" }).output(GitRemoteReposSchema),
62
62
  log: oc.route({ method: "GET", path: "/git/{repo}/log" }).input(GitLogQuerySchema).output(GitLogSchema),
@@ -67,13 +67,13 @@ export const gitContract = {
67
67
  // GitActionResult so a conflict/clean-apply failure is a value, not a 500. Read routes above.
68
68
  /* The halted-operation pair. `operation` is a READ every git surface can use to explain a worktree it cannot
69
69
  * otherwise act on; `abort` is the single way out, and it is git's own `--abort` rather than anything
70
- * clever. Neither is reachable from the daemon's own verbs those abort themselves so this exists purely
70
+ * clever. Neither is reachable from the daemon's own verbs, those abort themselves, so this exists purely
71
71
  * for what a terminal left behind. */
72
72
  operation: oc.route({ method: "GET", path: "/git/{repo}/operation" }).input(RepoParamSchema).output(GitOperationStateSchema),
73
73
  abort: oc.route({ method: "POST", path: "/git/{repo}/abort" }).input(RepoParamSchema).output(GitActionResultSchema),
74
74
  /* Walk the current branch back to where it was before its last action, off the branch's own reflog. The
75
75
  * complement to the Checkpoints timeline, not a duplicate of it: a checkpoint restores the working tree,
76
- * this moves the ref. The read carries `previousSha`, which the write sends back as a concurrency token
76
+ * this moves the ref. The read carries `previousSha`, which the write sends back as a concurrency token,
77
77
  * an undo prepared against a stale view is refused rather than landing somewhere unlooked-at. */
78
78
  undoable: oc.route({ method: "GET", path: "/git/{repo}/undo" }).input(RepoParamSchema).output(GitUndoStateSchema),
79
79
  undo: oc.route({ method: "POST", path: "/git/{repo}/undo" }).input(GitUndoSchema).output(GitActionResultSchema),
@@ -101,7 +101,7 @@ export const gitContract = {
101
101
  status: oc.route({ method: "GET", path: "/git/{repo}/status" }).input(RepoParamSchema).output(GitStatusSchema),
102
102
  commit: oc.route({ method: "POST", path: "/git/{repo}/commit" }).input(CommitSchema).output(CommitResultSchema),
103
103
  discard: oc.route({ method: "POST", path: "/git/{repo}/discard" }).input(DiscardSchema).output(OkSchema),
104
- // Index moves. Per-path, worktree untouched, so they need no checkpoint and can't fail destructively
104
+ // Index moves. Per-path, worktree untouched, so they need no checkpoint and can't fail destructively,
105
105
  // git's own error (an unmatched pathspec) propagates.
106
106
  stage: oc.route({ method: "POST", path: "/git/{repo}/stage" }).input(GitStageSchema).output(OkSchema),
107
107
  unstage: oc.route({ method: "POST", path: "/git/{repo}/unstage" }).input(GitStageSchema).output(OkSchema),
@@ -113,7 +113,7 @@ export const gitContract = {
113
113
  deleteBranch: oc.route({ method: "POST", path: "/git/{repo}/branches/delete" }).input(GitBranchDeleteSchema).output(OkSchema),
114
114
  // Remote sync. All three report a GitActionResult rather than throwing: no remote, no credentials and a
115
115
  // non-fast-forwardable pull are ORDINARY outcomes the panel renders, not 500s. `remote` is the read
116
- // (ahead/behind as of the last fetch hence the Fetch button) the sync bar polls.
116
+ // (ahead/behind as of the last fetch, hence the Fetch button) the sync bar polls.
117
117
  remote: oc.route({ method: "GET", path: "/git/{repo}/remote" }).input(RepoParamSchema).output(GitRemoteStateSchema),
118
118
  fetch: oc.route({ method: "POST", path: "/git/{repo}/fetch" }).input(RepoParamSchema).output(GitActionResultSchema),
119
119
  pull: oc.route({ method: "POST", path: "/git/{repo}/pull" }).input(RepoParamSchema).output(GitActionResultSchema),
@@ -1,14 +1,14 @@
1
1
  import { oc } from "@orpc/contract";
2
2
  import { AccountIdSchema, DeviceStartSchema, OauthAccountListSchema, OkSchema } from "../schemas.js";
3
3
 
4
- // xAI Grok (via OpenCode) uses subscription OAuth the sandbox owns the credential (OpenCode persists the
4
+ // xAI Grok (via OpenCode) uses subscription OAuth, the sandbox owns the credential (OpenCode persists the
5
5
  // tokens and refreshes them). `start` authorizes xAI's headless device-code method and returns the verification
6
6
  // URL + instructions (which carry the one-time code the user enters at x.ai); OpenCode then polls to completion
7
- // there is no paste-back and the UI polls `accounts` until connected. `disconnect` clears the tokens.
8
- // ponytail: OpenCode holds one xAI auth per data dir, so `accounts` is 0 or 1 the list shape matches the
7
+ //, there is no paste-back, and the UI polls `accounts` until connected. `disconnect` clears the tokens.
8
+ // ponytail: OpenCode holds one xAI auth per data dir, so `accounts` is 0 or 1, the list shape matches the
9
9
  // other providers without paying for per-account OpenCode servers yet.
10
10
  //
11
- // Like Claude's, this contract is now the account handshake alone the model catalog answers on the shared
11
+ // Like Claude's, this contract is now the account handshake alone, the model catalog answers on the shared
12
12
  // /providers/{provider}/models route (providers.contract.ts).
13
13
  export const grokContract = {
14
14
  start: oc.route({ method: "POST", path: "/grok/oauth/start" }).output(DeviceStartSchema),
@@ -6,7 +6,7 @@ import { HostFactsSchema, HostScopesSchema, MachineFlowLineSchema, MachineSandbo
6
6
  *
7
7
  * The direction is the unusual part: the machine is the oRPC SERVER and the daemon holds the client, even though
8
8
  * the machine is the side that dialled. A personal computer sits behind NAT with a closing lid, so it can only
9
- * ever be the one that connects but everything is asked OF it. oRPC's websocket adapter takes any socket-like
9
+ * ever be the one that connects, but everything is asked OF it. oRPC's websocket adapter takes any socket-like
10
10
  * object on either side, so the roles are free to be the opposite of who placed the call.
11
11
  *
12
12
  * No `.route()` on these: HTTP method and path are for the daemon's own REST surface, and this contract never
@@ -14,12 +14,12 @@ import { HostFactsSchema, HostScopesSchema, MachineFlowLineSchema, MachineSandbo
14
14
  *
15
15
  * `mcp` IS THE DELIBERATE HOLE in the typing, and it is worth understanding before someone "fixes" it. The agent
16
16
  * talks to a machine in MCP, over the daemon's loopback bridge; if this contract described each tool, then the
17
- * daemon would have to know every tool's schema and translate and a machine could no longer learn a tool
17
+ * daemon would have to know every tool's schema and translate, and a machine could no longer learn a tool
18
18
  * without a matching daemon release. Keeping one opaque procedure is what buys the machine an independent
19
19
  * release cycle. The payload is still validated where it is understood: on the machine, against the tool's own
20
20
  * schema, and by the agent's MCP client on the way back. */
21
21
  export const hostContract = {
22
- // What this computer is pulled right after the socket authenticates, and again whenever the sandbox wants
22
+ // What this computer is, pulled right after the socket authenticates, and again whenever the sandbox wants
23
23
  // it fresh. The card shows it, and the agent's skill pack is written against it.
24
24
  describe: oc.output(HostFactsSchema),
25
25
  // The grant, pushed down on every connect and again whenever the owner edits the card. The machine ENFORCES
@@ -28,7 +28,7 @@ export const hostContract = {
28
28
  // Liveness, driven by the daemon: it doubles as the keepalive that stops an idle tunnel from reaping the
29
29
  // connection, and as the probe whose failure means the machine is gone rather than quiet.
30
30
  ping: oc.output(OkSchema),
31
- // One MCP JSON-RPC message in, its answer out forwarded verbatim in both directions. See above.
31
+ // One MCP JSON-RPC message in, its answer out, forwarded verbatim in both directions. See above.
32
32
  mcp: oc.input(z.unknown()).output(z.unknown()),
33
33
  /* One operation on one of this machine's sandboxes, narrated as it happens.
34
34
  *
@@ -38,7 +38,7 @@ export const hostContract = {
38
38
  * container, which is minutes of silence unless the lines travel while they are produced. A stream is what
39
39
  * the browser needs, and a stream is the one thing an MCP tool result cannot be.
40
40
  *
41
- * The scope is still checked here, on the machine, by the same functions the MCP tools call this adds a
41
+ * The scope is still checked here, on the machine, by the same functions the MCP tools call, this adds a
42
42
  * way of WATCHING an operation, never a way of skipping the switch that permits it. */
43
43
  runSandboxFlow: oc.input(MachineSandboxFlowSchema).output(eventIterator(MachineFlowLineSchema)),
44
44
  };
@@ -7,9 +7,9 @@ import { IntenticRunSchema, OkSchema } from "../schemas.js";
7
7
  export const intenticContract = {
8
8
  run: oc.route({ method: "POST", path: "/intentic" }).input(IntenticRunSchema).output(eventIterator(IntenticLineSchema)),
9
9
  // Launch the minutes-long apply → adopt reconcile as a one-shot tmux job (session panel-infra-apply) and
10
- // return immediately progress is followed by attaching the terminal, not by holding this request open.
10
+ // return immediately, progress is followed by attaching the terminal, not by holding this request open.
11
11
  apply: oc.route({ method: "POST", path: "/intentic/apply" }).output(OkSchema),
12
- // Tail the running (or just-finished) apply's structured event stream the same ndjson lines the tmux pane
12
+ // Tail the running (or just-finished) apply's structured event stream, the same ndjson lines the tmux pane
13
13
  // renders as text, persisted to a durable file so the UI shows per-resource progress that survives a page
14
14
  // refresh. Replays from the run's {kind:"start"} then follows live, closing on {kind:"exit"}. GET, like
15
15
  // /events, because it takes no input; reuses the loose IntenticLine shape so no new schema is needed.
@@ -2,7 +2,7 @@ import { oc } from "@orpc/contract";
2
2
  import { LogReadQuerySchema, LogReadSchema, LogsListSchema } from "../schemas.js";
3
3
 
4
4
  // Daemon-owned debug logs (historyRoot/logs): terminal pipe-pane captures, intentic CLI run logs, daemon.log.
5
- // Read-only by design the files are written by the daemon/tmux only, so the record stays trustworthy.
5
+ // Read-only by design, the files are written by the daemon/tmux only, so the record stays trustworthy.
6
6
  export const logsContract = {
7
7
  list: oc.route({ method: "GET", path: "/logs" }).output(LogsListSchema),
8
8
  read: oc.route({ method: "GET", path: "/logs/file" }).input(LogReadQuerySchema).output(LogReadSchema),
@@ -11,29 +11,29 @@ import {
11
11
  OkSchema,
12
12
  } from "../schemas.js";
13
13
 
14
- /* The loop routes "run this conversation again until the goal is met".
14
+ /* The loop routes, "run this conversation again until the goal is met".
15
15
  *
16
16
  * TWO HALVES THAT LOOK LIKE ONE FEATURE AND ARE NOT, which is why they share a file and share nothing else.
17
17
  *
18
18
  * A RUNNING LOOP has no editor. It is started against a conversation, it converges or it gives up, and then it
19
- * is history: `start`, `stop`, and a `list` of what has run. No upsert, no enabled toggle, no id of its own
19
+ * is history: `start`, `stop`, and a `list` of what has run. No upsert, no enabled toggle, no id of its own,
20
20
  * the conversation IS the id.
21
21
  *
22
22
  * A SAVED LOOP is a manifest entry like a workflow, and gets the manifest treatment: list, save, remove. It is
23
23
  * the loop's MACHINERY without its goal (LoopDesignSchema says why at length), so it is authored once and
24
- * pointed at a different job every time. It has no `run` route of its own on purpose running one is `start`
24
+ * pointed at a different job every time. It has no `run` route of its own on purpose, running one is `start`
25
25
  * with the design's fields and the composer's sentence, so there is exactly one way a loop begins and exactly
26
26
  * one place that can refuse it.
27
27
  *
28
28
  * `start` acks immediately with the loop as recorded and runs detached, the same contract POST /agent keeps: the
29
29
  * first iteration alone can take minutes, and every surface that would render progress is already attached to
30
- * the conversation. What comes back is the record, not an outcome the outcome arrives on the fleet card.
30
+ * the conversation. What comes back is the record, not an outcome, the outcome arrives on the fleet card.
31
31
  */
32
32
  export const loopsContract = {
33
- // Every loop this workspace has run, newest first the record is kept after the loop ends, because "why did
33
+ // Every loop this workspace has run, newest first, the record is kept after the loop ends, because "why did
34
34
  // it stop at iteration 4" is the question a loop is read for, and the answer is its iteration history.
35
35
  list: oc.route({ method: "GET", path: "/loops" }).output(LoopsListSchema),
36
- /* Start looping a conversation. Rejects when that conversation is already looping a second loop on one
36
+ /* Start looping a conversation. Rejects when that conversation is already looping, a second loop on one
37
37
  * agent would have two pumps racing the same worktree and the same turn mutex, and the loser would spend a
38
38
  * turn to discover it.
39
39
  *
@@ -49,10 +49,10 @@ export const loopsContract = {
49
49
  stop: oc.route({ method: "POST", path: "/loops/{conversationId}/stop" }).input(LoopIdParamSchema).output(OkSchema),
50
50
 
51
51
  // Every saved loop. A literal path segment under /loops rather than a surface of its own, because a saved
52
- // loop is not a different feature it is the same loop with its goal left blank until somebody types one.
52
+ // loop is not a different feature, it is the same loop with its goal left blank until somebody types one.
53
53
  designs: oc.route({ method: "GET", path: "/loops/designs" }).output(LoopDesignsListSchema),
54
54
  /* Create or replace a saved loop, with the operation explicit so a name collision cannot turn a create into
55
- * a replacement. Refuses a design that could never finish nothing to produce and nothing to check with
55
+ * a replacement. Refuses a design that could never finish, nothing to produce and nothing to check, with
56
56
  * the same sentence `start` refuses an ad-hoc loop for, because it is the same mistake made earlier and
57
57
  * catching it at save time is the whole advantage of saving. */
58
58
  saveDesign: oc.route({ method: "POST", path: "/loops/designs" }).input(LoopDesignSaveSchema).output(LoopDesignSchema),
@@ -13,12 +13,12 @@ import {
13
13
 
14
14
  /* The sandbox's named personas (PersonaSchema): which connected accounts each one speaks for, what a session
15
15
  * wearing it may do, where it works, and what it is told. The card half is a plain three-verb CRUD with no apply
16
- * step, because a card provisions NOTHING unlike a capability, saving one connects nothing, installs nothing
16
+ * step, because a card provisions NOTHING, unlike a capability, saving one connects nothing, installs nothing
17
17
  * and spends nothing. It records a decision about accounts that already exist.
18
18
  *
19
19
  * The file behind it is committed workspace config (personas/personas-store.ts), so these routes are one of
20
20
  * two equally supported ways to edit them: this, and opening the file in the editor like any other project
21
- * config. Neither is the "real" one which is why `save` is a whole-card upsert rather than a field patch, so
21
+ * config. Neither is the "real" one, which is why `save` is a whole-card upsert rather than a field patch, so
22
22
  * a round trip through the UI leaves a diff a reviewer would recognise.
23
23
  *
24
24
  * THE KIT ROUTES BELOW EDIT FILES, not the card, and they are here rather than on the skills contract because
@@ -30,14 +30,14 @@ import {
30
30
  * a save that shipped the whole folder would make an edit to one skill capable of deleting another. */
31
31
  export const personasContract = {
32
32
  list: oc.route({ method: "GET", path: "/personas" }).output(PersonasListSchema),
33
- // Upsert by id re-saving the same id edits that card.
33
+ // Upsert by id, re-saving the same id edits that card.
34
34
  save: oc.route({ method: "POST", path: "/personas" }).input(PersonaSchema).output(OkSchema),
35
35
  /* Removing a card takes away a persona, never an account: the login it named stays connected and reachable from
36
- * every other surface. What it CAN do is orphan a reference an automation pinned to this id now names a
37
- * card that no longer exists and the resolver reads that as "no accounts at all" rather than "all of
36
+ * every other surface. What it CAN do is orphan a reference, an automation pinned to this id now names a
37
+ * card that no longer exists, and the resolver reads that as "no accounts at all" rather than "all of
38
38
  * them", so the automation goes quiet instead of posting as somebody unintended. */
39
39
  /* Removing a card takes away a persona, never an account: the login it named stays connected and reachable from
40
- * every other surface. It DOES take the card's kit with it a folder no card can reach is a folder no list
40
+ * every other surface. It DOES take the card's kit with it, a folder no card can reach is a folder no list
41
41
  * shows, and leaving the owner's prompt and skills orphaned on disk is worse than deleting what they just
42
42
  * asked to delete. */
43
43
  remove: oc.route({ method: "DELETE", path: "/personas/{id}" }).input(PersonaIdParamSchema).output(OkSchema),
@@ -46,10 +46,10 @@ export const personasContract = {
46
46
 
47
47
  kit: oc.route({ method: "GET", path: "/personas/{id}/kit" }).input(PersonaIdParamSchema).output(PersonaKitSchema),
48
48
  // An empty prompt DELETES the file rather than storing a blank one, so "custom with nothing written" is one
49
- // state instead of two the resolver falls back to the sandbox's prompt for it (personas.ts personaPrompt).
49
+ // state instead of two, the resolver falls back to the sandbox's prompt for it (personas.ts personaPrompt).
50
50
  savePrompt: oc.route({ method: "POST", path: "/personas/{id}/prompt" }).input(PersonaPromptSchema).output(OkSchema),
51
51
  readSkill: oc.route({ method: "GET", path: "/personas/{id}/skills/read" }).input(PersonaSkillNameSchema).output(PersonaSkillBodySchema),
52
- // Upsert by name, like the sandbox's own skills and with no enabled list to write, because a kit skill is
52
+ // Upsert by name, like the sandbox's own skills, and with no enabled list to write, because a kit skill is
53
53
  // on exactly when its persona is worn. That is what "specific to that persona" has to mean.
54
54
  saveSkill: oc.route({ method: "POST", path: "/personas/{id}/skills" }).input(PersonaSkillSchema).output(OkSchema),
55
55
  removeSkill: oc.route({ method: "POST", path: "/personas/{id}/skills/remove" }).input(PersonaSkillNameSchema).output(OkSchema),
@@ -2,7 +2,7 @@ import { oc } from "@orpc/contract";
2
2
  import { OkSchema, PortForwardResultSchema, PortParamSchema, PortsListSchema } from "../schemas.js";
3
3
 
4
4
  // Listening TCP ports in the sandbox + explicit forwarding through the preview proxy (see the ports section in
5
- // schemas.ts). `forward` is idempotent re-forwarding a port returns its existing slot's URL; `unforward`
5
+ // schemas.ts). `forward` is idempotent, re-forwarding a port returns its existing slot's URL; `unforward`
6
6
  // frees the slot immediately (the hostname keeps resolving, the proxy just stops mapping it).
7
7
  export const portsContract = {
8
8
  list: oc.route({ method: "GET", path: "/ports" }).output(PortsListSchema),
@@ -1,11 +1,11 @@
1
1
  import { oc } from "@orpc/contract";
2
2
  import { OkSchema, PrepushRunSchema } from "../schemas.js";
3
3
 
4
- // The pre-push check the command the workspace runs when the user pushes, before anything leaves the machine
4
+ // The pre-push check, the command the workspace runs when the user pushes, before anything leaves the machine
5
5
  // (see PrepushRunSchema for where this sits and why). Three verbs about ONE run: the check answers about the
6
6
  // main working tree, of which there is exactly one, so nothing here is addressed by id.
7
7
  //
8
- // `run` starts the check and returns immediately a suite takes minutes, and an oRPC call held open for one
8
+ // `run` starts the check and returns immediately, a suite takes minutes, and an oRPC call held open for one
9
9
  // would die on the first proxy timeout with the work still going. The dialog that started it polls `state` for
10
10
  // the verdict, and opens the terminals panel on the `session` the first answer names: the suite runs in a real
11
11
  // tmux window, so watching it is the terminal's job. `cancel` kills that window; the run settles as `cancelled`
@@ -3,21 +3,21 @@ import { ModelsSchema, NativeProviderParamSchema } from "../schemas.js";
3
3
 
4
4
  // EVERY NATIVE PROVIDER'S PICKER CATALOG, ON ONE ROUTE.
5
5
  //
6
- // There were five of these — /claude/models, /codex/models, /grok/models, /kimi/models, /gemini/models one per
6
+ // There were five of these — /claude/models, /codex/models, /grok/models, /kimi/models, /gemini/models, one per
7
7
  // provider, each a contract entry, a route factory and a service field wired separately. They differed in
8
8
  // nothing: same method, same output schema, same "the daemon's catalog for this provider, never empty". Three of
9
9
  // the five route files were the same fifteen lines with a name swapped, and the daemon paid for that shape twice
10
10
  // more in the branch chains that had to fan back out over the providers to ask them all the same question.
11
11
  //
12
- // So the provider is a PARAMETER, not five routes. Adding one is a row in the daemon's catalog registry the
13
- // same discipline the adapter registry already applies to serving a turn rather than a vertical slice through
12
+ // So the provider is a PARAMETER, not five routes. Adding one is a row in the daemon's catalog registry, the
13
+ // same discipline the adapter registry already applies to serving a turn, rather than a vertical slice through
14
14
  // the contract, the router, the service container and every test double.
15
15
  //
16
16
  // Endpoints keep their own route (endpoints.contract.ts) and should: they are user-created and unbounded, their
17
17
  // id names a capability that may not exist, and a missing one is a NOT_FOUND rather than an empty catalog. That
18
18
  // is a different question with a different failure, not a sixth provider.
19
19
  export const providersContract = {
20
- // One provider's models (+ its default id), never empty live discovery with a persisted/seed floor behind
20
+ // One provider's models (+ its default id), never empty, live discovery with a persisted/seed floor behind
21
21
  // it. Order is the provider's own preference order and is not re-ranked here; see ModelsSchema.
22
22
  models: oc.route({ method: "GET", path: "/providers/{provider}/models" }).input(NativeProviderParamSchema).output(ModelsSchema),
23
23
  };
@@ -1,7 +1,7 @@
1
1
  import { oc } from "@orpc/contract";
2
2
  import { OkSchema, PublicListSchema, PublishResultSchema, PublishSchema, UnpublishSchema } from "../schemas.js";
3
3
 
4
- // The workspace outbox what `public/` currently holds and its address (see the public section in schemas.ts).
4
+ // The workspace outbox, what `public/` currently holds and its address (see the public section in schemas.ts).
5
5
  // `publish` copies a workspace file or directory in, creating the outbox if this is the first one; `unpublish`
6
6
  // withdraws one and removes the outbox behind the last, so the directory's presence always means exactly "there
7
7
  // is something published". There is no route to READ a published file: that is the whole point of the
@@ -5,10 +5,10 @@ import { OkSchema, PushChannelIdSchema, PushChannelSchema, PushConfigQuerySchema
5
5
  // push/push-store.ts for why the key lives on the history volume), and sends on the three moments where the
6
6
  // operator's attention is genuinely wanted: a turn finished, the agent is blocked on an answer, and an
7
7
  // automation is waiting for approval. A channel is either a browser's web-push subscription or a native
8
- // install reached through the platform's push relay see PushChannelSchema for the split and why.
8
+ // install reached through the platform's push relay, see PushChannelSchema for the split and why.
9
9
  //
10
10
  // `test` exists because a notification pipeline has four independent failure points the user cannot inspect
11
- // (device permission, service-worker or shell registration, the daemon's key, the push service itself) a
11
+ // (device permission, service-worker or shell registration, the daemon's key, the push service itself), a
12
12
  // button that proves the whole chain end-to-end is worth more than any amount of status rendering.
13
13
  export const pushContract = {
14
14
  config: oc.route({ method: "GET", path: "/push/config" }).input(PushConfigQuerySchema).output(PushConfigSchema),
@@ -2,9 +2,9 @@ import { oc } from "@orpc/contract";
2
2
  import { OkSchema, SecretInventorySchema, SecretKeyParamSchema, SecretKeysSchema, SecretRevealSchema, SecretSetSchema } from "../schemas.js";
3
3
 
4
4
  // User-supplied env-var secrets, written to the sandbox's gitignored desired-state/.env (which
5
- // `apply` reloads each run no restart). `set` upserts one KEY=value, `remove` deletes it; `list` returns the
5
+ // `apply` reloads each run, no restart). `set` upserts one KEY=value, `remove` deletes it; `list` returns the
6
6
  // keys present. `inventory` aggregates every secret store into one view (keys + status + provenance, never
7
- // values). `reveal` is the single value-returning route owner-only, POST so the key never sits in a URL.
7
+ // values). `reveal` is the single value-returning route, owner-only, POST so the key never sits in a URL.
8
8
  // set/remove/list/reveal refuse until DevOps has scaffolded the desired-state repo; inventory always answers.
9
9
  export const secretsContract = {
10
10
  set: oc.route({ method: "POST", path: "/secrets" }).input(SecretSetSchema).output(OkSchema),
@@ -3,12 +3,12 @@ import { z } from "zod";
3
3
  import { SessionTranscriptSchema } from "../events.js";
4
4
  import { SessionIdParamSchema, SessionsListSchema } from "../schemas.js";
5
5
 
6
- // Past conversations in this workspace (the SDK-native session store, keyed on the working dir which for a
6
+ // Past conversations in this workspace (the SDK-native session store, keyed on the working dir, which for a
7
7
  // repo covers its linked worktrees too, so an isolated conversation's transcript is reachable from the
8
8
  // workspace root). `list` returns summaries for the history menu (filtered by `query` when the search box is
9
9
  // used); `get` restores one transcript for display.
10
10
  //
11
- // `caseSensitive` is the filter's Aa switch, on the same terms as the fleet search's off means the letters do
11
+ // `caseSensitive` is the filter's Aa switch, on the same terms as the fleet search's, off means the letters do
12
12
  // not matter, and the two routes answer one query together (the board lists these rows under its own cards), so
13
13
  // a switch either of them ignored would show as one field returning two different match sets.
14
14
  export const sessionsContract = {