@sema-agent/sdk 0.1.9 → 1.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 (59) hide show
  1. package/README.md +17 -0
  2. package/dist/client.d.ts +1 -1
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +1 -1
  5. package/dist/client.js.map +1 -1
  6. package/dist/errors.d.ts +22 -22
  7. package/dist/errors.d.ts.map +1 -1
  8. package/dist/errors.js +105 -109
  9. package/dist/errors.js.map +1 -1
  10. package/dist/events.d.ts +11 -22
  11. package/dist/events.d.ts.map +1 -1
  12. package/dist/events.js.map +1 -1
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/normalize.d.ts +17 -4
  18. package/dist/normalize.d.ts.map +1 -1
  19. package/dist/normalize.js +16 -9
  20. package/dist/normalize.js.map +1 -1
  21. package/dist/resources/approvals.d.ts +2 -7
  22. package/dist/resources/approvals.d.ts.map +1 -1
  23. package/dist/resources/approvals.js +1 -1
  24. package/dist/resources/approvals.js.map +1 -1
  25. package/dist/resources/assistant.d.ts +1 -1
  26. package/dist/resources/assistant.js +1 -1
  27. package/dist/resources/fleet.d.ts +4 -4
  28. package/dist/resources/fleet.d.ts.map +1 -1
  29. package/dist/resources/fleet.js +1 -1
  30. package/dist/resources/fleet.js.map +1 -1
  31. package/dist/resources/images.d.ts +4 -4
  32. package/dist/resources/images.d.ts.map +1 -1
  33. package/dist/resources/images.js +4 -4
  34. package/dist/resources/images.js.map +1 -1
  35. package/dist/resources/leader.d.ts +2 -3
  36. package/dist/resources/leader.d.ts.map +1 -1
  37. package/dist/resources/leader.js +2 -3
  38. package/dist/resources/leader.js.map +1 -1
  39. package/dist/resources/memory.d.ts +11 -53
  40. package/dist/resources/memory.d.ts.map +1 -1
  41. package/dist/resources/memory.js +2 -51
  42. package/dist/resources/memory.js.map +1 -1
  43. package/dist/resources/models.d.ts +4 -4
  44. package/dist/resources/models.js +1 -1
  45. package/dist/resources/ops.d.ts +3 -3
  46. package/dist/resources/session-sync.d.ts +1 -2
  47. package/dist/resources/session-sync.d.ts.map +1 -1
  48. package/dist/resources/session-sync.js.map +1 -1
  49. package/dist/resources/sessions.d.ts +4 -4
  50. package/dist/resources/sessions.js +4 -4
  51. package/dist/resources/workspace.d.ts.map +1 -1
  52. package/dist/resources/workspace.js +5 -2
  53. package/dist/resources/workspace.js.map +1 -1
  54. package/dist/sse.js +1 -1
  55. package/dist/sse.js.map +1 -1
  56. package/dist/types.d.ts +89 -54
  57. package/dist/types.d.ts.map +1 -1
  58. package/openapi.yaml +144 -215
  59. package/package.json +2 -2
package/openapi.yaml CHANGED
@@ -9,7 +9,7 @@ openapi: 3.1.0
9
9
  # 回填这里——本文件开头曾自称"the SINGLE SOURCE OF TRUTH"、"drift fails in CI"两句均已不成立
10
10
  # (spec.test.ts 只覆盖 ~15 个类型的局部字段,`PendingCheckpoint`/`TaskStats`/`Capabilities`
11
11
  # 等核心类型的大面积字段级 drift 对 CI 完全不可见)。**现行权威 = `packages/sdk/src/types.ts`
12
- # (+ events.ts/errors.ts),逐类型带 `server.ts:行号` 实拆坐标,三批核查每一处改动都配红先行
12
+ # (+ events.ts/errors.ts),逐类型带 server 实拆坐标,三批核查每一处改动都配红先行
13
13
  # 测试锚定,是目前唯一真正贴合 server 当前实现的文档**。本文件保留作 M0 时代的历史参照(早期
14
14
  # verb 清单/大致响应形状仍可读),但**任何具体字段名/是否顶层/是否为 optional 的判断,一律以
15
15
  # types.ts 为准,本文件不可信**——已实证撞获至少一处两者互斥的真矛盾(`PendingCheckpoint`,
@@ -37,6 +37,14 @@ openapi: 3.1.0
37
37
  # bake 控制面(SDK 侧还用 `Record<string, unknown>`、没有具名类型 ⇒ 应先在 types.ts 具名);
38
38
  # `SessionBundle` 目前是本文件里唯一的孤儿 schema(无人 $ref)。
39
39
  #
40
+ # ── 📍 取证坐标的约定:**文件级,不是行级**(2026-07-29 F-f 批)────────────────────────────
41
+ # 本文件与 `types.ts` 里的 server 取证坐标一律写成 **`src/http/routes/<域文件>.ts`** 这样的文件级
42
+ # 指路,不再写 `server.ts:<行号>`。理由是实测的:server 已把 `src/http/server.ts` 拆成
43
+ # `src/http/routes/*.ts`(主体只剩约 2800 行),此前散在两侧的 ~140 处行号坐标**绝大多数已经指到
44
+ # 文件结尾之外** —— 而且就算今天逐个改对,下一次重排会再烂一遍。文件级坐标对重排免疫。
45
+ # **要行级取证**:去 server 仓按符号名/路由字面量 grep,或查该文件的 git 历史 —— 那是唯一不会腐
46
+ # 的行级真源。别把行号写回来。
47
+ #
40
48
  # Consumed by @sema-agent/sdk (→ both doors: the CC/Codex MCP façade and the
41
49
  # portal BFF). Producer = the service.
42
50
  #
@@ -176,42 +184,6 @@ paths:
176
184
  application/json:
177
185
  schema: { $ref: '#/components/schemas/ErrorResponse' }
178
186
 
179
- /v1/memory:
180
- parameters:
181
- - $ref: '#/components/parameters/PrincipalHeader'
182
- get:
183
- tags: [sessions]
184
- operationId: memoryGet
185
- x-status: live # service 170c384. Owner-scoped by construction.
186
- summary: Read your own <user_memory> (transparency surface).
187
- description: >
188
- Scope derives from the request principal (same rule as task execution) — a caller CANNOT address
189
- anyone else's memory. No principal header → 401. Discover via capabilities().memory.
190
- responses:
191
- '200':
192
- description: The memory record (content null = empty).
193
- content:
194
- application/json:
195
- schema: { $ref: '#/components/schemas/MemoryRecord' }
196
- '401': { $ref: '#/components/responses/Unauthorized' }
197
- delete:
198
- tags: [sessions]
199
- operationId: memoryClear
200
- x-status: live
201
- summary: Clear your WHOLE memory scope (per-entry deletion is a future additive).
202
- responses:
203
- '200':
204
- description: Cleared.
205
- content:
206
- application/json:
207
- schema:
208
- type: object
209
- required: [ok, scope]
210
- properties:
211
- ok: { type: boolean }
212
- scope: { type: string }
213
- '401': { $ref: '#/components/responses/Unauthorized' }
214
-
215
187
  /v1/tasks:
216
188
  parameters:
217
189
  - $ref: '#/components/parameters/PrincipalHeader'
@@ -900,7 +872,7 @@ paths:
900
872
  🔴 The 5 query params below are ADDITIVE: a request with NONE of them returns the byte-identical legacy
901
873
  payload. `?message=` SHORT-CIRCUITS to a different response schema (`SessionMessageEnvelope`) — see below.
902
874
  # 补漏(2026-07-25):此前本操作**一个 query 参数都没声明**,所以整个分页/截断/单条展开面对生成式消费方
903
- # 等于不存在。以下 5 个按 server 亲读取证(`http/server.ts:5692-5723`)。
875
+ # 等于不存在。以下 5 个按 server 亲读取证(`src/http/routes/sessions.ts`)。
904
876
  parameters:
905
877
  - name: message
906
878
  in: query
@@ -1400,7 +1372,7 @@ paths:
1400
1372
  deliberately serve as octet-stream — agent output is untrusted; `x-content-type-options: nosniff`
1401
1373
  always set) + the `x-sema-content-binary` discriminator header (first-8KiB NUL sniff, [1894]③).
1402
1374
  Capped at `capabilities.workspace.maxFileBytes` (default 8MiB, WORKSPACE_FILE_MAX_BYTES) — over-cap ⇒
1403
- 413 STRUCTURED envelope `{code: "workspace_file_too_large", sizeBytes, limit}` ([1894]①; the archive
1375
+ 413 STRUCTURED envelope `{errorCode: "workspace_file_too_large", sizeBytes, limit}` ([1894]①; the archive
1404
1376
  endpoint is the escape hatch). When the SQL size index knows the size, the 413 fires BEFORE fetching
1405
1377
  the bytes.
1406
1378
  parameters:
@@ -1419,15 +1391,15 @@ paths:
1419
1391
  '401': { $ref: '#/components/responses/Unauthorized' }
1420
1392
  '404': { $ref: '#/components/responses/NotFound' }
1421
1393
  '413':
1422
- description: 'Structured over-cap envelope: {error, code: "workspace_file_too_large", sizeBytes, limit}.'
1394
+ description: 'Structured over-cap envelope: {error, errorCode: "workspace_file_too_large", sizeBytes, limit}.'
1423
1395
  content:
1424
1396
  application/json:
1425
1397
  schema:
1426
1398
  type: object
1427
- required: [error, code, sizeBytes, limit]
1399
+ required: [error, errorCode, sizeBytes, limit]
1428
1400
  properties:
1429
1401
  error: { type: string }
1430
- code: { type: string, enum: [workspace_file_too_large] }
1402
+ errorCode: { type: string, enum: [workspace_file_too_large] }
1431
1403
  sizeBytes: { type: integer }
1432
1404
  limit: { type: integer }
1433
1405
  '501': { $ref: '#/components/responses/NotImplemented' }
@@ -1565,90 +1537,6 @@ paths:
1565
1537
  schema: { $ref: '#/components/schemas/McpStatusPanel' }
1566
1538
  '401': { $ref: '#/components/responses/Unauthorized' }
1567
1539
 
1568
- /v1/sessions/{sessionId}/memory:
1569
- parameters:
1570
- - $ref: '#/components/parameters/PrincipalHeader'
1571
- - in: path
1572
- name: sessionId
1573
- required: true
1574
- schema: { type: string }
1575
- post:
1576
- tags: [sessions]
1577
- operationId: memoryAppend
1578
- x-status: live # MF-30, service @sema-agent/server 1.3.0 (server.ts:2880).
1579
- summary: Append a memory note (MF-30 — the /memory write verb).
1580
- description: >
1581
- 🔴 Memory is PER-PRINCIPAL, not per-session — {sessionId} is only the shell's addressing context (the
1582
- /memory command runs inside some session); a note appended for a principal is visible from ALL that
1583
- principal's sessions. Note stored VERBATIM (≤8 KiB, user-authored = intentional, NOT redacted).
1584
- Empty/oversized → 400. Always available when capabilities().memoryWrite.
1585
- requestBody:
1586
- required: true
1587
- content:
1588
- application/json:
1589
- schema:
1590
- type: object
1591
- required: [content]
1592
- properties: { content: { type: string } }
1593
- responses:
1594
- '200':
1595
- description: Append ack — unified { ok, id, scope } (service; handler always returns ok).
1596
- content:
1597
- application/json:
1598
- schema: { $ref: '#/components/schemas/MemoryWriteAck' }
1599
- '400': { description: "Empty / oversized / missing content." }
1600
- '401': { $ref: '#/components/responses/Unauthorized' }
1601
-
1602
- /v1/sessions/{sessionId}/memory/{noteId}:
1603
- parameters:
1604
- - $ref: '#/components/parameters/PrincipalHeader'
1605
- - in: path
1606
- name: sessionId
1607
- required: true
1608
- schema: { type: string }
1609
- - in: path
1610
- name: noteId
1611
- required: true
1612
- schema: { type: string }
1613
- patch:
1614
- tags: [sessions]
1615
- operationId: memoryEdit
1616
- x-status: live # MF-30 (server.ts:2881).
1617
- summary: Edit one memory note by id (id unchanged).
1618
- description: >
1619
- 🔴 501 when the backend lacks id-addressable update (honest degrade, never a fake 200). Per-PRINCIPAL.
1620
- requestBody:
1621
- required: true
1622
- content:
1623
- application/json:
1624
- schema:
1625
- type: object
1626
- required: [content]
1627
- properties: { content: { type: string } }
1628
- responses:
1629
- '200':
1630
- description: Edited note ack.
1631
- content:
1632
- application/json:
1633
- schema: { $ref: '#/components/schemas/MemoryWriteAck' }
1634
- '401': { $ref: '#/components/responses/Unauthorized' }
1635
- '501': { description: "Backend lacks id-addressable update." }
1636
- delete:
1637
- tags: [sessions]
1638
- operationId: memoryForget
1639
- x-status: live # MF-30 (server.ts:2882).
1640
- summary: Forget one memory note by id.
1641
- description: >
1642
- 🔴 501 when the backend lacks id-addressable delete (honest degrade). Per-PRINCIPAL.
1643
- responses:
1644
- '200':
1645
- description: Forgotten note ack.
1646
- content:
1647
- application/json:
1648
- schema: { $ref: '#/components/schemas/MemoryWriteAck' }
1649
- '401': { $ref: '#/components/responses/Unauthorized' }
1650
- '501': { description: "Backend lacks id-addressable delete." }
1651
-
1652
1540
  # ── 2c session-sync (P1d) — the cloud as a SYNC PEER ──────────────────────────────────────────────────────────
1653
1541
  # The local shell's local backend ⇄ this cloud service. PULL a session's whole state out, or PUSH the local
1654
1542
  # peer's in. Gate the whole surface off `capabilities.sessionSync` (= durable backend + entry export + a
@@ -1997,9 +1885,8 @@ paths:
1997
1885
  description: >
1998
1886
  Resolves a `suspended` run: an F4 approve/deny, or an answer to an AskUserQuestion. The resumed run
1999
1887
  continues its durable stream (`/v1/runs/:id/events`). design/80 D-1: the decision SHOULD carry the
2000
- action binding (checkpointToken/boundCallId/boundInputHash read off the PendingCheckpoint) — the server
2001
- resolves THAT exact checkpoint, fail-closed on mismatch. (Path param stays `sessionId` until service
2002
- finalizes a checkpointToken-keyed route; the binding travels in the body regardless.)
1888
+ action binding (boundCallId + boundInputHash, read off the PendingCheckpoint) — the server resolves THAT
1889
+ exact checkpoint, fail-closed on mismatch. (Path param stays `sessionId`; the binding travels in the body.)
2003
1890
  requestBody:
2004
1891
  required: true
2005
1892
  content:
@@ -2179,7 +2066,7 @@ paths:
2179
2066
  Owner-gated (NOT D-G); non-owner → 404. SDK → GateNotResumableError on the 409.
2180
2067
  responses:
2181
2068
  '200':
2182
- # 2026-07-25:此前只声明 `{status}`。真体(`http/server.ts:7688-7696`,与 plan_review 共用
2069
+ # 2026-07-25:此前只声明 `{status}`。真体(`src/http/routes/approvals-assistant.ts`,与 plan_review 共用
2183
2070
  # `driveResumeIntoRunLog`)带 taskId/sessionId + 失败态的 errorCode/errorMessage/retriable。
2184
2071
  description: >
2185
2072
  Resumed. 🔴 A 200 does NOT mean success — `status` can be `failed`, in which case `errorCode`/
@@ -2491,7 +2378,7 @@ paths:
2491
2378
  get:
2492
2379
  tags: [models]
2493
2380
  operationId: modelsList
2494
- x-status: live # service GET /v1/models (server.ts:859-882). SDK models.list().
2381
+ x-status: live # service GET /v1/models (src/http/routes/capabilities.ts). SDK models.list().
2495
2382
  summary: Non-secret model catalog (the `@model` picker / autocomplete data source).
2496
2383
  description: >
2497
2384
  READ-ONLY catalog of `@mention`-pickable models. The user selects a model PER-TASK by typing `@<name>` in
@@ -2787,7 +2674,7 @@ paths:
2787
2674
  get:
2788
2675
  tags: [fleet]
2789
2676
  operationId: fleetStream
2790
- x-status: live # service 1bf7a5c — streamFleet (http/server.ts:4874) + fleet/fleet-bus.ts. Owner-gated; in-process bus; NOT resumable.
2677
+ x-status: live # service 1bf7a5c — streamFleet (src/http/routes/fleet.ts) + fleet/fleet-bus.ts. Owner-gated; in-process bus; NOT resumable.
2791
2678
  summary: Live multi-row fleet view SSE (NON-resumable).
2792
2679
  description: >
2793
2680
  MF-Fleet (shell-host data contract). The LIVE fleet as an SSE PUSH stream: a SNAPSHOT on connect, then a
@@ -3474,9 +3361,12 @@ components:
3474
3361
  schema: { $ref: '#/components/schemas/ErrorResponse' }
3475
3362
  RateLimited:
3476
3363
  description: >
3477
- 429 — per-principal CUMULATIVE quota exceeded (`quotaExceeded`). `Retry-After` (seconds) honored by the
3478
- SDK on retry. This is the ONLY budget/limit signal at the HTTP layer; per-task budget gates are
3479
- result-level (200 + errorCode), NOT here (pinned wire contract).
3364
+ 429 — a limit was hit. Three real `errorCode`s ride this status: `limit.cost_quota_exceeded`
3365
+ (per-principal CUMULATIVE cost quota — the QuotaError body below), `limit.rate_exceeded`
3366
+ (request-rate limit; also the status-derived fallback code), and `quota_exhausted` (the E4 fleet
3367
+ quota-LEASE budget). `Retry-After` (seconds) honored by the SDK on retry. These are the ONLY
3368
+ budget/limit signals at the HTTP layer; per-task budget gates are result-level (200 + errorCode),
3369
+ NOT here (pinned wire contract).
3480
3370
  headers:
3481
3371
  Retry-After:
3482
3372
  schema: { type: integer }
@@ -3521,7 +3411,7 @@ components:
3521
3411
 
3522
3412
  ScenarioDetail:
3523
3413
  # 新增(2026-07-25 回填批):`GET /v1/capabilities/scenarios/{name}` 此前**整条路径**都不在本文件里
3524
- # (只有 `Capabilities.scenarios` 那个名字数组)。形按 server 亲读取证(`http/server.ts:1517-1527`)。
3414
+ # (只有 `Capabilities.scenarios` 那个名字数组)。形按 server 亲读取证(`src/http/routes/capabilities.ts`)。
3525
3415
  type: object
3526
3416
  description: >
3527
3417
  One scenario's detail card (`GET /v1/capabilities/scenarios/{name}`). The LIST of names rides
@@ -3557,7 +3447,6 @@ components:
3557
3447
  promptTokens: { type: integer }
3558
3448
  cachedTokens: { type: integer }
3559
3449
  outputTokens: { type: integer }
3560
- costUsd: { type: number, deprecated: true, description: "Legacy float track — prefer integer costMicroUsd for accounting (no FP drift); canonical read = the SDK's taskCostMicroUsd() normalizer. Kept on the wire (older engines still emit it)." }
3561
3450
  cacheHitRate: { type: number }
3562
3451
  toolCalls: { type: integer }
3563
3452
  cacheWriteTokens: { type: integer, description: Short-TTL cache-write tokens. }
@@ -3568,8 +3457,15 @@ components:
3568
3457
  costMicroUsd:
3569
3458
  type: integer
3570
3459
  description: >
3571
- Integer micro-USD cost. Prefer this over the float `costUsd` for accounting (no FP drift). Both are
3572
- emitted; they describe the same spend.
3460
+ Integer micro-USD cost — the ONLY cost track on this object (core 2.0.0 removed the legacy float
3461
+ `costUsd` at the source, server 1.319.0 adopted it, and SDK 1.0.0 removed the mirroring field plus its
3462
+ ×1e6 fallback). Canonical read = the SDK's `taskCostMicroUsd()` normalizer (integer pass-through + a
3463
+ non-finite guard).
3464
+ ⚠️ SCOPE: this removal covers `TaskStats` (and its nested/checkpoint variants) ONLY. The float
3465
+ `costUsd` on the SERVER's own accounting surfaces is alive and untouched — `GET /metrics/summary`
3466
+ (`costUsd`/`costUsdByModel`) and the usage-analytics face (`UsageTotals.costUsd`, `?metric=costUsd`)
3467
+ are server-side aggregates computed as Σ costMicroUsd / 1e6. Seeing those is NOT evidence of an
3468
+ un-upgraded peer.
3573
3469
  costBreakdown:
3574
3470
  description: >
3575
3471
  Per-axis cost detail (LLM root / nested subagents / compaction / infra). Deliberately untyped — it is an
@@ -3665,6 +3561,25 @@ components:
3665
3561
  sessionId:
3666
3562
  type: string
3667
3563
  description: Continue a conversation (same sessionId across turns). Omit on first turn → service mints one.
3564
+ requireExistingSession:
3565
+ type: boolean
3566
+ description: >
3567
+ design/114 Phase3 warm-resume assertion: require `sessionId` to ALREADY exist. `true` + a genuinely
3568
+ missing session (expired / purged / never created) ⇒ the run FAILS LOUD (`resume.session_not_found`)
3569
+ instead of silently starting a fresh empty session ("looks warm, actually fresh"). Sending `true`
3570
+ with NO sessionId also fails loud (nothing to resume). Absent/`false` ⇒ the historical create-on-miss.
3571
+ Rides the persisted body onto resume legs.
3572
+ projectId:
3573
+ type: string
3574
+ description: >
3575
+ design/142-S4: which PROJECT this run belongs to (a center registry key — generic lowercase UUID).
3576
+ A SELECTOR, not an identity or a capability: the tenant segment of any scope always comes from the
3577
+ verified principal, and the client only passes this through (zero minting authority). Shape-gated in
3578
+ the server authorizer — a malformed value is a 422 with `errorCode: "invalid_project_id"`. On the
3579
+ multi-tenant DB memory face it moves the derived scope from the user shelf to the project shelf
3580
+ (`proj:<tenant>/<projectId>`) and seeds `memory.scopes` from that project's `defaultScopes`;
3581
+ single-user deployments ignore the derivation and only apply the seed. Rides the persisted body
3582
+ onto resume legs.
3668
3583
  jobId:
3669
3584
  type: string
3670
3585
  minLength: 1
@@ -3717,6 +3632,18 @@ components:
3717
3632
  branch via setLeafId). With rewindFiles=true ⇒ "both" (also restore the working tree). Alone ⇒
3718
3633
  "conversation". HONORED only where the deployment wired a resume-anchor store + getLeafId (capabilities.resumeAt);
3719
3634
  unknown anchor ⇒ 4xx, capability-off ⇒ 501. Cannot combine with a durable resume.
3635
+ resumeAtMode:
3636
+ type: string
3637
+ enum: [at, before]
3638
+ description: >
3639
+ [833] EXCLUSIVE rewind (core 1.292 TaskSpec.resumeAtMode) — qualifies `resumeAt`'s landing point.
3640
+ `at` (the default when absent — zero regression) KEEPS the target message in the branched context;
3641
+ `before` branches at the target's PARENT, EXCLUDING the target itself ("remove this prompt and
3642
+ everything after it"). core enforces the edges and the service passes its rejection codes through
3643
+ UNCHANGED for the shell to render: `resume_at.before_target_not_user` (plain user-message targets
3644
+ only), `resume_at.before_root_unsupported` (cannot rewind past the session root — start a new
3645
+ session), `rewind_snapshot.unresolvable` (with rewindFiles: no snapshot at/above the branch point).
3646
+ Only meaningful WITH `resumeAt` — sent alone it is a 400 (fail-loud, not a silent no-op).
3720
3647
  rewindFiles:
3721
3648
  type: boolean
3722
3649
  description: >
@@ -3890,7 +3817,28 @@ components:
3890
3817
  deadlineNudge: { type: boolean, enum: [false] }
3891
3818
  callCapByDeadline: { type: boolean, enum: [false] }
3892
3819
  gracefulFinalize: { type: boolean, enum: [false] }
3820
+ outputSchema:
3821
+ type: object
3822
+ additionalProperties: true
3823
+ description: >
3824
+ Structured-output constraint (CC `--json-schema`): a JSON Schema the model's FINAL answer must match.
3825
+ Threaded into core's TaskSpec.outputSchema, which injects a built-in `submit_output` tool and surfaces
3826
+ the validated object as `TaskResult.structuredOutput`. An invalid submit retries (see `outputRetries`),
3827
+ then fails the task with `output.invalid`. A plain JSON-Schema OBJECT — the server validates shape and
3828
+ size; deep validity is core's. (Paired knob: `outputRetries` was already declared without this one.)
3893
3829
  outputRetries: { type: integer, description: How many times to retry a malformed structured output. }
3830
+ resilience:
3831
+ type: object
3832
+ description: >
3833
+ design/131 (core 1.246) per-task resilience INTENT flags. `allowDegrade` / `allowFailover` are
3834
+ caller-facing (permit model degradation / provider failover for this run). `bypassBreaker` is
3835
+ OPERATOR-ONLY: for a non-operator caller resolveSpec DROPS the key — a permission downgrade, not a
3836
+ 400, so a 2xx does NOT mean the breaker was actually bypassed. All opt-in; absent ⇒ the deployment's
3837
+ default resilience posture.
3838
+ properties:
3839
+ allowDegrade: { type: boolean }
3840
+ allowFailover: { type: boolean }
3841
+ bypassBreaker: { type: boolean, description: 'Operator-only; silently dropped for non-operator callers.' }
3894
3842
  compaction:
3895
3843
  type: object
3896
3844
  description: Compaction tuning for this task.
@@ -4143,7 +4091,10 @@ components:
4143
4091
 
4144
4092
  QuotaError:
4145
4093
  type: object
4146
- description: 429 per-principal cumulative-quota body (`quotaExceeded`).
4094
+ description: >
4095
+ 429 per-principal cumulative COST-quota body (`errorCode: "limit.cost_quota_exceeded"`). The other two
4096
+ 429 codes carry different bodies: `limit.rate_exceeded` sends only `retryAfterSec`, and
4097
+ `quota_exhausted` (E4 lease) passes the center's structured deny fields through verbatim.
4147
4098
  additionalProperties: true
4148
4099
  properties:
4149
4100
  error: { type: string }
@@ -4304,10 +4255,11 @@ components:
4304
4255
  selected: { type: array, items: { type: string } }
4305
4256
  note: { type: string }
4306
4257
  reason: { type: string }
4307
- # design/80 D-1 — action binding (TOCTOU guard). Read the three off the PendingCheckpoint the human saw
4258
+ # design/80 D-1 — action binding (TOCTOU guard). Read the TWO off the PendingCheckpoint the human saw
4308
4259
  # and echo VERBATIM; server resolves THAT exact checkpoint, fail-closed on mismatch (approval_binding_mismatch).
4309
4260
  # Omit only against a pre-D-1 worker. boundInputHash is OPAQUE — never hashed/recomputed client-side.
4310
- checkpointToken: { type: string, description: 'Single-use token of the exact checkpoint the human saw.' }
4261
+ # 🔴 `checkpointToken` REMOVED (SDK 1.0.0): §4a makes it server-INTERNAL and it is NEVER surfaced on a
4262
+ # /v1/approvals row, so a compliant client has no way to obtain a correct value for it.
4311
4263
  boundCallId: { type: string, description: '= PendingCheckpoint.boundCallId (the bound pendingAction.toolCallId).' }
4312
4264
  boundInputHash: { type: string, description: 'Echo PendingCheckpoint.boundInputHash byte-for-byte; server-minted opaque, NEVER recompute.' }
4313
4265
  updatedInput:
@@ -4337,7 +4289,14 @@ components:
4337
4289
  description: false ⇒ stats.costMicroUsd=0 may mean "no MODEL_COST_* configured", not "free".
4338
4290
  memory:
4339
4291
  type: boolean
4340
- description: Memory transparency endpoints (GET/DELETE /v1/memory) available. the pinned wire contract.
4292
+ description: >
4293
+ 🔴 HARD-CODED `false` on every current server (design/138 S1, clay 2026-07-08): it advertised the
4294
+ legacy MemoryStore surface (`GET`/`DELETE /v1/memory`), which was retired together with the store
4295
+ itself. The memory ENGINE that replaced it is model-facing skills over an injected memory dir and
4296
+ has NO service HTTP verbs, so this flag is not its availability signal. The SDK removed the five
4297
+ legacy verbs in 1.0.0; the live face is `client.memory.exportScope` / `.sync`
4298
+ (`GET /v1/memory/export`, `POST /v1/memory/sync/{scope}`), which this flag does NOT gate.
4299
+ Kept on the wire so an older shell that still reads it honestly hides the dead affordances.
4341
4300
  workflows: { type: boolean, description: "S8 self-orchestration workflow routes are mounted." }
4342
4301
  workflowsList: { type: boolean, description: "`GET /v1/workflows` list face (separate from the per-run reads)." }
4343
4302
  resumeAt: { type: boolean, description: "E18 resume-at-message anchors are resolvable." }
@@ -4444,12 +4403,16 @@ components:
4444
4403
  hooks: { type: boolean }
4445
4404
  memoryWrite:
4446
4405
  type: boolean
4447
- description: MF-30 — memory WRITE (append/edit/forget) available (deps.memory.append; server.ts:828).
4406
+ description: >
4407
+ 🔴 HARD-CODED `false` on every current server, for the same reason as `memory` above: it advertised
4408
+ the MF-30 session memory WRITE verbs, retired with the legacy MemoryStore (SDK 1.0.0 removed them).
4409
+ NOT related to `TaskRequest.memoryWrite` (the per-run memory-engine write PAUSE toggle), which is
4410
+ live and ungated by this flag.
4448
4411
  sessionSync:
4449
4412
  type: boolean
4450
4413
  description: >
4451
4414
  2c session-sync (P1d) — the `/v1/sessions/{sessionId}/sync/*` peer routes resolve (durable backend +
4452
- entry-export seam + a file-snapshot store wired; server.ts:850). Gate the whole sync surface off this.
4415
+ entry-export seam + a file-snapshot store wired; src/http/routes/capabilities.ts). Gate the whole sync surface off this.
4453
4416
 
4454
4417
  SkillSpec:
4455
4418
  type: object
@@ -4495,28 +4458,10 @@ components:
4495
4458
  egress: { type: boolean }
4496
4459
  irreversibility: { type: string, enum: [always, never] }
4497
4460
 
4498
- MemoryRecord:
4499
- type: object
4500
- description: The caller's own <user_memory> (owner-scoped by construction). content null = empty.
4501
- required: [scope, content]
4502
- properties:
4503
- scope: { type: string }
4504
- content: { type: ['string', 'null'] }
4505
-
4506
- MemoryWriteAck:
4507
- type: object
4508
- description: MF-30 write ack — unified { ok, id, scope } for append/edit/forget (service; the handler
4509
- always returns ok — the old src:2880 summary comment that dropped it was a doc-bug). id = the note (unchanged on edit).
4510
- required: [ok, id, scope]
4511
- properties:
4512
- ok: { type: boolean }
4513
- id: { type: string }
4514
- scope: { type: string }
4515
-
4516
4461
  ModelInfo:
4517
4462
  type: object
4518
4463
  description: >
4519
- A non-secret `@model` catalog entry (GET /v1/models; service server.ts:860-880). `name` = the `@handle` the
4464
+ A non-secret `@model` catalog entry (GET /v1/models; service src/http/routes/capabilities.ts). `name` = the `@handle` the
4520
4465
  user types in the objective body to pick this model per-task. 🔴 NON-SECRET — name/capabilities only, never
4521
4466
  baseUrl/apiKey/headers (the service strips them). Open set (additive future fields).
4522
4467
  required: [name]
@@ -4867,7 +4812,7 @@ components:
4867
4812
  tokens: { type: integer }
4868
4813
  FleetFrame:
4869
4814
  description: >
4870
- One decoded frame off GET /v1/fleet/stream (service streamFleet emit set, http/server.ts:4877-4908). On the
4815
+ One decoded frame off GET /v1/fleet/stream (service streamFleet emit set, src/http/routes/fleet.ts). On the
4871
4816
  wire this is SSE framing (the `type` here = the SSE `event` name; the object = the decoded `data:` JSON).
4872
4817
  Emit order: `meta` (FIRST) → `snapshot` (connect-time full set) → per-row `task`/`workflow` upserts +
4873
4818
  `task_remove`/`workflow_remove` departures. The SDK PRODUCES these frames; the consumer maintains the
@@ -5070,7 +5015,7 @@ components:
5070
5015
  description: >
5071
5016
  The `GET /v1/approvals` operator queue row (true shape). NEVER includes a capability token.
5072
5017
  ⚠️ `createdAt`/`deadline` are EPOCH MILLISECONDS (numbers), not ISO strings.
5073
- 🔴 真矛盾撞获+纠正(2026-07-25,core [1640] 审计撞获 + server 复核确认 server.ts:4536→
5018
+ 🔴 真矛盾撞获+纠正(2026-07-25,core [1640] 审计撞获 + server 复核确认 src/http/routes/approvals-assistant.ts→
5074
5019
  listPending() 真实实现 `src/plugins/tidb-checkpoint-store.ts:54-79`):这份 schema 此前声称
5075
5020
  "MIRRORS core CheckpointSummary,顶层 gateKind/severity,NEVER a riskDescriptor object"——
5076
5021
  与真实实现完全相反。真实的 `PendingCheckpoint`(service 自定义类型,不是 core 的
@@ -5243,7 +5188,7 @@ components:
5243
5188
  type: string
5244
5189
  # 🔴 `needs_review` 是 2026-07-25 补的:server 的行过滤器逐字是
5245
5190
  # `.filter(r => r.status === "running" || r.status === "suspended" || r.status === "needs_review")`
5246
- # (`http/server.ts:4677`,已亲读取证)——本枚举此前只有前两个,是真陈旧,照它生成的客户端会把一个
5191
+ # (`src/http/routes/approvals-assistant.ts`,已亲读取证)——本枚举此前只有前两个,是真陈旧,照它生成的客户端会把一个
5247
5192
  # 合法的一等 triage 态判成非法值。字段级 drift 门只比字段名、比不到枚举值,所以它没抓到这条。
5248
5193
  enum: [running, suspended, needs_review]
5249
5194
  description: >
@@ -5277,9 +5222,9 @@ components:
5277
5222
  AssistantTaskStatus:
5278
5223
  # 新增(2026-07-25 回填批):§4b resume / §4c plan_review / §4d preempt 三条决策端点此前在本文件里都只声明
5279
5224
  # 了 `{status}` 一个字段——与 SDK 三批核查前的旧类型同样陈旧。下面的形按 server 源码逐字取证:
5280
- # • resume / plan_review 200(共用 `driveResumeIntoRunLog`,`http/server.ts:7688-7696`):
5225
+ # • resume / plan_review 200(共用 `driveResumeIntoRunLog`,`src/http/routes/approvals-assistant.ts`):
5281
5226
  # `{ taskId, sessionId, status, errorCode?, errorMessage?, retriable? }`(后三个条件 spread ⇒ 缺则省键)
5282
- # • preempt 202(`http/server.ts:4726/4734/4737` 三个出口):`{ taskId, status, note }`
5227
+ # • preempt 202(`src/http/routes/approvals-assistant.ts` 三个出口):`{ taskId, status, note }`
5283
5228
  # ⚠️ `status` 在 202 上**并非恒为 `"preempting"`**:两个 no-op 出口分别回 `run.status` 与
5284
5229
  # `now?.status ?? "failed"` —— 所以这里不能把它写成 const。
5285
5230
  type: object
@@ -5649,15 +5594,19 @@ components:
5649
5594
  description: >
5650
5595
  Typed-error source. The SDK maps (status, errorCode) → a semantic error class so callers branch on the
5651
5596
  error, not a string. Messages are secret-scrubbed before surfacing.
5652
- 🔴 CANONICAL KEY (server >=1.302, 2026-07-28 归一): `errorCode` is ALWAYS present on typed error
5653
- bodies — the historical `code`-only track is retired (a source-level gate enforces it server-side).
5654
- `code` may still ride alongside as the historical/original-core-code slot; consumers read `errorCode`.
5597
+ 🔴 SINGLE KEY (server >=3.0.0): `errorCode` is the ONLY machine key on a typed error body. The
5598
+ historical `code` slot is GONE at the source (`http/send.ts` emits `{error, errorCode, ...extra}`;
5599
+ a source-level gate enforces it server-side) and the SDK no longer reads it — a body that still
5600
+ sends `code` yields `errorCode: undefined` and no typed subclass.
5655
5601
  additionalProperties: true
5656
5602
  properties:
5657
5603
  errorCode:
5658
5604
  type: string
5659
5605
  description: >
5660
- HTTP-error typed code. Known: `conflict` (409 session active / CAS), `quotaExceeded` (429).
5606
+ HTTP-error typed code. Real examples: `conflict` (409 session active / CAS);
5607
+ `limit.cost_quota_exceeded` (429 — the principal's CUMULATIVE cost quota; body = QuotaError);
5608
+ `limit.rate_exceeded` (429 — request-rate limit, also the status-derived fallback code);
5609
+ `quota_exhausted` (429 — the E4 fleet quota-LEASE budget, distinct from the cost quota).
5661
5610
  NOTE: budget (`budget.precall`/`budget.exceeded`) and `cancelled` are RESULT-level codes on
5662
5611
  TaskResult/RunRecord, NOT HTTP errors (pinned wire contract).
5663
5612
  error: { type: string }
@@ -5700,8 +5649,6 @@ components:
5700
5649
  - $ref: '#/components/schemas/Event_steering_injected'
5701
5650
  - $ref: '#/components/schemas/Event_done'
5702
5651
  - $ref: '#/components/schemas/Event_failed'
5703
- # design/158 B2: deprecated durable-leg alias — see Event_brain_status's own description.
5704
- - $ref: '#/components/schemas/Event_brain_status'
5705
5652
  discriminator:
5706
5653
  propertyName: type
5707
5654
  mapping:
@@ -5727,7 +5674,6 @@ components:
5727
5674
  steering_injected: '#/components/schemas/Event_steering_injected'
5728
5675
  done: '#/components/schemas/Event_done'
5729
5676
  failed: '#/components/schemas/Event_failed'
5730
- brain_status: '#/components/schemas/Event_brain_status'
5731
5677
 
5732
5678
  # design/99 §E2 (SHIPPED, core TaskEventIdentity) — additive per-event identity on every CONTENT event (NOT on
5733
5679
  # the lifecycle arms turn_end/compacted/suspended/done/failed). eventId = uuidv7 dedup/resume handle (the durable
@@ -5831,7 +5777,7 @@ components:
5831
5777
  Event_suggestions:
5832
5778
  type: object
5833
5779
  description: >
5834
- E12 (shell-host; service runs.ts:392 + server.ts:3633, opt-in via `TaskRequest.suggestNextPrompts`) —
5780
+ E12 (shell-host; service runs.ts:392 + src/http/routes/runs.ts, opt-in via `TaskRequest.suggestNextPrompts`) —
5835
5781
  post-completion "what to ask next" prompt suggestions. Appended to the DURABLE run-events tail AFTER a
5836
5782
  `done` with `status:"completed"` (core's fire-and-forget LLM pass). 🔴 UNTRUSTED model text, service-
5837
5783
  redacted, UI-ONLY — render as clickable next-prompt chips; NEVER re-feed to a model. Empty/absent ⇒ none.
@@ -5848,10 +5794,10 @@ components:
5848
5794
  phase on its own channel). 🔴 WIRE NOTE (design/158 B2, corrects the prior "EPHEMERAL — never
5849
5795
  persisted/replayed on resume" claim): the durable/replay leg (GET /v1/runs/:id/events) DOES persist this
5850
5796
  as its own liveness observation row. Server >=1.317 uses this SAME arm name on both legs AND normalizes
5851
- pre-upgrade rows (stored under the literal `brain_status`) to `status` at the read boundary — stored
5852
- bytes untouched, but a >=1.317 server never delivers the old literal; it only reaches consumers of a
5853
- server <1.317 (see Event_brain_status below — same shape, deprecated alias, additive-only, never emitted
5854
- on the live leg at any version).
5797
+ pre-upgrade rows (stored under the historical literal `brain_status`) to `status` at the read boundary —
5798
+ stored bytes untouched, but a >=1.317 server never delivers the old literal. 🔴 The deprecated
5799
+ `brain_status` alias arm was REMOVED from this union in SDK 1.0.0 (supported floor = server >=1.317, at
5800
+ which point the literal is never emitted on either leg).
5855
5801
  allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
5856
5802
  required: [type, phase]
5857
5803
  properties:
@@ -5859,23 +5805,6 @@ components:
5859
5805
  phase: { type: string, description: "rate_limited | retrying | reconnecting | circuit_open (open set)" }
5860
5806
  detail: { type: string, description: "neutral human hint (NO provider/HTTP detail)" }
5861
5807
  retryInSec: { type: number }
5862
- Event_brain_status:
5863
- type: object
5864
- deprecated: true
5865
- description: >
5866
- design/158 B2 — DEPRECATED historical durable-leg alias for Event_status (same field shape). Server
5867
- <1.317 wrote (and on replay delivers) the liveness-observation row under the literal type `brain_status`
5868
- instead of `status`. Server >=1.317 never writes this literal AND normalizes pre-upgrade rows to `status`
5869
- at the read boundary, so this literal only ever reaches a consumer whose server is <1.317 — kept in the
5870
- spec/SDK union only so that consumer can still type-check the frame. Never emitted on the live leg
5871
- (POST /v1/tasks/stream) at any server version.
5872
- allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
5873
- required: [type, phase]
5874
- properties:
5875
- type: { const: brain_status }
5876
- phase: { type: string, description: "rate_limited | retrying | reconnecting | circuit_open (open set)" }
5877
- detail: { type: string, description: "neutral human hint (NO provider/HTTP detail)" }
5878
- retryInSec: { type: number }
5879
5808
  Event_task_progress:
5880
5809
  type: object
5881
5810
  description: >
@@ -6329,7 +6258,7 @@ components:
6329
6258
  ApprovalStreamEvent:
6330
6259
  type: object
6331
6260
  description: >
6332
- One delta event off GET /v1/approvals/stream (SSE; server streamApprovals, http/server.ts:8924).
6261
+ One delta event off GET /v1/approvals/stream (SSE; server streamApprovals, src/http/routes/approvals-assistant.ts).
6333
6262
  Every data payload echoes a `type` field mirroring the SSE event name (so a client can dispatch
6334
6263
  without the `event:` line). OPEN set — a consumer that does not parse the delta can treat any
6335
6264
  non-heartbeat event as a "changed" signal and refetch the authoritative GET /v1/approvals list.
@@ -6366,7 +6295,7 @@ components:
6366
6295
  FleetMeta:
6367
6296
  type: object
6368
6297
  description: >
6369
- The connect-time `meta` frame payload of GET /v1/fleet/stream (server http/server.ts:9675 —
6298
+ The connect-time `meta` frame payload of GET /v1/fleet/stream (server src/http/routes/fleet.ts —
6370
6299
  the payload view of FleetFrame_meta, without the SSE frame envelope).
6371
6300
  required: [version, scoped]
6372
6301
  additionalProperties: true
@@ -6455,7 +6384,7 @@ components:
6455
6384
  type: object
6456
6385
  description: >
6457
6386
  The RUNNER claim response of POST /v1/images/bakes/claim and POST /v1/images/bakes/{bakeId}/claim
6458
- (server claimResponse, http/server.ts:9164 — exact key set): the VETTED argv + the per-bake ingest
6387
+ (server claimResponse, src/http/routes/images.ts — exact key set): the VETTED argv + the per-bake ingest
6459
6388
  secret (minted at claim, echoed on every ingest via the x-bake-ingest-secret header) + the
6460
6389
  profile/bands the runner needs for its profile-aware hard deadline. The runner executes `argv`
6461
6390
  VERBATIM — it never assembles its own command line. 204 (no body) = queue empty.
@@ -6497,7 +6426,7 @@ components:
6497
6426
  type: object
6498
6427
  description: >
6499
6428
  One SendUserFile distribution-link ledger row of GET /v1/sendfile-links (envelope `{links,
6500
- nextBefore?}`; server http/server.ts:5504 — exact projection). A principal caller is PINNED to its
6429
+ nextBefore?}`; server src/http/routes/sessions-list.ts — exact projection). A principal caller is PINNED to its
6501
6430
  own scope (?scope= ignored); a fleet credential may pass ?scope= (default = the single-user
6502
6431
  sentinel "_"). Page with `before` = a previous page's `nextBefore` (uuidv7; malformed → 400).
6503
6432
  required: [id, filename, size, ttlSec, track, bucket, key, createdAt]
@@ -6518,7 +6447,7 @@ components:
6518
6447
  type: object
6519
6448
  description: >
6520
6449
  The 200 receipt of POST /v1/runs/{runId}/subagents/{target}/steer and …/resume (server
6521
- http/server.ts:4143/4148 — exact literal: `status:"running"`, `delivery:"applied"`, `marker` =
6450
+ src/http/routes/runs.ts — exact literal: `status:"running"`, `delivery:"applied"`, `marker` =
6522
6451
  the engine-minted delivery marker, `note` = the CC-verbatim "Message queued for delivery…" copy).
6523
6452
  required: [taskId, target]
6524
6453
  additionalProperties: true
@@ -6534,7 +6463,7 @@ components:
6534
6463
  type: object
6535
6464
  description: >
6536
6465
  The 200 body of GET /v1/runs/{runId}/subagents/{target}/output and the generic
6537
- …/tasks/{target}/output|/stop faces (server http/server.ts:3852/4070). `content` = the engine
6466
+ …/tasks/{target}/output|/stop faces (server src/http/routes/runs.ts). `content` = the engine
6538
6467
  TaskOutput-tool text (the child's final assistant body once terminal) — UNTRUSTED model output,
6539
6468
  same posture as a run `result`. `output` = the engine registry's UnifiedTaskOutput projection
6540
6469
  passed through VERBATIM.
@@ -6571,7 +6500,7 @@ components:
6571
6500
  CompactAck:
6572
6501
  type: object
6573
6502
  description: >
6574
- The 202 ack of POST /v1/runs/{runId}/compact (K-1c manual compaction; server http/server.ts:3595 —
6503
+ The 202 ack of POST /v1/runs/{runId}/compact (K-1c manual compaction; server src/http/routes/runs.ts —
6575
6504
  exact literal: `status:"running"`, `delivery:"accepted"`). ACCEPTANCE, not an outcome: compaction
6576
6505
  runs at the next turn boundary and a `compacted{trigger:"manual"}` event rides the run stream ONLY
6577
6506
  if anything was summarized (mooted/failed → no event).
@@ -6586,7 +6515,7 @@ components:
6586
6515
  DetachAck:
6587
6516
  type: object
6588
6517
  description: >
6589
- The 202 ack of POST /v1/runs/{runId}/detach (server http/server.ts:3650 — exact literal:
6518
+ The 202 ack of POST /v1/runs/{runId}/detach (server src/http/routes/runs.ts — exact literal:
6590
6519
  `toolCallId` echoed, `delivery:"requested"`). Fire-and-forget: acceptance only — the
6591
6520
  authoritative outcome is the tool call's own `tool_end.structured {detached:true, task_id}`;
6592
6521
  a non-detachable env makes the request a fail-safe no-op.
@@ -6601,7 +6530,7 @@ components:
6601
6530
  SideQueryRequest:
6602
6531
  type: object
6603
6532
  description: >
6604
- The POST /v1/side-query body ([1469], server 1.242; http/server.ts:1853 — whitelist passthrough of
6533
+ The POST /v1/side-query body ([1469], server 1.242; src/http/routes/side-query.ts — whitelist passthrough of
6605
6534
  core SideQuerySpec). One-shot brain routing Q&A: no session side effects, no tool EXECUTION, no
6606
6535
  engine-side policy gate, no streaming (v1). `signal` is server territory — client disconnect
6607
6536
  abandons the call; sending it in the body is discarded. Rides every billable-submit gate
@@ -6633,7 +6562,7 @@ components:
6633
6562
  type: object
6634
6563
  description: >
6635
6564
  The 200 body of POST /v1/side-query (core SideQueryResult passed through verbatim, server
6636
- http/server.ts:1917). `model` = routing identity; `servedModel` = who actually served (degrading
6565
+ src/http/routes/side-query.ts). `model` = routing identity; `servedModel` = who actually served (degrading
6637
6566
  fallback attributes honestly). A post-stream error lands in `errorMessage`, NOT an HTTP error
6638
6567
  (400 is reserved for validation/model-resolution; 5xx = a server defect).
6639
6568
  required: [text, toolCalls, model, servedModel, usage, stopReason]
@@ -6737,7 +6666,7 @@ components:
6737
6666
  type: object
6738
6667
  description: >
6739
6668
  The common window envelope of the /v1/usage/{summary,series,breakdown} responses (server
6740
- http/server.ts:1284). `from`/`to` are the RESOLVED window (ISO-8601; defaults now-7d..now).
6669
+ src/http/routes/trace-usage.ts). `from`/`to` are the RESOLVED window (ISO-8601; defaults now-7d..now).
6741
6670
  required: [from, to]
6742
6671
  additionalProperties: true
6743
6672
  properties:
@@ -6749,14 +6678,14 @@ components:
6749
6678
  description: 'Present (true) ⇔ the store scan hit its row limit (USAGE_SCAN_LIMIT) — the window was truncated, never silently.'
6750
6679
 
6751
6680
  UsageSummary:
6752
- description: 'The 200 body of GET /v1/usage/summary — window envelope + totals (server http/server.ts:1286).'
6681
+ description: 'The 200 body of GET /v1/usage/summary — window envelope + totals (server src/http/routes/trace-usage.ts).'
6753
6682
  allOf:
6754
6683
  - $ref: '#/components/schemas/UsageWindowBase'
6755
6684
  - $ref: '#/components/schemas/UsageTotals'
6756
6685
 
6757
6686
  UsageSeries:
6758
6687
  description: >
6759
- The 200 body of GET /v1/usage/series (server http/server.ts:1294). UTC buckets; EMPTY BUCKETS ARE
6688
+ The 200 body of GET /v1/usage/series (server src/http/routes/trace-usage.ts). UTC buckets; EMPTY BUCKETS ARE
6760
6689
  NOT EMITTED — consumers zero-fill as needed.
6761
6690
  allOf:
6762
6691
  - $ref: '#/components/schemas/UsageWindowBase'
@@ -6776,7 +6705,7 @@ components:
6776
6705
 
6777
6706
  UsageBreakdown:
6778
6707
  description: >
6779
- The 200 body of GET /v1/usage/breakdown (server http/server.ts:1302). dimension=model expands the
6708
+ The 200 body of GET /v1/usage/breakdown (server src/http/routes/trace-usage.ts). dimension=model expands the
6780
6709
  per-model echo (one run may contribute to several model buckets; fallback rows land in
6781
6710
  "(unattributed)"); dimension=principal maps a NULL owner to "(anonymous)".
6782
6711
  allOf:
@@ -6798,7 +6727,7 @@ components:
6798
6727
  WorkflowAgentSteerReceipt:
6799
6728
  type: object
6800
6729
  description: >
6801
- The 200 receipt of POST /v1/workflows/{runId}/agents/{label}/steer (server http/server.ts:3752 —
6730
+ The 200 receipt of POST /v1/workflows/{runId}/agents/{label}/steer (server src/http/routes/workflows.ts —
6802
6731
  exact literal: `status:"running"`, `delivery:"applied"`, `marker` = the engine-minted delivery
6803
6732
  marker; NO `note`, unlike the run-subagent verb).
6804
6733
  required: [runId, label]
@@ -6814,7 +6743,7 @@ components:
6814
6743
  type: object
6815
6744
  description: >
6816
6745
  One snapshot row of GET /v1/sessions/{sessionId}/workspace (envelope `{sessionId, snapshots,
6817
- latest?, total}`; server http/server.ts:6109 — newest first, uuidv7 keys). E19 snapshot store's
6746
+ latest?, total}`; server src/http/routes/sessions.ts — newest first, uuidv7 keys). E19 snapshot store's
6818
6747
  read-only projection: each row is the freeze at a turn boundary, NOT a live workspace.
6819
6748
  required: [key, files]
6820
6749
  additionalProperties: true
@@ -6827,7 +6756,7 @@ components:
6827
6756
  type: object
6828
6757
  description: >
6829
6758
  One file entry of GET /v1/sessions/{sessionId}/workspace/{key}/tree (envelope `{sessionId, key,
6830
- entries, total, nextOffset?}`; server http/server.ts:6144 — stable path order, offset paging).
6759
+ entries, total, nextOffset?}`; server src/http/routes/sessions.ts — stable path order, offset paging).
6831
6760
  required: [path, hash]
6832
6761
  additionalProperties: true
6833
6762
  properties: