@sema-agent/sdk 8.2.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/openapi.yaml CHANGED
@@ -1453,7 +1453,7 @@ paths:
1453
1453
  required: [sessionId, leafId]
1454
1454
  properties:
1455
1455
  sessionId: { type: string }
1456
- leafId: { type: string, nullable: true, description: "null = session exists but has no entries yet." }
1456
+ leafId: { type: ["string", "null"], description: "null = session exists but has no entries yet." }
1457
1457
  '304': { description: 'Leaf unchanged since the presented ETag (no body).' }
1458
1458
  '401': { $ref: '#/components/responses/Unauthorized' }
1459
1459
  '404': { $ref: '#/components/responses/NotFound' }
@@ -6684,6 +6684,217 @@ components:
6684
6684
  and the history PULL answers the no-oracle 404 `not_found.blob`, while the REST of the sync
6685
6685
  surface keeps working.
6686
6686
 
6687
+ # ─── S-139(sdk 8.3.0):对 server 7.60.0 的整体重对账补齐的 19 位 ───────────────────────
6688
+ # 行号 = server 7.60.0 树的 `src/http/routes/capabilities.ts`。语义与谓词的全文在
6689
+ # `packages/sdk/src/types.ts` 的 `Capabilities` 同名成员上(逐条亲读 server 源码转述);
6690
+ # 这里只留 codegen 需要的形与一句定性。机械对账门 = `test/server-keyset-parity.test.ts`。
6691
+ deviceExecutor:
6692
+ description: >
6693
+ device lane (capabilities.ts:162). Object OR `false` — same tri-state family as `fleet`.
6694
+ Predicate = `deps.deviceHub` present, byte-identical to the `GET /v1/device/ws` upgrade
6695
+ handler's mount condition. `wsPath` is deliberately on the wire (hard-coding it downstream
6696
+ would turn a path change into a cross-repo breaking change). Device COUNT / online state are
6697
+ deliberately NOT advertised (that is the `/v1/devices/*` admin face).
6698
+ oneOf:
6699
+ - type: boolean
6700
+ enum: [false]
6701
+ - type: object
6702
+ required: [enabled, protocolVersion, maxInflightPerDevice, wsPath]
6703
+ additionalProperties: true
6704
+ properties:
6705
+ enabled: { type: boolean, enum: [true] }
6706
+ protocolVersion: { type: integer }
6707
+ maxInflightPerDevice: { type: integer }
6708
+ wsPath: { type: string }
6709
+ memoryEngine:
6710
+ description: >
6711
+ Memory ENGINE posture (capabilities.ts:210 = `projectMemoryEngineCapability`). Object = the
6712
+ memory face is really lit, `false` = dark. NOT the same thing as `memory`/`memoryWrite` (those
6713
+ advertise the RETIRED MemoryStore HTTP verbs and stay false forever) — the engine has NO HTTP
6714
+ verbs, so a true here does NOT mean there are memory read/write endpoints to call.
6715
+ `vectorMode: null` = this leg has no rung indicator (the `file` engine), NOT "the rung is null".
6716
+ oneOf:
6717
+ - type: boolean
6718
+ enum: [false]
6719
+ - type: object
6720
+ required: [backend, vectorMode]
6721
+ additionalProperties: true
6722
+ properties:
6723
+ backend: { type: string, enum: [file, pg, tidb] }
6724
+ # 🔴 openapi **3.1**:可空用 `type: [T, "null"]`,`nullable` 不是 3.1 关键字(会被静默忽略)。
6725
+ # `null` 也必须进 enum,否则真校验器把 file 引擎的常态答判非法。
6726
+ vectorMode: { type: ["string", "null"], enum: [native, portable, lexical, null] }
6727
+ sql:
6728
+ type: ["object", "null"]
6729
+ additionalProperties: true
6730
+ description: >
6731
+ This deployment's SQL transaction read semantics (capabilities.ts:216 =
6732
+ `projectSqlEngineCapability`), read back AFTER connection initialization set it — same source as
6733
+ the operator `GET /v1/diagnostics/wiring` `sqlEngine` section. `null` = NO SQL backend here
6734
+ (env-only worker / local file backend), NOT "could not read it". `txnMode: null` = this engine
6735
+ has no such indicator, NOT "optimistic".
6736
+ required: [engine, isolation, txnMode]
6737
+ properties:
6738
+ engine: { type: string, enum: [tidb, innodb, pg] }
6739
+ isolation: { type: string }
6740
+ txnMode: { type: ["string", "null"], enum: [pessimistic, null] }
6741
+ sessionBackgroundable:
6742
+ type: boolean
6743
+ description: >
6744
+ The REMOTE lane can detach (capabilities.ts:233 = `Boolean(deps.runStore)`): `POST
6745
+ /v1/tasks/stream` with `x-detach-on-disconnect: true` survives client disconnect; come back via
6746
+ the `X-Task-Id` response header and `GET /v1/runs/{id}` + `/events`. Deployment half only — the
6747
+ per-request half (caller must pass `sessionId`) is not in this bit. Scope is the REMOTE lane;
6748
+ never repurpose it to disable local backgrounding.
6749
+ runMemoryCaptureOptOut:
6750
+ type: boolean
6751
+ description: >
6752
+ `POST /v1/runs/{id}/memory/capture-optout` mid-run flip verb is present (capabilities.ts:237 =
6753
+ `Boolean(deps.runStore)`). Absent ⇒ do not render the affordance. True only promises the
6754
+ ENDPOINT exists, not that THIS run is live (non-live ⇒ 409 with a signposting body).
6755
+ memoryBundle:
6756
+ type: boolean
6757
+ description: >
6758
+ Governance carry-out bundle pair `POST /v1/memory/{export,import}` (operator lane) —
6759
+ capabilities.ts:261, two conjuncts: both engine seams wired AND `operatorPrincipals` NON-EMPTY
6760
+ (an empty roster makes those routes 403 for every identity). True does not promise the backend
6761
+ has the bundle composite face (core then refuses loudly with `memory.export_incomplete`).
6762
+ memoryCompliance:
6763
+ type: boolean
6764
+ description: >
6765
+ Provenance / erasure compliance pair `GET /v1/memory/entries/{entryId}/provenance` and
6766
+ `POST /v1/memory/erase` (operator lane) — capabilities.ts:273, same two-conjunct family as
6767
+ `memoryBundle`. Deliberately NOT the same source as `memoryBundle` (a deployment can have the
6768
+ bundle composite face without control-plane ownership, and vice versa).
6769
+ memoryOrigin:
6770
+ type: boolean
6771
+ description: >
6772
+ External-origin marking face (three routes under `/v1/memory/origin/*`, operator lane) —
6773
+ capabilities.ts:287, same two-conjunct family. Same predicate as `memoryCompliance` TODAY but a
6774
+ deliberately separate bit (two products; a deployment may want only one). True does not promise
6775
+ the `GET …/external` answer is complete — there is no scope enumeration face, so an empty answer
6776
+ must never be read as "the store is clean".
6777
+ memoryConsolidationDriver:
6778
+ type: boolean
6779
+ description: >
6780
+ Consolidation valve pair (`POST /v1/admin/memory/consolidation/run`, `GET
6781
+ /v1/admin/memory/consolidation`, operator lane) — capabilities.ts:301. FALSE ⇒ those routes are
6782
+ **404** (whole domain unmounted), NOT 501: do not branch on 501 here. Contrast
6783
+ `memoryOptOutGrant`, whose false arm IS a 501.
6784
+ memoryOptOutGrant:
6785
+ type: boolean
6786
+ description: >
6787
+ memory-capture opt-out GRANT table admin (four routes under `/v1/admin/memory-optout`,
6788
+ operator-only) — capabilities.ts:307. FALSE ⇒ **501** `capability.memory_optout_grant_required`
6789
+ (change the deployment shape), as opposed to `memoryConsolidationDriver`'s 404 (turn the knob on).
6790
+ permissionModeAuto:
6791
+ type: object
6792
+ additionalProperties: true
6793
+ description: >
6794
+ Default-state disclosure for `permissionMode: "auto"` (capabilities.ts:463; adjudicated by
6795
+ `src/auto-mode-face.ts`). The parts are deliberately NOT folded into one boolean — "this binary
6796
+ does not know auto" and "it knows auto but this box has no entitlement source" would collapse to
6797
+ the same false, and a shell must do different things for those. `reason` is present ONLY when
6798
+ `armed` is false; read its vocabulary as an OPEN set (server already grew it from four words to
6799
+ six). `model` is omitted when the classifier route cannot be resolved (the server logs the
6800
+ engine's refusal rather than 500-ing the read face). `?permissionMode=<five words>` folds the
6801
+ caller's INTENT into the verdict; anything outside the five words is a 400
6802
+ `request.field_invalid`.
6803
+ # 🔴 required 只有**三位**:武装三键(intentArming / armed / reason)是 server >= 7.57.0 (S-80)
6804
+ # 才有的,而本包的支持地板是 3.0.0 => every 7.x <= 7.56.0 server is inside the promised face and
6805
+ # emits ONLY these three (verified verbatim against server tags v7.50.0 / v7.56.0). Requiring the
6806
+ # arming triple would make a SUPPORTED server's legitimate response invalid.
6807
+ required: [accepted, classifierSeat, entitlementSource]
6808
+ properties:
6809
+ accepted: { type: boolean, enum: [true] }
6810
+ classifierSeat: { type: boolean }
6811
+ entitlementSource: { type: boolean }
6812
+ intentArming: { type: boolean, description: 'server >= 7.57.0 only. ABSENT together with `armed`/`reason` on <= 7.56.0.' }
6813
+ armed:
6814
+ type: boolean
6815
+ description: >
6816
+ server >= 7.57.0 only. Read as THREE states, not two: true = will arm; false = will not, and
6817
+ `reason` is then present; ABSENT = an older server that does not report arming at all — never
6818
+ fold that absence into false (it would render a 7.50 box that IS arming as "auto == default").
6819
+ reason:
6820
+ type: string
6821
+ enum: [mode_not_auto, deployment_incapable, org_denied, local_denied, settings_denied, resolver_fault]
6822
+ model: { type: string }
6823
+ readFace:
6824
+ type: ["string", "null"]
6825
+ enum: [open, roots, null]
6826
+ description: >
6827
+ The EFFECTIVE READ containment rung this deployment explicitly declared (capabilities.ts:484 =
6828
+ `deps.config.readFace ?? null`; env `READ_FACE` or config-center's `readFace.face` — same config
6829
+ key, so this bit does not distinguish org-pushed from local). `null` = this deployment pinned
6830
+ NOTHING and the engine default takes over; the server deliberately does NOT fold `null` into
6831
+ `roots` (copying an upstream default onto the wire becomes a lie the day core changes it).
6832
+ Minimal disclosure — the deny table itself is never on the capability face. There is NO
6833
+ per-request `readFace` field on TaskRequest.
6834
+ callerCwd:
6835
+ type: boolean
6836
+ description: >
6837
+ Whether a caller-supplied `cwd` is actually HONORED (capabilities.ts:541 =
6838
+ `cwdHonored(config) || deviceCwdHonored(config)`) — single-user `host` lane OR the `device` lane.
6839
+ Byte-identical predicate to the submit-side gate in `boot/resolve-spec.ts`. Prefer this bit;
6840
+ when absent (older worker) fall back to `projectContext` — that is the verbatim pre-bit behavior.
6841
+ a2a:
6842
+ type: boolean
6843
+ description: >
6844
+ The A2A CLIENT read face `GET /v1/sessions/{id}/a2a` exists (capabilities.ts:555, unconditional
6845
+ `true` — like `mcp`): with no peers configured it returns an honest empty panel, so there is no
6846
+ 501 path to gate on. Deliberately a DIFFERENT predicate from `a2aInjection`.
6847
+ a2aInjection:
6848
+ type: boolean
6849
+ description: >
6850
+ This deployment HONORS a caller-supplied `body.a2aPeers` (capabilities.ts:556 =
6851
+ `a2aInjectionHonored(config)`; three vetoes owned by `task-a2a.ts`: single-user AND `a2a`
6852
+ unlocked AND compliance permits). FALSE is a FIELD gate, not a 4xx: the request still 200s and
6853
+ the field is warned + ignored — EXCEPT under a config lock, where submit refuses 400
6854
+ `config.locked_key`.
6855
+ a2aServe:
6856
+ type: boolean
6857
+ description: >
6858
+ Server-as-peer knob (capabilities.ts:564 = `config.a2aServe !== undefined`): true ⟺
6859
+ `GET /.well-known/agent-card.json` and `POST /v1/a2a` exist; false ⟺ both 404. Scope is ROUTE
6860
+ EXISTENCE, not "every method runs" — `message/send` / `tasks/get` additionally need a durable run
6861
+ store (without it they answer a named JSON-RPC `-32004`).
6862
+ agentRoster:
6863
+ type: boolean
6864
+ description: >
6865
+ `GET /v1/agents/roster` background-agent roster read face (capabilities.ts:640 =
6866
+ `Boolean(deps.backgroundAgentStore)`, byte-identical to that route's 501 gate). Scope is the
6867
+ ENUMERATION face (content-free projection); subagent OUTPUT bodies go through
6868
+ `/v1/runs/{id}/subagents/{handle}/output`, gated by `subagentOutput`.
6869
+ retention:
6870
+ type: ["object", "null"]
6871
+ additionalProperties: true
6872
+ description: >
6873
+ Managed-retention deployment facts (capabilities.ts:654). `null` = the sweep lane is off
6874
+ (default). `mode: audit-only` = it runs and judges but calls NO destructive method; `enforce` =
6875
+ it really deletes. The predicate looks only at config because a box with `intervalSec > 0` and no
6876
+ real executor CANNOT BOOT (`boot/retention-lane.ts` refuses at startup).
6877
+ required: [mode, maxAgeDays]
6878
+ properties:
6879
+ mode: { type: string, enum: [audit-only, enforce] }
6880
+ maxAgeDays: { type: integer }
6881
+ workflowsGate:
6882
+ type: object
6883
+ additionalProperties: true
6884
+ description: >
6885
+ Self-orchestration denial disclosure (capabilities.ts:739). The two parts are deliberately not
6886
+ folded: `engineCan` = core's `workflowsCapability`; `denial` = the DEPLOYMENT-level admission
6887
+ refusal (closed set, today's only member `entitlement_resolver_absent`), `null` = this layer does
6888
+ not refuse. Non-null means the engine is there but this deployment can grant it to NO principal
6889
+ (half-configured) — signpost the OPERATOR, do not tell the user to retry. `denial: null` does NOT
6890
+ mean "you are authorized" (that is per-principal). `workflows` is the PRODUCT of the two factors.
6891
+ required: [engineCan, denial]
6892
+ properties:
6893
+ engineCan: { type: boolean }
6894
+ denial:
6895
+ type: ["string", "null"]
6896
+ enum: [entitlement_resolver_absent, null]
6897
+
6687
6898
  SkillSpec:
6688
6899
  type: object
6689
6900
  description: A per-request skill (passed as an object; core-native TaskSpec.skills shape).
@@ -10089,6 +10300,53 @@ components:
10089
10300
  parentToolCallId: { type: string }
10090
10301
  depth: { type: integer }
10091
10302
  agentName: { type: string }
10303
+ # ─── S-139(sdk 8.3.0):对 server 7.60.0 的整体重对账补齐的 9 位 ────────────────────────
10304
+ # 长 description 的单一真源在 `packages/sdk/src/resources/tool-approvals.ts` 的同名成员上;
10305
+ # 这里只留 codegen 需要的形与硬条款一句。机械对账门 = `test/server-keyset-parity.test.ts`。
10306
+ requiresRealApproval:
10307
+ type: boolean
10308
+ enum: [true]
10309
+ description: >
10310
+ server >= 7.30.0 (core 5.37, #283), "tool_approval" only, ADDITIVE: the SAFETY-class provenance
10311
+ bit core stamps at the gate. Present (true) or ABSENT — never encoded as false. Deliberately a
10312
+ DIFFERENT contract from the card's `risk.requiresRealApproval` (which is an always-present
10313
+ boolean): the card form needs the durable ask store, and this key is what lets a LIVE-ONLY
10314
+ deployment read the bit at all. Present ⇒ every automatic allowance (remembered rules,
10315
+ bypassPermissions posture) stands down.
10316
+ origin: { $ref: '#/components/schemas/AskOrigin' }
10317
+ inputHasBidi:
10318
+ type: boolean
10319
+ enum: [true]
10320
+ description: >
10321
+ server >= 7.45.0 (E-14), "tool_approval" only, ADDITIVE: the TO-BE-EXECUTED input (`args`)
10322
+ contains Unicode bidi control characters — what the eye reads may not be the byte order that
10323
+ runs. DISCLOSURE bit, bytes unchanged (sanitising would change the bytes about to execute, which
10324
+ is WORSE than not disclosing); rendering is the shell's. Present (true) or ABSENT; absence !=
10325
+ "verified clean". Computed BEFORE the byte cap, so it can ride a frame whose `args` were omitted.
10326
+ expiresAtMs:
10327
+ type: integer
10328
+ description: >
10329
+ server >= 7.34.0 (#288), "tool_approval" only, ADDITIVE: window triple (with `expiresInMs` and
10330
+ `serverNowMs`, same names/semantics as on ApprovalRequestFrame) so the LEGACY frame family can
10331
+ render a countdown too. `expiresAtMs` = this ask's absolute deadline on the server clock. The
10332
+ three keys are BORN AND ABSENT TOGETHER — any frame that gets emitted carries all three.
10333
+ expiresInMs:
10334
+ type: integer
10335
+ description: 'Window triple (see expiresAtMs): max(0, expiresAtMs - serverNowMs), computed at mint time.'
10336
+ serverNowMs:
10337
+ type: integer
10338
+ description: 'Window triple (see expiresAtMs): the server clock at FRAME MINT time — the countdown anchor; use it to correct local clock skew.'
10339
+ ruleOffersAbsence: { $ref: '#/components/schemas/RuleOffersAbsence' }
10340
+ denialLimitFallback: { $ref: '#/components/schemas/DenialLimitFallback' }
10341
+ parked:
10342
+ type: boolean
10343
+ enum: [true]
10344
+ description: >
10345
+ server >= 7.42.0 (#329), "tool_approval_complete" ONLY, ADDITIVE: the explicit discriminator for
10346
+ the PARK sense of `outcome: "expired"` (which is one word with three landings). Present ⇔ THIS ask
10347
+ settled through the park route ⇒ render "moved to the background queue", not "the card died".
10348
+ 🔴 ABSENCE MUST NOT BE READ AS "really denied": a store-less deployment, a deny policy, and a
10349
+ sibling VOIDed in a batch all emit no such key — absence only means "no park evidence".
10092
10350
  outcome:
10093
10351
  type: string
10094
10352
  enum: [allowed, denied, expired]
@@ -10226,6 +10484,10 @@ components:
10226
10484
  probeCause: { type: object, additionalProperties: true, description: 'server >= 7.17.0: structured reversibility-probe tightening cause — same shape and semantics as ToolApprovalFrame.probeCause ({code, roots:{shown,total}, further?:{shown,total}}); frame and card carry the SAME value (one narrow-read function server-side). See that key for the full contract.' }
10227
10485
  ruleEvidence: { type: object, additionalProperties: true, description: 'server >= 7.23.0: rule-provenance evidence — same shape and semantics as ToolApprovalFrame.ruleEvidence (each member a value or a NAMED absence word; display/reconciliation metadata, never adjudication input). Frame and card carry the SAME value. See that key for the full contract.' }
10228
10486
  delegation: { $ref: '#/components/schemas/ApprovalCardDelegation' }
10487
+ # S-139(sdk 8.3.0):同 A-057.④ 的理由 —— server 早随卡投出(帧与卡同一只窄读函数 ⇒ 同值),
10488
+ # 但本 schema 此前只在帧上公示过。长 description 的单一真源在 ToolApprovalFrame 的同名键。
10489
+ ruleOffersAbsence: { $ref: '#/components/schemas/RuleOffersAbsence' }
10490
+ denialLimitFallback: { $ref: '#/components/schemas/DenialLimitFallback' }
10229
10491
 
10230
10492
  RuleSuggestion:
10231
10493
  type: object
@@ -10248,6 +10510,69 @@ components:
10248
10510
  description: '`exact` = this one command only (`Bash(git status)`); `prefix` = word-boundary prefix (`Bash(git status:*)`). Closed vocabulary — an unknown value is not a candidate this contract describes; do not render it as redeemable.'
10249
10511
  command: { type: string, maxLength: 512, description: 'The command pattern inside the rule, for a shell that would rather not re-parse `rule`.' }
10250
10512
 
10513
+ # ─── S-139(sdk 8.3.0):对 server 7.60.0 整体重对账带进来的四张型面 ───────────────────────
10514
+ AskOrigin:
10515
+ type: string
10516
+ enum: [content_question, unresolvable, org_unavailable, org_rule, hook, ask_rule, denial_limit_fallback, policy]
10517
+ description: >
10518
+ WHO raised an ask (`ToolApprovalFrame.origin`; server >= 7.57.0 / core 7.5.0, S-125③/#564) — core's
10519
+ `ASK_ORIGINS`, ENGINE-STAMPED at the gate (core's words: "engine-stamped at the gate, never a policy's
10520
+ claim"), transcribed verbatim by the server, which deliberately mints no second eligibility table of
10521
+ its own.
10522
+
10523
+ 🔴 READ AS AN OPEN SET. The vocabulary's sole owner is core and it has grown before; branch with a
10524
+ default arm and treat an unknown word as "unknown origin", never as "no origin".
10525
+ 🔴 NOT interchangeable with `governanceForced`: this says which KIND of authority asked, that one says
10526
+ whether THIS DEPLOYMENT's ops governance layer is the gate — `origin: policy` covers any deployment
10527
+ ToolPolicy's ask, so a governance-produced ask and an ordinary one look identical in this one word.
10528
+
10529
+ RuleOffersAbsence:
10530
+ type: string
10531
+ enum: [mandated, shadowed, lane_cannot_speak]
10532
+ description: >
10533
+ WHY `ruleOffers` is absent while the rule lane IS present (`ToolApprovalFrame.ruleOffersAbsence` and
10534
+ `ApprovalCard.ruleOffersAbsence`; server >= 7.55.0 / core #490 fix ②, S-15). The engine names which
10535
+ door is shut: `mandated` = this ask must be confirmed every time (🔴 this arm must NOT point the user
10536
+ at writing a rule — a rule would not silence it, and saying so sends them into a loop); `shadowed` = a
10537
+ rule matched but could not clear it (the machine-readable twin of `persistedRuleShadowed`);
10538
+ `lane_cannot_speak` = the engine could mint no coverable form for this command.
10539
+
10540
+ Engine-side MUTUALLY EXCLUSIVE with `ruleOffers`. 🔴 ABSENCE IS NOT AN ASSERTION — it covers both
10541
+ "there are offers" and the three structural doors, and one frame cannot tell them apart. ADVISORY
10542
+ display metadata, NEVER adjudication input. The frame and the stored `card_json` go through the SAME
10543
+ server-side narrow read, so both faces carry identical values; a word outside the set is treated as
10544
+ malformed and the key is not minted at all (the server never passes an unknown word through).
10545
+
10546
+ DenialLimitKind:
10547
+ type: string
10548
+ enum: [consecutive, total]
10549
+ description: 'Which bound tripped in a `DenialLimitFallback` — the consecutive-refusal limit or the cumulative one.'
10550
+
10551
+ DenialLimitFallback:
10552
+ type: object
10553
+ additionalProperties: false
10554
+ required: [consecutive, total, limit, autoDenyAfterMs]
10555
+ description: >
10556
+ The auto-mode classifier's DENIAL-LIMIT FALLBACK card (`ToolApprovalFrame.denialLimitFallback` and
10557
+ `ApprovalCard.denialLimitFallback`; server >= 7.57.0 / core 7.4.0 #548, S-114): the call that hit the
10558
+ consecutive (default 3) or cumulative (default 20) refusal limit is no longer silently denied — it
10559
+ becomes a card a HUMAN must decide. The same mint also stamps `requiresRealApproval`; the two are twins.
10560
+
10561
+ 🔴 ALL FOUR MEMBERS ARE REQUIRED: core's shape has no optional member, so "one missing" is a bad value
10562
+ rather than an older core, and the server drops the whole key instead of half-minting a card whose
10563
+ counts would be misread.
10564
+ 🔴 `autoDenyAfterMs` (ms; `0` = not armed — the deployment turned the knob off, or a TOTAL-tier card
10565
+ waits for a person) is for RENDERING THE COUNTDOWN ONLY. Never start a second timer from it: the window
10566
+ is executed by the ENGINE, and two overlapping windows are worse than the original defect and silent.
10567
+ 🔴 ABSENCE IS NOT AN ASSERTION — the vast majority of asks are not fallback cards.
10568
+ ⚠️ The durable (parked) leg does NOT carry this key today; the card's copy rides `card_json`, which is
10569
+ a different leg from the parked row's `pendingAction`.
10570
+ properties:
10571
+ consecutive: { type: integer, description: 'Consecutive refusals at the moment the limit tripped.' }
10572
+ total: { type: integer, description: 'Cumulative refusals at the moment the limit tripped.' }
10573
+ limit: { $ref: '#/components/schemas/DenialLimitKind' }
10574
+ autoDenyAfterMs: { type: integer, description: 'This card''s own auto-deny window in ms; 0 = not armed. Countdown rendering only.' }
10575
+
10251
10576
  RuleOfferMatch:
10252
10577
  type: string
10253
10578
  description: >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/sdk",
3
- "version": "8.2.0",
3
+ "version": "8.3.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",