@sema-agent/client-core 0.66.0 → 0.67.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.
@@ -20,15 +20,27 @@
20
20
  * 仍然在公面上承诺着一件上游已经不发的事。本批因此不是「零改」,是**按退役条款把承诺一起收掉**。
21
21
  *
22
22
  * -- 一处窄读,复用不重铸 --------------------------------------------------------------------
23
- * **本轮轴**:一只 ask 上的 `classifierUnavailable.cause` —— 复用 0.63.0 已有的
24
- * {@link classifierUnavailableOf},**不重铸**。本模块因此有一条值级 import(它不进内核闭包,见
23
+ * **本轮轴**:一条门记录上的 `disposition.cause` —— 复用同批新铸的
24
+ * {@link classifierDenyCauseOf},**不重铸**。本模块因此有一条值级 import(它不进内核闭包,见
25
25
  * `run-client-core-portability-test.mjs` 的内核上限记账)。
26
26
  *
27
+ * -- 🔴 0.67.0:本轮轴的**事实源改道**(判据句一个字没改)------------------------------------
28
+ * core 7.14.0 把 `classifierUnavailable` 从 ask / park / carry / summary 六个载体上整族退役
29
+ * (其中 ask 那几处**自 #661 起引擎就没写过**),继任者是**拒绝面**的一个结构位
30
+ * `GateDisposition.denied.cause`(`gate-outcome.d.ts:168`)。⇒ 本模块的 `unavailable_this_round`
31
+ * 从「这只 ask 上盖了没跑成的章」改读「**本轮观测到的门记录**上那一格 deny 成因」。
32
+ * 🔴 **公面词表与三句判据零改**(§30f/§30k 的判据句逐字不动):换的是事实**从哪里来**,
33
+ * 不是这一端说什么。
34
+ * 🔴 **turn 边界怎么重置**:本读器是**纯函数**,`observed` 参数就是「本轮那一次观测」——
35
+ * 调用方每一 turn 传本 turn 的观测座(一只 ask / 一条耐久行 / 一只带 `gate` 的 `tool_end` 帧),
36
+ * 上一 turn 的事实**结构上**到不了这一次调用。包内**刻意不持有**跨 turn 的闩:一个会话级闩在
37
+ * 重连 / durable 重放上会把一条陈旧的成因渲成「现在」,而缺席不铸才是这一端唯一说得出口的话。
38
+ *
27
39
  * -- 🔴 优先序承重:本轮事实(否定 + 肯定)> 这条腿的 `armed` --------------------------------
28
40
  * 判据锚在**真正决定「分类器现在跑不跑」的量**上:
29
- * · **本轮事实最先** —— 它说的是眼前这一只 ask,最具体也最新。两条:否定事实
30
- * (`classifierUnavailable` ⇒ `unavailable_this_round`)与**肯定**事实(0.65.0 / B-071:
31
- * `origin === "denial_limit_fallback"` ⇒ 分类器真的跑过 ⇒ `available`);
41
+ * · **本轮事实最先** —— 它说的是眼前这一次观测,最具体也最新。两条:否定事实
42
+ * (门记录的 `disposition.cause === "unavailable"` ⇒ `unavailable_this_round`)与**肯定**事实
43
+ * (0.65.0 / B-071:`origin === "denial_limit_fallback"` ⇒ 分类器真的跑过 ⇒ `available`);
32
44
  * · **其次是 `armed`** —— core 顶注逐字:「A decider is minted per run (its latch is a RUN fact)」
33
45
  * ⇒ 同一会话的**后一条腿**完全可以重新武装,`armed === true` 时这条腿上真的有一只新铸的 decider。
34
46
  * 🔴 **0.65.0 / B-071 收窄**:`armed === true` 现在判的是新词 **`armed`**,不再是
@@ -42,7 +54,7 @@
42
54
  * `armed` 这一位若哪天也换形,本模块的**缺席臂**仍是正解:读不出就答 `undefined`(**说不出来**),
43
55
  * 绝不折成 `available` —— 那是把「没报」渲成「一切正常」。
44
56
  */
45
- import { classifierUnavailableOf } from './autoModeUnavailable.js';
57
+ import { classifierDenyCauseOf } from './autoModeUnavailable.js';
46
58
  /**
47
59
  * 分类器的三态(0.65.0:熔断族退役,`breaker_open` 随之删除;同批 `armed` 与 `available` 拆成
48
60
  * 两个词)。**「没武装」仍然不在里面** —— 那一问由 `wiring_manifest.autoMode.reason` 那一格
@@ -77,7 +89,7 @@ export const CLASSIFIER_STATUS_STATES = Object.freeze([
77
89
  * 这只 ask 的存在本身就证明分类器在这条调用链上跑过并数过它自己的拒绝。
78
90
  *
79
91
  * 🔴 **别的 origin 一个都不算**,而且不是保守起见:
80
- * · `org_*` / `hook` / `ask_rule` / `unresolvable` / `content_question` —— core 的
92
+ * · `org_*` / `hook` / `ask_rule` / `ancestor_marked` / `content_question` —— core 的
81
93
  * `CLASSIFIER_MAY_ANSWER` 表逐行 `false`,分类器**结构上**就不许碰这些 ask ⇒ 它们的存在
82
94
  * 与分类器跑没跑完全无关;
83
95
  * · `policy` / `safety_tighten` / `shell_gate_tighten` —— 分类器**可以**答(表里 `true`),
@@ -87,8 +99,8 @@ export const CLASSIFIER_STATUS_STATES = Object.freeze([
87
99
  */
88
100
  const CLASSIFIER_RAN_ORIGINS = new Set(['denial_limit_fallback']);
89
101
  /**
90
- * 一只 ask / 一条 `tool_end.gate` 记录上的 `origin` —— 两条载体同一个词表(sdk 的
91
- * `AskOrigin` 一张表两个面:`ToolApprovalFrame.origin` 与 `GateOutcome.origin`)。
102
+ * 一只 ask / 一条 `tool_end.gate` 记录上的 `origin` —— 两条载体同一个词表(core 的
103
+ * `ASK_ORIGINS` 一张表两个面:`ToolApprovalFrame.origin` 与 `GateOutcome.origin`)。
92
104
  * 顶层优先(活卡帧 / durable park 行),其次是门记录里的那一格。读不出即缺席。
93
105
  */
94
106
  function askOriginOf(ask) {
@@ -103,15 +115,33 @@ function askOriginOf(ask) {
103
115
  const inner = gate.origin;
104
116
  return typeof inner === 'string' && inner.length > 0 ? inner : undefined;
105
117
  }
118
+ /**
119
+ * 🔴 **有裁决**的那个 deny 成因词 —— 它**不是**「这一轮没跑成」(0.67.0 起是本模块唯一的排除集)。
120
+ *
121
+ * core `gate-outcome.d.ts:162-165` 逐字:`parse_error` = 「The classifier answered outside its verdict
122
+ * contract: blocked for safety, **counted by the denial limit like a ruling**」—— 分类器**跑了并且
123
+ * 答了**。而 `unavailable_this_round` 这一态答的是「这一轮**没跑成**」。两句话互斥,所以这个词
124
+ * 到达本读器时的正解是**落到下一条臂**(回落 `armed` = 「武装了,本轮如何这一端说不出来」),
125
+ * 绝不折成一个「没跑成」的成因。
126
+ *
127
+ * ⚠️ **行为与 0.66.0 逐字节相同**(判据句零改):修前这条排除住在 `autoModeUnavailable.ts` 的
128
+ * `NEVER_STAMPED_CAUSES` 里,理由是「core 明说它不 stamp 到 `classifierUnavailable` 那一格」;
129
+ * 退役后**那一格没了**,而 `parse_error` 在**拒绝面**是一个合法在场的成因词 ⇒ 排除的归属地
130
+ * 从「铸点不该有它」变成「**状态面**这一问不该收它」,于是这张表搬到本模块。
131
+ * core 哪天再给拒绝面加一个「答了但不算数」的臂,加员与它的处置同批落在这里,门会先红。
132
+ */
133
+ const NOT_A_ROUND_FAILURE = new Set(['parse_error']);
106
134
  /**
107
135
  * 「这个会话上,auto 分类器现在是什么状态」——三态,或 `undefined`(**说不出来**)。
108
136
  *
109
137
  * @param autoMode `wiring_manifest` 的 `autoMode` 段(投影后的或原始的都吃;本函数自己窄读)
110
- * @param ask 可选:**本轮**那只 ask(或 durable park 行的 `tool_approval` 载荷)
138
+ * @param ask 可选:**本轮那一次观测** —— 一只 ask / 一条 durable park 行的 `tool_approval`
139
+ * 载荷 / 一只带 `gate` 的 `tool_end` 帧 / 一条门记录本体。三形键路同形,同一把读器吃(0.67.0:
140
+ * 否定事实的载体从 ask 上的 `classifierUnavailable` 改成门记录上的 `disposition.cause`)。
111
141
  *
112
- * 优先序(承重,理由见模块顶注):**本轮事实(否定 + 肯定)> 这条腿的 `armed`**——先看 `ask` 上的
113
- * 本轮不可用事实,再看 `ask` 上那条「分类器真的跑过」的肯定事实,最后才看这条腿武没武装。
114
- * `ask` 带本轮事实时,`autoMode` 段缺席也照样答得出(两条本轮臂都不依赖那一段)。
142
+ * 优先序(承重,理由见模块顶注):**本轮事实(否定 + 肯定)> 这条腿的 `armed`**——先看观测座上的
143
+ * 本轮不可用事实,再看那条「分类器真的跑过」的肯定事实,最后才看这条腿武没武装。
144
+ * 观测座带本轮事实时,`autoMode` 段缺席也照样答得出(两条本轮臂都不依赖那一段)。
115
145
  *
116
146
  * 🔴 **`undefined` 是一个诚实的答案,不是一个坏路径**:
117
147
  * · `autoMode` 段缺席(老 mint / 外部 derive)⇒ 这一端**没有**分类器的健康读数;
@@ -120,9 +150,13 @@ function askOriginOf(ask) {
120
150
  * ⚠️ 「没武装」本身仍是一条要渲的事实 —— 但它的出处是 `autoMode.reason`,不是本读器。
121
151
  */
122
152
  export function classifierStatusOf(autoMode, ask) {
123
- const round = ask === undefined ? undefined : classifierUnavailableOf(ask);
124
- if (round !== undefined)
125
- return { state: 'unavailable_this_round', cause: round.cause };
153
+ // 🔴 0.67.0 事实源改道:否定事实 = **本轮观测到的门记录**上那一格分类器 deny 成因。
154
+ // `parse_error` 按 {@link NOT_A_ROUND_FAILURE} **落到下一条臂**(它是「答了」不是「没跑成」)——
155
+ // 与 0.66.0 的行为逐字节相同,只是排除的归属地换了(见那张表的头注)。
156
+ const round = ask === undefined ? undefined : classifierDenyCauseOf(ask);
157
+ if (round !== undefined && !NOT_A_ROUND_FAILURE.has(round)) {
158
+ return { state: 'unavailable_this_round', cause: round };
159
+ }
126
160
  // 🔴 B-071:**本轮的肯定事实**(分类器真的跑过)—— 与上面那条否定事实同属 per-call 轴,故同样
127
161
  // 压过 `armed`。它**不依赖** `autoMode` 段在不在场:可用性是这次调用的事实,不是装配的事实。
128
162
  const origin = ask === undefined ? undefined : askOriginOf(ask);
@@ -139,10 +173,18 @@ export function classifierStatusOf(autoMode, ask) {
139
173
  return { state: 'armed' };
140
174
  return undefined;
141
175
  }
142
- /** 逐本轮成因一句人话(状态面用;与卡面那几句刻意不同 —— 见模块顶注)。 */
176
+ /**
177
+ * 逐本轮成因一句人话(状态面用;与拒绝面那两句刻意不同 —— 见模块顶注)。
178
+ *
179
+ * 🔴 0.67.0:表内今天**只有 `unavailable` 一词** —— 它就是 {@link classifierDenyCauseOf} 在本读器上
180
+ * 能交出来的全部成因(`parse_error` 被 {@link NOT_A_ROUND_FAILURE} 排除在这一态之外)。
181
+ * 修前那两个词(`error`/`timeout`)是**退役掉的** `classifierUnavailable.cause` 的值域;它们今天
182
+ * 仍是 `AUTO_MODE_UNAVAILABLE_CAUSES` 的成员,但那张表在本包没有到达任何投影臂的路(见
183
+ * `autoModeUnavailable.ts` 顶注)⇒ 在这里给它们留一句话 = 一条永远走不到的渲染分支(假 affordance)。
184
+ * 一条从旧持久态恢复回来的视图若仍带着那两个词,{@link phraseOf} 的兜底会原样带上那个词。
185
+ */
143
186
  const ROUND_CAUSE_PHRASES = Object.freeze({
144
- error: 'the classifier leg errored',
145
- timeout: 'the classifier timed out',
187
+ unavailable: 'the classifier could not run this round',
146
188
  });
147
189
  /**
148
190
  * 一个成因词 → 一个短语。**按自有属性查表**(`Object.freeze` 不移除原型,裸下标会让一个来自 wire 的
@@ -161,7 +203,7 @@ function phraseOf(table, cause) {
161
203
  /**
162
204
  * 一次状态读数 → 一句人话。**唯一措辞铸点**(三端共用;端零自拼)。
163
205
  *
164
- * 三句逐字互异,且与 `classifierUnavailableDetail` 的三句**零重合**(两张面答两个问题)。
206
+ * 三句逐字互异,且与 `classifierDenyCauseDetail` 的两句**零重合**(两张面答两个问题)。
165
207
  * 🔴 **表外态不抛**:型面挡不住 wire,也挡不住一份从持久态恢复回来的视图 —— 一个
166
208
  * `{state:'breaker_open'}`(0.65.0 退役掉的那个词,可能来自旧持久态)必须渲出一句诚实的话,
167
209
  * 而不是把整屏带崩,也不冒充三句里的任何一句。
@@ -18,10 +18,27 @@
18
18
  * core 一动这里就先红。上游自己也是这么设计的:它导出码册的理由逐字写着「a downstream table with a
19
19
  * row missing … is a mechanically detectable disagreement rather than an argument」。
20
20
  *
21
- * -- 提货记账(码册加员)-----------------------------------------------------------------------
21
+ * -- 提货记账(码册加员 / audience 换档)-------------------------------------------------------
22
22
  * · **core 7.10.0 +2**:`delegation.ask_unresolvable`(audience **user** —— 委派链上那只 ask 判不出
23
23
  * 归属、没有人可问,这件事的收件人是发起这次委派的**用户**)/ `config.read_face_swapped`
24
24
  * (audience **operator** —— READ 容纳面被换过档,是部署事实)。四十八码 ⇒ **五十码**。
25
+ * · **core ≤7.16.0 +1**(0.67.0 提货批,由本门的 A1 段当天红抓出 —— 不是人眼发现的):
26
+ * `task.interrupt_unconsumed`(audience **user**;位置在 `task.late_approval` 与
27
+ * `memory.capture_opted_out` 之间,`governance-codes.js:146` / `NOTICE_AUDIENCE_TABLE:165` 真字节)。
28
+ * ⚠️ 它**不在** core 7.14.0 / 7.15.0 / 7.16.0 任何一份 `docs/wire-consumption` 逐键表里 ——
29
+ * 如实登记为**合同外加员**,处置随本门的双向对账走。五十码 ⇒ **五十一码**。
30
+ * · **core 7.14.0 audience 换档(value-domain BREAKING)**:`memory.consolidation_withheld`
31
+ * **user → operator**(`NOTICE_AUDIENCE_TABLE:169` 真字节)。合同逐字的理由:这条通告**没有
32
+ * `sessionId`**(一次固化跑在任何会话之外)⇒ 一个按会话路由 `user` 行的消费方**必须停止**在那里
33
+ * 等它;面向读者的那一半骑在回执上(`withheldFromCleanArm` / `withheldNeverSent`)。
34
+ * 🔴 三端落点:凡按 audience 分发的面(TUI 通告行 / web 通知中心 / 桌面 toast),这条码从此**只**
35
+ * 进运维面 —— 端不改代码也会跟着走(分发读的就是本表),但**通告文案面**若为它写过「告诉用户」
36
+ * 的专属行,那一行要跟着挪。
37
+ * · **7.16.0 的两个 memory 布局码不进本册**:`memory.layout_migrated` /
38
+ * `memory.layout_unowned_root_content` 在 core 里属 `NON_GOVERNANCE_MEMORY_CODES`
39
+ * (`governance-codes.js:11-27` 真字节),**不在** `ENGINE_NOTICE_CODES` / `NOTICE_AUDIENCE` 上。
40
+ * 本包对非治理码的既有路由**不变**:码册外 ⇒ 呈现面 fail-closed(只落 debug)。把它们抄进本册
41
+ * 会让 A1/A2 双向对账当天红 —— 那正是这张表是**抄件**而不是意见的意思。
25
42
  *
26
43
  * -- 🔴 单铸律:本模块**不抄**任何一句 core 的措辞 -------------------------------------------
27
44
  * `mcp.injection_dropped` 上游立了 `settlement.single_mint` 契约:**宿主只供事实**(哪个会话 /
@@ -33,7 +50,7 @@
33
50
  /** 一条通告是**说给谁听**的。两值,刻意不设第三值(见模块顶注)。 */
34
51
  export type NoticeAudience = 'user' | 'operator';
35
52
  /**
36
- * 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.10.0 = 五十码**;顺序同源)。
53
+ * 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**≤7.16.0 = 五十一码**;顺序同源)。
37
54
  * 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
38
55
  * ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
39
56
  * 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
@@ -18,10 +18,27 @@
18
18
  * core 一动这里就先红。上游自己也是这么设计的:它导出码册的理由逐字写着「a downstream table with a
19
19
  * row missing … is a mechanically detectable disagreement rather than an argument」。
20
20
  *
21
- * -- 提货记账(码册加员)-----------------------------------------------------------------------
21
+ * -- 提货记账(码册加员 / audience 换档)-------------------------------------------------------
22
22
  * · **core 7.10.0 +2**:`delegation.ask_unresolvable`(audience **user** —— 委派链上那只 ask 判不出
23
23
  * 归属、没有人可问,这件事的收件人是发起这次委派的**用户**)/ `config.read_face_swapped`
24
24
  * (audience **operator** —— READ 容纳面被换过档,是部署事实)。四十八码 ⇒ **五十码**。
25
+ * · **core ≤7.16.0 +1**(0.67.0 提货批,由本门的 A1 段当天红抓出 —— 不是人眼发现的):
26
+ * `task.interrupt_unconsumed`(audience **user**;位置在 `task.late_approval` 与
27
+ * `memory.capture_opted_out` 之间,`governance-codes.js:146` / `NOTICE_AUDIENCE_TABLE:165` 真字节)。
28
+ * ⚠️ 它**不在** core 7.14.0 / 7.15.0 / 7.16.0 任何一份 `docs/wire-consumption` 逐键表里 ——
29
+ * 如实登记为**合同外加员**,处置随本门的双向对账走。五十码 ⇒ **五十一码**。
30
+ * · **core 7.14.0 audience 换档(value-domain BREAKING)**:`memory.consolidation_withheld`
31
+ * **user → operator**(`NOTICE_AUDIENCE_TABLE:169` 真字节)。合同逐字的理由:这条通告**没有
32
+ * `sessionId`**(一次固化跑在任何会话之外)⇒ 一个按会话路由 `user` 行的消费方**必须停止**在那里
33
+ * 等它;面向读者的那一半骑在回执上(`withheldFromCleanArm` / `withheldNeverSent`)。
34
+ * 🔴 三端落点:凡按 audience 分发的面(TUI 通告行 / web 通知中心 / 桌面 toast),这条码从此**只**
35
+ * 进运维面 —— 端不改代码也会跟着走(分发读的就是本表),但**通告文案面**若为它写过「告诉用户」
36
+ * 的专属行,那一行要跟着挪。
37
+ * · **7.16.0 的两个 memory 布局码不进本册**:`memory.layout_migrated` /
38
+ * `memory.layout_unowned_root_content` 在 core 里属 `NON_GOVERNANCE_MEMORY_CODES`
39
+ * (`governance-codes.js:11-27` 真字节),**不在** `ENGINE_NOTICE_CODES` / `NOTICE_AUDIENCE` 上。
40
+ * 本包对非治理码的既有路由**不变**:码册外 ⇒ 呈现面 fail-closed(只落 debug)。把它们抄进本册
41
+ * 会让 A1/A2 双向对账当天红 —— 那正是这张表是**抄件**而不是意见的意思。
25
42
  *
26
43
  * -- 🔴 单铸律:本模块**不抄**任何一句 core 的措辞 -------------------------------------------
27
44
  * `mcp.injection_dropped` 上游立了 `settlement.single_mint` 契约:**宿主只供事实**(哪个会话 /
@@ -31,7 +48,7 @@
31
48
  * 出现在本包源码或产物里 => 当场红。
32
49
  */
33
50
  /**
34
- * 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.10.0 = 五十码**;顺序同源)。
51
+ * 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**≤7.16.0 = 五十一码**;顺序同源)。
35
52
  * 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
36
53
  * ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
37
54
  * 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
@@ -87,6 +104,8 @@ export const ENGINE_NOTICE_CODES = Object.freeze([
87
104
  'task.turn_interrupted',
88
105
  'task.halt_unconsumed',
89
106
  'task.late_approval',
107
+ // 0.67.0 提货批:core ≤7.16.0 加员(合同外,见模块顶注提货记账段)。
108
+ 'task.interrupt_unconsumed',
90
109
  'memory.capture_opted_out',
91
110
  'memory.capture_optout_unpersisted',
92
111
  'tool_result.offload_put_failed',
@@ -143,7 +162,9 @@ export const ENGINE_NOTICE_AUDIENCE = Object.freeze({
143
162
  'memory.consolidation_conflict': 'operator',
144
163
  'memory.consolidation_incomplete': 'operator',
145
164
  'memory.consolidation_refused': 'operator',
146
- 'memory.consolidation_withheld': 'user',
165
+ // 🔴 core 7.14.0 **value-domain BREAKING**:user → operator(见模块顶注提货记账段;
166
+ // 理由 = 这条通告没有 sessionId,一次固化跑在任何会话之外)。
167
+ 'memory.consolidation_withheld': 'operator',
147
168
  'route.fallback_to_primary': 'operator',
148
169
  'route.base_url_changed_key_unchanged': 'operator',
149
170
  'task.user_steer_undrained': 'user',
@@ -152,6 +173,7 @@ export const ENGINE_NOTICE_AUDIENCE = Object.freeze({
152
173
  'task.turn_interrupted': 'user',
153
174
  'task.halt_unconsumed': 'user',
154
175
  'task.late_approval': 'user',
176
+ 'task.interrupt_unconsumed': 'user',
155
177
  'memory.capture_opted_out': 'user',
156
178
  'memory.capture_optout_unpersisted': 'user',
157
179
  'tool_result.offload_put_failed': 'operator',
@@ -54,6 +54,20 @@ export type GateDispositionView = {
54
54
  } | {
55
55
  kind: 'denied';
56
56
  deniedBy: DeniedBy | (string & {});
57
+ /**
58
+ * 0.67.0(core 7.14.0 #688)—— 这次 deny 是**分类器那一轮没能裁决**的哪一形
59
+ * (`unavailable` = 跑不了 / `parse_error` = 跑了但答在契约之外;core `CLASSIFIER_DENY_CAUSES`)。
60
+ *
61
+ * 🔴 **本层按开集透传**(非空串即收),与同文件 `deniedBy` / `settlement.kind` / `origin` 三处
62
+ * 逐字同规:窄读域只许等于或宽于铸点域(B-025 定谳)。**判成员**那一步在公面读器
63
+ * `classifierDenyCauseOf` 上(闭集,理由见该函数)—— 两层分工与退役前的
64
+ * `classifierUnavailable`「过境 / 显示」两层逐字同形。
65
+ * 🔴 **缺席不是断言**:缺席同时覆盖「分类器自己裁决 block 了」「这不是分类器轮」「本部署没接
66
+ * 分类器」三形(core `gate-outcome.d.ts:162-166` 逐字),端**禁**读成「分类器好着呢」。
67
+ * 🔴 它站在 `deniedBy ∈ {classifier, policy}` 旁(core `DENIED_BY_MAY_CARRY_CAUSE`);那条配对
68
+ * 是**引擎的段内不变量**,本层不校(同 I1–I4 的处置,见 {@link gateOutcomeOf} 顶注)。
69
+ */
70
+ cause?: string;
57
71
  };
58
72
  /** 结算方的身份座(形由 {@link SettlementView.kind} 决定,本读器不重铸那张配对表)。 */
59
73
  export interface SettlementWhoView {
@@ -77,7 +77,9 @@ export function gateOutcomeOf(frame) {
77
77
  // 「拒了但说不出谁拒的」在上游**写不出来**(两臂在类型上就分了家)⇒ 到得了这里的这一形是坏记录。
78
78
  if (deniedBy === undefined)
79
79
  return undefined;
80
- disposition = { kind: 'denied', deniedBy };
80
+ // 0.67.0:分类器 deny 的成因位(开集透传、缺席不铸键;判成员在 `classifierDenyCauseOf`)。
81
+ const cause = str(dr.cause);
82
+ disposition = { kind: 'denied', deniedBy, ...(cause !== undefined ? { cause } : {}) };
81
83
  }
82
84
  else {
83
85
  // 处置词本身不认识 ⇒ 整只不成形:`allowed` / `denied` 是这条记录的**判别位**,猜不得。
@@ -73,3 +73,40 @@ export declare const ASK_ORIGIN_WORDS: readonly string[];
73
73
  * **不截断不改写**它 —— 显示封顶归端(它才知道自己的行宽)。
74
74
  */
75
75
  export declare function askOriginDetail(origin: unknown, message?: unknown): string;
76
+ /**
77
+ * 🔴 **`AskOrigin` 那条型面钉 0.67.0 退役,理由要写清**(如实登记,不是偷偷删):
78
+ * 它此前写作 `const _askOriginWordsPin: readonly AskOrigin[] = ASK_ORIGIN_WORDS`,而
79
+ * `AskOrigin = SdkAskOrigin` 的型面带 `(string & {})` 逃生口 ⇒ **任何字符串都满足它**,这条钉
80
+ * 在 core 7.14.0 把 `unresolvable` 换成 `ancestor_marked` 的当天**一声不响**(亲验:换词后
81
+ * `npx tsc --noEmit` 0 红)。一条恒真的钉不是钉,是[gates-fail-in-their-own-ways] 的「无契约表」那一档。
82
+ * ⇒ 判据整只移交给 `run-gate-vocabulary-test.mjs` 的 **B 段**:本表对 **core `ask-origin.js` 的
83
+ * `ASK_ORIGINS` 真字节**双向等值(词表属主是 core,sdk 只是它的镜像且**今天滞后一代**)。
84
+ * 那条对账拿的是运行期真字节,逃生口影响不到它。
85
+ */
86
+ /**
87
+ * **规则店读不出来是哪一头**(core `RULE_STORE_UNREADABLE_KINDS`;逐词逐序镜像,7.14.0 起两词)。
88
+ * · `store` —— 接上的那个店**读不出来**(读失败 / 超时 / 适配器抛了);
89
+ * · `call` —— 店读到了,但**这一次调用**读不出来(收紧 lexer 的 `unreadable`:展开里有读不懂的词 /
90
+ * 引号未闭合 / 语法错 —— 引擎自己那句话在 ask 的 `message` 上)。
91
+ *
92
+ * 🔴 **真闭集**(与 `AskOrigin` 的开集刻意不同):core 在**唯一 stamp 点**把政策自报的值剥掉之后
93
+ * 才盖章(7.14.0 合同逐字「A policy's self-declared value is removed at the stamp」)⇒ 表外值
94
+ * 结构上到不了消费端。
95
+ * 🔴 形制:`Object.freeze` 的数组,理由同上面两张表。
96
+ */
97
+ export declare const RULE_STORE_UNREADABLE_KINDS: readonly string[];
98
+ /** 这个值是不是 {@link RULE_STORE_UNREADABLE_KINDS} 的成员(core `isRuleStoreUnreadable` 的镜像)。
99
+ * 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。 */
100
+ export declare function isRuleStoreUnreadableKind(v: unknown): boolean;
101
+ /**
102
+ * 一个 `ruleStoreUnreadable` 词 → 一句人话。**唯一铸点**(三端共用;端零自拼)。
103
+ *
104
+ * 🔴 **与 {@link askOriginDetail} 并列不互替**:那一句答「谁问的」(出身),本句答「读不出来的是
105
+ * **哪一头**」。`rule_store_unavailable` 那只 ask 上两句都该在,渲一句丢一句就等于把人指去
106
+ * 错的地方 —— 而这正是 core 把这一位单独铸出来的理由。
107
+ * 🔴 **查表用 `Object.hasOwn`**(冻结不移除原型;理由与本文件另两个铸点逐字相同)。
108
+ * 🔴 表外词 / 坏值 ⇒ 一句**兜底**:原样带上那个词,并明说这次仍然是在问人。
109
+ * ⚠️ 与 {@link isRuleStoreUnreadableKind} 的闭集判据不矛盾:那一层答「这条事实在不在」(闭集,
110
+ * 出集 = 坏形),本层答「拿到一个词怎么渲」—— 一条从旧持久态恢复回来的视图必须渲出一句诚实的话。
111
+ */
112
+ export declare function ruleStoreUnreadableDetail(kind: unknown): string;
@@ -72,7 +72,12 @@ export function gateDeniedByDetail(deniedBy) {
72
72
  */
73
73
  export const ASK_ORIGIN_WORDS = Object.freeze([
74
74
  'content_question',
75
- 'unresolvable',
75
+ // 🔴 0.67.0 / core 7.14.0 **BREAKING 换词,无 alias**:`unresolvable` → `ancestor_marked`
76
+ // (`dist/core/ask-origin.js:1` `ASK_ORIGINS` 真字节;`ask-origin.d.ts:36-38` 是它的定义句)。
77
+ // 换的是**词**不是位:同一条 ladder 臂、同一张资格表。旧词按 clean-cut **不留别名** ——
78
+ // 一条 pre-7.14 的耐久行带 `"unresolvable"` 时它是**非成员**,投影**省略**那一格(见
79
+ // {@link askOriginDetail} 的表外词兜底句;`ASK_ORIGIN_SENTENCES` 里不再有它的一句)。
80
+ 'ancestor_marked',
76
81
  'org_unavailable',
77
82
  'org_rule',
78
83
  'rule_store_unavailable',
@@ -93,7 +98,7 @@ export const ASK_ORIGIN_WORDS = Object.freeze([
93
98
  *
94
99
  * ── 🔴 0.65.0 三句订正(B-080③;core `dist/core/ask-origin.d.ts` 真字节)───────────────────────
95
100
  * 三句修前各自漂开了上游的定义,而漂的方向都是「把引擎真正说的事换成一件别的事」:
96
- * · **`unresolvable`** 修前渲「门拿不定主意」—— core:36-38 逐字是「the call is MARKED by an
101
+ * · **`ancestor_marked`**(0.67.0 前名 `unresolvable`)修前渲「门拿不定主意」—— core:36-38 逐字是「the call is MARKED by an
97
102
  * ancestor (an inherited approver-unavailable float, or a durable mandate floated down because
98
103
  * this task can park it): it must reach the park with no synchronous decision-maker in between」。
99
104
  * 那不是犹豫,是**祖先盖的标记**+一条硬路径约束;渲成「拿不定主意」会让人去找一个不存在的
@@ -109,7 +114,7 @@ export const ASK_ORIGIN_WORDS = Object.freeze([
109
114
  */
110
115
  const ASK_ORIGIN_SENTENCES = Object.freeze({
111
116
  content_question: 'the tool itself asked you a question',
112
- unresolvable: 'an ancestor marked this call (an inherited approver-unavailable float, or a durable mandate): it must reach the park with no synchronous decision-maker in between',
117
+ ancestor_marked: 'an ancestor marked this call (an inherited approver-unavailable float, or a durable mandate): it must reach the park with no synchronous decision-maker in between',
113
118
  org_unavailable: 'the organization policy was unavailable, so this call asks',
114
119
  org_rule: 'an organization rule asks about this call',
115
120
  rule_store_unavailable: 'this call could not be checked against your standing deny/ask rules, so it asks',
@@ -166,11 +171,67 @@ export function askOriginDetail(origin, message) {
166
171
  return `this call asks; its origin ${word} is a word newer than this client, so answer it as usual`;
167
172
  }
168
173
  /**
169
- * **编译期对账钉**(不出公面):本包两张表的成员必须真属于 sdk 的两个联合。
170
- * 🔴 `DeniedBy` 那一张钉得**双向**(它在 wire 上是真闭集,型面也闭);`AskOrigin` 那一张只钉
171
- * 单向(它有逃生口,任何字符串都合法 —— 钉反向等于把开集当闭集用)。
174
+ * **编译期对账钉**(不出公面):`DeniedBy` 那张表的成员必须真属于 sdk 的联合,**双向**
175
+ * (它在 wire 上是真闭集,型面也闭)。
172
176
  */
173
177
  const _deniedByWordsPin = GATE_DENIED_BY_WORDS;
174
178
  void _deniedByWordsPin;
175
- const _askOriginWordsPin = ASK_ORIGIN_WORDS;
176
- void _askOriginWordsPin;
179
+ /**
180
+ * 🔴 **`AskOrigin` 那条型面钉 0.67.0 退役,理由要写清**(如实登记,不是偷偷删):
181
+ * 它此前写作 `const _askOriginWordsPin: readonly AskOrigin[] = ASK_ORIGIN_WORDS`,而
182
+ * `AskOrigin = SdkAskOrigin` 的型面带 `(string & {})` 逃生口 ⇒ **任何字符串都满足它**,这条钉
183
+ * 在 core 7.14.0 把 `unresolvable` 换成 `ancestor_marked` 的当天**一声不响**(亲验:换词后
184
+ * `npx tsc --noEmit` 0 红)。一条恒真的钉不是钉,是[gates-fail-in-their-own-ways] 的「无契约表」那一档。
185
+ * ⇒ 判据整只移交给 `run-gate-vocabulary-test.mjs` 的 **B 段**:本表对 **core `ask-origin.js` 的
186
+ * `ASK_ORIGINS` 真字节**双向等值(词表属主是 core,sdk 只是它的镜像且**今天滞后一代**)。
187
+ * 那条对账拿的是运行期真字节,逃生口影响不到它。
188
+ */
189
+ // ══ 0.67.0 / core 7.14.0 #688 C3 —— 第三张表:`ruleStoreUnreadable` 两词 ═════════════════════
190
+ //
191
+ // 它不是 `AskOrigin` 的第十二个词,而是**一个 origin 词底下的机制位**:`rule_store_unavailable`
192
+ // 这一个词盖了**两种机制**(core `ask-origin.d.ts:98-104` 顶注逐字点名),而对人的下一步**相反**。
193
+ // 词表属主 = core `RULE_STORE_UNREADABLE_KINDS`(`ask-origin.d.ts:116`),本包逐词逐序镜像,
194
+ // `run-gate-vocabulary-test.mjs` 的 C 段对**实装 core 的真字节**双向等值。
195
+ /**
196
+ * **规则店读不出来是哪一头**(core `RULE_STORE_UNREADABLE_KINDS`;逐词逐序镜像,7.14.0 起两词)。
197
+ * · `store` —— 接上的那个店**读不出来**(读失败 / 超时 / 适配器抛了);
198
+ * · `call` —— 店读到了,但**这一次调用**读不出来(收紧 lexer 的 `unreadable`:展开里有读不懂的词 /
199
+ * 引号未闭合 / 语法错 —— 引擎自己那句话在 ask 的 `message` 上)。
200
+ *
201
+ * 🔴 **真闭集**(与 `AskOrigin` 的开集刻意不同):core 在**唯一 stamp 点**把政策自报的值剥掉之后
202
+ * 才盖章(7.14.0 合同逐字「A policy's self-declared value is removed at the stamp」)⇒ 表外值
203
+ * 结构上到不了消费端。
204
+ * 🔴 形制:`Object.freeze` 的数组,理由同上面两张表。
205
+ */
206
+ export const RULE_STORE_UNREADABLE_KINDS = Object.freeze(['store', 'call']);
207
+ const RULE_STORE_UNREADABLE_SET = new Set(RULE_STORE_UNREADABLE_KINDS);
208
+ /** 这个值是不是 {@link RULE_STORE_UNREADABLE_KINDS} 的成员(core `isRuleStoreUnreadable` 的镜像)。
209
+ * 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。 */
210
+ export function isRuleStoreUnreadableKind(v) {
211
+ return typeof v === 'string' && RULE_STORE_UNREADABLE_SET.has(v);
212
+ }
213
+ /** 逐词一句人话。**两句刻意逐字互异** —— 两条不同的下一步(去修部署的规则店 / 去改自己那条规则)。 */
214
+ const RULE_STORE_UNREADABLE_SENTENCES = Object.freeze({
215
+ store: 'your standing deny/ask rules could not be read at all (the rule store did not answer), so this call asks',
216
+ call: 'this command could not be read against your standing deny/ask rules (the engine’s own sentence is on this ask), so it asks',
217
+ });
218
+ /**
219
+ * 一个 `ruleStoreUnreadable` 词 → 一句人话。**唯一铸点**(三端共用;端零自拼)。
220
+ *
221
+ * 🔴 **与 {@link askOriginDetail} 并列不互替**:那一句答「谁问的」(出身),本句答「读不出来的是
222
+ * **哪一头**」。`rule_store_unavailable` 那只 ask 上两句都该在,渲一句丢一句就等于把人指去
223
+ * 错的地方 —— 而这正是 core 把这一位单独铸出来的理由。
224
+ * 🔴 **查表用 `Object.hasOwn`**(冻结不移除原型;理由与本文件另两个铸点逐字相同)。
225
+ * 🔴 表外词 / 坏值 ⇒ 一句**兜底**:原样带上那个词,并明说这次仍然是在问人。
226
+ * ⚠️ 与 {@link isRuleStoreUnreadableKind} 的闭集判据不矛盾:那一层答「这条事实在不在」(闭集,
227
+ * 出集 = 坏形),本层答「拿到一个词怎么渲」—— 一条从旧持久态恢复回来的视图必须渲出一句诚实的话。
228
+ */
229
+ export function ruleStoreUnreadableDetail(kind) {
230
+ const known = typeof kind === 'string' && Object.hasOwn(RULE_STORE_UNREADABLE_SENTENCES, kind)
231
+ ? RULE_STORE_UNREADABLE_SENTENCES[kind]
232
+ : undefined;
233
+ if (known !== undefined)
234
+ return known;
235
+ const word = typeof kind === 'string' && kind.length > 0 ? kind : '(none)';
236
+ return `your standing deny/ask rules could not be applied to this call; the reported reason ${word} is a word newer than this client, so answer this ask as usual`;
237
+ }
@@ -78,7 +78,6 @@
78
78
  * 🔴 方向纪律:reason/note 只做归因,绝不参与裁决;缺席 ⇒ 现状字节不变。
79
79
  */
80
80
  import { type GateCurrentPending, type HitlFailureStage, type HitlSafetyCode, type HitlClientLike } from './hitlBridge.js';
81
- import type { ClassifierUnavailableView } from '../autoModeUnavailable.js';
82
81
  import { type DecideReceiptView } from '../decideReceipt.js';
83
82
  import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, DENIAL_LIMIT_KINDS } from '@sema-agent/sdk';
84
83
  import type { RuleSuggestion, ToolApprovalRespondAck, PersistedRuleAnchor as SdkPersistedRuleAnchor, RuleOfferMatch as SdkRuleOfferMatch, RuleOfferBatchMember as SdkRuleOfferBatchMember, RuleOfferUncoveredDetail as SdkRuleOfferUncoveredDetail, RuleOfferUncoveredReason as SdkRuleOfferUncoveredReason, AskOrigin as SdkAskOrigin, RuleOffersAbsence as SdkRuleOffersAbsence, DenialLimitKind as SdkDenialLimitKind, DenialLimitFallback as SdkDenialLimitFallback } from '@sema-agent/sdk';
@@ -235,12 +234,17 @@ export type RuleOfferUncoveredReason = SdkRuleOfferUncoveredReason;
235
234
  */
236
235
  export { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS };
237
236
  /**
238
- * 一只 ask 的**出身** —— **sdk 8.3.0 `AskOrigin` 派生**(core `ASK_ORIGINS` 闭八词:
239
- * `content_question` / `unresolvable` / `org_unavailable` / `org_rule` / `hook` / `ask_rule` /
240
- * `denial_limit_fallback` / `policy`;**引擎在门上盖章**,不是策略的自称)。
237
+ * 一只 ask 的**出身** —— **sdk 8.3.0 `AskOrigin` 派生**(core `ASK_ORIGINS`,7.14.0 起十一词:
238
+ * `content_question` / `ancestor_marked` / `org_unavailable` / `org_rule` / `rule_store_unavailable` /
239
+ * `hook` / `ask_rule` / `denial_limit_fallback` / `shell_gate_tighten` / `safety_tighten` / `policy`;
240
+ * **引擎在门上盖章**,不是策略的自称)。
241
241
  *
242
242
  * 🔴 **词表唯一属主是 core**,本别名只是型面供给(闭集给补全,`(string & {})` 让新词读得出来)——
243
243
  * 端一律按**开集**分支:认不得的词渲「未知出身」,**绝不**渲成「没有出身」。
244
+ * ⚠️ **sdk 8.8.0 的联合滞后一代**:它还写着 7.13.x 的 `unresolvable`,而 core 7.14.0 已把那一员
245
+ * **BREAKING 换成 `ancestor_marked`**(无 alias)。本包的**运行期**词表 `ASK_ORIGIN_WORDS`
246
+ * (`gateVocabulary.ts`)跟的是 **core 的真字节**,sdk 追平那天 `run-gate-vocabulary-test.mjs`
247
+ * 的滞后登记会自红逼删。一条 pre-7.14 的耐久行带 `"unresolvable"` ⇒ 非成员 ⇒ 投影**省略**那一格。
244
248
  * 🔴 与 {@link ToolApprovalFrame.governanceForced} **不是**一回事(sdk 顶注逐字):本词答「哪一类
245
249
  * 权威提的问」,那一位答「**本部署运维治理层**是不是这只 ask 的门」;`origin:"policy"` 覆盖
246
250
  * 任何部署 ToolPolicy 的 ask ⇒ 两者顶替不了对方。
@@ -682,29 +686,29 @@ export interface ApprovalCardRequest {
682
686
  */
683
687
  origin?: string;
684
688
  /**
685
- * cli L-174②(0.64.2;server ≥7.69.0 / core 7.10.0 #616)—— 「**问你是因为分类器这次跑不了**」的
686
- * 事实,**双源合流**({@link governanceForced} 同形,两腿在场性可以不一致):
687
- * · **活卡帧腿**:{@link ToolApprovalFrame.classifierUnavailable} 的窄读产物;
688
- * · **durable park 行腿**:`PendingAction.tool_approval.classifierUnavailable` 的孪生位
689
- * (core `checkpoint-store.d.ts` 逐字「the PARK twin of `AskRequest.classifierUnavailable`」),
690
- * 经**同一把**窄读器 —— 两处**键路同形**,各写一份就是两份台账各漂各的。
689
+ * **core 7.14.0 #688 C3**(0.67.0;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 是因为
690
+ * **持久规则那条腿读不出来**才问人的,而它**具体哪一头**读不出来:
691
+ * · `store` —— 那个人的**持久规则店整体**读不出来(读失败 / 超时 / 适配器抛了);
692
+ * · `call` —— 店读到了,但**这一次调用**对不上他的 deny/ask 规则行(收紧 lexer 的 `unreadable`:
693
+ * 展开里有读不懂的词 / 引号未闭合 / 语法错 —— 引擎自己的那句话在 `message` 上)。
691
694
  *
692
- * 🔴 **键路与 ask / park 行同形是有意的**:端不必为卡再学一个读法 —— `classifierUnavailableOf(req)`
693
- * 直接吃这张卡(0.63.0 件⑧ 的读器,§27h2),措辞走它的孪生铸点 `classifierUnavailableDetail`。
694
- * 🔴 **两层都按开集,显示层只多一条有出处的排除**(0.64.2 订正后两层判据几乎逐字相同):
695
- * · **本层(过境)**只判形 —— `cause` 非空串即收,与 server 唯一铸点 `readClassifierUnavailable`
696
- * 同判据。词表属主在 core,包在边界再校一次闭集,只会在 core 加词那天把一个**合法**值判没,
697
- * 而丢的正是「这次不可用是新出现的那一类」这条信息(与 `origin`/`ruleOffersAbsence` 逐字同规);
698
- * · **显示层**(`classifierUnavailableOf`)同样非空串即收,只排除**熔断轴独占**的词
699
- * (今天 = `parse_error`;core 明说它不 stamp 到这一格)—— 未知词在那一层渲**兜底句**,
700
- * 不是不渲。⚠️ 0.64.2 之前那一层是 unavailable **闭集**,于是一个合法的新成因词过得了本层、
701
- * 却在显示层被判没(异源对抗复审逼出的真病;详见 INTEGRATION §29e)。
702
- * 🔴 **显示元数据,不是裁决位**:不参与、也不改变本次决断的任何字节;缺席**不许**渲成
703
- * 「分类器跑成了」(缺席三形不可分,见帧上同名键)。
704
- * ⚠️ **退役日期已定**(上游发布记录 [6852]/[6853]):core 7.12.0 / server 7.70.0 起帧上这一格是**死键**,
705
- * 事实位随拒绝面走;本包 0.65.0 改读那一面而**不删本键**——缺席臂当天就是正解。
695
+ * **双源合流**(与退役前的 `classifierUnavailable` 两腿装配**同形同位**):
696
+ * · **活卡帧腿**:{@link ToolApprovalFrame.ruleStoreUnreadable} 的窄读产物;
697
+ * · **durable park 行腿**:`PendingAction.tool_approval.ruleStoreUnreadable` 的孪生位
698
+ * (core `checkpoint-store.d.ts:818` / 摘要行 `:1924-1926` 逐字同名),经**同一把**窄读器。
699
+ *
700
+ * 🔴 **在场 ⇔ `origin === "rule_store_unavailable"`**(core 7.14.0 合同逐字):缺席 = 这条腿把店
701
+ * 和这次调用都读通了,**或者压根没接规则店** —— 两形在这一格上不可分,端**禁**把缺席渲成
702
+ * 「你的规则都好着呢」。
703
+ * 🔴 **为什么非有它不可**:`origin` 那一个词盖了**两种机制**,而对人的下一步是**相反**的 ——
704
+ * `store` 要去修部署的规则店,`call` 要去改他自己那条规则/这条命令。只给 origin 的卡会把人
705
+ * 指到错的地方(core `ask-origin.d.ts:98-104` 顶注逐字点名这件事)。
706
+ * 🔴 **闭二词按闭集判**(与 `cause` 同一条,与 `origin`/`ruleOffersAbsence` 的开集纪律不同):
707
+ * core 在**唯一 stamp 点**上把政策自报的值剥掉后才盖章(合同逐字「A policy's self-declared
708
+ * value is removed at the stamp」)⇒ 表外值到不了消费端,真读到就是坏形,渲一句成因就是编事实。
709
+ * 人话两句走**唯一铸点** `ruleStoreUnreadableDetail`(三端零自拼)。
706
710
  */
707
- classifierUnavailable?: ClassifierUnavailableView;
711
+ ruleStoreUnreadable?: string;
708
712
  }
709
713
  /**
710
714
  * 🔴 **拆缝口** —— 弹「三选卡」并等人的决断。壳 = vendored CC `PermissionRequest`;
@@ -889,27 +893,24 @@ export interface ToolApprovalFrame {
889
893
  */
890
894
  denialLimitFallback?: DenialLimitFallback;
891
895
  /**
892
- * **server ≥7.69.0 / core 7.10.0 #616**(cli L-174②;**ADDITIVE**,`"tool_approval"` only。真发直证 =
893
- * engine 7.69.0 fixture `@sema-agent/server/dist/tool-approval.js:847` 的条件 stamp + 同包
894
- * `approval-card.js:244` `readClassifierUnavailable`(`z.object({cause: z.string().min(1).max(200)}).strict()`,
895
- * 与 `card_json` 铸点 `:315` 同一只读器);上游发布记录 [6863] ③ 表逐字「additive;缺席不是断言;`cause`
896
- * core 闭三词但 **wire 上 string**」)——这只 ask 是因为 **auto 模式分类器这一轮跑不了**才问人的,
897
- * `cause` 说的是「为什么没跑成」(core `AUTO_MODE_UNAVAILABLE_CAUSES`)。
896
+ * **core 7.14.0 #688 C3**(0.67.0;**ADDITIVE**,`"tool_approval"` only)——
897
+ * `AskRequest.ruleStoreUnreadable ∈ {"store","call"}`(core `ask-origin.d.ts:116`
898
+ * `RULE_STORE_UNREADABLE_KINDS` / `isRuleStoreUnreadable`;`tool-policy.d.ts:308` 是 ask 臂上的声明)。
899
+ * 「持久规则那条腿读不出来」这件事的**机制位**:`store` = 店整体读不出来 / `call` = 这条调用对不上
900
+ * 那个人的 deny/ask 规则行。
898
901
  *
899
- * 🔴 **显示元数据,不是裁决位**:引擎在门上已经判完了,没有任何东西读它决定放行与否。
900
- * 🔴 **缺席不是断言**:缺席同时覆盖「分类器答上了」「这只 ask 没资格走分类器」「本部署没接分类器」
901
- * 三形(core d.ts 逐字:read presence, never absence)—— 端**禁**读成「分类器好着呢」。
902
- * 🔴 **echo-only**:server 顶注逐字写明它不据本键做任何裁决;据它在下游自铸第二套熔断/回落判据
903
- * = 同一语义面两个写者(源头修复纪律)。本包同律 —— 本批只做过境,**不做熔断相关任何事**。
904
- * ⚠️ **它是一个已定退役日期的键**(上游发布记录 [6852] server 侧落点表逐字:「ask 帧 `classifierUnavailable`
905
- * **死键**;事实位随 deny 载荷 … 三面投影(tool_approval 帧 / card_json / inbox 行)**退役**,
906
- * `permissionDenied.classifierUnavailable` 走 `tool_end.gate` 既有透传」)⇒
907
- * **core 7.11.x 仍写;core 7.12.0 / server 7.70.0 起缺席**。本包 0.65.0 按 [6853] 的排期改从
908
- * 拒绝面渲,**码不删**(死键保留型):缺席臂那天就是正解,退役一个 additive 键不该逼三端各改一次。
902
+ * 🔴 **在场 ⇔ `origin === "rule_store_unavailable"`**(合同逐字)。缺席 = 这条腿把店和这次调用都读
903
+ * 通了,**或**本部署压根没接规则店 —— 两形不可分,端禁读成「你的规则都好着呢」。
904
+ * 🔴 **一个 origin 词盖两种机制,而下一步相反** —— 这正是它单独占一格的理由
905
+ * (core `ask-origin.d.ts:98-104` 顶注)。措辞铸点 `ruleStoreUnreadableDetail`,端零自拼;
906
+ * 引擎在 `message` 上给的**这一次**的散文(lexer 那句话)由 `askOriginDetail(origin, message)`
907
+ * 让位渲出(0.65.0 B-080③ 已有的臂),两者并列不互替。
908
+ * 🔴 **闭二词按闭集判**:core 在唯一 stamp 点剥掉政策自报的值之后才盖章 ⇒ 表外值到不了消费端。
909
909
  * ⚠️ **sdk 8.8.0 的运行期锚 `TOOL_APPROVAL_FRAME_KEYS`(27 项)尚无本键** ⇒ 镜像**领先**一代,
910
910
  * 对账门里挂着一条带退出条件的 `AHEAD_OF_ANCHOR` 登记(sdk 8.9.x 同拍补上那天它自红逼删)。
911
+ * ⚠️ 0.67.0 同批**删掉**了上一代那条同形登记(`classifierUnavailable` 随 core 7.14.0 退役)。
911
912
  */
912
- classifierUnavailable?: ClassifierUnavailableView;
913
+ ruleStoreUnreadable?: string;
913
914
  /**
914
915
  * server ≥7.13.0(#144 / core 5.25.0,[3438] 接力契约 / [3443] 主件;**ADDITIVE**,
915
916
  * `"tool_approval"` only。来源锚 = engine fixture `@sema-agent/server/dist/tool-approval.d.ts`
@@ -1099,7 +1100,7 @@ export interface ToolApprovalDelegation {
1099
1100
  * `TOOL_APPROVAL_FRAME_KEYS` 比对——SDK additive 增键时对账当天红,不再人肉追平。
1100
1101
  * 下面两个类型钉保证镜像与 interface 本身不可能漂移(少键/多键都是编译错)。
1101
1102
  */
1102
- export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "classifierUnavailable", "origin", "inputHasBidi", "parked", "persistedRuleShadowed", "probeCause", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome"];
1103
+ export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "ruleStoreUnreadable", "origin", "inputHasBidi", "parked", "persistedRuleShadowed", "probeCause", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome"];
1103
1104
  /**
1104
1105
  * 子代帧判别:显式键 fromSubagent(core 1.378 RB-39②)优先;缺席退 sourceTaskId 在场性权宜式
1105
1106
  * (server 1.258 [1549]①3,旧代际兼容)。