@sema-agent/sdk 11.3.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -0
- package/dist/control-types.d.ts +12 -10
- package/dist/control-types.d.ts.map +1 -1
- package/dist/control-types.js +1 -1
- package/dist/control-types.js.map +1 -1
- package/dist/errors.d.ts +9 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +11 -3
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/health.d.ts +118 -6
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +51 -1
- package/dist/health.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/registry/auth.d.ts +36 -16
- package/dist/registry/auth.d.ts.map +1 -1
- package/dist/registry/auth.js +17 -4
- package/dist/registry/auth.js.map +1 -1
- package/dist/registry/errors.d.ts +6 -5
- package/dist/registry/errors.d.ts.map +1 -1
- package/dist/registry/errors.js +6 -5
- package/dist/registry/errors.js.map +1 -1
- package/dist/registry/index.d.ts +3 -3
- package/dist/registry/index.js +3 -3
- package/dist/registry/scopes-effective.d.ts +34 -6
- package/dist/registry/scopes-effective.d.ts.map +1 -1
- package/dist/registry/scopes-effective.js +2 -2
- package/dist/registry/scopes-effective.js.map +1 -1
- package/dist/resources/approvals.d.ts +11 -0
- package/dist/resources/approvals.d.ts.map +1 -1
- package/dist/resources/approvals.js.map +1 -1
- package/dist/resources/sessions.d.ts +40 -1
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +48 -0
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/tool-approvals.d.ts +80 -14
- package/dist/resources/tool-approvals.d.ts.map +1 -1
- package/dist/resources/tool-approvals.js +49 -1
- package/dist/resources/tool-approvals.js.map +1 -1
- package/dist/types.d.ts +172 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/openapi.yaml +395 -12
- package/package.json +2 -2
- package/registry-openapi.yaml +6 -5
package/openapi.yaml
CHANGED
|
@@ -2322,6 +2322,106 @@ paths:
|
|
|
2322
2322
|
'422': { $ref: '#/components/responses/UnprocessableEntity' }
|
|
2323
2323
|
'501': { $ref: '#/components/responses/NotImplemented' }
|
|
2324
2324
|
|
|
2325
|
+
/v1/sessions/{sessionId}/background:
|
|
2326
|
+
parameters:
|
|
2327
|
+
- $ref: '#/components/parameters/PrincipalHeader'
|
|
2328
|
+
- in: path
|
|
2329
|
+
name: sessionId
|
|
2330
|
+
required: true
|
|
2331
|
+
schema: { type: string }
|
|
2332
|
+
get:
|
|
2333
|
+
tags: [sessions]
|
|
2334
|
+
operationId: sessionsBackgroundList
|
|
2335
|
+
x-status: live # S-745 (server 7.102.0; core 7.32.0 #1107); SDK sessions.background.
|
|
2336
|
+
summary: The session's background tasks (the exit sheet's "keeps running / will stop" material).
|
|
2337
|
+
description: >
|
|
2338
|
+
S-745 (server >= 7.102.0; core 7.32.0 #1107; contract §16 "embedded-shape contract"; mint
|
|
2339
|
+
`src/http/routes/background.ts`). 200 `{ rows }` — each row is core `TaskRegistry.list()`'s row projected
|
|
2340
|
+
KEY BY KEY by an explicit whitelist (`task_id` renamed `id`; `toolUseId` / `updatedAt` deliberately
|
|
2341
|
+
stripped). Only THIS session's rows: the access tuple is the session's own `{owner: sid, sessionId: sid,
|
|
2342
|
+
scope}` and visibility is core's fail-closed `canAccess` (the session's session-resident shells, the run row
|
|
2343
|
+
whose task id is the session id, workflows this session started, background agents rooted at this
|
|
2344
|
+
session). `retained` rides ONLY when true (core's retain predicate: env / task lane / row mark) — present =
|
|
2345
|
+
"keeps running" on the exit sheet; absent = an `includeRetained:false` stop WILL stop it. `description` is
|
|
2346
|
+
the model's description, falling back to the launch command text (content family: redacted, cut at 500
|
|
2347
|
+
chars). At most 500 rows (core `list()`'s own cap). 🔴 IN-PROCESS: only rows on THIS replica.
|
|
2348
|
+
Zero model work: not billable, not refused by drain. Gates (same family as `mcp/reconnect`): 501
|
|
2349
|
+
`capability.session_ownership_required` (no `sessionStorage.ownerOf`) · 404 `not_found.session` — unknown
|
|
2350
|
+
session AND someone else's session answer the SAME code and SAME message (no existence oracle); an EXPLICIT
|
|
2351
|
+
operator may read any session · 400 `request.path_malformed`. Probe with `capabilities.background.listFace`;
|
|
2352
|
+
ABSENT key = an older server, where this path is 404 `not_found.route` (same status, different code).
|
|
2353
|
+
responses:
|
|
2354
|
+
'200':
|
|
2355
|
+
description: The session's background rows (read the row schema for the `retained` / `status` readings).
|
|
2356
|
+
content:
|
|
2357
|
+
application/json:
|
|
2358
|
+
schema: { $ref: '#/components/schemas/SessionBackgroundList' }
|
|
2359
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
2360
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
2361
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
2362
|
+
'501': { $ref: '#/components/responses/NotImplemented' }
|
|
2363
|
+
|
|
2364
|
+
/v1/sessions/{sessionId}/background/stop:
|
|
2365
|
+
parameters:
|
|
2366
|
+
- $ref: '#/components/parameters/PrincipalHeader'
|
|
2367
|
+
- in: path
|
|
2368
|
+
name: sessionId
|
|
2369
|
+
required: true
|
|
2370
|
+
schema: { type: string }
|
|
2371
|
+
post:
|
|
2372
|
+
tags: [sessions]
|
|
2373
|
+
operationId: sessionsBackgroundStop
|
|
2374
|
+
x-status: live # S-745 (server 7.102.0; core 7.32.0 #1107); SDK sessions.backgroundStop.
|
|
2375
|
+
summary: Stop the session's background tasks — soft, then one grace, then a synchronous hard kill; receipts are complete before 200.
|
|
2376
|
+
description: >
|
|
2377
|
+
S-745 (server >= 7.102.0; contract §16; mint `src/http/routes/background.ts`). The SAME session-level
|
|
2378
|
+
convergence function as the `DELETE /v1/sessions/{sessionId}` cascade: SOFT (core's session anchor SIGTERMs
|
|
2379
|
+
and settles the session's background agents / workflows; every still-running shell row the hard face will
|
|
2380
|
+
revisit gets a per-row soft stop — with `includeRetained:true` the retained live services receive SIGTERM
|
|
2381
|
+
here too) → GRACE (the hard face waits until every row it will revisit is past "its soft-stop instant +
|
|
2382
|
+
`HOST_BG_KILL_GRACE_MS`", default 1000 ms; nothing to wait for ⇒ no wait) → HARD (core
|
|
2383
|
+
`killAllBackgroundShellsNow` — a synchronous process-group SIGKILL; a shell ignoring SIGTERM does not
|
|
2384
|
+
survive it). 🔴 THE RECEIPTS ARE COMPLETE BEFORE THE 200: with background rows the answer is one grace
|
|
2385
|
+
slower — budget the shell's exit wait in seconds.
|
|
2386
|
+
Body `{ includeRetained }` is REQUIRED with NO default (core's rule: the caller states which kind of stop
|
|
2387
|
+
this is): `true` = also stop the explicitly retained live services (the shell's "Exit and stop tasks");
|
|
2388
|
+
`false` = keep them (they come back as `retained_skipped`; `sema kill`'s session-level reap). The body
|
|
2389
|
+
gate is STRICT — absent / non-boolean / an extra key ⇒ 400 `request.body_shape`.
|
|
2390
|
+
Receipts carry SHELL rows only (`background_bash` / `monitor`); `outcome` is core's four words passed
|
|
2391
|
+
through VERBATIM — `killed` (a live process group was reaped now) · `already_gone` (already exited, or
|
|
2392
|
+
already hard-killed — incl. exiting within the grace) · `retained_skipped` (kept by
|
|
2393
|
+
`includeRetained:false`) · `no_pgid` (NO synchronous hard kill landed: remote / sandbox lanes have no
|
|
2394
|
+
host-local process group — e2b / k8s·kata / local-docker / ssh / device / adb always answer it — or win32 /
|
|
2395
|
+
a refused signal; core already sent an ordinary kill ⇒ "MAY STILL BE RUNNING", neither a failure nor ever
|
|
2396
|
+
"stopped").
|
|
2397
|
+
🔴 CREDENTIAL-GATED (server >= 7.102.0 as released): on a worker with no service credential
|
|
2398
|
+
(`SERVICE_AUTH_TOKEN(S)`) and without `ALLOW_UNAUTHED_WRITES`, this path answers 503
|
|
2399
|
+
`auth.service_token_required` BEFORE routing (same code and sentence as every other mutating door) — the
|
|
2400
|
+
principal header is self-asserted there, and stopping background processes is irreversible.
|
|
2401
|
+
`capabilities.background.exitFaces` does NOT include "credentials ready" (the same family gap as the
|
|
2402
|
+
`memoryCompliance` row) — branch on that code. Other gates as the list path: 501
|
|
2403
|
+
`capability.session_ownership_required` · 404 `not_found.session` (unknown and foreign sessions alike) · 400
|
|
2404
|
+
`request.path_malformed`; this path is rate-limited (429). NOT called by run cancel (Esc): session-resident
|
|
2405
|
+
background shells live across turns (CC parity). A delegated helper's shells hang on the helper's own
|
|
2406
|
+
session and are out of this door's reach. Probe with `capabilities.background.exitFaces`.
|
|
2407
|
+
requestBody:
|
|
2408
|
+
required: true
|
|
2409
|
+
content:
|
|
2410
|
+
application/json:
|
|
2411
|
+
schema: { $ref: '#/components/schemas/SessionBackgroundStopRequest' }
|
|
2412
|
+
responses:
|
|
2413
|
+
'200':
|
|
2414
|
+
description: The receipts (shell rows only). Read `no_pgid` as "may still be running".
|
|
2415
|
+
content:
|
|
2416
|
+
application/json:
|
|
2417
|
+
schema: { $ref: '#/components/schemas/SessionBackgroundStopResult' }
|
|
2418
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
2419
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
2420
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
2421
|
+
'429': { $ref: '#/components/responses/RateLimited' }
|
|
2422
|
+
'501': { $ref: '#/components/responses/NotImplemented' }
|
|
2423
|
+
'503': { $ref: '#/components/responses/Unauthorized' } # `auth.service_token_required` — the credential-gated write door (no service credential and no ALLOW_UNAUTHED_WRITES), before routing.
|
|
2424
|
+
|
|
2325
2425
|
/v1/sessions/{sessionId}/memory-status:
|
|
2326
2426
|
parameters:
|
|
2327
2427
|
- $ref: '#/components/parameters/PrincipalHeader'
|
|
@@ -3031,6 +3131,15 @@ paths:
|
|
|
3031
3131
|
(REOPENED) and re-appears on `/v1/approvals`. SDK → ParkedResumeStartupError. Client action:
|
|
3032
3132
|
re-fetch the pending list and decide again, fixing what was rejected. (Before 5.12.0 this shape
|
|
3033
3133
|
collapsed into the 409 `decide.revive_rejected`.)
|
|
3134
|
+
🔴 core 7.32.0 (#1110) ADDS A CAUSE (server >= 7.102.0; contract appendix A.1, MIGRATION 7.102.0): an
|
|
3135
|
+
`approve` on a child parked on an INHERITED tool (a tool family the child inherits from the scenario
|
|
3136
|
+
layer — the task tools, WebFetch …) whose redemption cannot hand over the inherited seat ⇒ core refuses
|
|
3137
|
+
BEFORE consuming the approval: the approval stays PENDING and a `deny` still settles it. From server 7.102.0
|
|
3138
|
+
a ONE-LEVEL row (its root session = the parent session, and that root session STILL belongs to this card's
|
|
3139
|
+
tenant) is redeemed with the seat re-resolved from the root session, so it no longer lands here; a DEEPER
|
|
3140
|
+
(grandchild) row, or one whose root session was deleted / changed owner, still does (core #1112 pending) —
|
|
3141
|
+
render it as "this card can only be denied / wait for a server upgrade". Not a regression: 7.31.x children
|
|
3142
|
+
never had those tools.
|
|
3034
3143
|
content:
|
|
3035
3144
|
application/json:
|
|
3036
3145
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
@@ -3854,6 +3963,23 @@ paths:
|
|
|
3854
3963
|
NOT strict (hand-written parser, unknown keys are ignored), so an older server answers 200 and
|
|
3855
3964
|
records nothing. Bit absent = old server, do not offer the field. Bit present ⇒ read the
|
|
3856
3965
|
per-call truth from the ack's `noteRecorded`.
|
|
3966
|
+
readRootGrant:
|
|
3967
|
+
type: string
|
|
3968
|
+
minLength: 1
|
|
3969
|
+
description: >-
|
|
3970
|
+
S-720 (server >= 7.102.0 / core 7.32.0 #1093), ADDITIVE — "Yes, and add directory": the frame's
|
|
3971
|
+
`readRootCandidate.dir` sent back BYTE FOR BYTE (a STRING — never normalised, cut or composed; not an
|
|
3972
|
+
object). Beside `allow` it also adds that directory to THIS RUN's read directories (read faces only).
|
|
3973
|
+
🔴 `decision:"allow"` ONLY — on `allow_session` / `deny` the server refuses BEFORE the decision with 400
|
|
3974
|
+
`request.body_shape` (the card stays open; answer the same `approvalId` again). SHAPE gate: a non-empty
|
|
3975
|
+
string of at most core's `READ_ROOT_CANDIDATE_DIR_MAX`, else the same 400 (an over-long value is refused
|
|
3976
|
+
whole, never cut — a cut directory is another directory). The server judges SHAPE, never VALUE: whether
|
|
3977
|
+
it equals the card's string is the ENGINE's call, and the verdict arrives only as an `engine_notice` —
|
|
3978
|
+
`approval.read_root_granted` (the run's read roots really widened) or `approval.read_root_grant_rejected`
|
|
3979
|
+
(nothing changed; the decision stands). The 200 never says which. Reach: THIS RUN only (the ask row has no
|
|
3980
|
+
such column, so replay / failover / durable resume do not carry it) and THIS DOOR only (the durable
|
|
3981
|
+
`/decide` and the in-stream `…/asks/{askId}/decision` doors do not read it). An older server ignores the
|
|
3982
|
+
unknown key and answers 200 with a plain allow (no capability bit yet) — trust the notice.
|
|
3857
3983
|
responses:
|
|
3858
3984
|
'200':
|
|
3859
3985
|
description: Ack (`decision` echoed).
|
|
@@ -6558,15 +6684,27 @@ components:
|
|
|
6558
6684
|
rewindFiles:
|
|
6559
6685
|
type: boolean
|
|
6560
6686
|
description: >
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6687
|
+
RETIRED SPELLING (the whole-tree snapshot epoch; S-15 / design/381, server >= 7.52 — note corrected in sdk
|
|
6688
|
+
11.4.0, the same stale-note family as `rewindFilesTo`, board [8437] U3). Server `src/http/wire-types.ts`: still
|
|
6689
|
+
accepted on the wire — its capture sense (true, no resumeAt) is a tolerated no-op with a deprecation disclosure;
|
|
6690
|
+
its restore sense (true + resumeAt) is core's TYPED migration rejection naming `restoreFiles` (restore semantics
|
|
6691
|
+
really changed: whole tree ⇒ tracked set; the server never remaps it silently). Send `restoreFiles` (probe
|
|
6692
|
+
`capabilities.restoreFiles`); this key stays declared only for <= 7.51 servers.
|
|
6564
6693
|
rewindFilesTo:
|
|
6565
6694
|
type: string
|
|
6566
6695
|
description: >
|
|
6567
|
-
CC Rewind "code"-only (core 1.166.0 TaskSpec.rewindFilesTo).
|
|
6568
|
-
|
|
6569
|
-
|
|
6696
|
+
CC Rewind "code"-only (core 1.166.0 TaskSpec.rewindFilesTo; server "R8"). Converge the files this session
|
|
6697
|
+
edited (the TRACKED set) to the history boundary at a prior USER message WITHOUT forking the conversation (the
|
|
6698
|
+
session leaf is untouched — only the files move). Use instead of resumeAt+restoreFiles when the user wants only
|
|
6699
|
+
files reverted. 🔴 The value is a HANDLE, not an entry id (corrected in sdk 11.4.0, board [8437] U3): the SAME
|
|
6700
|
+
kind of handle as `resumeAt`, resolved through the SAME anchor store — typically the `taskId` from that turn's
|
|
6701
|
+
202 receipt (the server keys the user-message anchor by the run's taskId). Server `src/boot/resolve-spec.ts:686-697`:
|
|
6702
|
+
`resumeAnchorStore.resolve(sessionId, handle, principal)` → entry id; unknown handle ⇒ 404
|
|
6703
|
+
`rewind_files_to.unknown_event`; no session ⇒ 422 `rewind_files_to.no_session`; no anchor store / no getLeafId ⇒
|
|
6704
|
+
501. ⚠️ The 501 is NOT the capability's whole predicate: `capabilities.rewindFilesTo` also requires the
|
|
6705
|
+
file-history store (capture face); without it the server does not 501 — core refuses in the run with
|
|
6706
|
+
`rewind.store_unconfigured` — so probe the bit first. Honored ONLY when `resumeAt` is absent. One-shot at submit
|
|
6707
|
+
(resume legs strip it, server >= 7.72.0).
|
|
6570
6708
|
restoreFiles:
|
|
6571
6709
|
type: boolean
|
|
6572
6710
|
description: >-
|
|
@@ -8187,7 +8325,16 @@ components:
|
|
|
8187
8325
|
with no explicit allowlist); ABSENT = an older server (degrade to not teaching, not validating).
|
|
8188
8326
|
resumeAt: { type: boolean, description: "E18 resume-at-message anchors are resolvable." }
|
|
8189
8327
|
rewindFiles: { type: boolean, description: "E19 working-tree snapshot/restore is wired." }
|
|
8190
|
-
rewindFilesTo:
|
|
8328
|
+
rewindFilesTo:
|
|
8329
|
+
type: boolean
|
|
8330
|
+
description: >-
|
|
8331
|
+
Code-only rewind (`TaskRequest.rewindFilesTo`) is wired — mint `routes/capabilities.ts:839` =
|
|
8332
|
+
`Boolean(deps.fileHistoryStore && deps.resumeAnchorStore && deps.sessionStorage?.getLeafId)`: it needs the
|
|
8333
|
+
file-history store (to restore) AND the anchor map (to resolve the target HANDLE). Corrected in sdk 11.4.0
|
|
8334
|
+
(board [8437] U3): the store is the FILE-HISTORY store (not the pre-S-15 whole-tree snapshot store), and since
|
|
8335
|
+
server 7.97.0 (S-589) that seat is the CAPTURE face = backend AND the `FILE_HISTORY_CAPTURE` knob — a deployment
|
|
8336
|
+
that turns capture off reports this bit false together with `rewindFiles` / `restoreFiles` / `sessionSync`
|
|
8337
|
+
(and `fileHistoryCapture: "off"`).
|
|
8191
8338
|
restoreFiles:
|
|
8192
8339
|
type: boolean
|
|
8193
8340
|
description: >-
|
|
@@ -8751,6 +8898,70 @@ components:
|
|
|
8751
8898
|
properties:
|
|
8752
8899
|
provider: { type: string, description: 'host | e2b | k8s | ssh | adb | local-docker | device — typed from the server''s RemoteExecProvider; `REMOTE_EXEC` unset ⇒ `host`.' }
|
|
8753
8900
|
toolsOnThisHost: { type: boolean, description: 'The tools run on the process that answered this request (server-absolute paths mean something to the model''s tools).' }
|
|
8901
|
+
taskWriteFaceOpen:
|
|
8902
|
+
type: boolean
|
|
8903
|
+
description: >
|
|
8904
|
+
server >= 7.95.0 (S-591; value meaning refined at 7.96.0 / S-613; mint `routes/capabilities.ts:653` =
|
|
8905
|
+
`taskWriteFaceRefusal(deps.config) === undefined && autonomyOverrides(deps.config.autonomy).writeFace !== "roots"`)
|
|
8906
|
+
— DISCLOSURE BIT OF THE WRITE-CONTAINMENT FACE: does this deployment honour the task-level "open the write
|
|
8907
|
+
fence" declaration (`permissionMode:"bypassPermissions"` ⇒ `TaskSpec.writeFace:"open"`, writes outside the
|
|
8908
|
+
workspace roots)? `false` has two forms: (1) the hosted-posture gate refuses ⇒ sending that mode gets
|
|
8909
|
+
`422 request.host_posture_refused`; (2) the deployment runs `AUTONOMY=read-only|plan` ⇒ the request is
|
|
8910
|
+
accepted but the write face is clamped back to roots — the declaration silently does nothing. Three states
|
|
8911
|
+
are folded into one bit on purpose: the caller has exactly one decision (send that key or not); tier and
|
|
8912
|
+
evidence live in the refusal body and the operator's `GET /v1/diagnostics/wiring`. It speaks ONLY for the
|
|
8913
|
+
write-containment cell — the other two columns of `bypassPermissions` are unaffected.
|
|
8914
|
+
ABSENT = an older worker (<= 7.94) ⇒ read as `true` (contract appendix B.1: nothing refused it back then).
|
|
8915
|
+
taskApproverPosture:
|
|
8916
|
+
type: boolean
|
|
8917
|
+
description: >
|
|
8918
|
+
server >= 7.95.0 (S-591 leg ③; mint `routes/capabilities.ts:659` = `taskApproverPostureHonored(deps.config)`,
|
|
8919
|
+
the SAME predicate as the real consumer) — DISCLOSURE BIT OF `approverPosture`: does this deployment honour
|
|
8920
|
+
the submit body's host-posture statement ("this run's approval cards are auto-answered by the host
|
|
8921
|
+
itself")? `false` ⇒ the key is IGNORED (the request is still 202-accepted; the server logs
|
|
8922
|
+
`task_approver_posture_ignored`) — deliberately NOT refused: the resume legs replay the persisted body
|
|
8923
|
+
verbatim and the caller cannot remove it, so a refusal would brick a parked task forever. Same reach as
|
|
8924
|
+
the hosted-gate half of `taskWriteFaceOpen` (hosted posture ⇒ both false); `AUTONOMY=read-only|plan`
|
|
8925
|
+
only clears `taskWriteFaceOpen`, never this bit.
|
|
8926
|
+
ABSENT = an older worker (<= 7.94) ⇒ read as `true` (contract appendix B.1: it passed through back then).
|
|
8927
|
+
fileHistoryCapture:
|
|
8928
|
+
type: string
|
|
8929
|
+
enum: ['off', on-always]
|
|
8930
|
+
description: >
|
|
8931
|
+
server >= 7.97.0 (S-589; mint `routes/capabilities.ts:847` = `fileHistoryCaptureOf(deps.fileHistoryStore)`,
|
|
8932
|
+
closed word set owned by the server's `src/file-history-capture.ts` `FILE_HISTORY_CAPTURE_WORD_SET`) —
|
|
8933
|
+
CAN FILE-HISTORY CAPTURE BE TURNED OFF. Derived from the ASSEMBLY RESULT (capture face = backend AND the
|
|
8934
|
+
`FILE_HISTORY_CAPTURE` deployment knob), NOT an echo of the knob — a deployment without the backend is
|
|
8935
|
+
`off` too; the SAME judgement as `rewindFiles` / `restoreFiles` / `rewindFilesTo` / `sessionSync`.
|
|
8936
|
+
`off` = this deployment captures no first-touch snapshots and has no rewind / restore / code-only rewind /
|
|
8937
|
+
session-sync ⇒ render neither a "turn capture off" switch nor a rewind entry. `on-always` = capturing, and
|
|
8938
|
+
it CANNOT be turned off per session (core's first-touch capture is process-wide) ⇒ render one read-only true
|
|
8939
|
+
sentence, never a switch that cannot switch.
|
|
8940
|
+
🔴 A third word `on-optional` ("this session may skip capture") is DELIBERATELY UNDECLARED by the server (it
|
|
8941
|
+
waits for a per-session no-capture seat in core); when it lands it is an additive server change and this
|
|
8942
|
+
enum grows with it. Keep a default arm (unknown word ⇒ treat as unknown, render no switch). Turning capture
|
|
8943
|
+
off does NOT delete what was already captured.
|
|
8944
|
+
ABSENT = an older worker (<= 7.96) ⇒ fall back to `rewindFiles` (`true` ⇒ `on-always`, `false` ⇒ `off`).
|
|
8945
|
+
background:
|
|
8946
|
+
type: object
|
|
8947
|
+
additionalProperties: true
|
|
8948
|
+
description: >
|
|
8949
|
+
server >= 7.102.0 (S-745 / core 7.32.0 #1107; mint `routes/capabilities.ts:308` = `{ listFace:
|
|
8950
|
+
sessionBackgroundFacesAvailable(deps), exitFaces: sessionBackgroundFacesAvailable(deps) }`) — presence of the
|
|
8951
|
+
session background-task doors: `listFace` = `GET /v1/sessions/{sessionId}/background`, `exitFaces` =
|
|
8952
|
+
`POST /v1/sessions/{sessionId}/background/stop` (contract §16). Both bits use the SAME predicate as the two
|
|
8953
|
+
doors' 501 (the session-ownership face `sessionStorage.ownerOf`), so "says yes but 501s" is structurally
|
|
8954
|
+
impossible; without it both bits are explicitly `false` and both doors answer 501
|
|
8955
|
+
`capability.session_ownership_required`. ENDPOINT-GATE FORM: `false` ⇒ do not call. True only promises the
|
|
8956
|
+
endpoint — not that this replica holds any background row of that session (the registry is in-process).
|
|
8957
|
+
⚠️ `exitFaces` does NOT cover "credentials ready": on a worker with no service credential and without
|
|
8958
|
+
`ALLOW_UNAUTHED_WRITES` the bit is true while the stop door answers 503 `auth.service_token_required` —
|
|
8959
|
+
branch on that code (the same family gap as `memoryCompliance`). ABSENT = an older server (both doors 404)
|
|
8960
|
+
⇒ the shell's exit dialog offers only "Stay / Exit", never "Exit and stop tasks".
|
|
8961
|
+
required: [listFace, exitFaces]
|
|
8962
|
+
properties:
|
|
8963
|
+
listFace: { type: boolean }
|
|
8964
|
+
exitFaces: { type: boolean }
|
|
8754
8965
|
WriteProtectionCapability:
|
|
8755
8966
|
type: object
|
|
8756
8967
|
additionalProperties: false
|
|
@@ -10806,6 +11017,13 @@ components:
|
|
|
10806
11017
|
sessionId: { type: string }
|
|
10807
11018
|
requiresRealApproval: { type: boolean, enum: [true] }
|
|
10808
11019
|
governanceForced: { type: boolean, enum: [true] }
|
|
11020
|
+
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).' }
|
|
11021
|
+
mandate:
|
|
11022
|
+
allOf: [{ $ref: '#/components/schemas/PersistedRuleMandate' }]
|
|
11023
|
+
description: 'server >= 7.102.0 (S-721): which word the mandated bit stands on — same layer and shape as `mandated`, the SAME value as `frame.mandate`. Absence never names a word.'
|
|
11024
|
+
origin:
|
|
11025
|
+
allOf: [{ $ref: '#/components/schemas/AskOrigin' }]
|
|
11026
|
+
description: 'server >= 7.102.0 (S-755 / cli L-695): WHO raised this ask, read once together with `frame.origin` when the entry is minted. The durable `pending[]` rows of the same response carry it top-level too — one reading for both row families. OPEN set (see AskOrigin).'
|
|
10809
11027
|
fromSubagent: { type: boolean, enum: [true], description: 'The ask originates from a delegated subagent.' }
|
|
10810
11028
|
originTaskId: { type: string, description: 'S-52 C2 (server ≥7.52, A-075.87): the delegated child taskId (= the child''s core runSourceTaskId, uuid) — correlates this live ask to the child run row. Minted by the SAME conditional spread as `fromSubagent`: the two keys are always both present or both absent (三键恒等亲证在案).' }
|
|
10811
11029
|
contentKind: { type: string, description: 'S-62 (server >= 7.6x): content-question kind — `content_ask` when the gated tool is AskUserQuestion (the SAME word as the two durable read faces and core''s summarize face). Absent = an ordinary tool ask. Display/triage only; it NEVER takes part in decision routing.' }
|
|
@@ -11114,6 +11332,27 @@ components:
|
|
|
11114
11332
|
presence may differ between the two legs for one ask. Derived from hot-reloadable governance knobs —
|
|
11115
11333
|
long subscribers follow the stream's re-emitted frames. Absence ≠ "not governance-forced"; it means
|
|
11116
11334
|
"no governance-origin evidence". Never written as false.
|
|
11335
|
+
# ── park-row facts (server `src/approval-card.ts` `ParkRowFacts` — the five facts core mints on the parked
|
|
11336
|
+
# `PendingAction.tool_approval` arm, projected by `parkRowFacts`, the SAME projection on both stores and on the
|
|
11337
|
+
# `/stream` `pending` frame). DISPLAY / TRIAGE projection, never a permission input; each present only when
|
|
11338
|
+
# true / a word. sdk 11.4.0 declares all five (the first three were already on the wire since 7.100.0 / 7.101.0).
|
|
11339
|
+
requiresRealApproval:
|
|
11340
|
+
type: boolean
|
|
11341
|
+
enum: [true]
|
|
11342
|
+
description: 'server >= 7.100.0 (S-700): this parked ask can only be cleared by a REAL HUMAN (core park-row twin seat, strict `=== true`). Absent = not marked, never "clearable without a person".'
|
|
11343
|
+
mandated:
|
|
11344
|
+
type: boolean
|
|
11345
|
+
enum: [true]
|
|
11346
|
+
description: 'server >= 7.101.0 (S-663 part 2 / core 7.31.0 #1079): the durable twin of the mandated bit (no rule can clear this ask). Independent of `requiresRealApproval` (which implies it) and `ruleOffersAbsence` — projected bit by bit, never inferred.'
|
|
11347
|
+
mandate:
|
|
11348
|
+
allOf: [{ $ref: '#/components/schemas/PersistedRuleMandate' }]
|
|
11349
|
+
description: 'server >= 7.102.0 (S-721): which word the mandated bit stands on — the park-row twin seat read through `readClosedWordSeat(…, "mandate")` (core `isPersistedRuleMandate`); an out-of-set word reads as absent. Answers the same as the inbox row for the same row.'
|
|
11350
|
+
origin:
|
|
11351
|
+
allOf: [{ $ref: '#/components/schemas/AskOrigin' }]
|
|
11352
|
+
description: 'server >= 7.102.0 (S-755 / cli L-695 / C-R111): WHO raised this ask — the park-row twin seat `PendingAction.tool_approval.origin` read through `readClosedWordSeat(…, "origin")` (core `isAskOrigin`). Same word as the live card frame and the inbox row. Absent = an old row (parked before core 7.5.0) or an out-of-set word — NOT "policy".'
|
|
11353
|
+
ruleOffersAbsence:
|
|
11354
|
+
allOf: [{ $ref: '#/components/schemas/RuleOffersAbsence' }]
|
|
11355
|
+
description: 'server >= 7.100.0 (S-700): WHY the park row offers no rule — the same narrow read and closed three-word set as the live card frame and `card_json`.'
|
|
11117
11356
|
hasBidiControls:
|
|
11118
11357
|
type: boolean
|
|
11119
11358
|
enum: [true]
|
|
@@ -11220,6 +11459,20 @@ components:
|
|
|
11220
11459
|
🔴 NEVER minted as `false` (the OMIT contract this row's other flags follow); absence is "not marked",
|
|
11221
11460
|
never "confirmed clearable without a person". The value comes WHOLE from core (`summarizeCheckpoint`
|
|
11222
11461
|
projects the park row's own bit) — the server neither recomputes nor redacts it.
|
|
11462
|
+
mandated:
|
|
11463
|
+
type: boolean
|
|
11464
|
+
enum: [true]
|
|
11465
|
+
description: >-
|
|
11466
|
+
server >= 7.101.0 (S-663 part 2 / core 7.31.0 #1079), ADDITIVE, present ONLY when true: the durable twin of
|
|
11467
|
+
the mandated bit (core `summarizeCheckpoint` screens the park row's `PendingAction.tool_approval.mandated`
|
|
11468
|
+
to a literal `true`; the server mints the key on strict `=== true`). Declared in sdk 11.4.0 — this schema is
|
|
11469
|
+
CLOSED, so before that a strict validator rejected every row that carried it.
|
|
11470
|
+
mandate:
|
|
11471
|
+
allOf: [{ $ref: '#/components/schemas/PersistedRuleMandate' }]
|
|
11472
|
+
description: >-
|
|
11473
|
+
server >= 7.102.0 (S-721 / core 7.32.0 #1092): which word the mandated bit stands on (core
|
|
11474
|
+
`CheckpointSummary.mandate`, already screened by core's `isPersistedRuleMandate`; the server does not screen
|
|
11475
|
+
twice). Answers the same as the operator queue row for the same park row.
|
|
11223
11476
|
denialLimitFallback:
|
|
11224
11477
|
$ref: '#/components/schemas/DenialLimitFallback'
|
|
11225
11478
|
description: >-
|
|
@@ -11849,6 +12102,73 @@ components:
|
|
|
11849
12102
|
budgetMs: { type: integer }
|
|
11850
12103
|
error: { type: string }
|
|
11851
12104
|
|
|
12105
|
+
SessionBackgroundRow:
|
|
12106
|
+
type: object
|
|
12107
|
+
description: >
|
|
12108
|
+
One row of `GET /v1/sessions/{sessionId}/background` (S-745, server >= 7.102.0; mint
|
|
12109
|
+
`src/http/routes/background.ts` `SessionBackgroundRow`) = core `TaskRegistry.list()`'s row projected key by
|
|
12110
|
+
key (`task_id` renamed `id`; `toolUseId` / `updatedAt` stripped). The three word sets are OWNED BY CORE
|
|
12111
|
+
(7.32.1 `SemaTaskType` / `SemaTaskStatus`), transcribed verbatim. 🔴 IN-PROCESS: only rows on this replica.
|
|
12112
|
+
Response projection: declared key by key AND open (additive keys between SDK releases must not make a legal
|
|
12113
|
+
row unreadable — the LivePendingRow ruling).
|
|
12114
|
+
additionalProperties: true
|
|
12115
|
+
required: [id, type, status, createdAt, sessionScoped]
|
|
12116
|
+
properties:
|
|
12117
|
+
id: { type: string, description: 'core `task_id` (renamed). A receipt''s `id` is the same value.' }
|
|
12118
|
+
description: { type: string, description: 'The model''s description, falling back to the launch command text (core keeps no separate raw command). Content family: redacted, cut at 500 characters. UNTRUSTED for display.' }
|
|
12119
|
+
type: { type: string, enum: [background_bash, workflow, background_agent, monitor], description: 'core `SemaTaskType`.' }
|
|
12120
|
+
status: { type: string, enum: [pending, running, parked, completed, failed, killed, cancelled], description: 'core `SemaTaskStatus` (`parked` = a background agent suspended on a pending approval — neither live nor terminal).' }
|
|
12121
|
+
createdAt: { type: integer, description: 'Registration time (epoch ms).' }
|
|
12122
|
+
sessionScoped: { type: boolean, description: '`true` = session-resident (lives across turns); `false` = run-scoped.' }
|
|
12123
|
+
retained:
|
|
12124
|
+
type: boolean
|
|
12125
|
+
enum: [true]
|
|
12126
|
+
description: >-
|
|
12127
|
+
core's retain predicate (env declaration / task lane / row mark — any ⇒ kept) — present ONLY when true,
|
|
12128
|
+
never minted as false, and only ever on a shell row (`background_bash` / `monitor`; core `list()` row
|
|
12129
|
+
doc). Present = "keeps running" on the exit sheet; absent = an `includeRetained:false` stop WILL stop it.
|
|
12130
|
+
SessionBackgroundList:
|
|
12131
|
+
type: object
|
|
12132
|
+
description: '`GET /v1/sessions/{sessionId}/background` 200 body (contract §16). An idle session answers `{ rows: [] }`.'
|
|
12133
|
+
additionalProperties: true
|
|
12134
|
+
required: [rows]
|
|
12135
|
+
properties:
|
|
12136
|
+
rows:
|
|
12137
|
+
type: array
|
|
12138
|
+
items: { $ref: '#/components/schemas/SessionBackgroundRow' }
|
|
12139
|
+
SessionBackgroundStopRequest:
|
|
12140
|
+
type: object
|
|
12141
|
+
description: >
|
|
12142
|
+
`POST /v1/sessions/{sessionId}/background/stop` body — server `StopBodySchema = z.object({ includeRetained:
|
|
12143
|
+
z.boolean() }).strict()`: EXACTLY this key, REQUIRED, NO default. `true` = also stop explicitly retained live
|
|
12144
|
+
services ("Exit and stop tasks"); `false` = keep them (`retained_skipped`). Absent / non-boolean / an extra
|
|
12145
|
+
key ⇒ 400 `request.body_shape`.
|
|
12146
|
+
additionalProperties: false
|
|
12147
|
+
required: [includeRetained]
|
|
12148
|
+
properties:
|
|
12149
|
+
includeRetained: { type: boolean }
|
|
12150
|
+
SessionBackgroundReceipt:
|
|
12151
|
+
type: object
|
|
12152
|
+
description: >
|
|
12153
|
+
One receipt of the stop door — SHELL rows only (`background_bash` / `monitor`). `outcome` = core 7.32.1
|
|
12154
|
+
`BackgroundShellHardKillReceipt.outcome` (`BackgroundHardKillOutcome` ∪ `retained_skipped`), passed through
|
|
12155
|
+
VERBATIM: `killed` / `already_gone` (both = "this row is reaped") · `retained_skipped` (kept, process alive) ·
|
|
12156
|
+
`no_pgid` (no synchronous hard kill landed — MAY STILL BE RUNNING; never render it as stopped).
|
|
12157
|
+
additionalProperties: true
|
|
12158
|
+
required: [id, outcome]
|
|
12159
|
+
properties:
|
|
12160
|
+
id: { type: string, description: 'The row id (core taskId).' }
|
|
12161
|
+
outcome: { type: string, enum: [killed, already_gone, retained_skipped, no_pgid] }
|
|
12162
|
+
SessionBackgroundStopResult:
|
|
12163
|
+
type: object
|
|
12164
|
+
description: '`POST /v1/sessions/{sessionId}/background/stop` 200 body. The receipts are COMPLETE before the 200 (soft → grace → hard is awaited).'
|
|
12165
|
+
additionalProperties: true
|
|
12166
|
+
required: [receipts]
|
|
12167
|
+
properties:
|
|
12168
|
+
receipts:
|
|
12169
|
+
type: array
|
|
12170
|
+
items: { $ref: '#/components/schemas/SessionBackgroundReceipt' }
|
|
12171
|
+
|
|
11852
12172
|
# ── 2c session-sync (P1d) — the cloud-as-a-SYNC-PEER schemas ──────────────────────────────────────────────
|
|
11853
12173
|
SyncEntry:
|
|
11854
12174
|
type: object
|
|
@@ -13651,6 +13971,17 @@ components:
|
|
|
13651
13971
|
spec-resolver, which now passes the notice seat). Consequence for consumers that assert on ledger
|
|
13652
13972
|
CONTENTS: a resume leg's ledger MAY now carry one extra `engine_notice` row it did not before — assert
|
|
13653
13973
|
"may appear", never an exact row count or order (and consume idempotently: reconnect replay shows it again).
|
|
13974
|
+
`approval.read_root_granted` / `approval.read_root_grant_rejected` (server >= 7.102.0 / S-720 / core 7.32.0
|
|
13975
|
+
#1093) — the ENGINE's verdict on a `readRootGrant` answer (POST /v1/tool-approvals/{id}/respond), at most one
|
|
13976
|
+
frame per answered ask. GRANTED = this run's read directories really include it now (core: the ONLY evidence the
|
|
13977
|
+
run widened; read faces only, this run only) — `{dir, covers?, root, toolName, toolCallId, sessionId, runId,
|
|
13978
|
+
taskId?}`, `root` = the canonical spelling the engine holds. REJECTED = nothing changed and the decision stands
|
|
13979
|
+
(say so plainly) — `{reason, offered?, requested?, toolName, toolCallId, sessionId, runId, taskId?}`, `reason` one of
|
|
13980
|
+
core's eight words (`on_refusal` / `not_a_string` / `no_candidate` / `mismatch` / `unresolvable` /
|
|
13981
|
+
`resolves_elsewhere` / `admits_artifact_store` — the directory contains, lies inside or is the local artifact
|
|
13982
|
+
store; unreachable on a server 7.102.0 deployment, which wires no artifact host — / `no_read_roots`), passed
|
|
13983
|
+
through verbatim by the server (echo-only, not enumerated) — read it as an OPEN set. `toolCallId` joins to the
|
|
13984
|
+
`tool_approval` frame.
|
|
13654
13985
|
`delegation.ask_unresolvable` (server >= 7.69.0 / core 7.10.0 #648) — an `ask` reached a FINAL DENY with
|
|
13655
13986
|
NOBODY having ruled on it: the approver consulted for the call answered `unavailable` and no durable park
|
|
13656
13987
|
caught it afterwards. The deny itself is unchanged (`tool_end.gate.settlement.kind:"approver_unavailable"`
|
|
@@ -14324,8 +14655,18 @@ components:
|
|
|
14324
14655
|
description: >
|
|
14325
14656
|
(server >= 7.93.0, core 7.26.0 #997) This card was MANDATED — a read-station / rule-lane forced ask (a rule can
|
|
14326
14657
|
never clear it; an approver's yes cannot release a deny-listed read). Present only when true, literal `true`;
|
|
14327
|
-
absent = an ordinary ask.
|
|
14328
|
-
(
|
|
14658
|
+
absent = an ordinary ask. ⚠️ CORRECTED (sdk 11.4.0): the durable parked row DOES carry a twin bit since core
|
|
14659
|
+
7.31.0 #1079 (`PendingAction.tool_approval.mandated`), projected since server 7.101.0 onto the operator queue
|
|
14660
|
+
row / the `/stream` `pending` frame / the inbox row (S-663 part 2) and the `livePending` row top level (T4①)
|
|
14661
|
+
— four faces, one bit. `card_json` does not carry it (`ApprovalCardSchema` is `.strict()`).
|
|
14662
|
+
mandate:
|
|
14663
|
+
allOf: [{ $ref: '#/components/schemas/PersistedRuleMandate' }]
|
|
14664
|
+
description: >-
|
|
14665
|
+
server >= 7.102.0 (S-721 / core 7.32.0 #1092), "tool_approval" only, ADDITIVE — which word the `mandated`
|
|
14666
|
+
bit stands on (server `src/tool-approval.ts:841`, read through `readClosedWordSeat(req, "mandate")` =
|
|
14667
|
+
core's `isPersistedRuleMandate` screen). Present only when the WHOLE cause of `mandated:true` is that one
|
|
14668
|
+
word; absence never names a word and is not "not mandated". Same value on the `livePending` row, the
|
|
14669
|
+
operator queue row and the inbox row; NOT on `card_json` / `approval_request`.
|
|
14329
14670
|
denialLimitFallback: { $ref: '#/components/schemas/DenialLimitFallback' }
|
|
14330
14671
|
parked:
|
|
14331
14672
|
type: boolean
|
|
@@ -14627,6 +14968,13 @@ components:
|
|
|
14627
14968
|
|
|
14628
14969
|
The SAME type is the `origin` member of `GateOutcome` on `tool_end` — one vocabulary, two faces.
|
|
14629
14970
|
|
|
14971
|
+
server >= 7.102.0 (S-755 / cli L-695 / C-R111): the word now also rides the `livePending` row top level
|
|
14972
|
+
(read once with the frame's) and the operator queue row (`GET /v1/approvals` `pending[]` + the `/stream`
|
|
14973
|
+
`pending` frame — the park-row twin seat, screened by core's `isAskOrigin`), besides the frame and the inbox
|
|
14974
|
+
row — five faces, one word. `card_json` / the `approval_request` frame still do not carry it (the card is
|
|
14975
|
+
`.strict()`). The eleven known words are exported at runtime as the SDK's `ASK_ORIGINS` (core 7.32.1
|
|
14976
|
+
`ASK_ORIGINS`, verbatim and in order) — known words, NOT an enforcement table.
|
|
14977
|
+
|
|
14630
14978
|
RuleOffersAbsence:
|
|
14631
14979
|
type: string
|
|
14632
14980
|
enum: [mandated, shadowed, lane_cannot_speak]
|
|
@@ -14644,6 +14992,26 @@ components:
|
|
|
14644
14992
|
server-side narrow read, so both faces carry identical values; a word outside the set is treated as
|
|
14645
14993
|
malformed and the key is not minted at all (the server never passes an unknown word through).
|
|
14646
14994
|
|
|
14995
|
+
PersistedRuleMandate:
|
|
14996
|
+
type: string
|
|
14997
|
+
enum: [operator_always, tool_marks, probe_mandate, probe_unanswered, write_protection, write_protection_unresolved]
|
|
14998
|
+
description: >
|
|
14999
|
+
WHICH WORD a mandated ask stands on (server >= 7.102.0 / S-721 / core 7.32.0 #1092) — core's
|
|
15000
|
+
`PERSISTED_RULE_MANDATES` six words, transcribed verbatim and in order (core 7.32.1
|
|
15001
|
+
`dist/core/ask-origin.d.ts:349`; the vocabulary's owner is core). Rides FOUR faces with one value: the
|
|
15002
|
+
`tool_approval` frame, the `livePending` row top level, the operator queue row (`GET /v1/approvals`
|
|
15003
|
+
`pending[]` + the `/v1/approvals/stream` `pending` frame) and the inbox row. NOT on `card_json` / the
|
|
15004
|
+
`approval_request` frame (live or reconnect replay — `ApprovalCardSchema` is `.strict()`), same as `mandated`.
|
|
15005
|
+
🔴 A TRUE CLOSED SET, deliberately unlike `AskOrigin`: on every face the server screens it through core's
|
|
15006
|
+
`isPersistedRuleMandate` (`approval-card.ts` `readClosedWordSeat`; the inbox face is screened by core's own
|
|
15007
|
+
`summarizeCheckpoint`) and an out-of-set word reads as ABSENT, never on the wire.
|
|
15008
|
+
🔴 ABSENCE NEVER NAMES A WORD and is NOT "not mandated": another door (governance / hook / ancestor) or more
|
|
15009
|
+
than one reason ⇒ absent; whether the ask is mandated is `mandated`. For an ENGINE-MINTED value, present ⇒
|
|
15010
|
+
`mandated` is true (core: present ⇔ that word is the bit's WHOLE reason); the converse does not hold. ⚠️ On the
|
|
15011
|
+
durable faces (queue row / inbox row) the server projects the two seats INDEPENDENTLY (it does not bind `mandate`
|
|
15012
|
+
to `mandated`, `approval-card.ts` `readClosedWordSeat`), so a hand-edited or generation-skewed row may carry one
|
|
15013
|
+
without the other — read `mandated` for the bit, never infer it from this word. Echo-only — the server never
|
|
15014
|
+
branches on the word.
|
|
14647
15015
|
DenialLimitKind:
|
|
14648
15016
|
type: string
|
|
14649
15017
|
enum: [consecutive, total]
|
|
@@ -15199,14 +15567,15 @@ components:
|
|
|
15199
15567
|
type: object
|
|
15200
15568
|
description: >
|
|
15201
15569
|
Decision-maker identity assertion (design/171 §5.1; the cross-repo source of truth is
|
|
15202
|
-
`@sema-agent/
|
|
15570
|
+
`@sema-agent/settings-schema` ActorAssertionWire — the SDK holds a value copy; the package was named
|
|
15571
|
+
`@sema-agent/registry-core` before 1.0.0).
|
|
15203
15572
|
|
|
15204
15573
|
NORMATIVE, not a style note: an ACTOR NEVER PARTICIPATES IN THE PERMISSION DECISION — authority always
|
|
15205
15574
|
belongs to the principal; this shape exists only for audit/echo/presentation. `id` is ALWAYS server-minted
|
|
15206
15575
|
(= the verified principal; an auth-off deployment mints the `"_"` sentinel), and a wire requester may
|
|
15207
15576
|
submit ONLY `label`.
|
|
15208
15577
|
required: [id]
|
|
15209
|
-
additionalProperties: false #
|
|
15578
|
+
additionalProperties: false # settings-schema's ActorAssertionWire is .strict()
|
|
15210
15579
|
properties:
|
|
15211
15580
|
id: { type: string, minLength: 1, maxLength: 256, description: 'Server-minted principal ("_" sentinel when auth is off). Never submittable by the requester.' }
|
|
15212
15581
|
label: { type: string, maxLength: 256, description: 'Unverified display text — the ONLY field a requester may submit (server redacts + bounds it). UNTRUSTED.' }
|
|
@@ -15217,7 +15586,7 @@ components:
|
|
|
15217
15586
|
description: >
|
|
15218
15587
|
Audit axis for which authorization path accepted the decision: `owner` (row owner) or `operator`
|
|
15219
15588
|
(explicit operator seat). CLOSED — verbatim-equal to the owning schema
|
|
15220
|
-
(
|
|
15589
|
+
(settings-schema ActorAssertionWire). Widening it here without widening the owner is copy drift.
|
|
15221
15590
|
|
|
15222
15591
|
AskDecisionBody:
|
|
15223
15592
|
type: object
|
|
@@ -15866,6 +16235,20 @@ components:
|
|
|
15866
16235
|
SAME projection as the `GET /v1/approvals` row (`projectPendingForWire`), declared here explicitly so
|
|
15867
16236
|
a stream consumer sees it typed instead of through the open index signature. Present ONLY when true;
|
|
15868
16237
|
absence = "not detected", never "confirmed clean" (see PendingCheckpoint.hasBidiControls).
|
|
16238
|
+
# sdk 11.4.0 (che-OV adversarial review [low] F5): the `pending` frame spreads the PendingCheckpoint row and the
|
|
16239
|
+
# `live_pending` frame (server >= 7.87.0) spreads the LivePendingRow — so the rows' park-row facts / mandate bit /
|
|
16240
|
+
# origin word ride these frames with the same names and values. Declared for the same reason as hasBidiControls.
|
|
16241
|
+
requiresRealApproval: { type: boolean, enum: [true], description: '`pending` / `live_pending` frames — see PendingCheckpoint / LivePendingRow.requiresRealApproval.' }
|
|
16242
|
+
mandated: { type: boolean, enum: [true], description: '`pending` / `live_pending` frames (server >= 7.101.0) — see the row schemas.' }
|
|
16243
|
+
mandate:
|
|
16244
|
+
allOf: [{ $ref: '#/components/schemas/PersistedRuleMandate' }]
|
|
16245
|
+
description: '`pending` / `live_pending` frames (server >= 7.102.0 / S-721) — see PendingCheckpoint.mandate / LivePendingRow.mandate.'
|
|
16246
|
+
origin:
|
|
16247
|
+
allOf: [{ $ref: '#/components/schemas/AskOrigin' }]
|
|
16248
|
+
description: '`pending` / `live_pending` frames (server >= 7.102.0 / S-755) — see PendingCheckpoint.origin / LivePendingRow.origin. OPEN set.'
|
|
16249
|
+
ruleOffersAbsence:
|
|
16250
|
+
allOf: [{ $ref: '#/components/schemas/RuleOffersAbsence' }]
|
|
16251
|
+
description: '`pending` frames only (server >= 7.100.0 / S-700) — see PendingCheckpoint.ruleOffersAbsence.'
|
|
15869
16252
|
|
|
15870
16253
|
ParkedDecideAccepted:
|
|
15871
16254
|
type: object
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Typed, zero-runtime-dependency SDK for the Sema agent fleet usage plane. The shared substrate for all doors (CC/Codex MCP façade + web). Server-side only — tokens never enter the browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -52,6 +52,6 @@
|
|
|
52
52
|
"prepublishOnly": "rm -f tsconfig.tsbuildinfo && npm run build && npm run typecheck --workspaces=false --prefix ../.. && npm test --workspaces=false --prefix ../.."
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@sema-agent/
|
|
55
|
+
"@sema-agent/settings-schema": "^5.0.0"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/registry-openapi.yaml
CHANGED
|
@@ -4,7 +4,8 @@ info:
|
|
|
4
4
|
version: "0.1.0"
|
|
5
5
|
description: >
|
|
6
6
|
⚠️ AUTHORITY POSTURE (read first): the registry SERVER lives in the sema-registry repo (web AI);
|
|
7
|
-
the machine contract single-source is `@sema-agent/
|
|
7
|
+
the machine contract single-source is `@sema-agent/settings-schema` (renamed from
|
|
8
|
+
`@sema-agent/registry-core` at 1.0.0, 2026-08-26; zod schemas + path constants —
|
|
8
9
|
AUTH_V1_PATHS/SCOPES_V1_PATHS etc.; the SDK keeps value-copies with same-source anchor tests).
|
|
9
10
|
THIS file documents the surface the SDK's registry subpath actually calls, so a consumer generating
|
|
10
11
|
a client from spec sees the full face — it mirrors, it does not rule. Backfilled 2026-07-28 from
|
|
@@ -12,7 +13,7 @@ info:
|
|
|
12
13
|
`registry-spec-path-gate.test.ts` (reflective: every /api path the SDK hits must be here, zero baseline).
|
|
13
14
|
USER-PLANE paths carry real request/response shapes; the ADMIN family (RegistryAdmin, user-JWT
|
|
14
15
|
role-gated — "admin" is a registry-side ROLE, not a separate credential) is documented loose
|
|
15
|
-
(operator tooling; shapes live in
|
|
16
|
+
(operator tooling; shapes live in settings-schema/zod and the registry server).
|
|
16
17
|
x-sdk-subpath: "@sema-agent/sdk/registry"
|
|
17
18
|
paths:
|
|
18
19
|
/api/healthz:
|
|
@@ -27,7 +28,7 @@ paths:
|
|
|
27
28
|
post:
|
|
28
29
|
operationId: registryDeviceCode
|
|
29
30
|
summary: Start the device-authorization flow (requestDeviceCode).
|
|
30
|
-
requestBody: { required: false, content: { application/json: { schema: { type: object, additionalProperties: true, description: '
|
|
31
|
+
requestBody: { required: false, content: { application/json: { schema: { type: object, additionalProperties: true, description: 'settings-schema DeviceCodeRequest (open: client metadata).' } } } }
|
|
31
32
|
responses:
|
|
32
33
|
'200':
|
|
33
34
|
description: '{device_code, user_code, verification_uri(_complete)?, interval, expires_in}.'
|
|
@@ -36,7 +37,7 @@ paths:
|
|
|
36
37
|
post:
|
|
37
38
|
operationId: registryDeviceToken
|
|
38
39
|
summary: Poll the device flow (pollUntilApproved's leg).
|
|
39
|
-
requestBody: { required: true, content: { application/json: { schema: { type: object, required: [grant_type, device_code], properties: { grant_type: { type: string, description: 'The RFC 8628 device grant type constant (
|
|
40
|
+
requestBody: { required: true, content: { application/json: { schema: { type: object, required: [grant_type, device_code], properties: { grant_type: { type: string, description: 'The RFC 8628 device grant type constant (settings-schema DEVICE_GRANT_TYPE).' }, device_code: { type: string } } } } } }
|
|
40
41
|
description: >
|
|
41
42
|
OAuth device-token semantics: `authorization_pending` keeps the interval, `slow_down` adds +5s,
|
|
42
43
|
`access_denied`/`expired_token` are terminal (typed errors in the SDK). Success = the token pair.
|
|
@@ -85,7 +86,7 @@ paths:
|
|
|
85
86
|
operationId: registryScopesList
|
|
86
87
|
summary: List the caller's scopes (listScopes; `?counts=` optional).
|
|
87
88
|
responses:
|
|
88
|
-
'200': { description: 'ScopesListResponse (
|
|
89
|
+
'200': { description: 'ScopesListResponse (settings-schema schema).', content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
89
90
|
post:
|
|
90
91
|
operationId: registryScopesCreate
|
|
91
92
|
summary: 'ADMIN: create a scope/space.'
|