@sema-agent/sdk 8.3.0 → 8.5.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/README.md +132 -0
- package/dist/events.d.ts +91 -28
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/tasks.d.ts +5 -2
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +5 -2
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +19 -5
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/types.d.ts +377 -22
- package/dist/types.d.ts.map +1 -1
- package/openapi.yaml +780 -63
- package/package.json +1 -1
package/openapi.yaml
CHANGED
|
@@ -5633,6 +5633,121 @@ components:
|
|
|
5633
5633
|
properties:
|
|
5634
5634
|
clampTolerance: { type: number }
|
|
5635
5635
|
|
|
5636
|
+
TerminalCause:
|
|
5637
|
+
description: >
|
|
5638
|
+
🔴 BREAKING (server >= 7.64.0, core 7.6.0 design/390 D-8) — WHY the run ended, as ONE tagged cause
|
|
5639
|
+
and the ONLY terminal record a `TaskResult` carries. It REPLACES the eight parallel plane keys of
|
|
5640
|
+
7.63.0 and earlier (`status` / `errorCode` / `errorMessage` / `blockedReason` / `checkpointToken` /
|
|
5641
|
+
`checkpointId` / `checkpointGate` / `workspaceRestoreMode`), all of which are GONE from this schema —
|
|
5642
|
+
no optional compatibility twin ships, because two spellings of one fact on one wire is two writers on
|
|
5643
|
+
one semantic surface.
|
|
5644
|
+
TRIAGE ON `terminal.kind`. The legacy five-word `status` (and the seven flat words) is a DERIVATION:
|
|
5645
|
+
call the engine's `terminalProjection(terminal)` — the ONE cause->plane derivation — never hand-roll it.
|
|
5646
|
+
Which pause reads as `suspended` and which as `needs_review` is decided by the engine's pause registry,
|
|
5647
|
+
not by this service.
|
|
5648
|
+
🔴 The service's OWN columns and envelopes are UNCHANGED and still speak the five words: the `status` /
|
|
5649
|
+
`errorCode` columns on `GET /v1/runs/:id`, the task-list row `status`, the `/decide` 200 body's
|
|
5650
|
+
`status` / `errorCode` / `errorMessage`, and the fleet row's terminal word. Only their data source moved
|
|
5651
|
+
(projected once from the cause).
|
|
5652
|
+
oneOf:
|
|
5653
|
+
- $ref: '#/components/schemas/TerminalCause_completed'
|
|
5654
|
+
- $ref: '#/components/schemas/TerminalCause_failed'
|
|
5655
|
+
- $ref: '#/components/schemas/TerminalCause_blocked'
|
|
5656
|
+
- $ref: '#/components/schemas/PausedCause'
|
|
5657
|
+
discriminator:
|
|
5658
|
+
propertyName: kind
|
|
5659
|
+
mapping:
|
|
5660
|
+
completed: '#/components/schemas/TerminalCause_completed'
|
|
5661
|
+
failed: '#/components/schemas/TerminalCause_failed'
|
|
5662
|
+
blocked: '#/components/schemas/TerminalCause_blocked'
|
|
5663
|
+
paused: '#/components/schemas/PausedCause'
|
|
5664
|
+
|
|
5665
|
+
TerminalCause_completed:
|
|
5666
|
+
type: object
|
|
5667
|
+
additionalProperties: false
|
|
5668
|
+
description: 'The run finished (a person''s clean halt included — see `TaskResult.haltedByUser`).'
|
|
5669
|
+
required: [kind]
|
|
5670
|
+
properties:
|
|
5671
|
+
kind: { const: completed }
|
|
5672
|
+
|
|
5673
|
+
TerminalCause_failed:
|
|
5674
|
+
type: object
|
|
5675
|
+
additionalProperties: false
|
|
5676
|
+
description: 'A limit, a provider failure, an abort, an invalid output…'
|
|
5677
|
+
required: [kind]
|
|
5678
|
+
properties:
|
|
5679
|
+
kind: { const: failed }
|
|
5680
|
+
code:
|
|
5681
|
+
type: string
|
|
5682
|
+
description: >
|
|
5683
|
+
The machine code this failure carried — the seat the retired flat `errorCode` occupied, now
|
|
5684
|
+
STRUCTURALLY owned by the failure arm ("a code belongs to a failure" is the shape, not a
|
|
5685
|
+
cross-field convention). OPEN SET, dotted namespaces so a caller can prefix-match a whole class:
|
|
5686
|
+
`limits.max_tokens_exceeded` / `limits.max_cost_exceeded` / `limits.max_turns_exceeded` /
|
|
5687
|
+
`limits.max_walltime_exceeded` / `config.*` / `resume_at.*`; brain codes (`auth` / `network` /
|
|
5688
|
+
`rate_limit` / …) and `conflict` stay FLAT. Two EXTERNAL stop causes are deliberately NOT
|
|
5689
|
+
`limits.*` (retrying them needs a new environment / a freed window, not a smaller budget):
|
|
5690
|
+
`env.lifetime_expired` and `usage.window_exhausted`.
|
|
5691
|
+
Governance codes arrive here too, and WHICH leg remaps one to an HTTP status differs per code —
|
|
5692
|
+
do not generalize from one to the other: (a) `memory.admission_denied` /
|
|
5693
|
+
`memory.admission_required` are remapped to 403/503 ONLY on the synchronous `POST /v1/tasks`;
|
|
5694
|
+
on `POST /v1/runs` -> `GET /v1/runs/{taskId}` and on the SSE `done` frame they ride a 200 result.
|
|
5695
|
+
(b) `usage.window_exhausted` is a 429 only when the PRE-ADMISSION gate catches it; caught in the
|
|
5696
|
+
race after admission it is NOT remapped on any leg, including the synchronous 200.
|
|
5697
|
+
A NESTED orchestrator that met a durable pause it cannot drive stamps `unexpected.suspended` /
|
|
5698
|
+
`unexpected.needs_review` and carries that pause on `nestedPause`.
|
|
5699
|
+
Consumers MUST branch with a `default` arm. Absent = the failure never had a code.
|
|
5700
|
+
message: { type: string, description: 'Human-readable failure text. Absent when there was none.' }
|
|
5701
|
+
nestedPause:
|
|
5702
|
+
allOf: [{ $ref: '#/components/schemas/PausedCause' }]
|
|
5703
|
+
description: >
|
|
5704
|
+
The durable pause this failure STANDS IN FOR — set ONLY at a nested hard boundary (verify /
|
|
5705
|
+
cascade): the nested leg paused on a durable gate the orchestrator cannot drive, so at ITS
|
|
5706
|
+
boundary the pause is reported as a failure while the pause's own cause travels here verbatim.
|
|
5707
|
+
🔴 On the wire it carries NO `token` — the same withholding rule as the top-level `paused` arm
|
|
5708
|
+
(see `PausedCause`); `gate` / `checkpointId` are present as usual.
|
|
5709
|
+
Absent on every failure the engine itself assembles.
|
|
5710
|
+
|
|
5711
|
+
TerminalCause_blocked:
|
|
5712
|
+
type: object
|
|
5713
|
+
additionalProperties: false
|
|
5714
|
+
description: 'The agent could not finish and said why (a governance verdict is NOT a failure).'
|
|
5715
|
+
required: [kind, reason]
|
|
5716
|
+
properties:
|
|
5717
|
+
kind: { const: blocked }
|
|
5718
|
+
reason: { type: string, description: 'Why the agent could not finish.' }
|
|
5719
|
+
|
|
5720
|
+
PausedCause:
|
|
5721
|
+
type: object
|
|
5722
|
+
additionalProperties: false
|
|
5723
|
+
description: >
|
|
5724
|
+
A durable pause committed a checkpoint and the run is resumable.
|
|
5725
|
+
🔴 THE `token` SEAT IS NEVER ON THE WIRE. It is the resume CAPABILITY (token-as-auth) and never leaves
|
|
5726
|
+
the service — the SAME discipline the retired top-level `checkpointToken` had, only the credential
|
|
5727
|
+
changed address (`src/terminal.ts` `stripResumeToken` removes it on both reachable paths: this arm and
|
|
5728
|
+
`TerminalCause_failed.nestedPause`). To act on this pause call
|
|
5729
|
+
`POST /v1/approvals/{sessionId}/decide` and reconcile by `checkpointId`.
|
|
5730
|
+
required: [kind, gate]
|
|
5731
|
+
properties:
|
|
5732
|
+
kind: { const: paused }
|
|
5733
|
+
gate:
|
|
5734
|
+
allOf: [{ $ref: '#/components/schemas/CheckpointGate' }]
|
|
5735
|
+
description: 'WHICH pause — who/what must resume it. Same word as the park row''s `gate.kind`.'
|
|
5736
|
+
checkpointId:
|
|
5737
|
+
type: string
|
|
5738
|
+
description: >
|
|
5739
|
+
The pause's NON-SECRET stable identity — the display/correlation key to log or render where the
|
|
5740
|
+
token must not travel. Absent on pre-identity checkpoints.
|
|
5741
|
+
restoreMode:
|
|
5742
|
+
type: string
|
|
5743
|
+
enum: [snapshot, park_only]
|
|
5744
|
+
description: >
|
|
5745
|
+
HOW the paused task's remote workspace comes back, present whenever the pause captured one.
|
|
5746
|
+
`snapshot` = the VM was suspended into a snapshot (provider billing typically stops).
|
|
5747
|
+
`park_only` = the env declared itself non-suspendable (an SSH host / an ADB device) so NOTHING was
|
|
5748
|
+
paused: the machine keeps running and keeps costing. ABSENT for a process-local pause — a
|
|
5749
|
+
scheduler that assumes "paused => idle and free" must be able to see the difference.
|
|
5750
|
+
|
|
5636
5751
|
TaskResult:
|
|
5637
5752
|
type: object
|
|
5638
5753
|
# 🔴 **刻意不封闭**(census 轴一裁定,2026-07-30)。此前是「没写」= JSON Schema 默认开放,分不清
|
|
@@ -5642,12 +5757,21 @@ components:
|
|
|
5642
5757
|
# 这里改成 false 会让 spec 与本仓自己的类型面互相打脸,并且把「引擎加字段」判成 wire 违约(它不是)。
|
|
5643
5758
|
# 收紧这一面的正解不是 additionalProperties,是把引擎真发的键**逐个登记**(字段级 drift 门的活)。
|
|
5644
5759
|
additionalProperties: true
|
|
5645
|
-
description:
|
|
5646
|
-
|
|
5760
|
+
description: >
|
|
5761
|
+
Synchronous task result (`POST /v1/tasks`). 🔴 BREAKING at server 7.64.0: the terminal is ONE tagged
|
|
5762
|
+
cause (`terminal`), not the eight parallel plane keys — see `TerminalCause`.
|
|
5763
|
+
required: [taskId, sessionId, terminal, stats]
|
|
5647
5764
|
properties:
|
|
5648
5765
|
taskId: { type: string }
|
|
5649
5766
|
sessionId: { type: string }
|
|
5650
|
-
|
|
5767
|
+
terminal:
|
|
5768
|
+
allOf: [{ $ref: '#/components/schemas/TerminalCause' }]
|
|
5769
|
+
description: >
|
|
5770
|
+
🔴 server >= 7.64.0 — the ONE terminal record. Branch on `terminal.kind`. The eight retired plane
|
|
5771
|
+
keys (`status` / `errorCode` / `errorMessage` / `blockedReason` / `checkpointToken` /
|
|
5772
|
+
`checkpointId` / `checkpointGate` / `workspaceRestoreMode`) are GONE from this schema and this
|
|
5773
|
+
SDK ships NO compatibility projection: a consumer that still needs the five-word `status` calls
|
|
5774
|
+
the engine's `terminalProjection(terminal)` itself.
|
|
5651
5775
|
result: { type: string }
|
|
5652
5776
|
activeTaskId:
|
|
5653
5777
|
type: [string, 'null']
|
|
@@ -5678,20 +5802,13 @@ components:
|
|
|
5678
5802
|
salvagedOutput:
|
|
5679
5803
|
type: string
|
|
5680
5804
|
description: Partial output preserved when the run could not complete normally (best-effort salvage).
|
|
5681
|
-
blockedReason:
|
|
5682
|
-
type: string
|
|
5683
|
-
description: Why a `blocked` status was reached (human-readable).
|
|
5684
|
-
checkpointGate:
|
|
5685
|
-
description: >
|
|
5686
|
-
The gate kind that produced `checkpointToken` when the run suspended. Deliberately UNTYPED here —
|
|
5687
|
-
the shape is core's and still evolving; treat it as opaque and branch on `status`/`errorCode` instead.
|
|
5688
5805
|
toolCallId:
|
|
5689
5806
|
type: string
|
|
5690
5807
|
description: >
|
|
5691
5808
|
[4913] (server 7.41+) — the PENDING tool call's id when this result is a durable park
|
|
5692
|
-
(`
|
|
5809
|
+
(`terminal.kind === "paused"` with a `tool_approval` pending action); same key and meaning as the
|
|
5693
5810
|
`tool_approval` frame's `toolCallId` (server >= 1.307). ABSENT (key omitted, never null) on a
|
|
5694
|
-
tool-less park (resource_limit / plan_review / task_done), on every
|
|
5811
|
+
tool-less park (resource_limit / plan_review / task_done), on every non-paused cause, and when the
|
|
5695
5812
|
server-side checkpoint read failed — consumers test presence.
|
|
5696
5813
|
degraded:
|
|
5697
5814
|
type: object
|
|
@@ -5716,21 +5833,6 @@ components:
|
|
|
5716
5833
|
description: >
|
|
5717
5834
|
The task's structured (schema-constrained) output when one was requested. Shape is caller-defined,
|
|
5718
5835
|
so this is intentionally untyped.
|
|
5719
|
-
errorCode:
|
|
5720
|
-
type: string
|
|
5721
|
-
description: >
|
|
5722
|
-
Result-level terminal code (NOT an HTTP error). Includes `budget.precall` / `budget.exceeded`
|
|
5723
|
-
(cost gate, non-retryable) — branch on this, not on a 4xx (pinned wire contract).
|
|
5724
|
-
Governance codes also arrive HERE, and WHICH leg renders them as an HTTP status differs per code —
|
|
5725
|
-
do not generalize from one to the other:
|
|
5726
|
-
(a) `memory.admission_denied` / `memory.admission_required` (server >=7.0.0) are remapped to 403/503
|
|
5727
|
-
ONLY on the synchronous `POST /v1/tasks`; on `POST /v1/runs` -> `GET /v1/runs/{taskId}` and on the
|
|
5728
|
-
SSE `done` frame they ride a 200 result (those legs have no second chance at a status line).
|
|
5729
|
-
(b) `usage.window_exhausted` is a 429 only when the PRE-ADMISSION gate catches it (all three submit
|
|
5730
|
-
endpoints). When the window is exhausted in the race after admission, the engine's refusal is NOT
|
|
5731
|
-
remapped on any leg — it lands in the result, including a 200 from the synchronous `POST /v1/tasks`.
|
|
5732
|
-
Branch on this field, never on the status alone.
|
|
5733
|
-
errorMessage: { type: string }
|
|
5734
5836
|
retryAfterMs:
|
|
5735
5837
|
type: integer
|
|
5736
5838
|
description: >
|
|
@@ -5751,6 +5853,51 @@ components:
|
|
|
5751
5853
|
rounds: { type: integer }
|
|
5752
5854
|
findings: { type: array, items: { type: string } }
|
|
5753
5855
|
|
|
5856
|
+
LegacyPlaneTaskResult:
|
|
5857
|
+
type: object
|
|
5858
|
+
additionalProperties: true
|
|
5859
|
+
description: >
|
|
5860
|
+
🔴 THE SHAPE THAT IS ON DISK — a task result written by server 7.63.0 or earlier, in the retired FLAT
|
|
5861
|
+
plane form. It appears ONLY on the faces that REPLAY PERSISTED BYTES, and only on a deployment that was
|
|
5862
|
+
upgraded across 7.64.0: `GET /v1/runs/:id` -> `result` (the service passes the stored blob through
|
|
5863
|
+
verbatim, redaction only — `src/http/routes/runs.ts`) and the durable-ledger replay of the `done` frame.
|
|
5864
|
+
NOTHING WRITES IT ANY MORE: the write path mints exactly one shape (`TaskResult`, with `terminal`).
|
|
5865
|
+
🔴 THIS IS NOT A COMPATIBILITY TWIN. The rule against "two spellings of one fact on one wire" is about
|
|
5866
|
+
WRITERS: two producers of one semantic surface. Here there is ONE writer and a READ face that admits the
|
|
5867
|
+
bytes a now-retired writer actually left on disk — the same distinction the service draws for its own
|
|
5868
|
+
two-generation reader (`persistedPlaneOf`, whose header records the two reproducible regressions that
|
|
5869
|
+
deleting it caused: a 500 on every historical `GET /v1/runs/:id`, and unredacted credentials replayed
|
|
5870
|
+
from old ledger rows).
|
|
5871
|
+
NARROWING: `"terminal" in result` — present = the current cause form, absent = this shape. Do NOT narrow
|
|
5872
|
+
on `status` alone: the SSE conflict envelope (`ActiveRunConflictDoneResult`) also carries `status`.
|
|
5873
|
+
🔴 `terminal` IS REFUSED HERE, and that clause is load-bearing rather than decorative: the two
|
|
5874
|
+
generations are MUTUALLY EXCLUSIVE on disk (7.63.0 wrote `status` and never `terminal`; 7.64.0 writes
|
|
5875
|
+
`terminal` and never `status`), and without the refusal a MALFORMED current result — `terminal: null`,
|
|
5876
|
+
an unknown cause kind, a `paused` cause that still carries its `token` — would fail the `TaskResult`
|
|
5877
|
+
arm and then be LAUNDERED through this one, so the read faces would silently lose every negative
|
|
5878
|
+
control `TaskResult` enforces while a consumer narrowing on `"terminal" in result` walks straight into
|
|
5879
|
+
it. The documented discriminant and the enforced one are the same clause.
|
|
5880
|
+
not: { required: [terminal] }
|
|
5881
|
+
required: [taskId, sessionId, status, stats]
|
|
5882
|
+
properties:
|
|
5883
|
+
taskId: { type: string }
|
|
5884
|
+
sessionId: { type: string }
|
|
5885
|
+
status: { $ref: '#/components/schemas/RunStatus' }
|
|
5886
|
+
result: { type: string }
|
|
5887
|
+
stats: { $ref: '#/components/schemas/TaskStats' }
|
|
5888
|
+
errorCode: { type: string, description: 'The retired flat terminal code. Its successor is `TerminalCause.failed.code`.' }
|
|
5889
|
+
errorMessage: { type: string, description: 'The retired flat failure text. Successor: `TerminalCause.failed.message`.' }
|
|
5890
|
+
blockedReason: { type: string, description: 'The retired flat governance reason. Successor: `TerminalCause.blocked.reason`.' }
|
|
5891
|
+
checkpointGate:
|
|
5892
|
+
description: >
|
|
5893
|
+
The retired flat pause gate — UNTYPED here on purpose, because these are bytes an older generation
|
|
5894
|
+
wrote and this contract does not re-litigate their shape. Successor: `TerminalCause.paused.gate`
|
|
5895
|
+
(typed as `CheckpointGate`).
|
|
5896
|
+
salvagedOutput: { type: string }
|
|
5897
|
+
model: { type: string }
|
|
5898
|
+
toolCallId: { type: string }
|
|
5899
|
+
retryAfterMs: { type: integer }
|
|
5900
|
+
|
|
5754
5901
|
RunReceipt:
|
|
5755
5902
|
type: object
|
|
5756
5903
|
# 封闭(census 轴一,2026-07-30):producer 铸造点 routes/runs.ts 与 idem 重放臂各自逐字写死
|
|
@@ -5769,7 +5916,12 @@ components:
|
|
|
5769
5916
|
description: >
|
|
5770
5917
|
Run state (`GET /v1/runs/:id`) — live shape per the pinned wire contract Drift 2: `result` is the NESTED TaskResult
|
|
5771
5918
|
object (output text in result.result, stats in result.stats; NO top-level stats), and the error text
|
|
5772
|
-
field is `error` (not errorMessage
|
|
5919
|
+
field is `error` (not errorMessage).
|
|
5920
|
+
🔴 server >= 7.64.0 — this ROW's own `status` / `errorCode` columns are UNCHANGED and still speak the
|
|
5921
|
+
five words; only their SOURCE moved. The nested `result` is the engine result itself and therefore
|
|
5922
|
+
changed shape with it (`result.terminal`, no plane keys): the row's `errorCode` column is now projected
|
|
5923
|
+
from `result.terminal` (`src/http/routes/runs.ts` -> `persistedPlaneOf`, which also reads the flat bytes
|
|
5924
|
+
7.63.0 and earlier wrote to disk), NOT copied from a `result.errorCode` that no longer exists.
|
|
5773
5925
|
# 封闭(census 轴一,2026-07-30;A-075.21 回填后 12 键):铸造点 routes/runs.ts 是一个逐键写死的
|
|
5774
5926
|
# 字面量(taskId/sessionId/status/msSinceLastActivity/crossSliceUsage/result/supervisorCost/
|
|
5775
5927
|
# suggestions/errorCode/error/jobId/source),与本 properties 一一对上;只有 taskId/sessionId/status
|
|
@@ -5806,10 +5958,21 @@ components:
|
|
|
5806
5958
|
spentMicroUsd: { type: integer, description: 'Integer micro-USD; absent on unpriced deployments (unknown, not 0).' }
|
|
5807
5959
|
maxSlices: { type: integer }
|
|
5808
5960
|
sliceCount: { type: integer }
|
|
5809
|
-
result:
|
|
5961
|
+
result:
|
|
5962
|
+
oneOf:
|
|
5963
|
+
- $ref: '#/components/schemas/TaskResult'
|
|
5964
|
+
- $ref: '#/components/schemas/LegacyPlaneTaskResult'
|
|
5965
|
+
description: >
|
|
5966
|
+
🔴 A READ-OF-DISK face, so it carries TWO generations of bytes (see `LegacyPlaneTaskResult`): the
|
|
5967
|
+
current cause form on anything server >= 7.64.0 wrote, and the retired flat form on rows written
|
|
5968
|
+
before the upgrade. The service passes the stored blob through verbatim (redaction only) and does
|
|
5969
|
+
NOT back-fill `terminal`. Narrow on `"terminal" in result`.
|
|
5810
5970
|
errorCode:
|
|
5811
5971
|
type: string
|
|
5812
|
-
description:
|
|
5972
|
+
description: >
|
|
5973
|
+
Result-level terminal code (e.g. `budget.exceeded`, `cancelled`); NOT an HTTP error. This ROW COLUMN
|
|
5974
|
+
is unchanged at 7.64.0 — only its source moved (projected from `result.terminal`, or read straight
|
|
5975
|
+
off a legacy flat blob).
|
|
5813
5976
|
error: { type: string }
|
|
5814
5977
|
jobId:
|
|
5815
5978
|
type: string
|
|
@@ -6080,20 +6243,29 @@ components:
|
|
|
6080
6243
|
input: { description: tool-call — redacted args. }
|
|
6081
6244
|
callId: { type: string }
|
|
6082
6245
|
isError: { type: boolean }
|
|
6083
|
-
# 🔴
|
|
6084
|
-
# `toolResultFieldsOf`(src/trace/project.ts)同时喂 turns 面与 trace SSE 面,而写侧
|
|
6085
|
-
# `toolEndEventData` 喂 durable 账本 ——
|
|
6086
|
-
|
|
6246
|
+
# 🔴 BREAKING (server >=7.64.0, core 7.6.0 S6-A) —— 与 `Event_tool_end.gate` **同一个值**:server 的
|
|
6247
|
+
# 共享挑键器 `toolResultFieldsOf`(src/trace/project.ts)同时喂 turns 面与 trace SSE 面,而写侧
|
|
6248
|
+
# `toolEndEventData` 喂 durable 账本 —— 三面一个真源。退役的 `settledBy` 与它的三兄弟
|
|
6249
|
+
# (`resolution`/`autoDenied`/`approver`)在这三面上一并删除。
|
|
6250
|
+
gate:
|
|
6251
|
+
allOf: [{ $ref: '#/components/schemas/GateOutcome' }]
|
|
6252
|
+
description: >
|
|
6253
|
+
tool-result — the WHOLE record of this call''s gate pass (see `GateOutcome`). The READ leg
|
|
6254
|
+
screens it INDEPENDENTLY of the write leg (a ledger row can come from any engine generation or
|
|
6255
|
+
a third-party producer), so a defective record is withheld here too. Absence is not a fact
|
|
6256
|
+
about the call.
|
|
6257
|
+
delivered:
|
|
6258
|
+
allOf: [{ $ref: '#/components/schemas/McpDelivered' }]
|
|
6259
|
+
description: 'tool-result — MCP delivery verdict; read with `errorCode`. Absent on every non-MCP-failure result.'
|
|
6260
|
+
errorCode:
|
|
6087
6261
|
type: string
|
|
6088
|
-
enum: [human, timeout, aborted]
|
|
6089
6262
|
description: >
|
|
6090
|
-
tool-result —
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
ledger row can come from any engine generation.
|
|
6263
|
+
tool-result — the machine code for WHY this call failed, verbatim from any tool''s
|
|
6264
|
+
`ToolResult.details.code` (OPEN set; the MCP family within it is core''s closed
|
|
6265
|
+
`McpFailureKind` word list since 7.6.0). Same key and semantics as `Event_tool_end.errorCode`.
|
|
6266
|
+
gatedCallId:
|
|
6267
|
+
type: string
|
|
6268
|
+
description: 'tool-result — WHICH tool call a durable park is holding (core >= 5.55.0); absent on a tool-less park.'
|
|
6097
6269
|
tokens:
|
|
6098
6270
|
type: object
|
|
6099
6271
|
properties:
|
|
@@ -6831,6 +7003,9 @@ components:
|
|
|
6831
7003
|
`roots` (copying an upstream default onto the wire becomes a lie the day core changes it).
|
|
6832
7004
|
Minimal disclosure — the deny table itself is never on the capability face. There is NO
|
|
6833
7005
|
per-request `readFace` field on TaskRequest.
|
|
7006
|
+
server >= 7.65.0 (S-167): on a SINGLE-USER TURNKEY worker (REQUIRE_PRINCIPAL unset) with no
|
|
7007
|
+
READ_FACE set this bit is `"open"` (posture-derived), where 7.64.0 answered `null`; multi-tenant
|
|
7008
|
+
workers still answer `null`. Provenance lives on the operator face `diagnostics.wiring.readFace`.
|
|
6834
7009
|
callerCwd:
|
|
6835
7010
|
type: boolean
|
|
6836
7011
|
description: >
|
|
@@ -6894,6 +7069,105 @@ components:
|
|
|
6894
7069
|
denial:
|
|
6895
7070
|
type: ["string", "null"]
|
|
6896
7071
|
enum: [entitlement_resolver_absent, null]
|
|
7072
|
+
writeProtection:
|
|
7073
|
+
oneOf:
|
|
7074
|
+
- $ref: '#/components/schemas/WriteProtectionCapability'
|
|
7075
|
+
- type: 'null'
|
|
7076
|
+
description: >
|
|
7077
|
+
server >= 7.63.0 (S-138) — the WRITE-PROTECTION TABLE's posture on this deployment (see
|
|
7078
|
+
`WriteProtectionCapability`). `null` = this process cannot say; an ABSENT key means an OLDER worker,
|
|
7079
|
+
and "no key" is NOT "no table" — an absent seat on the engine side is precisely the DEFAULT TABLE
|
|
7080
|
+
BEING IN PLACE.
|
|
7081
|
+
WriteProtectionCapability:
|
|
7082
|
+
type: object
|
|
7083
|
+
additionalProperties: false
|
|
7084
|
+
description: >
|
|
7085
|
+
server >= 7.63.0 (S-138) — the WRITE-PROTECTION TABLE's posture on this deployment. The engine's
|
|
7086
|
+
literal name table downgrades a locatable write (Write / Edit / NotebookEdit) that lands on a table
|
|
7087
|
+
row from `allow` to `ask`, so a shell can tell in advance that those paths will raise a card.
|
|
7088
|
+
🔴 THE THREE ARE DELIBERATELY NOT FOLDED INTO ONE BOOLEAN: folded, "the engine's default table is
|
|
7089
|
+
in place" and "an operator swapped in a table of their own" both read `true`, and those two say
|
|
7090
|
+
different things to an operator.
|
|
7091
|
+
🔴 MINIMUM DISCLOSURE: the per-row names/kinds are NOT here — a deployment-authored row can carry
|
|
7092
|
+
an internal path name, and listing them tells anyone who wants around them which names are NOT
|
|
7093
|
+
protected. Rows live on the operator face `GET /v1/diagnostics/wiring` -> `writeProtection.rows`.
|
|
7094
|
+
🔴 A PARALLEL MECHANISM, NOT THE SAME ONE: `SENSITIVE_WRITE_PATTERNS` (pattern-shaped write deny)
|
|
7095
|
+
is reported separately and must never be folded into this bit — the two have different fixes.
|
|
7096
|
+
The three-state reading of the SEAT itself lives at the reference point (`Capabilities.writeProtection`):
|
|
7097
|
+
`null` = this process cannot say; key absent = an older worker (and "no key" is NOT "no table").
|
|
7098
|
+
required: [armed, rows, replaced]
|
|
7099
|
+
properties:
|
|
7100
|
+
armed: { type: boolean, description: 'The effective table is non-empty => the engine really will raise a card on a row hit.' }
|
|
7101
|
+
rows: { type: integer, description: 'How many rows the effective table has (contents stay on the operator face).' }
|
|
7102
|
+
replaced: { type: boolean, description: 'The whole-table replacement knob was written => the default table is no longer in place as-is (an explicit EMPTY table counts — "the operator turned it off" is not "nothing was touched").' }
|
|
7103
|
+
|
|
7104
|
+
|
|
7105
|
+
WriteProtectedRow:
|
|
7106
|
+
type: object
|
|
7107
|
+
additionalProperties: false
|
|
7108
|
+
description: >
|
|
7109
|
+
One row of the write-protection table (core `WriteProtectedRow`): a LITERAL name plus how it matches.
|
|
7110
|
+
The `name` is also the row's stable identity — the string a refusal / ask message cites.
|
|
7111
|
+
required: [name, kind]
|
|
7112
|
+
properties:
|
|
7113
|
+
name: { type: string }
|
|
7114
|
+
kind:
|
|
7115
|
+
type: string
|
|
7116
|
+
enum: [basename, segment, segment-run]
|
|
7117
|
+
description: >
|
|
7118
|
+
`basename` = the target's LAST segment equals the row name · `segment` = ANY path segment equals it ·
|
|
7119
|
+
`segment-run` = a CONSECUTIVE run of segments equals the row's `/`-separated segments.
|
|
7120
|
+
|
|
7121
|
+
WriteProtectionPosture:
|
|
7122
|
+
type: object
|
|
7123
|
+
additionalProperties: false
|
|
7124
|
+
description: >
|
|
7125
|
+
server >= 7.63.0 (S-138) — the OPERATOR face of the write-protection table (`GET /v1/diagnostics/wiring`
|
|
7126
|
+
-> `writeProtection`). Same boot artefact as the tenant-facing `capabilities.writeProtection`, so the two
|
|
7127
|
+
faces cannot tell different stories; this one adds the ROW CONTENTS, which the tenant face withholds.
|
|
7128
|
+
required: [rows, source]
|
|
7129
|
+
properties:
|
|
7130
|
+
rows:
|
|
7131
|
+
type: array
|
|
7132
|
+
items: { $ref: '#/components/schemas/WriteProtectedRow' }
|
|
7133
|
+
description: 'The effective table, verbatim from the engine''s own compile (the service recomputes nothing). Empty = an explicitly empty table.'
|
|
7134
|
+
source:
|
|
7135
|
+
type: string
|
|
7136
|
+
enum: [default, extra, replace, off]
|
|
7137
|
+
description: >
|
|
7138
|
+
`default` = neither knob was written (the engine's default table is in place; the service does NOT
|
|
7139
|
+
copy that table — the engine owns it) · `extra` = default plus additions · `replace` = whole-table
|
|
7140
|
+
replacement · `off` = replaced with an EMPTY table (legal, and loud).
|
|
7141
|
+
droppedDefaultRows:
|
|
7142
|
+
type: array
|
|
7143
|
+
items: { type: string }
|
|
7144
|
+
description: >
|
|
7145
|
+
The DEFAULT row names a whole-table replacement dropped. Present only on the replacement family
|
|
7146
|
+
(`extra` / `default` cannot structurally drop a row). Row identity is judged by the ENGINE's own
|
|
7147
|
+
fold rule, so a case-variant spelling is not reported as a loss.
|
|
7148
|
+
|
|
7149
|
+
ReadFacePosture:
|
|
7150
|
+
type: object
|
|
7151
|
+
additionalProperties: false
|
|
7152
|
+
description: >
|
|
7153
|
+
server >= 7.65.0 (S-167) — the READ containment rung of this deployment AND WHO SET IT (operator face
|
|
7154
|
+
`GET /v1/diagnostics/wiring` -> `readFace`). `face` is the same boot artefact as the tenant-facing
|
|
7155
|
+
`capabilities.readFace` (`null` = nothing pinned by this deployment, the engine default is in force).
|
|
7156
|
+
`source` is a CLOSED four-word set on the server (exhaustive switch — adding a word is a compile error
|
|
7157
|
+
there): `env` = this machine's READ_FACE env var (wins over everything) · `center` = the config-center
|
|
7158
|
+
readFace domain (restart-to-apply) · `posture` = derived from the single-user turnkey posture
|
|
7159
|
+
(REQUIRE_PRINCIPAL unset ⇒ `open`; server >= 7.65.0 behaviour change) · `engine-default` = not pinned.
|
|
7160
|
+
`note` is a human-facing pointer for operators. Minimal disclosure: the deny table is never on this face.
|
|
7161
|
+
required: [face, source, note]
|
|
7162
|
+
properties:
|
|
7163
|
+
face:
|
|
7164
|
+
type: ["string", "null"]
|
|
7165
|
+
enum: [open, roots, null]
|
|
7166
|
+
source:
|
|
7167
|
+
type: string
|
|
7168
|
+
enum: [env, center, posture, engine-default]
|
|
7169
|
+
note:
|
|
7170
|
+
type: string
|
|
6897
7171
|
|
|
6898
7172
|
SkillSpec:
|
|
6899
7173
|
type: object
|
|
@@ -9267,6 +9541,214 @@ components:
|
|
|
9267
9541
|
parentToolCallId: { type: string }
|
|
9268
9542
|
sourceTaskId: { type: string }
|
|
9269
9543
|
bgAgentId: { type: string }
|
|
9544
|
+
DeniedBy:
|
|
9545
|
+
type: string
|
|
9546
|
+
description: >
|
|
9547
|
+
WHO REFUSED a call — the LAYER whose verdict is the deny (core 7.6.0 `DENIED_BY_VALUES`, 8 words,
|
|
9548
|
+
CLOSED). The other question a deny raises — who ASKED — is answered by `AskOrigin`; the two used to
|
|
9549
|
+
share one seven-word list in which `classifier` meant both.
|
|
9550
|
+
`policy` = the deployment `ToolPolicy` denied (directly, or re-checking an approved edit), or the
|
|
9551
|
+
approval-edit chain hit its round cap · `hook` = a PreToolUse hook denied, threw, or never answered ·
|
|
9552
|
+
`org` = an organization policy rule denied · `classifier` = the auto-mode classifier denied directly ·
|
|
9553
|
+
`plan_mode` = plan mode's read-only block on a write tool · `compliance` = the compliance call-time
|
|
9554
|
+
lock · `write_protection` = an approved edit was rewritten onto a write-protected path no approval
|
|
9555
|
+
covers · `ask_resolution` = the ask's own settlement IS the refusal (detail on `GateOutcome.settlement`).
|
|
9556
|
+
🔴 CLOSED ON THIS WIRE, and deliberately not marked open: the engine's invariant screen
|
|
9557
|
+
(`screenGateOutcome`) treats an out-of-set `deniedBy` as a DEFECT, and the service withholds a defective
|
|
9558
|
+
record WHOLE (report + withhold). A word outside this set therefore cannot reach a consumer — it arrives
|
|
9559
|
+
as the `gate` key being ABSENT, never as an unfamiliar word. Same rule for `Settlement.kind` and for
|
|
9560
|
+
`GateOutcome.origin`.
|
|
9561
|
+
enum: [policy, hook, org, classifier, plan_mode, compliance, write_protection, ask_resolution]
|
|
9562
|
+
|
|
9563
|
+
Settlement:
|
|
9564
|
+
description: >
|
|
9565
|
+
HOW the wait an ask was in ENDED — a DISCRIMINATED union on `kind` (core 7.6.0 `SETTLEMENT_KINDS`,
|
|
9566
|
+
12 words, CLOSED). It is deliberately NOT a free product of `kind` x `who`: a free product can express
|
|
9567
|
+
"human_allowed, ended by the engine's window" — a structurally complete record that contradicts itself.
|
|
9568
|
+
`who` says WHICH PARTY ended it and its shape is fixed BY the word; `when` is epoch ms written at the
|
|
9569
|
+
settlement site; a person's refusal carries the decider's own `note` when one was attached.
|
|
9570
|
+
🔴 Single mint: every kind is composed by the ENGINE at the site whose wait ended. A host never mints a
|
|
9571
|
+
word — it reports FACTS (a synchronous approver's `human`/`timeout`, a durable decide's
|
|
9572
|
+
`decidedBy: "person" | "sla_timeout"`) and core turns them into the word.
|
|
9573
|
+
Server-side projection note: `who.approver` and `note` are host-derived / decider-authored text and are
|
|
9574
|
+
secret-redacted (and `note` length-bounded) before they reach this wire.
|
|
9575
|
+
oneOf:
|
|
9576
|
+
- $ref: '#/components/schemas/Settlement_human'
|
|
9577
|
+
- $ref: '#/components/schemas/Settlement_approval_window_expired'
|
|
9578
|
+
- $ref: '#/components/schemas/Settlement_denial_limit_window_expired'
|
|
9579
|
+
- $ref: '#/components/schemas/Settlement_park_sla_expired'
|
|
9580
|
+
- $ref: '#/components/schemas/Settlement_fail_closed'
|
|
9581
|
+
|
|
9582
|
+
Settlement_human:
|
|
9583
|
+
type: object
|
|
9584
|
+
additionalProperties: false
|
|
9585
|
+
description: 'A person (or the approver acting for one) decided. `human_refused` may carry the decider''s own note.'
|
|
9586
|
+
required: [kind, who, when]
|
|
9587
|
+
properties:
|
|
9588
|
+
kind: { type: string, enum: [human_allowed, human_refused] }
|
|
9589
|
+
who:
|
|
9590
|
+
type: object
|
|
9591
|
+
additionalProperties: false
|
|
9592
|
+
required: [party]
|
|
9593
|
+
properties:
|
|
9594
|
+
party: { const: person }
|
|
9595
|
+
approver: { type: string, description: 'The attribution the approval channel reported. Absent = the channel reported no name — NEVER read as "nobody approved".' }
|
|
9596
|
+
when: { type: integer, format: int64, description: 'Epoch ms, written at the settlement site.' }
|
|
9597
|
+
note: { type: string, description: 'The refusing decider''s own words, when one was attached. A refusal WITHOUT a note is a bare "no".' }
|
|
9598
|
+
|
|
9599
|
+
Settlement_approval_window_expired:
|
|
9600
|
+
type: object
|
|
9601
|
+
additionalProperties: false
|
|
9602
|
+
description: 'An approval window elapsed with no answer — the engine''s own approval factory window, or a synchronous host approver reporting its own window elapsed.'
|
|
9603
|
+
required: [kind, who, when]
|
|
9604
|
+
properties:
|
|
9605
|
+
kind: { const: approval_window_expired }
|
|
9606
|
+
who:
|
|
9607
|
+
oneOf:
|
|
9608
|
+
- type: object
|
|
9609
|
+
additionalProperties: false
|
|
9610
|
+
required: [party, window]
|
|
9611
|
+
properties:
|
|
9612
|
+
party: { const: engine }
|
|
9613
|
+
window: { const: approval_factory }
|
|
9614
|
+
- type: object
|
|
9615
|
+
additionalProperties: false
|
|
9616
|
+
required: [party]
|
|
9617
|
+
properties:
|
|
9618
|
+
party: { const: host }
|
|
9619
|
+
when: { type: integer, format: int64 }
|
|
9620
|
+
|
|
9621
|
+
Settlement_denial_limit_window_expired:
|
|
9622
|
+
type: object
|
|
9623
|
+
additionalProperties: false
|
|
9624
|
+
description: 'The classifier denial-limit fallback''s auto-deny window (core''s own timer over the synchronous leg) elapsed with no answer.'
|
|
9625
|
+
required: [kind, who, when]
|
|
9626
|
+
properties:
|
|
9627
|
+
kind: { const: denial_limit_window_expired }
|
|
9628
|
+
who:
|
|
9629
|
+
type: object
|
|
9630
|
+
additionalProperties: false
|
|
9631
|
+
required: [party, window]
|
|
9632
|
+
properties:
|
|
9633
|
+
party: { const: engine }
|
|
9634
|
+
window: { const: denial_limit }
|
|
9635
|
+
when: { type: integer, format: int64 }
|
|
9636
|
+
|
|
9637
|
+
Settlement_park_sla_expired:
|
|
9638
|
+
type: object
|
|
9639
|
+
additionalProperties: false
|
|
9640
|
+
description: >
|
|
9641
|
+
A DURABLE park''s SLA deadline passed and the host''s sweep resolved it as a deny. A store
|
|
9642
|
+
`expire`/`reap` produces no `tool_end` and therefore no settlement.
|
|
9643
|
+
required: [kind, who, when]
|
|
9644
|
+
properties:
|
|
9645
|
+
kind: { const: park_sla_expired }
|
|
9646
|
+
who:
|
|
9647
|
+
type: object
|
|
9648
|
+
additionalProperties: false
|
|
9649
|
+
required: [party]
|
|
9650
|
+
properties:
|
|
9651
|
+
party: { const: host }
|
|
9652
|
+
approver: { type: string }
|
|
9653
|
+
when: { type: integer, format: int64 }
|
|
9654
|
+
|
|
9655
|
+
Settlement_fail_closed:
|
|
9656
|
+
type: object
|
|
9657
|
+
additionalProperties: false
|
|
9658
|
+
description: >
|
|
9659
|
+
The fail-closed family — nobody ended the wait, the situation did. `no_approver` (headless: no approver
|
|
9660
|
+
or question face is wired, or the deny posture string) · `approver_unavailable` (the approver answered
|
|
9661
|
+
the ROUTING question "nobody reachable" and no park took the ask) · `approver_error` (it threw) ·
|
|
9662
|
+
`approver_contract` (it answered outside its contract) · `presentation_failed` (args/edit could not be
|
|
9663
|
+
safely presented or adopted) · `blanket_allow_refused` (a blanket `onAsk:"allow"` met a
|
|
9664
|
+
`requiresRealApproval` ask) · `task_aborted` (the wait''s abort signal ended it).
|
|
9665
|
+
required: [kind, who, when]
|
|
9666
|
+
properties:
|
|
9667
|
+
kind:
|
|
9668
|
+
type: string
|
|
9669
|
+
enum: [no_approver, approver_unavailable, approver_error, approver_contract, presentation_failed, blanket_allow_refused, task_aborted]
|
|
9670
|
+
who:
|
|
9671
|
+
type: object
|
|
9672
|
+
additionalProperties: false
|
|
9673
|
+
required: [party]
|
|
9674
|
+
properties:
|
|
9675
|
+
party: { const: none }
|
|
9676
|
+
when: { type: integer, format: int64 }
|
|
9677
|
+
|
|
9678
|
+
GateDisposition:
|
|
9679
|
+
description: 'The final disposition of one tool-gate pass. A deny NAMES the layer that refused.'
|
|
9680
|
+
oneOf:
|
|
9681
|
+
- type: object
|
|
9682
|
+
additionalProperties: false
|
|
9683
|
+
required: [kind]
|
|
9684
|
+
properties:
|
|
9685
|
+
kind: { const: allowed }
|
|
9686
|
+
- type: object
|
|
9687
|
+
additionalProperties: false
|
|
9688
|
+
required: [kind, deniedBy]
|
|
9689
|
+
properties:
|
|
9690
|
+
kind: { const: denied }
|
|
9691
|
+
deniedBy: { $ref: '#/components/schemas/DeniedBy' }
|
|
9692
|
+
|
|
9693
|
+
GateOutcome:
|
|
9694
|
+
type: object
|
|
9695
|
+
additionalProperties: false
|
|
9696
|
+
description: >
|
|
9697
|
+
🔴 BREAKING (server >= 7.64.0, core 7.6.0 design/390 S6-A) — the WHOLE record of ONE tool-gate pass.
|
|
9698
|
+
It REPLACES the four orthogonal words of 7.63.0 and earlier (`settledBy` / `resolution` / `autoDenied` /
|
|
9699
|
+
`approver`, all four DELETED with no alias): their pairing rules lived only in comments, and consumers
|
|
9700
|
+
had to infer semantics from ABSENCE ("a `timeout` with no `resolution` means a durable park expired").
|
|
9701
|
+
Minted ONCE by the engine (the gate''s exit; the decide lane for a durable park) and projected without
|
|
9702
|
+
re-derivation onto three faces — the `permissionDenied` observer payload, this `tool_end` frame, and the
|
|
9703
|
+
durable row''s resolved outcome — so the three cannot tell different stories.
|
|
9704
|
+
The three members are orthogonal but bound by four engine invariants: (I1) `settlement` present <=>
|
|
9705
|
+
`origin` present — they describe the SAME ask; (I2) `deniedBy === "ask_resolution"` => `settlement`
|
|
9706
|
+
present AND a refusal kind; (I3) a `human_allowed` settlement beside a `denied` disposition means a
|
|
9707
|
+
LATER re-check vetoed a person''s approval, so `deniedBy` is one of the veto layers (`policy` / `hook` /
|
|
9708
|
+
`org` / `write_protection`) and the approver stays on the settlement; (I4) an `allowed` disposition has
|
|
9709
|
+
`settlement` absent or `human_allowed`.
|
|
9710
|
+
🔴 NOTHING here is read out of an ABSENCE: an ordinary allow with no ask is
|
|
9711
|
+
`{disposition:{kind:"allowed"}}`, a direct policy deny is `{disposition:{kind:"denied",deniedBy:"policy"}}`,
|
|
9712
|
+
and neither carries a settlement because neither settled one.
|
|
9713
|
+
🔴 The SERVICE withholds a record that fails the engine''s invariant screen (report + withhold, counter
|
|
9714
|
+
`server.trace.gate-outcome-defective`) — so "a gate should have been here but the key is absent" has a
|
|
9715
|
+
fourth cause besides the three below: that record was defective. The four are indistinguishable on the
|
|
9716
|
+
wire; a consumer falls back to `isError` + the message text.
|
|
9717
|
+
required: [disposition]
|
|
9718
|
+
properties:
|
|
9719
|
+
disposition: { $ref: '#/components/schemas/GateDisposition' }
|
|
9720
|
+
settlement:
|
|
9721
|
+
allOf: [{ $ref: '#/components/schemas/Settlement' }]
|
|
9722
|
+
description: 'Present only when THIS pass settled an ask. Same-present/same-absent as `origin` (I1).'
|
|
9723
|
+
origin:
|
|
9724
|
+
allOf:
|
|
9725
|
+
- { $ref: '#/components/schemas/AskOrigin' }
|
|
9726
|
+
# 🔴 闭集执法**只在这一面**:引擎的 `screenGateOutcome` 对 `origin` 判成员,出集即记录缺陷,而
|
|
9727
|
+
# 服务对缺陷记录是整条不上帧 ⇒ 词表外的值在这条 wire 上到不了消费端。审批帧那一面不判成员,
|
|
9728
|
+
# 所以 `AskOrigin` 本体保持真开(见该 schema 的长注)。这张 enum 是本 spec 里该词表的**唯一**
|
|
9729
|
+
# 执法点;core 加词时改这一处。
|
|
9730
|
+
- enum: [content_question, unresolvable, org_unavailable, org_rule, hook, ask_rule, denial_limit_fallback, shell_gate_tighten, safety_tighten, policy]
|
|
9731
|
+
description: >
|
|
9732
|
+
WHO ASKED. Same-present/same-absent as `settlement` (I1). CLOSED here (and only here) — see the
|
|
9733
|
+
enum note above.
|
|
9734
|
+
|
|
9735
|
+
McpDelivered:
|
|
9736
|
+
type: string
|
|
9737
|
+
description: >
|
|
9738
|
+
Whether a failed MCP request REACHED the server (core 7.6.0 `MCP_DELIVERY_VERDICTS`, CLOSED).
|
|
9739
|
+
`yes` = the server answered (a `protocol` rejection proves the exchange happened) · `no` = provably
|
|
9740
|
+
never sent (a connect-phase errno, a spawn failure, a malformed declaration, a server already known
|
|
9741
|
+
dead) — safe to retry, nothing executed · `unknown` = the client stopped waiting or lost the pipe
|
|
9742
|
+
mid-exchange, so the request MAY have executed and a write-capable tool''s side effects must be
|
|
9743
|
+
verified before a retry.
|
|
9744
|
+
🔴 READ IT WITH `errorCode`, never alone: the SAME `connection_closed` is directly retryable at `no`
|
|
9745
|
+
and must be investigated at `unknown` — which is exactly why the verdict is its own field and not
|
|
9746
|
+
folded into the class.
|
|
9747
|
+
⚠️ `no` says the CALLER''S TOOL CALL was not sent; it does NOT promise the server received zero bytes
|
|
9748
|
+
(an elicitation during the dial may already have crossed the connection) — core''s contract, passed
|
|
9749
|
+
through verbatim.
|
|
9750
|
+
enum: [yes, no, unknown]
|
|
9751
|
+
|
|
9270
9752
|
Event_tool_end:
|
|
9271
9753
|
type: object
|
|
9272
9754
|
description: >
|
|
@@ -9274,7 +9756,19 @@ components:
|
|
|
9274
9756
|
(TextContent|ImageContent)[] block array) and degrades to a single TRUNCATED string over the core size cap
|
|
9275
9757
|
(`truncated: true`). Absent ⇒ the tool produced no body. 🔴 UNTRUSTED RAW + observability-only: the service
|
|
9276
9758
|
has redactDeep'd + size-bounded it; a consumer MAY further bound, MUST never re-feed it to a model.
|
|
9277
|
-
allOf:
|
|
9759
|
+
allOf:
|
|
9760
|
+
- { $ref: '#/components/schemas/EventIdentity' }
|
|
9761
|
+
# 🔴 现役写口与退役四词**互斥**(S-170 codex r2 [medium] 验真后补):退役四词只出现在 <=7.63.0 写下的
|
|
9762
|
+
# durable 行上,而那种行结构上**没有** `gate`(7.63.0 压根不铸它)。所以「`gate` 与四词同帧」在
|
|
9763
|
+
# 任何一代的真字节里都不存在 —— 它只可能是现役写口回吐退役键,或一条自相矛盾的合成记录。
|
|
9764
|
+
# 不拒它,「四词只在回放里」这句话就没有任何机器在守(标记键 `x-legacy-replay-only` 是给人和
|
|
9765
|
+
# codegen 读的,不执法)。
|
|
9766
|
+
- not:
|
|
9767
|
+
anyOf:
|
|
9768
|
+
- { required: [gate, settledBy] }
|
|
9769
|
+
- { required: [gate, resolution] }
|
|
9770
|
+
- { required: [gate, autoDenied] }
|
|
9771
|
+
- { required: [gate, approver] }
|
|
9278
9772
|
additionalProperties: false # 封闭 + identity 本地镜像:见 Event_reasoning 处的长注
|
|
9279
9773
|
required: [type, toolCallId, toolName, isError]
|
|
9280
9774
|
properties:
|
|
@@ -9289,19 +9783,60 @@ components:
|
|
|
9289
9783
|
output: {} # NON-UNIFORM: string | (TextContent|ImageContent)[] | (truncated) string. Absent ⇒ no body.
|
|
9290
9784
|
truncated: { type: boolean }
|
|
9291
9785
|
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.
|
|
9292
|
-
# 🔴
|
|
9293
|
-
#
|
|
9294
|
-
#
|
|
9295
|
-
#
|
|
9786
|
+
# 🔴 BREAKING (server >=7.64.0, core 7.6.0 S6-A): `settledBy` / `resolution` / `autoDenied` / `approver`
|
|
9787
|
+
# are RETIRED and replaced by the ONE `gate` record below. NO 7.64.0+ writer mints them, and the TS type
|
|
9788
|
+
# does NOT carry them — nobody should code against a dead vocabulary.
|
|
9789
|
+
# 🔴 They are still DECLARED here, and only for one reason: this arm is `additionalProperties: false`, and
|
|
9790
|
+
# the durable-ledger replay leg (`GET /v1/runs/:id/events`) passes a stored `tool_end` row through
|
|
9791
|
+
# VERBATIM (the service's `redactLedgerEventData` returns the row unchanged for this type). Server 7.63.0
|
|
9792
|
+
# and earlier really did write all four into that ledger, so on a deployment upgraded across 7.64.0 those
|
|
9793
|
+
# bytes reach a consumer — and without a declaration that is not "four fields we cannot read", it is the
|
|
9794
|
+
# WHOLE FRAME judged invalid (the same failure family as `permissionRules` and `errorCode` before it).
|
|
9795
|
+
# Same doctrine as `LegacyPlaneTaskResult`: the write face mints ONE shape; a face that replays persisted
|
|
9796
|
+
# bytes admits what the retired writer actually left on disk. `x-legacy-replay-only: true` marks them so a
|
|
9797
|
+
# code generator / a reader can tell them apart from live keys at a glance.
|
|
9296
9798
|
settledBy:
|
|
9297
9799
|
type: string
|
|
9298
9800
|
enum: [human, timeout, aborted]
|
|
9801
|
+
x-legacy-replay-only: true
|
|
9299
9802
|
description: >
|
|
9300
|
-
core
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9803
|
+
RETIRED at server 7.64.0 (core 7.6.0 S6-A) — superseded by `gate.settlement`. Appears ONLY when a
|
|
9804
|
+
durable ledger row written by server <= 7.63.0 is replayed. Never minted by a current writer; not on
|
|
9805
|
+
the SDK type. Do not branch on it.
|
|
9806
|
+
resolution:
|
|
9807
|
+
type: string
|
|
9808
|
+
x-legacy-replay-only: true
|
|
9809
|
+
description: 'RETIRED at 7.64.0 — superseded by `gate.settlement.kind`. Replay-only, see `settledBy`.'
|
|
9810
|
+
autoDenied:
|
|
9811
|
+
const: true
|
|
9812
|
+
x-legacy-replay-only: true
|
|
9813
|
+
description: 'RETIRED at 7.64.0 — superseded by `gate.disposition` + `gate.settlement`. Replay-only, see `settledBy`.'
|
|
9814
|
+
approver:
|
|
9815
|
+
type: string
|
|
9816
|
+
x-legacy-replay-only: true
|
|
9817
|
+
description: 'RETIRED at 7.64.0 — superseded by `gate.settlement.who.approver`. Replay-only, see `settledBy`.'
|
|
9818
|
+
gate:
|
|
9819
|
+
allOf: [{ $ref: '#/components/schemas/GateOutcome' }]
|
|
9820
|
+
description: >
|
|
9821
|
+
🔴 server >= 7.64.0 — the WHOLE record of the gate pass this call went through: who allowed it or
|
|
9822
|
+
which LAYER refused it (`disposition`), how the wait it consumed ended (`settlement`, carrying the
|
|
9823
|
+
refusing person and their own note), and who ASKED (`origin`).
|
|
9824
|
+
🔴 ABSENCE IS NOT A FACT ABOUT THIS CALL: the gate never saw it (an unarmed gate, a deferred
|
|
9825
|
+
re-send, an orphan picked up by reconcile) — or the record was defective and the service withheld
|
|
9826
|
+
it (see `GateOutcome`). Never read a semantic out of the missing key.
|
|
9827
|
+
delivered:
|
|
9828
|
+
allOf: [{ $ref: '#/components/schemas/McpDelivered' }]
|
|
9829
|
+
description: >
|
|
9830
|
+
core >= 7.6.0 (S6-B) — whether THIS failed MCP request reached the server. Present only on an MCP
|
|
9831
|
+
failure: every successful call and every non-MCP failure omits it, and the absence carries NO
|
|
9832
|
+
semantics. Read it WITH `errorCode` (see `McpDelivered`).
|
|
9833
|
+
gatedCallId:
|
|
9834
|
+
type: string
|
|
9835
|
+
description: >
|
|
9836
|
+
core >= 5.55.0 (#333) — WHICH tool call a durable park is holding, minted by the engine from the
|
|
9837
|
+
committed checkpoint''s pending action (a tool may not self-report it). Present only on a park
|
|
9838
|
+
frame; absent on a park that holds no tool call (resource_limit / plan_review / task_done) —
|
|
9839
|
+
ABSENT, never guessed.
|
|
9305
9840
|
# 🔴 core >=5.9.0 (W3 / [2535]). OPEN SET — deliberately a bare `type: string`, NOT an enum.
|
|
9306
9841
|
# This arm is `additionalProperties: false`, and the server's `toolEndEventData` has been emitting
|
|
9307
9842
|
# `errorCode` since 5.9.0, so omitting it made every legitimate frame carrying one fail strict
|
|
@@ -9316,6 +9851,12 @@ components:
|
|
|
9316
9851
|
when `isError` is true. OPEN SET: a verbatim passthrough of any tool's `ToolResult.details.code`.
|
|
9317
9852
|
The engine's own codes (`gate.parked`, `tool.not_found`) are only two examples; the fs tools
|
|
9318
9853
|
already emit `path_not_in_root` / `readonly_out_of_root`, and self-registered tools may add more.
|
|
9854
|
+
🔴 core >= 7.6.0 — the MCP family within this open set is now the CLOSED `McpFailureKind` word list
|
|
9855
|
+
(`connect_refused` / `connection_failed` / `connection_closed` / `http_status` / `not_mcp_response` /
|
|
9856
|
+
`spawn_failed` / `timeout` / `protocol` / `invalid_config` / `unknown`); the retired
|
|
9857
|
+
`MCP_FAILURE_CODES` spellings — including `network` and the `http_<status>` encoding — are gone,
|
|
9858
|
+
and an HTTP status now rides the structured `httpStatus` seat on `wiring_manifest.mcp[]` instead of
|
|
9859
|
+
being baked into the code. The set as a WHOLE stays open (a tool owns its own codes).
|
|
9319
9860
|
Consumers MUST branch with a `default` arm and MUST NOT exhaustively switch on known values.
|
|
9320
9861
|
The service enforces only a length bound (>128 chars = malformed, the whole key is DROPPED rather
|
|
9321
9862
|
than truncated — truncating would mint a code core never sent). NOTE: this is a DIFFERENT
|
|
@@ -9680,6 +10221,80 @@ components:
|
|
|
9680
10221
|
renders "don't ask again" without reading this bit is advertising an outcome it cannot promise.
|
|
9681
10222
|
🔴 Same three-way reading as `syncWired`: present-and-false = concept known, not armed here;
|
|
9682
10223
|
absent = the worker never sent the key. Honestly `false` on server 7.12.0.
|
|
10224
|
+
modelGate:
|
|
10225
|
+
type: object
|
|
10226
|
+
additionalProperties: false
|
|
10227
|
+
description: >
|
|
10228
|
+
core >= 7.3.x (design/385 片2b), server >= 7.58 — TENANT-visible: which tools the tool-MODEL gate
|
|
10229
|
+
removed from THIS session and how to get them back. All three keys are engine-derived (`class` = the
|
|
10230
|
+
merged gate table''s class row key, `removed` = wire tool names, `restore` = the engine''s own
|
|
10231
|
+
recovery line), so the service passes them verbatim.
|
|
10232
|
+
🔴 ALL-OR-NOTHING: the service mints the section only when all three keys are present and
|
|
10233
|
+
well-formed — half a section would read as "these are the only tools that were removed".
|
|
10234
|
+
ABSENT = this run had nothing gated (the service never mints an empty section or `removed: []`).
|
|
10235
|
+
required: [class, removed, restore]
|
|
10236
|
+
properties:
|
|
10237
|
+
class: { type: string }
|
|
10238
|
+
removed: { type: array, items: { type: string } }
|
|
10239
|
+
restore: { type: string }
|
|
10240
|
+
autoMode:
|
|
10241
|
+
type: object
|
|
10242
|
+
additionalProperties: false
|
|
10243
|
+
description: >
|
|
10244
|
+
core >= 7.3.1 (#529), server >= 7.59 — TENANT-visible: did AUTO mode actually arm on THIS leg, and
|
|
10245
|
+
if not, which arm did it stop at. Sibling of `GET /v1/capabilities.permissionModeAuto`, which
|
|
10246
|
+
answers the BEFORE question ("would a submit right now arm?"); this section answers the AFTER one
|
|
10247
|
+
("did the leg that really ran arm?").
|
|
10248
|
+
🔴 `reason` is core''s closed word list passed through VERBATIM and is deliberately NOT normalised
|
|
10249
|
+
onto the service''s own six-word `PermissionModeAutoUnarmedReason` set: the two tables answer
|
|
10250
|
+
different questions at different granularity (core''s single `denied` covers the service''s
|
|
10251
|
+
`org_denied` + `local_denied`, and a settings-level kill-switch folds into core''s `no_intent`,
|
|
10252
|
+
not `denied`, because it rewrites the MODE before the intent seat is ever written). To tell those
|
|
10253
|
+
apart, read `/v1/capabilities`.
|
|
10254
|
+
🔴 ABSENCE IS NOT "not applicable" (core''s own words: it means an older mint or an external
|
|
10255
|
+
derivation) — never fold it to `armed: false`. A self-contradicting pair (`armed` disagreeing with
|
|
10256
|
+
`reason === "armed"`, core''s own in-section invariant) makes the service withhold the WHOLE section.
|
|
10257
|
+
required: [armed, reason]
|
|
10258
|
+
properties:
|
|
10259
|
+
armed: { type: boolean }
|
|
10260
|
+
reason: { type: string, description: 'core''s word (`armed` / `no_intent` / `no_face` / `denied` / `resolver_fault` / `latch_open` today). Open on read — branch known, keep a default arm.' }
|
|
10261
|
+
mcp:
|
|
10262
|
+
type: array
|
|
10263
|
+
description: >
|
|
10264
|
+
core >= 7.5.0 (#562), server >= 7.60 — TENANT-visible: one row per MCP server THIS leg declared —
|
|
10265
|
+
did it connect, if not which failure class, and how many tools it mounted.
|
|
10266
|
+
🔴 AN EMPTY ARRAY IS NOT ABSENCE: `[]` means "this leg declared no servers"; a missing key means an
|
|
10267
|
+
older mint or an external derivation. Never fold one into the other.
|
|
10268
|
+
🔴 The engine''s `error` free text is DELIBERATELY NOT PROJECTED (it is remote-author text, and core
|
|
10269
|
+
already owns the single redaction mint point for it). The actionable cause is `errorCode`.
|
|
10270
|
+
A row missing `name` or `status` is dropped individually — the other servers'' rows still ship.
|
|
10271
|
+
items:
|
|
10272
|
+
type: object
|
|
10273
|
+
additionalProperties: false
|
|
10274
|
+
required: [name, status]
|
|
10275
|
+
properties:
|
|
10276
|
+
name: { type: string, description: 'The declared server name.' }
|
|
10277
|
+
status: { type: string, description: 'Three-word engine set (connected / failed / …). Open on read.' }
|
|
10278
|
+
source: { type: string, description: 'The declarer''s own layer label, echoed verbatim by core (single-line, length-capped).' }
|
|
10279
|
+
toolCount: { type: integer, description: 'Tools mounted. ABSENT rather than 0 — a minted 0 would read as "connected with no tools".' }
|
|
10280
|
+
errorCode:
|
|
10281
|
+
type: string
|
|
10282
|
+
description: >
|
|
10283
|
+
core >= 7.6.0 — the `McpFailureKind` word (`connect_refused` / `connection_failed` /
|
|
10284
|
+
`connection_closed` / `http_status` / `not_mcp_response` / `spawn_failed` / `timeout` /
|
|
10285
|
+
`protocol` / `invalid_config` / `unknown`). The retired 7.5.0 spellings — `network` and the
|
|
10286
|
+
`http_<status>` encoding — are GONE; an HTTP status now rides `httpStatus`.
|
|
10287
|
+
Deliberately NOT enumerated here: the vocabulary''s single owner is the engine, and mirroring
|
|
10288
|
+
it would swallow a newly minted word as a violation. Switch with a `default` arm.
|
|
10289
|
+
delivered:
|
|
10290
|
+
allOf: [{ $ref: '#/components/schemas/McpDelivered' }]
|
|
10291
|
+
description: 'core >= 7.6.0 (S6-B) — did the request reach that server. Read WITH `errorCode`.'
|
|
10292
|
+
httpStatus:
|
|
10293
|
+
type: integer
|
|
10294
|
+
description: >
|
|
10295
|
+
core >= 7.6.0 (S6-B) — the status the endpoint answered with; rides ONLY with
|
|
10296
|
+
`errorCode === "http_status"` (401/403 = re-authorize, 5xx = that end is down). ABSENT rather
|
|
10297
|
+
than 0.
|
|
9683
10298
|
governance:
|
|
9684
10299
|
type: object
|
|
9685
10300
|
additionalProperties: false
|
|
@@ -9712,6 +10327,16 @@ components:
|
|
|
9712
10327
|
`memory.harvest_quarantined` `{count, moved, escalated, reason?}` — `moved` and `escalated` MUST NOT be
|
|
9713
10328
|
subtracted from each other (an in-place tombstone counts as both) · `memory.delegation_static_mark_waived`
|
|
9714
10329
|
`{reason, subagentType?, sessionId?}`.
|
|
10330
|
+
`config.durable_gate_unavailable` — a per-principal `forceDurableGate` entitlement took effect on a leg
|
|
10331
|
+
with NO checkpoint store, so every ask on that leg settles on the LIVE chain (answered in-stream where a
|
|
10332
|
+
live approval / question face exists, fail-closed denied where none does) and NO durable approval record
|
|
10333
|
+
is written. `{sessionId, runId, principal?, cause, liveApprover, liveQuestionFace}`.
|
|
10334
|
+
🔴 `cause` is a CLOSED two-word set: `no_deployment_store` (this deployment wired no store) and
|
|
10335
|
+
`task_store_disabled` (`TaskSpec.checkpointStore: "disabled"` — the per-run off switch).
|
|
10336
|
+
⚠️ server >= 7.64.0 / core 7.6.0 (D-9) RENAMED that second word from `task_store_null`, and the off
|
|
10337
|
+
switch itself became the WORD `"disabled"` instead of `null` (a string is not nullish, so the ordinary
|
|
10338
|
+
coalesce is the whole resolution rule and no reader has to remember a null test). A consumer still
|
|
10339
|
+
matching `task_store_null` matches nothing.
|
|
9715
10340
|
A notice whose `detail.sessionId` is absent is HONESTLY NOT DELIVERED (the server never guesses a session),
|
|
9716
10341
|
so the frame's absence does NOT mean "did not happen" — the operator-facing structured log always has the
|
|
9717
10342
|
full family. `detail` is already redacted + size-bounded by the server; still treat it as external text.
|
|
@@ -9764,14 +10389,28 @@ components:
|
|
|
9764
10389
|
kind:
|
|
9765
10390
|
type: string
|
|
9766
10391
|
description: >
|
|
10392
|
+
The SIX known kinds (`server src/http/wire-gate.ts` `WIRE_GATE_KINDS`), listed for codegen and
|
|
10393
|
+
autocomplete — NOT a closed set, and deliberately NOT an `enum` (see the note below):
|
|
9767
10394
|
`human` — plain HITL approval (budget-auto-approvable). `irreversible_ask` — design/37
|
|
9768
10395
|
irreversibility / design/70 egress tighten; NOT budgetable (load-bearing safety gate).
|
|
9769
10396
|
`resource_limit` — design/74 cost/token/time slice boundary; resolve `{decision:"continue"}`.
|
|
9770
10397
|
`needs_review` — design/76 dry-run/shadow → durable `needs_review` TERMINAL (post-prediction
|
|
9771
10398
|
review, disjoint from the approval family). `task_done` — design/38 Path A background sub-task
|
|
9772
|
-
handle (door B never sees it).
|
|
9773
|
-
|
|
10399
|
+
handle (door B never sees it). `plan_review` — [2400] TR-8 / design/80 D-B PRE-ACTION plan
|
|
10400
|
+
review, resolved at `POST /v1/assistant/tasks/:id/plan_review` (3-state), never at `/decide`.
|
|
10401
|
+
An unknown future kind is VALID on the wire: branch on `kind` and render it generically.
|
|
9774
10402
|
x-open-enum: true # do not close this union — an unknown future kind is VALID on the wire
|
|
10403
|
+
# 🔴 顶层 `enum` **已删**(S-170,codex r1 [high] 验真后修)—— 它与本 schema 自己声明的开集语义
|
|
10404
|
+
# 直接矛盾,而矛盾的那一头在执法:
|
|
10405
|
+
# ① 那张表停在**五**词,漏了 `plan_review` —— 它自 [2400] TR-8 起就是**现役**门(SDK 的
|
|
10406
|
+
# `CheckpointGate.kind` 与 server 的 `WIRE_GATE_KINDS` 六词都有它),下面 catch-all 臂的注
|
|
10407
|
+
# 甚至还把它当成「未来的未知 kind」举例。一次 plan_review park 的整条响应因此被判违约。
|
|
10408
|
+
# ② 就算补齐第六词,顶层 `enum` 仍是**合取**的:`x-open-enum` 只是意图标记,标准 JSON Schema
|
|
10409
|
+
# 的 `enum` 照样执法 ⇒ core 加第七个门的当天,每一条那类 park 响应全线违约。
|
|
10410
|
+
# ⇒ **kind 的合法性只由下面的 `oneOf` 一处决定**(具名臂管已知词的形状,catch-all 管未知词),
|
|
10411
|
+
# 规则从两处变一处。已知词表留在本描述里给 codegen / 自动补全读,不再是第二道执法点。
|
|
10412
|
+
# (本车把 `terminal.paused.gate` 指向本 schema 之后,这条既存缺陷的射程从 `suspended` 帧扩到了
|
|
10413
|
+
# 每一条 park 终局 —— 所以在本车里修,而不是留给下一车。)
|
|
9775
10414
|
reason: { type: string, description: 'present on human / irreversible_ask / resource_limit / needs_review (not task_done).' }
|
|
9776
10415
|
toolName: { type: string, description: 'present on human / irreversible_ask.' }
|
|
9777
10416
|
oneOf:
|
|
@@ -9790,12 +10429,16 @@ components:
|
|
|
9790
10429
|
- type: object # design/38 Path A background sub-task handle (door B never sees it)
|
|
9791
10430
|
required: [kind]
|
|
9792
10431
|
properties: { kind: { const: task_done } }
|
|
9793
|
-
- type: object #
|
|
10432
|
+
- type: object # [2400] TR-8 / design/80 D-B — PRE-ACTION plan review; resolved at POST /v1/assistant/tasks/:id/plan_review
|
|
10433
|
+
required: [kind, reason]
|
|
10434
|
+
properties: { kind: { const: plan_review } }
|
|
10435
|
+
- type: object # OPEN SET — a future kind this contract predates; render generically, never crash
|
|
9794
10436
|
required: [kind]
|
|
9795
|
-
# 🔴 the pinned wire contract: exclude the
|
|
10437
|
+
# 🔴 the pinned wire contract: exclude the KNOWN kinds so a known kind matches ONLY its const member above
|
|
9796
10438
|
# (not also this fallback) → keeps `oneOf` unambiguous AND preserves each kind's shape validation.
|
|
9797
|
-
# This fallback matches ONLY a future kind this contract predates. Add new known kinds to the enum
|
|
9798
|
-
|
|
10439
|
+
# This fallback matches ONLY a future kind this contract predates. Add new known kinds to the enum
|
|
10440
|
+
# AND to this exclusion list (S-170: `plan_review` was a KNOWN kind sitting in neither).
|
|
10441
|
+
properties: { kind: { type: string, not: { enum: [human, irreversible_ask, resource_limit, needs_review, task_done, plan_review] } } }
|
|
9799
10442
|
|
|
9800
10443
|
Event_suspended:
|
|
9801
10444
|
type: object
|
|
@@ -10513,7 +11156,14 @@ components:
|
|
|
10513
11156
|
# ─── S-139(sdk 8.3.0):对 server 7.60.0 整体重对账带进来的四张型面 ───────────────────────
|
|
10514
11157
|
AskOrigin:
|
|
10515
11158
|
type: string
|
|
10516
|
-
enum:
|
|
11159
|
+
x-open-enum: true
|
|
11160
|
+
# 🔴 顶层 `enum` **不放这里**(S-170 codex r2 [medium] 验真后修,与本车对 `CheckpointGate` 的处置同款):
|
|
11161
|
+
# 词表属主是引擎、而且它**真的长过**(core 7.6.0 从 8 词加到 10 词),而 `tool_approval` 帧这一面
|
|
11162
|
+
# server 只判非空串、不判成员(`src/tool-approval.ts` 帧铸点)⇒ 留一个 `enum` 在这里,core 加词的
|
|
11163
|
+
# 当天,一个**合法**的审批卡就会被严格消费端拒收。`x-open-enum` 只是意图标记,不解除 enum 的执法 ——
|
|
11164
|
+
# 这正是本车刚从 `CheckpointGate` 拆掉的那个假开集,不在这里换个地方重犯。
|
|
11165
|
+
# 闭集**执法**只属于**筛过的**那一面(`GateOutcome.origin`:引擎的 `screenGateOutcome` 判成员,
|
|
11166
|
+
# 出集即整条不上帧),所以那张 enum 落在**那个引用点**,恰一处。已知十词见下面的描述。
|
|
10517
11167
|
description: >
|
|
10518
11168
|
WHO raised an ask (`ToolApprovalFrame.origin`; server >= 7.57.0 / core 7.5.0, S-125③/#564) — core's
|
|
10519
11169
|
`ASK_ORIGINS`, ENGINE-STAMPED at the gate (core's words: "engine-stamped at the gate, never a policy's
|
|
@@ -10526,6 +11176,17 @@ components:
|
|
|
10526
11176
|
whether THIS DEPLOYMENT's ops governance layer is the gate — `origin: policy` covers any deployment
|
|
10527
11177
|
ToolPolicy's ask, so a governance-produced ask and an ordinary one look identical in this one word.
|
|
10528
11178
|
|
|
11179
|
+
🔴 core 7.6.0 ADDED TWO WORDS (the set was eight through core 7.5.x): `shell_gate_tighten` = the gate's
|
|
11180
|
+
own irreversibility tighten raised the ask over a tier the COARSE `shellGate` doctrine installed (a
|
|
11181
|
+
shell command under `shellGate: "classify"` / `"always"`), and `safety_tighten` = the gate's own
|
|
11182
|
+
post-fold tightens over an EXPLICIT fact of the call (an egress mark, an irreversibility mark, a
|
|
11183
|
+
peer-message referral in auto mode, a write onto the write-protected table). They are separate words
|
|
11184
|
+
precisely so a deny observer or an approval card can say WHICH engine layer raised the question — one
|
|
11185
|
+
word could not. Both are classifier-eligible (arming auto mode is the deployment's explicit choice to
|
|
11186
|
+
let the classifier resolve those classes).
|
|
11187
|
+
|
|
11188
|
+
The SAME type is the `origin` member of `GateOutcome` on `tool_end` — one vocabulary, two faces.
|
|
11189
|
+
|
|
10529
11190
|
RuleOffersAbsence:
|
|
10530
11191
|
type: string
|
|
10531
11192
|
enum: [mandated, shadowed, lane_cannot_speak]
|
|
@@ -11253,8 +11914,15 @@ components:
|
|
|
11253
11914
|
· `ActiveRunConflictDoneResult` — the SSE lane's REJECTION terminal: when the session already has an
|
|
11254
11915
|
active run, the submit's 409 is encoded as this done frame (`src/http/routes/tasks.ts`), and it
|
|
11255
11916
|
carries NO `taskId` / `sessionId` / `stats`.
|
|
11256
|
-
Narrow
|
|
11257
|
-
`errorCode === "conflict.session_active_run"
|
|
11917
|
+
Narrow in TWO steps: `stats` present (an engine result) vs absent (the conflict envelope) — or match
|
|
11918
|
+
`errorCode === "conflict.session_active_run"` — and then, among the engine results, `"terminal" in result`
|
|
11919
|
+
(the current cause form) vs absent (`LegacyPlaneTaskResult`, the flat bytes an older generation left in
|
|
11920
|
+
the durable ledger; a REPLAYED frame on an upgraded deployment can be that shape).
|
|
11921
|
+
🔴 server >= 7.64.0 — the two arms are now told apart by their KEYS, not by a shared word: the normal
|
|
11922
|
+
terminal carries `terminal` (the tagged cause) and NO `status`; the conflict shape carries the flat
|
|
11923
|
+
`status: "failed"` + `errorCode` because it is the SERVICE's own rejection envelope, not an engine
|
|
11924
|
+
result, and it did not change. `status` therefore appears on exactly one arm — but keep narrowing on
|
|
11925
|
+
`stats` / `errorCode`, which are the discriminants the service pins.
|
|
11258
11926
|
additionalProperties: false # 封闭:帧本身只有 {type,result,replay?};`result` 内部按臂各自裁定(TaskResult 开集,冲突形封闭)
|
|
11259
11927
|
required: [type, result]
|
|
11260
11928
|
properties:
|
|
@@ -11263,6 +11931,7 @@ components:
|
|
|
11263
11931
|
oneOf:
|
|
11264
11932
|
- $ref: '#/components/schemas/TaskResult'
|
|
11265
11933
|
- $ref: '#/components/schemas/ActiveRunConflictDoneResult'
|
|
11934
|
+
- $ref: '#/components/schemas/LegacyPlaneTaskResult'
|
|
11266
11935
|
replay:
|
|
11267
11936
|
type: boolean
|
|
11268
11937
|
description: >
|
|
@@ -12144,7 +12813,9 @@ components:
|
|
|
12144
12813
|
core's assembly self-evidence manifest (core >=5.14.0 `WiringManifest`). TWO HALVES, ONE shape (a
|
|
12145
12814
|
consumer must line the two faces up, so they are not split into separate types) — but which keys
|
|
12146
12815
|
belong to which half is DETERMINATE, not "usually": `leg`, `ask.effective` and `configFingerprint`
|
|
12147
|
-
are EFFECTIVE-half only (the live `wiring_manifest` event)
|
|
12816
|
+
are EFFECTIVE-half only (the live `wiring_manifest` event) — as are the three per-leg sections the
|
|
12817
|
+
event schema declares (`modelGate`, `autoMode`, `mcp`), which describe what THIS leg did and have no
|
|
12818
|
+
static counterpart — and the STATIC half
|
|
12148
12819
|
(GET /v1/diagnostics/wiring) NEVER mints them; every other section, plus `governance`, is always
|
|
12149
12820
|
present on the static half. Fields stay optional because core may add or drop sections and that
|
|
12150
12821
|
must not hard-break a client — read by half, and never wait on a key the half never sends.
|
|
@@ -12232,12 +12903,58 @@ components:
|
|
|
12232
12903
|
|
|
12233
12904
|
WiringDiagnostics:
|
|
12234
12905
|
type: object
|
|
12235
|
-
description:
|
|
12906
|
+
description: >
|
|
12907
|
+
GET /v1/diagnostics/wiring response (operator-only). No per-leg history by design.
|
|
12908
|
+
🔴 Every posture key here answers "what can THIS PROCESS say", so its absent form is an explicit
|
|
12909
|
+
`null` — never an empty shell that would read as a real answer. `null` = this process cannot say
|
|
12910
|
+
(it was not assembled by the composition root, or the facility is not wired).
|
|
12236
12911
|
required: [static, serverGates]
|
|
12237
12912
|
additionalProperties: false
|
|
12238
12913
|
properties:
|
|
12239
12914
|
static: { $ref: '#/components/schemas/WiringManifest' }
|
|
12240
12915
|
serverGates: { $ref: '#/components/schemas/ServerWiringGates' }
|
|
12916
|
+
writeProtection:
|
|
12917
|
+
oneOf:
|
|
12918
|
+
- $ref: '#/components/schemas/WriteProtectionPosture'
|
|
12919
|
+
- type: 'null'
|
|
12920
|
+
description: >
|
|
12921
|
+
server >= 7.63.0 (S-138) — the write-protection table, WITH row contents (operator face only; the
|
|
12922
|
+
tenant face `capabilities.writeProtection` carries counts alone). Same boot artefact as that bit.
|
|
12923
|
+
readFace:
|
|
12924
|
+
$ref: '#/components/schemas/ReadFacePosture'
|
|
12925
|
+
description: >
|
|
12926
|
+
server >= 7.65.0 (S-167) — the READ containment rung plus its provenance (`env` / `center` /
|
|
12927
|
+
`posture` / `engine-default`). Absent on older servers; never `null` on 7.65.0+ (the server always
|
|
12928
|
+
has an answer — `face: null` is how "nothing pinned" is spelled, the SOURCE is still known).
|
|
12929
|
+
memoryPosture:
|
|
12930
|
+
type: ["object", "null"]
|
|
12931
|
+
additionalProperties: true
|
|
12932
|
+
description: >
|
|
12933
|
+
server >= 7.30 (#252) — the memory plane's posture (backend / vector mode / lit-or-dark and why /
|
|
12934
|
+
embedder identity). Facts that used to live only in the startup log, which is neither queryable nor
|
|
12935
|
+
aggregatable across replicas. NOT YET MIRRORED KEY-BY-KEY in this SDK generation: declared here so a
|
|
12936
|
+
strict consumer stops rejecting a real operator response, read it as opaque.
|
|
12937
|
+
sqlEngine:
|
|
12938
|
+
type: ["object", "null"]
|
|
12939
|
+
additionalProperties: true
|
|
12940
|
+
description: >
|
|
12941
|
+
server >= 7.60 (S-131) — this deployment's SQL engine posture (engine / version / session isolation
|
|
12942
|
+
level / TiDB transaction mode), READ BACK off a live connection rather than echoed from env.
|
|
12943
|
+
`null` = no SQL backend. NOT YET MIRRORED KEY-BY-KEY in this SDK generation — read as opaque.
|
|
12944
|
+
configApply:
|
|
12945
|
+
type: ["object", "null"]
|
|
12946
|
+
additionalProperties: true
|
|
12947
|
+
description: >
|
|
12948
|
+
server >= 7.5x (#322) — the config generation ledger's operator face (per-group appliedVersion,
|
|
12949
|
+
deferredKeys with their reason, and a SANITISED lastRejected: key names and verdict text only,
|
|
12950
|
+
never values). The three keys on `/health` are a narrow projection of this same reading.
|
|
12951
|
+
NOT YET MIRRORED KEY-BY-KEY in this SDK generation — read as opaque.
|
|
12952
|
+
mcpRevocations:
|
|
12953
|
+
type: ["object", "null"]
|
|
12954
|
+
additionalProperties: true
|
|
12955
|
+
description: >
|
|
12956
|
+
server >= 7.5x (#324, design/338) — the mid-turn MCP revocation list. `null` = this process has no
|
|
12957
|
+
config pipeline (it cannot say). NOT YET MIRRORED KEY-BY-KEY in this SDK generation — read as opaque.
|
|
12241
12958
|
|
|
12242
12959
|
SendfileLinkRow:
|
|
12243
12960
|
type: object
|