@sema-agent/sdk 16.1.0 โ 16.3.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 +111 -1
- package/dist/errors.d.ts +52 -12
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +31 -5
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +8 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/adoption.d.ts +2 -1
- package/dist/resources/adoption.d.ts.map +1 -1
- package/dist/resources/adoption.js +2 -1
- package/dist/resources/adoption.js.map +1 -1
- package/dist/resources/approvals.d.ts +10 -3
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js +11 -3
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/assistant.d.ts +4 -2
- package/dist/resources/assistant.d.ts.map +1 -1
- package/dist/resources/assistant.js.map +1 -1
- package/dist/resources/leader.d.ts +5 -4
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +5 -4
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/memory.d.ts +6 -2
- package/dist/resources/memory.d.ts.map +1 -1
- package/dist/resources/memory.js +3 -1
- package/dist/resources/memory.js.map +1 -1
- package/dist/resources/ops.d.ts +3 -0
- package/dist/resources/ops.d.ts.map +1 -1
- package/dist/resources/ops.js +3 -0
- package/dist/resources/ops.js.map +1 -1
- package/dist/resources/rules.d.ts +4 -3
- package/dist/resources/rules.d.ts.map +1 -1
- package/dist/resources/rules.js +3 -3
- package/dist/resources/rules.js.map +1 -1
- package/dist/resources/runs.d.ts +26 -6
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +9 -2
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +11 -7
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +9 -6
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +9 -3
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +9 -3
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/tasks.d.ts +13 -1
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +13 -1
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +83 -12
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +37 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/resources/workflows.d.ts +5 -2
- package/dist/resources/workflows.d.ts.map +1 -1
- package/dist/resources/workflows.js +5 -2
- package/dist/resources/workflows.js.map +1 -1
- package/dist/settings.d.ts +22 -8
- package/dist/settings.d.ts.map +1 -1
- package/dist/sync.d.ts +19 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +88 -2
- package/dist/sync.js.map +1 -1
- package/dist/types.d.ts +195 -26
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/openapi.yaml +464 -101
- package/package.json +1 -1
package/openapi.yaml
CHANGED
|
@@ -416,7 +416,8 @@ paths:
|
|
|
416
416
|
๐ด PREPARE-TIME REFUSALS ARE TRIAGED ON WORK DONE (server >= 7.104.0 / S-271, one rule for the whole table): a
|
|
417
417
|
prepare-time refusal code that HAS a status in the server's per-code triage table (`resume_at.*` โ `resume_at.not_found` is 404, the rest 422 โ, governance codes,
|
|
418
418
|
`rewind.store_unconfigured` / `rewind.capture_disabled` / `rewind.child_scope_unsupported` / `rewind_snapshot.unresolvable`, the
|
|
419
|
-
registered `config.*` codes incl. the three roster-bound ones
|
|
419
|
+
registered `config.*` codes incl. the three roster-bound ones and โ server >= 7.116.0 โ `config.invalid_checkpoint_store` (400) and
|
|
420
|
+
`config.user_invoked_skill_unknown` (400: top-level `userInvokedSkills` named a skill this run does not carry) and โ server >= 7.117.0 โ `config.image_invalid` (400: an inline image failed the engine's byte admission; `error` starts with `TaskSpec.images: `), `corrupt_session`; codes outside the table, e.g. `rewind.invalid_spec`, stay
|
|
420
421
|
200 with a failed body) answers its 4xx / 5xx ERROR BODY only when the whole submission did ZERO WORK (cumulative
|
|
421
422
|
`stats.turns === 0` AND `stats.tokens === 0` โ the common case: nothing billed, not idempotency-cached). When a
|
|
422
423
|
`verify` / `cascade` run's earlier tier already ran turns and only the last tier is refused, the SAME code arrives
|
|
@@ -885,6 +886,13 @@ paths:
|
|
|
885
886
|
โ ๏ธ Against a server 7.19.0โ7.22.0 the OLD caveat applies verbatim: only the parked legs dedupe โ
|
|
886
887
|
a lost 200 retried with the same key injects TWICE with byte-identical receipts; treat a lost 200
|
|
887
888
|
there as "outcome unknown", never "safe to retry".
|
|
889
|
+
๐ด server >= 7.117.0 โ TWO MORE 409 answers on a TERMINAL run (the `parked_for_wake` leg), refused BEFORE the wake card is minted
|
|
890
|
+
(no card is minted; the row is untouched; on 7.116.x this was a 202 `parked_for_wake` followed by a refusal at `/wake`, i.e. a card that could
|
|
891
|
+
never be redeemed): when the stored submit body of this session is one this version no longer replays โ errorCode
|
|
892
|
+
`checkpoint.unsupported_version` (`retriable: true` = the card is still pending / cancellable, NOT "a retry will succeed"; the stored body carries
|
|
893
|
+
`settings.permissions.allow` under an earlier reading โ list or statement era) or errorCode `resume_blocked_by_policy` (`blockedBy: "request.field_invalid"`;
|
|
894
|
+
the stored skill `disallowedTools` carries an entry the engine now reads as nothing). Both answers are word-for-word the ones `POST /v1/sessions/{sessionId}/wake`
|
|
895
|
+
gives for the same body. Way out: cancel the task and resubmit as a new one (with the entry fixed). The SDK does not retry them (409 is not in the retry set).
|
|
888
896
|
content:
|
|
889
897
|
application/json:
|
|
890
898
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -960,7 +968,8 @@ paths:
|
|
|
960
968
|
un-started ones settle as interrupted pairs, in-flight tools are NOT collateral. TWO shapes,
|
|
961
969
|
discriminated by `text` presence.
|
|
962
970
|
WITH text = cut + steer: the in-flight turn is cut and the text goes to the FRONT of the queue โ the
|
|
963
|
-
`"now"` tier is the VERB's semantics, not a body field (the steer op's `priority`
|
|
971
|
+
`"now"` tier is the VERB's semantics, not a body field (the steer op's own `priority` is a separate
|
|
972
|
+
input: it takes effect only on a server whose `Capabilities.fleet.steerPriority` reads `"engine"`) โ
|
|
964
973
|
and the run CONTINUES. 202 `{taskId, status, delivery:"queued-immediate", messageId, note}`;
|
|
965
974
|
`messageId` โก the engine inputId, and a real cut is proven ONLY by a `task.turn_interrupted` event on
|
|
966
975
|
the run stream whose `detail.inputId` matches it (core: no false interrupt claims โ every real cut
|
|
@@ -2419,9 +2428,10 @@ paths:
|
|
|
2419
2428
|
written. DETERMINISTIC: a retry cannot change it (the SDK does not auto-retry this code; it arrives as a bare `APIError`
|
|
2420
2429
|
with `errorCode: "corrupt"`); the repair is the operator's โ fix the file or delete it (deleting = an explicit "no
|
|
2421
2430
|
rules"). For a damaged rules row `error` names the session, the damage grade and both exits, with NO on-disk path.
|
|
2422
|
-
โ ๏ธ The same code also comes from the write path's high-water-mark sidecar (`.hwm.json`) being unreadable
|
|
2423
|
-
|
|
2424
|
-
|
|
2431
|
+
โ ๏ธ The same code also comes from the write path's high-water-mark sidecar (`.hwm.json`) being unreadable: the sentence names the
|
|
2432
|
+
object, the damage and both exits (fix the mark file, or delete it โ deleting gives up the number it was holding). server >= 7.116.0
|
|
2433
|
+
does NOT name the on-disk path any more (the location goes to the operator log `file_store_corrupt_read` only); server <= 7.115.x
|
|
2434
|
+
still did. Also `internal.error` (unclassified).
|
|
2425
2435
|
content:
|
|
2426
2436
|
application/json:
|
|
2427
2437
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -3039,14 +3049,13 @@ paths:
|
|
|
3039
3049
|
2c session-sync PUSH Phase A โ a SMALL metadata body (`entryIds, snapshots, policy, anchors, resolution?`); the
|
|
3040
3050
|
entries stream in Phase B. The cloud classifies (ยง7), pre-checks blob presence (a missing referenced hash โ
|
|
3041
3051
|
422 `missing_blob` โ PUT it first), guards the import lease + any active run (409), then mints a stagingId.
|
|
3042
|
-
โ ๏ธ S-15 EPOCH
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
โค7.51 truth until that batch lands rather than half-changing.
|
|
3052
|
+
โ ๏ธ S-15 EPOCH: server โฅ7.52's Phase A consumes `{entryIds, fileHistory?, policy, anchors, resolution?,
|
|
3053
|
+
logDigest?}` (routes/session-sync.ts) โ the `snapshots` key is SILENTLY IGNORED there (an unknown body key); the
|
|
3054
|
+
file history rides `fileHistory` (a `FileHistoryExport` envelope, `null` / absent = none) and every blob it references must have been
|
|
3055
|
+
`PUT โฆ/sync/blobs/{hash}` first. โค7.51 servers consume `snapshots` and do not know `fileHistory`. SDK 16.2.0 carries
|
|
3056
|
+
`fileHistory` in `pushSessionBundle` / `importSessionBundle` (and fills `snapshots: []` on the pull side when the manifest omits it); a hand-rolled
|
|
3057
|
+
push must send `fileHistory` itself, and only to a peer whose `capabilities.sessionSyncFileHistory` is not false (server >= 7.116.0 โ else the
|
|
3058
|
+
commit 422s `missing_blob`).
|
|
3050
3059
|
`identical` โ `{ relation:"identical", basis, payloadVerified }` with NO stagingId (skip Phase B);
|
|
3051
3060
|
`basis` is `"entry-ids+digest"` when the caller supplied a comparable digest and it matched, else
|
|
3052
3061
|
`"entry-ids"` (id-set equality only) โ see the `ImportStaged` schema, which has carried these two
|
|
@@ -3063,6 +3072,11 @@ paths:
|
|
|
3063
3072
|
properties:
|
|
3064
3073
|
entryIds: { type: array, items: { type: string } }
|
|
3065
3074
|
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
3075
|
+
fileHistory:
|
|
3076
|
+
oneOf:
|
|
3077
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
3078
|
+
- { type: 'null' }
|
|
3079
|
+
description: 'server >= 7.52: the file-history envelope (replaces `snapshots`); `null` / absent = none. Every blob it references must already be PUT.'
|
|
3066
3080
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
3067
3081
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
3068
3082
|
resolution: { type: string, enum: [overwrite-dst], description: Override a fork/stale loss-of-history conflict. }
|
|
@@ -4639,10 +4653,11 @@ paths:
|
|
|
4639
4653
|
`LEADER_ENABLED` (default OFF) + `REMOTE_EXEC=e2b`. Mode is a SERVER deploy flag, not a client choice:
|
|
4640
4654
|
`LEADER_FANOUT_ENABLED=true` (default) lets the router fan out to N isolated workers (= the value-HOLD
|
|
4641
4655
|
correctness bet); `=false` pins a single worker. Either way it runs the E2B+git pipeline. Door B's brain
|
|
4642
|
-
is the strong single agent via `/v1/tasks`+`/v1/runs`+`scenario`. When
|
|
4643
|
-
the
|
|
4644
|
-
|
|
4645
|
-
|
|
4656
|
+
is the strong single agent via `/v1/tasks`+`/v1/runs`+`scenario`. When there is no leader face on the deployment
|
|
4657
|
+
(`LEADER_ENABLED` off) the answer depends on the server: server >= 7.116.0 mounts the route unconditionally and answers
|
|
4658
|
+
**501 `capability.leader_endpoint_required`** (new code; under multi-tenant the identity gate's 401 still comes first);
|
|
4659
|
+
<= 7.115.x did not register the route at all โ the generic **404** `not_found.route`. Detect "leader unavailable" by
|
|
4660
|
+
`errorCode` (or the `capabilities.leader` bit, which reads the same fact as the gate), not by the status alone.
|
|
4646
4661
|
|
|
4647
4662
|
|
|
4648
4663
|
๐ด IDEMPOTENCY (server >= 7.24.0): this POST now consumes the `Idempotency-Key` header โ the header is
|
|
@@ -4783,7 +4798,8 @@ paths:
|
|
|
4783
4798
|
description: >-
|
|
4784
4799
|
(declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate (not the bare
|
|
4785
4800
|
isOperator, whose empty-OPERATOR_PRINCIPALS "true-for-all" would make this index-mutating door
|
|
4786
|
-
world-writable).
|
|
4801
|
+
world-writable). With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501
|
|
4802
|
+
`capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization).
|
|
4787
4803
|
content:
|
|
4788
4804
|
application/json:
|
|
4789
4805
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4837,7 +4853,7 @@ paths:
|
|
|
4837
4853
|
'400': { $ref: '#/components/responses/BadRequest' }
|
|
4838
4854
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
4839
4855
|
'403':
|
|
4840
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate (ยงP2.4a).
|
|
4856
|
+
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate (ยงP2.4a). With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).
|
|
4841
4857
|
content:
|
|
4842
4858
|
application/json:
|
|
4843
4859
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4891,7 +4907,7 @@ paths:
|
|
|
4891
4907
|
responses:
|
|
4892
4908
|
'200': { description: '{ bake }.', content: { application/json: { schema: { type: object, required: [bake], additionalProperties: false, properties: { bake: { $ref: '#/components/schemas/BakeRecordView' } } } } } }
|
|
4893
4909
|
'403':
|
|
4894
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate.
|
|
4910
|
+
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).
|
|
4895
4911
|
content:
|
|
4896
4912
|
application/json:
|
|
4897
4913
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4909,7 +4925,7 @@ paths:
|
|
|
4909
4925
|
responses:
|
|
4910
4926
|
'202': { description: '{ bakeId, cancelRequested, note }.', content: { application/json: { schema: { $ref: '#/components/schemas/BakeCancelAck' } } } }
|
|
4911
4927
|
'403':
|
|
4912
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate.
|
|
4928
|
+
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).
|
|
4913
4929
|
content:
|
|
4914
4930
|
application/json:
|
|
4915
4931
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4971,7 +4987,7 @@ paths:
|
|
|
4971
4987
|
responses:
|
|
4972
4988
|
'200': { description: 'SSE stream.', content: { text/event-stream: { schema: { type: string } } } }
|
|
4973
4989
|
'403':
|
|
4974
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate (this summary previously did not mention the restriction at all).
|
|
4990
|
+
description: (declared 2026-07-31) errorCode "auth.operator_only" โ EXPLICIT operator gate (this summary previously did not mention the restriction at all). With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).
|
|
4975
4991
|
content:
|
|
4976
4992
|
application/json:
|
|
4977
4993
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -5183,7 +5199,7 @@ paths:
|
|
|
5183
5199
|
schema: { $ref: '#/components/schemas/EntryProvenanceAccount' }
|
|
5184
5200
|
'400': { description: 'errorCode "request.id_invalid" โ the entry id could not be decoded.' }
|
|
5185
5201
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5186
|
-
'403': { description: 'errorCode "auth.operator_only" โ provenance and erasure are operator-only deployment actions.' }
|
|
5202
|
+
'403': { description: 'errorCode "auth.operator_only" โ provenance and erasure are operator-only deployment actions. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5187
5203
|
'500':
|
|
5188
5204
|
description: >
|
|
5189
5205
|
errorCode "internal.memory_control_plane_corrupt" โ core's FAIL-CLOSED refusal: the control plane
|
|
@@ -5253,7 +5269,7 @@ paths:
|
|
|
5253
5269
|
application/json:
|
|
5254
5270
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
5255
5271
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5256
|
-
'403': { description: 'errorCode "auth.operator_only" โ provenance and erasure are operator-only deployment actions.' }
|
|
5272
|
+
'403': { description: 'errorCode "auth.operator_only" โ provenance and erasure are operator-only deployment actions. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5257
5273
|
'409':
|
|
5258
5274
|
description: >
|
|
5259
5275
|
Three core-minted codes, passed through verbatim; branch on `errorCode` (the status cannot tell them
|
|
@@ -5332,7 +5348,7 @@ paths:
|
|
|
5332
5348
|
schema: { $ref: '#/components/schemas/MemoryOriginExternalResult' }
|
|
5333
5349
|
'400': { description: 'errorCode "request.query_invalid" โ `scopes` is absent or normalizes to an empty list. The refusal text also names where scope keys come from and repeats that an empty answer is not a clean store.' }
|
|
5334
5350
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5335
|
-
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions.' }
|
|
5351
|
+
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5336
5352
|
'500':
|
|
5337
5353
|
description: 'errorCode "internal.memory_control_plane_corrupt" (meaning (1) only on this read face) or "internal.error" (unclassified, text not echoed).'
|
|
5338
5354
|
content:
|
|
@@ -5382,7 +5398,7 @@ paths:
|
|
|
5382
5398
|
application/json:
|
|
5383
5399
|
schema: { $ref: '#/components/schemas/MemoryOriginClearancesResult' }
|
|
5384
5400
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5385
|
-
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions.' }
|
|
5401
|
+
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5386
5402
|
'500':
|
|
5387
5403
|
description: 'errorCode "internal.memory_control_plane_corrupt" (the ledger cannot be read soundly) or "internal.error".'
|
|
5388
5404
|
content:
|
|
@@ -5446,7 +5462,7 @@ paths:
|
|
|
5446
5462
|
application/json:
|
|
5447
5463
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
5448
5464
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5449
|
-
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions.' }
|
|
5465
|
+
'403': { description: 'errorCode "auth.operator_only" โ origin marking and clearance are operator-only deployment actions. With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5450
5466
|
'409':
|
|
5451
5467
|
description: >
|
|
5452
5468
|
Six core-minted codes, passed through verbatim; BRANCH ON `errorCode` โ the six operator actions all
|
|
@@ -5569,7 +5585,7 @@ paths:
|
|
|
5569
5585
|
application/json:
|
|
5570
5586
|
schema: { $ref: '#/components/schemas/WiringDiagnostics' }
|
|
5571
5587
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5572
|
-
'403': { description: 'Multi-tenant worker: wiring diagnostics are operator-only (`auth.operator_only`).' }
|
|
5588
|
+
'403': { description: 'Multi-tenant worker: wiring diagnostics are operator-only (`auth.operator_only`). With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501 `capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization โ branch on `errorCode`, not the status).' }
|
|
5573
5589
|
'404': { description: 'This worker serves no wiring diagnostics (older server, or a process not assembled by the composition root).' }
|
|
5574
5590
|
|
|
5575
5591
|
/v1/sendfile-links:
|
|
@@ -5899,7 +5915,9 @@ paths:
|
|
|
5899
5915
|
description: >
|
|
5900
5916
|
OPERATOR-ONLY cross-tenant read. Absent (or equal to the caller's own principal) = read your own
|
|
5901
5917
|
rules. Anything else requires explicit OPERATOR_PRINCIPALS membership โ otherwise 403
|
|
5902
|
-
`auth.operator_only
|
|
5918
|
+
`auth.operator_only` (server >= 7.116.0: with an EMPTY list the answer is 501
|
|
5919
|
+
`capability.operator_principals_required` instead โ any identity, ahead of authorization; your own rules never
|
|
5920
|
+
go through the operator gate). Rule text contains command shapes, so third-party reads are an information
|
|
5903
5921
|
disclosure and are deliberately not opened to non-operators.
|
|
5904
5922
|
- name: scope
|
|
5905
5923
|
in: query
|
|
@@ -6644,7 +6662,14 @@ components:
|
|
|
6644
6662
|
application/json:
|
|
6645
6663
|
schema: { $ref: '#/components/schemas/QuotaError' }
|
|
6646
6664
|
NotImplemented:
|
|
6647
|
-
description:
|
|
6665
|
+
description: >
|
|
6666
|
+
501 โ "this deployment cannot answer this" (e.g. no TiDB run store; `wake` unsupported). server >= 7.116.0: HTTP has exactly ONE status for
|
|
6667
|
+
"unavailable on this deployment" โ 501 โ and the CAUSE is the code: `capability.*` = change the deployment shape / wire the facility
|
|
6668
|
+
(incl. the new `capability.leader_endpoint_required` for `/v1/leader*` and `capability.shared_memory_required` for `/v1/shared-memory/*`),
|
|
6669
|
+
`feature.*` = turn a knob on (incl. the new `feature.memory_consolidation_disabled` and `feature.config_catalog_disabled`), and
|
|
6670
|
+
`capability.operator_principals_required` = configure `OPERATOR_PRINCIPALS` (every operator-only endpoint answers it, for any identity,
|
|
6671
|
+
when the list is empty; a non-empty list the caller is not on is still 403 `auth.operator_only`). Branch on `errorCode`, not the status
|
|
6672
|
+
(these families answered 404 / 403 on <= 7.115.x). The one registered exception is `a2aServe`'s two routes (404, anti-fingerprint).
|
|
6648
6673
|
content:
|
|
6649
6674
|
application/json:
|
|
6650
6675
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -6824,7 +6849,18 @@ components:
|
|
|
6824
6849
|
name: { type: string }
|
|
6825
6850
|
description: { type: string }
|
|
6826
6851
|
content: { type: string }
|
|
6827
|
-
manifest:
|
|
6852
|
+
manifest:
|
|
6853
|
+
type: object
|
|
6854
|
+
additionalProperties: true
|
|
6855
|
+
deprecated: true
|
|
6856
|
+
description: >
|
|
6857
|
+
RETIRED โ server >= 7.116.0 rejects the WHOLE skill when this key is present on a delegated agent's skill (unknown key:
|
|
6858
|
+
`agent.skills must be โฆ`; a top-level skill answers 400 `request.field_invalid` "skill.manifest was retired in core 7.41.0 โ โฆ").
|
|
6859
|
+
core 7.41.0 retired the skill manifest (hard break, no alias). Rewrite `manifest.allowTools` to the skill's
|
|
6860
|
+
`allowedTools` (an allow-rule source, not a fence); `manifest.allowPaths` has no replacement (use the session rules'
|
|
6861
|
+
`allowDirs`). Older servers (<= 7.115.x) still accept it; the key stays declared here until the next major.
|
|
6862
|
+
allowedTools: { type: array, items: { type: string }, description: 'server >= 7.116.0 โ the skill''s allow-rule source (see `SkillSpec.allowedTools`); <= 7.115.x rejects the key (unknown key).' }
|
|
6863
|
+
disallowedTools: { type: array, items: { type: string }, description: 'server >= 7.116.0 โ the skill''s deny-rule source (see `SkillSpec.disallowedTools`); <= 7.115.x rejects the key (unknown key).' }
|
|
6828
6864
|
files:
|
|
6829
6865
|
type: array
|
|
6830
6866
|
items:
|
|
@@ -6933,6 +6969,18 @@ components:
|
|
|
6933
6969
|
LISTING RENDERER, not to this gate: turn it down with `settings.skillListingBudgetFraction` /
|
|
6934
6970
|
`settings.skillListingMaxDescChars`.
|
|
6935
6971
|
items: { $ref: '#/components/schemas/SkillSpec' }
|
|
6972
|
+
userInvokedSkills:
|
|
6973
|
+
type: array
|
|
6974
|
+
items: { type: string, minLength: 1 }
|
|
6975
|
+
description: >
|
|
6976
|
+
server >= 7.116.0 (core 7.41.0 #1303). Skills the HUMAN called by name (the shell parses the typed `/name`; by `SkillSpec.name`).
|
|
6977
|
+
Their `allowedTools` / `disallowedTools` take effect from the start of the run and NO `Skill` card is raised (the human naming
|
|
6978
|
+
it is the statement); it governs this one run only (a steer does not end it; the next submit does not carry it). Every name must be
|
|
6979
|
+
a skill the run carries (scenario factory โช this request's `skills`), else the engine refuses to start: 400
|
|
6980
|
+
`config.user_invoked_skill_unknown` (sync leg `POST /v1/tasks`; the async / live-stream legs answer 2xx and the same code lands on the
|
|
6981
|
+
terminal run row; `disableSkills: true` makes any name this code). A bad value shape (bare string / empty-string member / non-string /
|
|
6982
|
+
object / null) is a 400 `request.field_invalid`. Does not deliver the skill body. PROBE `capabilities.userInvokedSkills` (constant true);
|
|
6983
|
+
absent = an older server that answers 400 `request.body_shape` listing the key in `unknownKeys` โ do not send it.
|
|
6936
6984
|
reasoningEffort:
|
|
6937
6985
|
type: string
|
|
6938
6986
|
enum: [off, minimal, low, medium, high, xhigh, max]
|
|
@@ -7146,6 +7194,13 @@ components:
|
|
|
7146
7194
|
description: 'core 5.11.0: extra READ-ONLY absolute host paths โ read fence only (classify read-boundary auto-allow + read_file/grep containment); writes to the same dirs are still refused. Same shape/400 rules as additionalDirectories; servers <6.6.0 silently ignore (harmless additive).'
|
|
7147
7195
|
images:
|
|
7148
7196
|
type: array
|
|
7197
|
+
description: >
|
|
7198
|
+
Image input: `{ data, mimeType }` (inline base64) or `{ url }`. ๐ด INLINE-ARM ADMISSION (server >= 7.117.0 / core 7.42.0): `mimeType` must be one of `image/png` /
|
|
7199
|
+
`image/jpeg` / `image/gif` / `image/webp` (the API's type word, not a file extension), the decoded bytes must carry the DECLARED type's file signature, and the decoded size must
|
|
7200
|
+
not exceed 5 MiB โ otherwise the engine refuses BEFORE the first model call (after the UserPromptSubmit hook; not one model token spent) with 400 `config.image_invalid`, whose
|
|
7201
|
+
`error` starts with `TaskSpec.images: `. Before 7.117.0 such an image was sent as-is to the model provider and the whole first request failed there (no code to branch on).
|
|
7202
|
+
A base64 string longer than 5 242 880 characters (the model API's 5 MB image cap; the server reads the engine's exported constant) is NOT this code: the submit gate refuses it first
|
|
7203
|
+
with 413 `request.payload_too_large` (zero model calls, no submit hook, no run row). The `{ url }` arm is unchanged. The model must accept image input (`ModelInfo.vision`; absent = unknown, send anyway).
|
|
7149
7204
|
items:
|
|
7150
7205
|
oneOf:
|
|
7151
7206
|
- type: object
|
|
@@ -7289,9 +7344,20 @@ components:
|
|
|
7289
7344
|
the delivery lane, so raising it only helps a model whose declared window is below 200 000 tokens.
|
|
7290
7345
|
The engine's own twin code `config.skill_listing_budget_invalid` (400) is NOT reachable through this
|
|
7291
7346
|
submit leg today โ it belongs to callers that build a `TaskSpec` directly.
|
|
7292
|
-
๐ด `permissions.allow`
|
|
7293
|
-
|
|
7294
|
-
|
|
7347
|
+
๐ด `permissions.allow` โ THE READING DEPENDS ON THE SERVER GENERATION (probe `capabilities.settings.permissions`; an absent bit = the older generation).
|
|
7348
|
+
server >= 7.117.0 (`allowLayer === true`, core 7.42.0): the WHOLE list goes to the engine's allow layer and a listed call is NOT ASKED โ the engine's ordinary and
|
|
7349
|
+
"nobody stated it" questions are cleared, built-in write gates and shell checks included (like the reference implementation's `permissions.allow`); content forms
|
|
7350
|
+
(`Bash(git:*)`, `Read(//dir/**)`) are accepted; entries the engine reads as nothing (`*`, write-path forms such as `Edit(src/**)`, domain forms, names with whitespace) are NOT
|
|
7351
|
+
refused โ the run opens with an `engine_notice` `permission.allowed_tool_not_granted`. Any layer's deny / ask rule, operator `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` /
|
|
7352
|
+
`MANUAL_MODE_SHELL_GATE=always`, write protection, governance, a hook's ask and plan-mode asks still ask (a matching `request` member then shows as `allowRuleShadowed` on the
|
|
7353
|
+
card). The submit gate judges only the shape (array of strings, at most 1000 entries => 400) and the NAMES (the same judge and the same sentence as `deny` / `ask`: a retired name,
|
|
7354
|
+
an unprefixed short name, or a protocol name whose server segment cannot be minted / is missing / is a wildcard (`mcp__*`) is a whole-request 422) โ never the content.
|
|
7355
|
+
๐ด THE 422 SENTENCE (server >= 7.117.0): `error` starts with `request settings cannot be applied as written: ` (<= 7.116.x: a different sentence that said tighten-only โ all three
|
|
7356
|
+
buckets share this exit, and the old head misled a caller writing a tightening rule and lied about the allow bucket). Do NOT dispatch on the sentence: it carries no code of its own, so
|
|
7357
|
+
`errorCode` is the status-derived coarse code `request.unprocessable`.
|
|
7358
|
+
The skill lists (`skills[].allowedTools`) read exactly like this bucket from 7.117.0 on.
|
|
7359
|
+
Server 7.115.0โ7.116.x (`allowGrant` without `allowLayer`): `permissions.allow` IS A STATEMENT, NOT A WHITELIST โ an absent `allowGrant` is a server <= 7.114.x that reads the bucket
|
|
7360
|
+
as a list, so put nothing in it there. The bucket is compiled by the SAME rule compiler as `deny` / `ask`: a hit is a
|
|
7295
7361
|
reasoned allow = "somebody stated it" (it answers an MCP / A2A server-tool call nobody stated; without it an
|
|
7296
7362
|
ask-class mode raises a card, and with no approval surface the call is refused); a miss states nothing and the call is
|
|
7297
7363
|
judged as usual โ a tool off the list is NOT refused any more (<= 7.114.x refused it). It does NOT skip the question
|
|
@@ -7300,8 +7366,11 @@ components:
|
|
|
7300
7366
|
for that). For "only these tools" use the real knobs: the session rule `toolAllow`
|
|
7301
7367
|
(`PUT /v1/sessions/{sessionId}/policy`), per-request `excludeTools` / `excludeAllTools`, or the deployment's scenario
|
|
7302
7368
|
tool surface. Entry forms: a tool-name rule (exact name, `mcp__<server>__*`, `a2a__<peer>__*`; `Bash(*)` is accepted
|
|
7303
|
-
and compiled as a whole-tool rule
|
|
7304
|
-
|
|
7369
|
+
and compiled as a whole-tool rule; server >= 7.116.0 also accepts the two-segment covering form `mcp__<server>` / `a2a__<peer>`,
|
|
7370
|
+
read as the whole server โ same meaning as `mcp__<server>__*`); a retired name, a short name with no protocol prefix, a missing-segment
|
|
7371
|
+
name (`mcp__` / `mcp__<server>__`), a protocol name whose server segment the engine cannot have minted (e.g. `mcp__github.com__*` โ
|
|
7372
|
+
write `mcp__github_com__*`; server >= 7.116.0 refuses it with a 422 instead of accepting a rule that can never match), a backslash,
|
|
7373
|
+
more than 512 characters, or a CONTENT form
|
|
7305
7374
|
(`Bash(npm:*)`, `Read(./x)`, `WebFetch(domain:...)`) is a whole-request 422 (permanent content-form allows live in the
|
|
7306
7375
|
persistent rule store: `/v1/rules/cc-import`, or answer yes on a card). The same applies to a PreToolUse hook: an
|
|
7307
7376
|
EXPLICIT `permissionDecision: "allow"` states it (and binds only the arguments the hook saw); a hook that only adds
|
|
@@ -8218,6 +8287,16 @@ components:
|
|
|
8218
8287
|
is unchanged at 7.64.0 โ only its source moved (projected from `result.terminal`, or read straight
|
|
8219
8288
|
off a legacy flat blob). โ ๏ธ K-24 / S-173 (server >= 7.104.0): on a `needs_review` PARK row it is core's canonical
|
|
8220
8289
|
`review.pending` (absent before) โ never read "errorCode present" as "failed"; read `status` first.
|
|
8290
|
+
๐ด server >= 7.116.0 (S-1099) adds three values for the run store's own terminal verdicts, which used to live only in the `error`
|
|
8291
|
+
sentence: `run.stalled` (heartbeat-lost reap โ and the read-time fold that precedes the reap; sentence `run stalled (instance lost?)`),
|
|
8292
|
+
`run.orphaned` (local-lane restart / session-occupancy takeover reclaim; sentence `run orphaned by engine restart`) and
|
|
8293
|
+
`approval.expired` (the expiry reap of a durably parked approval; the column already carried it, the read face did not project it;
|
|
8294
|
+
sentence `approval expired before decision`). None of the three means the request was wrong โ resending the same request is
|
|
8295
|
+
pointless, only a new submission makes a new run. READ `status` FIRST (`failed`), then branch on the code. Open set (a string; always keep a
|
|
8296
|
+
default arm). ABSENCE: rows written by <= 7.115.x carry only the sentence; a one-time startup migration backfills the code
|
|
8297
|
+
(log `one_time_migrations_applied` `holderDeathCodeRowsBackfilled`) and a new replica reads such a row as the code during the upgrade window,
|
|
8298
|
+
but the migration has a window (30 days after the release, then the write-back and the read half are deleted) โ so
|
|
8299
|
+
"no `errorCode`" never proves "not a holder death": rows migrated late or after the window stay sentence-only.
|
|
8221
8300
|
error: { type: string }
|
|
8222
8301
|
jobId:
|
|
8223
8302
|
type: string
|
|
@@ -9029,7 +9108,8 @@ components:
|
|
|
9029
9108
|
server >=7.12.0 โ the `GET /v1/outcomes` mechanical-signal read aggregate (design/73 ยง7.2) is
|
|
9030
9109
|
available. Predicate mirrors the route's refusal arms exactly: a QUERYABLE ledger is wired (a
|
|
9031
9110
|
file-only sink writes JSONL and has no query face โ 501), AND on a multi-tenant deployment the
|
|
9032
|
-
operator list is non-empty (single-user has no such gate โ the only user IS the operator)
|
|
9111
|
+
operator list is non-empty (single-user has no such gate โ the only user IS the operator); with an empty
|
|
9112
|
+
list the multi-tenant route answers 501 `capability.operator_principals_required` (server >= 7.116.0; 403 before).
|
|
9033
9113
|
Added because this face previously had a 501 but NO capability bit, leaving consumers to
|
|
9034
9114
|
trial-by-501 โ the exact pattern this capability surface exists to remove.
|
|
9035
9115
|
images:
|
|
@@ -9053,7 +9133,17 @@ components:
|
|
|
9053
9133
|
principalโorg membership fold present), so true โบ the face actually works โ a deployment with
|
|
9054
9134
|
the store but no membership authority deliberately reports false (and does not mount the routes).
|
|
9055
9135
|
workflows: { type: boolean, description: "ENGINE-CAN: this worker's engine can orchestrate S8 self-orchestration workflows (server: `workflowsCapable ?? Boolean(workflowRunStore)`). The MOUNTING of the durable /v1/workflows read routes is the separate `workflowsList` bit below; the two coincide in today's wiring but are declared as orthogonal axes." }
|
|
9056
|
-
workflowsList: { type: boolean, description: "`GET /v1/workflows` list
|
|
9136
|
+
workflowsList: { type: boolean, description: "`GET /v1/workflows` list / detail / stream faces (the workflow run store is wired; separate from the per-run reads). server >= 7.116.0: the journal face `GET /v1/workflows/{id}/journal` is advertised by the new bit `workflowsJournal`, not by this one (value unchanged)." }
|
|
9137
|
+
workflowsJournal:
|
|
9138
|
+
type: boolean
|
|
9139
|
+
description: >
|
|
9140
|
+
server >= 7.116.0 (predicate class "facility": the workflow run store AND the journal store). Advertises
|
|
9141
|
+
`GET /v1/workflows/{id}/journal`. On a deployment with the run store but no journal store (`DB_BACKEND=memory`,
|
|
9142
|
+
multi-tenant bare boot, SQL coordinates not fully configured) with self-orchestration on, `workflowsList` is true
|
|
9143
|
+
and this is false; the journal face then answers 501 `capability.workflow_store_required` (any id, ahead of the
|
|
9144
|
+
per-row owner check; `capability.self_orchestration_required` when the run store is absent). A journal entry point reads THIS bit, not
|
|
9145
|
+
`workflowsList`. ABSENT = an older server (<= 7.115.x): fall back to `workflowsList` (the old behaviour โ the
|
|
9146
|
+
bit could be true while the journal face always answers 501).
|
|
9057
9147
|
workflowModels:
|
|
9058
9148
|
type: array
|
|
9059
9149
|
items: { type: string }
|
|
@@ -9096,8 +9186,8 @@ components:
|
|
|
9096
9186
|
(DESIGN-278 ยง5 S2 โ deployment config self-description) is mounted on this DEPLOYMENT. TWO-term
|
|
9097
9187
|
conjunction, written against the route's own refusal arms: โ the `CONFIG_CATALOG_ENABLED` knob is
|
|
9098
9188
|
on (default on; a compliance deployment that turns it off makes the path a 404 โ the valve-family
|
|
9099
|
-
precedent) AND โก the operator principal list is NON-EMPTY (with an empty list the route
|
|
9100
|
-
identity). ๐ด DEPLOYMENT-LEVEL AVAILABILITY, NOT THE CALLER'S AUTHORIZATION: the caller's own
|
|
9189
|
+
precedent; server >= 7.116.0 answers 501 `feature.config_catalog_disabled` there, 404 before) AND โก the operator principal list is NON-EMPTY (with an empty list the route refuses every
|
|
9190
|
+
identity โ 501 `capability.operator_principals_required` on server >= 7.116.0, 403 before). ๐ด DEPLOYMENT-LEVEL AVAILABILITY, NOT THE CALLER'S AUTHORIZATION: the caller's own
|
|
9101
9191
|
identity is NOT in the predicate โ the route additionally requires the CURRENT principal to be an
|
|
9102
9192
|
explicit operator (`routes/config-catalog.ts` `explicitOperatorOk`, else 403 `auth.operator_only`),
|
|
9103
9193
|
so a non-operator reads `true` and still gets 403. Show/invoke the catalog only for an identity you
|
|
@@ -9117,8 +9207,15 @@ components:
|
|
|
9117
9207
|
`false`/absent otherwise (same predicate as the route's 501). `resume: "snapshot"` is a semantic
|
|
9118
9208
|
advertisement: the bus is latest-state (not an event log) and every connection opens with a full
|
|
9119
9209
|
snapshot frame, so reconnect = re-snapshot (deliberately no last-event-id cursor); transient
|
|
9120
|
-
bg_notification frames re-deliver via the durable completion inbox. `steerPriority
|
|
9121
|
-
|
|
9210
|
+
bg_notification frames re-deliver via the durable completion inbox. `steerPriority` (a string, open
|
|
9211
|
+
set) says whether the steer body's `priority` takes effect on THIS server: `steerPriority: "advisory"`
|
|
9212
|
+
(server <=7.115.x) = accepted + enum-validated + echoed but a no-op (nothing is handed to the engine);
|
|
9213
|
+
`steerPriority: "engine"` (server >=7.116.0) = `priority` (`now` / `next` / `later`) is handed to the
|
|
9214
|
+
engine as the injection tier, and the engine owns what each tier means โ `now` cuts the in-flight turn
|
|
9215
|
+
IMMEDIATELY (the running tool receives an abort, an approval card pending on this replica is revoked; one `engine_notice`
|
|
9216
|
+
`task.turn_interrupted` frame is the evidence), `later` is delivered after the turn the run would have stopped on, no `priority` =
|
|
9217
|
+
`next`. Read this bit before offering a `priority` choice; an absent
|
|
9218
|
+
or unknown value means "do not assume it takes effect", never `"engine"`.
|
|
9122
9219
|
oneOf:
|
|
9123
9220
|
- type: boolean
|
|
9124
9221
|
enum: [false]
|
|
@@ -9342,22 +9439,28 @@ components:
|
|
|
9342
9439
|
settings:
|
|
9343
9440
|
type: object
|
|
9344
9441
|
description: >
|
|
9345
|
-
๐ด server >= 7.115.0
|
|
9346
|
-
server give `settings.permissions.allow` on a task submit"
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
`
|
|
9353
|
-
(
|
|
9442
|
+
๐ด server >= 7.115.0, ALWAYS present: `{ permissions: { allowGrant: true } }`; server >= 7.117.0 adds `allowLayer: true` to `permissions` โ the VERSION bits for
|
|
9443
|
+
"which reading does this server give `settings.permissions.allow` on a task submit" (both constant `true`, never vary with the deployment: the single-user
|
|
9444
|
+
and `REQUIRE_PRINCIPAL=true` forms carry the same value). Read three levels: `settings` -> `permissions` -> <bit>; an absent / non-boolean bit = a server without it.
|
|
9445
|
+
`permissions.allowGrant === true` (>= 7.115.0) = the `allow` bucket is read as allow RULES, not as a list (a tool off the list is no longer refused).
|
|
9446
|
+
`permissions.allowLayer === true` (>= 7.117.0, core 7.42.0) = the server hands the WHOLE `allow` list to the engine's allow layer: a listed call is NOT ASKED (the engine's
|
|
9447
|
+
ordinary and "nobody stated it" questions are cleared โ built-in write gates / shell checks included, like the reference implementation's `permissions.allow`); content forms
|
|
9448
|
+
(`Bash(git:*)`, `Read(//dir/**)`) are accepted; entries the engine reads as nothing (`*`, write-path / domain forms, names with whitespace) are NOT refused โ the run opens with an
|
|
9449
|
+
`engine_notice` `permission.allowed_tool_not_granted`; any layer's deny / ask rule, operator `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell floor / write protection /
|
|
9450
|
+
governance, a hook's ask and plan-mode asks still ask (a matching member then shows as `allowRuleShadowed` on the card). The submit gate judges only the shape and the NAMES (retired
|
|
9451
|
+
name / unprefixed short name / unmintable protocol server segment => 422, at most 1000 entries => 400) โ never the content.
|
|
9452
|
+
๐ด ABSENT `allowLayer` with `allowGrant` present = a 7.115.0โ7.116.x server: allow is a STATEMENT (it does not clear the engine's own write gate / shell checks; a content form
|
|
9453
|
+
is a whole-request 422). ABSENT KEY altogether (no `settings`) = an older server (<= 7.114.x), which read `allow` as a WHITELIST (everything off the list refused) โ do not put
|
|
9454
|
+
anything in the allow bucket there. NOT the same bit as `taskSettings.permissions` (unchanged, still a boolean: "this server accepts the `settings.permissions` face"). The
|
|
9455
|
+
deployment-level "who stated what" (operator env `APPROVAL_GRANT`) is on the operator diagnostics face (`serverGates.approvalGrant`), not here.
|
|
9354
9456
|
additionalProperties: true
|
|
9355
9457
|
properties:
|
|
9356
9458
|
permissions:
|
|
9357
9459
|
type: object
|
|
9358
9460
|
additionalProperties: true
|
|
9359
9461
|
properties:
|
|
9360
|
-
allowGrant: { type: boolean, description: 'Constant `true` on server >= 7.115.0: `settings.permissions.allow` is read as allow RULES
|
|
9462
|
+
allowGrant: { type: boolean, description: 'Constant `true` on server >= 7.115.0: `settings.permissions.allow` is read as allow RULES, not as a list. The whole `settings` key being absent = an older server.' }
|
|
9463
|
+
allowLayer: { type: boolean, description: 'Constant `true` on server >= 7.117.0 (core 7.42.0): the whole `settings.permissions.allow` list goes to the engine allow layer (listed calls are not asked; content forms accepted; entries read as nothing get an `engine_notice` `permission.allowed_tool_not_granted`). Absent = a server without it (7.115.0โ7.116.x: allow is a statement; older: a list).' }
|
|
9361
9464
|
memoryWrite:
|
|
9362
9465
|
type: boolean
|
|
9363
9466
|
description: >
|
|
@@ -9373,9 +9476,25 @@ components:
|
|
|
9373
9476
|
S-15 ๆขๅบ; โค7.51 the last conjunct was the file-snapshot store). Gate the whole sync surface off
|
|
9374
9477
|
this. โ ๏ธ The two BLOB faces (PUT โฆ/sync/blobs/{hash}, GET โฆ/sync/history/blobs/{hash})
|
|
9375
9478
|
additionally need the store's blob faces (`syncBlobFaces` โ the SQL/cloud backends; the local
|
|
9376
|
-
file backend has none): without them
|
|
9377
|
-
|
|
9378
|
-
surface keeps working.
|
|
9479
|
+
file backend has none): without them BOTH answer 501 `capability.snapshot_store_required`
|
|
9480
|
+
(server >= 7.116.0; the history PULL answered a no-oracle 404 `not_found.blob` there on <= 7.115.x),
|
|
9481
|
+
while the REST of the sync surface keeps working. Since server >= 7.116.0 the two blob faces are
|
|
9482
|
+
advertised by their own bit `sessionSyncFileHistory`; this bit speaks for the conversation half
|
|
9483
|
+
(its predicate additionally requires a session-policy store that can purge, `deleteBySession` โ
|
|
9484
|
+
a deployment whose embedder-supplied store lacks it answers the whole family 501
|
|
9485
|
+
`capability.policy_purge_required` and this bit is false).
|
|
9486
|
+
sessionSyncFileHistory:
|
|
9487
|
+
type: boolean
|
|
9488
|
+
description: >
|
|
9489
|
+
server >= 7.116.0 (predicate class "facility": `sessionSync` AND the file-history store has blob transfer faces
|
|
9490
|
+
โ SQL backends only; `DB_BACKEND=local` is always false). Advertises exactly the two file-history blob faces
|
|
9491
|
+
`PUT /v1/sessions/{sessionId}/sync/blobs/{hash}` and `GET /v1/sessions/{sessionId}/sync/history/blobs/{hash}`.
|
|
9492
|
+
READ IT ON BOTH ENDS of a sync: if either is false, sync the conversation only โ do not push `fileHistory`, do
|
|
9493
|
+
not PUT blobs (a `fileHistory` pushed to a peer without the blob faces 422s `missing_blob` after commit). When
|
|
9494
|
+
false the two routes answer 501 `capability.snapshot_store_required` (any session id, ahead of the owner check).
|
|
9495
|
+
A blob that the session history graph does not reference / whose bytes are gone stays a 404 `not_found.blob`.
|
|
9496
|
+
ABSENT = an older server (<= 7.115.x): the bit cannot be read there (a `DB_BACKEND=local` deployment with
|
|
9497
|
+
`sessionSync: true` answered PUT blob 501 on every call), so try as before.
|
|
9379
9498
|
|
|
9380
9499
|
# โโโ S-139(sdk 8.3.0):ๅฏน server 7.60.0 ็ๆดไฝ้ๅฏน่ดฆ่กฅ้ฝ็ 19 ไฝ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
9381
9500
|
# ่กๅท = server 7.60.0 ๆ ็ `src/http/routes/capabilities.ts`ใ่ฏญไนไธ่ฐ่ฏ็ๅ
จๆๅจ
|
|
@@ -9468,7 +9587,8 @@ components:
|
|
|
9468
9587
|
description: >
|
|
9469
9588
|
Governance carry-out bundle pair `POST /v1/memory/{export,import}` (operator lane) โ
|
|
9470
9589
|
capabilities.ts:261, two conjuncts: both engine seams wired AND `operatorPrincipals` NON-EMPTY
|
|
9471
|
-
(an empty roster makes those routes
|
|
9590
|
+
(an empty roster makes those routes refuse every identity โ 501 `capability.operator_principals_required` on
|
|
9591
|
+
server >= 7.116.0, 403 before). True does not promise the backend
|
|
9472
9592
|
has the bundle composite face (core then refuses loudly with `memory.export_incomplete`).
|
|
9473
9593
|
memoryCompliance:
|
|
9474
9594
|
type: boolean
|
|
@@ -9570,10 +9690,13 @@ components:
|
|
|
9570
9690
|
a2aServe:
|
|
9571
9691
|
type: boolean
|
|
9572
9692
|
description: >
|
|
9573
|
-
Server-as-peer
|
|
9574
|
-
`
|
|
9575
|
-
|
|
9576
|
-
|
|
9693
|
+
Server-as-peer: true โบ `GET /.well-known/agent-card.json` and `POST /v1/a2a` exist; false โบ both 404
|
|
9694
|
+
(`not_found.route`, anti-fingerprint โ the one registered exception to "unavailable = 501"). server >= 7.116.0
|
|
9695
|
+
predicate (class "facility + config"): the `A2A_SERVE_ENABLED` knob AND a durable run store; <= 7.115.x looked at the knob
|
|
9696
|
+
only (`config.a2aServe !== undefined`). ๐ด value change: with the knob on but NO durable run store
|
|
9697
|
+
(`DB_BACKEND=memory`, multi-tenant bare boot) this bit is now false and the card and the RPC both answer 404 (7.115.x:
|
|
9698
|
+
true, card 200, every `message/send` / `tasks/get` a JSON-RPC `-32004`); the startup log carries a warn
|
|
9699
|
+
`a2a_serve_not_served`. The old "the server deliberately does not fold the run store into this bit" note is retired.
|
|
9577
9700
|
agentRoster:
|
|
9578
9701
|
type: boolean
|
|
9579
9702
|
description: >
|
|
@@ -9768,6 +9891,23 @@ components:
|
|
|
9768
9891
|
answers the request key with a 400 `request.body_shape` naming it under `unknownKeys` โ do not send the key
|
|
9769
9892
|
there and tell the user the factory skills stay installed. True only says "this server knows the key", not
|
|
9770
9893
|
whether the deployment has any factory skills.
|
|
9894
|
+
userInvokedSkills:
|
|
9895
|
+
type: boolean
|
|
9896
|
+
enum: [true]
|
|
9897
|
+
description: >
|
|
9898
|
+
server >= 7.116.0 (constant true; no predicate, no tenant gate) โ the ADVANCE READING for the request key
|
|
9899
|
+
`TaskRequest.userInvokedSkills` (skills the human named; effective from the start of the run, no `Skill` card);
|
|
9900
|
+
the bit and the key are the SAME word. ABSENT = an older server (<= 7.115.x), which answers the key with a 400
|
|
9901
|
+
`request.body_shape` naming it under `unknownKeys` โ do not send it there.
|
|
9902
|
+
skillToolLists:
|
|
9903
|
+
type: boolean
|
|
9904
|
+
enum: [true]
|
|
9905
|
+
description: >
|
|
9906
|
+
server >= 7.116.0 (constant true) โ the skill tool lists `allowedTools` / `disallowedTools` TAKE EFFECT (allow-rule /
|
|
9907
|
+
deny-rule source; see `SkillSpec.allowedTools`). ABSENT = an older server (<= 7.115.x): on a top-level skill the two
|
|
9908
|
+
lists are accepted but the engine does not read them โ they are silently inert and there is NO 400 to probe, so do not
|
|
9909
|
+
expect them to stop a tool (fence with deny rules instead); on a delegated agent's skill they are an unknown key that
|
|
9910
|
+
rejects the whole skill.
|
|
9771
9911
|
WriteProtectionCapability:
|
|
9772
9912
|
type: object
|
|
9773
9913
|
additionalProperties: false
|
|
@@ -9902,11 +10042,50 @@ components:
|
|
|
9902
10042
|
engine refuses the skill outright at load time, so the HTTP face answers first where the caller can read it).
|
|
9903
10043
|
The bound is 1 048 576 **UTF-16 code units** (`MAX_SKILL_CONTENT_CHARS`); see the STRING-LENGTH UNIT
|
|
9904
10044
|
convention in `info.description` for why this `maxLength` states that number verbatim.
|
|
10045
|
+
๐ด server >= 7.116.0 (core 7.41.0): a skill carries two TOOL LISTS, `allowedTools` / `disallowedTools` โ the
|
|
10046
|
+
run-scoped ALLOW-RULE and DENY-RULE source of the skill once it is activated. NOT a fence (<= 7.115.x the engine read
|
|
10047
|
+
the skill's tool list as "only these"): unlisted tools are judged as usual, listed ones are not asked about for the rest
|
|
10048
|
+
of the run. On server 7.116.x that made it WIDER than `settings.permissions.allow` (then a statement that did not
|
|
10049
|
+
release the engine's own write gate / shell ordinary asks on built-in tools); server >= 7.117.0 reads the two request-level
|
|
10050
|
+
allow sources the SAME way (see `capabilities.settings.permissions.allowLayer`). Probe `capabilities.skillToolLists`
|
|
10051
|
+
(absent = an old server that accepts the keys on a top-level skill and silently ignores them). The skill's `manifest`
|
|
10052
|
+
key is RETIRED: any value on a top-level skill is a 400 `request.field_invalid` ("skill.manifest was retired in core
|
|
10053
|
+
7.41.0 โ โฆ"; rewrite `manifest.allowTools` to `allowedTools`; `allowPaths` has no replacement), and on a delegated
|
|
10054
|
+
agent's skill (`agents[].skills[]`) it is an unknown key that rejects the whole skill.
|
|
9905
10055
|
required: [name, description, content]
|
|
9906
10056
|
properties:
|
|
9907
10057
|
name: { type: string, minLength: 1 }
|
|
9908
10058
|
description: { type: string }
|
|
9909
10059
|
content: { type: string, minLength: 1, maxLength: 1048576 }
|
|
10060
|
+
allowedTools:
|
|
10061
|
+
type: array
|
|
10062
|
+
items: { type: string }
|
|
10063
|
+
description: >
|
|
10064
|
+
server >= 7.116.0. The skill's run-scoped ALLOW-RULE source (permission-rule spellings: a tool name,
|
|
10065
|
+
`mcp__<server>` / `mcp__<server>__*`; `*`, write paths and domain forms grant nothing). Once the skill is activated
|
|
10066
|
+
(named in top-level `userInvokedSkills` โ no `Skill` card โ or activated by the model and the card approved) the
|
|
10067
|
+
listed tools are not asked about for the rest of the run: it clears the engine's ordinary and "nobody stated it" asks;
|
|
10068
|
+
deny / ask rules, `APPROVAL_REQUIRE`, `APPROVAL_NEVER_AUTO`, the shell floor, write protection and plan-mode asks are not cleared.
|
|
10069
|
+
NOT a fence: unlisted tools are judged as usual. Versus `settings.permissions.allow`: on server 7.116.x this list was WIDER (that bucket
|
|
10070
|
+
was then only a statement); server >= 7.117.0 reads the two the SAME way, entry for entry (entries the engine reads as nothing get an
|
|
10071
|
+
`engine_notice` `permission.allowed_tool_not_granted`). A non-string-array is a 400 `request.field_invalid`; a protocol name whose server
|
|
10072
|
+
segment cannot be minted / is missing / is a wildcard (`mcp__*`) is a 400 too, and from 7.117.0 so is a retired name / unprefixed short
|
|
10073
|
+
name (the name layer is judged by the same judge as the allow bucket) and a list of more than 1000 entries (top-level `skills[]` and
|
|
10074
|
+
`agents[].skills[]` judge identically). Probe `capabilities.skillToolLists`.
|
|
10075
|
+
disallowedTools:
|
|
10076
|
+
type: array
|
|
10077
|
+
items: { type: string }
|
|
10078
|
+
description: >
|
|
10079
|
+
server >= 7.116.0. The skill's run-scoped DENY-RULE source (same grammar / gates / probe as `allowedTools`): once the skill
|
|
10080
|
+
is activated these tools are refused for the run (no execution, no card; `tool_end.gate.disposition` is
|
|
10081
|
+
`{ kind: "denied", deniedBy: "policy" }`); write-path forms and command rules compile into deny rows too.
|
|
10082
|
+
๐ด server >= 7.117.0: an entry the engine reads as nothing (`*`, a domain form `WebFetch(domain:โฆ)`, a protocol name with a wildcard, a name with
|
|
10083
|
+
whitespace or malformed) is refused AT SUBMIT โ 400 `request.field_invalid`, `error` = `skill.disallowedTools entry "<entry>" reads as nothing (<reason>): <how to write it>`
|
|
10084
|
+
(delegated level: prefix `agents[<i>]: skills[<j>]: `), top-level `skills[]` and `agents[].skills[]` alike โ because an entry that looks like a refusal but refuses nothing is
|
|
10085
|
+
worse than none (<= 7.116.x accepted it with only an operator-audience notice that was not sent to the session stream; that code is now `permission.allowed_tool_not_granted`,
|
|
10086
|
+
user audience, on the session stream). ๐ด The resume legs judge the stored body the same way: a parked task whose stored skill `disallowedTools` carries such an entry answers
|
|
10087
|
+
409 `resume_blocked_by_policy` (`blockedBy: "request.field_invalid"`, same sentence) BEFORE the claim โ row and card untouched; a terminal run's `POST /v1/runs/{taskId}/steer`
|
|
10088
|
+
answers it before minting the wake card. Why: engine 7.41 trimmed whitespace (`"Bash "` was a working deny), engine 7.42 reads verbatim (reads as nothing). The allow side does not refuse.
|
|
9910
10089
|
|
|
9911
10090
|
McpServerSpec:
|
|
9912
10091
|
type: object
|
|
@@ -10648,16 +10827,17 @@ components:
|
|
|
10648
10827
|
baseUrl/apiKey/headers (the service strips them).
|
|
10649
10828
|
# ๐ด ๅฐ้ญ + required ่กฅ้ธ้ ็น(census ๆน2 ็ฌฌไธๆฎต,2026-07-30):้ธ้ ็น `routes/capabilities.ts`
|
|
10650
10829
|
# ๆฏ้้ฎๅญ้ข้ๆๅฝฑ(็ฝๅๅ,ไธๆฏ้ไผ โโใopen setใๆงๆณจไธๆ็ซ,ๆฐ้ฎ่ฆๅ
่ฟ่ฟ้ spec)ใcore Model ็ฑปๅ
|
|
10651
|
-
# ้ id/provider/reasoning
|
|
10652
|
-
#
|
|
10653
|
-
|
|
10830
|
+
# ้ id/provider/reasoning ้ฝๆฏๅฟ
ๅกซ โ ๅ้ฎๆ ๆกไปถ;contextWindow/maxOutputTokens 0/็ผบ็ๅณ็็ฅ,
|
|
10831
|
+
# supportedEffortLevels ไป
reasoning ๆจกๅใ๐ด server 7.117.0 ่ตท `vision` ๆฏไธๆ(ๆถ / ไธๆถ / ๆฒกๅฃฐๆ `input`),
|
|
10832
|
+
# ๆฒกๅฃฐๆ โ ้ฎ็ผบๅธญ โ ไธๅๆฏๅฟ
ๆ้ฎ(ๆญคๅ็ฑ `input` ๆ็ฎๆๅธๅฐ,ๅฏนๆฒกๅฃฐๆ็ๆก็ฎๆฅ false)ใ
|
|
10833
|
+
required: [name, id, provider, reasoning]
|
|
10654
10834
|
additionalProperties: false
|
|
10655
10835
|
properties:
|
|
10656
10836
|
name: { type: string, description: 'the @mention handle (user-pickable model name).' }
|
|
10657
10837
|
id: { type: string, description: 'underlying model id (display, e.g. deepseek-v4-pro).' }
|
|
10658
10838
|
provider: { type: string }
|
|
10659
10839
|
reasoning: { type: boolean, description: 'a reasoning-tier model (picker can badge it).' }
|
|
10660
|
-
vision: { type: boolean, description: 'accepts image input.' }
|
|
10840
|
+
vision: { type: boolean, description: 'Whether this catalog row accepts image input โ THREE states (server >= 7.117.0; before it a row that declared no `input` reported `false`): `true` = the row declares `input` and it contains "image"; `false` = declares `input` without it; ABSENT = the row declared no `input` (a hand-written catalog entry; the env lane and the config-center lane always declare it). ABSENT means UNKNOWN, not false: treat it as "send the image anyway and tell the user", do not read it as `false` and block the image locally โ the server hands the image to the model for that same row at run time. Only an explicit `false` justifies "this model does not take images".' }
|
|
10661
10841
|
contextWindow: { type: integer, description: 'E4 (SHIPPED) โ context-window token DENOMINATOR for the %-used gauge; omitted when unknown.' }
|
|
10662
10842
|
maxOutputTokens: { type: integer, description: 'E4 (SHIPPED) โ single-call max output tokens; omitted when unknown.' }
|
|
10663
10843
|
supportedEffortLevels:
|
|
@@ -11841,6 +12021,11 @@ components:
|
|
|
11841
12021
|
expiresAtMs: { type: number, description: 'Absolute window deadline โ the SAME number minted once for the tool_approval frame (never recomputed).' }
|
|
11842
12022
|
sessionId: { type: string }
|
|
11843
12023
|
requiresRealApproval: { type: boolean, enum: [true] }
|
|
12024
|
+
rememberRefused:
|
|
12025
|
+
type: boolean
|
|
12026
|
+
enum: [true]
|
|
12027
|
+
description: >-
|
|
12028
|
+
server >= 7.116.0, ADDITIVE, present ONLY when true (never `false`): the "remember for this session" answer (live `allow_session` / durable `/decide` `remember:"session"`) will NOT be remembered on this card โ the decision is accepted and applies once, the receipt's `rememberApplied` is `false` (existing key, not a new one), later cards of the same kind still ask. A shell reads this to decide whether to render the "allow for the session" choice instead of inferring it from `requiresRealApproval` / `mandated` / `governanceForced`. One bit for four reasons: the operator-governance gate / a human must approve each time / a mandated card / the answer would also grant more than this one call (new in 7.116.0: approving an engine `Skill` card activates the skill and frees its listed tools for the run, which the card cannot show, so it is not remembered). ABSENT = remember works on this card, OR an older server (<= 7.115.x never carries the key). Same bit on the live frame, the `approval_request` card (= `card_json`, incl. the reconnect replay), the `livePending` row, and the `/v1/approvals` `pending[]` row (+ their `/stream` frames); NOT on inbox rows.
|
|
11844
12029
|
governanceForced: { type: boolean, enum: [true] }
|
|
11845
12030
|
mandated: { type: boolean, enum: [true], description: 'server >= 7.101.0 (T4โ ): the mandated bit, same layer and shape as the two flags above (present only when true); the SAME value as `frame.mandated` (read once when the entry is minted).' }
|
|
11846
12031
|
mandate:
|
|
@@ -12003,6 +12188,9 @@ components:
|
|
|
12003
12188
|
Present โ the request carried `remember:"session"` and the worker has an exemption store. `true` = the
|
|
12004
12189
|
per-session per-tool exemption landed; `false` = the grant failed (logged) or the gate carried no
|
|
12005
12190
|
rememberable toolName โ the decision itself still stands.
|
|
12191
|
+
๐ด server >= 7.116.0: ALWAYS `false` on a card that carries `rememberRefused: true` (an engine `Skill` card etc. โ the
|
|
12192
|
+
answer would also grant more than this one call): the decision is accepted and applies once, the exemption store gets
|
|
12193
|
+
zero writes (existing key, not a new one). Ordinary cards keep `true` = landed.
|
|
12006
12194
|
|
|
12007
12195
|
ApprovalExemption:
|
|
12008
12196
|
type: object
|
|
@@ -12112,6 +12300,16 @@ components:
|
|
|
12112
12300
|
toolName: { type: string }
|
|
12113
12301
|
summary: { type: string }
|
|
12114
12302
|
touchedPaths: {}
|
|
12303
|
+
allowRuleShadowed:
|
|
12304
|
+
type: array
|
|
12305
|
+
items: { $ref: '#/components/schemas/AllowRuleShadow' }
|
|
12306
|
+
description: >
|
|
12307
|
+
server >= 7.117.0 (core 7.42.0): the DURABLE dual of `ToolApprovalFrame.allowRuleShadowed` โ the allow-layer members that matched this call
|
|
12308
|
+
and could not clear its ask (same shape and semantics; entries are secret-redacted again at the server's read boundary). Passed through whole
|
|
12309
|
+
on `GET /v1/approvals` and `/v1/approvals/stream`. Absent != "you have no rule". ๐ด The old key `shadowedRule` (a string, server <= 7.116.x)
|
|
12310
|
+
is RETIRED: the SQL backend rewrote its parked rows once at the 7.117.0 boot to `[{ member: "persisted", entries: [<old value>] }]`, but the
|
|
12311
|
+
file backend's pre-upgrade parked rows and run results already on disk (`checkpointGate.riskDescriptor`) keep the old key verbatim
|
|
12312
|
+
(text still redacted, no structured disclosure) โ a consumer reading those must still tolerate the old string.
|
|
12115
12313
|
# server 7.16.0 [3684]โก โ durable ้ๅ่กๅฝๅ ไธค้ฎ(ไธๆดปๅก tool_approval ๅธง็ๅๅ้ฎ่ฏญไนๅๆใๅคๆฎไธๅๆบ;
|
|
12116
12314
|
# ไธคๆก่
ฟๅฏนๅไธๅช ask ็ๅจๅบๆงๅฏไปฅไธไธ่ด,ไธคไพง้ฝๅช่ฎคๅจๅบใ้ฝ็ฆๆ็ผบๅธญ่ฏปๆๅฆๅฎ)ใ
|
|
12117
12315
|
ruleSuggestions:
|
|
@@ -12146,6 +12344,11 @@ components:
|
|
|
12146
12344
|
๐ด DISPLAY / TRIAGE ONLY, and ABSENT MEANS THERE REALLY IS NO SUPPLY (rule lane unarmed, the
|
|
12147
12345
|
command yields no rule, no rule could silence this ask, or an old row) โ never "the projection
|
|
12148
12346
|
dropped it", which is precisely the bug this key exists to close. Never `null`, never `[]`.
|
|
12347
|
+
rememberRefused:
|
|
12348
|
+
type: boolean
|
|
12349
|
+
enum: [true]
|
|
12350
|
+
description: >-
|
|
12351
|
+
server >= 7.116.0, ADDITIVE, present ONLY when true (never `false`): the "remember for this session" answer (live `allow_session` / durable `/decide` `remember:"session"`) will NOT be remembered on this card โ the decision is accepted and applies once, the receipt's `rememberApplied` is `false` (existing key, not a new one), later cards of the same kind still ask. A shell reads this to decide whether to render the "allow for the session" choice instead of inferring it from `requiresRealApproval` / `mandated` / `governanceForced`. One bit for four reasons: the operator-governance gate / a human must approve each time / a mandated card / the answer would also grant more than this one call (new in 7.116.0: approving an engine `Skill` card activates the skill and frees its listed tools for the run, which the card cannot show, so it is not remembered). ABSENT = remember works on this card, OR an older server (<= 7.115.x never carries the key). Same bit on the live frame, the `approval_request` card (= `card_json`, incl. the reconnect replay), the `livePending` row, and the `/v1/approvals` `pending[]` row (+ their `/stream` frames); NOT on inbox rows.
|
|
12149
12352
|
governanceForced:
|
|
12150
12353
|
type: boolean
|
|
12151
12354
|
enum: [true]
|
|
@@ -13098,31 +13301,97 @@ components:
|
|
|
13098
13301
|
type: object
|
|
13099
13302
|
description: >
|
|
13100
13303
|
2c session-sync `GET โฆ/sync/manifest` payload (wrapped server-side as `{ manifest }`). The THIN cross-backend
|
|
13101
|
-
snapshot: entry IDS (oldest-first, NOT payloads) +
|
|
13102
|
-
|
|
13103
|
-
|
|
13304
|
+
snapshot: entry IDS (oldest-first, NOT payloads) + the file-history envelope + policy + anchors + leaf.
|
|
13305
|
+
๐ด server >= 7.52 (S-15, design/381; re-read byte for byte against 7.116.0): the key `snapshots` (per-snapshot
|
|
13306
|
+
relPathโblobHash, the retired E19 whole-tree snapshot epoch) is NO LONGER SENT โ the server's `exportSessionManifest` mints
|
|
13307
|
+
`{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }` and `fileHistory` (core's versioned
|
|
13308
|
+
`FileHistoryExport` envelope; `null` = no history / the source store cannot export) replaces it. <= 7.51 servers still send
|
|
13309
|
+
`snapshots` and no `fileHistory`. The blob BYTES never ride the manifest: content-addressed, via the history blob faces
|
|
13310
|
+
(`GET โฆ/sync/history/blobs/{hash}` / `PUT โฆ/sync/blobs/{hash}`; probe `capabilities.sessionSyncFileHistory` on BOTH ends).
|
|
13311
|
+
The SDK's `manifest()` fills `snapshots: []` when the wire omits it.
|
|
13312
|
+
# ๅฐ้ญ(census ๆน2 ็ฌฌไธๆฎต,2026-07-30;16.2.0 ๆ 7.116.0 ๅๅธๅญ่้ๆ ธ):้ธ้ ็น `session-sync.ts`(exportSessionManifest ๅฐพ้จ
|
|
13313
|
+
# ๅญ้ข้)ๆฐๆฏ `{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }` 7 ้ฎ(โฅ7.52),ๆ `snapshots`;
|
|
13314
|
+
# โค7.51 ่ server ๅ `snapshots`ใๆ `fileHistory` โ ไธค้ฎ้ฝไธ่ฟ required(ๆฏๆๅบ็บฟ 3.0.0)ใ
|
|
13104
13315
|
additionalProperties: false
|
|
13105
|
-
required: [sessionId, entryIds, entryCount, leafId,
|
|
13316
|
+
required: [sessionId, entryIds, entryCount, leafId, policy, anchors]
|
|
13106
13317
|
properties:
|
|
13107
13318
|
sessionId: { type: string }
|
|
13108
13319
|
entryIds: { type: array, items: { type: string }, description: Oldest-first, verbatim cross-backend. }
|
|
13109
13320
|
entryCount: { type: integer, description: '= entryIds.length (the `/sync/entries` trailer count).' }
|
|
13110
13321
|
leafId: { type: [string, 'null'] }
|
|
13111
|
-
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
13322
|
+
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' }, description: 'server <= 7.51 ONLY (the retired E19 snapshot epoch); server >= 7.52 does not send it โ see `fileHistory`.' }
|
|
13323
|
+
fileHistory:
|
|
13324
|
+
oneOf:
|
|
13325
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
13326
|
+
- { type: 'null' }
|
|
13327
|
+
description: 'server >= 7.52: the per-edited-file rewind history envelope; `null` = no history / the source store cannot export; key ABSENT = a <= 7.51 server (that generation sends `snapshots`).'
|
|
13112
13328
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
13113
13329
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
13114
13330
|
|
|
13331
|
+
FileHistoryExport:
|
|
13332
|
+
type: object
|
|
13333
|
+
description: >
|
|
13334
|
+
Mirror of core's `FileHistoryExport` (`formatVersion: "file-history/1"`) โ the session-sync envelope for the per-edited-file rewind history graph
|
|
13335
|
+
(server >= 7.52; replaces the retired E19 `SyncSnapshot`). Blob bytes are NOT inside: they are content-addressed and travel through the history blob faces.
|
|
13336
|
+
The SDK reads only `tracked[].versions[].blobHash` (which blobs to move) and passes everything else through verbatim โ the server's import door judges
|
|
13337
|
+
`formatVersion` (refuse-not-coerce) and the closed `keyKind` / `keyFamily` sets, so they are plain strings here.
|
|
13338
|
+
required: [formatVersion, tracked, boundaries]
|
|
13339
|
+
properties:
|
|
13340
|
+
formatVersion: { type: string, description: 'today only `file-history/1`; the server refuses any other value.' }
|
|
13341
|
+
tracked:
|
|
13342
|
+
type: array
|
|
13343
|
+
items:
|
|
13344
|
+
type: object
|
|
13345
|
+
required: [relOrAbsPath, keyKind, keyFamily, baseAvailable, versions]
|
|
13346
|
+
properties:
|
|
13347
|
+
relOrAbsPath: { type: string }
|
|
13348
|
+
keyKind: { type: string }
|
|
13349
|
+
keyFamily: { type: string }
|
|
13350
|
+
baseAvailable: { type: boolean }
|
|
13351
|
+
versions:
|
|
13352
|
+
type: array
|
|
13353
|
+
items:
|
|
13354
|
+
type: object
|
|
13355
|
+
required: [version, blobHash, backupTime]
|
|
13356
|
+
properties:
|
|
13357
|
+
version: { type: integer }
|
|
13358
|
+
blobHash: { type: [string, 'null'], description: '`null` = the "did not exist" marker (no blob to move).' }
|
|
13359
|
+
mode: { type: integer }
|
|
13360
|
+
parentIdent: { type: string }
|
|
13361
|
+
backupTime: { type: string }
|
|
13362
|
+
boundaries:
|
|
13363
|
+
type: array
|
|
13364
|
+
items:
|
|
13365
|
+
type: object
|
|
13366
|
+
required: [entryId, files]
|
|
13367
|
+
properties:
|
|
13368
|
+
entryId: { type: string }
|
|
13369
|
+
files:
|
|
13370
|
+
type: array
|
|
13371
|
+
items:
|
|
13372
|
+
type: object
|
|
13373
|
+
required: [relOrAbsPath, version]
|
|
13374
|
+
properties:
|
|
13375
|
+
relOrAbsPath: { type: string }
|
|
13376
|
+
version: { type: integer }
|
|
13377
|
+
|
|
13115
13378
|
SessionBundle:
|
|
13116
13379
|
type: object
|
|
13117
13380
|
description: >
|
|
13118
13381
|
The portable state of ONE session, ready to replay into another backend. Blobs are NOT inlined (each
|
|
13119
13382
|
snapshot carries only its `manifest`; the bytes stream through the content-addressed blob routes). The SDK
|
|
13120
|
-
assembles this from a manifest + the streamed entries for a PUSH.
|
|
13383
|
+
assembles this from a manifest + the streamed entries for a PUSH. server >= 7.52: the file history rides `fileHistory`
|
|
13384
|
+
(the `FileHistoryExport` envelope) instead of `snapshots`.
|
|
13121
13385
|
required: [sessionId, entries, snapshots, policy, anchors]
|
|
13122
13386
|
properties:
|
|
13123
13387
|
sessionId: { type: string }
|
|
13124
13388
|
entries: { type: array, items: { $ref: '#/components/schemas/SyncEntry' } }
|
|
13125
13389
|
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
13390
|
+
fileHistory:
|
|
13391
|
+
oneOf:
|
|
13392
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
13393
|
+
- { type: 'null' }
|
|
13394
|
+
description: 'server >= 7.52 file-history envelope (same as `SessionManifest.fileHistory`); key absent = the source is a <= 7.51 server.'
|
|
13126
13395
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
13127
13396
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
13128
13397
|
|
|
@@ -13409,6 +13678,8 @@ components:
|
|
|
13409
13678
|
`not_found.resource` / `request.unprocessable` / `capability.unavailable` โฆ). ALWAYS PRESENT on server >= 7.104.0
|
|
13410
13679
|
(S-607); before that it was absent when the original refusal carried no code. SDK:
|
|
13411
13680
|
`ResumeBlockedByPolicyError.blockedBy` (`undefined` when the key is absent or not a string โ never defaulted).
|
|
13681
|
+
server >= 7.117.0 adds a third fold source: a stored skill `disallowedTools` entry the engine now reads as nothing (the submit leg's 400 `request.field_invalid` sentence)
|
|
13682
|
+
โ `blockedBy: "request.field_invalid"`, refused before the claim; the terminal-run steer leg answers it before minting the wake card.
|
|
13412
13683
|
|
|
13413
13684
|
ResumeLegConflictError:
|
|
13414
13685
|
description: >
|
|
@@ -13985,10 +14256,17 @@ components:
|
|
|
13985
14256
|
unattended leg run under `UNATTENDED_PERMISSION_MODE=dontAsk`).
|
|
13986
14257
|
AskClass:
|
|
13987
14258
|
type: string
|
|
13988
|
-
enum: [content_question, hook, ancestor, unverifiable_delete, transcript_write, org_rule, governance_unavailable, rule_unreadable, ask_rule, denial_limit_fallback, operator_forced, shell_floor, write_protection_unresolved, probe, write_protection, tool_marks_mcp, tool_marks_a2a, policy_rra, artifact_shared_read, mode, unstated, ordinary]
|
|
13989
|
-
description: >
|
|
13990
|
-
core `ASK_CLASSES` (twenty-two words as of core 7.40.0 โ 7.34.0 minted twenty; `shell_floor` joined in 7.39.0 #1260 and rides
|
|
13991
|
-
server >= 7.113.0; `unstated` joined in 7.40.0 and rides server >= 7.115.0
|
|
14259
|
+
enum: [content_question, hook, ancestor, unverifiable_delete, transcript_write, org_rule, governance_unavailable, rule_unreadable, ask_rule, denial_limit_fallback, 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]
|
|
14260
|
+
description: >
|
|
14261
|
+
core `ASK_CLASSES` (twenty-two words as of core 7.40.0, twenty-three as of core 7.41.0 โ 7.34.0 minted twenty; `shell_floor` joined in 7.39.0 #1260 and rides
|
|
14262
|
+
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
|
|
14263
|
+
server >= 7.116.0) โ which CLASS an ask falls in (the columns of the mode ร class arbitration table).
|
|
14264
|
+
`requires_user_interaction` = the MCP server declared, in the tool's advertisement, `_meta["anthropic/requiresUserInteraction"] === true`
|
|
14265
|
+
(only the boolean `true`): EVERY call of that tool asks the human, in EVERY mode including `bypassPermissions` (it is not one of the ten
|
|
14266
|
+
RELEASABLE classes), and only the human's answer clears it โ `settings.permissions.allow`, operator `APPROVAL_GRANT`, a skill's tool list +
|
|
14267
|
+
`userInvokedSkills` and a hook's explicit allow all fail to; with no approval seat the call is refused (the server sees nothing). The frame
|
|
14268
|
+
also carries `requiresRealApproval: true` / `mandated: true` (`origin: "safety_tighten"`). A client that renders cards by exhaustive `askClass`
|
|
14269
|
+
adds this one word.
|
|
13992
14270
|
`unstated` = NOBODY STATED IT: in an ask-class mode (`default` / `acceptEdits` / `auto` / `plan`) a call to an MCP server tool or A2A skill
|
|
13993
14271
|
(a seat that states no permission of its own) reached the end of the fold with no layer โ rule / hook / approver / classifier / mode
|
|
13994
14272
|
release โ having said "this time is fine"; the engine raises a card with `askClass: "unstated"` (sentence `The agent requested permission to use <tool>,
|
|
@@ -15589,6 +15867,11 @@ components:
|
|
|
15589
15867
|
args:
|
|
15590
15868
|
description: '"tool_approval" only: the call''s args, secret-redacted. UNTRUSTED for display. Absent (with argsOmitted) when over the byte cap or unserializable.'
|
|
15591
15869
|
argsOmitted: { type: boolean, enum: [true] }
|
|
15870
|
+
rememberRefused:
|
|
15871
|
+
type: boolean
|
|
15872
|
+
enum: [true]
|
|
15873
|
+
description: >-
|
|
15874
|
+
server >= 7.116.0, ADDITIVE, present ONLY when true (never `false`): the "remember for this session" answer (live `allow_session` / durable `/decide` `remember:"session"`) will NOT be remembered on this card โ the decision is accepted and applies once, the receipt's `rememberApplied` is `false` (existing key, not a new one), later cards of the same kind still ask. A shell reads this to decide whether to render the "allow for the session" choice instead of inferring it from `requiresRealApproval` / `mandated` / `governanceForced`. One bit for four reasons: the operator-governance gate / a human must approve each time / a mandated card / the answer would also grant more than this one call (new in 7.116.0: approving an engine `Skill` card activates the skill and frees its listed tools for the run, which the card cannot show, so it is not remembered). ABSENT = remember works on this card, OR an older server (<= 7.115.x never carries the key). Same bit on the live frame, the `approval_request` card (= `card_json`, incl. the reconnect replay), the `livePending` row, and the `/v1/approvals` `pending[]` row (+ their `/stream` frames); NOT on inbox rows.
|
|
15592
15875
|
governanceForced:
|
|
15593
15876
|
type: boolean
|
|
15594
15877
|
enum: [true]
|
|
@@ -15674,29 +15957,45 @@ components:
|
|
|
15674
15957
|
requiresRealApproval / shadowed / hook-produced / inherited-unresolved / ancestor-resolved /
|
|
15675
15958
|
anonymous asks. Absence reads as "THIS CARD has no such option", never as "this deployment has no
|
|
15676
15959
|
rule lane" (that is `capabilities.permissionRules`) and never as "your rule broke" (that is
|
|
15677
|
-
`persistedRuleShadowed`).
|
|
15960
|
+
`allowRuleShadowed`; `persistedRuleShadowed` on a server <= 7.116.x).
|
|
15678
15961
|
|
|
15679
15962
|
โ ๏ธ REDEMPTION SCOPE is the live respond leg keyed by this frame's `approvalId` only; a replayed
|
|
15680
15963
|
offer on another replica is not a promise that it is still redeemable.
|
|
15681
15964
|
persistedRuleShadowed:
|
|
15682
15965
|
type: string
|
|
15966
|
+
deprecated: true
|
|
15683
15967
|
description: >
|
|
15684
|
-
server
|
|
15968
|
+
๐ด RETIRED by server 7.117.0 (core 7.42.0) โ replaced by `allowRuleShadowed`, no alias. A server >= 7.117.0 never mints this key
|
|
15969
|
+
(its strict card schema even refuses a stored card carrying it); only a server <= 7.116.x still does, and the SDK keeps the declaration
|
|
15970
|
+
for those servers (the supported floor is far below 7.117.0). Slated for deletion in the next major.
|
|
15971
|
+
|
|
15972
|
+
For those older servers (server >= 7.13.0 / core 5.25.0 #144, ADDITIVE, "tool_approval" only): this ask MATCHED one of the
|
|
15685
15973
|
caller's persisted allow rules and that rule COULD NOT silence it. The value is the shadowed rule's
|
|
15686
15974
|
VERBATIM text (secret-redacted + length-bounded). UNTRUSTED for display, same treatment as `message`.
|
|
15687
|
-
|
|
15688
|
-
|
|
15689
|
-
|
|
15690
|
-
|
|
15691
|
-
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
|
|
15698
|
-
|
|
15699
|
-
|
|
15975
|
+
๐ด ABSENT != "you have no rule": present only when a rule matched AND could not clear the ask. ๐ด Deliberately SEPARATE
|
|
15976
|
+
from `governanceForced` and not derivable from it: that key answers "who imposed the gate", this one answers "what
|
|
15977
|
+
happened to YOUR rule". The durable dual on those servers is `gate.riskDescriptor.shadowedRule` on the parked row.
|
|
15978
|
+
allowRuleShadowed:
|
|
15979
|
+
type: array
|
|
15980
|
+
items: { $ref: '#/components/schemas/AllowRuleShadow' }
|
|
15981
|
+
description: >
|
|
15982
|
+
server >= 7.117.0 (core 7.42.0), ADDITIVE, "tool_approval" only โ BREAKING RENAME, replacing the retired string `persistedRuleShadowed`
|
|
15983
|
+
(no alias): the allow-layer members that MATCHED this call and could NOT clear this ask, one `{ member, entries, omitted? }` record per
|
|
15984
|
+
matching member (see AllowRuleShadow). `member` is one of `hook` / `deployment` / `persisted` / `skill` / `request`; `entries` are the
|
|
15985
|
+
entries that member matched, as their source spells them (UNTRUSTED for display like `message`, secret-redacted, <= 512 chars each,
|
|
15986
|
+
<= 32 listed; a `hook` record's `entries` is always the empty list); `omitted` counts the entries not listed.
|
|
15987
|
+
|
|
15988
|
+
The explaining sentence ("... matches this call but does not clear the ask โ <reason>") is IN `message` (the engine writes it where it builds
|
|
15989
|
+
the card); this key is the structured twin of the same fact. Render a line from it ("your rule matched, but this call must be confirmed each
|
|
15990
|
+
time"): without it the only conclusion a user can draw is "my rule broke".
|
|
15991
|
+
|
|
15992
|
+
๐ด ABSENT != "you have no rule": present only when a member matched AND could not clear the ask; a match that cleared never becomes an ask.
|
|
15993
|
+
๐ด `member: "hook"` does not say whose hook (a deployment PreToolUse hook and, on the single-user lane, the request's own `settings.hooks`
|
|
15994
|
+
share one member). ๐ด Deliberately SEPARATE from `governanceForced` (that one: "who imposed the gate"; this one: "what happened to YOUR
|
|
15995
|
+
rule"). What the allow layer can NOT clear: any layer's deny / ask rule, operator `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` /
|
|
15996
|
+
`MANUAL_MODE_SHELL_GATE=always`, write protection, sensitive-path writes, governance, a hook's ask, plan-mode asks. The durable dual is
|
|
15997
|
+
`gate.riskDescriptor.allowRuleShadowed` on the parked row (PendingCheckpoint.riskDescriptor). Rolling-upgrade caveat: a card stored by a
|
|
15998
|
+
<= 7.116.x replica (`card_json` carrying `persistedRuleShadowed`) cannot be read by a >= 7.117.0 replica โ the replay skips it.
|
|
15700
15999
|
probeCause:
|
|
15701
16000
|
type: object
|
|
15702
16001
|
description: >
|
|
@@ -16053,6 +16352,11 @@ components:
|
|
|
16053
16352
|
argsOmitted: { type: boolean, enum: [true], description: 'Present (true) only when args exceeded the byte cap. Never false.' }
|
|
16054
16353
|
toolCallId: { type: string, description: 'The engine''s tool-call id (the `call_โฆ` on the assistant message''s tool_use block) โ same domain as ToolApprovalFrame.toolCallId.' }
|
|
16055
16354
|
risk: { $ref: '#/components/schemas/ApprovalRiskAxes' }
|
|
16355
|
+
rememberRefused:
|
|
16356
|
+
type: boolean
|
|
16357
|
+
enum: [true]
|
|
16358
|
+
description: >-
|
|
16359
|
+
server >= 7.116.0, ADDITIVE, present ONLY when true (never `false`): the "remember for this session" answer (live `allow_session` / durable `/decide` `remember:"session"`) will NOT be remembered on this card โ the decision is accepted and applies once, the receipt's `rememberApplied` is `false` (existing key, not a new one), later cards of the same kind still ask. A shell reads this to decide whether to render the "allow for the session" choice instead of inferring it from `requiresRealApproval` / `mandated` / `governanceForced`. One bit for four reasons: the operator-governance gate / a human must approve each time / a mandated card / the answer would also grant more than this one call (new in 7.116.0: approving an engine `Skill` card activates the skill and frees its listed tools for the run, which the card cannot show, so it is not remembered). ABSENT = remember works on this card, OR an older server (<= 7.115.x never carries the key). Same bit on the live frame, the `approval_request` card (= `card_json`, incl. the reconnect replay), the `livePending` row, and the `/v1/approvals` `pending[]` row (+ their `/stream` frames); NOT on inbox rows.
|
|
16056
16360
|
governanceForced:
|
|
16057
16361
|
type: boolean
|
|
16058
16362
|
enum: [true]
|
|
@@ -16084,12 +16388,21 @@ components:
|
|
|
16084
16388
|
promise and the per-leg index rules are stated verbatim on ToolApprovalFrame.ruleOffers.
|
|
16085
16389
|
persistedRuleShadowed:
|
|
16086
16390
|
type: string
|
|
16391
|
+
deprecated: true
|
|
16392
|
+
description: >
|
|
16393
|
+
๐ด RETIRED by server 7.117.0 (core 7.42.0) โ replaced by `allowRuleShadowed`, no alias (a server >= 7.117.0 never mints it; the strict card
|
|
16394
|
+
schema refuses a stored card carrying it). Only a server <= 7.116.x still does; slated for deletion in the next major. For those servers
|
|
16395
|
+
(ADDITIVE, server >= 7.13.0 / core 5.25.0 #144): the VERBATIM text of the persisted rule this ask matched but which could not silence it
|
|
16396
|
+
(secret-redacted + length-bounded). UNTRUSTED for display. Semantics, the ABSENT != "you have no rule" clause and the deliberate separation
|
|
16397
|
+
from `governanceForced` are stated verbatim on ToolApprovalFrame.persistedRuleShadowed.
|
|
16398
|
+
allowRuleShadowed:
|
|
16399
|
+
type: array
|
|
16400
|
+
items: { $ref: '#/components/schemas/AllowRuleShadow' }
|
|
16087
16401
|
description: >
|
|
16088
|
-
ADDITIVE (server >= 7.
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
`
|
|
16092
|
-
the stored `card_json` and the replayed frame carry the SAME material.
|
|
16402
|
+
ADDITIVE (server >= 7.117.0 / core 7.42.0, BREAKING RENAME of the retired `persistedRuleShadowed`): the allow-layer members that matched this
|
|
16403
|
+
call and could not clear this ask. Semantics, the five members, the always-empty `hook` entries, the explaining sentence living in `message`,
|
|
16404
|
+
the ABSENT != "you have no rule" clause and the separation from `governanceForced` are stated verbatim on ToolApprovalFrame.allowRuleShadowed
|
|
16405
|
+
โ the live frame, the stored `card_json`, the replayed frame and the `approval_request` card carry the SAME material.
|
|
16093
16406
|
fromSubagent: { type: boolean, enum: [true], description: 'Present โ the ask comes from a DELEGATED child โ the explicit discriminator (a worker cannot forge it).' }
|
|
16094
16407
|
sourceTaskId: { type: string, description: 'The child''s core session id โ row-join value + fallback discriminator.' }
|
|
16095
16408
|
sourceAgentName: { type: string, description: 'The child agent''s display name, redacted. UNTRUSTED.' }
|
|
@@ -16214,6 +16527,37 @@ components:
|
|
|
16214
16527
|
`.strict()`). The eleven known words are exported at runtime as the SDK's `ASK_ORIGINS` (core 7.32.1
|
|
16215
16528
|
`ASK_ORIGINS`, verbatim and in order) โ known words, NOT an enforcement table.
|
|
16216
16529
|
|
|
16530
|
+
AllowRuleMember:
|
|
16531
|
+
type: string
|
|
16532
|
+
enum: [hook, deployment, persisted, skill, request]
|
|
16533
|
+
description: >
|
|
16534
|
+
The closed five-word vocabulary of `AllowRuleShadow.member` (server >= 7.117.0 / core 7.42.0 `ALLOW_RULE_MEMBERS`, verbatim and in the order the engine reads the members). The SDK exports
|
|
16535
|
+
it at runtime as `ALLOW_RULE_MEMBERS`. Owner = core; read it as an open string with a default arm (core may add a member and the server follows).
|
|
16536
|
+
|
|
16537
|
+
AllowRuleShadow:
|
|
16538
|
+
type: object
|
|
16539
|
+
additionalProperties: false
|
|
16540
|
+
required: [member, entries]
|
|
16541
|
+
description: >
|
|
16542
|
+
One allow-layer DISCLOSURE record (`ToolApprovalFrame.allowRuleShadowed` / `ApprovalCard.allowRuleShadowed` / the durable
|
|
16543
|
+
`PendingCheckpoint.riskDescriptor.allowRuleShadowed`; server >= 7.117.0 / core 7.42.0 `AllowRuleShadow`): one member of the allow layer that
|
|
16544
|
+
MATCHED the call and could NOT clear its ask. At most one record per member, at most five per ask. The vocabulary owner is core; the server
|
|
16545
|
+
drops the whole key on a member outside the five words, so a >= 7.117.0 server only ever sends these five โ still read `member` as an open
|
|
16546
|
+
string with a default arm (core may add members and the server follows).
|
|
16547
|
+
properties:
|
|
16548
|
+
member:
|
|
16549
|
+
$ref: '#/components/schemas/AllowRuleMember'
|
|
16550
|
+
description: >
|
|
16551
|
+
Which allow-layer member matched, in the order the engine reads them: `hook` = a PreToolUse hook's explicit `allow` (a deployment hook or,
|
|
16552
|
+
on the single-user lane, the request's own `settings.hooks` โ the key cannot say which) ยท `deployment` = the operator's `APPROVAL_GRANT` ยท
|
|
16553
|
+
`persisted` = a person's stored allow rules ยท `skill` = an activated skill's `allowedTools` ยท `request` = the request's `settings.permissions.allow`.
|
|
16554
|
+
entries:
|
|
16555
|
+
type: array
|
|
16556
|
+
maxItems: 32
|
|
16557
|
+
items: { type: string, maxLength: 512 }
|
|
16558
|
+
description: 'The entries that member matched, as their source spells them (UNTRUSTED for display, secret-redacted, <= 512 chars each, <= 32 listed). Always the empty list for `hook` โ its word is about the call, not about an entry.'
|
|
16559
|
+
omitted: { type: integer, minimum: 1, description: 'How many matched entries were not listed (beyond the cap). Absent = none omitted.' }
|
|
16560
|
+
|
|
16217
16561
|
RuleOffersAbsence:
|
|
16218
16562
|
type: string
|
|
16219
16563
|
enum: [mandated, shadowed, lane_cannot_speak]
|
|
@@ -16222,7 +16566,7 @@ components:
|
|
|
16222
16566
|
`ApprovalCard.ruleOffersAbsence`; server >= 7.55.0 / core #490 fix โก, S-15). The engine names which
|
|
16223
16567
|
door is shut: `mandated` = this ask must be confirmed every time (๐ด this arm must NOT point the user
|
|
16224
16568
|
at writing a rule โ a rule would not silence it, and saying so sends them into a loop); `shadowed` = a
|
|
16225
|
-
|
|
16569
|
+
an allow-layer member matched but could not clear it (the machine-readable twin of `allowRuleShadowed`; `persistedRuleShadowed` on a server <= 7.116.x);
|
|
16226
16570
|
`lane_cannot_speak` = the engine could mint no coverable form for this command.
|
|
16227
16571
|
|
|
16228
16572
|
Engine-side MUTUALLY EXCLUSIVE with `ruleOffers`. ๐ด ABSENCE IS NOT AN ASSERTION โ it covers both
|
|
@@ -16707,16 +17051,27 @@ components:
|
|
|
16707
17051
|
sessionId: { type: string, description: 'gone.ask_parked ONLY โ gate reconciliation coordinate 1; drive the existing durable-gate flow with it.' }
|
|
16708
17052
|
gateBoundCallId: { type: string, description: 'gone.ask_parked ONLY โ gate reconciliation coordinate 2.' }
|
|
16709
17053
|
gateBoundInputHash: { type: string, description: 'gone.ask_parked ONLY โ gate reconciliation coordinate 3.' }
|
|
16710
|
-
state: { type: string, enum: [DENIED, VOID], description: 'gone.ask ONLY โ the terminal state.' }
|
|
17054
|
+
state: { type: string, enum: [DENIED, VOID], description: 'gone.ask ONLY โ the terminal state. server >= 7.116.0 also mints `VOID` for "the process that held the ask is gone" (local lane restart; see `deniedReason`).' }
|
|
16711
17055
|
deniedReason:
|
|
16712
17056
|
type: string
|
|
16713
17057
|
description: >
|
|
16714
17058
|
gone.ask ONLY โ attribution, GROUPED BY `state`. `DENIED` carries the single-member deny
|
|
16715
17059
|
vocabulary `routing_failure_fail_closed`; `VOID` carries the separate (and growing) void
|
|
16716
|
-
vocabulary,
|
|
17060
|
+
vocabulary, seven words today: `run_cancelled`, `batch_aborted`, `batch_bound_elsewhere`,
|
|
17061
|
+
`adhoc_leg_no_durable_domain`, `orphan_ttl_exceeded` and โ new in server 7.116.0 (local lane) โ
|
|
17062
|
+
`crashed_before_park` (the process that held the ask crashed / was killed) and `shutdown_before_park`
|
|
17063
|
+
(an orderly shutdown could not settle the card inside its grace window; a fault shape, hard to build black-box).
|
|
17064
|
+
The last two are the SAME word as `GET /v1/approvals` `crashConverged[].cause`; the other six were already on the wire
|
|
17065
|
+
(7.3.0 / 7.55.0 / 7.108.0) and are only registered in the server's self-minted word table by 7.116.0.
|
|
17066
|
+
ABSENT = the row carries no attribution. The two vocabularies never mix; the VOID one is open (read an unknown word as "the ask ended without
|
|
17067
|
+
a human decision, reason unknown").
|
|
16717
17068
|
description: >
|
|
16718
17069
|
410 body. THE TWO LEGS ARE DISJOINT: `gone.ask_parked` carries exactly the three gate coordinates,
|
|
16719
|
-
`gone.ask` carries exactly `{state, deniedReason?}
|
|
17070
|
+
`gone.ask` carries exactly `{state, deniedReason?}` (no `consumerState`).
|
|
17071
|
+
๐ด server >= 7.116.0 (local lane, `DB_BACKEND=local`): after a crash / kill and a restart on the same data root, answering the PREVIOUS
|
|
17072
|
+
life's still-open card is now `410 gone.ask` with `state: "VOID"` and `deniedReason` `crashed_before_park` / `shutdown_before_park` โ
|
|
17073
|
+
<= 7.115.x answered `200` + `consumerState: "absent"` (the run had long been reclaimed; nothing executed). An ask that was already decided
|
|
17074
|
+
(decided, then the process died mid-execution) is unchanged: `409 conflict.ask_decided`. SQL backends are unchanged in 7.116.0. Routing off field presence across the legs is how a
|
|
16720
17075
|
consumer ends up driving the wrong durable gate.
|
|
16721
17076
|
๐ด The checkpoint token is NEVER here: the resume credential is not externally disclosed. Use
|
|
16722
17077
|
`sessionId`.
|
|
@@ -18495,9 +18850,15 @@ components:
|
|
|
18495
18850
|
description: >-
|
|
18496
18851
|
[2400] TR-4 โ per-message queue priority on POST /v1/runs/{taskId}/steer. ACCEPTED + ENUM-VALIDATED
|
|
18497
18852
|
FAIL-LOUD (`routes/runs.ts`; anything else is 400 `request.field_invalid`) and echoed back on the
|
|
18498
|
-
receipt
|
|
18499
|
-
|
|
18500
|
-
on
|
|
18853
|
+
receipt. WHETHER IT TAKES EFFECT is the server's call โ read `Capabilities.fleet.steerPriority` first:
|
|
18854
|
+
`"engine"` (server >=7.116.0) = the tier is handed to the engine on every delivery leg (`now` cuts the in-flight turn
|
|
18855
|
+
IMMEDIATELY โ the running tool receives an abort, an approval card pending on this replica is revoked, one `engine_notice`
|
|
18856
|
+
`task.turn_interrupted` frame is the evidence; `next` โก no `priority`; `later` is delivered after the turn the run would have stopped on; parked
|
|
18857
|
+
legs store the tier and deliver on the resume's / wake's first turn; replaying the same `Idempotency-Key` + text with a different effective
|
|
18858
|
+
tier is 409 `steering.duplicate_input_id`); `"advisory"` (server <=7.115.x) = accepted and echoed but NOT applied โ
|
|
18859
|
+
core's steer was a single-slot last-writer-wins with no per-message priority or addressable drop, so a
|
|
18860
|
+
faithful priority queue (and DELETE /v1/runs/{taskId}/queue/{messageId}) waited on a core seam. An absent
|
|
18861
|
+
or unknown capability value means "do not assume it is applied".
|
|
18501
18862
|
|
|
18502
18863
|
SteerReceipt:
|
|
18503
18864
|
type: object
|
|
@@ -18774,6 +19135,8 @@ components:
|
|
|
18774
19135
|
server 1.239 ([1392]โก): on allow_session, an honest echo of whether the grant was REALLY
|
|
18775
19136
|
recorded (true = landed in the bridge store; false = no sessionId, could not record โ do not
|
|
18776
19137
|
render "session-wide allowed"). Omitted on non-allow_session decisions and on older servers.
|
|
19138
|
+
๐ด server >= 7.116.0: ALWAYS `false` on a card that carries `rememberRefused: true` (an engine `Skill` card etc.) โ the decision
|
|
19139
|
+
applies once and nothing is remembered (existing key, not a new one).
|
|
18777
19140
|
updatedInputForwarded:
|
|
18778
19141
|
type: boolean
|
|
18779
19142
|
description: >
|