@sema-agent/sdk 21.0.0 → 22.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.
package/openapi.yaml CHANGED
@@ -7414,11 +7414,12 @@ components:
7414
7414
  `acceptEdits` (in-workspace writes do not ask) or `bypassPermissions` (422 `request.host_posture_refused` on hosted
7415
7415
  deployments) for the old no-ask posture. `auto` arms iff `permissionMode === "auto"` ∧ a classifier seat is mounted ∧
7416
7416
  `caps.autoMode !== false` (one polarity); when the requested mode does not take effect the stream gets `engine_notice`
7417
- `config.permission_mode_unavailable`. `bypassPermissions` RELEASES the ten releasable ask classes (server >= 7.115.0: the tenth is `unstated`, a server-tool call nobody stated)
7417
+ `config.permission_mode_unavailable`. `bypassPermissions` RELEASES the releasable ask classes (nine on every face from server >= 7.127.0; ten on
7418
+ server 7.115.0–7.126.x, where the extra one is `rule_unreadable`; `unstated`, a server-tool call nobody stated, is releasable from server >= 7.115.0)
7418
7419
  and DISCLOSES each (`tool_end.gate.disposition.released` + one `engine_notice` `permission.ask_released_by_mode` per (mode, class) per run);
7419
7420
  immune classes (deployment-authored, ask / org rules, hooks, ancestors, questions …) still ask; a write whose protection
7420
7421
  cannot be judged is refused (`deniedBy: mode`) on the file tools — and, from server >= 7.122.0 / core 7.47.0, RELEASED on the SHELL face
7421
- (an eleventh class, `write_protection_unresolved`, for a caller-supplied tool whose wire name is exactly `Bash` or `Monitor` and which
7422
+ (the class the shell face adds, `target_unresolved` from server >= 7.126.0 — the previous spelling on 7.122.0–7.125.x — for a caller-supplied tool whose wire name is exactly `Bash` or `Monitor` and which
7422
7423
  declares a write-path target; see `ModeRelease.reason`). `plan` (server >= 7.122.0): the engine's plan mode and nothing the service adds —
7423
7424
  the tool table equals `default`'s, the engine mounts the plan-presenting tool, and a write or any non-read-only call is asked AT CALL TIME by the
7424
7425
  engine's plan gate (a card where somebody can answer, a refusal where nobody can; a delegated sub-agent inherits plan as its ceiling); up to
@@ -8008,6 +8009,75 @@ components:
8008
8009
  blocked: '#/components/schemas/TerminalCause_blocked'
8009
8010
  paused: '#/components/schemas/PausedCause'
8010
8011
 
8012
+ ToolOutput:
8013
+ description: >
8014
+ The two shapes of a tool's model-facing body (`Event_tool_end.output`, the turns face `tool-result.output`, the trace stream
8015
+ `tool-result.data.output` — one schema, three faces): a STRING (a string result; over the core text cap it is cut and ends with
8016
+ `…[+N chars truncated]`) or an ARRAY of `ToolOutputBlock` (each block keeps its slot). Handle both. Only the core tool contract
8017
+ is described — a third-party tool that returns content outside it (a body that is neither, a block outside the contract) is
8018
+ the tool's breach, not a third wire shape.
8019
+ oneOf:
8020
+ - type: string
8021
+ - type: array
8022
+ items: { $ref: '#/components/schemas/ToolOutputBlock' }
8023
+
8024
+ ToolOutputBlock:
8025
+ description: >
8026
+ One block of an array-shaped `ToolOutput` (core 7.50.0 `tool_end` output note). Closed, four arms: text; an admitted image /
8027
+ document with its base64 `data`; that same media block's DESCRIPTOR when it did not travel on this face (`{ type, mimeType?,
8028
+ bytes, truncated: true }` — `bytes` = decoded size, a media type over 255 characters is not echoed); and the ONE `omitted`
8029
+ summary core folds the rest of the media into when not even a descriptor fits. Media block vs descriptor share `type` —
8030
+ tell them apart by `data`. Which face sees which (server >= 7.127.0): the LIVE face carries media whole (only a connection
8031
+ backlog over 64 MiB degrades that frame's media to descriptors); the ledger and replay faces (`GET /v1/runs/:id/events`, the
8032
+ turns face, the trace stream) always carry descriptors, with the frame-level `truncated: true`. Render a block with no
8033
+ `data` and `truncated: true` as "not delivered" from its `mimeType` / `bytes`.
8034
+ oneOf:
8035
+ - $ref: '#/components/schemas/ToolOutputTextBlock'
8036
+ - $ref: '#/components/schemas/ToolOutputMediaBlock'
8037
+ - $ref: '#/components/schemas/ToolOutputMediaDescriptor'
8038
+ - $ref: '#/components/schemas/ToolOutputOmittedBlock'
8039
+
8040
+ ToolOutputTextBlock:
8041
+ type: object
8042
+ description: 'The text arm of `ToolOutputBlock` (core `TextContent`).'
8043
+ additionalProperties: false
8044
+ required: [type, text]
8045
+ properties:
8046
+ type: { const: text }
8047
+ text: { type: string }
8048
+
8049
+ ToolOutputMediaBlock:
8050
+ type: object
8051
+ description: 'The media arm of `ToolOutputBlock` (core `ImageContent` / `DocumentContent`) — on the LIVE face only; the ledger / replay faces carry `ToolOutputMediaDescriptor` instead.'
8052
+ additionalProperties: false
8053
+ required: [type, data, mimeType]
8054
+ properties:
8055
+ type: { type: string, enum: [image, document] }
8056
+ data: { type: string, description: 'base64 bytes (not text-redacted: it is an encoding of bytes).' }
8057
+ mimeType: { type: string }
8058
+
8059
+ ToolOutputMediaDescriptor:
8060
+ type: object
8061
+ description: 'The descriptor arm of `ToolOutputBlock`: the same media block did not travel on this face (core budget degrade / the server''s ledger face / a backlogged live connection).'
8062
+ additionalProperties: false
8063
+ required: [type, bytes, truncated]
8064
+ properties:
8065
+ type: { type: string, enum: [image, document] }
8066
+ mimeType: { type: string, description: 'Echoed when it is at most 255 characters.' }
8067
+ bytes: { type: integer, minimum: 0, description: 'Decoded byte size of the media that did not travel.' }
8068
+ truncated: { const: true }
8069
+
8070
+ ToolOutputOmittedBlock:
8071
+ type: object
8072
+ description: 'The summary arm of `ToolOutputBlock` (core 7.50.0): when not even a descriptor fits, this media block and every later one fold into this ONE block.'
8073
+ additionalProperties: false
8074
+ required: [type, blocks, bytes, truncated]
8075
+ properties:
8076
+ type: { const: omitted }
8077
+ blocks: { type: integer, minimum: 1 }
8078
+ bytes: { type: integer, minimum: 0 }
8079
+ truncated: { const: true }
8080
+
8011
8081
  TerminalCause_completed:
8012
8082
  type: object
8013
8083
  additionalProperties: false
@@ -8015,6 +8085,24 @@ components:
8015
8085
  required: [kind]
8016
8086
  properties:
8017
8087
  kind: { const: completed }
8088
+ detail:
8089
+ allOf: [{ $ref: '#/components/schemas/TerminalCompletedDetail' }]
8090
+ description: >
8091
+ server >= 7.126.0 (core 7.49.0 `TerminalCompletedDetail`, forwarded verbatim): a machine-readable account BESIDE a completion, for the one
8092
+ shape that completes yet may be short. PRESENT only when the final assistant message carried the provider's unknown stream-end word and
8093
+ the run completed on that turn; every other completion leaves it absent.
8094
+
8095
+ TerminalCompletedDetail:
8096
+ type: object
8097
+ additionalProperties: false
8098
+ description: >
8099
+ The account a `completed` cause may carry (server >= 7.126.0; core 7.49.0 `dist/core/terminal-cause.d.ts`, key-for-key). `kind` is CLOSED with one
8100
+ member: `finish_reason_unknown` — the final turn's provider ended it with a stream-end word the engine does not read; the turn was kept as
8101
+ the model left it and the run announced it (`route.finish_reason_unknown`). Read it as "completed, but the last answer may be cut", never as a failure.
8102
+ required: [kind, finishReasonUnknown]
8103
+ properties:
8104
+ kind: { const: finish_reason_unknown }
8105
+ finishReasonUnknown: { type: string, description: 'The provider''s stream-end word in the provider echo shape (bytes outside it become `?`); not an engine word.' }
8018
8106
 
8019
8107
  TerminalCause_failed:
8020
8108
  type: object
@@ -9113,6 +9201,9 @@ components:
9113
9201
  properties:
9114
9202
  type: { type: string, description: 'thinking | content | tool-call | tool-result | (open)' }
9115
9203
  text: { type: string }
9204
+ output:
9205
+ allOf: [{ $ref: '#/components/schemas/ToolOutput' }]
9206
+ description: 'tool-result — the model-facing body, the SAME two shapes as `Event_tool_end.output` (one block schema, three faces). This is a ledger face: a media block is always its descriptor here (server >= 7.127.0).'
9116
9207
  id: { type: string, description: tool-call — matches approvals toolCallId. }
9117
9208
  name: { type: string }
9118
9209
  input: { description: tool-call — redacted args. }
@@ -12703,6 +12794,12 @@ components:
12703
12794
  (where only the `error` frame carried it). Equal to the SSE `event:` line verbatim — its reason
12704
12795
  to exist is the proxy/relay case that strips the `event:` line and forwards only the data JSON,
12705
12796
  where this is the only key left to dispatch on. Heartbeats (`data: {}`) carry none.
12797
+ output:
12798
+ allOf: [{ $ref: '#/components/schemas/ToolOutput' }]
12799
+ description: >
12800
+ `tool-result` frames only (no other known event carries this key; the data object stays open for the rest): the model-facing
12801
+ body in the SAME two shapes as `Event_tool_end.output` and the turns face (one block schema, three faces). A ledger face — a
12802
+ media block is always its descriptor here (server >= 7.127.0).
12706
12803
 
12707
12804
  PendingList:
12708
12805
  type: object
@@ -12713,15 +12810,55 @@ components:
12713
12810
  # 结构性不可见)。ADDITIVE / tolerate-absent:键缺席=「协调器未装配(本部署无 live 审批面)」或
12714
12811
  # 旧 server;空数组=「有面、此刻无待批」——两义可判别,消费端测 presence。**分数组不混编**:
12715
12812
  # live 行的决议口=POST /v1/tool-approvals/{approvalId}/respond,durable 行=decide 口;数组名即路由判据。
12813
+ # 22.0.0:第三、四顶层键此前漏声明 —— 封闭 schema 上一个真键 = 合法信封被严格校验器拒收。
12716
12814
  additionalProperties: false
12717
12815
  required: [pending]
12718
12816
  properties:
12719
12817
  pending:
12720
12818
  type: array
12721
12819
  items: { $ref: '#/components/schemas/PendingCheckpoint' }
12820
+ serverNowMs:
12821
+ type: integer
12822
+ description: >
12823
+ server >= 7.57.0 (always present from that version): the server's clock at the moment THIS response was minted. Render a countdown as
12824
+ `deadline − serverNowMs`, never against the local clock (a terminal with clock skew would show a card as alive that already expired).
12825
+ Not repeated per row — one response has one "now".
12722
12826
  livePending:
12723
12827
  type: array
12724
12828
  items: { $ref: '#/components/schemas/LivePendingRow' }
12829
+ crashConverged:
12830
+ type: array
12831
+ items: { $ref: '#/components/schemas/CrashConvergedRow' }
12832
+ description: >
12833
+ server >= 7.55.0: approval asks the previous process left pending, converged at boot to NOT DECIDABLE (audit rows, not queue rows — no
12834
+ decide route, no run revival). Present iff the local-lane ask audit store is wired; `[]` = the face exists and nothing was converged;
12835
+ absent = no such face on this deployment (or an older server).
12836
+
12837
+ CrashConvergedRow:
12838
+ type: object
12839
+ description: >
12840
+ One `GET /v1/approvals` `crashConverged[]` row (server >= 7.55.0; server `src/approval-ask-audit-store.ts` `CrashConvergedRow`, key-for-key):
12841
+ an ask whose carrying leg died, converged at boot so it can no longer be decided. Args / card body are NOT listed (same rule as
12842
+ `livePending` rows). Open like the other response row projections (a strict consumer must not reject a row for a key added later).
12843
+ additionalProperties: true
12844
+ required: [approvalId, toolName, taskId, ts, expiresAtMs, decision, cause, orphanState, convergedAtMs, resumeSafe]
12845
+ properties:
12846
+ approvalId: { type: string }
12847
+ toolName: { type: string }
12848
+ taskId: { type: string }
12849
+ sessionId: { type: string }
12850
+ ts: { type: number, description: 'Mint time (ms epoch; named like `livePending[].ts`).' }
12851
+ expiresAtMs: { type: number }
12852
+ decision: { const: denied, description: 'Discriminating constant: the card can no longer be decided.' }
12853
+ cause:
12854
+ type: string
12855
+ enum: [crashed_before_park, shutdown_before_park]
12856
+ description: '`crashed_before_park` = the process crashed; `shutdown_before_park` (server >= 7.108.0) = an orderly shutdown cut the leg. The SAME word as the decide door''s 410 `gone.ask` body `cause`.'
12857
+ orphanState: { type: string, enum: [pending, decided], description: '`pending` = the tool provably never ran; `decided` = a person had answered, a partial side effect is possible.' }
12858
+ originalDecision: { const: approve, description: 'decided arm only: the person had approved.' }
12859
+ decidedAtMs: { type: number }
12860
+ convergedAtMs: { type: number }
12861
+ resumeSafe: { type: boolean, description: 'pending arm = a re-run (the engine''s resume compensation leg) is safe and a shell may resume by default; decided arm = leave it to a person.' }
12725
12862
 
12726
12863
  LivePendingRow:
12727
12864
  type: object
@@ -14618,6 +14755,7 @@ components:
14618
14755
  - $ref: '#/components/schemas/Event_compacted'
14619
14756
  - $ref: '#/components/schemas/Event_suggestions'
14620
14757
  - $ref: '#/components/schemas/Event_status'
14758
+ - $ref: '#/components/schemas/Event_task_started'
14621
14759
  - $ref: '#/components/schemas/Event_task_progress'
14622
14760
  - $ref: '#/components/schemas/Event_workspace_changed'
14623
14761
  - $ref: '#/components/schemas/Event_engine_notice'
@@ -14693,6 +14831,7 @@ components:
14693
14831
  compacted: '#/components/schemas/Event_compacted'
14694
14832
  suggestions: '#/components/schemas/Event_suggestions'
14695
14833
  status: '#/components/schemas/Event_status'
14834
+ task_started: '#/components/schemas/Event_task_started'
14696
14835
  task_progress: '#/components/schemas/Event_task_progress'
14697
14836
  workspace_changed: '#/components/schemas/Event_workspace_changed'
14698
14837
  engine_notice: '#/components/schemas/Event_engine_notice'
@@ -15143,42 +15282,55 @@ components:
15143
15282
  `UNATTENDED_PERMISSION_MODE=dontAsk`).
15144
15283
  AskClass:
15145
15284
  type: string
15146
- enum: [content_question, hook, ancestor, dangerous_delete, unverifiable_delete, transcript_write, org_rule, governance_unavailable, rule_unreadable, ask_rule, denial_limit_fallback, classifier_no_ruling, requires_user_interaction, operator_forced, shell_floor, write_protection_unresolved, probe, write_protection, tool_marks_mcp, tool_marks_a2a, policy_rra, artifact_shared_read, mode, unstated, ordinary]
15285
+ enum: [content_question, hook, ancestor, dangerous_delete, unverifiable_delete, unverifiable_shell_text, transcript_write, org_rule, governance_unavailable, rule_unreadable, ask_rule, denial_limit_fallback, classifier_no_ruling, requires_user_interaction, operator_forced, shell_floor, target_unresolved, probe, write_protection, tool_marks_mcp, tool_marks_a2a, policy_rra, artifact_shared_read, mode, unstated, ordinary]
15147
15286
  description: >
15148
- core `ASK_CLASSES` (twenty-two words as of core 7.40.0, twenty-three as of core 7.41.0, twenty-four as of core 7.43.0, twenty-five as of core 7.45.0 — 7.34.0 minted twenty; `shell_floor` joined in 7.39.0 #1260 and rides
15287
+ core `ASK_CLASSES` (twenty-two words as of core 7.40.0, twenty-three as of core 7.41.0, twenty-four as of core 7.43.0, twenty-five as of core 7.45.0, twenty-six as of core 7.49.0 — 7.34.0 minted twenty; `unverifiable_shell_text` joined in 7.49.0 #1505 and rides server >= 7.126.0, where the
15288
+ unresolved-write-target class was also RENAMED to `target_unresolved` (#955; zero alias — the previous spelling is in the SDK README's 22.0.0 migration table); `shell_floor` joined in 7.39.0 #1260 and rides
15149
15289
  server >= 7.113.0; `unstated` joined in 7.40.0 and rides server >= 7.115.0; `requires_user_interaction` joined in 7.41.0 and rides
15150
15290
  server >= 7.116.0; `classifier_no_ruling` joined in 7.43.0 #1353 and rides server >= 7.118.0; `dangerous_delete` joined in 7.45.0 and rides
15151
15291
  server >= 7.119.0) — which CLASS an ask falls in (the columns of the mode × class arbitration table).
15152
15292
  `dangerous_delete` = a DELETE OF A PROTECTED PLACE: an `rm` / `rmdir` whose target is the filesystem root, a top-level directory, the home
15153
15293
  directory, the task root / working directory / an added working directory or an ancestor of one (including `rm -rf *` at the task root and
15154
- `rm -rf ~/*`), or a shell handed a script that is only assembled at run time (`bash -c "$CMD"`, `eval "$(…)"`). ONLY A PERSON'S ANSWER clears
15294
+ `rm -rf ~/*`); on server 7.119.0–7.125.x it also covered a shell handed a script that is only assembled at run time, which is
15295
+ `unverifiable_shell_text` from server >= 7.126.0. ONLY A PERSON'S ANSWER clears
15155
15296
  it: no mode (`bypassPermissions` included), no allow (request `settings.permissions.allow`, operator `APPROVAL_GRANT`, a stored allow row, a
15156
15297
  skill's tool list, a hook's allow) and no `auto` classifier does; the frame carries `requiresRealApproval: true`, nobody answering means the
15157
- call does not run (the unattended leg refuses), and it is bypass-IMMUNE (not one of the ten releasable classes).
15298
+ call does not run (the unattended leg refuses), and it is bypass-IMMUNE (not a releasable class).
15299
+ `unverifiable_shell_text` (core 7.49.0 #1505, server >= 7.126.0) = the engine CANNOT READ the text this shell will execute — the shell is fed
15300
+ text the command does not spell (a program's output, a substitution, a file's content, an argv a stream fills in: `bash -c "$CMD"`,
15301
+ `eval "$(…)"`, `xargs sh -c …`; shell text that does not parse or is nested too deep lands here too). Its arbitration row is
15302
+ `unverifiable_delete`'s save the classifier column: bypass-IMMUNE, no allow rule clears it, the `auto` classifier is not asked, `dontAsk`
15303
+ refuses; only a person's answer clears it. The card carries no `mandate` word.
15304
+ `target_unresolved` (core 7.49.0 #955, server >= 7.126.0; the previous spelling was used on 7.122.0–7.125.x) = WHERE A WRITE LANDS COULD NOT BE
15305
+ DETERMINED (a link on the way could not be examined, or the environment could not resolve the target), so whether it lands on a guarded path
15306
+ (the write-protection table, the sensitive-path list) is unknown. Refused on the file tools; on the SHELL face `bypassPermissions` releases it and
15307
+ names it in `ModeRelease.reason`. The same word is a `PersistedRuleMandate` member.
15158
15308
  `classifier_no_ruling` = the auto-mode classifier did not rule (it could not run — `error` / `timeout` — or replied with no verdict —
15159
15309
  `parse_error`), so a person decides: the denial-limit fallback's row (bypass-immune, no allow rule clears it, the classifier is not asked
15160
15310
  again); the live frame and the inbox row also carry the cause as `classifierNoRuling`.
15161
15311
  `requires_user_interaction` = the MCP server declared, in the tool's advertisement, `_meta["anthropic/requiresUserInteraction"] === true`
15162
- (only the boolean `true`): EVERY call of that tool asks the human, in EVERY mode including `bypassPermissions` (it is not one of the ten
15163
- RELEASABLE classes), and only the human's answer clears it — `settings.permissions.allow`, operator `APPROVAL_GRANT`, a skill's tool list +
15312
+ (only the boolean `true`): EVERY call of that tool asks the human, in EVERY mode including `bypassPermissions` (it is not a
15313
+ RELEASABLE class), and only the human's answer clears it — `settings.permissions.allow`, operator `APPROVAL_GRANT`, a skill's tool list +
15164
15314
  `userInvokedSkills` and a hook's explicit allow all fail to; with no approval seat the call is refused (the server sees nothing). The frame
15165
15315
  also carries `requiresRealApproval: true` / `mandated: true` (`origin: "safety_tighten"`). A client that renders cards by exhaustive `askClass`
15166
15316
  adds this one word.
15167
15317
  `unstated` = NOBODY STATED IT: in an ask-class mode (`default` / `acceptEdits` / `auto` / `plan`) a call to an MCP server tool or A2A skill
15168
15318
  (a seat that states no permission of its own) reached the end of the fold with no layer — rule / hook / approver / classifier / mode
15169
15319
  release — having said "this time is fine"; the engine raises a card with `askClass: "unstated"` (sentence `The agent requested permission to use <tool>,
15170
- but it has not been granted yet.`), and with no approval surface the call is refused. It is clearable (one of the ten RELEASABLE
15171
- classes: an allow rule — `settings.permissions.allow` / operator `APPROVAL_GRANT` — an explicit hook `permissionDecision: "allow"`, the auto-mode
15320
+ but it has not been granted yet.`), and with no approval surface the call is refused. It is clearable (a RELEASABLE
15321
+ class: an allow rule — `settings.permissions.allow` / operator `APPROVAL_GRANT` — an explicit hook `permissionDecision: "allow"`, the auto-mode
15172
15322
  classifier or `bypassPermissions` clears it); under `plan` only READ-ONLY server tools raise it.
15173
15323
  `shell_floor` = the operator's `shellGate: "always"` floor on a shell-running seat (the question the `operator_always` mandate
15174
15324
  word discloses), a class of its own so a set that holds another forced question still holds it; like `operator_forced` it is
15175
15325
  bypass-IMMUNE (not releasable).
15176
- CLOSED on the gate record (screened with core `isAskClass`). `bypassPermissions` releases only the ten RELEASABLE classes
15177
- (`transcript_write` / `rule_unreadable` / `probe` / `write_protection` / `tool_marks_mcp` / `tool_marks_a2a` /
15178
- `artifact_shared_read` / `mode` / `unstated` / `ordinary`) — on every face — plus, from server >= 7.122.0 / core 7.47.0, an eleventh on the SHELL
15179
- face only: `write_protection_unresolved` (core `releasableAskClassesFor(face)`: shell 11, other faces 10; on the file tools that class is
15180
- refused, `deniedBy: mode`); every other class (deployment-authored `operator_forced`, ask / org rules, hook,
15181
- ancestor, content question, …) asks under every mode.
15326
+ CLOSED on the gate record (screened with core `isAskClass`). `bypassPermissions` releases only the RELEASABLE classes (core
15327
+ `releasableAskClassesFor(face)`). Server >= 7.127.0 (core 7.50.0): nine on every face (`transcript_write` / `probe` / `write_protection` /
15328
+ `tool_marks_mcp` / `tool_marks_a2a` / `artifact_shared_read` / `mode` / `unstated` / `ordinary`) plus a tenth on the SHELL face only,
15329
+ `target_unresolved` (shell 10, other faces 9; on the file tools that class is refused, `deniedBy: mode`); `rule_unreadable` is no longer released
15330
+ by any mode (bypass asks too, and the run gets one `permission.rule_store_unavailable` notice). Server 7.122.0–7.126.x (core 7.47.0–7.49.x) also
15331
+ released `rule_unreadable` on every face: ten RELEASABLE classes plus an eleventh on the SHELL face (shell 11, other faces 10). Up to 7.121.x the
15332
+ `RELEASABLE_ASK_CLASSES` constant (deleted in core 7.47.0) held ten, face-blind. Every other class (deployment-authored `operator_forced`, ask / org
15333
+ rules, hook, ancestor, content question, `unverifiable_shell_text`, …) asks under every mode.
15182
15334
  ModeRelease:
15183
15335
  type: object
15184
15336
  additionalProperties: false
@@ -15194,24 +15346,26 @@ components:
15194
15346
  classes: { type: array, items: { $ref: '#/components/schemas/AskClass' } }
15195
15347
  origin:
15196
15348
  type: string
15197
- enum: [content_question, ancestor_marked, org_unavailable, org_rule, rule_store_unavailable, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
15349
+ enum: [content_question, plan_review, ancestor_marked, org_unavailable, org_rule, rule_store_unavailable, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
15198
15350
  description: 'The origin word the card would have shown (core `ASK_ORIGINS`; screened closed on this face, same list as `GateOutcome.origin`).'
15199
15351
  mandate: { $ref: '#/components/schemas/PersistedRuleMandate' }
15200
15352
  reason:
15201
15353
  type: string
15202
- enum: [rule_unreadable, write_protection_unresolved]
15354
+ enum: [target_unresolved]
15203
15355
  description: >
15204
15356
  WHAT the release went over — one word: the FIRST member (in core `MODE_RELEASE_REASONS` array order) that the ask's class
15205
- set holds; ABSENT when the set holds none. CLOSED set — the server screens it with core `isModeReleaseReason`, so a word
15206
- outside it withholds the whole `gate` from the frame (and a consumer that dispatches on the word must learn each new one).
15207
- `rule_unreadable` = the release went over a rule this call could not be read against (the rule store was unreadable — a
15208
- security-axis fail-open direction the server discloses on its own).
15209
- `write_protection_unresolved` (server >= 7.122.0 / core 7.47.0) = the release went over a write whose target the
15210
- write-protection judge could not RESOLVE (whether it lands on the protected table is unknown). It is released on the SHELL
15357
+ set holds; ABSENT when the set holds none. CLOSED set of ONE word — the server screens it with core `isModeReleaseReason`, so a word
15358
+ outside it withholds the whole `gate` from the frame.
15359
+ `target_unresolved` = the release went over a write whose landing place could not be determined (a link on the way could not be examined,
15360
+ or the environment could not resolve the target), so whether it lands on a guarded path is unknown. It is released on the SHELL
15211
15361
  face only: a caller-supplied tool whose wire name is exactly `Bash` or `Monitor` and which declares a write-path target,
15212
15362
  under `bypassPermissions`; on the file tools the same unresolved write is still refused (`deniedBy: mode`). The engine's
15213
15363
  own `Bash` / `Monitor` cannot mint this class and the server mounts no such tool — it comes from a caller-embedded tool of
15214
- those names. Before server 7.122.0 / core 7.47.0 the set was `rule_unreadable` alone.
15364
+ those names.
15365
+ History (this SDK's type and this enum hold the one word from 22.0.0; a word an older server sends reads as OUT OF SET and is not rewritten):
15366
+ server 7.122.0–7.125.x (core 7.47.0–7.48.x) spelled this member differently (the SDK README's 22.0.0 migration table); server <= 7.126.x also
15367
+ had `rule_unreadable` (the release went over a rule this call could not be read against) — core 7.50.0 / server >= 7.127.0 releases an
15368
+ unreadable rule under no mode, so that member left (`rule_unreadable` stays an `AskClass`). Before server 7.122.0 the set was `rule_unreadable` alone.
15215
15369
 
15216
15370
  GateClassifierAttribution:
15217
15371
  # sdk 9.5.0:具名 —— 同一份形挂在 `GateDisposition` 的两只臂上,内联会立刻是两份会各自漂的镜像。
@@ -15296,7 +15450,7 @@ components:
15296
15450
  # 服务对缺陷记录是整条不上帧 ⇒ 词表外的值在这条 wire 上到不了消费端。审批帧那一面不判成员,
15297
15451
  # 所以 `AskOrigin` 本体保持真开(见该 schema 的长注)。这张 enum 是本 spec 里该词表的**唯一**
15298
15452
  # 执法点;core 加词时改这一处。
15299
- - enum: [content_question, ancestor_marked, org_unavailable, org_rule, rule_store_unavailable, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
15453
+ - enum: [content_question, plan_review, ancestor_marked, org_unavailable, org_rule, rule_store_unavailable, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
15300
15454
  description: >
15301
15455
  WHO ASKED. Same-present/same-absent as `settlement` (I1). CLOSED here (and only here) — see the
15302
15456
  enum note above.
@@ -15389,10 +15543,13 @@ components:
15389
15543
  Event_tool_end:
15390
15544
  type: object
15391
15545
  description: >
15392
- design/99 §E1 (SHIPPED) — `output` is the model-facing action-card BODY: NON-UNIFORM (a string, or a
15393
- (TextContent|ImageContent)[] block array) and degrades to a single TRUNCATED string over the core size cap
15394
- (`truncated: true`). Absent ⇒ the tool produced no body. 🔴 UNTRUSTED RAW + observability-only: the service
15395
- has redactDeep'd + size-bounded it; a consumer MAY further bound, MUST never re-feed it to a model.
15546
+ design/99 §E1 (SHIPPED) — `output` is the model-facing action-card BODY in TWO shapes (`ToolOutput`: a string, or a
15547
+ `ToolOutputBlock` array — handle both). A string over the core text cap is cut and ends with the marker; in a block array
15548
+ the text stream is cut in place and image / document blocks ride whole on the LIVE face (core 7.50.0 / server >= 7.127.0;
15549
+ a connection backlog over 64 MiB degrades that frame's media to descriptors), while the ledger and replay faces always
15550
+ carry descriptors. `truncated: true` ⇔ the body is not the tool's content as returned. Absent ⇒ the tool produced no body.
15551
+ 🔴 UNTRUSTED RAW + observability-only: the service has redacted the text + size-bounded it (media `data` is bytes and rides
15552
+ verbatim); a consumer MAY further bound, MUST never re-feed it to a model.
15396
15553
  allOf:
15397
15554
  - { $ref: '#/components/schemas/EventIdentity' }
15398
15555
  # 🔴 现役写口与退役四词**互斥**(S-170 codex r2 [medium] 验真后补):退役四词只出现在 <=7.63.0 写下的
@@ -15429,9 +15586,9 @@ components:
15429
15586
  a retired name the roster still answers to). Present ONLY on a refused call (`gate.disposition.kind === "denied"`), and absent when the station that refused it did not know the roster name; per-tool refusal accounting reads this, not `toolName`.
15430
15587
  structured: {} # core 1.203 CC 卡片明细;与 output 同一 UNTRUSTED RAW 待遇(已 redactDeep),形状开放
15431
15588
  isError: { type: boolean }
15432
- output: {} # NON-UNIFORM: string | (TextContent|ImageContent)[] | (truncated) string. Absent ⇒ no body.
15433
- truncated: { type: boolean }
15434
- totalChars: { type: integer, description: 'core >=1.442 (RB-210): honest ORIGINAL size when truncated — sum of each block''s true size (text=chars, image/document=base64 bytes), no JSON-wrapping overhead. Absent on older cores / untruncated results.' } # true ⇒ output was size-bounded to a truncated string.
15589
+ output: { $ref: '#/components/schemas/ToolOutput' } # 22.0.0: two shapes, one block schema shared with the trace faces
15590
+ truncated: { type: boolean, description: 'true exactly when `output` is not the content the tool returned (text cut, a media block replaced by its descriptor or folded into the `omitted` summary — by core, or by the server on the ledger / replay faces and on a backlogged live connection).' }
15591
+ totalChars: { type: integer, description: 'core >=1.442 (RB-210): honest ORIGINAL size when truncated — sum of each block''s true size (text=chars, image/document=base64 length, whether the block rode or was replaced by its descriptor), no JSON-wrapping overhead. PRESENT ⇒ `truncated`; the converse does not hold (core omits it when the content could not be read). When server >= 7.127.0 replaces media by descriptors (ledger / replay faces, a backlogged live connection) it sets `truncated` AND this key (core''s value kept as is, otherwise the per-block true sizes summed). Absent on older cores / untruncated results / unreadable content — never read it as 0.' } # true ⇒ output was size-bounded to a truncated string.
15435
15592
  # 🔴 BREAKING (server >=7.64.0, core 7.6.0 S6-A): `settledBy` / `resolution` / `autoDenied` / `approver`
15436
15593
  # are RETIRED and replaced by the ONE `gate` record below. NO 7.64.0+ writer mints them, and the TS type
15437
15594
  # does NOT carry them — nobody should code against a dead vocabulary.
@@ -15650,6 +15807,46 @@ components:
15650
15807
  errClass: { type: string, description: "connect_refused | transport | rate_limit | server | http | output_cap — retry-wait frames ONLY; never inferred from phase" }
15651
15808
  providerCondition: { type: string, description: "server >= 7.126.0 (core 7.49.0 #1454, passed through verbatim): what the provider said about the account / capacity — core's closed `PROVIDER_CONDITIONS`; a retry frame carries only the three retryable words `throttled | overloaded | unknown` (`quota_exhausted` / `stop_other` do not retry and ride the terminal `detail.providerCondition`). Presence law as `errorStatus`; read as an OPEN set (keep a default arm). ABSENT = not judged, read the same as `unknown` (back off, do not assert quota). Moves with `providerConditionSource`." }
15652
15809
  providerConditionSource: { type: string, description: "server >= 7.126.0 (core 7.49.0 #1454): the evidence the `providerCondition` verdict rests on — `unified_header | provider_code | status`; present exactly when `providerCondition` is; read as an OPEN set." }
15810
+ retryAtMs: { type: number, description: "server >= 7.52.0 (core 7.0.0): the WALL-CLOCK end of the wait = `Date.now() + retryInMs` at emit, on the emitting process's clock (not monotonic — never compare it with a local monotonic timer). `retryInMs` stays the authoritative RELATIVE amount; this is the producer's absolute note (a reader several hops away recomputing it would reset the countdown on every replay). Moves with `retryInMs`; absent ⇒ not minted." }
15811
+ errorStatus: { type: integer, description: "server >= 7.54.0 (core 7.1.0): the HTTP status of the attempt that just failed, present ONLY when that status names the failure (absent on a transport non-answer, a mid-stream tear, a local circuit-open verdict and the `recovered` / `gave_up` frames). Absent = no status named the failure — not 0; a 2xx never appears." }
15812
+ elapsedMs: { type: number, description: "server >= 7.58.0 (core 7.3.1): ONLY on the `waiting_first_token` phase — how long the current segment has waited so far (at emit, emitting process's clock). Absent = unknown, not 0. A waiting frame never carries `retryInMs` / `retryAtMs` (it OBSERVES a wait, it does not ANNOUNCE one) — do not merge the two families into one countdown." }
15813
+ timeoutMs: { type: number, description: "server >= 7.58.0 (core 7.3.1): present with `elapsedMs` on the same phase — the bound of the segment being waited on (core 7.33.0+: the first-byte window before the response head, the first-token watchdog after it; each segment counts from 0)." }
15814
+ eventId: { type: string }
15815
+ parentToolCallId: { type: string }
15816
+ sourceTaskId: { type: string }
15817
+ bgAgentId: { type: string }
15818
+ Event_task_started:
15819
+ type: object
15820
+ description: >
15821
+ server >= 7.127.0 (core 7.50.0 `task_started`; server projection `taskStartedEventData`, an explicit per-key whitelist) — a
15822
+ delegated child STARTED: one frame per cycle (first spawn / revival; a durable continuation leg mints none), after the child's
15823
+ `wiring_manifest` and before its first `task_progress` and first model request, so a consumer opens the child row at start.
15824
+ Every member is a value `task_progress` already carries with the same meaning. 🔴 LIVE AND LEDGERED, like `task_progress`: it rides
15825
+ the same door (sync stream main leg, forward lane, the child tail stream) AND is persisted, so the async lane's ledger tail and the
15826
+ `GET /v1/runs/:id/events` replay carry it (before the child's first `task_progress`). Core's "never persisted, never replayed on
15827
+ resume" binds the ENGINE (session tree, checkpoints, resume replay); the server ledgers it because `agentType` / `rootSessionId` /
15828
+ `parentSessionId` / `startedAt` ride only this frame. `name` / `workflowAgentLabel` are UNTRUSTED display text, redacted by the server; `spawnName`
15829
+ is a validated identity key, verbatim. Absent optional keys stay absent (`taskType` absent = a foreground child; `seq`
15830
+ absent = no `a*` row, never cycle 1). Servers <= 7.126.x never send it.
15831
+ allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
15832
+ additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注(builder=taskStartedEventData)
15833
+ required: [type, taskId, sessionId, model]
15834
+ properties:
15835
+ type: { const: task_started }
15836
+ taskId: { type: string, description: 'The child RUN id (`spec.taskId ?? sessionId`) — the key its `task_progress` frames carry.' }
15837
+ sessionId: { type: string, description: 'The child run''s session id.' }
15838
+ taskType: { type: string, description: 'As `task_progress.taskType`: absent for a foreground (synchronous) child. Open on read.' }
15839
+ seq: { type: integer, description: 'As `task_progress.seq`: the registry row''s cycle generation; absent when there is no `a*` row.' }
15840
+ workflowRunId: { type: string }
15841
+ workflowAgentLabel: { type: string, description: 'UNTRUSTED display text (redacted).' }
15842
+ parentTaskId: { type: string }
15843
+ parentSessionId: { type: string }
15844
+ rootSessionId: { type: string }
15845
+ name: { type: string, description: 'The child''s display label (the same value as `task_progress.name`) — UNTRUSTED, redacted.' }
15846
+ spawnName: { type: string, description: 'The explicit `Agent({name})` spawn identity, verbatim; present when the spawn carried one.' }
15847
+ agentType: { type: string, description: 'The resolved subagent type (absent on a workflow-lane agent).' }
15848
+ model: { type: string, description: 'The model the child leg was PREPARED with.' }
15849
+ startedAt: { type: number, description: 'Epoch ms at the mint (sent only when finite).' }
15653
15850
  eventId: { type: string }
15654
15851
  parentToolCallId: { type: string }
15655
15852
  sourceTaskId: { type: string }
@@ -15730,7 +15927,9 @@ components:
15730
15927
  `message_committed` + stream order). Live emissions PRECEDE the commit and omit `entryId`.
15731
15928
  SERVICE PROJECTION: core's `principal` is deliberately NOT forwarded (the stream is already owner-scoped —
15732
15929
  the frame does not restate the tenant). `issuer` / `actor.id` / `actor.issuer` are host-derived identity
15733
- strings and arrive SECRET-REDACTED.
15930
+ strings and arrive SECRET-REDACTED. Server >= 7.127.0 does NOT project core 7.50.0's `attachments` member (always absent here)
15931
+ and does not accept the engine's request-layer `userAttachments` key: a submit / resume body carrying it is 400
15932
+ `request.body_shape` (named in `unknownKeys`).
15734
15933
  allOf: [{ $ref: '#/components/schemas/EventIdentity' }]
15735
15934
  additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注
15736
15935
  required: [type, inputId]
@@ -17458,7 +17657,7 @@ components:
17458
17657
  # 当天,一个**合法**的审批卡就会被严格消费端拒收。`x-open-enum` 只是意图标记,不解除 enum 的执法 ——
17459
17658
  # 这正是本车刚从 `CheckpointGate` 拆掉的那个假开集,不在这里换个地方重犯。
17460
17659
  # 闭集**执法**只属于**筛过的**那一面(`GateOutcome.origin`:引擎的 `screenGateOutcome` 判成员,
17461
- # 出集即整条不上帧),所以那张 enum 落在**那个引用点**,恰一处。已知十一词见下面的描述。
17660
+ # 出集即整条不上帧),所以那张 enum 落在**那个引用点**,恰一处。已知十二词(core 7.49.0 +plan_review)见下面的描述。
17462
17661
  description: >
17463
17662
  WHO raised an ask (`ToolApprovalFrame.origin`; server >= 7.57.0 / core 7.5.0, S-125③/#564) — core's
17464
17663
  `ASK_ORIGINS`, ENGINE-STAMPED at the gate (core's words: "engine-stamped at the gate, never a policy's
@@ -17485,13 +17684,19 @@ components:
17485
17684
  fails closed to a person. It is the personal-store sibling of `org_unavailable` (a governance source that
17486
17685
  cannot be read means ASK, never a silent allow).
17487
17686
 
17687
+ 🔴 core 7.49.0 ADDS A TWELFTH WORD (server >= 7.126.0), second in authority order: `plan_review` = a durable PLAN pause — the
17688
+ model's own request (the first-party plan tool) stopped the run for a human verdict on a plan. Same family as
17689
+ `content_question` (a content-routing ask, never a permission question: no permission decider, classifier or mode answers it
17690
+ and it never reaches an approver as an `AskRequest`); only the plan pause's decide lane stamps it, so the decided row's record
17691
+ names the ask it settled.
17692
+
17488
17693
  The SAME type is the `origin` member of `GateOutcome` on `tool_end` — one vocabulary, two faces.
17489
17694
 
17490
17695
  server >= 7.102.0 (S-755 / cli L-695 / C-R111): the word now also rides the `livePending` row top level
17491
17696
  (read once with the frame's) and the operator queue row (`GET /v1/approvals` `pending[]` + the `/stream`
17492
17697
  `pending` frame — the park-row twin seat, screened by core's `isAskOrigin`), besides the frame and the inbox
17493
17698
  row — five faces, one word. `card_json` / the `approval_request` frame still do not carry it (the card is
17494
- `.strict()`). The eleven known words are exported at runtime as the SDK's `ASK_ORIGINS` (core 7.32.1
17699
+ `.strict()`). The known words (twelve from core 7.49.0) are exported at runtime as the SDK's `ASK_ORIGINS` (core 7.32.1
17495
17700
  `ASK_ORIGINS`, verbatim and in order) — known words, NOT an enforcement table.
17496
17701
 
17497
17702
  AllowRuleMember:
@@ -17544,11 +17749,12 @@ components:
17544
17749
 
17545
17750
  PersistedRuleMandate:
17546
17751
  type: string
17547
- enum: [operator_always, tool_marks, probe_mandate, probe_unanswered, write_protection, write_protection_unresolved]
17752
+ enum: [operator_always, tool_marks, probe_mandate, probe_unanswered, write_protection, target_unresolved]
17548
17753
  description: >
17549
17754
  WHICH WORD a mandated ask stands on (server >= 7.102.0 / S-721 / core 7.32.0 #1092) — core's
17550
17755
  `PERSISTED_RULE_MANDATES` six words, transcribed verbatim and in order (core 7.32.1
17551
- `dist/core/ask-origin.d.ts:349`; the vocabulary's owner is core). Rides FOUR faces with one value: the
17756
+ `dist/core/ask-origin.d.ts:349`; the vocabulary's owner is core; the sixth word is `target_unresolved` from core 7.49.0 #955 / server >= 7.126.0 —
17757
+ server 7.122.0–7.125.x sent the previous spelling, which reads as out of set here, see the SDK README's 22.0.0 migration table). Rides FOUR faces with one value: the
17552
17758
  `tool_approval` frame, the `livePending` row top level, the operator queue row (`GET /v1/approvals`
17553
17759
  `pending[]` + the `/v1/approvals/stream` `pending` frame) and the inbox row. NOT on `card_json` / the
17554
17760
  `approval_request` frame (live or reconnect replay — `ApprovalCardSchema` is `.strict()`), same as `mandated`.
@@ -17613,12 +17819,17 @@ components:
17613
17819
  rules (`//abs`, `~/`, root-relative, cwd-relative; `*` within a segment, `**` across segments). `name` /
17614
17820
  `name_prefix` (server >= 7.118.0 / core 7.43.0 #1318) = the `Skill` name grammar: `Skill(<name>)` exact,
17615
17821
  `Skill(<prefix>:*)` a name prefix with NO word boundary; a skill card's "don't ask again" offer carries
17616
- `match: "name"`. A replica rolled back to 7.117.x reads a `name` / `name_prefix` row as a damaged row.
17822
+ `match: "name"`. A replica rolled back to 7.117.x reads a `name` / `name_prefix` row as a damaged row. `host` /
17823
+ `subdomain` (server >= 7.126.0 / core 7.49.0 #1365) = the `WebFetch` domain grammar: `WebFetch(domain:<host>)` one exact
17824
+ host, `WebFetch(domain:*.<domain>)` every host under that domain — ALLOW rows only; the server's `Bash` card edit face
17825
+ always refuses these two words (no network grant is minted through a card). A replica rolled back to 7.125.x reads such a
17826
+ row as a damaged row.
17617
17827
 
17618
- 🔴 SEVEN MEMBERS, closed: the server validates the member on both faces. A consumer type narrower than the
17828
+ 🔴 NINE MEMBERS, closed: the server validates the member on both faces. A consumer type narrower than the
17619
17829
  mint point is a lie — it lets a `switch` claim exhaustiveness the wire does not honour (SDK <= 16 declared
17620
- four here, so a `path` offer and every 7.118.0 skill-card offer were dropped as malformed).
17621
- enum: [exact, prefix, wildcard, subpath, path, name, name_prefix]
17830
+ four here, so a `path` offer and every 7.118.0 skill-card offer were dropped as malformed; SDK <= 21 declared
17831
+ seven, so every domain grant row on `GET /v1/rules` was dropped the same way).
17832
+ enum: [exact, prefix, wildcard, subpath, path, name, name_prefix, host, subdomain]
17622
17833
 
17623
17834
  RuleOfferUncoveredReason:
17624
17835
  type: string
@@ -18242,6 +18453,22 @@ components:
18242
18453
  400 `request.field_invalid`; any value on a direct-door worker ⇒ 400 `decided_by_not_in_proof`. An older server
18243
18454
  (no `approvalDecidedBy` bit) has a strict body here ⇒ 400 `request.body_shape`, nothing decided.
18244
18455
 
18456
+ ApprovalDecideGateKind:
18457
+ type: string
18458
+ enum: [human, irreversible_ask]
18459
+ description: >
18460
+ server >= 7.126.0 (sdk 21.1.0 `APPROVAL_DECIDE_GATE_KINDS`, verbatim and in order; single owner = server
18461
+ `APPROVAL_GATE_KINDS`) — the parked gate kinds the DURABLE decision door `POST /v1/approvals/{sessionId}/decide`
18462
+ accepts (the live `POST /v1/tool-approvals/{approvalId}/respond` answers the same card family). A parked row of
18463
+ kind `plan_review` goes to the plan-review door instead (`PlanReviewGateKind`); `resource_limit` / `needs_review` /
18464
+ `task_done` have no human decision door (resume / terminal). Clients route a pending row by reading this set,
18465
+ never by a hand-written copy of it.
18466
+ PlanReviewGateKind:
18467
+ type: string
18468
+ enum: [plan_review]
18469
+ description: >
18470
+ server >= 7.126.0 (sdk 21.1.0 `PLAN_REVIEW_GATE_KINDS`) — the parked gate kind the plan-review door
18471
+ `POST /v1/assistant/tasks/{taskId}/plan_review` accepts (3-state approve | edit | reject).
18245
18472
  ApprovalDecidedBy:
18246
18473
  type: string
18247
18474
  enum: [person, policy]
@@ -18737,6 +18964,16 @@ components:
18737
18964
  core-stream `eventId`, so this is its own time coordinate. 🔴 It MUST be declared here: this schema
18738
18965
  is `additionalProperties: false`, so omitting a key the server really sends makes a strict validator
18739
18966
  reject a legitimate frame. Absent on servers < 7.3.0.
18967
+ expiresInMs:
18968
+ type: integer
18969
+ description: >
18970
+ server >= 7.39.0, OPEN frame only: the coordinator's OWN answer window (`QUESTION_TTL_MS`, default 5 minutes) — at expiry the ask is
18971
+ released as nobody reachable (`unanswered`) and the engine decides park vs continue. Minted from the SAME ttl the release timer arms
18972
+ (one source, so a countdown rendered from it never disagrees with the release). Relative; with `expiresAtMs` and `serverNowMs` it is a
18973
+ clock-skew-proof trio.
18974
+ expiresAtMs:
18975
+ type: integer
18976
+ description: 'server >= 7.39.0, OPEN frame only: `serverNowMs + expiresInMs` — the absolute deadline on the server''s clock.'
18740
18977
  Event_question_complete:
18741
18978
  type: object
18742
18979
  description: >
@@ -19715,7 +19952,9 @@ components:
19715
19952
  A leg's LSP code-intelligence seam (core 7.18.0 #789). 🔴 THE TWO BITS ARE INDEPENDENT AND MUST NOT BE
19716
19953
  READ AS ONE: `mounted` is the ROSTER fact (a wired manager whose `LSP` tool was excluded reports
19717
19954
  `false`), while `lane` arms on the manager / the hands / the opt-out and NOT on the mount — so
19718
- `{mounted: false, lane: "diagnostics"}` is a REAL, REACHABLE state, not bad data.
19955
+ `{mounted: false, lane: "diagnostics"}` is a REAL, REACHABLE state, not bad data. LANE REACH (server >= 7.127.0 / core 7.50.0):
19956
+ LSP mounts only on a lane that binds reads to the object it judged — today the host lane; on e2b / k8s (and ssh / adb / device /
19957
+ local-docker / in-process) this section is always absent and the roster has no LSP tool (the server logs `lsp_not_mounted` at boot).
19719
19958
  additionalProperties: false
19720
19959
  required: [mounted]
19721
19960
  properties:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/sdk",
3
- "version": "21.0.0",
3
+ "version": "22.0.0",
4
4
  "description": "Typed, zero-runtime-dependency SDK for the Sema agent fleet usage plane. The shared substrate for all doors (CC/Codex MCP façade + web). Server-side only — tokens never enter the browser.",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -52,6 +52,6 @@
52
52
  "prepublishOnly": "rm -f tsconfig.tsbuildinfo && npm run build && npm run typecheck --workspaces=false --prefix ../.. && npm test --workspaces=false --prefix ../.. && npm run prepack"
53
53
  },
54
54
  "devDependencies": {
55
- "@sema-agent/settings-schema": "^11.2.0"
55
+ "@sema-agent/settings-schema": "^12.2.1"
56
56
  }
57
57
  }