@sema-agent/sdk 16.1.0 → 16.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +111 -1
  2. package/dist/errors.d.ts +52 -12
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +31 -5
  5. package/dist/errors.js.map +1 -1
  6. package/dist/events.d.ts +8 -0
  7. package/dist/events.d.ts.map +1 -1
  8. package/dist/events.js.map +1 -1
  9. package/dist/index.d.ts +7 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/resources/adoption.d.ts +2 -1
  14. package/dist/resources/adoption.d.ts.map +1 -1
  15. package/dist/resources/adoption.js +2 -1
  16. package/dist/resources/adoption.js.map +1 -1
  17. package/dist/resources/approvals.d.ts +10 -3
  18. package/dist/resources/approvals.d.ts.map +1 -1
  19. package/dist/resources/approvals.js +11 -3
  20. package/dist/resources/approvals.js.map +1 -1
  21. package/dist/resources/assistant.d.ts +4 -2
  22. package/dist/resources/assistant.d.ts.map +1 -1
  23. package/dist/resources/assistant.js.map +1 -1
  24. package/dist/resources/leader.d.ts +5 -4
  25. package/dist/resources/leader.d.ts.map +1 -1
  26. package/dist/resources/leader.js +5 -4
  27. package/dist/resources/leader.js.map +1 -1
  28. package/dist/resources/memory.d.ts +6 -2
  29. package/dist/resources/memory.d.ts.map +1 -1
  30. package/dist/resources/memory.js +3 -1
  31. package/dist/resources/memory.js.map +1 -1
  32. package/dist/resources/ops.d.ts +3 -0
  33. package/dist/resources/ops.d.ts.map +1 -1
  34. package/dist/resources/ops.js +3 -0
  35. package/dist/resources/ops.js.map +1 -1
  36. package/dist/resources/rules.d.ts +4 -3
  37. package/dist/resources/rules.d.ts.map +1 -1
  38. package/dist/resources/rules.js +3 -3
  39. package/dist/resources/rules.js.map +1 -1
  40. package/dist/resources/runs.d.ts +26 -6
  41. package/dist/resources/runs.d.ts.map +1 -1
  42. package/dist/resources/runs.js +9 -2
  43. package/dist/resources/runs.js.map +1 -1
  44. package/dist/resources/session-sync.d.ts +11 -7
  45. package/dist/resources/session-sync.d.ts.map +1 -1
  46. package/dist/resources/session-sync.js +9 -6
  47. package/dist/resources/session-sync.js.map +1 -1
  48. package/dist/resources/sessions.d.ts +9 -3
  49. package/dist/resources/sessions.d.ts.map +1 -1
  50. package/dist/resources/sessions.js +9 -3
  51. package/dist/resources/sessions.js.map +1 -1
  52. package/dist/resources/tasks.d.ts +13 -1
  53. package/dist/resources/tasks.d.ts.map +1 -1
  54. package/dist/resources/tasks.js +13 -1
  55. package/dist/resources/tasks.js.map +1 -1
  56. package/dist/resources/tool-approvals.d.ts +83 -12
  57. package/dist/resources/tool-approvals.d.ts.map +1 -1
  58. package/dist/resources/tool-approvals.js +37 -1
  59. package/dist/resources/tool-approvals.js.map +1 -1
  60. package/dist/resources/workflows.d.ts +5 -2
  61. package/dist/resources/workflows.d.ts.map +1 -1
  62. package/dist/resources/workflows.js +5 -2
  63. package/dist/resources/workflows.js.map +1 -1
  64. package/dist/settings.d.ts +22 -8
  65. package/dist/settings.d.ts.map +1 -1
  66. package/dist/sync.d.ts +19 -2
  67. package/dist/sync.d.ts.map +1 -1
  68. package/dist/sync.js +88 -2
  69. package/dist/sync.js.map +1 -1
  70. package/dist/types.d.ts +195 -26
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js.map +1 -1
  73. package/openapi.yaml +464 -101
  74. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -57,7 +57,7 @@
57
57
  * null" may be correct — check for a normalizer at the boundary before widening it to `| null`.
58
58
  */
59
59
  import type { SemaSettings } from "./settings.js";
60
- import type { AskOrigin, ClassifierUnavailable, DenialLimitFallback, PersistedRuleMandate, RuleOffer, RuleOffersAbsence, ToolApprovalFrame } from "./resources/tool-approvals.js";
60
+ import type { AllowRuleShadow, AskOrigin, ClassifierUnavailable, DenialLimitFallback, PersistedRuleMandate, RuleOffer, RuleOffersAbsence, ToolApprovalFrame } from "./resources/tool-approvals.js";
61
61
  /** Authenticated end-user identity. Opaque to the service (used as memory scope + session owner). The SDK
62
62
  * normalizes; the service does NOT validate the format. Convention: `user:` / `org:` / `ai:` / `anon:`. */
63
63
  export type Principal = string;
@@ -309,8 +309,19 @@ export interface TaskRequest {
309
309
  * {@link import("./settings.js").SemaSettings.skillListingMaxDescChars} 两只旋钮。
310
310
  *
311
311
  * Merge: scenario WINS on name collision (user's dropped + warn-logged) — the safety baseline can't be
312
- * overridden. Injected by the trusted BFF, never raw user input. */
312
+ * overridden. Injected by the trusted BFF, never raw user input.
313
+ *
314
+ * 🔴 **server ≥7.116.0:每只技能可带 `allowedTools` / `disallowedTools`(本 run 的 allow / deny 规则来源,不是围栏 —— 读法与比 `settings.permissions.allow` 宽的口径见
315
+ * {@link SkillSpec.allowedTools};探测位 `capabilities.skillToolLists`),技能的 `manifest` 键提交即 400**(core 7.41.0 退役;`manifest.allowTools` 改写成 `allowedTools`)。 */
313
316
  skills?: SkillSpec[];
317
+ /** server ≥7.116.0(core 7.41.0 #1303):**人用名字点过的技能**(壳从人敲的 `/name` 解析出来的,按 {@link SkillSpec.name})—— 非空串数组。这些技能的
318
+ * `allowedTools` / `disallowedTools` **开跑即生效、不出 `Skill` 卡**(人自己点的名就是那句表态);**只管这一次** run(steer 不终止它,下一次提交不带)。
319
+ * 每个名字必须是这一 run 装着的技能(场景出厂 ∪ 本请求 `skills`),否则引擎拒启 **400 `config.user_invoked_skill_unknown`**(同步腿 `POST /v1/tasks`;
320
+ * 异步 / 活流腿 HTTP 2xx、同码落在终态 run 行);`disableSkills: true` 时点任何名字都是这个码。值形坏(裸串 / 含空串 / 含非串 / 对象 / null)⇒ 400
321
+ * `request.field_invalid`。不投递技能正文(正文照旧由 `Skill` 工具 / 调用方负责)。
322
+ * 🔴 **先探 `capabilities.userInvokedSkills`**(恒真):位缺席 = 老 server ⇒ **别发这个键**(≤7.115.x 答 400 `request.body_shape`,`unknownKeys` 逐字列名)。
323
+ * 清单的读法见 {@link SkillSpec.allowedTools}(比同版 `settings.permissions.allow` 宽;托管 / 多租户部署不设开关)。 */
324
+ userInvokedSkills?: string[];
314
325
  /** Per-turn reasoning strength (CC `/effort` parity). One of the core ThinkingLevel tiers:
315
326
  * `off`|`minimal`|`low`|`medium`|`high`|`xhigh`|`max`. Service maps it → `TaskSpec.thinking`
316
327
  * (server.ts reasoningEffort → main.ts:1270); an UNKNOWN value is a 400 (fail-loud). Omit ⇒ engine
@@ -357,6 +368,12 @@ export interface TaskRequest {
357
368
  * **单独送 `debate:true` 不会有辩论轮**;②`resolve-spec` 的显式组队判据是 `council || debate`
358
369
  * (`:940/1555`)⇒ 单独送它**仍然**会放宽租期预算并抑制自动升档。同样只有字面 `true` 算数。 */
359
370
  debate?: boolean;
371
+ /** 图文输入:`{ data, mimeType }`(内联 base64)或 `{ url }`。
372
+ * 🔴 **内联臂的准入(server ≥7.117.0 / core 7.42.0)**:`mimeType` 必须是 `image/png` / `image/jpeg` / `image/gif` / `image/webp` 之一(发 API 自己的类型词,不发扩展名),解码后的字节必须带**声明类型**的文件签名,
373
+ * 解码后不得超 5 MiB —— 过不了 ⇒ 引擎在**第一次模型调用之前**拒(UserPromptSubmit hook 之后,一个模型 token 没烧),**400 `config.image_invalid`**,`error` 以 `TaskSpec.images: ` 起
374
+ * (`config.` 不是前缀族 ⇒ 带码的 `APIError`,按 `errorCode` 分支;400 不自动重试)。≤7.116.x 没有这道门:这种图原样送到模型供应方,整只首请求在供应方那边失败(没有本包可依的码)。
375
+ * **「base64 太长」不走本码**:一张内联图的 base64 串超过 5 242 880 字符(模型 API 的 5 MB 图片界;server 读引擎导出的同一只常量)⇒ 受理口先拒 **413 `request.payload_too_large`**(零模型调用、不跑提交钩子、不建 run 行)。
376
+ * 出路:发文件的原样字节与 API 的类型词;超 5 MB 的图先缩。URL 臂(`{ url }`)不变(server 早已按签名认类型)。模型要支持图片输入(见 {@link ModelInfo.vision};缺席 ⇒ 照发)。 */
360
377
  images?: Array<{
361
378
  data: string;
362
379
  mimeType: string;
@@ -901,12 +918,20 @@ export interface TaskAgentDefinition {
901
918
  allowTools?: string[];
902
919
  /** Denylist of tool names (subtractive; applied after `allowTools`). */
903
920
  denyTools?: string[];
904
- /** Skills preloaded into the agent: `{ name, description, content }` (+ optional manifest/files). */
921
+ /** Skills preloaded into the agent: `{ name, description, content }` (+ optional allowedTools / disallowedTools / files).
922
+ * server ≥7.116.0:子代技能受理两只清单(`allowedTools` / `disallowedTools`,读法见 {@link SkillSpec.allowedTools};≤7.115.x 是未知键整条拒)。 */
905
923
  skills?: Array<{
906
924
  name: string;
907
925
  description: string;
908
926
  content: string;
927
+ /** @deprecated server ≥7.116.0 **整条技能拒**(子代技能上 `manifest` 是未知键 ⇒ `agent.skills must be …` 400;顶层技能是 400 `request.field_invalid`,
928
+ * 句首 `skill.manifest was retired in core 7.41.0 — `)—— core 7.41.0 退役了技能 `manifest`(硬破坏,零别名)。**改写**:`manifest.allowTools` →
929
+ * 技能的 `allowedTools`(语义变了:allow 规则来源、不是围栏,见 {@link SkillSpec.allowedTools});写围栏 `allowPaths` 没有替身
930
+ * (圈写路径用会话规则 `allowDirs`)。详见 server 随包 `MIGRATION.md` 7.116.0 节。
931
+ * 本成员**留着**:老一代 server(≤7.115.x)仍收它,删公开成员 = major,下个 major 删;对 ≥7.116.0 的 server 别再发。 */
909
932
  manifest?: Record<string, unknown>;
933
+ allowedTools?: string[];
934
+ disallowedTools?: string[];
910
935
  files?: Array<{
911
936
  path: string;
912
937
  content: string;
@@ -1375,7 +1400,10 @@ export interface ModelInfo {
1375
1400
  provider?: string;
1376
1401
  /** 该模型是否 reasoning 档(picker 可标徽章)。 */
1377
1402
  reasoning?: boolean;
1378
- /** 是否支持图片输入。 */
1403
+ /** 这条目录行**收不收图片输入**,三态(server ≥7.117.0;之前对没声明的条目报 `false`):`true` = 条目声明了 `input` 且含 `"image"`;`false` = 声明了 `input` 且不含它;
1404
+ * **键缺席 = 条目没声明 `input`**(手写的目录条目;env 车道与配置中心车道恒声明,不会缺席)—— 缺席 = **不知道**,不是 `false`。
1405
+ * 🔴 消费方读法:**缺席 ⇒ 照发并告知**(把图交给 server,由引擎处理;收不收以引擎为准),**不要读成 false(也就是别据此把用户的图拦在本地)** —— server 对同一条目在运行期照样把图交给模型,
1406
+ * 拦截只会让「目录说不知道」变成「用户发不出图」。≤7.116.x 的 server 对没声明的条目报 `false`(那是它们的读法,同一个坑);只有明说 `false` 才该提示「这个模型不收图」。 */
1379
1407
  vision?: boolean;
1380
1408
  /** E4(shell-host;service src/http/routes/capabilities.ts,SHIPPED)— 上下文窗口 token 总额 = 「% 上下文已用 / 距 compact N
1381
1409
  * token / 低上下文告警」仪表的**分母**。soft-degrade:未知(0)则 service 省略 → 壳渲染裸 token 数无 %。
@@ -2073,7 +2101,17 @@ export interface RunRecord {
2073
2101
  result?: TaskResult | LegacyPlaneTaskResult;
2074
2102
  /** 本**行的列**,7.64.0 未变(照旧说五词);只是数据源改成从 `result.terminal` 投影一次(旧行则直接读平面键)。
2075
2103
  * ⚠️ K-24 / S-173(server ≥7.104.0):`needs_review` park 行上本位 = core 的规范码 **`review.pending`**(此前缺席)——
2076
- * **禁**把「本位在场」读成失败,先读 `status`。`suspended` park 行缺席。 */
2104
+ * **禁**把「本位在场」读成失败,先读 `status`。`suspended` park 行缺席。
2105
+ *
2106
+ * 🔴 **server ≥7.116.0 多三种取值(additive 读面;S-1099)**:run 店自己判的终局此前只在 `error` 句子里,现在同时带机读码 ——
2107
+ * **`run.stalled`**(失联收割:心跳旧于 `REAP_RUN_STALE_SEC` 的 `running` 行被收割;读面在收割落盘前提前折叠的那一形同码;句子 `run stalled (instance lost?)`)·
2108
+ * **`run.orphaned`**(local 车道重启回收 / 会话占用接管回收;句子 `run orphaned by engine restart`)·
2109
+ * **`approval.expired`**(审批过期收割:耐久审批停驻的 run 过期被收割;行上码列早就有,读面此前不投;句子 `approval expired before decision`)。句子照旧。
2110
+ * 这三码都**不是请求写错**,重试同一请求无意义,重新提交才有新 run;按 `error` 句子判「持有者没了」的消费端改按本码判;把「`errorCode` 在场」读成「core 报了错」的消费端
2111
+ * **先读 `status`**(`failed`)再按码分支。本位**仍是开集串**(词表属主在 server / core,分支永远带 `default`),没有闭集可加。
2112
+ * 🔴 **缺席语义(旧行)**:升级前(≤7.115.x)写下的死亡判决行只有 `error` 句子、码列为空 —— 7.116.0 每次起服做**一次性迁移补码**(`one_time_migrations_applied` 的
2113
+ * `holderDeathCodeRowsBackfilled`),SQL 后端的新副本读这种行时同样读成码(升级窗);**但迁移有窗**(发布日 + 30 天之后的第一个小版本把写回与读侧一起删),
2114
+ * 删后仍只有句子的行不再带码、`errorCode` 缺席 —— 所以「本位缺席 ≠ 不是持有者死亡」,**旧行迁移补码之后仍可能无码**,别拿缺席反推别的。 */
2077
2115
  errorCode?: string;
2078
2116
  error?: string;
2079
2117
  /** Work-view correlation. Present when the run has a jobId (omitted when null). LIVE server-side
@@ -2370,14 +2408,20 @@ export type DeniedBy = "policy" | "hook" | "org" | "persisted_rule" | "classifie
2370
2408
  */
2371
2409
  export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypassPermissions" | "dontAsk";
2372
2410
  /**
2373
- * 一只问**属于哪一类**(core `ASK_CLASSES`:7.34.0 铸二十词,core 7.39.0 起 `shell_floor` 入册 ⇒ 二十一词,core 7.40.0 起 `unstated` 入册 ⇒ **二十二词**;模式 × 类仲裁表的列)。K-32 扩项 / server ≥7.106.0 起出现在
2411
+ * 一只问**属于哪一类**(core `ASK_CLASSES`:7.34.0 铸二十词,core 7.39.0 起 `shell_floor` 入册 ⇒ 二十一词,core 7.40.0 起 `unstated` 入册 ⇒ 二十二词,core 7.41.0 起 `requires_user_interaction` 入册 ⇒ **二十三词**;模式 × 类仲裁表的列)。K-32 扩项 / server ≥7.106.0 起出现在
2374
2412
  * {@link ModeRelease.askClass} / `.classes` 与 deny 臂的 `askClass` / `classes` 上,以及通告 `permission.ask_released_by_mode` 的 detail 里;
2375
2413
  * K-37 扩项 / server ≥7.109.0(S-934 ②)起也在审批面:活卡帧 / 卡面 / 运维队列行 / `/stream` `pending` 帧的 `askClass` / `classes`
2376
2414
  * (同样经 core `isAskClass` 筛,读不出整对不投;见 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.askClass})。
2377
2415
  * 🔴 **门记录这一面是真闭集**(server 按 core `isAskClass` 筛,出集整条不上帧)。`bypassPermissions` 只放行其中**可放**的十类
2378
2416
  * (core `RELEASABLE_ASK_CLASSES`:`transcript_write` / `rule_unreadable` / `probe` / `write_protection` / `tool_marks_mcp` / `tool_marks_a2a` /
2379
2417
  * `artifact_shared_read` / `mode` / `unstated` / `ordinary`);其余(`operator_forced` 部署出身、`ask_rule` / `org_rule`、`hook`、`ancestor`、`content_question`、
2380
- * `unverifiable_delete`、`governance_unavailable`、`policy_rra` …)任何模式下都照问。
2418
+ * `unverifiable_delete`、`governance_unavailable`、`policy_rra`、`requires_user_interaction` …)任何模式下都照问。
2419
+ *
2420
+ * 🔴 **`requires_user_interaction`(core 7.41.0;server ≥7.116.0 提货)= 服务器声明「这只工具每次都要用户在场」**:MCP 服务器在工具申报里声明
2421
+ * `_meta["anthropic/requiresUserInteraction"] === true`(只认布尔 `true`)⇒ 这只工具的**每一次**调用都问人 —— **每种模式含 `bypassPermissions`** 都问(**不在**可放十类里),
2422
+ * 且**只有人的答**清得掉:请求 `settings.permissions.allow`、运维 `APPROVAL_GRANT`、技能清单 + `userInvokedSkills`、PreToolUse hook 的显式 allow 都清不掉它;
2423
+ * 无审批席 ⇒ 拒(服务器侧零收到)、无人值守腿不答这一类;帧上同带 `requiresRealApproval:true` / `mandated:true`(`origin:"safety_tighten"`),卡上没有「不再询问」规则。
2424
+ * 按 `askClass` 穷举渲卡的客户端要加这一个词;本型是闭集(server 对 `askClass` / `classes` 按 core `isAskClass` 筛,出集整对不投)。
2381
2425
  *
2382
2426
  * 🔴 **`unstated`(core 7.40.0;server ≥7.115.0 提货)= 没人表态的调用**:询问类模式(`default` / `acceptEdits` / `auto` / `plan`)下,MCP 服务器工具 / A2A 技能(引擎里「自己不表态权限」的席位)的调用,
2383
2427
  * 走到折叠尾**没有任何一层**(规则 / hook / 审批人 / 分类器 / 模式释放)说过「这次可以」⇒ 出一张 `askClass: "unstated"` 的卡(卡句 `The agent requested permission to use <tool>, but it has not been granted yet.`);
@@ -2385,7 +2429,9 @@ export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypa
2385
2429
  * 先探 `capabilities.settings.permissions.allowGrant`)· 运维 env `APPROVAL_GRANT` · PreToolUse hook 显式 `permissionDecision:"allow"` · 接审批面 · `permissionMode:"bypassPermissions"`(请求腿);
2386
2430
  * `plan` 模式下只有**只读**的服务器工具出这张卡。本类说的是「**没人说**」,不是 `ask_rule` / `org_rule` 那种「有人说了问」。
2387
2431
  */
2388
- export type AskClass = "content_question" | "hook" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "operator_forced"
2432
+ export type AskClass = "content_question" | "hook" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback"
2433
+ /** core 7.41.0 / server ≥7.116.0:服务器工具申报声明「每次调用都要用户在场」(见本型顶注)—— **不在** `bypassPermissions` 可放的十类里,只有人的答清得掉。 */
2434
+ | "requires_user_interaction" | "operator_forced"
2389
2435
  /** core 7.39.0(#1260;server ≥7.113.0 提货):运维旋钮 `shellGate: "always"` 在**跑 shell 的席位**上的地板 —— `operator_always` 授权词所披露的那一问,
2390
2436
  * 自己成一类,免得持有另一种强制问的类集把它藏掉。与 `operator_forced` 同样**免疫 bypass**(不在 `bypassPermissions` 可放的十类里)。 */
2391
2437
  | "shell_floor" | "write_protection_unresolved" | "probe" | "write_protection" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "mode"
@@ -3208,6 +3254,32 @@ export interface SkillSpec {
3208
3254
  name: string;
3209
3255
  description: string;
3210
3256
  content: string;
3257
+ /** server ≥7.116.0(core 7.41.0 技能清单取上游全形):这只技能的**allow 规则来源**(字符串数组;条目文法 = 持久规则文法 ——
3258
+ * 工具名、`mcp__<server>` / `mcp__<server>__*` 一类协议名;`*` / 写路径 / 域名形什么都不授予)。
3259
+ * 🔴 **读法变了:它不是围栏**(≤7.115.x 引擎 7.40 把它当「只许这些」的围栏读)—— 7.116.0 起**没列的工具照常判**(询问类模式下问、
3260
+ * `bypassPermissions` 或部署 allow 下直接跑),不再因为没列被拒;**列着的工具在这只技能被激活之后、本 run 内免问**
3261
+ * (激活 = 请求顶层 {@link TaskRequest.userInvokedSkills} 点了它的名〔开跑即生效、不出 `Skill` 卡〕,或模型调 `Skill` 激活且那张卡被批准)。
3262
+ * 清的是引擎的普通问与「没人表态」两类问;deny 规则 / ask 规则 / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell 地板 / 写保护 / plan 模式的问,清单都清不掉。
3263
+ * 🔴 **与 `settings.permissions.allow` 的关系随 server 代际变(7.117.0 起收成一种读法)**:**≥7.117.0**(能力位 `settings.permissions.allowLayer`,core 7.42.0)两只请求级放行源是**同一读法**
3264
+ * —— 同一条条目逐格同读(都进引擎的 allow 层、都清内置工具的写门 / shell 普通问、读成空的条目都发通告 `permission.allowed_tool_not_granted`);**7.116.x 上**请求自带技能的清单
3265
+ * **比同版 `settings.permissions.allow` 更宽**(后者当时只是表态,不放内置工具上引擎自己的写门 / shell 普通问)—— 那一口径到 7.116.x 为止。
3266
+ * 值形:字符串数组(含空数组)⇒ 受理;裸串 / 含非串 / 对象 ⇒ 400 `request.field_invalid`;协议名的服务器段铸不出 / 缺段 / 带通配(`mcp__*`)⇒ 400
3267
+ * (顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)。🔴 **7.117.0 起另有两道**(两张清单、顶层与子代两处受理口同判):**名字层**与 `settings.permissions.allow` 同一只判官 —— 退役名 / 无前缀短名(例 `Task`)
3268
+ * 提交即 400(7.116.x 受理,引擎读作一个永不命中的名字);每张清单**超过 1000 条** ⇒ 400(句子给写法「合并成更宽的条目」;7.116.x 无帽)。
3269
+ * 🔴 **先探 `capabilities.skillToolLists`**:位缺席 = 老 server ⇒ 顶层技能上的两只清单**照收但引擎不读**(静默不生效,没有 400 可探 ——
3270
+ * 别指望清单拦得住工具,圈工具用 deny 规则),子代技能上是未知键整条拒。
3271
+ * 🔴 `manifest` 键 server ≥7.116.0 **提交即拒**(顶层 400 `request.field_invalid`、子代整条技能拒);改写 `manifest.allowTools` → 本键;
3272
+ * 写围栏 `allowPaths` 没有替身(圈写路径用会话规则 `allowDirs`)。本型从不声明 `manifest` ⇒ 顶层按型写不出它。 */
3273
+ allowedTools?: string[];
3274
+ /** server ≥7.116.0:这只技能的 **deny 规则来源**(同 {@link allowedTools} 的文法 / 两道受理门 / 探测位):技能被激活之后,本 run 内这些工具**拒**(不执行、零卡,
3275
+ * `tool_end.gate.disposition` 为 `{ kind: "denied", deniedBy: "policy" }`);写路径形(`Write(/tmp/**)`)与命令规则照编 deny 行。
3276
+ * 🔴 **server ≥7.117.0:引擎读成空的条目提交即 400**(顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)—— `*`、域名形(`WebFetch(domain:…)`)、协议名带通配、带空白 / 畸形的名字:
3277
+ * `400 request.field_invalid`,`error` = `skill.disallowedTools entry "<条目>" reads as nothing (<原因词>): <怎么写>`(子代那一层前缀 `agents[<i>]: skills[<j>]: `)。
3278
+ * 为什么拒:一条以为拒了、其实什么也不拒的条目,比没有更坏(≤7.116.x 受理这种条目,只发一条 operator 受众、不上会话流的通告;**那个旧码已改名**为 `permission.allowed_tool_not_granted`,user 受众、上会话流 —— 见 `engine_notice` 臂)。
3279
+ * 🔴 **续跑同判**:升级时还停驻、提交体里带这种条目的任务,续跑 ⇒ 认领之前 **409 `resume_blocked_by_policy`**(`blockedBy:"request.field_invalid"`,`error` 带同一句;行与卡一个字节不动,出路 = 取消、改好条目重提;
3280
+ * 终态 run 的 `POST /v1/runs/:id/steer` 在铸唤醒卡之前当场同答)—— 因为引擎 7.41 去首尾空白(`"Bash "` 曾是一条有效的拒)而 7.42 逐字读(读成空),不判就是升级后那条拒无声消失。
3281
+ * allow 侧不拒(`allowedTools` 里读成空的条目发通告)。位缺席 = 老 server(见 {@link allowedTools})。 */
3282
+ disallowedTools?: string[];
3211
3283
  }
3212
3284
  /** A per-request MCP server (CC `.mcp.json` parity) — core-native `McpServerSpec` shape (core types.ts:277).
3213
3285
  * `stdio` = a local command the worker spawns (single-user only); `http` = a remote streamable-HTTP server. */
@@ -3379,15 +3451,18 @@ export interface Capabilities {
3379
3451
  /** #13([1871] web asks;server ≥1.296)fleet 面能力族——对象=面在场,`false`/缺席=无 /v1/fleet/stream
3380
3452
  * (路由 501 同谓词)。`resume: "snapshot"` 是语义广告:总线是 latest-state 非事件日志,每次连接开头
3381
3453
  * 即全量 snapshot 帧 ⇒ 重连=重快照,行状态无丢帧(刻意无 last-event-id 游标——重放缓冲与 snapshot
3382
- * 重复建设);通知帧走 durable inbox 兜底重投。`steerPriority: "advisory"`=steer body.priority 收下+
3383
- * 枚举校验但 no-op(E15,候 core 队列 seam)——诚实不假 yes。开集容未来键。 */
3454
+ * 重复建设);通知帧走 durable inbox 兜底重投。`steerPriority` 答「steer body.priority 在这台 server 上生不生效」,
3455
+ * **两代值**:`steerPriority: "advisory"`(server ≤7.115.x)= 收下 + 枚举校验 + 回显但**不生效**(no-op,诚实不假 yes);
3456
+ * `steerPriority: "engine"`(server ≥7.116.0)= `priority`(`now` / `next` / `later`)交给引擎作注入档位,各档语义只有
3457
+ * 引擎那一个定义 —— `now` **当场**切断在飞的 turn(正在执行的工具收到中止、本副本上挂着的审批卡被撤),`later` 在 run 本会停下的那一 turn 之后才投,不带 = `next`。要不要给用户露出 priority 的选择,先读这一位;
3458
+ * 缺席 / 未知词(开集)⇒ 按「不生效」处理,别当 `"engine"`。开集容未来键。 */
3384
3459
  fleet?: false | {
3385
3460
  stream?: boolean;
3386
3461
  sessionScope?: boolean;
3387
3462
  observe?: boolean;
3388
3463
  resume?: "snapshot" | (string & {});
3389
3464
  bgNotifyFailClosed?: boolean;
3390
- steerPriority?: "advisory" | (string & {});
3465
+ steerPriority?: "advisory" | "engine" | (string & {});
3391
3466
  /** server ≥7.48.0(#281;K-32 扩项补声明 —— server 7.106.0 的复合位成员闭集 `COMPOSITE_CAPABILITY_MEMBERS` 登记了它,本包此前漏了):
3392
3467
  * 本二进制会在 `hook_notice` 帧上发**第二个** kind `hook_non_blocking_failure`(用户自配的 hook 自己坏了:exit ≠ 0 ∧ ≠ 2 / 超时 /
3393
3468
  * 起不来 / 坏 JSON)。缺席 = 老 worker 只发得出 `hook_decision_unavailable` 一个 kind ⇒ 渲染面按 `kind` 分派、未知 kind 别崩。 */
@@ -3441,7 +3516,8 @@ export interface Capabilities {
3441
3516
  /** S-32(server ≥7.53,`routes/capabilities.ts:731`)—— `GET /v1/config/catalog` operator lane(部署配置目录
3442
3517
  * 自描述,DESIGN-278 §5 S2)在**本部署**挂载。谓词**两项合取**,逐项对着路由拒绝臂写:①旋钮
3443
3518
  * `CONFIG_CATALOG_ENABLED` 开着(默认 on;合规部署显式关 ⇒ 路径 404,阀门族先例)∧ ②operator 名单**非空**
3444
- * (空名单下路由对任何身份恒 403)。
3519
+ * (空名单下路由对任何身份恒拒 —— server ≥7.116.0 答 **501 `capability.operator_principals_required`**,≤7.115.x 答 403)。
3520
+ * 🔴 server ≥7.116.0 旋钮关着(`CONFIG_CATALOG_ENABLED=false`)时路径答 **501 `feature.config_catalog_disabled`**(≤7.115.x:404;同路径 `POST` ⇒ 405 + `Allow: GET`)—— 「这台没有」按 `errorCode` 判。
3445
3521
  * 🔴 **部署级可用性,不是调用者授权**(codex R1 验真后订正):调用者自己的身份**不在**谓词里 —— 路由另要求
3446
3522
  * 当前 principal 是显式 operator(`routes/config-catalog.ts` `explicitOperatorOk`,否则 403 `auth.operator_only`),
3447
3523
  * 非 operator 读到 `true` 照样 403。只对**已另行确立**为 operator 的身份展示/调用目录;本位回答的是「这台机
@@ -3535,8 +3611,21 @@ export interface Capabilities {
3535
3611
  * `beginImportStaging` ∧ a file-snapshot store. 🔴 The fourth conjunct is the correction: this doc used to
3536
3612
  * list only three, and that three-item version was DISPROVEN in the field ([2024], cli 取证) — a warm-cache
3537
3613
  * wrapper store forwarded exactly those three and dropped the staging family, so caps said `true` while PUSH
3538
- * Phase A 501'd forever. Gate the whole `client.sessions.sync.*` surface off this — DON'T trial-by-501. */
3614
+ * Phase A 501'd forever. Gate the whole `client.sessions.sync.*` surface off this — DON'T trial-by-501.
3615
+ *
3616
+ * 🔴 **server ≥7.116.0:本位说的是「对话半族」**(manifest / entries / plan / import 两段)—— 文件历史的 **blob 两口**(`PUT …/sync/blobs/:hash` /
3617
+ * `GET …/sync/history/blobs/:hash`)归新位 {@link sessionSyncFileHistory}。三种生产后端(mysql / pg / local)上本位**值不变**,变的是广告的端点收窄;
3618
+ * 判据另加「策略店擦得动」(`deleteBySession`;嵌入方自带的策略店缺这只动词 ⇒ 整族 501 `capability.policy_purge_required`、本位为 `false`,
3619
+ * 7.115.x 只有 consented `overwrite-dst` 的导入在 commit 前答 501)。 */
3539
3620
  sessionSync?: boolean;
3621
+ /** server ≥7.116.0(S-509,契约附录 B.1,谓词类「设施依赖」):**会话同步的文件历史 blob 面**可用 —— `PUT /v1/sessions/:id/sync/blobs/:hash` 与
3622
+ * `GET /v1/sessions/:id/sync/history/blobs/:hash` 两口。= {@link sessionSync} ∧ 文件历史店有 blob 传输面(`syncBlobFaces`;**只有 SQL 后端有**,`DB_BACKEND=local` 上恒 `false`)。
3623
+ * 🔴 **两端都读**:同步是 src → dst 两个 peer,**任一端为 `false` ⇒ 只同步对话**:别推 `fileHistory`、别 PUT blob(把 `fileHistory` 推给没有 blob 面的对端,
3624
+ * commit 之后因缺 blob 422 `missing_blob`)。位为 `false` 时两口答 **501 `capability.snapshot_store_required`**(任何会话 id 同一句,先于属主判);
3625
+ * blob「未被会话历史图引用 / 字节不存在」仍是 404 `not_found.blob`(scope 边界,只在有 blob 面的后端上可达)。
3626
+ * ⚠️ **缺席 = 老 server(≤7.115.x)**:那里 `sessionSync: true` 的 local 部署上 PUT blob 恒 501(位说「能」而口恒拒)—— 缺席时**读不出**这一面能不能用,
3627
+ * 既有 verb 照旧试(`pushSessionBundle` / `pullSessionBundle` 对缺席位照旧尝试,见 {@link import("./sync.js").PushSessionResult.fileHistory})。 */
3628
+ sessionSyncFileHistory?: boolean;
3540
3629
  /** 🔴 K-5 session-resume gates(service src/http/routes/capabilities.ts,§0.5 session 抽象)—— shell 的 `/resume` picker 据此诚实
3541
3630
  * gate,别 trial-by-501:`sessionList` = list 可用(`Boolean(sessionStorage.listSessions ?? runStore.listSessions)`,
3542
3631
  * 喂 picker 行);`sessions` = transcript preview 可用(`Boolean(sessionAudit)`,`GET /v1/sessions/:id`→SessionAudit)。
@@ -3611,15 +3700,20 @@ export interface Capabilities {
3611
3700
  hooks?: boolean;
3612
3701
  [k: string]: unknown;
3613
3702
  };
3614
- /** 🔴 **server ≥7.115.0 起恒在**:`{ permissions: { allowGrant: true } }` —— 「请求体 `settings.permissions.allow` 按**哪一种读法**收」的**版本位**(S-654;wire additive,新顶层键)。
3615
- * `permissions.allowGrant === true` = 这台 server 把 `allow` 桶编成 **allow 规则**:命中 = 给出「有人表态」(让没人表态的 MCP / A2A 服务器工具调用不再出卡),**不是免问、不是名单**
3616
- * (名单外的工具不再被拒;引擎对内置工具的写门 / shell 检查照问,deny / ask 照赢;坏形 / 内容形名字提交即 422 —— 读法全文见 {@link import("./settings.js").SettingsPermissions.allow})。
3617
- * 🔴 **键缺席 = 老 server(≤7.114.x,按名单读 `allow`:名单外一律拒)—— 别投 allow 桶**(投了只是一份收窄,方向安全,但不是你要的「表态」)。
3703
+ /** 🔴 **server ≥7.115.0 起恒在**:`{ permissions: { allowGrant: true } }`;**≥7.117.0 起 `permissions` 多一位 `allowLayer: true`** —— 「请求体 `settings.permissions.allow` 按**哪一种读法**收」的**版本位**(wire additive;两位都是恒真、
3704
+ * 不随部署形变:单用户与 `REQUIRE_PRINCIPAL=true` 两形同值,不挂任何设施)。逐位读,三段读 `settings` → `permissions` → <位>:
3705
+ * · `allowGrant === true`(≥7.115.0)= 两代都成立的那句话:**allow 桶按 allow 规则读,不是名单**(名单外的工具不再被拒);键缺席 = 老 server(≤7.114.x,按名单读)—— **别投 allow 桶**(投了只是一份收窄,方向安全,但不是你要的)。
3706
+ * · `allowLayer === true`(**≥7.117.0**,core 7.42.0)= 这台 server 把 `allow` **整份原样**交给引擎的 **allow 层**:表里的调用**免问** —— 清「普通问 + 没人表态」两类(内置工具的写门 / shell 普通问也清,与参照实现的 `permissions.allow` 同读);
3707
+ * **内容形受理**(`Bash(git:*)`、`Read(//dir/<glob>)`);引擎读成空的条目(`*`、写路径 / 域名形、带空白的名字、`Read(~/…)`)**不拒**,开跑时收 `engine_notice` `permission.allowed_tool_not_granted`(user 受众);
3708
+ * 清不掉的:任何一层的 deny / ask 规则、运维强制类(`APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / `MANUAL_MODE_SHELL_GATE=always` / 写保护 / 敏感写 / 治理)、hook 的问、plan 的问 —— 清不掉而命中时卡上带 `allowRuleShadowed`
3709
+ * ({@link import("./resources/tool-approvals.js").ToolApprovalFrame.allowRuleShadowed});受理口只判**名字**(退役名 / 无前缀短名 / 协议名对端段铸不出 ⇒ 422)与条数(≤1000,超了 400),内容不判。
3710
+ * 🔴 **键缺席 = 7.115.0–7.116.x(allow 只表态:不放掉内置工具的写门 / shell 检查,内容形整请求 422)或更老 —— 别指望内置工具免问、别投内容形**。
3618
3711
  * ⚠️ 与 `taskSettings.permissions` 不是一件事:那一位不变、仍是布尔(只说「受理这一面」,读 `=== true` 的旧端不失明);判 allow 的读法只看本位。
3619
- * 本位是**版本位**:恒 `true`、不随部署形变;部署级「替谁表了态」(运维 env `APPROVAL_GRANT`)不在能力面,在 operator 诊断面 {@link ServerWiringGates.approvalGrant}。 */
3712
+ * 运维侧「替谁表了态」(env `APPROVAL_GRANT`)不在能力面,在 operator 诊断面 {@link ServerWiringGates.approvalGrant}。 */
3620
3713
  settings?: {
3621
3714
  permissions?: {
3622
3715
  allowGrant?: boolean;
3716
+ allowLayer?: boolean;
3623
3717
  [k: string]: unknown;
3624
3718
  };
3625
3719
  [k: string]: unknown;
@@ -3762,8 +3856,15 @@ export interface Capabilities {
3762
3856
  s3PublicEndpoint?: string | null;
3763
3857
  /** GET /v1/files/sent 台账面(`routes/capabilities.ts` 的能力对象 `Boolean(sendFileLedger)`)。 */
3764
3858
  sendUserFileLedger?: boolean;
3765
- /** GET /v1/workflows 列表面(`routes/capabilities.ts` 的能力对象 `Boolean(workflowRunStore)`;`workflows` 总位见上)。 */
3859
+ /** GET /v1/workflows 的**列表 / 详情 / 流三口**(`Boolean(workflowRunStore)`;`workflows` 总位见上)。
3860
+ * 🔴 **server ≥7.116.0:本位只说这三口,journal 口看新位 {@link workflowsJournal}**(7.115.x 的本位广告 journal 口,而 journal 店缺席时那一口恒 501 —— 位说「能」而口恒拒)。
3861
+ * 本位**值不变**(= workflow 行店在场)。 */
3766
3862
  workflowsList?: boolean;
3863
+ /** server ≥7.116.0(S-509,谓词类「设施依赖」):`GET /v1/workflows/:id/journal` 可用 = workflow 行店 ∧ journal 店。
3864
+ * 无后端部署(`DB_BACKEND=memory`、多租户裸起、SQL 坐标没配齐)+ 自编排开着的形上 `workflowsList: true`、本位 `false`;位为 `false` 时 journal 口答
3865
+ * **501 `capability.workflow_store_required`**(对任何 id 同一句,先于按行判属主;行店缺席时是 `capability.self_orchestration_required`)。
3866
+ * 🔴 **journal 入口读本位,别读 `workflowsList`**;**缺席 = 老 server(≤7.115.x)**⇒ 按 `workflowsList` 兜底(= 旧行为:位为真而 journal 口可能恒 501)。 */
3867
+ workflowsJournal?: boolean;
3767
3868
  /** device lane 探测位(server `routes/capabilities.ts:162`;design/device-executor-lane-v2 §4.8)——
3768
3869
  * **一个诚实对象或 `false`**,与 {@link fleet} / {@link workspace} 同族三态形。谓词 = `deps.deviceHub`
3769
3870
  * 在场,而那正是 `GET /v1/device/ws` 的 upgrade 处理器挂没挂的**同一个**判据(`server.ts` 的
@@ -3925,13 +4026,14 @@ export interface Capabilities {
3925
4026
  * **例外**是配置被 lock 时,提交口 400 `config.locked_key`(那条 veto 正是让「说 yes ⟺ 路真能用」
3926
4027
  * 在这一形上仍成立的东西)。 */
3927
4028
  a2aInjection?: boolean;
3928
- /** server-as-peer 半场的**旋钮实况**(server `routes/capabilities.ts:564` =
3929
- * `deps.config.a2aServe !== undefined`;DESIGN-269 车2)—— 这台 worker 是否作为一个 A2A agent 对外存在。
3930
- * `true` ⟺ `A2A_SERVE_ENABLED` 开 ⟺ `GET /.well-known/agent-card.json` 与 `POST /v1/a2a` 两条路由存在;
3931
- * `false` ⟺ 两条都 **404**(设计稿 §3.3「卡都不发 = 对外不存在」)。缺席即关。
3932
- * ⚠️ **辖域 = 路由在不在,不是「每个方法都能跑」**:`message/send` / `tasks/get` 还需要 durable run store
3933
- * (缺它时两个方法回具名 JSON-RPC `-32004`,不是静默降级)。server 刻意不把 runStore 折进本位 ——
3934
- * 那会造出「卡还在发、位却是 false」这种更糟的谎。 */
4029
+ /** server-as-peer 半场的**能否对外存在**(DESIGN-269 车2;server ≥7.116.0 谓词 = **`A2A_SERVE_ENABLED` 旋钮 ∧ 有 durable run store**,契约附录 B.1「设施 + config」;
4030
+ * ≤7.115.x 只看旋钮 = `deps.config.a2aServe !== undefined`)—— 这台 worker 是否作为一个 A2A agent 对外存在。
4031
+ * `true` ⟺ 旋钮开 ∧ 有 run 店 ⟺ `GET /.well-known/agent-card.json` 与 `POST /v1/a2a` 两条路由存在;
4032
+ * `false` ⟺ 两条都 **404**(`not_found.route`,反指纹:「卡都不发 = 对外不存在」,**唯一**登记在 404 而非 501 的「不可用」例外)。缺席即关。
4033
+ * 🔴 **7.116.0 的位值变化**:`A2A_SERVE_ENABLED=true` 而**没有 durable run store** 的部署(`DB_BACKEND=memory`、多租户裸起)上,本位由 `true` 变 `false`
4034
+ * —— 那里它广告的两条路由本来就恒拒(7.115.x:卡照发 200,`message/send` / `tasks/get` 恒答 JSON-RPC `-32004`);现在卡与 RPC 都 404,起服日志一行 warn
4035
+ * `a2a_serve_not_served`(`reason` 点名成因)。对端 orchestrator 对这种部署拉卡由 200 变 404(与旋钮关同一形)。出路:`DB_BACKEND=mysql|pg|local`,或关掉 `A2A_SERVE_ENABLED`。
4036
+ * 旧注「server 刻意不把 runStore 折进本位」**作废**(位与路由门现读同一只事实,「位说有而端点恒拒」结构上不可能)。 */
3935
4037
  a2aServe?: boolean;
3936
4038
  /** 后台 agent **名册读面** `GET /v1/agents/roster` 的位(server `routes/capabilities.ts:640` =
3937
4039
  * `Boolean(deps.backgroundAgentStore)`;#A1)。谓词**逐字**是那条路由的 501 门 ⇒「说 yes ⟺ 路由真能用」
@@ -4113,6 +4215,14 @@ export interface Capabilities {
4113
4215
  * ⚠️ **缺席 = 老 server(≤7.108.x)**:那台对请求键答 400 `request.body_shape`(`unknownKeys` 逐字列名)⇒ 别发那个键,如实告诉用户
4114
4216
  * 「这台 server 上出厂技能照装」(CC `--disable-slash-commands` 在那台上兑现不了)。位为真**只**说「认这个键」,不说这台部署有没有出厂技能。 */
4115
4217
  disableSkills?: boolean;
4218
+ /** **请求键 {@link TaskRequest.userInvokedSkills} 的事先读数**(server ≥7.116.0;恒真位,铸点字面 `userInvokedSkills: true`,不挂谓词、无租户门)—— 这台 server 认不认
4219
+ * 顶层 `userInvokedSkills`(人用名字点过的技能,开跑即生效、不出 `Skill` 卡)。位名与请求键**同一个词**。
4220
+ * ⚠️ **缺席 = 老 server(≤7.115.x)**:那台对这个键答 400 `request.body_shape`(`unknownKeys` 逐字列名)⇒ **别发那个键**。位为真**只**说「认这个键」。 */
4221
+ userInvokedSkills?: boolean;
4222
+ /** **技能两只清单 `allowedTools` / `disallowedTools` 的事先读数**(server ≥7.116.0;恒真位):技能上的两只清单**生效**(allow / deny 规则来源,读法见 {@link SkillSpec.allowedTools})。
4223
+ * ⚠️ **缺席 = 老 server(≤7.115.x)**:顶层技能上的两只清单**照收但引擎不读**(静默不生效,**没有 400 可探**)—— 别指望清单拦得住工具,圈工具用 deny 规则
4224
+ * (请求 `settings.permissions.deny`);子代技能(`agents[].skills[]`)上两只清单是未知键 ⇒ 整条技能拒。 */
4225
+ skillToolLists?: boolean;
4116
4226
  [k: string]: unknown;
4117
4227
  }
4118
4228
  /**
@@ -4333,6 +4443,9 @@ export interface LivePendingRow {
4333
4443
  sessionId?: string;
4334
4444
  requiresRealApproval?: true;
4335
4445
  governanceForced?: true;
4446
+ /** server ≥7.116.0:这张卡上「本会话放行」不会被记住(真才带、永不 `false`;缺席 = 记得住 **或** 老 server)。与 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused}
4447
+ * **同一位**(`livePending` 行顶层与其内 {@link frame} 同投)。 */
4448
+ rememberRefused?: true;
4336
4449
  /** server ≥7.101.0(T4① / 车OC;sdk 11.4.0 追平)—— 强制位(`AskRequest.mandated`),与上两位**同层同形**(真才带,
4337
4450
  * 缺席不编 false);值 = 条目上那一位(server `askBroadcast` 铸条目时取自这一次过闸的 `req.mandated`,与 {@link frame}
4338
4451
  * 上同名键同源)。此前只在 `frame` 里。 */
@@ -4447,6 +4560,9 @@ export interface PendingCheckpoint {
4447
4560
  * 以 stream 重发帧为准。additive,**只在为真时在场**,恒不写 false;缺席 ≠「非治理门」,是「无治理
4448
4561
  * 来源证据」。 */
4449
4562
  governanceForced?: true;
4563
+ /** server ≥7.116.0:这张卡上「本会话放行」不会被记住(真才带、永不 `false`;缺席 = 记得住 **或** 老 server;`/v1/approvals` 的 `pending[]` 行与 `/stream` 的 `pending` 帧同投)。
4564
+ * 与 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused} **同一位**。 */
4565
+ rememberRefused?: true;
4450
4566
  /** server ≥7.100.0(S-700)—— 这只 park 住的 ask **只有真人能清**(core park 行孪生座,`=== true` 严判才铸)。
4451
4567
  * 与 inbox 行 / 活卡帧同名位同一件事。缺席 = 「没打这个标」,**不是**「不用人也能清」。 */
4452
4568
  requiresRealApproval?: true;
@@ -4513,6 +4629,13 @@ export interface PendingCheckpoint {
4513
4629
  /** core 5.11.0([2625] Added②):铸造时在场的 shell 门 doctrine 自报——仅 shell-gated ask 铸造
4514
4630
  * 时在场(在场条件敏感,勿按在场性判别 code;[2597] 案取证缺口的结构性补)。 */
4515
4631
  shellGateDoctrine?: "classify" | "always";
4632
+ /** server ≥7.117.0(core 7.42.0)—— allow 层披露:命中这次调用、却没能清掉这只 ask 的成员,`{ member, entries, omitted? }[]`(见 {@link AllowRuleShadow};
4633
+ * 语义逐字见 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.allowRuleShadowed} —— 本键是它的**耐久对偶**,经 `GET /v1/approvals` 与 `/stream` 的 `riskDescriptor`
4634
+ * 整体透传;条目在读边界另过 server 的脱敏)。缺席 ≠ 「你没有规则」。
4635
+ * 🔴 **旧键 `shadowedRule`(字符串)已退役**(≤7.116.x 的耐久对偶,本型从未声明它):SQL 后端在 7.117.0 升级起服时把停驻行一次性改写成
4636
+ * `[{ member: "persisted", entries: [<旧值>] }]`;**file 后端升级前的停驻行与已落盘的 run 结果**(`checkpointGate.riskDescriptor`)上旧键原样留着(文本仍脱敏,只缺结构化披露)——
4637
+ * 读这两处的消费端要同时认得「旧串」,本包不为它再声明一个键。 */
4638
+ allowRuleShadowed?: AllowRuleShadow[];
4516
4639
  } | null;
4517
4640
  [k: string]: unknown;
4518
4641
  }
@@ -4951,6 +5074,39 @@ export interface SyncSnapshot {
4951
5074
  key: string;
4952
5075
  manifest: Array<[string, string]>;
4953
5076
  }
5077
+ /** core `FileHistoryExport`(`formatVersion: "file-history/1"`)的**镜像** —— server ≥7.52(S-15 / design/381)起会话同步搬运文件历史的信封,**取代**已退役的 E19 整树快照
5078
+ * {@link SyncSnapshot}:per-edited-file 的版本链(tracked)+ 边界(boundaries);**blob 字节不在信封里**(按 hash 寻址,经 history blob 两口搬运,见
5079
+ * {@link import("./resources/session-sync.js").SessionSyncResource.getHistoryBlob} / `putBlob`)。SDK 只读 `tracked[].versions[].blobHash`(决定要搬哪些 blob),其余**逐字透传**
5080
+ * (server 的 import 门按 `formatVersion` refuse-not-coerce、复核 `keyKind` / `keyFamily` 闭集 —— SDK 不替它判,也不复制那两张闭集词表:二者按 `string` 读)。
5081
+ * 键集对拍 core `dist/core/file-history-store.d.ts` 的 `FileHistoryExport`。 */
5082
+ export interface FileHistoryExport {
5083
+ /** 今天唯一值 `"file-history/1"`;server 对别的值拒(不是 SDK 的判)。 */
5084
+ formatVersion: string;
5085
+ tracked: Array<{
5086
+ /** 任务根下捕获 ⇒ 相对路径,否则逐字绝对路径。 */
5087
+ relOrAbsPath: string;
5088
+ /** 键的自描述(core 闭集;本包不复制词表)。 */
5089
+ keyKind: string;
5090
+ keyFamily: string;
5091
+ /** `false` ⇒ pristine base 没能捕获(链从 v1 之上起);随图走、不推断。 */
5092
+ baseAvailable: boolean;
5093
+ /** 完整保留链(v1 在先当且仅当 `baseAvailable`)。`blobHash: null` = 「当时不存在」标记(不用搬 blob)。 */
5094
+ versions: Array<{
5095
+ version: number;
5096
+ blobHash: string | null;
5097
+ mode?: number;
5098
+ parentIdent?: string;
5099
+ backupTime: string;
5100
+ }>;
5101
+ }>;
5102
+ boundaries: Array<{
5103
+ entryId: string;
5104
+ files: Array<{
5105
+ relOrAbsPath: string;
5106
+ version: number;
5107
+ }>;
5108
+ }>;
5109
+ }
4954
5110
  /** One E18 resume-at anchor (eventId→entryId + its source owner). `owner` is RE-KEYED to the importing principal
4955
5111
  * on a PUSH (§9) — the local peer sends what it has; the cloud overwrites it. */
4956
5112
  export interface SyncAnchor {
@@ -4970,7 +5126,14 @@ export interface SessionManifest {
4970
5126
  entryCount: number;
4971
5127
  /** The session's current leaf entry id, or null. */
4972
5128
  leafId: string | null;
5129
+ /** 🔴 **server ≥7.52(S-15)起不发这个键、wire 上不再有它**(E19 整树快照纪元退役;server `exportSessionManifest` 铸 `{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }`,
5130
+ * 7.116.0 发布字节逐键核过)。≤7.51 老 server 仍发它。**本型承诺它恒是数组**:{@link import("./resources/session-sync.js").SessionSyncResource.manifest} 在 wire 缺席时填 `[]`
5131
+ * —— 所以对 ≥7.52 的 server 它恒空,真正的文件历史在 {@link fileHistory}。
5132
+ * 🚧 这是为了不在 minor 里收窄公开型的**披露性过渡**(`snapshots` 本该是可选 / 随退役纪元删除):**下一个 major 把它改可选并删掉 `manifest()` 的填充**。 */
4973
5133
  snapshots: SyncSnapshot[];
5134
+ /** server ≥7.52:per-edited-file 文件历史信封({@link FileHistoryExport});`null` = 没有历史 / 源店导不出;**键缺席 = ≤7.51 老 server**(那一代走 {@link snapshots})。
5135
+ * 搬 blob 前先读两端的 {@link Capabilities.sessionSyncFileHistory}(server ≥7.116.0)。 */
5136
+ fileHistory?: FileHistoryExport | null;
4974
5137
  policy: SessionRulesRecord[];
4975
5138
  anchors: SyncAnchor[];
4976
5139
  }
@@ -4982,6 +5145,8 @@ export interface SessionBundle {
4982
5145
  /** The FULL durable conversation log, verbatim ids/parents/payload (oldest-first). */
4983
5146
  entries: SyncEntry[];
4984
5147
  snapshots: SyncSnapshot[];
5148
+ /** 同 {@link SessionManifest.fileHistory}(server ≥7.52 的文件历史信封;键缺席 = 源是 ≤7.51 老 server)。 */
5149
+ fileHistory?: FileHistoryExport | null;
4985
5150
  policy: SessionRulesRecord[];
4986
5151
  anchors: SyncAnchor[];
4987
5152
  }
@@ -6168,6 +6333,9 @@ export interface ApprovalDecisionResult {
6168
6333
  errorCode?: string;
6169
6334
  errorMessage?: string;
6170
6335
  retriable?: boolean;
6336
+ /** 带 `remember` 的 `/decide` 才有的回执位。🔴 **server ≥7.116.0:在带授予的卡上(引擎 `Skill` 卡等,卡面位 `rememberRefused`)恒 `false`** —— 既有键,不是新键:
6337
+ * 决定照收、只放行这一次、豁免店零写;同一条件也使 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused} 在场。
6338
+ * 普通卡上仍是「按请求记」(`true` ⇒ 之后同工具零卡)。 */
6171
6339
  rememberApplied?: boolean;
6172
6340
  /** #368 幂等回放形的判别式(同一份 decide 体重发、命中已决行);回放形**不带** `taskId`/`status:"resuming"`。 */
6173
6341
  idempotent?: true;
@@ -6219,6 +6387,7 @@ export interface ServerWiringGates {
6219
6387
  * **非空 ∨ `REQUIRE_PRINCIPAL`**:满足任一,调用方就必须是名单里的 principal,否则 403
6220
6388
  * `auth.operator_only`。**「没开 REQUIRE_PRINCIPAL」不等于开放** —— 列了名单的部署上匿名/非名单一样 403;
6221
6389
  * 唯一开放的姿势是空名单 ∧ 非多租户(单租户 turnkey,唯一的用户就是 operator)。
6390
+ * 🔴 server ≥7.116.0:**多租户形 + 空名单 ⇒ 501 `capability.operator_principals_required`**(对任何身份,先于授权;≤7.115.x 是 403)—— 按 `errorCode` 分支。
6222
6391
  *
6223
6392
  * 🔴 **不含 per-leg 历史**:治理段只出现在 live 帧的 operator 投影里,durable 账本恒存剥后形(账本写的
6224
6393
  * 那一刻不知道未来读者是谁)。要某条历史腿的治理面,只能在它跑的时候以 operator 身份订阅。