@sema-agent/server 7.99.0 → 7.101.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 (174) hide show
  1. package/MIGRATION.md +35 -1
  2. package/README.md +12 -1
  3. package/README.zh-CN.md +9 -1
  4. package/USAGE.md +150 -56
  5. package/dist/approval-ask-machine.d.ts +10 -0
  6. package/dist/approval-ask-machine.js +3 -0
  7. package/dist/approval-card.d.ts +86 -1
  8. package/dist/approval-card.js +42 -8
  9. package/dist/approval-policy-settlement.d.ts +31 -0
  10. package/dist/approval-policy-settlement.js +16 -0
  11. package/dist/approval-reconciler.d.ts +8 -1
  12. package/dist/approval-reconciler.js +5 -4
  13. package/dist/approval.d.ts +44 -20
  14. package/dist/approval.js +14 -6
  15. package/dist/boot/config-center.d.ts +16 -8
  16. package/dist/boot/config-center.js +114 -90
  17. package/dist/boot/execution-env.d.ts +1 -2
  18. package/dist/boot/execution-env.js +21 -3
  19. package/dist/boot/leader.js +12 -9
  20. package/dist/boot/memory-consolidation.d.ts +38 -0
  21. package/dist/boot/memory-consolidation.js +35 -0
  22. package/dist/boot/parked-revive-gate.js +1 -0
  23. package/dist/boot/reapers.js +1 -0
  24. package/dist/boot/resolve-spec.d.ts +0 -1
  25. package/dist/boot/resolve-spec.js +28 -10
  26. package/dist/boot/runner-deps.d.ts +2 -2
  27. package/dist/boot/runner-deps.js +9 -3
  28. package/dist/boot/stage-02-registry-pull.js +9 -0
  29. package/dist/boot/stage-05-execution-env.d.ts +1 -1
  30. package/dist/boot/stage-06-runners.d.ts +2 -2
  31. package/dist/boot/stage-06-runners.js +3 -3
  32. package/dist/boot/stage-07-capability-layer.d.ts +2 -3
  33. package/dist/boot/stage-07-capability-layer.js +6 -6
  34. package/dist/boot/stage-08-reapers.d.ts +3 -4
  35. package/dist/boot/stage-08-reapers.js +2 -2
  36. package/dist/boot/stage-09-leader.d.ts +2 -3
  37. package/dist/boot/stage-10-http-server.d.ts +2 -3
  38. package/dist/boot/stage-10-http-server.js +2 -2
  39. package/dist/boot/stores.js +4 -0
  40. package/dist/capabilities/center-plugins.d.ts +14 -2
  41. package/dist/capabilities/center-plugins.js +13 -5
  42. package/dist/capabilities/hands-lane.js +2 -1
  43. package/dist/capabilities/scenarios.js +18 -5
  44. package/dist/capabilities/tool-defer.d.ts +2 -2
  45. package/dist/config-catalog.d.ts +2 -2
  46. package/dist/config-catalog.js +16 -15
  47. package/dist/config-center/apply-effective.d.ts +59 -39
  48. package/dist/config-center/apply-effective.js +231 -120
  49. package/dist/config-center/apply-ledger.d.ts +45 -16
  50. package/dist/config-center/apply-ledger.js +28 -18
  51. package/dist/config-center/facade.d.ts +12 -6
  52. package/dist/config-center/facade.js +2 -2
  53. package/dist/config-center/hot-keys-registry.d.ts +11 -4
  54. package/dist/config-center/hot-keys-registry.js +11 -7
  55. package/dist/config-center/http-client.d.ts +4 -1
  56. package/dist/config-center/http-client.js +15 -10
  57. package/dist/config-center/read-warnings.d.ts +115 -6
  58. package/dist/config-center/read-warnings.js +115 -5
  59. package/dist/config-center/restart-signal.d.ts +21 -14
  60. package/dist/config-center/restart-signal.js +16 -22
  61. package/dist/config-center/types.d.ts +9 -3
  62. package/dist/config-invariants.d.ts +2 -2
  63. package/dist/config-invariants.js +15 -0
  64. package/dist/config-provider.d.ts +4 -0
  65. package/dist/config-provider.js +64 -9
  66. package/dist/config-types.d.ts +57 -13
  67. package/dist/config.js +87 -22
  68. package/dist/cross-session-settings.js +1 -1
  69. package/dist/deployment-governance.d.ts +45 -12
  70. package/dist/deployment-governance.js +37 -9
  71. package/dist/env-name-allowlist-knobs.d.ts +37 -0
  72. package/dist/env-name-allowlist-knobs.js +24 -0
  73. package/dist/fleet-client.d.ts +2 -1
  74. package/dist/hooks/hook-llm.js +13 -4
  75. package/dist/host-lsp-manager.d.ts +41 -0
  76. package/dist/host-lsp-manager.js +15 -0
  77. package/dist/http/active-run-conflict.d.ts +2 -12
  78. package/dist/http/active-run-conflict.js +1 -6
  79. package/dist/http/admission.js +30 -7
  80. package/dist/http/memory-store-refusal-reply.d.ts +24 -0
  81. package/dist/http/memory-store-refusal-reply.js +10 -0
  82. package/dist/http/resume-legs.d.ts +1 -1
  83. package/dist/http/resume-legs.js +14 -10
  84. package/dist/http/route-ctx.d.ts +2 -2
  85. package/dist/http/routes/approvals-assistant.d.ts +1 -1
  86. package/dist/http/routes/approvals-assistant.js +3 -2
  87. package/dist/http/routes/capabilities.js +3 -3
  88. package/dist/http/routes/memory-bundle.js +3 -0
  89. package/dist/http/routes/memory-compliance.js +3 -0
  90. package/dist/http/routes/memory-origin.js +3 -0
  91. package/dist/http/routes/sessions.js +7 -0
  92. package/dist/http/routes/side-query.js +10 -4
  93. package/dist/http/routes/tasks.js +7 -6
  94. package/dist/http/server.d.ts +6 -5
  95. package/dist/http/wire-types.d.ts +6 -3
  96. package/dist/instruction-source-notice.d.ts +97 -0
  97. package/dist/instruction-source-notice.js +78 -0
  98. package/dist/leader/wire.d.ts +20 -12
  99. package/dist/leader/wire.js +7 -6
  100. package/dist/memory-layer-legacy-lock.d.ts +14 -0
  101. package/dist/memory-layer-legacy-lock.js +74 -0
  102. package/dist/memory-store-refusal.d.ts +37 -0
  103. package/dist/memory-store-refusal.js +14 -0
  104. package/dist/model-entry-refusal.d.ts +130 -0
  105. package/dist/model-entry-refusal.js +157 -0
  106. package/dist/model-provider.d.ts +9 -3
  107. package/dist/model-route-endpoint.d.ts +1 -1
  108. package/dist/model-select.d.ts +49 -4
  109. package/dist/model-select.js +48 -17
  110. package/dist/observability/corrupt-read-seat.d.ts +21 -4
  111. package/dist/observability/corrupt-read-seat.js +31 -0
  112. package/dist/observability/fail-open.d.ts +16 -4
  113. package/dist/observability/fail-open.js +16 -4
  114. package/dist/observability/metrics.js +1 -0
  115. package/dist/observability/run-terminal.js +1 -0
  116. package/dist/observability/secret-env-scrub.d.ts +27 -3
  117. package/dist/observability/secret-env-scrub.js +22 -6
  118. package/dist/orchestration/workflow-completion-inbox.d.ts +31 -23
  119. package/dist/orchestration/workflow-completion-inbox.js +8 -3
  120. package/dist/plugins/approval-ask-store-file.d.ts +20 -2
  121. package/dist/plugins/approval-ask-store-file.js +21 -3
  122. package/dist/plugins/approval-ask-store-memory.d.ts +2 -0
  123. package/dist/plugins/approval-ask-store-memory.js +39 -13
  124. package/dist/plugins/approval-ask-store-sql.d.ts +24 -5
  125. package/dist/plugins/approval-ask-store-sql.js +27 -3
  126. package/dist/plugins/caching-session-store.d.ts +6 -0
  127. package/dist/plugins/caching-session-store.js +6 -0
  128. package/dist/plugins/checkpoint-store-sql.d.ts +9 -3
  129. package/dist/plugins/checkpoint-store-sql.js +19 -2
  130. package/dist/plugins/local-checkpoint-store.js +2 -0
  131. package/dist/plugins/local-session-store.d.ts +20 -25
  132. package/dist/plugins/local-session-store.js +111 -64
  133. package/dist/plugins/mailbox-store-sql.d.ts +7 -5
  134. package/dist/plugins/mailbox-store-sql.js +6 -4
  135. package/dist/plugins/permission-rule-store-file.js +3 -2
  136. package/dist/plugins/pg-session-storage.d.ts +7 -0
  137. package/dist/plugins/pg-session-storage.js +19 -0
  138. package/dist/plugins/remote-env-host.d.ts +3 -1
  139. package/dist/plugins/remote-env-host.js +3 -6
  140. package/dist/plugins/sql-json-column.d.ts +16 -3
  141. package/dist/plugins/sql-json-column.js +15 -4
  142. package/dist/plugins/tidb-pool.js +5 -0
  143. package/dist/plugins/tidb-session-store.d.ts +13 -0
  144. package/dist/plugins/tidb-session-store.js +14 -0
  145. package/dist/plugins/web-search.d.ts +44 -23
  146. package/dist/plugins/web-search.js +161 -50
  147. package/dist/project-memory.d.ts +10 -0
  148. package/dist/project-memory.js +28 -14
  149. package/dist/run-local.d.ts +17 -15
  150. package/dist/run-local.js +119 -18
  151. package/dist/runs.js +6 -5
  152. package/dist/runtime-governance.d.ts +50 -3
  153. package/dist/runtime-governance.js +5 -0
  154. package/dist/sealed-key.d.ts +5 -2
  155. package/dist/server-secret-env.d.ts +26 -2
  156. package/dist/server-secret-env.js +9 -0
  157. package/dist/task-settings.d.ts +1 -1
  158. package/dist/tool-approval.d.ts +150 -28
  159. package/dist/tool-approval.js +150 -54
  160. package/dist/trace/core-keyset-guard.d.ts +30 -8
  161. package/dist/trace/engine-notice-wire.d.ts +27 -1
  162. package/dist/trace/engine-notice-wire.js +8 -0
  163. package/dist/trace/ledger-sink.js +2 -2
  164. package/dist/trace/project.d.ts +13 -0
  165. package/dist/trace/project.js +22 -5
  166. package/dist/trace/projection-drop.d.ts +2 -0
  167. package/dist/trace/projection-drop.js +6 -0
  168. package/dist/trace/sema-provenance.d.ts +4 -1
  169. package/dist/trace/sema-provenance.js +1 -1
  170. package/dist/trace/task-notification-facets.d.ts +65 -0
  171. package/dist/trace/task-notification-facets.js +31 -0
  172. package/dist/trace/wire-projection-faces.d.ts +3 -3
  173. package/dist/trace/wire-projection-faces.js +3 -3
  174. package/package.json +3 -3
@@ -1,11 +1,12 @@
1
1
  import type { HostDecidedBy, HostSettledBy } from "./host-decision.js";
2
2
  import type { IncomingMessage } from "node:http";
3
- import { type AskRequest, type AskOutcome, type ReadRootGrantCandidate, type RuleOffer } from "@sema-agent/core";
3
+ import { type AskRequest, type AskOutcome, type CheckpointGate, type PendingAction, type ReadRootGrantCandidate, type RuleOffer } from "@sema-agent/core";
4
4
  import { type CardRulePersisted, type RuleConsentLane } from "./rules-consent.js";
5
5
  import { type DenialLimitFallback, type RuleOffersAbsence, type ApprovalRequestFrame, type ApprovalRevokeFrame, type RuleEvidenceProjection } from "./approval-card.js";
6
6
  import { type ApprovalAskStore, type AskRow } from "./plugins/approval-ask-store-sql.js";
7
7
  import type { ApprovalAskAuditSink } from "./approval-ask-audit-store.js";
8
8
  import { type GovernanceAskMarks } from "./governance-ask-marks.js";
9
+ import { type GovernancePosture } from "./runtime-governance.js";
9
10
  /** [ref]:审批 gate kind 闭集(core gateMatch 的 `human`/`irreversible_ask` ↔ outcome.gate "policy_ask")。
10
11
  * 此前 7 份手写副本散在两只 checkpoint store 的数组/SQL 字面与 /decide 守卫——core 加审批味 kind 时
11
12
  * 全部静默漂移。core 无导出词表(全大写导出面零命中,2026-08-09 亲验),属主落此;SQL IN 片段从
@@ -80,10 +81,11 @@ export type ParkedAskRedeem = (req: ParkedAskRedeemRequest) => Promise<{
80
81
  * 一问身上与「站着的答案」有关的三个事实位 —— {@link standingAnswerMayRetire} 的全部入参。
81
82
  *
82
83
  * 🔴 **三格全必填布尔**,刻意不做 `?: true` 的「只记真」形:判据哪天多一位,每个读者都要当场编译红,
83
- * 而不是漏传一格被静默读成 `false`(那是安全轴上的 fail-open)。读者各自从自己手里的形折成这三格:
84
- * live 读侧取 `req` + 本地治理 peek,live 写侧取 pending 条目。本型**不绑** live 条目 —— 耐久 `/decide`
85
- * 腿候 core 给 `PendingAction` 补 `mandated` 孪生位后按同一形接入(见 S-663;今天行上只有
86
- * `requiresRealApproval` 孪生与依赖车道的 `ruleOffersAbsence`,缺一位不先接两位)。
84
+ * 而不是漏传一格被静默读成 `false`(那是安全轴上的 fail-open)。读者各自从自己手里的形折成这三格,
85
+ * 然后交**同一只** {@link standingAnswerMayRetire}(判据只有一份,折法各归读者):
86
+ * · live 读侧取 `req` + 本地治理 peek;live 写侧取 pending 条目;
87
+ * · 耐久 `/decide` 腿(S-663 → NP-1,7.100.0)取 park 行,经 {@link parkRowStandingAnswerFacts}(三格全从行上读)。
88
+ * 本型**不绑** live 条目。
87
89
  */
88
90
  export interface StandingAnswerFacts {
89
91
  /** 本仓治理层(`AUTONOMY` / `commandPolicy` / shellGate / `SENSITIVE_WRITE_PATTERNS`)产的门。 */
@@ -94,20 +96,25 @@ export interface StandingAnswerFacts {
94
96
  readonly mandated: boolean;
95
97
  }
96
98
  /**
97
- * 🔴 **S-660 —— 会话级放行的唯一判据:站着的答案能不能退掉这一问。** 纯谓词,两个(将来三个)读者:
99
+ * 🔴 **S-660 —— 会话级放行的唯一判据:站着的答案能不能退掉这一问。** 纯谓词,三个读者:
98
100
  * · **读侧**(`askBroadcast` 的会话授权短路):`true` 才可能由既有 grant 代答,否则往下走真出卡;
99
101
  * · **写侧**(`finishRespond` 的 `grantable`):`true` 才可能把这张卡上的 `allow_session` 铸成 grant,
100
- * 否则只放行这一次、`rememberApplied:false`。
102
+ * 否则只放行这一次、`rememberApplied:false`;
103
+ * · **耐久 `/decide` 腿**(NP-1,`http/resume-legs.ts` 的 remember 可记性):入参由 {@link parkRowStandingAnswerFacts}
104
+ * 从 park 行铸 —— `false` ⇒ 可记工具名 `null` ⇒ 放行本次、不落豁免、回执 `rememberApplied:false`。
101
105
  * 两臂读同一份事实、说同一句话:一问若不许被记住的放行答掉,它的应答也不许变成一条记住的放行 —— 否则
102
106
  * 同一只卡「重跑一遍」就被自己上一次的回答代答(test [ref] U1s-off 的真形)。
103
107
  *
104
108
  * **为什么三位是同一类**(「站着的答案退不掉的一问」):会话授权 = **上一次**应答记下的一揽子放行,不是对
105
109
  * **这一次**调用的应答 —— 与持久 allow 规则同族,只是更短命(`askBroadcast` 短路处的注早已这么定性)。
106
- * · `mandated`:core 7.29.0 `PermissionResult` ask 臂 `mandated` 成员的文档「no persisted allow rule and no standing
107
- * posture may retire it, only an answer to THIS call」;`ruleClearanceOf` 的文档「Allow rules silence the
108
- * classifier's questions, never a mandated one」。core 09-23 澄清(将在 7.30.0 落进 d.ts):「从早先某次
109
- * 回答记住的放行,**任何 scope、会话级也算**」都是站着的答案。它**不**绑这一次调用的应答者(人、hook、
110
- * 部署的一揽子 `onAsk:"allow"` 席、mandate 表允许的活判定者)—— 那一半本仓不动(见 `mandated` 帧键顶注)。
110
+ * · `mandated`:core `PermissionResult` ask 臂 `mandated` 成员的文档。7.29.0 原句「no persisted allow rule and no standing
111
+ * posture may retire it, only an answer to THIS call」;**7.30.0 起 d.ts 已落 [ref] 澄清**(S-616 在 7.30.1 装树亲核):
112
+ * core `PermissionResult` ask 臂的 `mandated` 成员文档「no persisted allow rule and no STANDING ANSWER (a release remembered
113
+ * from an earlier call, at any scope, a session included) may retire it」,`AskRequest.mandated` 孪生句同义 ——
114
+ * 「从早先某次回答记住的放行,**任何 scope、会话级也算**」都是站着的答案。core `ruleClearanceOf` 的文档
115
+ * 「Allow rules silence the classifier's questions, never a mandated one」。它**不**绑
116
+ * 这一次调用的应答者(人、hook、部署的一揽子 `onAsk:"allow"` 席、mandate 表允许的活判定者 —— 同一句 d.ts 逐一点名)——
117
+ * 那一半本仓不动(见 `mandated` 帧键顶注)。本谓词行为对 7.29.0 零改(文档到货,判据本来就是这么读的)。
111
118
  * · `requiresRealApproval`([ref]):更强的那条,连一揽子席也不得答,当然也不许记住的放行答。
112
119
  * · `governanceForced`([ref]):运维治理层的门,客户端表态掀不掉;持久规则车道早已同判(`buildRuleLaneMaterial`)。
113
120
  * 本谓词**不重推** core 的 `ruleClearanceOf` / `ruleMayClear`(core 刻意不导出:闸外重算拿不到同一份标记快照,
@@ -117,9 +124,41 @@ export interface StandingAnswerFacts {
117
124
  * **自己**的位 —— core 每一次过闸(含 failover / 重启后的重入)都由 `runGateLanes` 里的 `stampAskOrigin`
118
125
  * 重新盖、经同一处的 `carryOf` 带上 `AskRequest`,读侧手里的 `req` 恒是这一次过闸的真值。`governanceForced`
119
126
  * 需要行读,是因为它来自本仓的**进程内**治理标表:failover / 重启后幂等命中既有行时本地表恒空,行上的卡才
120
- * 存着落库那一刻的判定。何况行上本来就没有 `mandated`(耐久面不造孪生座)—— 读了也读不到。
127
+ * 存着落库那一刻的判定。(那张「行」是本仓的 ask 账本行,不是 core 的 park 行;core 7.31.0 #1079 起 park 行上的
128
+ * `mandated` 孪生座由**耐久** `/decide` 腿读,见 {@link parkRowStandingAnswerFacts}。)
121
129
  */
122
130
  export declare function standingAnswerMayRetire(facts: StandingAnswerFacts): boolean;
131
+ /**
132
+ * 🔴 **S-663 → NP-1(7.100.0 合并复审 [ref] 交叉表 #2)—— 耐久 `/decide` 腿的 {@link StandingAnswerFacts}:从 park 行铸三位。**
133
+ * 纯投影,**不判**:判据是同一只 {@link standingAnswerMayRetire}(唯一读点 = `http/resume-legs.ts` 的 remember 可记性,
134
+ * `standingAnswerMayRetire(parkRowStandingAnswerFacts(…))`)。修前耐久腿自成一只谓词、只读 `ruleOffersAbsence` 一词,同一行上
135
+ * core 盖好的 `requiresRealApproval` 与治理出身都不读 ⇒ 那两类卡的 `remember:"session"` 照旧铸会话免询问,而 live 腿对同一张卡
136
+ * 答 `false`(两腿同一个问题、两份事实覆盖;两腿复审同报)。三格各自的来源(全在**这一条**已属主校验的载入行上,不另读):
137
+ * · `governanceForced` —— 行上的治理标:`gate.riskDescriptor.shellGateDoctrine` × 本部署治理姿态,经 **同一只**
138
+ * `governanceOriginOf`(`runtime-governance.ts`;运维队列 `projectPendingForWire` / 409 体同一个属主,不另判)。它在
139
+ * 本读者这里只**收窄**(失真两个方向的代价登记在 `governanceMandatesShellGateAlways` 顶注)。⚠️ 它**只覆盖 shell 门的
140
+ * `always` 档** —— live 腿的治理标来自进程内标记表(敏感写路径 / `commandPolicy` / `AUTONOMY` 内层策略 / shellGate 各档),
141
+ * park 行上唯一的取证格只有 `riskDescriptor.shellGateDoctrine`(见下方 🚧);
142
+ * · `requiresRealApproval` —— 行上 core 铸的那一位,经 `approval-card.ts` 的 {@link readParkRowTrueSeat}(与运维
143
+ * 队列 `parkRowFacts` 同一只读法,`=== true`)。刻意**不**经 `parkRowFacts` 本身:那只展示投影顺手对 `ruleOffersAbsence`
144
+ * 的集外词计展示面 F 类 tag,而本读者对同一格是 fail-closed(S-663 codex r1 钉「权限面不计展示面 tag」);
145
+ * · `mandated` —— **S-663 二段(core #1079,7.31.0 / S-723)**:行上 core 铸的孪生座 `PendingAction.tool_approval.mandated`,经
146
+ * **同一只** {@link readParkRowTrueSeat}(`=== true`);**或**强制子集 `ruleOffersAbsence` 经三态窄读
147
+ * {@link readRuleOffersAbsenceSeat} 读成 `"mandated"` / 读不出(集外词 / 非串值,世代差)⇒ `true`。两臂是**两个事实**的析取,
148
+ * 不是同一个事实的新旧两种读法:core 对 `"mandated"` 这一词的定义就是「no persisted rule could ever clear this ask」(强制的
149
+ * 充分条件),而 #1079 之前铸的行(7.30.x 引擎 park、升级后才被 `/decide`)没有孪生座 —— 只读孪生座会让这类在飞行照旧落豁免,
150
+ * 是对上一版的回归;读不出按强制是 fail-closed(一个本仓不认识的新词可能正是一种强制因由)。
151
+ *
152
+ * 🚧 **剩余不对称一处**(耐久腿读得到的事实比 live 腿少,读不到的一律照旧可记):
153
+ * ① (已关,S-663 二段)`mandated` 孪生位 —— core #1079 到货,行上词为 `shadowed` / 缺席的强制卡由孪生座读到
154
+ * (`test/approval-exemption-http.test.ts` 原 🚧 格已按钉翻成「false + 零行」);
155
+ * ② **非 shell 治理(候 S-707)**:治理位经 `governanceOriginOf` 只覆盖 shell 门 `always` 档;敏感写路径
156
+ * (`SENSITIVE_WRITE_PATTERNS`)、`commandPolicy`、`AUTONOMY` 内层策略产的门与 shellGate `classify` 档,park 行上没有取证格
157
+ * (live 腿靠进程内标记表,跨副本 / 重启后够不着),本折法读不到它们的治理出身。
158
+ */
159
+ export declare function parkRowStandingAnswerFacts(pending: Extract<PendingAction, {
160
+ kind: "tool_approval";
161
+ }>, gate: CheckpointGate, governance: GovernancePosture | undefined): StandingAnswerFacts;
123
162
  /** A live approval frame delivered to whoever tails this run's stream. `type` IS the SSE event name (named-event
124
163
  * convention, same as question). The shell renders `tool_approval` as the CC three-choice card and dismisses on
125
164
  * `tool_approval_complete`. */
@@ -186,14 +225,19 @@ export interface ToolApprovalFrame {
186
225
  * 车道**有什么可给,而那条车道对它不说话的工具、**没接规则店的部署**(本仓的 live-only 形)、装不下规则的
187
226
  * 任务都是结构性沉默 —— 它的缺席**不是**断言。本键是这一问**自己**的属性,凡强制皆在场。读错的代价 core
188
227
  * 实测过:同一条根外读命令在 shell 工具上是强制问、在 monitor 工具上看起来是普通问。
228
+ * (耐久 `/decide` 腿手里只有 park 行:core 7.31.0 #1079 起行上有本键的孪生座 `PendingAction.tool_approval.mandated`,
229
+ * S-663 二段读它;#1079 之前铸的行没有孪生座,那条腿仍读那一词的**在场**(`"mandated"` ⇒ 强制)、从不读它的缺席 —— 见
230
+ * {@link parkRowStandingAnswerFacts}。live 腿恒读本键。)
189
231
  *
190
232
  * 🔴 **它不是 `requiresRealApproval`**:强制只说「没有规则能清掉」,**不**说「没有应答者可以答」——
191
233
  * 一个人、一只 hook、一张一揽子 `onAsk:"allow"` 席照常答得了强制卡。两键别互推。
192
234
  *
193
- * 🔴 **真才带,缺席绝不编 `false`**(`governanceForced` / `requiresRealApproval` 同形)。缺席同时覆盖
194
- * 「不是强制」「老引擎」「这是一张从 park 行上重铸的耐久卡」三形 —— **耐久面上本仓不造孪生座**:core 的
195
- * 寄存行(`PendingAction`)没有这一位(KL-997a 亲读登记),行上强制表现为 `ruleOffersAbsence:"mandated"`
196
- * 且无 `ruleOffers`;在 `card_json` 侧自铸一个就是本仓成了这个事实的第二个源(而 park 那侧根本没有输入)。
235
+ * 🔴 **真才带,缺席绝不编 `false`**(`governanceForced` / `requiresRealApproval` 同形)。缺席覆盖「不是强制」「老引擎」
236
+ * 两形。**本仓从不自铸本键**:活卡帧(与 `livePending` 行顶层,T4①)只读 `AskRequest.mandated`;耐久面(运维队列行 / inbox 行)
237
+ * 自 core 7.31.0 #1079 起读 core 在 park 行上铸的孪生座(`PendingAction.tool_approval.mandated` / `CheckpointSummary.mandated`,
238
+ * S-663 二段),同样只投 core 给的那一位 —— 自铸一个就是本仓成了这个事实的第二个源。⚠️ **`card_json` 卡面不带本键**
239
+ * (`ApprovalCardSchema` 没有这一位,`.strict()`)⇒ 断连重放的 `approval_request` 帧(`buildReplayFrame` 只回放卡)上它恒缺席,
240
+ * 消费方读队列行 / 活卡帧 / `livePending` 行(8D-6:此前这里写的「`card_json` 只读 `AskRequest.mandated`」是错句,T4② 车OC 改真)。
197
241
  * 🔴 **server 不判「是不是强制」**(判定属主在 core 的闸站),只**读**闸站盖好的这一位 —— 读者恰一个:
198
242
  * S-660 起的会话级放行判据 {@link standingAnswerMayRetire}(会话授权是**上一次**应答记下的站着的答案,
199
243
  * 不是对这一次调用的应答 ⇒ 强制卡上既不被既有 grant 代答、也不铸 grant)。上一段「一揽子 `onAsk:"allow"`
@@ -482,6 +526,10 @@ export interface LivePendingRow {
482
526
  sessionId?: string;
483
527
  requiresRealApproval?: true;
484
528
  governanceForced?: true;
529
+ /** T4①(八病审计 8D-5,车OC / 7.101.0):强制位([ref],`AskRequest.mandated`)—— 与上两位**同层同形**(真才带,缺席不编 false),
530
+ * 值 = 条目上那一位(`askBroadcast` 铸条目时取自这一次过闸的 `req.mandated`,与 {@link frame} 上的同名键同源)。此前只在
531
+ * `frame` 里:同一个 `GET /v1/approvals` 响应的 durable `pending[]` 行顶层带它(S-663 二段),live 行却要进帧里读。 */
532
+ mandated?: true;
485
533
  /** 发起者为委派子代(originTaskId 在场)。 */
486
534
  fromSubagent?: true;
487
535
  /** [ref] C2(additive):委派子代的 **canonical taskId**。值域精确成文(codex R1-F3 问询后按 core dist
@@ -684,6 +732,29 @@ export type RespondSettledBy = Extract<HostSettledBy, HostDecidedBy>;
684
732
  * (`config.ts` 的解析腿,[ref] A 档)。
685
733
  */
686
734
  export type UnattendedApprovalPolicy = "park" | "deny";
735
+ /**
736
+ * S-689 —— `deny` 政策下「无人可答」交给 core 的形:core `AskOutcome` 对象臂的**部署政策拒**
737
+ * (`settledBy:"policy"` ⇒ core 结算 `policy_refused`、`who.party:"none"`,模型读的是策略句)。
738
+ *
739
+ * 修前这里交**裸 `false`** —— 而在 core 的 onAsk 契约里裸 `false` 就是「一个人拒了」:结算记
740
+ * `human_refused` / `who.party:"person"`,模型被告知「用户不想继续,停下来等他」,run 以
741
+ * `haltedOnUserRejection` 收束。可这台部署自己声明了没有人会来 —— 拒的是它的政策。
742
+ *
743
+ * 型从 core 的 `AskOutcome` 对象臂**收窄**而不是另写一份(`settledBy` 取 core 那一格词表里的 `"policy"`:
744
+ * core 哪天退役这个词,这里编译期先红)。`reason` 必填:core 以 `policy note` 围栏把它交给模型,内容见
745
+ * {@link unattendedRefusalReason}。
746
+ */
747
+ export type UnattendedPolicyRefusal = Extract<AskOutcome, {
748
+ allow: boolean;
749
+ }> & {
750
+ allow: false;
751
+ settledBy: Extract<HostSettledBy, "policy">;
752
+ reason: string;
753
+ };
754
+ /** 「无人可答」终局的**闭集** —— core `AskOutcome` 联合里只有这两臂由 {@link ToolApprovalCoordinator.unattendedOutcome}
755
+ * 铸:park 政策的路由答 `"unavailable"`,deny 政策的 {@link UnattendedPolicyRefusal}。没有布尔臂(S-689:裸 `false`
756
+ * 是人的拒绝,这个口从不替人说话)。 */
757
+ export type UnattendedAskOutcome = Extract<AskOutcome, "unavailable"> | UnattendedPolicyRefusal;
687
758
  /**
688
759
  * [ref] 车3 刀 3b —— 「流内审批协议到底上不上场」的**单一谓词**(设计稿 §2.3 注入 / §2.4 能力面 /
689
760
  * §8.4 park 设施自检,三处同一份判据)。
@@ -1006,6 +1077,10 @@ export declare class ToolApprovalCoordinator {
1006
1077
  /**
1007
1078
  * [ref] R-13 C —— 「**无人可答**」这一类终局的**唯一**成形口(park 路由 vs deny 政策)。
1008
1079
  *
1080
+ * 终局形(S-689):park ⇒ `"unavailable"`;deny ⇒ {@link UnattendedPolicyRefusal}
1081
+ * `{allow:false, settledBy:"policy", reason}`(core 记 `policy_refused`)。**从不**交裸 `false`:那在 core 的
1082
+ * onAsk 契约里是「一个人拒了」,而本口的全部臂都是「没有人能答」。
1083
+ *
1009
1084
  * 五臂(设计稿 §1 的表)全部读它,`unattendedPolicy` 因此是一处施加、五处消费:
1010
1085
  * (a) 有店窗到期 `expireAsk` 赢 CAS / (b) 无店窗到期(D1)/ (c) 有店但 `expireAsk` 报错
1011
1086
  * —— 三条走 `windowRouteUnavailable` 标志,在 {@link shapeOutcome}(askBroadcast 内)成形;
@@ -1019,16 +1094,25 @@ export declare class ToolApprovalCoordinator {
1019
1094
  * 的终局会取决于「谁赢了那把 CAS」「重试没重试」—— 比残余更坏的不可解释性。人的**真决议**(回放出
1020
1095
  * `true`/`false`)当然不过这个口:那不是「无人可答」。
1021
1096
  *
1022
- * 🔴 **不**归它管的一类(刻意,不是遗漏):`ensureAsk` **身份未定 / 坏行**两臂 —— 那里的 park 路由是对
1023
- * **身份不确定**的处置(与「有没有人」无关),且背后可能正躺着一条真行。于是 `deny` 部署上仍可能落
1024
- * 极少数 park(店抖动期),已知且有意的残余,成文在 config-types 的域注。
1025
- *
1026
- * ⚠️ **`deny` 部署上持久行仍会经 PARKING 记账**(codex R1-F1 的另一半,验真后**不采纳**其「给 deny
1027
- * 造一条原子 deny 终态转移」的建议):那是店语义变更(新转移 + 批内兄弟连坐语义 + 真双库套件),且与
1028
- * 已裁的设计稿(§2:(a) 在 deny 下只改交给 core 的终局)相左。**危害亲验为零**:收敛器判据①的
1029
- * `bindBatch` 只把 PARKING 行绑到**已经存在的 core checkpoint** 上,而 `deny` 部署里 core 从不 park
1030
- * ⇒ 结构上绑不上,该行按判据②/④/⑤ 自行收敛成 DENIED/VOID,不会凭空生出一张 park 或幻影 gate。
1031
- * 残余 = 那类行的归因会记成 `routing_failure`(其实是政策 deny),归因精化登记为候件。
1097
+ * **`ensureAsk` 的两条兜底臂也归它管**(S-702,7.100.0 合并复审 opus 腿 E1;此前两臂直接交裸 `"unavailable"`,是这句
1098
+ * 「唯一成形口」的例外):行不可用(`persisted_row_unusable`:信封形不合 / deadline 越界)与身份不定(`ensure_indeterminate`:
1099
+ * ensure 失败且复核读全失败)。两臂的**处置**不变 —— 不编造 wire 身份、不在身份未定时呈卡收人决(fail-closed)—— 变的只是
1100
+ * 「不呈卡之后交什么」:它们同样是「这只 ask 没有人能答」,于是同样过这个口(park ⇒ `"unavailable"` 逐字不变;deny ⇒
1101
+ * 部署政策拒对象),交出去的是**结算**时再经 {@link landUnattendedOutcome} 把同一个结算落在行上。修前 deny 部署在这两形下
1102
+ * 仍 durable park(与「不积压挂起 run」的自声明相反)。
1103
+ *
1104
+ * 🔴 **`deny` 部署上政策结算当场落行**(NP-2,7.100.0 合并复审 [ref] 交叉表 #4;codex R1-F1 当年**不采纳**的那一半
1105
+ * 「给 deny 造一条原子 deny 终态转移」在这里收了):窗到期 / emit 全灭两臂在 deny 政策下的终局 claim 是
1106
+ * `refuse` 意图(政策→意图的唯一映射在 `approval-policy-settlement.ts` 的 `settleByPolicy`)—— STREAM_PENDING→DECIDED(deny) + `settled_by = "policy"`,**按 ask
1107
+ * 作用域**(不碰批、不连坐兄弟)。落的来源词与本口交给 core 的是**同一个常量**(`POLICY_REFUSAL_DECISION`),于是
1108
+ * 同 ask 重入 / 收敛后重入由 `outcomeOfDecidedRow` 读回同一个对象。当年「危害为零」的论证(PARKING 行绑不上、
1109
+ * 自行收敛成 DENIED/VOID)在 S-689 之后不再成立:首判交 `{allow:false, settledBy:"policy"}`,行停 PARKING 的回放
1110
+ * 却交裸 `false`(收敛后 DENIED 无来源)—— core 当成人拒、可停批,两次判决第一次可被观测地分家。
1111
+ * S-702 / S-706 把同一只 claim 接到了另外三处:两条兜底臂({@link landUnattendedOutcome})与崩溃恢复腿(收敛器孤儿段,
1112
+ * 它是窗到期竞争者在崩溃后的补位)—— 四处调的是**一只** `settleByPolicy`,谁也不自己挑意图。deny 部署上仍按 PARKING
1113
+ * 记账的只剩一形:别的写者(park 政策副本 / 切换政策之前)推进过的行,重入走本口(`replayed_parked`)。
1114
+ * deny 政策下批仍是**单 ask 批**(见 {@link batchIdFor}):`refuse` 本来就不碰批,单 ask 批让新行与存量整腿批行
1115
+ * 的差别只剩「批 id 是谁」,结算语义一致。
1032
1116
  */
1033
1117
  private unattendedOutcome;
1034
1118
  /** 政策**读**口(不是终局铸口)—— 回答「这台部署把无人可答翻成 park 吗」。
@@ -1037,6 +1121,14 @@ export declare class ToolApprovalCoordinator {
1037
1121
  * 纯粹的**政策查询**(`unattendedOutcome() !== false`)会和同一只 ask 的真终局各记一条遥测 ——
1038
1122
  * 「一只 ask 一条线」当场不成立。读口不落日志,铸口落;谁也不兼职。 */
1039
1123
  private get unattendedRoutesToPark();
1124
+ /**
1125
+ * 一只 ask 落在**哪只批**里 —— 批作用域随政策(S-689 codex R1-F1,判据全文见 {@link deriveAskScopedBatchId})。
1126
+ * · park 路由 ⇒ 整腿一批(`deriveBatchId`):窗到期赢家整批转投递面、兄弟连坐,core 随后 park,腿就此结束;
1127
+ * · deny 政策 ⇒ 单 ask 批:没有 park 路由,腿在一次部署政策拒之后继续跑 —— 整腿一批会让首只到期把批关掉,
1128
+ * 同腿后续的卡人批不动(`decideAsk` batch_closed ⇒ 404),兄弟还被连坐成 VOID、以裸 `false` 交 core(人拒)。
1129
+ * 读的是政策**读**口(不落遥测)。
1130
+ */
1131
+ private batchIdFor;
1040
1132
  /** {@link unattendedOutcome} 的**公开**口:`windowZero` 的 immediate-unavailable 闭包长在装配层
1041
1133
  * (`http/routes/tasks.ts` 的 sync 腿),它必须与协调器内五臂读**同一个**旋钮值,而不是各算一遍。
1042
1134
  * 出处随调用方给(那条腿知道自己是哪一只 ask)。 */
@@ -1044,7 +1136,30 @@ export declare class ToolApprovalCoordinator {
1044
1136
  taskId?: string;
1045
1137
  owner?: string | null;
1046
1138
  toolName?: string;
1047
- }): "unavailable" | false;
1139
+ }): UnattendedAskOutcome;
1140
+ /**
1141
+ * S-702 —— 两条兜底臂的「无人可答」终局的**落行**半场。交给 core 的值已由 {@link unattendedOutcome} 一处铸好,这里只回答
1142
+ * 「这条持久行上落什么」,判据是「交出去的是不是**结算**」(行 = 真源:交出去的结算必须同时是行上的结算,否则同 ask 重入 /
1143
+ * 收敛后重入回放出来的是另一个答案 —— NP-2 在 live 腿上收掉的同一种分家):
1144
+ * · park 路由(`"unavailable"`)不是结算 ⇒ 行**不动**:它留在 STREAM_PENDING,投递面由既有机器接(崩溃恢复腿按政策代打),
1145
+ * 与两臂修前逐字同形 —— park 部署行为不变;
1146
+ * · 部署政策拒(deny)是结算 ⇒ 经 {@link settleByPolicy}(live 腿 / 崩溃恢复腿同一只政策感知终态 claim)把同一个结算落在行上。
1147
+ *
1148
+ * 🔴 **只对「本次调用插下的」行调用**(调用方的义务;codex 对抗复审 F1 + R2-2 / [ref] 件2 同一条纪律「放弃收尾只许动本次插入的
1149
+ * 行」):兜底臂发生在**窗开之前** —— 一条幂等命中的 STREAM_PENDING 行此刻可能正被别的登记(另一副本 / 另一版本 / 重入)呈卡、
1150
+ * 有人正要按;当场 refuse 等于把一张活卡在它自己的窗走完之前作废。所以归属证不出(幂等命中、ensure 报错、迟到结果
1151
+ * `inserted:false`)⇒ 本方法不被调用、行不动:它的属主按自己的窗收场,属主不在了由收敛器孤儿段(同一只 claim,S-706)在
1152
+ * 窗过 + 宽限之后落同一个政策结算。`row.batchId` 恒取**行上**的批(claim 的 scope;本地派生的批可能与存量行不同,
1153
+ * 错 scope 的 claim 答 absent,不证明「行上没有决议」—— codex F1)。
1154
+ *
1155
+ * 答案处置(律 1 答案自足,与 live 腿同一个分类器 {@link classifyClaimLoss} + 同一个同 askId 分发口 {@link dispatchClaimTruth}):
1156
+ * - 赢 ⇒ 交政策拒;同 askId 的其余本地登记随行收尾(与 live 腿赢臂同形:park 路由口,deny 下它们同样成形为政策拒);
1157
+ * - 输 ⇒ 行真相:真决议 ⇒ 交它并分发给同 askId 的其余登记(codex F2:此前只交本调用方,另一条登记可按自己的店错落成相反终局);
1158
+ * 行已进投递面(别的写者推进的 PARKING/PARKED)⇒ 分发 park 路由、本调用交政策拒本身(与 `replayed_parked` 在 deny 下同答);
1159
+ * - absent / 编辑在飞 / 店抛错 ⇒ 交政策拒本身(fail-closed 方向不变);迟到回来的 claim 答案同样分发(赢 ⇒ park 路由口;输 ⇒ 真相)。
1160
+ * 本方法从不抛错(店错只进 `noteStoreError`)—— 迟到落盘行的收尾对它 fire-and-forget。
1161
+ */
1162
+ private landUnattendedOutcome;
1048
1163
  /**
1049
1164
  * [ref] 车3 刀 3b —— [ref] §3.3 / 设计稿 §0 X-2 的**写侧准入门**。
1050
1165
  *
@@ -1219,6 +1334,13 @@ export declare class ToolApprovalCoordinator {
1219
1334
  */
1220
1335
  private hasOtherSuspendedOwner;
1221
1336
  private settleSameAskIdParkRoute;
1337
+ /**
1338
+ * claim 败方真相的**同 askId 分发口**(codex [ref] R6-2 / R7-1 立在 live 腿的闭包里;S-702 codex F2 起两条兜底臂的落行半场
1339
+ * {@link landUnattendedOutcome} 也调它 —— 一个分发口,不写第二份):真相是**行**的,不是某一条登记的 ⇒ 真决议经
1340
+ * {@link notifyExternalDecision}、投递面经 {@link settleSameAskIdParkRoute} 交给同 askId 的全部本地登记;各登记的 settle 自带
1341
+ * 单赢者卫兵,对已落的恒无操作。absent / 编辑在飞没有可分发的真相。
1342
+ */
1343
+ private dispatchClaimTruth;
1222
1344
  /** [ref]:落一条 park 墓碑(容量帽按**插入序**逐出最旧,与 `allowAllSessions` 同款有界纪律)。
1223
1345
  * 调用点唯一 = `settle` 里的 park 路由支(见那处注);真终局绝不调它。
1224
1346
  *