@sema-agent/server 7.142.0 → 7.143.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 (258) hide show
  1. package/MIGRATION.md +442 -0
  2. package/USAGE.md +41 -24
  3. package/dist/adoption/plan.js +22 -0
  4. package/dist/approval-ask-audit-store.d.ts +7 -5
  5. package/dist/approval-ask-audit-store.js +12 -6
  6. package/dist/approval-ask-machine.d.ts +15 -7
  7. package/dist/approval-ask-machine.js +10 -4
  8. package/dist/approval-card.d.ts +124 -25
  9. package/dist/approval-card.js +103 -23
  10. package/dist/approval-queue-kind.d.ts +27 -0
  11. package/dist/approval-queue-kind.js +6 -0
  12. package/dist/approval-reconciler.d.ts +8 -8
  13. package/dist/approval-reconciler.js +3 -3
  14. package/dist/audit.js +4 -2
  15. package/dist/boot/budget-tracing.d.ts +1 -1
  16. package/dist/boot/governance-seams.d.ts +26 -41
  17. package/dist/boot/governance-seams.js +61 -28
  18. package/dist/boot/late-binds.d.ts +7 -4
  19. package/dist/boot/late-binds.js +3 -1
  20. package/dist/boot/leader.js +2 -4
  21. package/dist/boot/memory-consolidation.d.ts +0 -8
  22. package/dist/boot/memory-consolidation.js +3 -3
  23. package/dist/boot/reapers.js +5 -4
  24. package/dist/boot/resolve-spec.d.ts +1 -1
  25. package/dist/boot/resolve-spec.js +8 -8
  26. package/dist/boot/runner-deps.d.ts +10 -7
  27. package/dist/boot/runner-deps.js +5 -17
  28. package/dist/boot/shutdown.d.ts +9 -0
  29. package/dist/boot/shutdown.js +16 -2
  30. package/dist/boot/stage-02-web-admin-pull.js +3 -0
  31. package/dist/boot/stage-03-store-backend.d.ts +4 -1
  32. package/dist/boot/stage-03-store-backend.js +1 -2
  33. package/dist/boot/stage-04-stores.d.ts +5 -2
  34. package/dist/boot/stage-04-stores.js +3 -5
  35. package/dist/boot/stage-05-execution-env.d.ts +5 -2
  36. package/dist/boot/stage-06-runners.d.ts +5 -2
  37. package/dist/boot/stage-06-runners.js +1 -3
  38. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  39. package/dist/boot/stage-07-capability-layer.js +5 -1
  40. package/dist/boot/stage-08-reapers.d.ts +5 -2
  41. package/dist/boot/stage-09-leader.d.ts +5 -2
  42. package/dist/boot/stage-10-http-server.d.ts +5 -2
  43. package/dist/boot/stage-10-http-server.js +9 -1
  44. package/dist/boot/stores.d.ts +5 -2
  45. package/dist/boot/stores.js +7 -7
  46. package/dist/boot/web-admin.d.ts +5 -1
  47. package/dist/boot/web-admin.js +31 -19
  48. package/dist/capabilities/hands-lane.d.ts +9 -39
  49. package/dist/capabilities/hands-lane.js +8 -13
  50. package/dist/capabilities/mcp-probe.d.ts +3 -2
  51. package/dist/capabilities/scenarios.d.ts +11 -1
  52. package/dist/capabilities/scenarios.js +1 -0
  53. package/dist/capabilities/skills.d.ts +1 -17
  54. package/dist/capabilities/skills.js +0 -8
  55. package/dist/capability-facts.d.ts +8 -8
  56. package/dist/capability-facts.js +4 -4
  57. package/dist/card-void.d.ts +6 -9
  58. package/dist/config-catalog.js +1 -1
  59. package/dist/config-dir-trust.js +58 -29
  60. package/dist/config-invariants.d.ts +7 -1
  61. package/dist/config-invariants.js +7 -0
  62. package/dist/config-provider.d.ts +10 -0
  63. package/dist/config-provider.js +15 -4
  64. package/dist/config-root-migration.d.ts +13 -0
  65. package/dist/config-root-migration.js +99 -0
  66. package/dist/config-types.d.ts +5 -5
  67. package/dist/config.d.ts +4 -3
  68. package/dist/config.js +1 -1
  69. package/dist/delegated-session-owner.d.ts +5 -3
  70. package/dist/delegated-session-owner.js +1 -1
  71. package/dist/device-ws-protocol.d.ts +1 -0
  72. package/dist/device-ws-protocol.js +2 -1
  73. package/dist/env-model-table-gate.d.ts +53 -0
  74. package/dist/env-model-table-gate.js +53 -0
  75. package/dist/fleet/fleet-bus.d.ts +28 -52
  76. package/dist/fleet/fleet-bus.js +35 -100
  77. package/dist/fleet/fleet-reconciler.d.ts +4 -4
  78. package/dist/fleet/fleet-reconciler.js +1 -1
  79. package/dist/fleet/subagent-tail-bus.d.ts +14 -11
  80. package/dist/fleet/subagent-tail-bus.js +15 -28
  81. package/dist/hooks/hook-runner.js +28 -7
  82. package/dist/host-decision.d.ts +54 -20
  83. package/dist/host-decision.js +42 -14
  84. package/dist/http/admission.d.ts +1 -1
  85. package/dist/http/admission.js +7 -3
  86. package/dist/http/approval-sweeps.js +11 -8
  87. package/dist/http/caller-trust.d.ts +1 -1
  88. package/dist/http/durable-run-leg.js +2 -2
  89. package/dist/http/engine-refusal.d.ts +16 -0
  90. package/dist/http/engine-refusal.js +17 -0
  91. package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
  92. package/dist/http/memory-compliance-failure-reply.js +4 -6
  93. package/dist/http/owner-access.d.ts +11 -0
  94. package/dist/http/owner-access.js +13 -0
  95. package/dist/http/resume-legs.d.ts +21 -7
  96. package/dist/http/resume-legs.js +71 -49
  97. package/dist/http/resume-restatement.d.ts +39 -0
  98. package/dist/http/resume-restatement.js +25 -0
  99. package/dist/http/route-ctx.d.ts +35 -10
  100. package/dist/http/route-ctx.js +1 -1
  101. package/dist/http/routes/approvals-assistant.d.ts +9 -1
  102. package/dist/http/routes/approvals-assistant.js +142 -31
  103. package/dist/http/routes/capabilities.js +11 -2
  104. package/dist/http/routes/memory-policy.d.ts +2 -2
  105. package/dist/http/routes/memory-policy.js +1 -1
  106. package/dist/http/routes/notify-wake.js +23 -25
  107. package/dist/http/routes/rules.js +48 -13
  108. package/dist/http/routes/runs.js +9 -8
  109. package/dist/http/routes/session-memory-sync.d.ts +34 -6
  110. package/dist/http/routes/session-memory-sync.js +27 -10
  111. package/dist/http/routes/session-sync.js +13 -20
  112. package/dist/http/routes/sessions.d.ts +2 -2
  113. package/dist/http/routes/sessions.js +22 -23
  114. package/dist/http/routes/tasks.js +27 -49
  115. package/dist/http/server.d.ts +13 -7
  116. package/dist/http/server.js +2 -2
  117. package/dist/http/stored-body-replay.js +15 -4
  118. package/dist/http/wire-types.d.ts +17 -7
  119. package/dist/leader/leader.js +5 -2
  120. package/dist/leader/wire.d.ts +7 -1
  121. package/dist/leader/wire.js +6 -5
  122. package/dist/leg-facts.d.ts +37 -0
  123. package/dist/leg-facts.js +15 -0
  124. package/dist/memory-bundle-engine.d.ts +1 -4
  125. package/dist/memory-bundle-engine.js +2 -2
  126. package/dist/memory-operator-faces.d.ts +30 -66
  127. package/dist/memory-operator-faces.js +17 -88
  128. package/dist/memory-scope-stores.d.ts +38 -40
  129. package/dist/memory-scope-stores.js +51 -36
  130. package/dist/memory-scope.d.ts +0 -9
  131. package/dist/memory-scope.js +0 -9
  132. package/dist/memory-sync-client.js +14 -3
  133. package/dist/memory-sync.d.ts +20 -4
  134. package/dist/memory-sync.js +23 -4
  135. package/dist/model-plane-face.d.ts +13 -7
  136. package/dist/model-plane-face.js +2 -1
  137. package/dist/observability/fail-open.d.ts +20 -4
  138. package/dist/observability/fail-open.js +17 -4
  139. package/dist/observability/run-terminal.js +4 -0
  140. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
  141. package/dist/orchestration/workflow-completion-inbox.js +0 -12
  142. package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
  143. package/dist/orchestration/workflow-park-decision.d.ts +8 -3
  144. package/dist/orchestration/workflow-park-decision.js +5 -3
  145. package/dist/org-delivery-gate.d.ts +11 -0
  146. package/dist/org-delivery-gate.js +19 -1
  147. package/dist/parked-decide.d.ts +13 -9
  148. package/dist/parked-decide.js +7 -7
  149. package/dist/parked-revive-surface.js +1 -1
  150. package/dist/peer-inbound-face.d.ts +127 -0
  151. package/dist/peer-inbound-face.js +158 -0
  152. package/dist/permission-rule-list.d.ts +13 -9
  153. package/dist/permission-rule-list.js +7 -3
  154. package/dist/plugins/approval-ask-store-file.js +18 -6
  155. package/dist/plugins/approval-ask-store-memory.js +8 -6
  156. package/dist/plugins/approval-ask-store-sql.d.ts +28 -13
  157. package/dist/plugins/approval-ask-store-sql.js +30 -11
  158. package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
  159. package/dist/plugins/checkpoint-store-sql.js +9 -7
  160. package/dist/plugins/file-history-store-sql.d.ts +24 -18
  161. package/dist/plugins/file-history-store-sql.js +24 -19
  162. package/dist/plugins/file-run-store.d.ts +29 -0
  163. package/dist/plugins/file-run-store.js +97 -8
  164. package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
  165. package/dist/plugins/imported-layer-root-retirement.js +96 -0
  166. package/dist/plugins/local-checkpoint-store.d.ts +1 -1
  167. package/dist/plugins/local-checkpoint-store.js +2 -2
  168. package/dist/plugins/local-session-store.d.ts +6 -2
  169. package/dist/plugins/local-session-store.js +8 -2
  170. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
  171. package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
  172. package/dist/plugins/mailbox-store-sql.d.ts +12 -8
  173. package/dist/plugins/mailbox-store-sql.js +76 -7
  174. package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
  175. package/dist/plugins/memory-sync-store-pg.js +21 -0
  176. package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
  177. package/dist/plugins/memory-sync-store-tidb.js +13 -1
  178. package/dist/plugins/one-time-migrations.d.ts +32 -2
  179. package/dist/plugins/one-time-migrations.js +106 -3
  180. package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
  181. package/dist/plugins/org-delivery-quota-store.js +2 -12
  182. package/dist/plugins/park-commit-watch.d.ts +1 -1
  183. package/dist/plugins/permission-rule-store-file.d.ts +10 -1
  184. package/dist/plugins/permission-rule-store-file.js +15 -2
  185. package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
  186. package/dist/plugins/permission-rule-store-sql.js +35 -2
  187. package/dist/plugins/remote-env-device.d.ts +8 -11
  188. package/dist/plugins/remote-env-device.js +6 -3
  189. package/dist/plugins/remote-env-k8s.d.ts +37 -24
  190. package/dist/plugins/remote-env-k8s.js +50 -17
  191. package/dist/plugins/retention-store-sql.d.ts +2 -2
  192. package/dist/plugins/sandbox-read-floor.d.ts +5 -7
  193. package/dist/plugins/sandbox-read-floor.js +2 -7
  194. package/dist/plugins/sql-errors.d.ts +10 -1
  195. package/dist/plugins/sql-errors.js +13 -0
  196. package/dist/plugins/store-backend.d.ts +23 -28
  197. package/dist/plugins/store-backend.js +9 -1
  198. package/dist/plugins/store-contracts.d.ts +29 -5
  199. package/dist/plugins/store-contracts.js +4 -1
  200. package/dist/plugins/task-attachment-store.d.ts +2 -2
  201. package/dist/plugins/task-attachment-store.js +37 -52
  202. package/dist/plugins/tool-result-store-sql.d.ts +9 -8
  203. package/dist/plugins/tool-result-store-sql.js +23 -2
  204. package/dist/plugins/wiring-section-codec.d.ts +32 -0
  205. package/dist/plugins/wiring-section-codec.js +55 -0
  206. package/dist/plugins/workspace-fill.d.ts +1 -1
  207. package/dist/rule-entry-list.d.ts +3 -2
  208. package/dist/rule-entry-list.js +5 -1
  209. package/dist/rules-consent.d.ts +28 -5
  210. package/dist/rules-consent.js +40 -28
  211. package/dist/run-local.js +9 -5
  212. package/dist/runs.d.ts +12 -8
  213. package/dist/runs.js +6 -7
  214. package/dist/runtime-governance.d.ts +1 -1
  215. package/dist/server-secret-env.d.ts +4 -0
  216. package/dist/session-error-wire.d.ts +12 -0
  217. package/dist/session-error-wire.js +6 -0
  218. package/dist/session-incarnation.d.ts +1 -1
  219. package/dist/session-notify-door.d.ts +106 -0
  220. package/dist/session-notify-door.js +93 -0
  221. package/dist/session-sync.d.ts +9 -14
  222. package/dist/session-sync.js +5 -5
  223. package/dist/session-workspace.d.ts +3 -13
  224. package/dist/session-workspace.js +0 -9
  225. package/dist/standing-answer-grant.d.ts +5 -0
  226. package/dist/standing-answer-grant.js +10 -0
  227. package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
  228. package/dist/stores-sql/session-policy-store-sql.js +3 -13
  229. package/dist/task-mcp.d.ts +1 -1
  230. package/dist/task-settings.d.ts +11 -8
  231. package/dist/task-settings.js +31 -11
  232. package/dist/tool-approval.d.ts +52 -34
  233. package/dist/tool-approval.js +66 -57
  234. package/dist/trace/core-keyset-guard.d.ts +11 -8
  235. package/dist/trace/engine-notice-wire.d.ts +1 -1
  236. package/dist/trace/engine-notice-wire.js +3 -1
  237. package/dist/trace/exit-seat.d.ts +7 -1
  238. package/dist/trace/exit-seat.js +1 -0
  239. package/dist/trace/ledger-sink.d.ts +2 -2
  240. package/dist/trace/model-segment.d.ts +55 -25
  241. package/dist/trace/model-segment.js +101 -33
  242. package/dist/trace/project.d.ts +7 -4
  243. package/dist/trace/project.js +6 -0
  244. package/dist/trace/redact.d.ts +61 -9
  245. package/dist/trace/redact.js +1490 -468
  246. package/dist/trace/self-minted-wire.d.ts +510 -38
  247. package/dist/trace/self-minted-wire.js +165 -17
  248. package/dist/trace/wire-projection-faces.d.ts +1 -1
  249. package/dist/trace/wire-projection-faces.js +1 -1
  250. package/dist/verifier-pause-card.d.ts +33 -5
  251. package/dist/verifier-pause-card.js +15 -10
  252. package/dist/web-admin-client/apply-effective.d.ts +12 -16
  253. package/dist/web-admin-client/apply-effective.js +90 -10
  254. package/dist/workspace-space.d.ts +19 -3
  255. package/dist/workspace-space.js +8 -4
  256. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
  257. package/package.json +3 -2
  258. package/wire-changes/server@7.143.0.json +1167 -0
@@ -1,5 +1,5 @@
1
1
  import type { ExecutionLane } from "./execution-lane-caps.js";
2
- import { type ApprovalDecidedBy, type HostSettledBy, type RetiredDecisionKeyFacts } from "./host-decision.js";
2
+ import { type ApprovalDecider, type HostSettledBy, type HostSource, type RetiredDecisionKeyFacts } from "./host-decision.js";
3
3
  import type { IncomingMessage } from "node:http";
4
4
  import { type AskClass, type AskRequest, type AskOutcome, type PermissionResult, type CheckpointGate, type PendingAction, type PersistedRuleMandate, type ReadRootGrantCandidate, type RuleOffer, type AutoModeFallbackCause, type BoundGrantAbsence, type BoundSkillGrants, type ToolApprovalCard, type ReopenReason } from "@sema-agent/core";
5
5
  import { type CardRulePersisted, type RuleConsentLane } from "./rules-consent.js";
@@ -78,7 +78,7 @@ export type ToolApprovalReadBody = ({
78
78
  } & AskRowReadProjection);
79
79
  /**
80
80
  * 结算一张卡的**判决** —— 判别联合,逼每个调用点说清「这次等待是怎么结束的」:
81
- * · `by:"human"` —— 一次**决议**到了(人答,或从问账行读回来的决议,含部署政策拒落成的 `DECIDED` 行,`hostSettledBy` 记它的来源词):`allowed` 说方向;审计 settle 行
81
+ * · `by:"human"` —— 一次**决议**到了(人答,或从问账行读回来的决议,含部署政策拒落成的 `DECIDED` 行,`hostSource` 记它的来源词与机器座位):`allowed` 说方向;审计 settle 行
82
82
  * `outcome` = `allowed` / `denied`,**没有 `cause`**;
83
83
  * · `by:"system"` —— 这次等待**没有等到决议就结束了**(非人结局):必须点名一个 {@link SettleCause};审计 settle 行 `outcome:"expired"` + 该 `cause`。
84
84
  * 成因**只从事实读**(窗钟到 / 中止信号 / emit 零接收 / 腿作用域退出 / 兄弟被原子撤卡 / 有序关停锁存位 / 问账行的列),不从拒句散文判;
@@ -88,14 +88,14 @@ export type SettleVerdict = {
88
88
  readonly by: "human";
89
89
  readonly allowed: boolean;
90
90
  readonly updatedInput?: unknown;
91
- /** 宿主自报来源(见 {@link HostSettledBy};缺席 = 人)。 */
92
- readonly hostSettledBy?: HostSettledBy;
91
+ /** 宿主自报来源(`AskOutcome` 的 `settledBy` / `decidedVia` 一只值,见 {@link HostSource};缺席 = 人)。 */
92
+ readonly hostSource?: HostSource;
93
93
  readonly denyReason?: string;
94
94
  readonly readRootGrant?: string;
95
95
  } | {
96
96
  readonly by: "system";
97
97
  readonly cause: SettleCause;
98
- readonly hostSettledBy?: HostSettledBy;
98
+ readonly hostSource?: HostSource;
99
99
  };
100
100
  /**
101
101
  * 🔴 [ref](案A)追记 F6 —— durable 回决口(`POST /v1/tasks/:taskId/asks/:askId/decision`)的 **200 体
@@ -139,10 +139,10 @@ export interface ParkedAskRedeemRequest {
139
139
  decision: "approve" | "deny";
140
140
  /** [ref] 同源的人写理由(deny 时 core 把它交给模型;allow 只进审计面)。 */
141
141
  note?: string;
142
- /** [ref]:决定体的**出处位**(已过 `readDecidedBy` 的 wire 词,缺席已落成 `"person"`),经 `hostDecisionFacts` 落到停驻座的
142
+ /** [ref]:决定体的**出处位**(已过 `readDecider` 的 wire 词,缺席已落成 `"person"`),经 `hostDecisionFacts` 落到停驻座的
143
143
  * `hostDecision.decidedBy`。live 命中臂与本 PARKED 臂读**同一格** —— 同一份体落在哪条臂上只取决于副本与时序;两臂各走自己座的
144
- * 那一只映射(live = `liveSettledBy`,停驻 = 恒等),词表只有一份。 */
145
- decidedBy: ApprovalDecidedBy;
144
+ * 那一只映射(live = `liveHostSource`,停驻 = 恒等),词表只有一份。 */
145
+ decider: ApprovalDecider;
146
146
  /** [ref] ctrl+g 编辑放行的实参整体替换(approve 才有意义)。 */
147
147
  updatedInput?: unknown;
148
148
  /** 发起本次 respond 的**已验证**调用方(live 腿 `gatedPrincipal` 的那一把)。席在赎回之前拿它与
@@ -362,7 +362,12 @@ export interface ToolApprovalFrame {
362
362
  * [ref] MED-1 后不再是判别式,core JSDoc 钉明「不是子代判别键」)。值 = 子代的 core session id
363
363
  * (与 task_progress.taskId / bg_notification.sessionId 同值域,可关联子代行)。旧壳(< fromSubagent
364
364
  * 接线)兜底按在场性渲染归属标仍然正确。 */
365
- sourceTaskId?: string;
365
+ sourceSessionId?: string;
366
+ /** core 7.61.0:发起这一问的委派腿的 agent id(后台子代 = 注册表行 id `a…`;前台子代 = 它的会话 id)—— **在场即委派事实**(直接起跑的
367
+ * workflow 的 agent 带它而不带 `fromSubagent`),宿主的问缺席。消费方按它把审批归到后台行(一个键相等)。 */
368
+ agentId?: string;
369
+ /** core 7.61.0:谁问的、为什么问(`readAskReasons` 窄读;卡与运维队列行同一只读口)。结构化审批面按它渲理由行,`message` 照旧逐字给只读文本的消费方。 */
370
+ askReasons?: readonly import("./approval-card.js").AskReasonProjection[];
366
371
  /** [ref] [ref]②:core 1.378 显式判别键——委派子代 gate 发起的 ask 恒带 `true`,受信 internals 事实
367
372
  * (worker 不可自造/不可抑制)。取代 [ref] MED-1 的「在场 ∧ ≠ 宿主 sessionId」权宜判别式。 */
368
373
  fromSubagent?: true;
@@ -418,9 +423,10 @@ export interface ToolApprovalFrame {
418
423
  * 🔴 **真才带,缺席绝不编 `false`**(`governanceForced` / `requiresRealApproval` 同形)。缺席覆盖「不是强制」「老引擎」
419
424
  * 两形。**本仓从不自铸本键**:活卡帧(与 `livePending` 行顶层,T4①)只读 `AskRequest.mandated`;耐久面(运维队列行 / inbox 行)
420
425
  * 自 core 7.31.0 [ref] 起读 core 在 park 行上铸的孪生座(`PendingAction.tool_approval.mandated` / `CheckpointSummary.mandated`,
421
- * [ref] 二段),同样只投 core 给的那一位 —— 自铸一个就是本仓成了这个事实的第二个源。⚠️ **`card_json` 卡面不带本键**
422
- * (`ApprovalCardSchema` 没有这一位,`.strict()`)⇒ 断连重放的 `approval_request` 帧(`buildReplayFrame` 只回放卡)上它恒缺席,
423
- * 消费方读队列行 / 活卡帧 / `livePending` 行(8D-6:此前这里写的「`card_json` 只读 `AskRequest.mandated`」是错句,T4② 车OC 改真)。
426
+ * [ref] 二段),同样只投 core 给的那一位 —— 自铸一个就是本仓成了这个事实的第二个源。⚠️ **`card_json` 的卡面不带本键**
427
+ * (`ApprovalCardSchema` 没有这一位,`.strict()`);7.143.0 起卡信封旁的活面事实座(`liveFacts`)存着呈卡帧上同一位(同一只帧对象挑出,不是自铸)
428
+ * ⇒ 断连重放的 `approval_request` 帧与活铸帧同值;本版之前铸的行没有那一座 ⇒ 重放帧带 `liveFactsUnknown`(8D-6:此前这里写的
429
+ * 「`card_json` 只读 `AskRequest.mandated`」是错句,T4② 车OC 改真)。
424
430
  * 🔴 **server 不判「是不是强制」**(判定属主在 core 的闸站),只**读**闸站盖好的这一位 —— 读者恰一个:
425
431
  * [ref] 起的会话级放行判据 {@link standingAnswerHome}(会话授权是**上一次**应答记下的站着的答案,
426
432
  * 不是对这一次调用的应答 ⇒ 强制卡上既不被既有 grant 代答、也不铸 grant)。上一段「一揽子 `onAsk:"allow"`
@@ -481,7 +487,7 @@ export interface ToolApprovalFrame {
481
487
  * `{ kind: "extension", name }`,卡上「扩展 X 想跑 …」那一行的出处。模型消息带来的调用上缺席。display 事实,不是裁决输入。
482
488
  * 读法与 `tool_start` / `tool_end` 上的同名键是同一只(`trace/extension-call-face.ts`:注册名过注册方文本的出口纪律,与 `wiring_manifest.mods[]` 的 `name`
483
489
  * 逐字节同;形不对 ⇒ 丢 + 计一次)。呈卡腿上它是 `approval_request` 顶层的卡外座之一(`APPROVAL_REQUEST_LIVE_FACT_KEYS`,同一只帧对象的值);
484
- * ⚠️ `card_json` 卡面不带本键(卡的键集属主在契约包),断连重放帧上它恒缺席(与其余卡外座同)。
490
+ * ⚠️ `card_json` 卡面不带本键(卡的键集属主在契约包);7.143.0 起卡信封的活面事实座同存一份 ⇒ 断连重放帧与活铸帧同值(与其余卡外座同)。
485
491
  */
486
492
  requestedBy?: ExtensionRequesterFace;
487
493
  /**
@@ -540,9 +546,11 @@ export interface ToolApprovalFrame {
540
546
  * 把提议的根放回读边界又走了一遍才递出来,下游再判一遍就是同一事实的第二个判官(与 `origin` /
541
547
  * `denialLimitFallback` 两条顶注的同一条禁令)。
542
548
  *
543
- * 🔴 **只此一面**:core 的负控逐字写着「the durable park row has no twin of this seat in this version」——
544
- * 一只 PARKED 的根外读 ask 渲的仍是单独那张确认卡。所以 `card_json` / 耐久面**没有**这一座,本仓也不
545
- * 自铸一个(自铸 = 同一事实的第二个源,而且那个源会在 park 兑现时说谎)。
549
+ * 🔴 **停驻面没有孪生**:core 的负控逐字写着「the durable park row has no twin of this seat in this version」——
550
+ * 一只 PARKED 的根外读 ask 渲的仍是单独那张确认卡。所以停驻行 / 运维队列行 / inbox 行**没有**这一座,本仓也不
551
+ * 自铸一个(自铸 = 同一事实的第二个源,而且那个源会在 park 兑现时说谎)。问行卡信封的活面事实座(7.143.0)不是自铸:
552
+ * 它是呈卡帧上这一格的同一份值、同一条写落下,只供同一只还在流上的问的重放帧读(断流续读 / 开流 preamble),
553
+ * 射程与卡上 `ruleOffers` 同一句(回授经重放帧自己的 `approvalId` 走活应答口)。
546
554
  */
547
555
  readRootCandidate?: ReadRootGrantCandidate;
548
556
  /**
@@ -689,7 +697,8 @@ export interface ToolApprovalFrame {
689
697
  *
690
698
  * 🔴 **在场才带**(缺席绝不编空串;缺席 ≠「没有原因」);窄读单点 = `approval-card.ts` 的 `readProbeReason`
691
699
  * (非串 / 空白 ⇒ 缺席;超信封 ⇒ **整只丢不截**;内容族 ⇒ 脱敏,与耐久面同一规则 ⇒ 对同一句话两面同值)。
692
- * 🔴 **只在本帧上**:呈卡帧 / `card_json` 不携它(`ApprovalCardSchema` 是 `.strict()` 的耐久信封,加键要另行裁定)。
700
+ * 🔴 **不在卡上**:`ApprovalCardSchema`(`.strict()`)没有它;呈卡帧 `approval_request` 顶层带它(活面事实座),7.143.0 起卡信封的
701
+ * `liveFacts` 座同存一份 ⇒ 断连重放帧与活铸帧同值。
693
702
  * 🔴 **展示 / 分诊元数据,永不是裁决输入**;永不进 `message`(那是分类器 / 模型的输入面)。
694
703
  * `\p{Cf}` 展示重排类字符(方向 / 零宽标记):core 在这个座上**不剥**(同值契约下 core 自己披露的残余,[ref]);本仓脱敏器
695
704
  * (`redactSecrets`)入口剥全部 `\p{Cf}`(7.70.0 起),活卡帧与耐久面**都过它** ⇒ 两面同值、且都是剥后字节(`test/approval-probe-reason-wire.test.ts` 钉)。
@@ -767,23 +776,30 @@ export interface LivePendingRow {
767
776
  requiresRealApproval?: true;
768
777
  governanceForced?: true;
769
778
  /** T4①(八病审计 8D-5,车OC / 7.101.0):强制位([ref],`AskRequest.mandated`)—— 与上两位**同层同形**(真才带,缺席不编 false),
770
- * 值 = 条目上那一位(`askBroadcast` 铸条目时取自这一次过闸的 `req.mandated`,与 {@link frame} 上的同名键同源)。此前只在
771
- * `frame` 里:同一个 `GET /v1/approvals` 响应的 durable `pending[]` 行顶层带它([ref] 二段),live 行却要进帧里读。 */
779
+ * 值 = 内嵌帧 {@link frame} 上的同名键(同一个值,不另读;7.143.0 起):活登记 = 这只问的活铸帧;接管登记 = 从问行卡信封回读的重放帧
780
+ * (行上记着才在,存量行缺席并带 {@link liveFactsUnknown})。此前只在 `frame` 里:同一个 `GET /v1/approvals` 响应的 durable `pending[]` 行顶层
781
+ * 带它([ref] 二段),live 行却要进帧里读。 */
772
782
  mandated?: true;
773
783
  /** 7.116.0(审计修复批 S4):这张卡上的「本会话放行」不会被记住 —— 与 {@link ToolApprovalFrame.rememberRefused} 同名同义同源
774
784
  * (同一只判据,读条目上的四位事实);真才带。 */
775
785
  rememberRefused?: true;
776
- /** [ref](core 7.32.0 [ref]):强制位站在哪一个词上 —— 与 `mandated` 同层同形(在场逐字,缺席不编词),值 = 条目上那一个词
777
- * (与 {@link frame} 上同名键同源;帧型该键顶注是全文)。 */
786
+ /** [ref](core 7.32.0 [ref]):强制位站在哪一个词上 —— 与 `mandated` 同层同形(在场逐字,缺席不编词),值 = 内嵌帧 {@link frame} 上的同名键
787
+ * (读法同 `mandated`;帧型该键顶注是全文)。 */
778
788
  mandate?: PersistedRuleMandate;
779
789
  /** [ref](cli [ref] / [ref]):ask 的**出身词**(谁提的这一问,core `ASK_ORIGINS` 闭集一词)—— 与 `mandate` 同层同形(在场逐字,
780
- * 缺席不编词),值 = 条目上那一个词(铸条目那一次与 {@link frame} 上同名键**同一次**读定;帧型该键顶注是全文)。同一个
790
+ * 缺席不编词),值 = 内嵌帧 {@link frame} 上的同名键(读法同 `mandated`;帧型该键顶注是全文)。同一个
781
791
  * `GET /v1/approvals` 响应里 durable `pending[]` 行的 `origin` 也在顶层(park 行孪生座),两族行同一种读法。 */
782
792
  origin?: string;
793
+ /**
794
+ * 7.143.0:**这一行的活面事实不在问行上** —— 与内嵌帧 {@link frame} 上的同名标记位同值(`ApprovalRequestFrame.liveFactsUnknown`,只读那一格)。
795
+ * 只有接管登记会带(行是本版之前铸的,卡信封上没有活面事实座;或那一座读不出):这时顶层的 `mandated` / `mandate` / `origin` 缺席的意思是「不知道」,
796
+ * 不是「不强制 / 没有出身」—— 消费方按不知道读(强制与否不知道 ⇒ 按强制)。活登记恒不带(活铸帧上恒有事实);只记真。
797
+ */
798
+ liveFactsUnknown?: true;
783
799
  /** 发起者为委派子代(originTaskId 在场)。 */
784
800
  fromSubagent?: true;
785
801
  /** [ref] C2(additive):委派子代的 **canonical taskId**。值域精确成文(codex R1-F3 问询后按 core dist
786
- * 亲证):值 = `AskRequest.sourceTaskId` = 发起 task 的 sessionId(core prepare-task `askSourceIdentity`);
802
+ * 亲证):值 = `AskRequest.sourceSessionId` = 发起 task 的 sessionId(core prepare-task `askSourceIdentity`);
787
803
  * 而 core 的 canonical taskId = `spec.taskId ?? sessionId`(runtask.js `runSourceTaskId`),Runner 铸的
788
804
  * 委派子代 spec **不带** taskId ⇒ 子代 canonical taskId ≡ 子代 sessionId ≡ 本键 ≡
789
805
  * `task_progress.taskId`(同一 `runSourceTaskId` 铸)—— 关联 join 在本键存在的唯一面(`fromSubagent`
@@ -878,7 +894,7 @@ interface ToolApprovalRunContextBase {
878
894
  abortSignal?: AbortSignal;
879
895
  /** [ref]([ref] §3.1 askId 派生的腿轴;车3 刀 3a 换轴:原 `leg?: number` → `legKey?: string`)。
880
896
  * = `sha256(resume checkpoint token)` 的 hex,**首腿缺席折空串**(空串是首腿的真值,不是「未知」)。
881
- * 与 `ToolApprovalRunContext.taskId`(= 派生里的 `runId` 轴)一起,使同一 `(sourceTaskId, toolCallId)`
897
+ * 与 `ToolApprovalRunContext.taskId`(= 派生里的 `runId` 轴)一起,使同一 `(sourceSessionId, toolCallId)`
882
898
  * 在不同 run / 不同 resume 腿下铸出不同持久行(不会被上一腿或上一 run 已终结的行绊住)。
883
899
  * 换轴动机与残留边界见 `approval-ask-machine.ts` 的 `deriveAskId` 头注。
884
900
  * 真值由装配点(刀 3b)供给,本刀只立形 + 折空串兜底。 */
@@ -981,7 +997,7 @@ type ParsedToolApproval = {
981
997
  updatedInput?: unknown;
982
998
  persistRule?: ParsedPersistRule;
983
999
  note?: string;
984
- decidedBy: ApprovalDecidedBy;
1000
+ decider: ApprovalDecider;
985
1001
  readRootGrant?: string;
986
1002
  };
987
1003
  /**
@@ -1274,7 +1290,7 @@ export declare function approvalPreambleReplays(input: Omit<ApprovalLegInput, "n
1274
1290
  * 从定义上不是「投递面拿走了它」)。{@link ToolApprovalCoordinator.notifyExternalDecision} 收的就是它。 */
1275
1291
  export type DecidedAskOutcome = Exclude<AskOutcome, "unavailable">;
1276
1292
  /** 铸点的入参形 = 行上与**这条决议本身**有关的三格。整行(`AskRow`)与 claim 败方读数都满足。 */
1277
- type DecidedRowFacts = Pick<AskRow, "decision" | "settledBy"> & {
1293
+ type DecidedRowFacts = Pick<AskRow, "decision" | "settledBy" | "decidedVia"> & {
1278
1294
  updatedInput?: unknown;
1279
1295
  };
1280
1296
  /**
@@ -1326,11 +1342,11 @@ export declare class ToolApprovalCoordinator {
1326
1342
  /** [ref] 车2(codex 交叉复审 round3 抓获真 finding,round5 精化成 Set):次级索引,键 = 持久层 askId
1327
1343
  * (与 {@link pending} 的 wire-面 uuidv7 `id` 是两条独立的身份轴,顶注同精神)——只在 askStore 在场且
1328
1344
  * 这只 ask 真有 askId 时才登记。**同一 askId 下可能同时挂着不止一条本地条目**(round5 抓获:
1329
- * `ensureAsk` 是幂等 upsert,若 core 对同一 (sourceTaskId,runId,toolCallId,legKey) 真发起过两次并发调用——如
1345
+ * `ensureAsk` 是幂等 upsert,若 core 对同一 (sourceSessionId,runId,toolCallId,legKey) 真发起过两次并发调用——如
1330
1346
  * 重试/failover 场景,round4 finding2 的顶注同源——两次 `askBroadcast` 各自的调用栈都会在行仍是
1331
1347
  * STREAM_PENDING 时各自注册一条独立的本地 pending 条目,值形若是单值 Map 会被后到者覆盖前者的登记,
1332
1348
  * 前者从此再也没有任何本地事件会驱动它 settle),故值形是 `Set`,不是单个 `PendingApproval`。
1333
- * 存在理由(两类真实成因共用同一套修复):①同一批(相同 sourceTaskId+leg)下若有多只**不同** ask 并发
1349
+ * 存在理由(两类真实成因共用同一套修复):①同一批(相同 sourceSessionId+leg)下若有多只**不同** ask 并发
1334
1350
  * 在飞(不同 toolCallId,同一 batchId),`expireAsk` 赢家的同一次持久事务会把批内其余 STREAM_PENDING
1335
1351
  * 兄弟原子撤成 VOID 并把它们的 askId 列在 `voidedSiblings` 里;②同一 askId 的**重复本地注册**(见上)。
1336
1352
  * 两类情形下,那些"没赢"的本地条目各自独立的 timer/settle 闭包都对"这只 askId 其实已经有了终局"一无
@@ -2241,8 +2257,8 @@ export declare class ToolApprovalCoordinator {
2241
2257
  adoptOpenAsks(): Promise<OpenAskAdoption>;
2242
2258
  /**
2243
2259
  * [ref]:由一条待决行铸一条接管登记并放进活集合(唯一铸点;读法见 {@link AdoptedRegistrationPart})。事实全部取自行与行上的卡:属主 / 会话(adhoc 替身
2244
- * = taskId 时不投,与按问读口的行投影同读)/ 子代出身(卡 `fromSubagent` ⇒ 行 `sourceTaskId`)/ 窗死线 / 铸造时刻取行;工具名、要人位、治理位、类集取卡;
2245
- * 授予绑定卡上没有 ⇒ `unreadable`(于是站着的答案判据答 `none`:`rememberRefused`,`allow_session` 只放行这一次 —— 既有律);规则素材不在 ⇒ `persistRule`
2260
+ * = taskId 时不投,与按问读口的行投影同读)/ 子代出身(卡 `fromSubagent` ⇒ 行 `sourceSessionId`)/ 窗死线 / 铸造时刻取行;工具名、要人位、治理位、类集取卡;
2261
+ * 强制位 / 强制词 / 出身词取重放帧顶层(= 信封事实座,7.143.0;存量行缺席);授予绑定按 `unreadable` 读(于是站着的答案判据答 `none`:`rememberRefused`,`allow_session` 只放行这一次 —— 既有律);规则素材不在 ⇒ `persistRule`
2246
2262
  * 答 `rule_lane_unavailable`(晚答腿同一个词)。卡面的 `rememberRefused` 与条目同一只判据(活登记那一处的同一条纪律)。
2247
2263
  */
2248
2264
  private registerAdopted;
@@ -2262,11 +2278,13 @@ export declare class ToolApprovalCoordinator {
2262
2278
  * [ref]:某只委派子代此刻有没有**待决**的活卡 —— fleet 对账腿「子代活性由属主说了算」的属主②读口(另一只是
2263
2279
  * bg registry 账)。子代卡在一张没人答的卡上时当然不出帧,只看「静默」就会把它当孤儿扫下面板(报案的真形)。
2264
2280
  * 只答是非、不交出 Map(与 `isRunLiveOnThisReplica` 同姿势);纯读,零锁零结算语义。
2265
- * 键 = ask 发起者域(`originTaskId` = core `AskRequest.sourceTaskId` = 子代自己的 core session id),**不是**
2266
- * fleet 行 id —— 换算在 `FleetEventBus.childOwnerKeys`。只看本副本的内存登记:子代跑在本副本,它的活卡就登记在
2267
- * 本副本;耐久 park 的卡由 bg registry 的 `parked` 态作保(见 fleet-reconciler.ts `bgAgentVouches`)。
2281
+ * 入参 = 一条腿的名字(fleet 行 → 名字的换算在 `FleetEventBus.childOwnerKeys`);活卡帧上带着发起腿的名字:`agentId`(core 7.61.0:
2282
+ * 委派腿的腿 task id —— 后台子代 = 它的注册表行 id;前台子代 = 它的会话 id;workflow agent = 脚本声明的 task id,否则会话 id;在场即委派事实,
2283
+ * 直接起跑的 workflow 的 agent 带它而不带 `fromSubagent`;宿主的问缺席),委派子代的问另带发起会话 `sourceSessionId`(帧上只出委派子代的问)。
2284
+ * 任一个落在入参里 ⇒ 这一问是那条腿的。只看本副本的内存登记:子代跑在本副本,它的活卡就登记在本副本;耐久 park 的卡由 bg registry 的
2285
+ * `parked` 态作保(见 fleet-reconciler.ts `bgAgentVouches`)。
2268
2286
  */
2269
- hasLivePendingFrom(originTaskId: string): boolean;
2287
+ hasLivePendingFromLeg(names: readonly string[]): boolean;
2270
2288
  /**
2271
2289
  * 🔴 [ref](案A)追记 F4 —— **跨副本决议的执行通知**(悬挂行的一次终态轮询)。
2272
2290
  *
@@ -1,5 +1,5 @@
1
1
  import { readApprovalCard } from "./approval-content-kind.js";
2
- import { heldAskOf, liveSettledBy, readDecidedBy, retiredDecisionKeyFacts, DECIDED_BY_OUTSIDE_CLOSED_SET, POLICY_CANNOT_ALLOW_PERSON_ASK } from "./host-decision.js";
2
+ import { heldAskOf, liveHostSource, readDecider, retiredDecisionKeyFacts, POLICY_CANNOT_ALLOW_PERSON_ASK } from "./host-decision.js";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { uuidv7, classifyAsk, foldArbitrationRow, policyCannotAnswer, screenAskClassMembers, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, parseRuleText, pathConfinableWriteToolNames } from "@sema-agent/core";
5
5
  import { precheckCardRuleText } from "./rules-consent.js";
@@ -12,14 +12,14 @@ import { createLogger } from "./observability/logger.js";
12
12
  import { errorKindOf } from "./observability/err-text.js";
13
13
  import { recordFailOpen } from "./observability/fail-open.js";
14
14
  import { ownerOfCheckpointScope } from "./security.js";
15
- import { deriveAskId, deriveAskScopedBatchId, deriveBatchId, MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt } from "./approval-ask-machine.js";
16
- import { currentParkArm, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildReplayFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readProbeReason, readReadRootCandidate, readStoredCardEnvelope, readRuleEvidence, readAllowRuleShadowed, readRuleOffersAbsence, readRuleOffersAbsenceSeat, readParkRowTrueSeat, readAskClassPair, readClosedWordSeat, buildApprovalCompleteFrame, readRuleOfferList, } from "./approval-card.js";
15
+ import { deriveAskId, deriveAskScopedBatchId, deriveBatchId, MAX_DECISION_NOTE_CHARS, noteLandedOnRow, noteRecordedReceipt, readBoundInputHash } from "./approval-ask-machine.js";
16
+ import { currentParkArm, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, adoptStoredLiveFacts, buildApprovalRequestFrame, buildReplayFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readProbeReason, readReadRootCandidate, readStoredCardEnvelope, readRuleEvidence, readAllowRuleShadowed, readRuleOffersAbsence, readRuleOffersAbsenceSeat, readParkRowTrueSeat, readAskClassPair, readAskReasons, readClosedWordSeat, buildApprovalCompleteFrame, readRuleOfferList, } from "./approval-card.js";
17
17
  import { askOwnerAdmits, askRowCarriesOwner, POLICY_REFUSAL_DECISION, projectAskTerminalClaimTruth } from "./plugins/approval-ask-store-sql.js";
18
18
  import { APPROVAL_ENDING_CAUSES, SETTLE_OUTCOME, askRowEndingCause, askRowParkTrigger } from "./approval-deny-reasons.js";
19
19
  import { settleByPolicy } from "./approval-policy-settlement.js";
20
20
  import { governanceAskMarksFor, runWithGovernanceAskScope } from "./governance-ask-marks.js";
21
21
  import { governanceOriginOf } from "./runtime-governance.js";
22
- import { grantBindingOf } from "./standing-answer-grant.js";
22
+ import { agreedGrantBinding, grantBindingOf } from "./standing-answer-grant.js";
23
23
  import { operatorAsk } from "./operator-ask.js";
24
24
  import { APPROVAL_EXEMPTED_EVENT } from "./plugins/approval-exemption-store.js";
25
25
  import { refusalBody } from "./http/refusal-body.js";
@@ -47,7 +47,7 @@ export function approvalDecidePath(sessionId) {
47
47
  return `/v1/approvals/${encodeURIComponent(sessionId)}/decide`;
48
48
  }
49
49
  function parkSessionOf(row) {
50
- return row.sourceTaskId === row.sessionId && row.sessionId !== row.taskId ? row.sessionId : undefined;
50
+ return row.sourceSessionId === row.sessionId && row.sessionId !== row.taskId ? row.sessionId : undefined;
51
51
  }
52
52
  function ruleMaterialCarriesCredentialShape(command) {
53
53
  return redactSecretsWithArms(command, { observe: false }).arms.has("full");
@@ -223,10 +223,11 @@ function livePendingRowOf(e) {
223
223
  ...(e.sessionId !== undefined ? { sessionId: e.sessionId } : {}),
224
224
  ...(e.requiresRealApproval ? { requiresRealApproval: true } : {}),
225
225
  ...(e.governanceForced ? { governanceForced: true } : {}),
226
- ...(e.mandated ? { mandated: true } : {}),
226
+ ...(listFrame.mandated === true ? { mandated: true } : {}),
227
227
  ...(standingAnswerHome(pendingEntryStandingAnswerFacts(e)) === "none" ? { rememberRefused: true } : {}),
228
- ...(e.mandate !== undefined ? { mandate: e.mandate } : {}),
229
- ...(e.origin !== undefined ? { origin: e.origin } : {}),
228
+ ...(listFrame.mandate !== undefined ? { mandate: listFrame.mandate } : {}),
229
+ ...(listFrame.origin !== undefined ? { origin: listFrame.origin } : {}),
230
+ ...(listFrame.type === "approval_request" && listFrame.liveFactsUnknown === true ? { liveFactsUnknown: true } : {}),
230
231
  ...(e.originTaskId !== undefined ? { fromSubagent: true, originTaskId: e.originTaskId } : {}),
231
232
  ...(approvalCard !== undefined ? { approvalCard } : {}),
232
233
  frame: listFrame,
@@ -294,17 +295,17 @@ function parseToolApprovalFields(body, retired) {
294
295
  }
295
296
  if (retired !== undefined)
296
297
  return { ok: false, error: retired.error };
297
- const decidedByReading = readDecidedBy(body.decidedBy, false);
298
- let decidedBy;
299
- switch (decidedByReading.kind) {
298
+ const deciderReading = readDecider(body, false);
299
+ let decider;
300
+ switch (deciderReading.kind) {
300
301
  case "outside_closed_set":
301
- return { ok: false, error: DECIDED_BY_OUTSIDE_CLOSED_SET };
302
+ return { ok: false, error: deciderReading.message };
302
303
  case "accepted":
303
- decidedBy = decidedByReading.decidedBy;
304
+ decider = deciderReading.decider;
304
305
  break;
305
306
  default: {
306
- const unreachable = decidedByReading;
307
- throw new Error(`unhandled decidedBy reading: ${JSON.stringify(unreachable)}`);
307
+ const unreachable = deciderReading;
308
+ throw new Error(`unhandled decider reading: ${JSON.stringify(unreachable)}`);
308
309
  }
309
310
  }
310
311
  const rawGrant = body.readRootGrant;
@@ -319,7 +320,7 @@ function parseToolApprovalFields(body, retired) {
319
320
  ...(d !== "deny" && u !== undefined ? { updatedInput: u } : {}),
320
321
  ...(persistRule !== undefined ? { persistRule } : {}),
321
322
  ...(note !== undefined ? { note } : {}),
322
- decidedBy,
323
+ decider,
323
324
  ...(readRootGrant !== undefined ? { readRootGrant } : {}),
324
325
  };
325
326
  }
@@ -357,12 +358,6 @@ function boundArgs(args) {
357
358
  }
358
359
  return { args: redacted, omitted: false, hasBidi };
359
360
  }
360
- function readBoundInputHash(req) {
361
- if (req === null || typeof req !== "object")
362
- return null;
363
- const v = Reflect.get(req, "boundInputHash");
364
- return typeof v === "string" && v.length > 0 ? v : null;
365
- }
366
361
  export function resolveStreamApprovalGate(input) {
367
362
  if (!input.toolApprovalEnabled)
368
363
  return { active: false, reason: "no_tool_approval" };
@@ -492,7 +487,7 @@ function replayTerminalAskRow(row) {
492
487
  }
493
488
  export function outcomeOfDecidedRow(row) {
494
489
  const allow = row.decision === "approve";
495
- const source = row.settledBy !== null ? { settledBy: row.settledBy } : {};
490
+ const source = row.settledBy !== null ? { settledBy: row.settledBy, ...(row.decidedVia !== null ? { decidedVia: row.decidedVia } : {}) } : {};
496
491
  const edit = allow && row.updatedInput !== undefined ? { updatedInput: row.updatedInput } : {};
497
492
  return row.settledBy === null && !("updatedInput" in edit) ? allow : { allow, ...edit, ...source };
498
493
  }
@@ -502,7 +497,7 @@ function settleArgsOfDecided(outcome) {
502
497
  return {
503
498
  allowed: outcome.allow,
504
499
  ...(outcome.updatedInput !== undefined ? { updatedInput: outcome.updatedInput } : {}),
505
- ...(outcome.settledBy !== undefined ? { settledBy: outcome.settledBy } : {}),
500
+ ...(outcome.settledBy !== undefined ? { source: { settledBy: outcome.settledBy, ...(outcome.decidedVia !== undefined ? { decidedVia: outcome.decidedVia } : {}) } } : {}),
506
501
  };
507
502
  }
508
503
  function verdictOfDecided(args) {
@@ -510,7 +505,7 @@ function verdictOfDecided(args) {
510
505
  by: "human",
511
506
  allowed: args.allowed,
512
507
  ...(args.updatedInput !== undefined ? { updatedInput: args.updatedInput } : {}),
513
- ...(args.settledBy !== undefined ? { hostSettledBy: args.settledBy } : {}),
508
+ ...(args.source !== undefined ? { hostSource: args.source } : {}),
514
509
  };
515
510
  }
516
511
  function settleArgsOf(outcome) {
@@ -633,8 +628,8 @@ export class ToolApprovalCoordinator {
633
628
  get unattendedRoutesToPark() {
634
629
  return this.unattendedPolicy !== "deny";
635
630
  }
636
- batchIdFor(askId, sourceTaskId, runId, legKey) {
637
- return this.unattendedRoutesToPark ? deriveBatchId(sourceTaskId, runId, legKey) : deriveAskScopedBatchId(askId);
631
+ batchIdFor(askId, sourceSessionId, runId, legKey) {
632
+ return this.unattendedRoutesToPark ? deriveBatchId(sourceSessionId, runId, legKey) : deriveAskScopedBatchId(askId);
638
633
  }
639
634
  unattendedAskOutcome(site) {
640
635
  const facts = {
@@ -1024,7 +1019,7 @@ export class ToolApprovalCoordinator {
1024
1019
  async sessionGrantUncontestedByRow(origin, req) {
1025
1020
  if (!this.askStore)
1026
1021
  return true;
1027
- const call = { taskId: origin.taskId, legKey: origin.legKey, toolCallId: req.toolCallId, sourceTaskId: req.sourceTaskId ?? origin.taskId };
1022
+ const call = { taskId: origin.taskId, legKey: origin.legKey, toolCallId: req.toolCallId, sourceSessionId: req.sourceSessionId ?? origin.taskId };
1028
1023
  try {
1029
1024
  const rows = await this.withStoreDeadline(this.askStore.listByCall(call), "listByCall(session-grant-provenance)", DURABLE_CONVERGE_READ_TIMEOUT_MS);
1030
1025
  return rows.length === 0;
@@ -1330,6 +1325,7 @@ export class ToolApprovalCoordinator {
1330
1325
  const cardWord = readApprovalCard(req.approvalCard);
1331
1326
  const originWord = typeof req.origin === "string" && req.origin.length > 0 ? req.origin : undefined;
1332
1327
  const askClassPair = readAskClassPair(req);
1328
+ const askReasonsOfReq = readAskReasons(req);
1333
1329
  const requester = extensionRequesterOf(req.requestedBy, "tool_approval");
1334
1330
  const frame = {
1335
1331
  type: "tool_approval",
@@ -1338,7 +1334,7 @@ export class ToolApprovalCoordinator {
1338
1334
  ...(typeof req.toolCallId === "string" && req.toolCallId !== "" ? { toolCallId: req.toolCallId } : {}),
1339
1335
  ...(child
1340
1336
  ? {
1341
- sourceTaskId: req.sourceTaskId,
1337
+ sourceSessionId: req.sourceSessionId,
1342
1338
  fromSubagent: true,
1343
1339
  ...(typeof req.sourceAgentName === "string" ? { sourceAgentName: redactSecrets(req.sourceAgentName) } : {}),
1344
1340
  ...(req.delegation
@@ -1352,7 +1348,9 @@ export class ToolApprovalCoordinator {
1352
1348
  : {}),
1353
1349
  }
1354
1350
  : {}),
1351
+ ...(typeof req.agentId === "string" && req.agentId !== "" ? { agentId: req.agentId } : {}),
1355
1352
  message: typeof req.message === "string" ? redactDeep(req.message) : "",
1353
+ ...(askReasonsOfReq !== undefined ? { askReasons: askReasonsOfReq } : {}),
1356
1354
  ...(governanceForced ? { governanceForced: true } : {}),
1357
1355
  ...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
1358
1356
  ...(req.mandated === true ? { mandated: true } : {}),
@@ -1384,6 +1382,7 @@ export class ToolApprovalCoordinator {
1384
1382
  const card = this.askStore ? buildApprovalCard(frame, req, req.requiresRealApproval === true) : undefined;
1385
1383
  let cardForFrame = card;
1386
1384
  let persistedExpiresAtMs = expiresAtMs;
1385
+ let factsOfRecord;
1387
1386
  let entryExecutionLane = origin.executionLane;
1388
1387
  let lateEnsuredRow;
1389
1388
  let lateTerminalRow;
@@ -1412,16 +1411,16 @@ export class ToolApprovalCoordinator {
1412
1411
  : replayed;
1413
1412
  };
1414
1413
  if (this.askStore && card) {
1415
- const sourceTaskId = req.sourceTaskId ?? origin.taskId;
1414
+ const sourceSessionId = req.sourceSessionId ?? origin.taskId;
1416
1415
  const runId = origin.taskId;
1417
1416
  const legKey = origin.legKey;
1418
- askId = deriveAskId(sourceTaskId, runId, legKey, req);
1419
- batchId = this.batchIdFor(askId, sourceTaskId, runId, legKey);
1417
+ askId = deriveAskId(sourceSessionId, runId, legKey, req);
1418
+ batchId = this.batchIdFor(askId, sourceSessionId, runId, legKey);
1420
1419
  try {
1421
1420
  const existingOrCreated = await this.withStoreDeadline(this.askStore.ensureAsk({
1422
1421
  askId,
1423
1422
  taskId: origin.taskId,
1424
- sourceTaskId,
1423
+ sourceSessionId,
1425
1424
  sessionId: origin.sessionId ?? origin.taskId,
1426
1425
  owner: origin.owner,
1427
1426
  executionLane: origin.executionLane,
@@ -1429,7 +1428,7 @@ export class ToolApprovalCoordinator {
1429
1428
  toolCallId: req.toolCallId,
1430
1429
  legKey,
1431
1430
  parentToolCallId: req.delegation?.parentToolCallId ?? null,
1432
- cardJson: buildApprovalCardEnvelope(askId, card),
1431
+ cardJson: buildApprovalCardEnvelope(askId, card, frame),
1433
1432
  boundInputHash: readBoundInputHash(req),
1434
1433
  ...durableRuleMaterial(ruleLaneMaterial),
1435
1434
  schemaVersion: 1,
@@ -1463,6 +1462,9 @@ export class ToolApprovalCoordinator {
1463
1462
  persistedExpiresAtMs = existingOrCreated.row.expiresAtMs;
1464
1463
  entryExecutionLane = existingOrCreated.row.executionLane;
1465
1464
  cardForFrame = persistedEnvelope.card;
1465
+ factsOfRecord = existingOrCreated.inserted ? undefined : persistedEnvelope.liveFacts;
1466
+ if (factsOfRecord !== undefined)
1467
+ adoptStoredLiveFacts(frame, factsOfRecord);
1466
1468
  if (cardForFrame.governanceForced === true)
1467
1469
  frame.governanceForced = true;
1468
1470
  else
@@ -1560,7 +1562,7 @@ export class ToolApprovalCoordinator {
1560
1562
  if (hostSettled !== undefined || (denyReasonSettled !== undefined && denyReasonSettled !== "")) {
1561
1563
  return {
1562
1564
  allow: false,
1563
- ...(hostSettled !== undefined ? { settledBy: hostSettled } : {}),
1565
+ ...hostSettled,
1564
1566
  ...(denyReasonSettled !== undefined && denyReasonSettled !== "" ? { reason: denyReasonSettled } : {}),
1565
1567
  };
1566
1568
  }
@@ -1577,7 +1579,7 @@ export class ToolApprovalCoordinator {
1577
1579
  return {
1578
1580
  allow: true,
1579
1581
  ...(settled.updatedInput !== undefined ? { updatedInput: settled.updatedInput } : {}),
1580
- ...(hostSettled !== undefined ? { settledBy: hostSettled } : {}),
1582
+ ...hostSettled,
1581
1583
  ...(settled.readRootGrant !== undefined ? { readRootGrant: settled.readRootGrant } : {}),
1582
1584
  };
1583
1585
  }
@@ -1589,10 +1591,10 @@ export class ToolApprovalCoordinator {
1589
1591
  done = true;
1590
1592
  const allowed = verdict.by === "human" && verdict.allowed;
1591
1593
  const outcome = verdict.by === "system" ? SETTLE_OUTCOME.EXPIRED : verdict.allowed ? SETTLE_OUTCOME.ALLOWED : SETTLE_OUTCOME.DENIED;
1592
- const hostSettledBy = verdict.hostSettledBy;
1594
+ const hostSource = verdict.hostSource;
1593
1595
  const updatedInput = verdict.by === "human" ? verdict.updatedInput : undefined;
1594
1596
  const readRootGrant = verdict.by === "human" ? verdict.readRootGrant : undefined;
1595
- hostSettled = hostSettledBy;
1597
+ hostSettled = hostSource;
1596
1598
  denyReasonSettled = verdict.by === "human" && !verdict.allowed ? verdict.denyReason : undefined;
1597
1599
  if (timer)
1598
1600
  clearTimeout(timer);
@@ -1626,7 +1628,7 @@ export class ToolApprovalCoordinator {
1626
1628
  const common = {
1627
1629
  approvalId: wireApprovalId,
1628
1630
  ...(windowRouteUnavailable ? { parkRouted: true } : {}),
1629
- ...(hostSettledBy !== undefined ? { settledBy: hostSettledBy } : {}),
1631
+ ...(hostSource !== undefined ? { settledBy: hostSource.settledBy } : {}),
1630
1632
  settledAtMs: Date.now(),
1631
1633
  };
1632
1634
  return verdict.by === "system"
@@ -1638,7 +1640,7 @@ export class ToolApprovalCoordinator {
1638
1640
  approvalId: wireApprovalId,
1639
1641
  taskId: origin.taskId,
1640
1642
  carrierLeg,
1641
- executingSessionId: req.sourceTaskId,
1643
+ executingSessionId: req.sourceSessionId,
1642
1644
  toolCallId: req.toolCallId,
1643
1645
  settleRecord,
1644
1646
  });
@@ -1792,7 +1794,7 @@ export class ToolApprovalCoordinator {
1792
1794
  if (done)
1793
1795
  return;
1794
1796
  windowRouteUnavailable = true;
1795
- settle({ by: "system", cause, ...(hostSettledBy !== undefined ? { hostSettledBy } : {}) });
1797
+ settle({ by: "system", cause, ...(hostSettledBy !== undefined ? { hostSource: { settledBy: hostSettledBy } } : {}) });
1796
1798
  };
1797
1799
  const windowExpired = (hostSelfReport, cause) => {
1798
1800
  void (async () => {
@@ -1901,11 +1903,13 @@ export class ToolApprovalCoordinator {
1901
1903
  }
1902
1904
  const entryClasses = askClassPair?.classes;
1903
1905
  const entryDeploymentListQuestion = carriesDeploymentListQuestion(deploymentListAsks, entryClasses);
1904
- const entryGrantBinding = grantBindingOf(req);
1906
+ const legGrantBinding = grantBindingOf(req);
1907
+ const entryGrantBinding = factsOfRecord === undefined ? legGrantBinding : agreedGrantBinding(legGrantBinding, grantBindingOf(factsOfRecord));
1908
+ const entryMandated = req.mandated === true || factsOfRecord?.mandated === true;
1905
1909
  const rememberRefused = standingAnswerHome(pendingEntryStandingAnswerFacts({
1906
1910
  ...(effectiveGovernanceForced ? { governanceForced: true } : {}),
1907
1911
  ...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
1908
- ...(req.mandated === true ? { mandated: true } : {}),
1912
+ ...(entryMandated ? { mandated: true } : {}),
1909
1913
  grantBinding: entryGrantBinding,
1910
1914
  classes: entryClasses,
1911
1915
  ...(entryDeploymentListQuestion ? { deploymentListQuestion: true } : {}),
@@ -1928,7 +1932,7 @@ export class ToolApprovalCoordinator {
1928
1932
  owner: origin.owner,
1929
1933
  ...(primary ? { ctxTaskId: primary.taskId, originCtx: primary } : {}),
1930
1934
  ...(reachability === "unreached" ? { suspended: true } : {}),
1931
- ...(child ? { originTaskId: req.sourceTaskId } : primary ? { targetCtxs: new Set(aliveCtxs), onTargetGone } : {}),
1935
+ ...(child ? { originTaskId: req.sourceSessionId } : primary ? { targetCtxs: new Set(aliveCtxs), onTargetGone } : {}),
1932
1936
  ...(origin.sessionId ? { sessionId: origin.sessionId } : {}),
1933
1937
  frame,
1934
1938
  ...(cardFrame !== undefined ? { cardFrame } : {}),
@@ -1944,9 +1948,7 @@ export class ToolApprovalCoordinator {
1944
1948
  ...(ruleLaneMaterial !== undefined ? { ruleLane: ruleLaneMaterial } : {}),
1945
1949
  ...(effectiveGovernanceForced ? { governanceForced: true } : {}),
1946
1950
  ...(req.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
1947
- ...(req.mandated === true ? { mandated: true } : {}),
1948
- ...(mandateWord !== undefined ? { mandate: mandateWord } : {}),
1949
- ...(originWord !== undefined ? { origin: originWord } : {}),
1951
+ ...(entryMandated ? { mandated: true } : {}),
1950
1952
  ...(askId !== undefined && batchId !== undefined ? { askId, batchId } : {}),
1951
1953
  };
1952
1954
  selfEntry = pendingEntry;
@@ -1963,7 +1965,7 @@ export class ToolApprovalCoordinator {
1963
1965
  this.askAudit?.recordAsk({
1964
1966
  approvalId: wireApprovalId,
1965
1967
  taskId: origin.taskId,
1966
- ...(req.sourceTaskId !== undefined ? { sourceTaskId: req.sourceTaskId } : {}),
1968
+ ...(req.sourceSessionId !== undefined ? { sourceSessionId: req.sourceSessionId } : {}),
1967
1969
  ...(origin.sessionId !== undefined ? { sessionId: origin.sessionId } : {}),
1968
1970
  owner: origin.owner,
1969
1971
  toolName: req.toolName,
@@ -2123,7 +2125,7 @@ export class ToolApprovalCoordinator {
2123
2125
  const preRule = this.precheckEditedRuleBeforeDecision(entry, judgedOwner, parsed);
2124
2126
  if (preRule !== undefined)
2125
2127
  return preRule;
2126
- if (parsed.value !== "deny" && policyCannotAnswer(heldAskOf(entry.requiresRealApproval === true), parsed.decidedBy)) {
2128
+ if (parsed.value !== "deny" && policyCannotAnswer(heldAskOf(entry.requiresRealApproval === true), parsed.decider.decidedBy)) {
2127
2129
  return { status: 400, body: refusalBody({ errorCode: "request.body_shape", message: POLICY_CANNOT_ALLOW_PERSON_ASK }) };
2128
2130
  }
2129
2131
  const ruleEligibility = { eligible: true };
@@ -2486,7 +2488,7 @@ export class ToolApprovalCoordinator {
2486
2488
  gateBoundInputHash: row.gateBoundInputHash,
2487
2489
  decision,
2488
2490
  ...(parsed.note !== undefined ? { note: parsed.note } : {}),
2489
- decidedBy: parsed.decidedBy,
2491
+ decider: parsed.decider,
2490
2492
  ...(parsed.updatedInput !== undefined && parsed.value !== "deny" ? { updatedInput: parsed.updatedInput } : {}),
2491
2493
  ...(principal !== undefined ? { principal } : {}),
2492
2494
  ...(httpReq !== undefined ? { httpReq } : {}),
@@ -2729,7 +2731,7 @@ export class ToolApprovalCoordinator {
2729
2731
  decision: parsed.value === "deny" ? "deny" : "approve",
2730
2732
  ...(parsed.note !== undefined ? { decisionNote: parsed.note } : {}),
2731
2733
  ...(parsed.value !== "deny" && parsed.updatedInput !== undefined ? { updatedInput: parsed.updatedInput } : {}),
2732
- ...((sb) => (sb !== undefined ? { settledBy: sb } : {}))(liveSettledBy(parsed.decidedBy)),
2734
+ ...liveHostSource(parsed.decider),
2733
2735
  }), "decideAsk", DURABLE_CALL_TIMEOUT_MS, (late) => {
2734
2736
  if (late.ok)
2735
2737
  this.notifyExternalDecision(askId, outcomeOfDecidedRow(late.row));
@@ -2809,13 +2811,13 @@ export class ToolApprovalCoordinator {
2809
2811
  this.allowAllSessions.add(sessionAllowKey(judgedOwner, entry.sessionId, sessionAllowCategory(entry.toolName), entry.grantBinding));
2810
2812
  }
2811
2813
  const allowed = parsed.value !== "deny";
2812
- const settleArgs = opts?.settleOutcome !== undefined ? settleArgsOfDecided(opts.settleOutcome) : { allowed, updatedInput: parsed.updatedInput, settledBy: liveSettledBy(parsed.decidedBy) };
2814
+ const settleArgs = opts?.settleOutcome !== undefined ? settleArgsOfDecided(opts.settleOutcome) : { allowed, updatedInput: parsed.updatedInput, source: liveHostSource(parsed.decider) };
2813
2815
  const readRootGrant = opts?.settleOutcome === undefined || opts.settleOutcomeIsThisRequest === true ? parsed.readRootGrant : undefined;
2814
2816
  entry.settle({
2815
2817
  by: "human",
2816
2818
  allowed: settleArgs.allowed,
2817
2819
  updatedInput: settleArgs.updatedInput,
2818
- ...(settleArgs.settledBy !== undefined ? { hostSettledBy: settleArgs.settledBy } : {}),
2820
+ ...(settleArgs.source !== undefined ? { hostSource: settleArgs.source } : {}),
2819
2821
  ...(!settleArgs.allowed && parsed.note !== undefined ? { denyReason: parsed.note } : {}),
2820
2822
  ...(readRootGrant !== undefined ? { readRootGrant } : {}),
2821
2823
  });
@@ -2871,6 +2873,7 @@ export class ToolApprovalCoordinator {
2871
2873
  const facts = {
2872
2874
  ...(card.governanceForced === true ? { governanceForced: true } : {}),
2873
2875
  ...(card.risk.requiresRealApproval ? { requiresRealApproval: true } : {}),
2876
+ ...(replayFrame.mandated === true ? { mandated: true } : {}),
2874
2877
  grantBinding: { kind: "unreadable" },
2875
2878
  ...(card.classes !== undefined ? { classes: card.classes } : {}),
2876
2879
  };
@@ -2905,7 +2908,7 @@ export class ToolApprovalCoordinator {
2905
2908
  owner: row.owner,
2906
2909
  executionLane: row.executionLane,
2907
2910
  ...(row.sessionId !== row.taskId ? { sessionId: row.sessionId } : {}),
2908
- ...(card.fromSubagent === true ? { originTaskId: row.sourceTaskId } : {}),
2911
+ ...(card.fromSubagent === true ? { originTaskId: row.sourceSessionId } : {}),
2909
2912
  toolName: card.toolName,
2910
2913
  ...facts,
2911
2914
  approvalId: row.askId,
@@ -2962,10 +2965,16 @@ export class ToolApprovalCoordinator {
2962
2965
  }
2963
2966
  return rows;
2964
2967
  }
2965
- hasLivePendingFrom(originTaskId) {
2966
- for (const e of this.pending.values())
2967
- if (e.originTaskId === originTaskId && e.adopted !== true)
2968
+ hasLivePendingFromLeg(names) {
2969
+ if (names.length === 0)
2970
+ return false;
2971
+ for (const e of this.pending.values()) {
2972
+ if (e.adopted === true)
2973
+ continue;
2974
+ const { agentId, sourceSessionId } = e.frame;
2975
+ if ((agentId !== undefined && names.includes(agentId)) || (sourceSessionId !== undefined && names.includes(sourceSessionId)))
2968
2976
  return true;
2977
+ }
2969
2978
  return false;
2970
2979
  }
2971
2980
  async pollSuspendedDecisions() {