@sema-agent/sdk 16.1.0 → 16.2.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 +62 -1
- package/dist/errors.d.ts +47 -11
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +26 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- 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 +20 -6
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +3 -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 +7 -1
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +7 -1
- package/dist/resources/tasks.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +17 -3
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +4 -0
- 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 +7 -3
- 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 +160 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/openapi.yaml +318 -63
- 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), `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
|
|
@@ -960,7 +961,8 @@ paths:
|
|
|
960
961
|
un-started ones settle as interrupted pairs, in-flight tools are NOT collateral. TWO shapes,
|
|
961
962
|
discriminated by `text` presence.
|
|
962
963
|
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`
|
|
964
|
+
`"now"` tier is the VERB's semantics, not a body field (the steer op's own `priority` is a separate
|
|
965
|
+
input: it takes effect only on a server whose `Capabilities.fleet.steerPriority` reads `"engine"`) —
|
|
964
966
|
and the run CONTINUES. 202 `{taskId, status, delivery:"queued-immediate", messageId, note}`;
|
|
965
967
|
`messageId` ≡ the engine inputId, and a real cut is proven ONLY by a `task.turn_interrupted` event on
|
|
966
968
|
the run stream whose `detail.inputId` matches it (core: no false interrupt claims — every real cut
|
|
@@ -2419,9 +2421,10 @@ paths:
|
|
|
2419
2421
|
written. DETERMINISTIC: a retry cannot change it (the SDK does not auto-retry this code; it arrives as a bare `APIError`
|
|
2420
2422
|
with `errorCode: "corrupt"`); the repair is the operator's — fix the file or delete it (deleting = an explicit "no
|
|
2421
2423
|
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
|
-
|
|
2424
|
+
⚠️ The same code also comes from the write path's high-water-mark sidecar (`.hwm.json`) being unreadable: the sentence names the
|
|
2425
|
+
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
|
|
2426
|
+
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
|
|
2427
|
+
still did. Also `internal.error` (unclassified).
|
|
2425
2428
|
content:
|
|
2426
2429
|
application/json:
|
|
2427
2430
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -3039,14 +3042,13 @@ paths:
|
|
|
3039
3042
|
2c session-sync PUSH Phase A — a SMALL metadata body (`entryIds, snapshots, policy, anchors, resolution?`); the
|
|
3040
3043
|
entries stream in Phase B. The cloud classifies (§7), pre-checks blob presence (a missing referenced hash →
|
|
3041
3044
|
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.
|
|
3045
|
+
⚠️ S-15 EPOCH: server ≥7.52's Phase A consumes `{entryIds, fileHistory?, policy, anchors, resolution?,
|
|
3046
|
+
logDigest?}` (routes/session-sync.ts) — the `snapshots` key is SILENTLY IGNORED there (an unknown body key); the
|
|
3047
|
+
file history rides `fileHistory` (a `FileHistoryExport` envelope, `null` / absent = none) and every blob it references must have been
|
|
3048
|
+
`PUT …/sync/blobs/{hash}` first. ≤7.51 servers consume `snapshots` and do not know `fileHistory`. SDK 16.2.0 carries
|
|
3049
|
+
`fileHistory` in `pushSessionBundle` / `importSessionBundle` (and fills `snapshots: []` on the pull side when the manifest omits it); a hand-rolled
|
|
3050
|
+
push must send `fileHistory` itself, and only to a peer whose `capabilities.sessionSyncFileHistory` is not false (server >= 7.116.0 — else the
|
|
3051
|
+
commit 422s `missing_blob`).
|
|
3050
3052
|
`identical` → `{ relation:"identical", basis, payloadVerified }` with NO stagingId (skip Phase B);
|
|
3051
3053
|
`basis` is `"entry-ids+digest"` when the caller supplied a comparable digest and it matched, else
|
|
3052
3054
|
`"entry-ids"` (id-set equality only) — see the `ImportStaged` schema, which has carried these two
|
|
@@ -3063,6 +3065,11 @@ paths:
|
|
|
3063
3065
|
properties:
|
|
3064
3066
|
entryIds: { type: array, items: { type: string } }
|
|
3065
3067
|
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
3068
|
+
fileHistory:
|
|
3069
|
+
oneOf:
|
|
3070
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
3071
|
+
- { type: 'null' }
|
|
3072
|
+
description: 'server >= 7.52: the file-history envelope (replaces `snapshots`); `null` / absent = none. Every blob it references must already be PUT.'
|
|
3066
3073
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
3067
3074
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
3068
3075
|
resolution: { type: string, enum: [overwrite-dst], description: Override a fork/stale loss-of-history conflict. }
|
|
@@ -4639,10 +4646,11 @@ paths:
|
|
|
4639
4646
|
`LEADER_ENABLED` (default OFF) + `REMOTE_EXEC=e2b`. Mode is a SERVER deploy flag, not a client choice:
|
|
4640
4647
|
`LEADER_FANOUT_ENABLED=true` (default) lets the router fan out to N isolated workers (= the value-HOLD
|
|
4641
4648
|
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
|
-
|
|
4649
|
+
is the strong single agent via `/v1/tasks`+`/v1/runs`+`scenario`. When there is no leader face on the deployment
|
|
4650
|
+
(`LEADER_ENABLED` off) the answer depends on the server: server >= 7.116.0 mounts the route unconditionally and answers
|
|
4651
|
+
**501 `capability.leader_endpoint_required`** (new code; under multi-tenant the identity gate's 401 still comes first);
|
|
4652
|
+
<= 7.115.x did not register the route at all → the generic **404** `not_found.route`. Detect "leader unavailable" by
|
|
4653
|
+
`errorCode` (or the `capabilities.leader` bit, which reads the same fact as the gate), not by the status alone.
|
|
4646
4654
|
|
|
4647
4655
|
|
|
4648
4656
|
🔴 IDEMPOTENCY (server >= 7.24.0): this POST now consumes the `Idempotency-Key` header — the header is
|
|
@@ -4783,7 +4791,8 @@ paths:
|
|
|
4783
4791
|
description: >-
|
|
4784
4792
|
(declared 2026-07-31) errorCode "auth.operator_only" — EXPLICIT operator gate (not the bare
|
|
4785
4793
|
isOperator, whose empty-OPERATOR_PRINCIPALS "true-for-all" would make this index-mutating door
|
|
4786
|
-
world-writable).
|
|
4794
|
+
world-writable). With an EMPTY `OPERATOR_PRINCIPALS` the answer is instead 501
|
|
4795
|
+
`capability.operator_principals_required` (server >= 7.116.0; any identity, ahead of authorization).
|
|
4787
4796
|
content:
|
|
4788
4797
|
application/json:
|
|
4789
4798
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4837,7 +4846,7 @@ paths:
|
|
|
4837
4846
|
'400': { $ref: '#/components/responses/BadRequest' }
|
|
4838
4847
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
4839
4848
|
'403':
|
|
4840
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" — EXPLICIT operator gate (§P2.4a).
|
|
4849
|
+
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
4850
|
content:
|
|
4842
4851
|
application/json:
|
|
4843
4852
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4891,7 +4900,7 @@ paths:
|
|
|
4891
4900
|
responses:
|
|
4892
4901
|
'200': { description: '{ bake }.', content: { application/json: { schema: { type: object, required: [bake], additionalProperties: false, properties: { bake: { $ref: '#/components/schemas/BakeRecordView' } } } } } }
|
|
4893
4902
|
'403':
|
|
4894
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" — EXPLICIT operator gate.
|
|
4903
|
+
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
4904
|
content:
|
|
4896
4905
|
application/json:
|
|
4897
4906
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4909,7 +4918,7 @@ paths:
|
|
|
4909
4918
|
responses:
|
|
4910
4919
|
'202': { description: '{ bakeId, cancelRequested, note }.', content: { application/json: { schema: { $ref: '#/components/schemas/BakeCancelAck' } } } }
|
|
4911
4920
|
'403':
|
|
4912
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" — EXPLICIT operator gate.
|
|
4921
|
+
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
4922
|
content:
|
|
4914
4923
|
application/json:
|
|
4915
4924
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -4971,7 +4980,7 @@ paths:
|
|
|
4971
4980
|
responses:
|
|
4972
4981
|
'200': { description: 'SSE stream.', content: { text/event-stream: { schema: { type: string } } } }
|
|
4973
4982
|
'403':
|
|
4974
|
-
description: (declared 2026-07-31) errorCode "auth.operator_only" — EXPLICIT operator gate (this summary previously did not mention the restriction at all).
|
|
4983
|
+
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
4984
|
content:
|
|
4976
4985
|
application/json:
|
|
4977
4986
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -5183,7 +5192,7 @@ paths:
|
|
|
5183
5192
|
schema: { $ref: '#/components/schemas/EntryProvenanceAccount' }
|
|
5184
5193
|
'400': { description: 'errorCode "request.id_invalid" — the entry id could not be decoded.' }
|
|
5185
5194
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5186
|
-
'403': { description: 'errorCode "auth.operator_only" — provenance and erasure are operator-only deployment actions.' }
|
|
5195
|
+
'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
5196
|
'500':
|
|
5188
5197
|
description: >
|
|
5189
5198
|
errorCode "internal.memory_control_plane_corrupt" — core's FAIL-CLOSED refusal: the control plane
|
|
@@ -5253,7 +5262,7 @@ paths:
|
|
|
5253
5262
|
application/json:
|
|
5254
5263
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
5255
5264
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5256
|
-
'403': { description: 'errorCode "auth.operator_only" — provenance and erasure are operator-only deployment actions.' }
|
|
5265
|
+
'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
5266
|
'409':
|
|
5258
5267
|
description: >
|
|
5259
5268
|
Three core-minted codes, passed through verbatim; branch on `errorCode` (the status cannot tell them
|
|
@@ -5332,7 +5341,7 @@ paths:
|
|
|
5332
5341
|
schema: { $ref: '#/components/schemas/MemoryOriginExternalResult' }
|
|
5333
5342
|
'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
5343
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5335
|
-
'403': { description: 'errorCode "auth.operator_only" — origin marking and clearance are operator-only deployment actions.' }
|
|
5344
|
+
'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
5345
|
'500':
|
|
5337
5346
|
description: 'errorCode "internal.memory_control_plane_corrupt" (meaning (1) only on this read face) or "internal.error" (unclassified, text not echoed).'
|
|
5338
5347
|
content:
|
|
@@ -5382,7 +5391,7 @@ paths:
|
|
|
5382
5391
|
application/json:
|
|
5383
5392
|
schema: { $ref: '#/components/schemas/MemoryOriginClearancesResult' }
|
|
5384
5393
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5385
|
-
'403': { description: 'errorCode "auth.operator_only" — origin marking and clearance are operator-only deployment actions.' }
|
|
5394
|
+
'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
5395
|
'500':
|
|
5387
5396
|
description: 'errorCode "internal.memory_control_plane_corrupt" (the ledger cannot be read soundly) or "internal.error".'
|
|
5388
5397
|
content:
|
|
@@ -5446,7 +5455,7 @@ paths:
|
|
|
5446
5455
|
application/json:
|
|
5447
5456
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
5448
5457
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5449
|
-
'403': { description: 'errorCode "auth.operator_only" — origin marking and clearance are operator-only deployment actions.' }
|
|
5458
|
+
'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
5459
|
'409':
|
|
5451
5460
|
description: >
|
|
5452
5461
|
Six core-minted codes, passed through verbatim; BRANCH ON `errorCode` — the six operator actions all
|
|
@@ -5569,7 +5578,7 @@ paths:
|
|
|
5569
5578
|
application/json:
|
|
5570
5579
|
schema: { $ref: '#/components/schemas/WiringDiagnostics' }
|
|
5571
5580
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
5572
|
-
'403': { description: 'Multi-tenant worker: wiring diagnostics are operator-only (`auth.operator_only`).' }
|
|
5581
|
+
'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
5582
|
'404': { description: 'This worker serves no wiring diagnostics (older server, or a process not assembled by the composition root).' }
|
|
5574
5583
|
|
|
5575
5584
|
/v1/sendfile-links:
|
|
@@ -5899,7 +5908,9 @@ paths:
|
|
|
5899
5908
|
description: >
|
|
5900
5909
|
OPERATOR-ONLY cross-tenant read. Absent (or equal to the caller's own principal) = read your own
|
|
5901
5910
|
rules. Anything else requires explicit OPERATOR_PRINCIPALS membership ⇒ otherwise 403
|
|
5902
|
-
`auth.operator_only
|
|
5911
|
+
`auth.operator_only` (server >= 7.116.0: with an EMPTY list the answer is 501
|
|
5912
|
+
`capability.operator_principals_required` instead — any identity, ahead of authorization; your own rules never
|
|
5913
|
+
go through the operator gate). Rule text contains command shapes, so third-party reads are an information
|
|
5903
5914
|
disclosure and are deliberately not opened to non-operators.
|
|
5904
5915
|
- name: scope
|
|
5905
5916
|
in: query
|
|
@@ -6644,7 +6655,14 @@ components:
|
|
|
6644
6655
|
application/json:
|
|
6645
6656
|
schema: { $ref: '#/components/schemas/QuotaError' }
|
|
6646
6657
|
NotImplemented:
|
|
6647
|
-
description:
|
|
6658
|
+
description: >
|
|
6659
|
+
501 — "this deployment cannot answer this" (e.g. no TiDB run store; `wake` unsupported). server >= 7.116.0: HTTP has exactly ONE status for
|
|
6660
|
+
"unavailable on this deployment" — 501 — and the CAUSE is the code: `capability.*` = change the deployment shape / wire the facility
|
|
6661
|
+
(incl. the new `capability.leader_endpoint_required` for `/v1/leader*` and `capability.shared_memory_required` for `/v1/shared-memory/*`),
|
|
6662
|
+
`feature.*` = turn a knob on (incl. the new `feature.memory_consolidation_disabled` and `feature.config_catalog_disabled`), and
|
|
6663
|
+
`capability.operator_principals_required` = configure `OPERATOR_PRINCIPALS` (every operator-only endpoint answers it, for any identity,
|
|
6664
|
+
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
|
|
6665
|
+
(these families answered 404 / 403 on <= 7.115.x). The one registered exception is `a2aServe`'s two routes (404, anti-fingerprint).
|
|
6648
6666
|
content:
|
|
6649
6667
|
application/json:
|
|
6650
6668
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -6824,7 +6842,18 @@ components:
|
|
|
6824
6842
|
name: { type: string }
|
|
6825
6843
|
description: { type: string }
|
|
6826
6844
|
content: { type: string }
|
|
6827
|
-
manifest:
|
|
6845
|
+
manifest:
|
|
6846
|
+
type: object
|
|
6847
|
+
additionalProperties: true
|
|
6848
|
+
deprecated: true
|
|
6849
|
+
description: >
|
|
6850
|
+
RETIRED — server >= 7.116.0 rejects the WHOLE skill when this key is present on a delegated agent's skill (unknown key:
|
|
6851
|
+
`agent.skills must be …`; a top-level skill answers 400 `request.field_invalid` "skill.manifest was retired in core 7.41.0 — …").
|
|
6852
|
+
core 7.41.0 retired the skill manifest (hard break, no alias). Rewrite `manifest.allowTools` to the skill's
|
|
6853
|
+
`allowedTools` (an allow-rule source, not a fence); `manifest.allowPaths` has no replacement (use the session rules'
|
|
6854
|
+
`allowDirs`). Older servers (<= 7.115.x) still accept it; the key stays declared here until the next major.
|
|
6855
|
+
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).' }
|
|
6856
|
+
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
6857
|
files:
|
|
6829
6858
|
type: array
|
|
6830
6859
|
items:
|
|
@@ -6933,6 +6962,18 @@ components:
|
|
|
6933
6962
|
LISTING RENDERER, not to this gate: turn it down with `settings.skillListingBudgetFraction` /
|
|
6934
6963
|
`settings.skillListingMaxDescChars`.
|
|
6935
6964
|
items: { $ref: '#/components/schemas/SkillSpec' }
|
|
6965
|
+
userInvokedSkills:
|
|
6966
|
+
type: array
|
|
6967
|
+
items: { type: string, minLength: 1 }
|
|
6968
|
+
description: >
|
|
6969
|
+
server >= 7.116.0 (core 7.41.0 #1303). Skills the HUMAN called by name (the shell parses the typed `/name`; by `SkillSpec.name`).
|
|
6970
|
+
Their `allowedTools` / `disallowedTools` take effect from the start of the run and NO `Skill` card is raised (the human naming
|
|
6971
|
+
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
|
|
6972
|
+
a skill the run carries (scenario factory ∪ this request's `skills`), else the engine refuses to start: 400
|
|
6973
|
+
`config.user_invoked_skill_unknown` (sync leg `POST /v1/tasks`; the async / live-stream legs answer 2xx and the same code lands on the
|
|
6974
|
+
terminal run row; `disableSkills: true` makes any name this code). A bad value shape (bare string / empty-string member / non-string /
|
|
6975
|
+
object / null) is a 400 `request.field_invalid`. Does not deliver the skill body. PROBE `capabilities.userInvokedSkills` (constant true);
|
|
6976
|
+
absent = an older server that answers 400 `request.body_shape` listing the key in `unknownKeys` — do not send it.
|
|
6936
6977
|
reasoningEffort:
|
|
6937
6978
|
type: string
|
|
6938
6979
|
enum: [off, minimal, low, medium, high, xhigh, max]
|
|
@@ -7300,8 +7341,11 @@ components:
|
|
|
7300
7341
|
for that). For "only these tools" use the real knobs: the session rule `toolAllow`
|
|
7301
7342
|
(`PUT /v1/sessions/{sessionId}/policy`), per-request `excludeTools` / `excludeAllTools`, or the deployment's scenario
|
|
7302
7343
|
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
|
-
|
|
7344
|
+
and compiled as a whole-tool rule; server >= 7.116.0 also accepts the two-segment covering form `mcp__<server>` / `a2a__<peer>`,
|
|
7345
|
+
read as the whole server — same meaning as `mcp__<server>__*`); a retired name, a short name with no protocol prefix, a missing-segment
|
|
7346
|
+
name (`mcp__` / `mcp__<server>__`), a protocol name whose server segment the engine cannot have minted (e.g. `mcp__github.com__*` —
|
|
7347
|
+
write `mcp__github_com__*`; server >= 7.116.0 refuses it with a 422 instead of accepting a rule that can never match), a backslash,
|
|
7348
|
+
more than 512 characters, or a CONTENT form
|
|
7305
7349
|
(`Bash(npm:*)`, `Read(./x)`, `WebFetch(domain:...)`) is a whole-request 422 (permanent content-form allows live in the
|
|
7306
7350
|
persistent rule store: `/v1/rules/cc-import`, or answer yes on a card). The same applies to a PreToolUse hook: an
|
|
7307
7351
|
EXPLICIT `permissionDecision: "allow"` states it (and binds only the arguments the hook saw); a hook that only adds
|
|
@@ -8218,6 +8262,16 @@ components:
|
|
|
8218
8262
|
is unchanged at 7.64.0 — only its source moved (projected from `result.terminal`, or read straight
|
|
8219
8263
|
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
8264
|
`review.pending` (absent before) — never read "errorCode present" as "failed"; read `status` first.
|
|
8265
|
+
🔴 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`
|
|
8266
|
+
sentence: `run.stalled` (heartbeat-lost reap — and the read-time fold that precedes the reap; sentence `run stalled (instance lost?)`),
|
|
8267
|
+
`run.orphaned` (local-lane restart / session-occupancy takeover reclaim; sentence `run orphaned by engine restart`) and
|
|
8268
|
+
`approval.expired` (the expiry reap of a durably parked approval; the column already carried it, the read face did not project it;
|
|
8269
|
+
sentence `approval expired before decision`). None of the three means the request was wrong — resending the same request is
|
|
8270
|
+
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
|
|
8271
|
+
default arm). ABSENCE: rows written by <= 7.115.x carry only the sentence; a one-time startup migration backfills the code
|
|
8272
|
+
(log `one_time_migrations_applied` `holderDeathCodeRowsBackfilled`) and a new replica reads such a row as the code during the upgrade window,
|
|
8273
|
+
but the migration has a window (30 days after the release, then the write-back and the read half are deleted) — so
|
|
8274
|
+
"no `errorCode`" never proves "not a holder death": rows migrated late or after the window stay sentence-only.
|
|
8221
8275
|
error: { type: string }
|
|
8222
8276
|
jobId:
|
|
8223
8277
|
type: string
|
|
@@ -9029,7 +9083,8 @@ components:
|
|
|
9029
9083
|
server >=7.12.0 — the `GET /v1/outcomes` mechanical-signal read aggregate (design/73 §7.2) is
|
|
9030
9084
|
available. Predicate mirrors the route's refusal arms exactly: a QUERYABLE ledger is wired (a
|
|
9031
9085
|
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)
|
|
9086
|
+
operator list is non-empty (single-user has no such gate — the only user IS the operator); with an empty
|
|
9087
|
+
list the multi-tenant route answers 501 `capability.operator_principals_required` (server >= 7.116.0; 403 before).
|
|
9033
9088
|
Added because this face previously had a 501 but NO capability bit, leaving consumers to
|
|
9034
9089
|
trial-by-501 — the exact pattern this capability surface exists to remove.
|
|
9035
9090
|
images:
|
|
@@ -9053,7 +9108,17 @@ components:
|
|
|
9053
9108
|
principal→org membership fold present), so true ⟺ the face actually works — a deployment with
|
|
9054
9109
|
the store but no membership authority deliberately reports false (and does not mount the routes).
|
|
9055
9110
|
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
|
|
9111
|
+
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)." }
|
|
9112
|
+
workflowsJournal:
|
|
9113
|
+
type: boolean
|
|
9114
|
+
description: >
|
|
9115
|
+
server >= 7.116.0 (predicate class "facility": the workflow run store AND the journal store). Advertises
|
|
9116
|
+
`GET /v1/workflows/{id}/journal`. On a deployment with the run store but no journal store (`DB_BACKEND=memory`,
|
|
9117
|
+
multi-tenant bare boot, SQL coordinates not fully configured) with self-orchestration on, `workflowsList` is true
|
|
9118
|
+
and this is false; the journal face then answers 501 `capability.workflow_store_required` (any id, ahead of the
|
|
9119
|
+
per-row owner check; `capability.self_orchestration_required` when the run store is absent). A journal entry point reads THIS bit, not
|
|
9120
|
+
`workflowsList`. ABSENT = an older server (<= 7.115.x): fall back to `workflowsList` (the old behaviour — the
|
|
9121
|
+
bit could be true while the journal face always answers 501).
|
|
9057
9122
|
workflowModels:
|
|
9058
9123
|
type: array
|
|
9059
9124
|
items: { type: string }
|
|
@@ -9096,8 +9161,8 @@ components:
|
|
|
9096
9161
|
(DESIGN-278 §5 S2 — deployment config self-description) is mounted on this DEPLOYMENT. TWO-term
|
|
9097
9162
|
conjunction, written against the route's own refusal arms: ① the `CONFIG_CATALOG_ENABLED` knob is
|
|
9098
9163
|
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
|
|
9164
|
+
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
|
|
9165
|
+
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
9166
|
identity is NOT in the predicate — the route additionally requires the CURRENT principal to be an
|
|
9102
9167
|
explicit operator (`routes/config-catalog.ts` `explicitOperatorOk`, else 403 `auth.operator_only`),
|
|
9103
9168
|
so a non-operator reads `true` and still gets 403. Show/invoke the catalog only for an identity you
|
|
@@ -9117,8 +9182,15 @@ components:
|
|
|
9117
9182
|
`false`/absent otherwise (same predicate as the route's 501). `resume: "snapshot"` is a semantic
|
|
9118
9183
|
advertisement: the bus is latest-state (not an event log) and every connection opens with a full
|
|
9119
9184
|
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
|
-
|
|
9185
|
+
bg_notification frames re-deliver via the durable completion inbox. `steerPriority` (a string, open
|
|
9186
|
+
set) says whether the steer body's `priority` takes effect on THIS server: `steerPriority: "advisory"`
|
|
9187
|
+
(server <=7.115.x) = accepted + enum-validated + echoed but a no-op (nothing is handed to the engine);
|
|
9188
|
+
`steerPriority: "engine"` (server >=7.116.0) = `priority` (`now` / `next` / `later`) is handed to the
|
|
9189
|
+
engine as the injection tier, and the engine owns what each tier means — `now` cuts the in-flight turn
|
|
9190
|
+
IMMEDIATELY (the running tool receives an abort, an approval card pending on this replica is revoked; one `engine_notice`
|
|
9191
|
+
`task.turn_interrupted` frame is the evidence), `later` is delivered after the turn the run would have stopped on, no `priority` =
|
|
9192
|
+
`next`. Read this bit before offering a `priority` choice; an absent
|
|
9193
|
+
or unknown value means "do not assume it takes effect", never `"engine"`.
|
|
9122
9194
|
oneOf:
|
|
9123
9195
|
- type: boolean
|
|
9124
9196
|
enum: [false]
|
|
@@ -9373,9 +9445,25 @@ components:
|
|
|
9373
9445
|
S-15 换店; ≤7.51 the last conjunct was the file-snapshot store). Gate the whole sync surface off
|
|
9374
9446
|
this. ⚠️ The two BLOB faces (PUT …/sync/blobs/{hash}, GET …/sync/history/blobs/{hash})
|
|
9375
9447
|
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.
|
|
9448
|
+
file backend has none): without them BOTH answer 501 `capability.snapshot_store_required`
|
|
9449
|
+
(server >= 7.116.0; the history PULL answered a no-oracle 404 `not_found.blob` there on <= 7.115.x),
|
|
9450
|
+
while the REST of the sync surface keeps working. Since server >= 7.116.0 the two blob faces are
|
|
9451
|
+
advertised by their own bit `sessionSyncFileHistory`; this bit speaks for the conversation half
|
|
9452
|
+
(its predicate additionally requires a session-policy store that can purge, `deleteBySession` —
|
|
9453
|
+
a deployment whose embedder-supplied store lacks it answers the whole family 501
|
|
9454
|
+
`capability.policy_purge_required` and this bit is false).
|
|
9455
|
+
sessionSyncFileHistory:
|
|
9456
|
+
type: boolean
|
|
9457
|
+
description: >
|
|
9458
|
+
server >= 7.116.0 (predicate class "facility": `sessionSync` AND the file-history store has blob transfer faces
|
|
9459
|
+
— SQL backends only; `DB_BACKEND=local` is always false). Advertises exactly the two file-history blob faces
|
|
9460
|
+
`PUT /v1/sessions/{sessionId}/sync/blobs/{hash}` and `GET /v1/sessions/{sessionId}/sync/history/blobs/{hash}`.
|
|
9461
|
+
READ IT ON BOTH ENDS of a sync: if either is false, sync the conversation only — do not push `fileHistory`, do
|
|
9462
|
+
not PUT blobs (a `fileHistory` pushed to a peer without the blob faces 422s `missing_blob` after commit). When
|
|
9463
|
+
false the two routes answer 501 `capability.snapshot_store_required` (any session id, ahead of the owner check).
|
|
9464
|
+
A blob that the session history graph does not reference / whose bytes are gone stays a 404 `not_found.blob`.
|
|
9465
|
+
ABSENT = an older server (<= 7.115.x): the bit cannot be read there (a `DB_BACKEND=local` deployment with
|
|
9466
|
+
`sessionSync: true` answered PUT blob 501 on every call), so try as before.
|
|
9379
9467
|
|
|
9380
9468
|
# ─── S-139(sdk 8.3.0):对 server 7.60.0 的整体重对账补齐的 19 位 ───────────────────────
|
|
9381
9469
|
# 行号 = server 7.60.0 树的 `src/http/routes/capabilities.ts`。语义与谓词的全文在
|
|
@@ -9468,7 +9556,8 @@ components:
|
|
|
9468
9556
|
description: >
|
|
9469
9557
|
Governance carry-out bundle pair `POST /v1/memory/{export,import}` (operator lane) —
|
|
9470
9558
|
capabilities.ts:261, two conjuncts: both engine seams wired AND `operatorPrincipals` NON-EMPTY
|
|
9471
|
-
(an empty roster makes those routes
|
|
9559
|
+
(an empty roster makes those routes refuse every identity — 501 `capability.operator_principals_required` on
|
|
9560
|
+
server >= 7.116.0, 403 before). True does not promise the backend
|
|
9472
9561
|
has the bundle composite face (core then refuses loudly with `memory.export_incomplete`).
|
|
9473
9562
|
memoryCompliance:
|
|
9474
9563
|
type: boolean
|
|
@@ -9570,10 +9659,13 @@ components:
|
|
|
9570
9659
|
a2aServe:
|
|
9571
9660
|
type: boolean
|
|
9572
9661
|
description: >
|
|
9573
|
-
Server-as-peer
|
|
9574
|
-
`
|
|
9575
|
-
|
|
9576
|
-
|
|
9662
|
+
Server-as-peer: true ⟺ `GET /.well-known/agent-card.json` and `POST /v1/a2a` exist; false ⟺ both 404
|
|
9663
|
+
(`not_found.route`, anti-fingerprint — the one registered exception to "unavailable = 501"). server >= 7.116.0
|
|
9664
|
+
predicate (class "facility + config"): the `A2A_SERVE_ENABLED` knob AND a durable run store; <= 7.115.x looked at the knob
|
|
9665
|
+
only (`config.a2aServe !== undefined`). 🔴 value change: with the knob on but NO durable run store
|
|
9666
|
+
(`DB_BACKEND=memory`, multi-tenant bare boot) this bit is now false and the card and the RPC both answer 404 (7.115.x:
|
|
9667
|
+
true, card 200, every `message/send` / `tasks/get` a JSON-RPC `-32004`); the startup log carries a warn
|
|
9668
|
+
`a2a_serve_not_served`. The old "the server deliberately does not fold the run store into this bit" note is retired.
|
|
9577
9669
|
agentRoster:
|
|
9578
9670
|
type: boolean
|
|
9579
9671
|
description: >
|
|
@@ -9768,6 +9860,23 @@ components:
|
|
|
9768
9860
|
answers the request key with a 400 `request.body_shape` naming it under `unknownKeys` — do not send the key
|
|
9769
9861
|
there and tell the user the factory skills stay installed. True only says "this server knows the key", not
|
|
9770
9862
|
whether the deployment has any factory skills.
|
|
9863
|
+
userInvokedSkills:
|
|
9864
|
+
type: boolean
|
|
9865
|
+
enum: [true]
|
|
9866
|
+
description: >
|
|
9867
|
+
server >= 7.116.0 (constant true; no predicate, no tenant gate) — the ADVANCE READING for the request key
|
|
9868
|
+
`TaskRequest.userInvokedSkills` (skills the human named; effective from the start of the run, no `Skill` card);
|
|
9869
|
+
the bit and the key are the SAME word. ABSENT = an older server (<= 7.115.x), which answers the key with a 400
|
|
9870
|
+
`request.body_shape` naming it under `unknownKeys` — do not send it there.
|
|
9871
|
+
skillToolLists:
|
|
9872
|
+
type: boolean
|
|
9873
|
+
enum: [true]
|
|
9874
|
+
description: >
|
|
9875
|
+
server >= 7.116.0 (constant true) — the skill tool lists `allowedTools` / `disallowedTools` TAKE EFFECT (allow-rule /
|
|
9876
|
+
deny-rule source; see `SkillSpec.allowedTools`). ABSENT = an older server (<= 7.115.x): on a top-level skill the two
|
|
9877
|
+
lists are accepted but the engine does not read them — they are silently inert and there is NO 400 to probe, so do not
|
|
9878
|
+
expect them to stop a tool (fence with deny rules instead); on a delegated agent's skill they are an unknown key that
|
|
9879
|
+
rejects the whole skill.
|
|
9771
9880
|
WriteProtectionCapability:
|
|
9772
9881
|
type: object
|
|
9773
9882
|
additionalProperties: false
|
|
@@ -9902,11 +10011,42 @@ components:
|
|
|
9902
10011
|
engine refuses the skill outright at load time, so the HTTP face answers first where the caller can read it).
|
|
9903
10012
|
The bound is 1 048 576 **UTF-16 code units** (`MAX_SKILL_CONTENT_CHARS`); see the STRING-LENGTH UNIT
|
|
9904
10013
|
convention in `info.description` for why this `maxLength` states that number verbatim.
|
|
10014
|
+
🔴 server >= 7.116.0 (core 7.41.0): a skill carries two TOOL LISTS, `allowedTools` / `disallowedTools` — the
|
|
10015
|
+
run-scoped ALLOW-RULE and DENY-RULE source of the skill once it is activated. NOT a fence (<= 7.115.x the engine read
|
|
10016
|
+
the skill's tool list as "only these"): unlisted tools are judged as usual, listed ones are not asked about for the rest
|
|
10017
|
+
of the run — which makes it WIDER than `settings.permissions.allow` (that one stays a statement and does not
|
|
10018
|
+
release the engine's own write gate / shell ordinary asks on built-in tools). Probe `capabilities.skillToolLists`
|
|
10019
|
+
(absent = an old server that accepts the keys on a top-level skill and silently ignores them). The skill's `manifest`
|
|
10020
|
+
key is RETIRED: any value on a top-level skill is a 400 `request.field_invalid` ("skill.manifest was retired in core
|
|
10021
|
+
7.41.0 — …"; rewrite `manifest.allowTools` to `allowedTools`; `allowPaths` has no replacement), and on a delegated
|
|
10022
|
+
agent's skill (`agents[].skills[]`) it is an unknown key that rejects the whole skill.
|
|
9905
10023
|
required: [name, description, content]
|
|
9906
10024
|
properties:
|
|
9907
10025
|
name: { type: string, minLength: 1 }
|
|
9908
10026
|
description: { type: string }
|
|
9909
10027
|
content: { type: string, minLength: 1, maxLength: 1048576 }
|
|
10028
|
+
allowedTools:
|
|
10029
|
+
type: array
|
|
10030
|
+
items: { type: string }
|
|
10031
|
+
description: >
|
|
10032
|
+
server >= 7.116.0. The skill's run-scoped ALLOW-RULE source (permission-rule spellings: a tool name,
|
|
10033
|
+
`mcp__<server>` / `mcp__<server>__*`; `*`, write paths and domain forms grant nothing). Once the skill is activated
|
|
10034
|
+
(named in top-level `userInvokedSkills` — no `Skill` card — or activated by the model and the card approved) the
|
|
10035
|
+
listed tools are not asked about for the rest of the run: it clears the engine's ordinary and "nobody stated it" asks,
|
|
10036
|
+
so it is WIDER than `settings.permissions.allow`; deny / ask rules, `APPROVAL_REQUIRE`, `APPROVAL_NEVER_AUTO`, the shell
|
|
10037
|
+
floor, write protection and plan-mode asks are not cleared. NOT a fence: unlisted tools are judged as usual. A non-string-array
|
|
10038
|
+
is a 400 `request.field_invalid`; a protocol name whose server segment cannot be minted / is missing / is a wildcard
|
|
10039
|
+
(`mcp__*`) is a 400 too (top-level `skills[]` and `agents[].skills[]` judge identically). Probe `capabilities.skillToolLists`.
|
|
10040
|
+
disallowedTools:
|
|
10041
|
+
type: array
|
|
10042
|
+
items: { type: string }
|
|
10043
|
+
description: >
|
|
10044
|
+
server >= 7.116.0. The skill's run-scoped DENY-RULE source (same grammar / gates / probe as `allowedTools`): once the skill
|
|
10045
|
+
is activated these tools are refused for the run (no execution, no card; `tool_end.gate.disposition` is
|
|
10046
|
+
`{ kind: "denied", deniedBy: "policy" }`). `*` and domain forms (`WebFetch(domain:…)`) read as "none" on this side too —
|
|
10047
|
+
accepted with 2xx and only an operator-audience notice `skills.allowed_tool_not_granted`; write-path forms and the rest compile
|
|
10048
|
+
into deny rows (as the server contract states it for the engine's `compileSkillGrant`; the SDK did not re-run the engine on the deny side's write-path forms —
|
|
10049
|
+
the engine's own notice text lists "a write-path or domain entry" among entries that "grant (or refuse) nothing").
|
|
9910
10050
|
|
|
9911
10051
|
McpServerSpec:
|
|
9912
10052
|
type: object
|
|
@@ -11841,6 +11981,11 @@ components:
|
|
|
11841
11981
|
expiresAtMs: { type: number, description: 'Absolute window deadline — the SAME number minted once for the tool_approval frame (never recomputed).' }
|
|
11842
11982
|
sessionId: { type: string }
|
|
11843
11983
|
requiresRealApproval: { type: boolean, enum: [true] }
|
|
11984
|
+
rememberRefused:
|
|
11985
|
+
type: boolean
|
|
11986
|
+
enum: [true]
|
|
11987
|
+
description: >-
|
|
11988
|
+
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
11989
|
governanceForced: { type: boolean, enum: [true] }
|
|
11845
11990
|
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
11991
|
mandate:
|
|
@@ -12003,6 +12148,9 @@ components:
|
|
|
12003
12148
|
Present ⇔ the request carried `remember:"session"` and the worker has an exemption store. `true` = the
|
|
12004
12149
|
per-session per-tool exemption landed; `false` = the grant failed (logged) or the gate carried no
|
|
12005
12150
|
rememberable toolName — the decision itself still stands.
|
|
12151
|
+
🔴 server >= 7.116.0: ALWAYS `false` on a card that carries `rememberRefused: true` (an engine `Skill` card etc. — the
|
|
12152
|
+
answer would also grant more than this one call): the decision is accepted and applies once, the exemption store gets
|
|
12153
|
+
zero writes (existing key, not a new one). Ordinary cards keep `true` = landed.
|
|
12006
12154
|
|
|
12007
12155
|
ApprovalExemption:
|
|
12008
12156
|
type: object
|
|
@@ -12146,6 +12294,11 @@ components:
|
|
|
12146
12294
|
🔴 DISPLAY / TRIAGE ONLY, and ABSENT MEANS THERE REALLY IS NO SUPPLY (rule lane unarmed, the
|
|
12147
12295
|
command yields no rule, no rule could silence this ask, or an old row) — never "the projection
|
|
12148
12296
|
dropped it", which is precisely the bug this key exists to close. Never `null`, never `[]`.
|
|
12297
|
+
rememberRefused:
|
|
12298
|
+
type: boolean
|
|
12299
|
+
enum: [true]
|
|
12300
|
+
description: >-
|
|
12301
|
+
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
12302
|
governanceForced:
|
|
12150
12303
|
type: boolean
|
|
12151
12304
|
enum: [true]
|
|
@@ -13098,31 +13251,97 @@ components:
|
|
|
13098
13251
|
type: object
|
|
13099
13252
|
description: >
|
|
13100
13253
|
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
|
-
|
|
13254
|
+
snapshot: entry IDS (oldest-first, NOT payloads) + the file-history envelope + policy + anchors + leaf.
|
|
13255
|
+
🔴 server >= 7.52 (S-15, design/381; re-read byte for byte against 7.116.0): the key `snapshots` (per-snapshot
|
|
13256
|
+
relPath→blobHash, the retired E19 whole-tree snapshot epoch) is NO LONGER SENT — the server's `exportSessionManifest` mints
|
|
13257
|
+
`{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }` and `fileHistory` (core's versioned
|
|
13258
|
+
`FileHistoryExport` envelope; `null` = no history / the source store cannot export) replaces it. <= 7.51 servers still send
|
|
13259
|
+
`snapshots` and no `fileHistory`. The blob BYTES never ride the manifest: content-addressed, via the history blob faces
|
|
13260
|
+
(`GET …/sync/history/blobs/{hash}` / `PUT …/sync/blobs/{hash}`; probe `capabilities.sessionSyncFileHistory` on BOTH ends).
|
|
13261
|
+
The SDK's `manifest()` fills `snapshots: []` when the wire omits it.
|
|
13262
|
+
# 封闭(census 批2 第三段,2026-07-30;16.2.0 按 7.116.0 发布字节重核):铸造点 `session-sync.ts`(exportSessionManifest 尾部
|
|
13263
|
+
# 字面量)恰是 `{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }` 7 键(≥7.52),无 `snapshots`;
|
|
13264
|
+
# ≤7.51 老 server 发 `snapshots`、无 `fileHistory` ⇒ 两键都不进 required(支持底线 3.0.0)。
|
|
13104
13265
|
additionalProperties: false
|
|
13105
|
-
required: [sessionId, entryIds, entryCount, leafId,
|
|
13266
|
+
required: [sessionId, entryIds, entryCount, leafId, policy, anchors]
|
|
13106
13267
|
properties:
|
|
13107
13268
|
sessionId: { type: string }
|
|
13108
13269
|
entryIds: { type: array, items: { type: string }, description: Oldest-first, verbatim cross-backend. }
|
|
13109
13270
|
entryCount: { type: integer, description: '= entryIds.length (the `/sync/entries` trailer count).' }
|
|
13110
13271
|
leafId: { type: [string, 'null'] }
|
|
13111
|
-
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
13272
|
+
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`.' }
|
|
13273
|
+
fileHistory:
|
|
13274
|
+
oneOf:
|
|
13275
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
13276
|
+
- { type: 'null' }
|
|
13277
|
+
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
13278
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
13113
13279
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
13114
13280
|
|
|
13281
|
+
FileHistoryExport:
|
|
13282
|
+
type: object
|
|
13283
|
+
description: >
|
|
13284
|
+
Mirror of core's `FileHistoryExport` (`formatVersion: "file-history/1"`) — the session-sync envelope for the per-edited-file rewind history graph
|
|
13285
|
+
(server >= 7.52; replaces the retired E19 `SyncSnapshot`). Blob bytes are NOT inside: they are content-addressed and travel through the history blob faces.
|
|
13286
|
+
The SDK reads only `tracked[].versions[].blobHash` (which blobs to move) and passes everything else through verbatim — the server's import door judges
|
|
13287
|
+
`formatVersion` (refuse-not-coerce) and the closed `keyKind` / `keyFamily` sets, so they are plain strings here.
|
|
13288
|
+
required: [formatVersion, tracked, boundaries]
|
|
13289
|
+
properties:
|
|
13290
|
+
formatVersion: { type: string, description: 'today only `file-history/1`; the server refuses any other value.' }
|
|
13291
|
+
tracked:
|
|
13292
|
+
type: array
|
|
13293
|
+
items:
|
|
13294
|
+
type: object
|
|
13295
|
+
required: [relOrAbsPath, keyKind, keyFamily, baseAvailable, versions]
|
|
13296
|
+
properties:
|
|
13297
|
+
relOrAbsPath: { type: string }
|
|
13298
|
+
keyKind: { type: string }
|
|
13299
|
+
keyFamily: { type: string }
|
|
13300
|
+
baseAvailable: { type: boolean }
|
|
13301
|
+
versions:
|
|
13302
|
+
type: array
|
|
13303
|
+
items:
|
|
13304
|
+
type: object
|
|
13305
|
+
required: [version, blobHash, backupTime]
|
|
13306
|
+
properties:
|
|
13307
|
+
version: { type: integer }
|
|
13308
|
+
blobHash: { type: [string, 'null'], description: '`null` = the "did not exist" marker (no blob to move).' }
|
|
13309
|
+
mode: { type: integer }
|
|
13310
|
+
parentIdent: { type: string }
|
|
13311
|
+
backupTime: { type: string }
|
|
13312
|
+
boundaries:
|
|
13313
|
+
type: array
|
|
13314
|
+
items:
|
|
13315
|
+
type: object
|
|
13316
|
+
required: [entryId, files]
|
|
13317
|
+
properties:
|
|
13318
|
+
entryId: { type: string }
|
|
13319
|
+
files:
|
|
13320
|
+
type: array
|
|
13321
|
+
items:
|
|
13322
|
+
type: object
|
|
13323
|
+
required: [relOrAbsPath, version]
|
|
13324
|
+
properties:
|
|
13325
|
+
relOrAbsPath: { type: string }
|
|
13326
|
+
version: { type: integer }
|
|
13327
|
+
|
|
13115
13328
|
SessionBundle:
|
|
13116
13329
|
type: object
|
|
13117
13330
|
description: >
|
|
13118
13331
|
The portable state of ONE session, ready to replay into another backend. Blobs are NOT inlined (each
|
|
13119
13332
|
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.
|
|
13333
|
+
assembles this from a manifest + the streamed entries for a PUSH. server >= 7.52: the file history rides `fileHistory`
|
|
13334
|
+
(the `FileHistoryExport` envelope) instead of `snapshots`.
|
|
13121
13335
|
required: [sessionId, entries, snapshots, policy, anchors]
|
|
13122
13336
|
properties:
|
|
13123
13337
|
sessionId: { type: string }
|
|
13124
13338
|
entries: { type: array, items: { $ref: '#/components/schemas/SyncEntry' } }
|
|
13125
13339
|
snapshots: { type: array, items: { $ref: '#/components/schemas/SyncSnapshot' } }
|
|
13340
|
+
fileHistory:
|
|
13341
|
+
oneOf:
|
|
13342
|
+
- { $ref: '#/components/schemas/FileHistoryExport' }
|
|
13343
|
+
- { type: 'null' }
|
|
13344
|
+
description: 'server >= 7.52 file-history envelope (same as `SessionManifest.fileHistory`); key absent = the source is a <= 7.51 server.'
|
|
13126
13345
|
policy: { type: array, items: { $ref: '#/components/schemas/SessionRulesRecord' } }
|
|
13127
13346
|
anchors: { type: array, items: { $ref: '#/components/schemas/SyncAnchor' } }
|
|
13128
13347
|
|
|
@@ -13985,10 +14204,17 @@ components:
|
|
|
13985
14204
|
unattended leg run under `UNATTENDED_PERMISSION_MODE=dontAsk`).
|
|
13986
14205
|
AskClass:
|
|
13987
14206
|
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
|
|
14207
|
+
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]
|
|
14208
|
+
description: >
|
|
14209
|
+
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
|
|
14210
|
+
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
|
|
14211
|
+
server >= 7.116.0) — which CLASS an ask falls in (the columns of the mode × class arbitration table).
|
|
14212
|
+
`requires_user_interaction` = the MCP server declared, in the tool's advertisement, `_meta["anthropic/requiresUserInteraction"] === true`
|
|
14213
|
+
(only the boolean `true`): EVERY call of that tool asks the human, in EVERY mode including `bypassPermissions` (it is not one of the ten
|
|
14214
|
+
RELEASABLE classes), and only the human's answer clears it — `settings.permissions.allow`, operator `APPROVAL_GRANT`, a skill's tool list +
|
|
14215
|
+
`userInvokedSkills` and a hook's explicit allow all fail to; with no approval seat the call is refused (the server sees nothing). The frame
|
|
14216
|
+
also carries `requiresRealApproval: true` / `mandated: true` (`origin: "safety_tighten"`). A client that renders cards by exhaustive `askClass`
|
|
14217
|
+
adds this one word.
|
|
13992
14218
|
`unstated` = NOBODY STATED IT: in an ask-class mode (`default` / `acceptEdits` / `auto` / `plan`) a call to an MCP server tool or A2A skill
|
|
13993
14219
|
(a seat that states no permission of its own) reached the end of the fold with no layer — rule / hook / approver / classifier / mode
|
|
13994
14220
|
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 +15815,11 @@ components:
|
|
|
15589
15815
|
args:
|
|
15590
15816
|
description: '"tool_approval" only: the call''s args, secret-redacted. UNTRUSTED for display. Absent (with argsOmitted) when over the byte cap or unserializable.'
|
|
15591
15817
|
argsOmitted: { type: boolean, enum: [true] }
|
|
15818
|
+
rememberRefused:
|
|
15819
|
+
type: boolean
|
|
15820
|
+
enum: [true]
|
|
15821
|
+
description: >-
|
|
15822
|
+
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
15823
|
governanceForced:
|
|
15593
15824
|
type: boolean
|
|
15594
15825
|
enum: [true]
|
|
@@ -16053,6 +16284,11 @@ components:
|
|
|
16053
16284
|
argsOmitted: { type: boolean, enum: [true], description: 'Present (true) only when args exceeded the byte cap. Never false.' }
|
|
16054
16285
|
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
16286
|
risk: { $ref: '#/components/schemas/ApprovalRiskAxes' }
|
|
16287
|
+
rememberRefused:
|
|
16288
|
+
type: boolean
|
|
16289
|
+
enum: [true]
|
|
16290
|
+
description: >-
|
|
16291
|
+
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
16292
|
governanceForced:
|
|
16057
16293
|
type: boolean
|
|
16058
16294
|
enum: [true]
|
|
@@ -16707,16 +16943,27 @@ components:
|
|
|
16707
16943
|
sessionId: { type: string, description: 'gone.ask_parked ONLY — gate reconciliation coordinate 1; drive the existing durable-gate flow with it.' }
|
|
16708
16944
|
gateBoundCallId: { type: string, description: 'gone.ask_parked ONLY — gate reconciliation coordinate 2.' }
|
|
16709
16945
|
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.' }
|
|
16946
|
+
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
16947
|
deniedReason:
|
|
16712
16948
|
type: string
|
|
16713
16949
|
description: >
|
|
16714
16950
|
gone.ask ONLY — attribution, GROUPED BY `state`. `DENIED` carries the single-member deny
|
|
16715
16951
|
vocabulary `routing_failure_fail_closed`; `VOID` carries the separate (and growing) void
|
|
16716
|
-
vocabulary,
|
|
16952
|
+
vocabulary, seven words today: `run_cancelled`, `batch_aborted`, `batch_bound_elsewhere`,
|
|
16953
|
+
`adhoc_leg_no_durable_domain`, `orphan_ttl_exceeded` and — new in server 7.116.0 (local lane) —
|
|
16954
|
+
`crashed_before_park` (the process that held the ask crashed / was killed) and `shutdown_before_park`
|
|
16955
|
+
(an orderly shutdown could not settle the card inside its grace window; a fault shape, hard to build black-box).
|
|
16956
|
+
The last two are the SAME word as `GET /v1/approvals` `crashConverged[].cause`; the other six were already on the wire
|
|
16957
|
+
(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.
|
|
16958
|
+
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
|
|
16959
|
+
a human decision, reason unknown").
|
|
16717
16960
|
description: >
|
|
16718
16961
|
410 body. THE TWO LEGS ARE DISJOINT: `gone.ask_parked` carries exactly the three gate coordinates,
|
|
16719
|
-
`gone.ask` carries exactly `{state, deniedReason?}
|
|
16962
|
+
`gone.ask` carries exactly `{state, deniedReason?}` (no `consumerState`).
|
|
16963
|
+
🔴 server >= 7.116.0 (local lane, `DB_BACKEND=local`): after a crash / kill and a restart on the same data root, answering the PREVIOUS
|
|
16964
|
+
life's still-open card is now `410 gone.ask` with `state: "VOID"` and `deniedReason` `crashed_before_park` / `shutdown_before_park` —
|
|
16965
|
+
<= 7.115.x answered `200` + `consumerState: "absent"` (the run had long been reclaimed; nothing executed). An ask that was already decided
|
|
16966
|
+
(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
16967
|
consumer ends up driving the wrong durable gate.
|
|
16721
16968
|
🔴 The checkpoint token is NEVER here: the resume credential is not externally disclosed. Use
|
|
16722
16969
|
`sessionId`.
|
|
@@ -18495,9 +18742,15 @@ components:
|
|
|
18495
18742
|
description: >-
|
|
18496
18743
|
[2400] TR-4 — per-message queue priority on POST /v1/runs/{taskId}/steer. ACCEPTED + ENUM-VALIDATED
|
|
18497
18744
|
FAIL-LOUD (`routes/runs.ts`; anything else is 400 `request.field_invalid`) and echoed back on the
|
|
18498
|
-
receipt
|
|
18499
|
-
|
|
18500
|
-
on
|
|
18745
|
+
receipt. WHETHER IT TAKES EFFECT is the server's call — read `Capabilities.fleet.steerPriority` first:
|
|
18746
|
+
`"engine"` (server >=7.116.0) = the tier is handed to the engine on every delivery leg (`now` cuts the in-flight turn
|
|
18747
|
+
IMMEDIATELY — the running tool receives an abort, an approval card pending on this replica is revoked, one `engine_notice`
|
|
18748
|
+
`task.turn_interrupted` frame is the evidence; `next` ≡ no `priority`; `later` is delivered after the turn the run would have stopped on; parked
|
|
18749
|
+
legs store the tier and deliver on the resume's / wake's first turn; replaying the same `Idempotency-Key` + text with a different effective
|
|
18750
|
+
tier is 409 `steering.duplicate_input_id`); `"advisory"` (server <=7.115.x) = accepted and echoed but NOT applied —
|
|
18751
|
+
core's steer was a single-slot last-writer-wins with no per-message priority or addressable drop, so a
|
|
18752
|
+
faithful priority queue (and DELETE /v1/runs/{taskId}/queue/{messageId}) waited on a core seam. An absent
|
|
18753
|
+
or unknown capability value means "do not assume it is applied".
|
|
18501
18754
|
|
|
18502
18755
|
SteerReceipt:
|
|
18503
18756
|
type: object
|
|
@@ -18774,6 +19027,8 @@ components:
|
|
|
18774
19027
|
server 1.239 ([1392]②): on allow_session, an honest echo of whether the grant was REALLY
|
|
18775
19028
|
recorded (true = landed in the bridge store; false = no sessionId, could not record — do not
|
|
18776
19029
|
render "session-wide allowed"). Omitted on non-allow_session decisions and on older servers.
|
|
19030
|
+
🔴 server >= 7.116.0: ALWAYS `false` on a card that carries `rememberRefused: true` (an engine `Skill` card etc.) — the decision
|
|
19031
|
+
applies once and nothing is remembered (existing key, not a new one).
|
|
18777
19032
|
updatedInputForwarded:
|
|
18778
19033
|
type: boolean
|
|
18779
19034
|
description: >
|