@sema-agent/server 7.150.0 → 7.152.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 (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -1,14 +1,14 @@
1
1
  import type { ApprovalLegOrigin } from "./approval-leg-origin.js";
2
- import { type ApprovalDecider, type HostSettledBy, type HostSource, type RetiredDecisionKeyFacts } from "./host-decision.js";
2
+ import { type ApprovalDecider, type HostSettledBy, type HostSource } 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";
6
6
  import type { GateCurrencyStore } from "./approval-gate-currency.js";
7
7
  import { type HitlTransport } from "./hitl-delivery.js";
8
8
  import { type AllowRuleShadowProjection, type DenialLimitFallback, type RuleOffersAbsence, type ApprovalRequestFrame, type ApprovalRevokeFrame, type ApprovalCardLegFrame, type ApprovalCompleteFrame, type RuleEvidenceProjection } from "./approval-card.js";
9
- import { type ApprovalAskStore, type AskRow } from "./plugins/approval-ask-store-sql.js";
9
+ import { type ApprovalAskStore, type AskDecision, type AskDecisionRecord, type AskRow, type DecideResult, type RecordParkedDecisionResult } from "./plugins/approval-ask-store-sql.js";
10
10
  import type { ApprovalAskAuditSink } from "./approval-ask-audit-store.js";
11
- import { type AskRowEndingCause, type SettleCause, type SettleOutcome } from "./approval-deny-reasons.js";
11
+ import { type AskRowEndingCause, type SettleCause } from "./approval-deny-reasons.js";
12
12
  import type { ParkCommitWatch } from "./plugins/park-commit-watch.js";
13
13
  import { type GovernanceAskMarks } from "./governance-ask-marks.js";
14
14
  import { type GovernancePosture } from "./runtime-governance.js";
@@ -36,7 +36,7 @@ export declare const MAX_ALLOW_SESSIONS = 4096;
36
36
  export declare function approvalDecidePath(sessionId: string): string;
37
37
  /**
38
38
  * 一只转停驻的问**去哪只会话决** —— 它的停车行(检查点卡)落在哪只会话上,耐久回决口 `POST /v1/approvals/:sessionId/decide` 就按这只会话找卡(卡自己的会话,
39
- * 决断口的地址;不是卡归属的 run 会话 —— cascade 级上的卡归调用方的 run,却只能在级自己的会话上决)。三处同读这一只:决断口对 PARKED 行的 `410 gone.ask_parked`
39
+ * 决断口的地址;不是卡归属的 run 会话 —— cascade 级上的卡归调用方的 run,却只能在级自己的会话上决)。三处同读这一只:决断口对 PARKED 行在这台部署交不了停驻赎回时(直连门)的 `410 gone.ask_parked`
40
40
  * 回显、迟到回决口对 PARKING 行的 `202` 与按问读口 `parked` 的 `decidePath`。
41
41
  * 停车行落在**铸它那条腿**的会话上 = 行上的发起会话 `sourceSessionId`(core 铸停车行的 `sessionId` 与铸这一问的发起会话是同一只变量;根腿 = 行上的会话,
42
42
  * 委派 / 后台子代腿 = 子代自己的会话,不是行上记的投递会话):
@@ -46,25 +46,24 @@ export declare function approvalDecidePath(sessionId: string): string;
46
46
  */
47
47
  export declare function parkSessionOf(row: Pick<AskRow, "state" | "sourceSessionId" | "taskId">): string | undefined;
48
48
  /**
49
- * [ref] 随批小件:`tool_approval.not_pending` 404 的**判别位**([ref] 排障代价实证 —— 三因合并成一句人话,现场分不出「答案没地方兑」与「打错副本了」)。
50
- * 🔴 `tool_approval.not_pending` 整个码**只在已过属主门的面上出**(属主看得见的「这张卡不在待决」)。调用方**看不见**这只问 —— 无行 / 行不是调用方的 /
51
- * 行读不出 / 这台部署没有问账可判 —— 一律 404 `not_found.ask`(与耐久决断口同一个词:两扇门底下是同一只问;不带任何状态位,属主门不过与未知 id 逐字节同,
52
- * 唯一成形口 {@link ToolApprovalCoordinator.askNotVisible})。
53
- * DECIDED/PARKED 已从 404 分流(DECIDED ⇒ 200 回放首决,回执带 `decidedBy`,**不是**成因;PARKED ⇒ 赎回席),过了属主门的残余两类:
54
- * · 行 `VOID` / `DENIED`(没有人决过它)—— `cause` = **行上记的那个成因词**(问账 `ending_cause` 列;与决断口 410 `gone.ask` 体的 `cause`、审计 settle 行
55
- * 的 `cause` 同一个词,闭集 {@link SettleCause});行上没写归因(存量行)⇒ 缺席,不替没写的行编一个词;
56
- * · {@link NOT_PENDING_UNKNOWN_CAUSE} —— 行仍待决而本副本没有在等它的登记(本副本不认得它的活卡:它活在别的副本上,或本副本这条登记已散场):
57
- * 换副本或换端点重试才有意义(这个词只属于 404 面,不是结局成因)。
58
- * **无持久店的部署上恒不带 `cause`**:那台机器压根没有行可判,编一个 cause 是撒谎。
49
+ * [ref] 随批小件:`tool_approval.not_pending` 404 的**判别位**([ref] 排障代价实证)。这个码只在按问读口**已过可见门**之后出(属主看得见的「这张卡此刻说不出待决」;
50
+ * 调用方**看不见**这只问 —— 无行 / 不属这只 task / 行不是调用方的 / 行读不出 —— 一律 404 `not_found.ask`,唯一成形口 {@link ToolApprovalCoordinator.askNotVisible})。
51
+ * 判别位只有一个词:{@link NOT_PENDING_UNKNOWN_CAUSE} —— 行仍待决而本副本没有在等它的登记(它活在别的副本上,或本副本这条登记已散场):换副本重读才有意义
52
+ * (这个词只属于 404 面,不是结局成因;没有人决过的行在读口上是 `state:"void"` + 行上的成因词,不走这个码)。坏行(读不出可用的决议)⇒ `cause` 缺席。
59
53
  */
60
54
  export declare const NOT_PENDING_UNKNOWN_CAUSE: "unknown_or_other_replica";
61
- export type NotPendingCause = AskRowEndingCause | typeof NOT_PENDING_UNKNOWN_CAUSE;
55
+ export type NotPendingCause = typeof NOT_PENDING_UNKNOWN_CAUSE;
62
56
  /**
63
- * `GET /v1/tool-approvals/:approvalId` 应答体 `state` 的**闭集**(一只 ask 此刻在哪一态;读法与应答口逐条同源):
64
- * · `pending` —— 本副本上有在等它的活登记(应答口此刻收得下);
65
- * · `decided` —— 行 `DECIDED`(有人 / 有策略决过;回执三键同晚答回放体),**或**行 `PARKED` 而它的门已被决([ref]:checkpoint 已结算,见 {@link ParkedGateReading});
66
- * · `parked` —— 行 `PARKING`,或行 `PARKED` 且门仍是该会话当前待决的审批门(转后台候批;应答口走迟到受理,耐久回决口照收);门是被引擎重开的(决过之后续跑腿在动作开跑前失败)⇒ 另带 `reopened`([ref],见 {@link ReopenedGate});
67
- * · `void` —— 行 `DENIED` / `VOID`(没有人决过它,答案无处兑现;`cause` 同晚答 404),**或**行 `PARKED` 而它的门已过期 / 被取代(含停驻 run 被取消;此时 `cause` 缺席)。
57
+ * 审批卡同根两扇口(决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`、按问读口 `GET /v1/tasks/:taskId/asks/:askId`)对**看不见**这只问的调用方的那一句
58
+ * (`404 not_found.ask`;查无 / 不属这只 task / 不是你的 / 行读不出 同一句)—— 一句一处:两扇口底下是同一只问,句子分岔就等于把「它存在但不是你的」写在 wire 上。
59
+ */
60
+ export declare const ASK_NOT_FOUND_UNDER_TASK = "no such approval ask under this task (never existed, belongs to another task, or is not yours)";
61
+ /**
62
+ * `GET /v1/tasks/:taskId/asks/:askId` 应答体 `state` 的**闭集**(一只 ask 此刻在哪一态;读法 = {@link ToolApprovalCoordinator.readStateOfRow} 的六态表):
63
+ * · `pending` —— 本副本上有在等它的活登记(决断口的 live 臂此刻收得下);
64
+ * · `decided` —— 行 `DECIDED`(有人 / 有策略决过;`decision` / `decidedAtMs` / `decisionNote`,与决断口回放同一对词),**或**行 `PARKED` 而它的门已被决([ref]:checkpoint 已结算,见 {@link ParkedGateReading});
65
+ * · `parked` —— 行 `PARKING`,或行 `PARKED` 且门仍是该会话当前待决的审批门(转后台候批;决断口的停驻臂与耐久回决口照收);门是被引擎重开的(决过之后续跑腿在动作开跑前失败)⇒ 另带 `reopened`([ref],见 {@link ReopenedGate});
66
+ * · `void` —— 行 `DENIED` / `VOID`(没有人决过它,答案无处兑现;`cause` = 行上记的成因词,与决断口 410 同一列),**或**行 `PARKED` 而它的门已过期 / 被取代(含停驻 run 被取消;此时 `cause` 缺席)。
68
67
  */
69
68
  export declare const TOOL_APPROVAL_READ_STATES: readonly ["pending", "decided", "parked", "void"];
70
69
  export type ToolApprovalReadState = (typeof TOOL_APPROVAL_READ_STATES)[number];
@@ -77,12 +76,12 @@ export interface AskRowReadProjection {
77
76
  toolName?: string;
78
77
  frame?: ApprovalRequestFrame;
79
78
  }
80
- /** `GET /v1/tool-approvals/:approvalId` 的 200 体:列表面同一只行投影 + `state` + 各态附键。 */
79
+ /** `GET /v1/tasks/:taskId/asks/:askId` 的 200 体:列表面同一只行投影 + `state` + 各态附键。`decision` 与决断口同一对词(`approve` / `deny`,行上的词)。 */
81
80
  export type ToolApprovalReadBody = ({
82
81
  state: "pending";
83
82
  } & LivePendingRow) | ({
84
83
  state: "decided";
85
- decision: "allow" | "deny";
84
+ decision: AskDecision;
86
85
  decidedAtMs: number;
87
86
  decisionNote?: string;
88
87
  } & AskRowReadProjection) | ({
@@ -93,6 +92,14 @@ export type ToolApprovalReadBody = ({
93
92
  state: "void";
94
93
  cause?: AskRowEndingCause;
95
94
  } & AskRowReadProjection);
95
+ /** 一条行的**可读决议**(权威四合取:二值 ∧ 非 provisional ∧ 有 `decidedAtMs` ∧ 态确为 DECIDED;四合取各自的来由见耐久决断口 `decidedRowIsAuthoritative`
96
+ * 的顶注)。**这是那只判据的唯一读法** —— 读口、唯一写者的迟到臂、耐久决断口的守卫都读它。读不出 ⇒ `undefined`(各口按「不是一条可用的人的决议」
97
+ * 处置,绝不把坏行包装成首决交出去)。 */
98
+ export declare function decidedRowFacts(row: AskRow): {
99
+ decision: AskDecision;
100
+ decidedAtMs: number;
101
+ decisionNote?: string;
102
+ } | undefined;
96
103
  /**
97
104
  * 结算一张卡的**判决** —— 判别联合,逼每个调用点说清「这次等待是怎么结束的」:
98
105
  * · `by:"human"` —— 一次**决议**到了(人答,或从问账行读回来的决议,含部署政策拒落成的 `DECIDED` 行,`hostSource` 记它的来源词与机器座位):`allowed` 说方向;审计 settle 行
@@ -135,7 +142,7 @@ export type SettleVerdict = {
135
142
  * 悬挂 promise 的可能是另一个副本(F4 的轮询腿会在它自己的下一拍续跑)。run 的生死读 run 面。
136
143
  *
137
144
  * [ref] 起**同一个词、同一句语义**也出现在 live 面:审批机起服时从问账接管的登记(没有引擎腿在等)在 `livePending` 行上带它,
138
- * 在 live 应答口的 200 回执上按同一判据(本副本被唤醒的等待腿数 = 0)带它。一个事实,各面一个读法。
145
+ * 在决断口 live 形的 200 回执上按同一判据(本副本被唤醒的等待腿数 = 0)带它。一个事实,各面一个读法。
139
146
  */
140
147
  export declare const ASK_DECISION_CONSUMER_ABSENT = "absent";
141
148
  /**
@@ -165,58 +172,118 @@ export interface ParkedAskRedeemRequest {
165
172
  /** 卡上点的是 `allow_session` ⇒ `"session"`:与 `/decide` 体上的 `remember:"session"` 是**同一只**「本会话放行」请求,交同一个铸点
166
173
  * (续跑腿 `resumeCheckpoint`;可记与否从同一条停驻行判、落同一只豁免店、只在结清之后落)。缺席 = 只放行这一次的那两个词。 */
167
174
  remember?: "session";
175
+ /** 「不再询问」的规则位(已过唯一判官 {@link readPersistRuleSlot})—— 与 `/decide` 体上的 `persistRule` 是**同一只**请求,交同一个铸点(续跑腿结清点,记录 = 这张卡的问行)。 */
176
+ persistRule?: ParsedPersistRule;
168
177
  /** 发起本次 respond 的**已验证**调用方(live 腿 `gatedSubject` 的那一把)。席在赎回之前拿它与
169
178
  * **checkpoint 当下的 scope** 对一次(codex R1-[high] 一:收编改写身份之后,任何缓存的属主判据都
170
179
  * 过期;门必须贴在当下的持久事实上)。 */
171
180
  principal?: string;
181
+ /** 调用方的**运维身份**(交来这一问的那扇门已判过的那一格;[ref] α):席复核 checkpoint 当下的 scope、续跑腿复核载入行时按它读面表 `scope.decide` 的运维列。
182
+ * 耐久决断口 = 它的面表 `ask.decide` 运维列读到的那位(显式运维代决别人的卡,live 与停驻两形同放);7.151.x 及以前的应答口恒 `false`(面表 `ask.answer` 没有运维列;该口 7.152.0 起已删)。
183
+ * 必填:缺省等于替门作答「不是运维」或「是运维」—— 两个方向都是同一扇门对两形说两种话。 */
184
+ operator: boolean;
172
185
  /** 发起本次 respond 的真实 HTTP 请求。赎回腿据它做准入解析与舰队 scope(与 `/decide` 腿同姿势);
173
186
  * 缺席 ⇒ 那条腿按「无请求」形处置(它自己的成文语义,本席不替它决定)。 */
174
187
  httpReq?: IncomingMessage;
175
188
  }
189
+ /**
190
+ * 一次对停驻卡的决定 —— 耐久决断口的停驻形(7.151.x 及以前另有应答口 PARKED 臂同调)交给**同一只**赎回(`ToolApprovalCoordinator` 的 `runParkedFlight`)的那一份。
191
+ * 门各自已过属主门、把自己的词映进来:`write` = 这次决定的记录(决议向 · 出处 · 理由 · 署名 · 键 —— 停驻门受理之后落在问行上的就是它),其余是停驻门要的余项。
192
+ */
193
+ export interface ParkedDecisionRequest {
194
+ readonly write: AskDecisionWrite;
195
+ /** 「本会话放行」(决断体上的 `remember:"session"`;与 `/decide` 的 `remember:"session"` 同一只请求、同一个铸点 —— 续跑腿 `resumeCheckpoint`)。 */
196
+ readonly remember?: "session";
197
+ /** 「不再询问」的规则位(决断体上的 `persistRule`,唯一判官 {@link readPersistRuleSlot})—— 交赎回席,由续跑腿的结清点兑(记录 = 这张卡的问行)。 */
198
+ readonly persistRule?: ParsedPersistRule;
199
+ /** ctrl+g 编辑实参(只 approve 交给门的绑定;不落问行)。 */
200
+ readonly updatedInput?: unknown;
201
+ readonly principal?: string;
202
+ /** 见 {@link ParkedAskRedeemRequest.operator}(同一格,原样交席)。 */
203
+ readonly operator: boolean;
204
+ /** 要人门([ref])的判词,由口按这张卡与决定者位判好交来(`true` ⇒ 这一形的放行不归策略答)。只在「这一次要写」时读:门上已站着决定 ⇒ 先回放 / 冲突。 */
205
+ readonly policyMayNotApprove?: boolean;
206
+ readonly httpReq?: IncomingMessage;
207
+ }
208
+ /** 耐久决断口对一只停驻的问拿到的答案(`ToolApprovalCoordinator.decideParkedAsk`;口按自己的 wire 律渲染,与 `DECIDED` 行同一条回放 / 冲突律)。 */
209
+ export type ParkedAskAnswer =
210
+ /** 本次请求被停驻门受理(赎回席的受理恒是 `200`:`acceptedResumingReceipt` 一只铸点;`body` = 那只受理体;`recorded` = 受理之后落了记录的那一行,没落成 ⇒ 缺席)。 */
211
+ {
212
+ readonly kind: "accepted";
213
+ readonly body: Record<string, unknown>;
214
+ readonly recorded?: AskRow;
215
+ readonly rememberApplied?: boolean;
216
+ readonly rule?: RuleSlotReceipt;
217
+ }
218
+ /** 没生效(门 / 席 / 准入的拒,原样)。 */
219
+ | {
220
+ readonly kind: "refused";
221
+ readonly status: number;
222
+ readonly body: Record<string, unknown>;
223
+ }
224
+ /** 门上已站着一次决定(向 / 时刻 / 理由取门;署名取行上的记录 —— 只在记录说的就是门上这一向时;`byThisRequest` = 本次请求的键就是记录上那把)。 */
225
+ | {
226
+ readonly kind: "standing";
227
+ readonly decision: AskDecision;
228
+ readonly decidedAtMs: number;
229
+ readonly decisionNote?: string;
230
+ readonly actor?: unknown;
231
+ readonly byThisRequest: boolean;
232
+ }
233
+ /**
234
+ * 这台部署上停驻形**只有耐久审批门收**:赎回席没接(直连门部署 —— 停驻门的决定要签名信封,而这扇口没有决策证明;fail-closed,接线处 `boot/late-binds.ts`),
235
+ * 或行上没有门坐标(受损行,没有门可交)。口按自己的词指路那道门。
236
+ */
237
+ | {
238
+ readonly kind: "gate_only";
239
+ }
240
+ /** 重判那一读读不出 / 行已不在门判过的属主域(门读之后被收编改写)⇒ 与查无同答(口按自己的词)。 */
241
+ | {
242
+ readonly kind: "gone";
243
+ }
244
+ /** 要写的是一次策略对要人的卡的放行(`ParkedDecisionRequest.policyMayNotApprove`)⇒ 写之前拒(口按自己的词;与 live 形同一道门、同一个位置)。 */
245
+ | {
246
+ readonly kind: "policy_refused";
247
+ };
176
248
  /** [ref]:赎回席的结局 = 赎回腿的原始 HTTP 结果面 + 请求带了 `remember` 时铸点的真答(`rememberApplied`:落没落;不进 `body` —— 首次受理的回执挂它,
177
249
  * 受理回执(幂等回放的那一份)不存它)。 */
178
250
  export interface ParkedAskRedeemResult {
179
251
  status: number;
180
252
  body: Record<string, unknown>;
181
253
  rememberApplied?: boolean;
182
- /**
183
- * [ref]:这次赎回所决的那道门的世代(席读到的那一行 checkpoint 的世代号,core `checkpointRevOf`)—— 受理回执的键的一半,由**真正决了它的那一席**交回。
184
- * 生产席读到行之后的每一答都带(行读不到的拒答不带);缺席 ⇒ 回执说不出这一代 ⇒ 照旧回放({@link receiptAnswersNow})。
185
- */
186
- gateGeneration?: number;
254
+ /** 请求带了 `persistRule` 时续跑腿结清点铸的规则回执(2xx 恒带;不进 `body` —— 首次受理的回执挂它:回放不兑规则)。 */
255
+ rule?: RuleSlotReceipt;
187
256
  }
188
257
  /** [ref]:赎回席(装配层注入;缺席 ⇒ PARKED 臂逐字回落修前 404)。 */
189
258
  export type ParkedAskRedeem = (req: ParkedAskRedeemRequest) => Promise<ParkedAskRedeemResult>;
190
259
  /**
191
260
  * 一张门被引擎**重开**过的停驻卡([ref]):决过之后,续跑腿在被批准的动作开跑之前失败,引擎把同一张门(同一把 token)翻回待决。
192
- * `reason` = core 记在行上的重开因由词原样(闭集 `REOPEN_REASONS`:`env_failed` 同一个决议再交一次即可续跑(两扇决议口都行:应答口的受理回执键带门世代,重开之后不再回放首次受理,[ref]);`tool_unavailable` / `constraint_rejected` 要重新决;`config_refused` 改好部署配置后再交原决议,或重新决);
261
+ * `reason` = core 记在行上的重开因由词原样(闭集 `REOPEN_REASONS`:`env_failed` 同一个决议再交一次即可续跑(决断口与耐久回决口都行);`tool_unavailable` / `constraint_rejected` 要重新决;`config_refused` 改好部署配置后再交原决议,或重新决);
193
262
  * `decision` / `decidedAtMs` / `decisionNote?` = 重开之前的那次决议(读法与已结算门的 `decided` 同一只;读不出 ⇒ 三键缺席,只带因由词)。
194
263
  */
195
264
  export type ReopenedGate = {
196
265
  readonly reason: ReopenReason;
197
266
  } | {
198
267
  readonly reason: ReopenReason;
199
- readonly decision: "allow" | "deny";
268
+ readonly decision: AskDecision;
200
269
  readonly decidedAtMs: number;
201
270
  readonly decisionNote?: string;
202
271
  };
203
272
  /**
204
273
  * 按问读口对一张 `PARKED` 卡的**门读法**([ref];判官的唯一属主 = `approval-gate-currency.ts`,协调器本身不认识 checkpoint 的形):
205
- * · `open` —— 这张卡的门仍是该会话当前待决的审批门(应答口收得下)⇒ 读口说 `parked`;门被引擎重开过 ⇒ 另带 `reopened`([ref],{@link ReopenedGate});
206
- * `generation` = 这道门此刻的世代号(core `checkpointRevOf`:每一次 resolve / reopen 都推它)—— 应答口受理回执的键的一半([ref]:重开 = 新一代 = 新键);
274
+ * · `open` —— 这张卡的门仍是该会话当前待决的审批门(决断口的停驻臂收得下)⇒ 读口说 `parked`;门被引擎重开过 ⇒ 另带 `reopened`([ref],{@link ReopenedGate});
207
275
  * · `decided` —— 门已被决:方向 / 时刻 / 理由取自 checkpoint 上的结算赢家 ⇒ 读口说 `decided`;
208
276
  * · `void` —— 门已过期 / 被取代(含停驻 run 被取消:取消先把门 expire)⇒ 读口说 `void`(没有人决过它,答案无处兑现);
209
277
  * · `unknown` —— 说不出可信的话:`row_absent` = checkpoint 行没了;`decision_unreadable` = 门已结算却读不出可用的决议(行的 status 词或结算种类不在闭集表里 / 结算记录过不了 core 的
210
- * 门记录筛 / 方向或时刻读不出)⇒ 读口答 404 `tool_approval.not_pending`(坏行不包装成首决;应答口并不同判:它的 PARKED 臂只对 checkpoint 行没了答 404,已结算的门答 409 `approval_stale`),
278
+ * 门记录筛 / 方向或时刻读不出)⇒ 读口答 404 `tool_approval.not_pending`(坏行不包装成首决),
211
279
  * 并记一行 error:`defects` 是读不出的那几处(非空),日志带首句 + 计数。
212
280
  */
213
281
  export type ParkedGateReading = {
214
282
  readonly kind: "open";
215
- readonly generation: number;
216
283
  readonly reopened?: ReopenedGate;
217
284
  } | {
218
285
  readonly kind: "decided";
219
- readonly decision: "allow" | "deny";
286
+ readonly decision: AskDecision;
220
287
  readonly decidedAtMs: number;
221
288
  readonly decisionNote?: string;
222
289
  } | {
@@ -300,7 +367,7 @@ export type StandingAnswerHome = "none" | "seat" | "server_store";
300
367
  /**
301
368
  * 🔴 **[ref] —— 会话级放行的唯一判据:站着的答案能不能退掉这一问,能的话它记在哪({@link StandingAnswerHome})。** 纯函数,读者:
302
369
  * · **读侧**(`askBroadcast` 的会话授权短路 {@link ToolApprovalCoordinator.standingGrantSettles}):`seat` 才可能由既有授权代答,否则往下走真出卡;
303
- * · **写侧**(`finishRespond` 与 `recordDeploymentListAnswer`,经 {@link liveSessionAnswer}):`seat` 把 `allow_session` 铸成进程内授权;`server_store` 落 server 的会话豁免店;
370
+ * · **写侧**(`settleLiveDecision`,经 {@link liveSessionAnswer}):`seat` 把 `remember:"session"` 铸成进程内授权;`server_store` 落 server 的会话豁免店;
304
371
  * `none` 只放行这一次、`rememberApplied:false`;
305
372
  * · **卡面提示位**(活卡帧 / 条目 / `livePending` 行的 `rememberRefused`):在场 ⇔ 本函数答 `none` 或这条腿记不下(读的是 {@link liveSessionAnswer},它先问本函数);
306
373
  * · **耐久可记性**({@link standingAnswerDurablyRecordable}:`/decide` 的 remember、运维队列行、策略层两只豁免读面)。
@@ -372,23 +439,19 @@ export declare function parkRowStandingAnswerFacts(stored: Extract<PendingAction
372
439
  }>, gate: CheckpointGate, governance: GovernancePosture | undefined,
373
440
  /** 部署名单门对这一行的调用出不出它自己的问(`approval.ts` 的 `deploymentListAsks`,调用方现读活配置;停驻行上只有 wire 名)。 */
374
441
  deploymentListAsks: boolean): StandingAnswerFacts;
375
- /** A live approval frame delivered to whoever tails this run's stream. `type` IS the SSE event name (named-event
376
- * convention, same as question). The shell renders `tool_approval` as the CC three-choice card and dismisses on
377
- * `tool_approval_complete`.
378
- * 🔴 **旧族**:只投给呈卡协议未上场的腿(一条腿一个帧族,见 {@link ToolApprovalRunContext});呈卡腿上同一次铸定的这只对象仍是
379
- * 卡外开卡事实的来源(`ApprovalRequestLiveFacts` 取自它)与 `livePending` 行的 `frame`。 */
442
+ /** 一只 ask 在 `askBroadcast` 里铸定的**素材对象**(一处脱敏属主)—— 呈卡帧的卡({@link ApprovalCardSource})与卡外开卡事实
443
+ * (`ApprovalRequestLiveFacts`)都取自它。🔴 **它本身不上 wire**:审批只有呈卡族一个帧族(旧族的开卡 / 闭合帧连同只属于它们的 `type` 与闭合三键已退役;
444
+ * `approvalId` 随身份退役那一步收;键集账见 `trace/core-keyset-guard.ts`)。 */
380
445
  export interface ToolApprovalFrame {
381
- type: "tool_approval" | "tool_approval_complete";
382
446
  approvalId: string;
383
- /** "tool_approval" only: which tool asked (canonical core name as core sent it) + the policy's ask message. */
447
+ /** which tool asked (canonical core name as core sent it) + the policy's ask message. */
384
448
  toolName?: string;
385
- /** [ref] "tool_approval" only: **core 的 tool-call id**(`AskRequest.toolCallId`,逐字透传)——消费端用它
449
+ /** [ref] **core 的 tool-call id**(`AskRequest.toolCallId`,逐字透传)——消费端用它
386
450
  * 把审批卡锚到助手消息里那个 `tool_use` 块。`approvalId` 是审批自己的新 uuidv7、与该块**无关**,
387
451
  * 此前帧上只有它 ⇒ 两个宿主都只能拿它当 key 铸卡,而那个 id 之后再没有任何帧提到过,卡永远停在
388
452
  * awaiting_approval。「拿最近一次 tool_start 当锚」这类补偿也不成立:**审批帧比 `tool_start` 先到**
389
453
  * (cli 帧级取证 4020ms vs 4142ms)。durable(parked)腿本来就存着这个值(parked-decide.ts),
390
- * 本键 = 把 live 腿的字段集与它对齐。闭合帧(`tool_approval_complete`)不带——它按 approvalId 消卡,
391
- * 多一个锚只会多一份歧义。 */
454
+ * 本键 = 把 live 腿的字段集与它对齐(卡上 `card.toolCallId`)。 */
392
455
  toolCallId?: string;
393
456
  /** **只在委派子代的 ask 上在场**(现判别键 = {@link ToolApprovalFrame.fromSubagent};本字段本身
394
457
  * [ref] MED-1 后不再是判别式,core JSDoc 钉明「不是子代判别键」)。值 = 子代的 core session id
@@ -416,7 +479,7 @@ export interface ToolApprovalFrame {
416
479
  };
417
480
  message?: string;
418
481
  /**
419
- * [ref]/[ref] **ADDITIVE**,`"tool_approval"` only —— `true` ⇔ 这只 ask 的门来自**运维治理层**
482
+ * [ref]/[ref] **ADDITIVE** —— `true` ⇔ 这只 ask 的门来自**运维治理层**
420
483
  * (`AUTONOMY` / `commandPolicy` / `MANUAL_MODE_SHELL_GATE` / `SENSITIVE_WRITE_PATTERNS` 合成的那条
421
484
  * policy,`applyRuntimeGovernance`),而不是模型默认门或客户端表态。壳据此渲染「治理强制」徽标,回答
422
485
  * [ref]#1/[ref] 实证的那个 UX 缺口:「我都开 bypassPermissions 了为什么还在问」。
@@ -428,7 +491,7 @@ export interface ToolApprovalFrame {
428
491
  * `governance-ask-marks.ts` 顶注。
429
492
  */
430
493
  governanceForced?: true;
431
- /** [ref]([ref]③/[ref];**ADDITIVE**,`"tool_approval"` only)——core PreToolUse hook/策略族铸的
494
+ /** [ref]([ref]③/[ref];**ADDITIVE**)——core PreToolUse hook/策略族铸的
432
495
  * **安全类 ask 出身位**(`AskRequest.requiresRealApproval`,core 5.37 起可选、真才带)。帧顶层契约与
433
496
  * core 侧同构:**真才带,缺席绝不编 false**(governanceForced 同形)——与 `card.requiresRealApproval`
434
497
  * (approval-card.ts,恒在布尔)**两侧契约刻意不同、别混**:卡是 durable 店形(askStore 在场)专属,
@@ -438,7 +501,7 @@ export interface ToolApprovalFrame {
438
501
  * `card.risk.requiresRealApproval`、列表行顶层同值)。 */
439
502
  requiresRealApproval?: true;
440
503
  /**
441
- * **[ref]**(core 7.26.0;**ADDITIVE**,`"tool_approval"` only)—— **这一问没有任何规则能清掉**
504
+ * **[ref]**(core 7.26.0;**ADDITIVE**)—— **这一问没有任何规则能清掉**
442
505
  * (`AskRequest.mandated`:org / 治理层、保护判官、hook 的筛查权、被祖先的应答者裁决的问…… 由引擎在闸站
443
506
  * 盖章,策略方不可自填、只可收紧)。壳据它渲染「规则清不掉这一问」,并让**声明了自动应答姿态**的席位知道
444
507
  * 哪些卡它不该自动答。
@@ -468,9 +531,9 @@ export interface ToolApprovalFrame {
468
531
  */
469
532
  mandated?: true;
470
533
  /**
471
- * **7.116.0(审计修复批 S4;ADDITIVE,`"tool_approval"` only)—— 这张卡上的「本会话放行」只放行这一次、不会被记住。**
534
+ * **7.116.0(审计修复批 S4;ADDITIVE,卡外 / 卡内事实)—— 这张卡上的「本会话放行」只放行这一次、不会被记住。**
472
535
  * 在场 ⇔ 同一只判官 {@link liveSessionAnswer} 答 `none`(问本身记不住:治理强制 / 必须真人 / 强制 / 应答还授予别的东西 / 类集清不掉;或这条腿记不下:
473
- * 没有会话 / 读不出会话住客),回决侧写授权(`finishRespond`)读的是同一只 ⇒ 帧说不可记 ⇔ 点了 `allow_session` 回执 `rememberApplied:false`。壳读这一位决定渲不渲
536
+ * 没有会话 / 读不出会话住客),回决侧写授权(`settleLiveDecision`)读的是同一只 ⇒ 帧说不可记 ⇔ 带了 `remember:"session"` 回执 `rememberApplied:false`。壳读这一位决定渲不渲
474
537
  * 「本会话放行」,不再从 `requiresRealApproval` / `mandated` / `governanceForced` 三位自己推断(那一推断漏掉第四个理由:core 7.41.0
475
538
  * 的 `Skill` 卡批准即授予清单,三位全无)。`card_json` 卡面、`livePending` 行、运维队列行同名同义。
476
539
  * 判官是 {@link liveSessionAnswer}(这一问的事实 + 这条腿记不记得下:没有会话的腿、读不出会话住客的腿同样在场),回决写侧读同一只。
@@ -478,7 +541,7 @@ export interface ToolApprovalFrame {
478
541
  */
479
542
  rememberRefused?: true;
480
543
  /**
481
- * **[ref](core 7.32.0 [ref];ADDITIVE,`"tool_approval"` only)** —— 强制位**站在哪一个词上**:core `PERSISTED_RULE_MANDATES`
544
+ * **[ref](core 7.32.0 [ref];ADDITIVE,卡外 / 卡内事实)** —— 强制位**站在哪一个词上**:core `PERSISTED_RULE_MANDATES`
482
545
  * 六词之一(`operator_always` / `tool_marks` / `probe_mandate` / `probe_unanswered` / `write_protection` /
483
546
  * `target_unresolved`,词义属主在 core)。只在 `mandated: true` 的**整因**是那一个词时在场;另一扇门(治理 / hook /
484
547
  * 祖先)或不止一个理由 ⇒ 缺席 —— **缺席从不命名一个词**,也不等于「不强制」(读 `mandated`)。值经 `approval-card.ts` 的
@@ -488,7 +551,7 @@ export interface ToolApprovalFrame {
488
551
  */
489
552
  mandate?: PersistedRuleMandate;
490
553
  /**
491
- * **[ref]③/[ref]**(core 7.5.0;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 的**出身**:
554
+ * **[ref]③/[ref]**(core 7.5.0;**ADDITIVE**)—— 这只 ask 的**出身**:
492
555
  * 谁提的这一问,一个 core 闭集词(`ASK_ORIGINS` **11 员**,core 7.14.0 现值:content_question /
493
556
  * ancestor_marked / org_unavailable / org_rule / rule_store_unavailable / hook / ask_rule /
494
557
  * denial_limit_fallback / shell_gate_tighten / safety_tighten / policy)。引擎在门上盖章(core d.ts:
@@ -518,7 +581,7 @@ export interface ToolApprovalFrame {
518
581
  */
519
582
  origin?: string;
520
583
  /**
521
- * **ADDITIVE,`"tool_approval"` only** —— 这一问的调用是**一张扩展注册自己发起**的(`$.tool.call`,core 7.56.0 `AskRequest.requestedBy`):
584
+ * **ADDITIVE,卡外 / 卡内事实** —— 这一问的调用是**一张扩展注册自己发起**的(`$.tool.call`,core 7.56.0 `AskRequest.requestedBy`):
522
585
  * `{ kind: "extension", name }`,卡上「扩展 X 想跑 …」那一行的出处。模型消息带来的调用上缺席。display 事实,不是裁决输入。
523
586
  * 读法与 `tool_start` / `tool_end` 上的同名键是同一只(`trace/extension-call-face.ts`:注册名过注册方文本的出口纪律,与 `wiring_manifest.mods[]` 的 `name`
524
587
  * 逐字节同;形不对 ⇒ 丢 + 计一次)。呈卡腿上它是 `approval_request` 顶层的卡外座之一(`APPROVAL_REQUEST_LIVE_FACT_KEYS`,同一只帧对象的值);
@@ -526,7 +589,7 @@ export interface ToolApprovalFrame {
526
589
  */
527
590
  requestedBy?: ExtensionRequesterFace;
528
591
  /**
529
- * **[ref] ②(core 7.37.0 [ref];ADDITIVE,`"tool_approval"` only)** —— 这一问的**类**:`classes` 的首员(core `ASK_CLASSES` 序),
592
+ * **[ref] ②(core 7.37.0 [ref];ADDITIVE,卡外 / 卡内事实)** —— 这一问的**类**:`classes` 的首员(core `ASK_CLASSES` 序),
530
593
  * `MODE_ARBITRATION` 的行键(权限模式读的就是它 / 它们)。引擎在每一个铸 `origin` 的站盖章(策略自报的值在盖章处被替换),本仓经
531
594
  * `approval-card.ts` 的 `readAskClassPair(req)` 窄读(判法 = core 屏 `screenAskClassMembers`,[ref] ⑥ / [ref],本仓零自写对判;屏拒 ⇒ 两键都不投 + 计一次
532
595
  * [ref] 集外 tag)。**与 {@link classes} 同在同缺**;缺席 = 老引擎 / 不盖类的站(共享制品读确认,core [ref]),不是「无类」。
@@ -539,7 +602,7 @@ export interface ToolApprovalFrame {
539
602
  * 几类)。与 `askClass` 同在同缺、同一只窄读;逐字同序过境,不排序不去重。 */
540
603
  classes?: AskClass[];
541
604
  /**
542
- * core 7.43.0 [ref] / [ref](**ADDITIVE**,`"tool_approval"` only)—— 对引擎 `Skill` 工具的调用,批准它**还授予**的东西的摘要
605
+ * core 7.43.0 [ref] / [ref](**ADDITIVE**)—— 对引擎 `Skill` 工具的调用,批准它**还授予**的东西的摘要
543
606
  * (`AskRequest.boundGrantDigest`,技能名 + 两只清单规范拼写的哈希);别的卡缺席。与停驻行 / inbox 行的同名位同值(core:同一只工厂铸,
544
607
  * 活卡与它的停驻孪生按 `(toolCallId, boundGrantDigest)` 对账)。逐字过境,本仓不重算;站着的答案按「工具 + 它」记([ref])。
545
608
  */
@@ -547,7 +610,7 @@ export interface ToolApprovalFrame {
547
610
  /** 上一位哈希的那一份值:`{ skill, allowedTools, disallowedTools }`(`skill: null` = 调用没点名任何已载技能)。与摘要同在同缺;**部署文本**,
548
611
  * 壳按上下文转义渲染(core:display metadata)。逐字过境。 */
549
612
  boundGrants?: BoundSkillGrants;
550
- /** [ref](core 7.51.0 [ref],**ADDITIVE**,`"tool_approval"` only):这张卡为什么没有 {@link boundGrantDigest} —— 引擎铸的每张卡恰带两者之一:
613
+ /** [ref](core 7.51.0 [ref],**ADDITIVE**):这张卡为什么没有 {@link boundGrantDigest} —— 引擎铸的每张卡恰带两者之一:
551
614
  * `not_bindable`(这一问不是引擎 `Skill` 工具的激活,不绑任何授予 ⇒ 应答可按工具记)/ `unreadable`(绑着却读不出;活卡上引擎恒给摘要,这一词
552
615
  * 只出现在读存量行的面上)。闭集经 `readClosedWordSeat(req, "boundGrantAbsence")` 窄读(筛 = core `BOUND_GRANT_ABSENCES`),集外 ⇒ 缺席 + 计一次。
553
616
  * 与停驻行 / 运维队列行 / inbox 行的同名位同值;站着的答案的授予绑定读它(`standing-answer-grant.ts` `grantBindingOf`,问是谁的都同读)。display。 */
@@ -556,7 +619,7 @@ export interface ToolApprovalFrame {
556
619
  * `readClosedWordSeat(req, "classifierNoRuling")` 窄读(筛 = core `isAutoModeFallbackCause`),集外 ⇒ 缺席 + 计一次。display:本仓不按它裁决。 */
557
620
  classifierNoRuling?: AutoModeFallbackCause;
558
621
  /**
559
- * **core 7.49.0 [ref](ADDITIVE,`"tool_approval"` only)—— 这一问渲在哪张卡上**:引擎在闸站铸的那一个词(闭集 = core 的 `TOOL_APPROVAL_CARDS`,
622
+ * **core 7.49.0 [ref](ADDITIVE,卡外 / 卡内事实)—— 这一问渲在哪张卡上**:引擎在闸站铸的那一个词(闭集 = core 的 `TOOL_APPROVAL_CARDS`,
560
623
  * 本文不抄词表 —— 词表的唯一写者在引擎),`AskRequest.approvalCard` 逐字过境,经
561
624
  * `approval-content-kind.ts` 的 `readApprovalCard` 闭集窄读(集外 ⇒ 缺席 + 计一次 closed-word-out-of-set)。`question` = 问用户的问题(引擎保留的
562
625
  * 问答工具),不是副作用工具。**本仓不从工具名回推卡**(工具名只作展示):此前按名字铸的 `livePending` 行 / 队列行 `contentKind` 随本键删。
@@ -566,7 +629,7 @@ export interface ToolApprovalFrame {
566
629
  */
567
630
  approvalCard?: ToolApprovalCard;
568
631
  /**
569
- * **[ref]**(core 7.19.0;**ADDITIVE**,`"tool_approval"` only)—— 这只**根外读** ask 的**清障目录**:
632
+ * **[ref]**(core 7.19.0;**ADDITIVE**)—— 这只**根外读** ask 的**清障目录**:
570
633
  * 把 `dir` 加进本会话的读目录(壳侧既有的 `/add-dir` 口),同一条调用就不会再问。
571
634
  *
572
635
  * 🔴 **在场才读,永远不读缺席**。缺席不是「无计可施」:它同时覆盖敏感路径 deny 行(按模式判,加任何
@@ -585,11 +648,11 @@ export interface ToolApprovalFrame {
585
648
  * 一只 PARKED 的根外读 ask 渲的仍是单独那张确认卡。所以停驻行 / 运维队列行 / inbox 行**没有**这一座,本仓也不
586
649
  * 自铸一个(自铸 = 同一事实的第二个源,而且那个源会在 park 兑现时说谎)。问行卡信封的活面事实座(7.143.0)不是自铸:
587
650
  * 它是呈卡帧上这一格的同一份值、同一条写落下,只供同一只还在流上的问的重放帧读(断流续读 / 开流 preamble),
588
- * 射程与卡上 `ruleOffers` 同一句(回授经重放帧自己的 `approvalId` 走活应答口)。
651
+ * 射程与卡上 `ruleOffers` 同一句(回授经重放帧自己的 `askId` 走决断口的 live 形)。
589
652
  */
590
653
  readRootCandidate?: ReadRootGrantCandidate;
591
654
  /**
592
- * **E-14**([ref]② Trojan Source 族;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 的**工具输入**
655
+ * **E-14**([ref]② Trojan Source 族;**ADDITIVE**)—— 这只 ask 的**工具输入**
593
656
  * (`AskRequest.args`)里含 bidi 控制符(LRM/RLM、嵌入/覆写、隔离符;字符类与在场谓词的属主是 core 的 `BIDI_CONTROL_CHARS` / `carriesBidiControls`,经 `text-bidi.ts` 的 `hasBidiControls` 取)。
594
657
  *
595
658
  * 🔴 **真才带,缺席绝不编 `false`**(与 `governanceForced`/`requiresRealApproval` 同形)。缺席的含义是
@@ -601,11 +664,11 @@ export interface ToolApprovalFrame {
601
664
  * 执行的那串字节(卡上显示的与真跑的不是同一个东西),**比不披露更坏**;所以 server 只报「有」,显形
602
665
  * 归壳的渲染面(转义/高亮/加标记,壳自己定)。
603
666
  *
604
- * **判据素材** = `boundArgs` 里对**原字节**(`redactDeep` 之前)的那一次序列化,且在**字节帽判定之前**算:
605
- * · 超帽时 args 以 `argsOmitted:true` 缺席上帧(卡上根本没有 args)—— 那正是人最看不见输入的一格,
667
+ * **判据素材** = `boundArgs` 里对**原字节**(`redactDeep` 之前)的那一次序列化,与折叠判定无关:
668
+ * · 动作卡超帽时 args 以 `argsOmitted:true` 缺席上帧(卡上根本没有 args)—— 那正是人最看不见输入的一格,
606
669
  * 更需要知道「你看不到的那份里有隐形字符」,所以帽不影响本键;
607
- * · 序列化失败(循环引用 / 抛错的 `toJSON` / BigInt)⇒ 两件事一起交白卷:args 不上帧,本键**不铸**
608
- * (两次 `JSON.stringify` 共用同一个 try/catch —— 顶注反对的是第二个**静默降级点**,不是第二次序列化);
670
+ * · 序列化失败(循环引用 / 抛错的 `toJSON` / BigInt;脱敏后那一份或原字节那一份,任一)⇒ 两件事一起交白卷:args 不上帧,本键**不铸**
671
+ * (结局只有一个,且看得见:`argsOmitted`);
609
672
  * · 素材是**原字节**,不是脱敏后那份:7.70.0–7.124.x 的脱敏器吐出剥掉全部 `\p{Cf}` 的文本(bidi 控制符整族都是
610
673
  * `\p{Cf}`),在它上面扫本键恒缺席;7.125.0 起脱敏产物回到原文(认出的凭据跨度映回原文坐标替换,跨度外的
611
674
  * 格式字符逐字保留),原字节与卡面在 bidi 控制符上已无差别,素材仍取原字节(脱敏前那一次序列化,上一条)。
@@ -616,9 +679,9 @@ export interface ToolApprovalFrame {
616
679
  * 在骗你的眼睛」,把两个来源折进一个布尔会让壳无法判断该给哪一段加显形标记。
617
680
  */
618
681
  inputHasBidi?: true;
619
- /** [ref]([ref]② cli 请托;**ADDITIVE**,`"tool_approval"` only,7.34.0+)——窗三键,与
682
+ /** [ref]([ref]② cli 请托;**ADDITIVE**,7.34.0+)——窗三键,与
620
683
  * `approval_request` 帧([ref] 呈卡帧)同名同义:`expiresAtMs` = 本 ask 的绝对到期墙钟
621
- * (有店=行上一次铸定的 `expiresAtMs`,与卡帧/落库同值;无店 D1=注册时刻算定的同名初值),
684
+ * (行上一次铸定的 `expiresAtMs`,与卡帧/落库同值),
622
685
  * `serverNowMs` = **帧铸造时刻**(cli [ref] 锚定语义:倒计时锚=帧到手时刻的服务器钟),
623
686
  * `expiresInMs` = `max(0, expiresAtMs - serverNowMs)` 现算。三键同生同缺(没有活审批通道的腿不发帧,
624
687
  * 发出的帧恒带);旧消费端无感,新壳借此给旧族帧补倒计时([ref] Q2 那类 77 分钟死卡的根治半场)。 */
@@ -626,7 +689,7 @@ export interface ToolApprovalFrame {
626
689
  expiresInMs?: number;
627
690
  serverNowMs?: number;
628
691
  /**
629
- * core 7.42.0 [ref](**硬破坏换名**:取代 7.41.x 的 `persistedRuleShadowed`,零别名;`"tool_approval"` only)——
692
+ * core 7.42.0 [ref](**硬破坏换名**:取代 7.41.x 的 `persistedRuleShadowed`,零别名;卡外 / 卡内事实)——
630
693
  * allow 层里**命中了这次调用、却没能清掉这只 ask** 的成员,每个成员一条 `{ member, entries, omitted? }`:`member` ∈ core `ALLOW_RULE_MEMBERS`
631
694
  * (`hook` 部署 PreToolUse hook 的 allow / `deployment` 运维的 `APPROVAL_GRANT` / `persisted` 人存的 allow 规则 / `skill` 被激活技能的清单 /
632
695
  * `request` 请求的 `settings.permissions.allow`);`entries` = 那个成员命中的条目原文(hook 恒空表);`omitted` = 没列出的条目数。
@@ -649,7 +712,7 @@ export interface ToolApprovalFrame {
649
712
  */
650
713
  allowRuleShadowed?: AllowRuleShadowProjection[];
651
714
  /**
652
- * [ref] 车二(core 5.18.0 [ref]):`"tool_approval"` only —— 引擎为这次 ask 铸的**规则候选**
715
+ * [ref] 车二(core 5.18.0 [ref]):卡外 / 卡内事实 —— 引擎为这次 ask 铸的**规则候选**
653
716
  * (`AskRequest.ruleOffers`,core 5.58.0 判别联合逐字透传:闭词表 `kind`/`match` + 引擎铸的文本,
654
717
  * server 不重铸不重排;序即契约——exact single 恒 0、batch 恒末,选择键=offer index)。
655
718
  * 壳据它渲「不再询问」,回决时用 `persistRule.rule` 报出选中的那一条。
@@ -661,7 +724,7 @@ export interface ToolApprovalFrame {
661
724
  */
662
725
  ruleOffers?: readonly RuleOffer[];
663
726
  /**
664
- * [ref] 第五单(core [ref] 修②;**ADDITIVE**,`"tool_approval"` only)—— `ruleOffers` 的**缺席因由**:
727
+ * [ref] 第五单(core [ref] 修②;**ADDITIVE**)—— `ruleOffers` 的**缺席因由**:
665
728
  * 规则车道在场却无可给时,引擎点名哪扇门关了(闭三词集 `mandated`/`shadowed`/`lane_cannot_speak`,
666
729
  * 引擎侧与 `ruleOffers` 互斥)。壳据它把「为什么没有不再询问」渲成对应文案(`mandated` 臂**不得**
667
730
  * 指向写规则)。ADVISORY 展示元数据、永不是裁决输入;**缺席不是断言**(covers「有 offers」与三扇
@@ -670,7 +733,7 @@ export interface ToolApprovalFrame {
670
733
  */
671
734
  ruleOffersAbsence?: RuleOffersAbsence;
672
735
  /**
673
- * [ref](core 7.4.0 [ref];**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 是 auto 模式分类器的**限额
736
+ * [ref](core 7.4.0 [ref];**ADDITIVE**)—— 这只 ask 是 auto 模式分类器的**限额
674
737
  * 回落卡**:分类器连续(缺省 3)或累计(缺省 20)拒到限额的**那一次**调用不再静默 deny,而是落成一张
675
738
  * 必须真人批的卡(同一次铸造同时盖 `requiresRealApproval`,两键是孪生)。
676
739
  * `{consecutive, total, limit:"consecutive"|"total", autoDenyAfterMs}` —— 触限时的两个计数、哪一道界
@@ -692,7 +755,7 @@ export interface ToolApprovalFrame {
692
755
  */
693
756
  denialLimitFallback?: DenialLimitFallback;
694
757
  /**
695
- * [ref] 件 G1(core 5.33.0 backlog [ref],判据帖 [ref] G1;**ADDITIVE**,`"tool_approval"` only)——
758
+ * [ref] 件 G1(core 5.33.0 backlog [ref],判据帖 [ref] G1;**ADDITIVE**)——
696
759
  * 这次 ask **为什么**被收紧的**结构化**因由(`AskRequest.probeCause`:工具的 `reversibilityProbe`
697
760
  * 判不出可回滚时,引擎在 maybe 档收紧点铸并 `normalizeProbeCause` 校验过的那一只)。
698
761
  *
@@ -724,7 +787,7 @@ export interface ToolApprovalFrame {
724
787
  };
725
788
  };
726
789
  /**
727
- * [ref](7.115.0;**ADDITIVE**,`"tool_approval"` only)—— 这次 ask 被收紧时探针给出的那一句**散文**因由
790
+ * [ref](7.115.0;**ADDITIVE**)—— 这次 ask 被收紧时探针给出的那一句**散文**因由
728
791
  * (`AskRequest.probeReason`:core 在 maybe 档收紧点 `inlineUntrusted(…, 200)` 过的一句话)。与
729
792
  * {@link probeCause}(结构化因由)**并列、不替代**:引擎自己铸的因由走结构位,**部署自写的探针**只会写这一句
730
793
  * —— 一只只给 reason 不给 cause 的探针,此前其审批人在活卡上读不到任何因由(耐久面
@@ -740,7 +803,7 @@ export interface ToolApprovalFrame {
740
803
  */
741
804
  probeReason?: string;
742
805
  /**
743
- * [ref] 件 G2(core 5.35.0 [ref] G-2;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 背后的
806
+ * [ref] 件 G2(core 5.35.0 [ref] G-2;**ADDITIVE**)—— 这只 ask 背后的
744
807
  * **规则出处证据**(`AskRequest.ruleEvidence`,引擎在 gate 内盖章):org 快照 `orgRevision` / 命中的
745
808
  * org 规则原文 `orgRule` / 被越级个人规则的 add dots `personalRuleDots`,**每员 = 值或五词命名缺席**
746
809
  * (`not_wired|not_adjudicated|unavailable|no_match|not_reported`,core `AskEvidenceAbsence` 闭集)。
@@ -758,49 +821,17 @@ export interface ToolApprovalFrame {
758
821
  * 本键的 dots 是那条规则的**机器身份**(a rule is a set of adds;数组即身份,消费端禁 join 成标量)。
759
822
  */
760
823
  ruleEvidence?: RuleEvidenceProjection;
761
- /** "tool_approval" only: the tool call's args, secret-redacted, UNTRUSTED-for-display. Absent (with
824
+ /** the tool call's args, secret-redacted, UNTRUSTED-for-display. Absent (with
762
825
  * `argsOmitted: true`) when over the byte cap or unserializable. */
763
826
  args?: unknown;
764
827
  argsOmitted?: boolean;
765
- /** [ref] 随批小件([ref]-5 视觉真空的 server 半场;**ADDITIVE**,`"tool_approval_complete"` only,
766
- * 真才带)——`outcome:"expired"` 一词三义(park / 当场 deny / 无设施 deny,见 outcome 注)里 **park
767
- * 那一义的显式判别位**:在场 ⇔ **这条 ask 本身**按 park 路由收尾(`parkRouted`,settle 咽喉里置位;
768
- * [ref] F1/F3:首版读政策口〔unattendedPolicy+askStore 在场〕,对批内被连坐 VOID 的兄弟、取消/断连、
769
- * D5 fail-open 等非 park 终局全撒谎)。同一把 `approvalId`(= 行的键)仍可打 `respond` 走迟到受理兑现
770
- * (wire 契约迟到受理段;迟到腿直接读行,任一副本可达)。
771
- * 壳据此把「卡失效」改渲「已转后台候批」。缺席**禁**读作
772
- * 「真 deny」:无店部署 / deny 政策 / VOID 兄弟都发不出这个键,缺席只是「无 park 证据」。 */
773
- parked?: true;
774
- /**
775
- * "tool_approval_complete" only: how the ask settled. `allowed`/`denied` = a human decision.
776
- *
777
- * 🔴 `expired` = **这张卡失效了**(TTL / abort / 断连 / 批内兄弟被撤卡 superseded),**不等于「这次调用
778
- * 被拒了」**([ref]:本注上一版逐字写着「fail-closed deny the shell should render as such」——那是
779
- * [ref] 断连转 park 与 [ref] R-13 窗到期转 park **之前**的语义,两批都没回来改这一行)。同一个词今天有
780
- * 三种落点,由部署决定,壳**不能**从这个词自己推出终局:
781
- * · park 设施在场 + 缺省 `park` 政策 ⇒ core durable park(run 挂起候补批,`shapeOutcome` 交
782
- * `"unavailable"` 而本帧仍发 `expired`);
783
- * · `UNATTENDED_APPROVAL_POLICY=deny` ⇒ 当场 fail-closed deny(旧注只描述了这一支);
784
- * · 无 park 设施的部署 ⇒ core 自己 fail-closed deny。
785
- * ⇒ 壳把它渲成「卡消失了」,**终局读 done 帧的 `status`/`errorCode`/`pendingGate`**。成文真源 =
786
- * docs/ASSISTANT-WIRE-CONTRACT.md §4a-bis(「别把 expired 本身当拒绝回执渲染」)。
787
- * 成因表也补了第四支:`settleVoidedSiblings` 的撤卡兄弟走的同样是这个词,那既不是 TTL 也不是断连。
788
- * Cosmetic dialog-dismiss(这句仍成立——它讲的是**帧的角色**,不是终局)。
789
- */
790
- outcome?: SettleOutcome;
791
- /**
792
- * "tool_approval_complete" only(**ADDITIVE**):`outcome:"expired"` 的**成因** —— 与审计 settle 行 `cause` 是同一个词(闭集 {@link SettleCause}:窗到期 / 广播全灭 /
793
- * 断连 / 呈不出去 / run 取消 / run 退出 / 批撤 / 兄弟被撤 / 崩溃 / 关停 ……)。**在场 ⇔ 非人结局**;人答(`allowed` / `denied`)不带。壳据它把「卡消失了」渲成具体的话
794
- * (「已取消」「已到期」「断连」各自一句),而不再只有 `expired` 一个词。⚠️ 缺席不是证据:旧 server 从不发这个键,人答也不发。
795
- */
796
- cause?: SettleCause;
797
828
  }
798
829
  /** The per-run context `ask` recovers via ALS (mirrors QuestionRunContext + sessionId, which keys the allow-all). */
799
830
  /** [ref]:`GET /v1/approvals` 第二顶层键 `livePending` 的行形(与 durable `pending` 行**分数组不混编**
800
- * ——两族行形与决议路由不同:本族行的决议口=`POST /v1/tool-approvals/:approvalId/respond`,durable 行
831
+ * ——两族行形与决议路由不同:本族行的决议口=决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`,durable 行
801
832
  * =decide 口;数组名即路由判据)。可选位全部「只记真、缺席不编」。 */
802
833
  export interface LivePendingRow {
803
- /** = `respond()` / `GET /v1/tool-approvals/:id` 收的 wire id:有行的 ask = 行的键 `askId`,无行的 ask = 登记本地键(见 {@link PendingApproval.approvalId})。 */
834
+ /** 这只 ask 的 wire 身份 = 行的键 `askId`(与内嵌帧上的同名键同值;见 {@link PendingApproval.approvalId})。 */
804
835
  approvalId: string;
805
836
  toolName: string;
806
837
  /** 登记时刻(ms epoch)。 */
@@ -831,16 +862,16 @@ export interface LivePendingRow {
831
862
  * 不是「不强制 / 没有出身」—— 消费方按不知道读(强制与否不知道 ⇒ 按强制)。活登记恒不带(活铸帧上恒有事实);只记真。
832
863
  */
833
864
  liveFactsUnknown?: true;
834
- /** 发起者为委派子代(originTaskId 在场)。 */
865
+ /** 发起者为委派子代(`sourceSessionId` 在场)。 */
835
866
  fromSubagent?: true;
836
- /** [ref] C2(additive):委派子代的 **canonical taskId**。值域精确成文(codex R1-F3 问询后按 core dist
837
- * 亲证):值 = `AskRequest.sourceSessionId` = 发起 task 的 sessionId(core prepare-task `askSourceIdentity`);
867
+ /** 委派子代的**会话 id**(additive 键,与内嵌帧 {@link frame} 的卡上的同名键同名同值:一个事实一个名字)。值域精确成文(按 core dist
868
+ * 亲证):值 = `AskRequest.sourceSessionId` = 发起这只问的会话(core prepare-task `askSourceIdentity`);
838
869
  * 而 core 的 canonical taskId = `spec.taskId ?? sessionId`(runtask.js `runSourceTaskId`),Runner 铸的
839
870
  * 委派子代 spec **不带** taskId ⇒ 子代 canonical taskId ≡ 子代 sessionId ≡ 本键 ≡
840
871
  * `task_progress.taskId`(同一 `runSourceTaskId` 铸)—— 关联 join 在本键存在的唯一面(`fromSubagent`
841
- * 子代 ask)上恒等成立。缺席 = 顶层 ask。`fromSubagent` 保留不动(byte-compat:先于本键的消费方仍按
872
+ * 子代 ask)上恒等成立。缺席 = 宿主自身的 ask。`fromSubagent` 保留不动(byte-compat:先于本键的消费方仍按
842
873
  * 它判别)。 */
843
- originTaskId?: string;
874
+ sourceSessionId?: string;
844
875
  /** core 7.49.0 [ref]:这一问的卡词 —— 与 {@link frame} 上的 `approvalCard` **同一个值**(行读帧上那一格,不另读一遍),与 durable
845
876
  * 队列行顶层的同名键同层同形(那一面读门的 `gate.approvalCard`)。缺席 = 引擎没给(宿主自建 ask / 老引擎)。展示/分诊用,永不参与决议路由。
846
877
  * (此前此处是按工具名铸的 `contentKind`,随 [ref] 删:卡只有引擎铸的这一个词。) */
@@ -860,10 +891,9 @@ export interface LivePendingRow {
860
891
  *
861
892
  * 缺席 = 老 server(7.86.0 及以前);本服务自 7.87.0 起**恒在场**(条目上是必填格)。恒不铸 `null`。
862
893
  *
863
- * 🔴 **一只 ask 一个帧族(7.133.0 起)**:呈卡族的 ask(有行 —— 呈卡协议上场的 worker)⇒ 呈卡帧 `approval_request`(卡内事实在 `card` 里,
864
- * 卡外的活面事实在帧顶层);旧族的 ask(无行)⇒ 活卡帧 `tool_approval`。按 `frame.type` 判别。
894
+ * 🔴 **只有一个帧族**:恒是呈卡帧 `approval_request`(卡内事实在 `card` 里,卡外的活面事实在帧顶层)—— 没有行的 ask 不登记、不上列表。
865
895
  */
866
- frame?: ToolApprovalFrame | ApprovalRequestFrame;
896
+ frame?: ApprovalRequestFrame;
867
897
  /**
868
898
  * [ref]:**本副本上没有引擎腿在等这只问** —— 与耐久决断口 200 体同名同值同义的那一位({@link ASK_DECISION_CONSUMER_ABSENT})。
869
899
  * 在场 ⇔ 这一行是审批机起服时从问账接管的问(前一个进程 / 别的副本铸下、行仍 `STREAM_PENDING`;见 {@link ToolApprovalCoordinator.adoptOpenAsks}):
@@ -875,23 +905,19 @@ export interface LivePendingRow {
875
905
  /**
876
906
  * 一条执行腿的审批上下文 = 腿的身份三位 + 腿轴 + **帧族词 + 一只同族传输**。
877
907
  *
878
- * 🔴 **一条腿一个帧族**({@link ApprovalLegFamily}):呈卡协议在本腿上场(装配点按 `resolveApprovalLeg(...).active`)⇒ 族词 `approval_request`,
879
- * 本腿上一只 ask 的开卡 / 消卡 / 撤卡只走呈卡族(`approval_request` / `approval_complete` / `approval_revoke`),旧族帧一帧不发;协议未上场 ⇒
880
- * 族词 `tool_approval`(`tool_approval` / `tool_approval_complete`)。传输按族定型:呈卡族上下文的传输收不进旧族帧,「同一只 ask 在同一条腿上
881
- * 发两种开卡帧」不可构造。消费方在 wire 上判别本腿是哪一族:`GET /v1/capabilities` 的 `streamApproval`(与装配点同一只判据
882
- * `resolveStreamApprovalGate`,按 worker 求值;为真 ⇒ 本 worker 每条呈卡的腿都是呈卡族)。
908
+ * 🔴 **一只 ask 一个帧族,全仓只有一族**(`approval_request`:开卡 `approval_request` / 消卡 `approval_complete` / 批级撤卡 `approval_revoke`)。
909
+ * 只有呈卡协议在本 worker 上场(`resolveStreamApprovalGate(...).active`)、这条腿没关窗、这条 run 声明了这一族时才有上下文
910
+ * ({@link resolveApprovalLeg} 的 `unattended` 缺席);其余每一形这条腿都没有活审批通道,问当场交无人值守政策口 —— 没有「协议没上场就回退发另一族」的腿。
911
+ * 传输按族定型(收不进别的帧)。消费方在 wire 上读同一只判据:`GET /v1/capabilities` 的 `approvalFrameFamilies`(`[]` / `["approval_request"]`)。
883
912
  *
884
913
  * 传输是本腿**一只**(问题 / 表单两只协调器的上下文共用同一只;律在 `hitl-delivery.ts`:先本 run 账本、再直写,账本落不下 ⇒ 不上直写)。
885
914
  */
886
915
  export type ToolApprovalRunContext = ToolApprovalRunContextBase & ApprovalLegFamily;
887
916
  /** 帧族词 + 同族传输(见 {@link ToolApprovalRunContext} 顶注)。族词取自 {@link APPROVAL_FRAME_FAMILIES} 闭集。 */
888
- export type ApprovalLegFamily = {
917
+ export interface ApprovalLegFamily {
889
918
  readonly family: "approval_request";
890
919
  readonly transport: HitlTransport<ApprovalCardLegFrame | ApprovalRevokeFrame>;
891
- } | {
892
- readonly family: "tool_approval";
893
- readonly transport: HitlTransport<ToolApprovalFrame>;
894
- };
920
+ }
895
921
  /** 两族共有的腿身份与腿轴。 */
896
922
  interface ToolApprovalRunContextBase extends ApprovalLegOrigin {
897
923
  taskId: string;
@@ -911,7 +937,6 @@ interface ToolApprovalRunContextBase extends ApprovalLegOrigin {
911
937
  * 可 park 的 ask 拖成 abort-deny。真值由车3 的装配点供给,本车只立形+消费。 */
912
938
  legDeadlineMonotonic?: number;
913
939
  }
914
- export type ToolApprovalDecision = "allow" | "allow_session" | "deny";
915
940
  /**
916
941
  * [ref] 车二:回决回执上 `ruleRefusal` 的**闭词表**(「不再询问」这次为什么没存上)。
917
942
  *
@@ -981,42 +1006,160 @@ export declare const PERSIST_RULE_BATCH_EXCLUSIVE_ERROR = "persistRule.batchOffe
981
1006
  */
982
1007
  /** [ref](core 7.32.0 [ref])—— `readRootGrant` 只随 `decision:"allow"`(CC 卡的第三选项「Yes, and add directory」= 放行这一次
983
1008
  * + 加目录;`allow_session` 不是那一个选项,`deny` 上它没有意义)。裁决之前响亮拒,不静默丢。 */
984
- export declare const READ_ROOT_GRANT_ALLOW_ONLY = "readRootGrant is only meaningful with decision \"allow\" \u2014 it is the card's \"Yes, and add directory\" answer (allow this call and add the card's readRootCandidate.dir to this run's read directories)";
1009
+ export declare const READ_ROOT_GRANT_ALLOW_ONLY = "readRootGrant is only meaningful with a plain allow-this-call decision (not a deny, not a session allow) \u2014 it is the card's \"Yes, and add directory\" answer (allow this call and add the card's readRootCandidate.dir to this run's read directories)";
985
1010
  /**
986
1011
  * [ref]:这台部署不受理读根授权时,带 `readRootGrant` 的应答的拒句。受理与否是**部署姿态**(能力事实 `readRootGrant`,位 `approvalReadRootGrant`;
987
1012
  * 判据的唯一属主在 `capability-facts.ts`,回决路由把它读来交给 {@link ToolApprovalCoordinator.respond}):不受理 ⇒ 裁决**之前**响亮 400,
988
1013
  * 这只 ask 没被结算,同一张卡不带该键的 `allow` 照常成。不静默丢键 —— 壳以为加上了目录而引擎只看到一次普通放行,是 [ref] 修过的那一种病。
989
1014
  */
990
- export declare const READ_ROOT_GRANT_NOT_ACCEPTED = "readRootGrant is not accepted on this deployment \u2014 a read-directory grant is honored only on a single-user host-lane deployment (GET /v1/capabilities approvalReadRootGrant is false here); answer with plain decision \"allow\" instead";
1015
+ export declare const READ_ROOT_GRANT_NOT_ACCEPTED = "readRootGrant is not accepted on this deployment \u2014 a read-directory grant is honored only on a single-user host-lane deployment (GET /v1/capabilities approvalReadRootGrant is false here); answer with a plain allow-this-call decision instead";
991
1016
  /** [ref]:`readRootGrant` 的形 —— 卡上 `readRootCandidate.dir` 的原串(非空,≤ core `READ_ROOT_CANDIDATE_DIR_MAX`;超限整只拒,不截:截过的目录是另一个目录)。 */
992
1017
  export declare const READ_ROOT_GRANT_SHAPE = "readRootGrant must be the card's readRootCandidate.dir sent back byte for byte \u2014 a non-empty string of at most 1024 characters";
993
- export declare const PERSIST_RULE_SCOPE_REFUSED = "this endpoint does not accept a rule scope \u2014 the server mints it from where the approval happened (send neither `scope` nor `persistRule.scope`)";
994
- /** [ref]:`respond()` 要的**部署事实**(由回决路由从能力事实交进;协调器不读 config,也不自判姿态)。 */
995
- export interface ToolApprovalRespondDeployment {
996
- /** 这台部署受理不受理应答体里的 `readRootGrant` —— 能力事实 `readRootGrant` 的 `.available`(位 `approvalReadRootGrant` 的同一个值)。 */
997
- readonly readRootGrantAccepted: boolean;
998
- }
999
- /** {@link parseToolApprovalResponse} 的成功分支形(`respond()` 拆分出的私有收尾方法复用,避免裸内联匿名类型重复三处)。 */
1000
- type ParsedToolApproval = {
1018
+ /**
1019
+ * 读根授权只交得给**在等这张卡的引擎腿**(引擎的问 `AskOutcome.readRootGrant`;续跑的决议形没有这一格)—— 卡已停驻(问行 `PARKED`)时带它 ⇒ 决议之前响亮拒,
1020
+ * 卡不被结算(否则决定生效、目录静默不加)。去掉这一键重决即可。
1021
+ */
1022
+ export declare const READ_ROOT_GRANT_LIVE_ONLY = "readRootGrant can only be honored while the card is live (an engine leg is waiting on it); this ask is parked, so the directory could not be added \u2014 answer it again without readRootGrant";
1023
+ /**
1024
+ * 决定体上读根授权那一键(`readRootGrant`)的**唯一读法**(形门 + 只随「放行这一次」门;都只看体就能判 ⇒ 裁决之前、存在性之前响亮拒,卡不被结算)。
1025
+ * `plainApprove` = 这次决定是不带「本会话放行」的放行。只判形,**不判**它是不是那张卡上的串(判官是 core:对不上 ⇒ 引擎拒授权、放行照旧)。
1026
+ * 受理姿态(部署事实 `readRootGrant`,{@link READ_ROOT_GRANT_NOT_ACCEPTED})由口在本读法之后判。
1027
+ */
1028
+ export declare function readReadRootGrantSlot(raw: unknown, plainApprove: boolean): {
1001
1029
  ok: true;
1002
- value: ToolApprovalDecision;
1003
- updatedInput?: unknown;
1004
- persistRule?: ParsedPersistRule;
1005
- note?: string;
1006
- decider: ApprovalDecider;
1007
- readRootGrant?: string;
1030
+ grant?: string;
1031
+ } | {
1032
+ ok: false;
1033
+ error: string;
1008
1034
  };
1035
+ export declare const PERSIST_RULE_SCOPE_REFUSED = "this endpoint does not accept a rule scope \u2014 the server mints it from where the approval happened (send neither `scope` nor `persistRule.scope`)";
1009
1036
  /**
1010
- * Validate the respond body — the closed three-choice enum (rationale in the module header).
1011
- *
1012
- * 失败形的机读位:体里带着退役键 `settledBy` 的任何一次拒(无论这次拒的**句子**说的是它还是体里别的毛病 —— 校验是顺序短路的,先撞上谁谁说话)都另带
1013
- * 机读位 `field`({@link retiredDecisionKeyFacts} 的 `extra`,三条决定口同一只铸点;`respond()` 映射 400 时带出);拒的成因就是退役键时,**句**也取自同一铸点。
1014
- * 铸在**这一层**而不是散在下面每个失败 return 上:一个事实一处读。
1037
+ * `persistRule` 位的**唯一体形判官**(凡能决一张工具审批卡的口都调它:活卡回决口、耐久决断口 `/decide`;拒句一字不改)。
1038
+ * 两个显式臂:候选臂(缺 `edited` 或 `edited:false`,文本是卡上某只候选的逐字文本)/ 自由文本臂(`edited:true`,人手改过的规则);batch 臂用 `batchOfferIndex`
1039
+ * (面上候选数组的下标),与文本两臂互斥。`scope` 不属于携带方(server 从授权发生地自铸)。`deny` 带这一位 ⇒ 忽略(人拒了这次操作,谈不上持久化同意)。
1015
1040
  */
1016
- export declare function parseToolApprovalResponse(body: unknown): ParsedToolApproval | ({
1041
+ export declare function readPersistRuleSlot(raw: unknown, decision: "allow" | "deny"): {
1042
+ ok: true;
1043
+ slot?: ParsedPersistRule;
1044
+ } | {
1017
1045
  ok: false;
1018
1046
  error: string;
1019
- } & Partial<RetiredDecisionKeyFacts["extra"]>);
1047
+ };
1048
+ /** 一张卡铸时的那一份规则记录(兑付的唯一素材;三只读者各从自己的载体读出同一形)。 */
1049
+ export interface CardRuleRecord {
1050
+ /** 规则落在谁名下 = 这一次决断的门判过的那位属主(收编之后是新属主)。 */
1051
+ readonly owner: string;
1052
+ readonly toolName: string;
1053
+ /** 卡形的绑定值(被裁决的命令原字节,或值形卡的那一只值;`cardBindingOf`)。 */
1054
+ readonly command: string;
1055
+ /** 唯一读者 `readCardRuleOffers` 读出的那份数组(原字)—— 面上投出的候选是它的展示形,下标同一个空间。 */
1056
+ readonly offers: readonly RuleOffer[];
1057
+ readonly toolCallId?: string;
1058
+ readonly boundInputHash?: string;
1059
+ /** 铸卡快照的 project root;缺席 = 授权发生地在 server 坐标系里不可知 ⇒ 不铸 scope(core 答 `scope-unresolved`,只会拒不会放宽)。 */
1060
+ readonly scopeRoot?: string;
1061
+ }
1062
+ /** 记录读者的读数:读出一份记录,或说清为什么没有(三个词都是 {@link RuleRefusalReason} 的成员,回执原样带出)。 */
1063
+ export type CardRuleRecordReading = {
1064
+ readonly kind: "record";
1065
+ readonly record: CardRuleRecord;
1066
+ } | {
1067
+ readonly kind: "absent";
1068
+ readonly refusal: "rule_lane_unavailable" | "rule_governance_forced" | "rule_material_absent" | "rule_store_error";
1069
+ };
1070
+ /** 规则位的回执(键集 = 契约里回决回执的规则位五键;只出现在带了 `persistRule` 的首决回执上,幂等回放不带)。 */
1071
+ export interface RuleSlotReceipt {
1072
+ readonly rulePersisted: boolean;
1073
+ readonly ruleRefusal?: RuleRefusalReason;
1074
+ /** 自由文本臂落下的**规范拼写**(core 可能把 `Bash(adb *)` 规范成 `Bash(adb:*)`)。 */
1075
+ readonly persistedRule?: string;
1076
+ /** batch 臂落下的规则文本(展示序)。 */
1077
+ readonly persistedRules?: readonly string[];
1078
+ /** batch 臂逐条自描述锚(offer 空间:`offerIndex` = 请求体那个下标,`memberIndex` = 那只批 `rules[]` 的位置);车道证不出归属 ⇒ 缺席。 */
1079
+ readonly persistedRuleAnchors?: readonly {
1080
+ readonly offerIndex: number;
1081
+ readonly memberIndex: number;
1082
+ readonly rule: string;
1083
+ }[];
1084
+ }
1085
+ /**
1086
+ * **有问行的停驻卡**的记录读者:问行上的 `rule_command` / `rule_scope_root`(铸卡快照)/ `card_json`(候选表 / 工具名 / 治理位)/ `tool_call_id` / `bound_input_hash`。
1087
+ * 读它不依赖本副本有没有这张卡的登记(任何副本兑得了);卡读不回来 / 治理档 / `rule_command` 为 NULL(从没进过规则车道,或凭据形在铸行时已扣下)⇒ 没有素材。
1088
+ * `owner` = 续跑腿已复核过的属主;行此刻不带这位属主(收编在两读之间改写了它)⇒ 这一行不是这张卡的记录 ⇒ 没有素材。
1089
+ */
1090
+ export declare function readCardRuleRecordOfAskRow(row: AskRow, owner: string | null): CardRuleRecordReading;
1091
+ /** 一只问行上这张卡铸时的候选(`card_json.ruleOffers`;唯一读者在铸点读过)—— 运维队列行投影有问行的停驻卡时读的就是它(与 {@link readCardRuleRecordOfAskRow} 同一份数组)。
1092
+ * 卡读不回来 ⇒ `undefined`(队列行不投候选,与记录读者的「没有素材」同向)。 */
1093
+ export declare function cardRuleOffersOfAskRow(row: AskRow): readonly RuleOffer[] | undefined;
1094
+ /**
1095
+ * **没有问行的停驻卡**(直停驻 / 窗 0 / 其余不经活卡的工具门)的记录读者:core 在停驻那一刻铸的这一份 —— 候选 = 同一只读者 `readCardRuleOffers` 读
1096
+ * `pendingAction.ruleOffers`(与队列行的投影同一份数组),绑定值 = 与活卡铸点同一只 `cardBindingOf`,治理档 = 行上的治理标(与队列行 `governanceForced`
1097
+ * 同读,调用方交进来),scope = 停驻行上 server 铸的快照列(没有快照的存量行 ⇒ 缺席 ⇒ `scope-unresolved`,与真不可兑同形)。没有引擎铸的候选 ⇒ 没有素材。
1098
+ */
1099
+ export declare function readCardRuleRecordOfParkRow(pa: Pick<Extract<PendingAction, {
1100
+ kind: "tool_approval";
1101
+ }>, "toolName" | "args" | "toolCallId" | "boundInputHash" | "ruleOffers">, facts: {
1102
+ readonly owner: string | null;
1103
+ readonly governanceForced: boolean;
1104
+ readonly scopeRoot: string | null;
1105
+ }): CardRuleRecordReading;
1106
+ /**
1107
+ * **唯一兑付函数**(`persistCardRule` 在 src 里只在这里调)。门序只有一份:治理档 → 车道 / 属主 → 素材缺席 → 提交歧义(`eligible`,只有活卡的提交歧义臂会是 false)
1108
+ * → 编辑放行(`updatedInput` 与 `persistRule` 同在 ⇒ `rule_input_edited`:生效的是编辑后的调用,候选是从原始命令铸的)→ batch 臂(下标指不到 / 指到 single ⇒ `rule_not_offered`)
1109
+ * / 文本臂(候选臂:报来的文本恰好对上一只 single 候选的原字或展示形 ⇒ 兑那一只的原字;对不上或对上不止一只 ⇒ `rule_not_offered`)→ `persistCardRule`
1110
+ * → 失败词原样回 / 店抛 ⇒ `rule_store_error`。失败**不改判**裁决(调用方在裁决已受理之后才调本函数),回执如实说没存上。
1111
+ */
1112
+ export declare function redeemCardRule(lane: RuleConsentLane | undefined, reading: CardRuleRecordReading, slot: ParsedPersistRule, ctx: {
1113
+ readonly inputWasEdited: boolean;
1114
+ readonly eligible: boolean;
1115
+ }): Promise<RuleSlotReceipt>;
1116
+ /** 决断口 live 臂在 CAS 之前握住的那条登记的不透明把手({@link ToolApprovalCoordinator.holdLiveLeg} 铸,只交回 {@link ToolApprovalCoordinator.settleLiveDecision})。 */
1117
+ export interface HeldLiveLeg {
1118
+ readonly askId: string;
1119
+ }
1120
+ /**
1121
+ * 决断口 live 形一次人决随身带来的 live 词(已过各自的唯一读法:`readRememberSlot` / `readReadRootGrantSlot` / {@link readPersistRuleSlot})——
1122
+ * 只在本请求干净赢下 CAS 之后由 {@link ToolApprovalCoordinator.settleLiveDecision} 一处兑。
1123
+ */
1124
+ export interface LiveDecisionExtras {
1125
+ /** 「本会话放行」。 */
1126
+ readonly remember?: "session";
1127
+ /** 读根授权(卡上 `readRootCandidate.dir` 原串)。 */
1128
+ readonly readRootGrant?: string;
1129
+ /** 「不再询问」的规则位。 */
1130
+ readonly persistRule?: ParsedPersistRule;
1131
+ /** 这次放行带了 ctrl+g 编辑(⇒ 规则位答 `rule_input_edited`)。 */
1132
+ readonly inputWasEdited: boolean;
1133
+ }
1134
+ /**
1135
+ * **一次人对一张卡的决定** —— 唯一的人决口(决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`)
1136
+ * 两形(live / 停驻)落行的唯一入参形;{@link ToolApprovalCoordinator.writeAskDecision} 是它唯一的写者,{@link askDecisionRecordOf} 是它到店记录的唯一映射。
1137
+ * `actor` = 耐久决断口铸的署名(审计投影,恒由已验证主体派生;应答口不铸,列 NULL);`idempotencyKey` = 耐久决断口的回决幂等键(应答口没有这一位)。
1138
+ */
1139
+ export interface AskDecisionWrite {
1140
+ readonly decision: AskDecision;
1141
+ readonly decider: ApprovalDecider;
1142
+ readonly note?: string;
1143
+ readonly actor?: unknown;
1144
+ readonly idempotencyKey?: string;
1145
+ }
1146
+ /** live 形的决定另带 ctrl+g 编辑实参(`undefined` = 没带;**`null` 是值**,语义三态的属主 = `AskRow.updatedInput`):随决议同一条 CAS 落列、交给在等的那条腿。
1147
+ * 停驻形的编辑走停驻门的绑定(`DecideBinding.updatedInput`),不落问行。 */
1148
+ export interface LiveAskDecisionWrite extends AskDecisionWrite {
1149
+ readonly updatedInput?: unknown;
1150
+ }
1151
+ /** 一张卡的人决落在哪一形上:live = `STREAM_PENDING → DECIDED` 的单赢者 CAS(带批维);停驻 = 停驻门受理之后落在仍 `PARKED` 的行上。 */
1152
+ export type AskDecisionForm = {
1153
+ readonly kind: "live";
1154
+ readonly batchId: string;
1155
+ } | {
1156
+ readonly kind: "parked";
1157
+ };
1158
+ /**
1159
+ * {@link AskDecisionWrite} → 店的那份记录({@link AskDecisionRecord})—— **唯一映射**(两形同读)。出处两格经同步座映射 {@link liveHostSource}
1160
+ * (`person` ⇒ 不写 = 列 NULL = 人决;`policy` ⇒ `"policy"` + 座位),理由空 ⇒ NULL,署名 / 键缺席 ⇒ NULL。
1161
+ */
1162
+ export declare function askDecisionRecordOf(write: AskDecisionWrite): AskDecisionRecord;
1020
1163
  /**
1021
1164
  * [ref] R-13 C —— `UNATTENDED_APPROVAL_POLICY` 的**闭集**词表([ref]Q1「裁2:A+C」/[ref] 裁②)。
1022
1165
  *
@@ -1064,32 +1207,30 @@ export type UnattendedAskOutcome = Extract<AskOutcome, "unavailable"> | Unattend
1064
1207
  /** [ref] 候裁 16:耐久会话授权店(`src/plugins/approval-exemption-store.ts` 的同一只店):审批席读它(引擎的问),活卡上部署名单那一问的
1065
1208
  * 「本会话放行」写它(名单门在出问之前读同一行)。 */
1066
1209
  export type SessionGrantStore = Pick<ApprovalExemptionStore, "has" | "grant">;
1067
- /** redactDeep + size-bound the UNTRUSTED tool args before they are streamed. Over the cap / unserializable ⇒
1068
- * undefined (frame rides argsOmitted — see MAX_APPROVAL_ARGS_BYTES). */
1069
1210
  /**
1070
- * 给审批人看的一份入参 —— 卡上 `args` 的**同一种读法**({@link boundArgs}:脱敏 + 字节帽;超帽 / 序列化不出 ⇒ `undefined`)。
1211
+ * 给审批人看的一份入参 —— 卡上 `args` 的**同一种读法**({@link boundArgs} → `human-facing-args.ts` 的 `humanFacingArgs`:脱敏;问 / 计划卡整份,
1212
+ * 其余卡与无卡超 `HUMAN_FACING_ARGS_BYTES` UTF-8 字节 ⇒ `undefined`;序列化不出 ⇒ `undefined`)。与停驻行 `input` 同一只判定。
1071
1213
  * 读者:卡帧 / 卡面(经 `boundArgs` 本体)与续跑拒体的 `acceptableForm`(core 7.56.0 [ref]:编辑复判只收改写后的那一形,人在决定口看到它、批准它)。
1072
1214
  */
1073
- export declare function approverFacingArgs(args: unknown): unknown;
1215
+ export declare function approverFacingArgs(args: unknown, card: ToolApprovalCard | undefined): unknown;
1074
1216
  /**
1075
1217
  * [ref] 车3 刀 3b —— 「流内审批协议到底上不上场」的**单一谓词**(设计稿 §2.3 注入 / §2.4 能力面 /
1076
1218
  * §8.4 park 设施自检,三处同一份判据)。
1077
1219
  *
1078
1220
  * 🔴 为什么必须是一个函数而不是三处各写一遍的合取式:车4 落地时曾在回决端点里放了一份局部的
1079
1221
  * `backend.kind !== "local"` 临时判据,并在注释里写死「等能力面谓词落地就换掉本段 —— 两份判据长期并存
1080
- * 必然漂」。这就是那一车。三个消费点(协调器注入 / `/v1/capabilities` / 回决端点 501)现在读同一个符号,
1081
- * 于是「能力面说 true」⟺「协调器真拿到了 askStore」⟺「回决端点真有账可 CAS」是**结构成立**的,
1222
+ * 必然漂」。这就是那一车。三个消费点(协调器构造 / `/v1/capabilities` / 回决端点 501)现在读同一个符号,
1223
+ * 于是「能力面说 true」⟺「协调器在场(恒带 askStore)」⟺「回决端点真有账可 CAS」是**结构成立**的,
1082
1224
  * 不再靠三处注释互相提醒。
1083
1225
  *
1084
- * 四个合取项,缺一即不上场(每一项的缺席都有它自己的 `reason`,供启动期 info 与诊断分辨):
1085
- * 1. `toolApprovalEnabled` —— 连活卡腿都没有,谈不上流内协议;
1086
- * 2. `streamApprovalEnabled` —— 协议总开关(`STREAM_APPROVAL_ENABLED`,树上已**默认 ON**;显式 `false`
1087
- * 是唯一干净还原键。默认极性与版本坐标的属主口径见 `config.ts` 的 `streamApprovalConfig()` 头注);
1088
- * 3. `backend` 在场 —— env-only worker 没有 `StoreBackend` 本体;
1089
- * 4. **park 设施在场**(§8.4)—— 缺席时「窗到期 ⇒ unavailable」在 core 侧没有降级目的地,结局是
1090
- * fail-closed deny,**比现状(5min 活卡、人能批)更差**。所以自检不满足 ⇒ **协议不上场**、现行
1091
- * `tool_approval` 活卡腿逐字保留,而不是「把 ask 推向一个不存在的目的地」(§14 属主照准,core [ref]
1092
- * 回帖确认即原意)。
1226
+ * 三个合取项,缺一即不上场(每一项的缺席都有它自己的 `reason`,供启动期 info 与诊断分辨):
1227
+ * 1. `toolApprovalEnabled` —— 连审批席都没有,谈不上呈卡;
1228
+ * 2. `backend` 在场 —— env-only worker 没有 `StoreBackend` 本体,也就没有 ask 账;
1229
+ * 3. **park 设施在场**(§8.4)—— 缺席时「窗到期 ⇒ unavailable」在 core 侧没有降级目的地。
1230
+ * 🔴 **不上场 ⇒ 这台 worker 不呈卡,也没有审批协调器**(`boot/coordinators.ts` 不构造它;协调器缺席 = 协议不上场,消费方一律这样读):
1231
+ * 审批只有一个帧族(呈卡族,开卡帧无持久身份不铸),没有「协议没上场就回退发另一族活卡」的腿。没有审批席 ⇒ 受门的问的终局归 core:
1232
+ * 第 1 项不满足(开关关)而 park 设施在场 ⇒ 照常 durable park;第 2 / 3 项不满足 ⇒ 无处可停,core 的无审批席臂当场拒(fail-closed)。
1233
+ * 曾经的第二项(协议总开关 `STREAM_APPROVAL_ENABLED`)与它的拒因词一起退役(零别名):那个开关的「关」就是回退发旧族活卡,旧族没了它就没有可关的东西。
1093
1234
  *
1094
1235
  * 🔴 **[ref]:第 5 项(旧第 4 项 `volatile_ask_ledger` = 「账必须是持久的」,判据 `kind !== "local"`)
1095
1236
  * 已整条删除,词也从闭集里删了(零别名)**。它当年成立的唯一输入是 local 车道交的 `InMemoryApprovalAskStore`;
@@ -1104,20 +1245,12 @@ export type StreamApprovalGate<TStore extends GateCurrencyStore = GateCurrencySt
1104
1245
  checkpointStore: TStore;
1105
1246
  } | {
1106
1247
  active: false;
1107
- reason: "no_tool_approval" | "protocol_disabled" | "no_backend" | "no_park_facility";
1248
+ reason: "no_tool_approval" | "no_backend" | "no_park_facility";
1108
1249
  };
1109
1250
  /** {@link resolveStreamApprovalGate} 的入参。`backend` 用**结构形**(不 import `StoreBackend`):本模块是
1110
1251
  * 协调器的家,不该为一个布尔判据把整棵 store 依赖树拖进类型面。 */
1111
1252
  export interface StreamApprovalGateInput<TStore extends GateCurrencyStore = GateCurrencyStore> {
1112
1253
  toolApprovalEnabled: boolean;
1113
- /** 协议总开关。⚠️ 调用点一律写 `config.streamApproval?.enabled === true` —— **可选链的缺席臂折算
1114
- * false**(段整段缺席 ⇒ 协议不上场)。
1115
- * 🔴 当年这条写的理由是「缺席折算值 == 产品默认(那时是 OFF)」,所以 `?.` 纯粹无副作用;产品默认
1116
- * 现已翻 ON(`config.ts` 的 `streamApprovalConfig()`),两者**不再相等**,那条理由作废。现行的
1117
- * (更弱也更诚实的)判据:真实 boot 恒有此段(`config.ts` 无条件铸 + 白名单门盯着),`?.` 服务的只是
1118
- * 那些只填被测路由用得到的键的 stub-harness,而一个没填这个段的 harness 要的必然是「别上场」。
1119
- * **不要**照「缺席 = 与产品默认同」去推理。 */
1120
- streamApprovalEnabled: boolean;
1121
1254
  backend: {
1122
1255
  readonly kind: "mysql" | "pg" | "local";
1123
1256
  approvalAsk(): ApprovalAskStore;
@@ -1133,25 +1266,22 @@ export interface StreamApprovalGateInput<TStore extends GateCurrencyStore = Gate
1133
1266
  }
1134
1267
  export declare function resolveStreamApprovalGate<TStore extends GateCurrencyStore>(input: StreamApprovalGateInput<TStore>): StreamApprovalGate<TStore>;
1135
1268
  /**
1136
- * 审批开卡帧的**帧族词表**(闭集)—— wire 上一只 ask 的开卡帧可能属于的族:
1137
- * · `tool_approval`:旧族(活卡帧 `tool_approval` / 消卡帧 `tool_approval_complete`);
1138
- * · `approval_request`:呈卡族(开卡帧 `approval_request` / 消卡帧 `approval_complete` / 批级撤卡帧 `approval_revoke`)。
1269
+ * 审批开卡帧的**帧族词表**(闭集,一个词)—— `approval_request`:开卡帧 `approval_request` / 消卡帧 `approval_complete` / 批级撤卡帧 `approval_revoke`。
1139
1270
  *
1140
- * 一条腿选哪个族只由上面 {@link resolveStreamApprovalGate} 的 `active` 定(为真 ⇒ 上下文的族词 `approval_request`;为假 ⇒ `tool_approval`,
1141
- * 见 {@link ToolApprovalRunContext});`GET /v1/capabilities` 的 `approvalFrameFamilies` 把**同一份**判据结果(能力事实 `streamApproval` 的那一次求值)
1142
- * 译成本词表里的词(`capability-facts.ts` 的 `approvalFrameFamilies`,对判据拒因的穷举 switch:拒因多一个 ⇒ 编译红)。
1143
- * 腿选口的规则与能力位的映射是同一条,由 `test/stream-approval-on-e2e.test.ts` 在同一台 worker 上拿真腿发出的开卡帧族对拍能力位,不靠注释互相提醒。
1271
+ * 一台 worker 呈不呈这一族只由上面 {@link resolveStreamApprovalGate} 的 `active` 定({@link presentedApprovalFrameFamily});`GET /v1/capabilities` 的
1272
+ * `approvalFrameFamilies` 是**同一份**判据结果(能力事实 `streamApproval` 的那一次求值)的投影:`["approval_request"]` / `[]`。
1273
+ * 腿判的规则与能力位的映射是同一条,由 `test/stream-approval-on-e2e.test.ts` 在同一台 worker 上拿真腿发出的开卡帧族对拍能力位,不靠注释互相提醒。
1144
1274
  * 词表只有这一份(元组即类型);加一族而没有逐处跟进 ⇒ `test/capability-facts.test.ts` 的 `satisfies Record<ApprovalFrameFamily, true>` 编译红。
1145
1275
  */
1146
- export declare const APPROVAL_FRAME_FAMILIES: readonly ["tool_approval", "approval_request"];
1276
+ export declare const APPROVAL_FRAME_FAMILIES: readonly ["approval_request"];
1147
1277
  export type ApprovalFrameFamily = (typeof APPROVAL_FRAME_FAMILIES)[number];
1148
1278
  /**
1149
- * 这台 worker **呈卡用的那一个族**(活卡协调器在场时)—— 全仓唯一的映射,三个读者:能力位 `approvalFrameFamilies`(`capability-facts.ts`,
1150
- * 壳读它决定声明什么)、{@link resolveApprovalLeg}(腿判「这条 run 声明了没有」)与耐久事件流开流 preamble(`routes/runs.ts`:这条 run 名下的卡
1151
- * 铸于声明了这一族的腿,卡作证的声明就是它)。各写一份三元式 = 壳照一份声明、服务端照另一份判,那正是 [ref] 要封的「两边各说各话」。
1279
+ * 这台 worker **呈卡用的族**(缺席 = 这台 worker 不呈卡)—— 全仓唯一的映射,三个读者:能力位 `approvalFrameFamilies`(`capability-facts.ts`,
1280
+ * 壳读它决定声明什么)、{@link resolveApprovalLeg}(腿判「这台 worker 呈不呈卡、这条 run 声明了没有」)与耐久事件流开流 preamble(`routes/runs.ts`:这条 run
1281
+ * 名下的卡铸于声明了这一族的腿,卡作证的声明就是它)。各写一份三元式 = 壳照一份声明、服务端照另一份判,那正是 [ref] 要封的「两边各说各话」。
1152
1282
  * 入参 = {@link resolveStreamApprovalGate} 的 `active`。
1153
1283
  */
1154
- export declare function presentedApprovalFrameFamily(streamApprovalOn: boolean): ApprovalFrameFamily;
1284
+ export declare function presentedApprovalFrameFamily(streamApprovalOn: boolean): ApprovalFrameFamily | undefined;
1155
1285
  /** 坏声明的拒体(fresh 受理面 400 `request.field_invalid`):一句话 + 机读位,形与 [ref] 座位族 / [ref] 三桶的 `bad_entry` 同。 */
1156
1286
  export interface ApprovalFrameFamiliesIssue {
1157
1287
  readonly message: string;
@@ -1177,13 +1307,15 @@ export declare function declaredApprovalFrameFamilies(settings: unknown): Readon
1177
1307
  /** 一条腿**没有活审批通道**的成因(见 {@link ApprovalLegAssembly.unattended});`frame_family_undeclared` 带上缺的那个族。 */
1178
1308
  export type LegUnattended = {
1179
1309
  readonly arm: "window_zero";
1310
+ } | {
1311
+ readonly arm: "card_protocol_absent";
1180
1312
  } | {
1181
1313
  readonly arm: "frame_family_undeclared";
1182
1314
  readonly family: ApprovalFrameFamily;
1183
1315
  };
1184
1316
  /** {@link resolveApprovalLeg} 的入参(sync / bg / resume 三腿 + 开流 preamble 共用一份形)。 */
1185
1317
  export interface ApprovalLegInput {
1186
- /** = `resolveStreamApprovalGate(...).active`(协议在本 worker 上场没有)。 */
1318
+ /** = `resolveStreamApprovalGate(...).active`(呈卡协议在本 worker 上场没有;不上场 ⇒ 这台 worker 不呈卡)。 */
1187
1319
  streamApprovalOn: boolean;
1188
1320
  /** `config.streamApproval.windowMs`(`STREAM_ASK_WINDOW_MS`)。
1189
1321
  * 🔴 [ref]:`undefined` = **这份装配没有 `streamApproval` 段**(只出现在只填被测键的 stub-harness ——
@@ -1227,8 +1359,9 @@ export interface ApprovalLegInput {
1227
1359
  *
1228
1360
  * 🔴 **[ref]**:「这条腿有没有活审批通道」多一个成因 —— 这条 run 没声明本 worker 呈卡用的族。它与关窗是**同一件事**(不呈卡、问当场交政策口),
1229
1361
  * 所以进同一个字段(`unattended` 的成因词),三条腿零新分支;判据读 {@link presentedApprovalFrameFamily}(能力位读同一只)。
1230
- * 判据**不**放进 {@link resolveStreamApprovalGate}:那是 worker 级谓词(协调器注入 / 能力位 / 回决 501 都没有 run),且它为假时腿退回旧族 `emit` ——
1231
- * 正是「回退发 `tool_approval`」。
1362
+ * 🔴 **这台 worker 不呈卡**(呈卡协议不上场:无 store backend / 无 park 设施 —— 能力位 `approvalFrameFamilies: []`)是同一件事的第三个成因
1363
+ * `card_protocol_absent`:同一个字段、同一只席、三条腿零新分支。审批只有一个帧族,没有「协议不上场就回退发旧族活卡」的腿;判据仍是
1364
+ * {@link presentedApprovalFrameFamily}(缺席 ⇒ 这一成因),worker 级谓词 {@link resolveStreamApprovalGate} 不变。
1232
1365
  *
1233
1366
  * **没有活审批通道的两件事必须同时做**(调用方契约):不包 ALS **且** `spec.onAsk` = {@link ToolApprovalCoordinator.boundUnattendedAsk}(带成因)。
1234
1367
  * 只做一件另一条路仍会呈卡(ALS 腿是 `deps.onAsk` 的到达路;不包 ALS 也让这条腿不进 broker 活流集合 = 不是别的腿的卡的投递目标)。
@@ -1236,21 +1369,20 @@ export interface ApprovalLegInput {
1236
1369
  * 旧文「bg/resume 无装配点,不包 ALS 即等价」的缺席论证已退役,别再据它推断「少装一件也行」。
1237
1370
  */
1238
1371
  export interface ApprovalLegAssembly {
1239
- /** 协议在本腿上是否上场。false ⇒ 呈卡族的上下文不接(族词 `approval_request`、`legKey` /
1240
- * `legDeadlineMonotonic` 都不接)—— **协议件**逐字保持协议之前的行为。
1241
- * ⚠️ [ref] 门职分离(codex R1-F1 随修):本位**不再兼职**「审批席在场性」—— `spec.onAsk = boundAsk`
1242
- * 三腿恒装(判据 = 协调器在场,即 `TOOL_APPROVAL_ENABLED`),协议关时 bg/resume 腿的 ask 也能命中
1243
- * 同 (owner, session) 活流呈活卡(sync 腿 [ref] 起本就如此;bg/resume 的这条行为差 = [ref] CHANGELOG
1244
- * 披露的行为面变更)。旧文「本腿逐字保持协议之前的行为」只对协议件成立,别再把它读成「协议关 = 零呈卡」。 */
1372
+ /** 呈卡协议在本 worker 上是否上场。false ⇒ 这条腿恒没有活审批通道({@link unattended} 恒在场:关窗或 `card_protocol_absent`)。
1373
+ * 协议不上场 = 零呈卡:生产装配上这时没有审批协调器(`boot/coordinators.ts`),三条腿都不装审批席,每只受门的问由 core 的无审批席臂拒;
1374
+ * 没有「借同 (owner, session) 的另一条活流呈活卡」的路 —— 那条路只在呈卡腿之间存在(呈卡腿的 `boundAsk` 经活流集合投卡,活流集合里只有呈卡腿)。 */
1245
1375
  active: boolean;
1246
1376
  /** **这条腿没有活审批通道**(在场 ⇒ 不包 ALS、不是任何卡的投递目标、`spec.onAsk` 是 {@link ToolApprovalCoordinator.boundUnattendedAsk}
1247
- * 席 —— 每只问当场交无人值守政策口,臂 = 本值)。缺席 ⇒ 这条腿按 {@link presentedApprovalFrameFamily} 的族呈卡。成因闭集两个,先后即判序:
1377
+ * 席 —— 每只问当场交无人值守政策口,臂 = 本值)。缺席 ⇒ 这条腿按 {@link presentedApprovalFrameFamily} 的族呈卡。成因闭集三个,先后即判序:
1248
1378
  * · `window_zero`(§8.3)—— 运维关窗(`STREAM_ASK_WINDOW_MS=0`),或协议上场时本腿剩余 walltime 撑不住安全余量。
1249
1379
  * 🔴 [ref] 起与 `active` 解耦:`0` 是**部署级**旋钮,在两条车道上是同一个意思(旧形下关协议的部署配了 `0` 拿到的是等满 5min 的活卡)。
1250
1380
  * ⚠️ 「窗**缺席**」(`windowMs: undefined` = 这份装配根本没有 streamApproval 段,只出现在 stub-harness)**不是**关窗。
1251
1381
  * 排在声明之前:那时谁都不呈卡,缺的不是客户端的声明。
1252
- * · `frame_family_undeclared`([ref])—— 这条 run 的请求没有声明本 worker 呈卡用的族(`settings.approvalFrameFamilies`)。判据对两个族同一条:
1253
- * 不回退发另一族、不双发、没有「键缺席 ⇒ 视作旧族」的默认。
1382
+ * · `card_protocol_absent` —— 这台 worker 不呈卡(呈卡协议不上场:无 store backend / 无 park 设施;能力位 `approvalFrameFamilies` 为 `[]`)。
1383
+ * 排在声明之前:那时这台 worker 谁都不呈卡,缺的不是客户端的声明。
1384
+ * · `frame_family_undeclared`([ref])—— 这条 run 的请求没有声明本 worker 呈卡用的族(`settings.approvalFrameFamilies`)。
1385
+ * 没有「键缺席 ⇒ 视作声明了」的默认。
1254
1386
  * 三条腿只问「在场没有」,成因随席交给唯一铸点(遥测臂 + deny 政策的拒因句)。 */
1255
1387
  unattended?: LegUnattended;
1256
1388
  /** §7.3 本 leg 的 walltime deadline(`performance.now()` 单调基)。只在 `active ∧ 有活审批通道 ∧
@@ -1288,11 +1420,11 @@ type DecidedRowFacts = Pick<AskRow, "decision" | "settledBy" | "decidedVia" | "d
1288
1420
  * 字面值 ⇒ 对象臂(语义三态的唯一属主 = `AskRow.updatedInput` 顶注);
1289
1421
  * · **结算来源**([ref])—— 行上非 null 即宿主自报的那个词(`null` = 人决,与「不铸这个键」同义;
1290
1422
  * 语义属主 = `AskRow.settledBy` 顶注);
1291
- * · **拒因**([ref] 的行派生半场)—— 拒行上**非空**的 `decisionNote` 铸成 `reason`(与应答口 `shapeDeny` 同键同形:core 以带说明的人拒句
1423
+ * · **拒因**([ref] 的行派生半场)—— 拒行上**非空**的 `decisionNote` 铸成 `reason`(与 7.151.x 及以前应答口的 `shapeDeny` 同键同形:core 以带说明的人拒句
1292
1424
  * 把它交给模型,围栏 `delimitUntrusted` 与长度上限 `REVIEWER_NOTE_MAX_BODY` 全在 core,本仓只透传不预判;空串按 core 契约的缺席读,不铸只装了
1293
1425
  * 空值的对象臂)。**allow 行的说明恒不铸**:core 对 allow 行的 `reason` 恒销毁,说明只走审计面(行的 `decisionNote` 列)。
1294
1426
  * 此前这一格不在铸点里 ⇒ 耐久决断口 / 重放 / 兄弟广播 / claim 败方 / 歧义提交恢复 / 悬挂轮询六条行派生的路,都把带说明的拒交成裸 `false`
1295
- * (core 读作「一个人拒了、没说怎么办」:STOP 句 + 本轮收住),而同一段说明经应答口到达却带着 `reason` 进模型 —— 一扇门两种去向。
1427
+ * (core 读作「一个人拒了、没说怎么办」:STOP 句 + 本轮收住),而同一段说明经应答口(7.152.0 起已删)到达却带着 `reason` 进模型 —— 一扇门两种去向。
1296
1428
  *
1297
1429
  * 🔴 [ref]:来源位**两向都读**。决定体的出处位 `decidedBy:"policy"` 在 allow 与 deny 上都会落列(引擎 7.39.0 起铸
1298
1430
  * `policy_allowed`),所以 approve 行带来源位是一条合法的行,它的每条读回路径交还 `{allow:true, settledBy:"policy", updatedInput?}`
@@ -1326,8 +1458,7 @@ export declare class ToolApprovalCoordinator {
1326
1458
  /** 判据钩子(生产路径不调)。 */
1327
1459
  terminalClaimsInFlightForTest(askId: string): number;
1328
1460
  /** [ref] 车2(codex 交叉复审 round3 抓获真 finding,round5 精化成 Set):次级索引,键 = 持久层 askId
1329
- * (与 {@link pending} 的 wire-面 uuidv7 `id` 是两条独立的身份轴,顶注同精神)——只在 askStore 在场且
1330
- * 这只 ask 真有 askId 时才登记。**同一 askId 下可能同时挂着不止一条本地条目**(round5 抓获:
1461
+ * (与 {@link pending} 的 wire-面 uuidv7 `id` 是两条独立的身份轴,顶注同精神)——每条登记都在这里(每只 ask 都有 askId)。**同一 askId 下可能同时挂着不止一条本地条目**(round5 抓获:
1331
1462
  * `ensureAsk` 是幂等 upsert,若 core 对同一 (sourceSessionId,runId,toolCallId,legKey) 真发起过两次并发调用——如
1332
1463
  * 重试/failover 场景,round4 finding2 的顶注同源——两次 `askBroadcast` 各自的调用栈都会在行仍是
1333
1464
  * STREAM_PENDING 时各自注册一条独立的本地 pending 条目,值形若是单值 Map 会被后到者覆盖前者的登记,
@@ -1359,11 +1490,11 @@ export declare class ToolApprovalCoordinator {
1359
1490
  * {@link DEFAULT_UNREACHED_ASK_TTL_MS} = 1h,域 [60s, 24h] 由 config 守)。只作用于
1360
1491
  * `AskReachability === "unreached"` 的那一支;有活流的 ask 恒用 {@link ttlMs}。 */
1361
1492
  private readonly unreachedTtlMs;
1362
- /** [ref] 车2([ref] §7 协调器半场,D1):可选持久层——缺席 ⇒ 每一条现行为逐字不变(in-memory
1363
- * promise 机械即契约);在场 ⇒ 四竞争者(回决/窗到期/取消/emit 全灭)的终局多一道持久 CAS 记账。
1364
- * additive 改造,不是替换——settle 闭包/pending map/TTL/broker 全保留,CAS 只决定「谁有权 settle
1365
- * 成什么终局」。 */
1366
- private readonly askStore?;
1493
+ /** 这台 worker 的审批问账([ref] §7 协调器半场)—— **必选**:协调器只在呈卡协议上场时构造(`boot/coordinators.ts`,
1494
+ * 判据 {@link resolveStreamApprovalGate}),每一只协调器都有账。四竞争者(回决 / 窗到期 / 取消 / emit 全灭)的终局恒经这本账的
1495
+ * 持久 CAS 记账;settle 闭包 / pending map / TTL / broker 是本副本的活面,CAS 决定「谁有权 settle 成什么终局」。
1496
+ * 没有「无账协调器」这一形:呈卡协议不上场的 worker 根本没有协调器(缺席 = 协议不上场)。 */
1497
+ private readonly askStore;
1367
1498
  /** [ref] 车2([ref] §3.3 D3):窗长三元公式的安全余量,构造期定,详见 {@link effectiveAskWindowMs}。 */
1368
1499
  private readonly windowMarginMs;
1369
1500
  /** [ref] 车3 刀 3b(设计稿 §0 X-2 写侧准入门):per-task / per-owner 的未决 ask 上限。 */
@@ -1378,9 +1509,9 @@ export declare class ToolApprovalCoordinator {
1378
1509
  /** [ref] F4:悬挂决议轮询腿的**轮转游标**(整数偏移,与集合成员无关 —— 理由见
1379
1510
  * `pollSuspendedDecisions` 里那段:按 askId 记的形会在「上一拍最后碰的那条被结算掉」时塌回队首,
1380
1511
  * 构造出永久饥饿的前缀)。只回答「上一拍扫到第几个」,单调推进、按当前长度取模。 */
1381
- private suspendedPollOffset;
1382
- /** [ref]:悬挂轮询腿第二层(接管登记)的轮转游标 —— 与 {@link suspendedPollOffset} 同一条理由,两层各一只。 */
1383
- private adoptedPollOffset;
1512
+ private readonly suspendedPollCursor;
1513
+ /** [ref]:悬挂轮询腿第二层(接管登记)的轮转游标 —— 与 {@link suspendedPollCursor} 同一条理由,两层各一只。 */
1514
+ private readonly adoptedPollCursor;
1384
1515
  /** [ref] + codex R3-[critical]:askId → **此刻正带着 `updatedInput` 决它的请求数**(见
1385
1516
  * {@link markEditedDecisionInFlight} 顶注)。只在 `decideAsk` 那一次调用期间非空,故天然有界。 */
1386
1517
  private readonly editedDecisionsInFlight;
@@ -1407,11 +1538,9 @@ export declare class ToolApprovalCoordinator {
1407
1538
  * core 的 global 缺省(= 现行为,恒不更宽;也绝不错铸一个坐标系不对的 root)。装配见 main.ts:
1408
1539
  * registry cwd(host lane 显式注册的 launch dir)?? 无手(`none`)单用户形的 `process.cwd()`。 */
1409
1540
  private readonly ruleScopeRootFor;
1410
- /** [ref]:停驻行迟到决议的受理回执表(键 = 行的键 `askId`,插入序 = 逐出序)。语义与有界理由见
1411
- * {@link ParkRedemption} 顶注。 */
1541
+ /** 停驻卡在飞的赎回表(键 = 行的键 `askId`;一飞落定即收回)。语义与有界理由见 {@link ParkRedemption} 顶注。 */
1412
1542
  private readonly parkRedemptions;
1413
1543
  private readonly parkRedemptionMax;
1414
- private readonly parkRedemptionTtlMs;
1415
1544
  /** [ref]:per-principal 子帽(语义与取值理由见 {@link DEFAULT_PARK_REDEMPTION_PER_PRINCIPAL_MAX})。 */
1416
1545
  private readonly parkRedemptionPerPrincipalMax;
1417
1546
  /** [ref]:PARKED 臂的赎回席**取值口**(晚绑 —— 赎回腿要 checkpoint/bg 店与裸 Agent 工具,它们在协调器
@@ -1443,12 +1572,12 @@ export declare class ToolApprovalCoordinator {
1443
1572
  /** [ref] F1:有序关停下路由到 park、**处置尚未被观察到**的卡 —— 审计 settle 行在这里候着({@link settleParksAwaitingCommit})。
1444
1573
  * 只在关停期有成员(进程随后退出,不需要回收)。 */
1445
1574
  private readonly parksAwaitingCommit;
1446
- constructor(opts?: {
1575
+ constructor(opts: {
1447
1576
  ttlMs?: number;
1448
- /** [ref](案A):零活流铸造的 ask 的窗(见 {@link unreachedTtlMs})。装配点在协议**上场**时才传
1449
- * (与 `ttlMs` 同条件、同理由:悬挂的三条发现通道全长在 ask 行上);缺席 ⇒ 1h 代码默认。 */
1577
+ /** [ref](案A):零活流铸造的 ask 的窗(见 {@link unreachedTtlMs});缺席 ⇒ 1h 代码默认。 */
1450
1578
  unreachedTtlMs?: number;
1451
- askStore?: ApprovalAskStore;
1579
+ /** 审批问账(必选,见 {@link askStore})。 */
1580
+ askStore: ApprovalAskStore;
1452
1581
  windowMarginMs?: number;
1453
1582
  admitMaxPerTask?: number;
1454
1583
  admitMaxPerOwner?: number;
@@ -1464,10 +1593,8 @@ export declare class ToolApprovalCoordinator {
1464
1593
  parkedRedeem?: () => ParkedAskRedeem | undefined;
1465
1594
  /** [ref]:按问读口的门读席(见 {@link ToolApprovalCoordinator.parkedGate})。 */
1466
1595
  parkedGate?: ParkedGateRead;
1467
- /** [ref]:受理回执表两道界(缺省见 {@link DEFAULT_PARK_REDEMPTION_MAX}/{@link DEFAULT_PARK_REDEMPTION_TTL_MS})。
1468
- * 不是部署旋钮(不接 env),可注入只为让「有界」这件事被判据观测得到。 */
1596
+ /** 在飞赎回表的容量帽(缺省见 {@link DEFAULT_PARK_REDEMPTION_MAX})。不是部署旋钮(不接 env),可注入只为让「有界」这件事被判据观测得到。 */
1469
1597
  parkRedemptionMax?: number;
1470
- parkRedemptionTtlMs?: number;
1471
1598
  /** [ref]:per-principal 子帽(同上不接 env;生效值恒 `min(本值, parkRedemptionMax)`)。 */
1472
1599
  parkRedemptionPerPrincipalMax?: number;
1473
1600
  /** [ref] (c):local 车道审计 sink(见 {@link ToolApprovalCoordinator.askAudit})。 */
@@ -1489,8 +1616,8 @@ export declare class ToolApprovalCoordinator {
1489
1616
  * onAsk 契约里是「一个人拒了」,而本口的全部臂都是「没有人能答」。
1490
1617
  *
1491
1618
  * 五臂(设计稿 §1 的表)全部读它,`unattendedPolicy` 因此是一处施加、五处消费:
1492
- * (a) 有店窗到期 `expireAsk` 赢 CAS / (b) 无店窗到期(D1)/ (c) 有店但 `expireAsk` 报错
1493
- * —— 三条走 `windowRouteUnavailable` 标志,在 {@link shapeOutcome}(askBroadcast 内)成形;
1619
+ * (a) 窗到期 `expireAsk` 赢 CAS / (c) `expireAsk` 报错
1620
+ * —— 两条走 `windowRouteUnavailable` 标志,在 {@link shapeOutcome}(askBroadcast 内)成形;
1494
1621
  * (d) 没有活审批通道的腿(装配层短路:关窗 / 未声明呈卡族,[ref])与无 ALS 上下文的 headless 腿 —— 走本方法/{@link ask};
1495
1622
  * (e) 断连 `forceParkNow` / emit 全灭 / 写侧准入超限 —— 走本方法。
1496
1623
  *
@@ -1577,7 +1704,7 @@ export declare class ToolApprovalCoordinator {
1577
1704
  * 超限的处置是 `"unavailable"`(park 路由),**缺省 park 政策下永不 deny**:过载是**我方**的容量事实,不是人对这次
1578
1705
  * 操作的判断;用 deny 表达过载会把一次「本可以 park 后由人补批」的操作变成任务失败(§3.3 硬条款)。
1579
1706
  *
1580
- * 只在 `askStore` 在场(= 协议开着)时把关:开关关闭时本方法恒放行,现行为逐字不变(D1/A-1)。
1707
+ * 每一只协调器都把关(协调器只在呈卡协议上场时存在,见 {@link askStore})。
1581
1708
  *
1582
1709
  * ⚠️ **已认领的偏离**(设计 X-2 字面要求「计数在持久层做」):v1 是**进程内**计数 —— 它对单副本完整
1583
1710
  * 有效,多副本下每个副本各自把关(真实上限 = N × 帽)。理由=持久层计数要么在每只 ask 的热路径上多一次
@@ -1598,51 +1725,6 @@ export declare class ToolApprovalCoordinator {
1598
1725
  private static ruleOffersEqual;
1599
1726
  private static batchMemberEqual;
1600
1727
  private static uncoveredDetailEqual;
1601
- /**
1602
- * [ref] / 5.58 复审 F-1 —— OFFER 的**文本座尺**(红先修)。
1603
- *
1604
- * 🔴 病灶(真复现,`npm run build --flag=<700 字> && git status`):`batch` 成员的 `segment` 是复合命令
1605
- * 那一段的**原字节**,它**不经** `parseRuleText`,所以 core 的 `MAX_RULE_TEXT_CHARS` 对它一个字
1606
- * 都不管;而卡的 `ApprovalCardSchema` 对四个文本座一律 `.max(MAX_RULE_TEXT_CHARS)`。逐字拷进卡 ⇒
1607
- * `card_json` 落库 ⇒ `ensureAsk` 当场回读 `safeParse` 判假 ⇒ `persisted-row-unusable` ⇒ **整只 ask 走
1608
- * park**,重放腿一并跳过该行。与「重扫二轮 §基数帽」是**同一条悬崖的另一条边**(那次是 offer 条数
1609
- * 没执法,这次是文本长度),5.58 换形之前不存在——旧 `RuleSuggestion` 三个座全是解析器输出,结构性 ≤512。
1610
- *
1611
- * 两个座两种处置,**刻意不同**:
1612
- * · `segment` = **纯渲染座**(core 明写「never adjudication input」)⇒ 截长是诚实省略,与
1613
- * `toolName`/`message` 的 `capText` 同待遇,也与耐久腿 `boundedRuleOffers` 的同名处置同形。
1614
- * · `rule`/`command` = **兑付等式的左边**(回决 `persistRule.rule` 按文本在引擎重铸的 offer 表里定位)
1615
- * ⇒ 截一个字就恒 `rule_not_offered`,所以**绝不截**;真超尺(= core 放宽了自己的 512 或本仓与 core
1616
- * 版本不同步)⇒ **整条车道撤回**(返回 `undefined`),与本文件既有的治理撤回 / 漂移撤回逐字同形:
1617
- * 少渲一格是安全方向,渲一格按不动的才是 wire 谎言。今天这条臂不可达(每个座都是解析器产物),
1618
- * 它守的是版本不同步那一形 —— 与 `isCommandRuleMatch` 的运行期 `default` 同族。
1619
- *
1620
- * 位置在**素材铸点**(与基数帽同一处):两族帧 + `card_json` + 回决口的等式左边从此拿的是**同一份**
1621
- * 已截素材,而不是两处各截一遍。
1622
- */
1623
- /** 兑付侧座(single 的 rule/command、command 成员的 rule/command、directoryRead 成员的 rule/directory)任一超尺?
1624
- * `segment` 与 `uncoveredDetail[].segment` 是纯渲染座,不在此列(截长是诚实省略)。 */
1625
- private static ruleOfferTextsOverSize;
1626
- /** codex r1 [high]([ref]):offer 的自称座与 `parseRuleText(rule, "allow")` 派生的三元组逐字一致?(理由见调用点)`cardTool` = 这张卡的工具(`req.toolName`)。 */
1627
- private static ruleOfferDerivedFactsAgree;
1628
- /**
1629
- * 一只 single 候选属于这张卡吗 —— 一条规则:**它的规则文本点名的就是这张卡的工具,且它的匹配词的卡形就是这只工具的卡形**(两只读法都在
1630
- * `permission-rule-vocab.ts`:{@link cardRuleFormOf} / {@link CARD_RULE_FORM_OF_MATCH})。core 为一张卡铸的 single 恰是这一形:shell 卡上的命令规则、
1631
- * 名字 / 主机工具卡上那一条精确值规则、没有规则词替它说话的工具卡上的整工具规则;兑付侧 `prepareCardApproval` 按「这张卡的工具 + 绑定值」重铸,
1632
- * 别的形 / 别的工具的候选在那里恒兑不动 ⇒ 渲出来就是一格按不动的「不再询问」。丢(与本文件其余撤回 / 丢弃臂同一方向:少渲一格是安全方向)。
1633
- */
1634
- private static singleOfferBelongsOnCard;
1635
- private static boundRuleOfferTexts;
1636
- /**
1637
- * 这张卡的**绑定值**(`prepareCardApproval` 的 `command`,也是耐久行的 `rule_command`)= **卡形的绑定值**(core `prepareCardApproval` 对 `command` 入参的逐形定义):
1638
- * · 值形(整工具 / 名字 / 主机:core 对这三形只铸**一只** single,它的 `command` 座就是那个值 —— 整工具 `""`、名字工具是调用带的名字、主机工具是调用到达的主机)
1639
- * ⇒ 那一只候选自己的 `command`;
1640
- * · 其余(命令形候选 / 批,或读者把候选丢光了)⇒ 被裁决的命令原字节 `args.command`(非空串;读不出 ⇒ 没有素材)。空候选表不说任何值形:
1641
- * 绑定值回到调用自己的命令(编辑面兑的就是它)。
1642
- * 候选走到这里之前已过 {@link singleOfferBelongsOnCard}:每只 single 都是这张卡的工具、这只工具的卡形 ⇒ 值形与命令形不会同卡。值形候选不止一只 = 不是 core 铸得出的卡
1643
- * ⇒ 没有素材(整条车道撤回,与本文件其余撤回臂同形)。`req.args` 窄读,禁裸 as-cast。
1644
- */
1645
- private static cardBindingOf;
1646
1728
  private buildRuleLaneMaterial;
1647
1729
  /** [ref]([ref]/[ref] 双属主裁定):把某 wire run 的**流内未决 ask** 立即转 durable park——断连支专用。
1648
1730
  * 匹配键=`ctxTaskId`(wire run id)。该字段的顶注说它「不是清扫判据」——那是因为清扫要判**连接**的
@@ -1874,32 +1956,14 @@ export declare class ToolApprovalCoordinator {
1874
1956
  */
1875
1957
  private dispatchClaimTruth;
1876
1958
  /**
1877
- * [ref]:为一次**赎回**开一格(单飞句柄的座位)。调用点唯一 = {@link redeemParkedAsk} 开飞之前。在飞的格不受容量帽约束 ——
1878
- * 它们有界于此刻在飞的赎回请求数,且开飞即受理承诺之前的那一段(逐它会撕正在进行的兑付);容量帽只管落定之后留下的**回执**
1879
- * ({@link retainParkRedemption})。
1880
- */
1881
- /**
1882
- * 受理回执表的**准入**半场:在飞的格(赎回腿还没回来)永不被逐 —— 单飞靠它 —— 所以表的两道界对它们只能在开格之前判。
1959
+ * 在飞赎回表的**准入**:在飞的格(赎回腿还没回来)永不被逐 —— 单飞靠它 —— 所以表的两道界只能在开格之前判。
1883
1960
  * 本 principal 在飞的格已到生效子帽,或全表在飞的格已到全局帽 ⇒ 拒新(`429 limit.rate_exceeded` + `retryAfterSec`,路由据体铸 `Retry-After` 头),
1884
1961
  * 不开格、不进赎回腿;已在飞的那几只照常落定,之后同一只卡的受理照常。回 `undefined` = 放行。
1885
- * 两道界与回执半场({@link retainParkRedemption})同一组数:表里每一格都有界 —— 回执靠逐出,在飞的格靠准入。
1886
1962
  */
1887
1963
  private parkRedemptionAdmission;
1964
+ /** 为一次赎回开一格(单飞句柄的座位)。调用点唯一 = {@link runParkedFlight} 开飞之前(读口已保证此刻没有在飞的格)。 */
1888
1965
  private openParkRedemption;
1889
- /**
1890
- * [ref] / [ref]:一次赎回**受理成功**之后,它的回执留不留(容量帽按**插入序**逐出最旧,与 `allowAllSessions` 同款有界纪律)。回 `false` = 容量拒新:
1891
- * 这一格当场收回(那一次受理照旧生效,只是没有本副本的回执可依 —— 200 丢包后的重试再进赎回腿,终局由它的 CAS 定)。
1892
- *
1893
- * 两道界**只数回执**(已受理、不在飞的格;在飞的格永不被逐),且**只看本 principal 的那一段**(理由与两条臂的方向差见
1894
- * {@link DEFAULT_PARK_REDEMPTION_PER_PRINCIPAL_MAX}),生效子帽对全局帽取小。记账用开格那一刻行上的 owner —— 要的是「压力来自谁」这个近似,
1895
- * 不是「谁有权决这只 ask」(权威属主门恒按行上当下的 `owner` 复判)。
1896
- * · 本 principal 的回执数已到子帽 ⇒ 逐本 principal 最旧的那张(过期的优先)—— 量产者自伤;
1897
- * · 全表回执已到全局帽 ⇒ 先收全表第一张过期回执(清扫是惰性的,若干租户各自远低于子帽却把全局填满时,TTL 过后没人再来查那些旧 id,
1898
- * 不回收就永远满 —— 回收过期条目不是「挤他人」,是收垃圾);一张过期的都没有 ⇒ 拒新,一格都不挤别人([ref] Q3)。
1899
- */
1900
- private retainParkRedemption;
1901
- /** [ref]:取受理回执(**惰性清扫**:过期回执读到即删,不另起定时器 —— 这张表只在迟到回决那一刻被读)。**在飞的格不随 TTL 过期**:重叠的请求
1902
- * (哪怕晚于 TTL 才到)照样等它、回放它的结果,绝不另起第二次赎回。 */
1966
+ /** 这只问此刻在飞的赎回(没有 ⇒ `undefined`)。 */
1903
1967
  private lookupParkRedemption;
1904
1968
  /**
1905
1969
  * [ref] 车4 §12-E(F29/F30 裁定形):外部回决(车4 端点或本类 respond 腿)**赢下持久 CAS 之后**,把同
@@ -1911,12 +1975,46 @@ export declare class ToolApprovalCoordinator {
1911
1975
  * 真决议」,重复注册必须拿到**同一个**决议(approve 就是 approve)——合并会把外部批准的重复条目错
1912
1976
  * 结算成拒绝。已被结算过的条目再调 settle 天然无操作(幂等),所以本口对「赢家自己已 settle」安全。
1913
1977
  */
1914
- notifyExternalDecision(askId: string, outcome: DecidedAskOutcome): {
1978
+ notifyExternalDecision(askId: string, outcome: DecidedAskOutcome, readRootGrant?: string): {
1915
1979
  settled: number;
1916
1980
  };
1981
+ /**
1982
+ * 决断口 live 臂在 CAS **之前**握住本副本上等这只问的那条登记({@link HeldLiveLeg};没有 ⇒ 空握)。CAS 写成与回读之间,别的观察者(悬挂轮询 / 同一只问的另一次请求)
1983
+ * 可能先按行把登记结清、移出活集合 —— 赢家的授予({@link settleLiveDecision} 的 ①)读的是它判时握住的这一条,不在结清时再查活集合。
1984
+ */
1985
+ holdLiveLeg(askId: string): HeldLiveLeg;
1986
+ /**
1987
+ * 这只问「要人」的读法 —— 行上那张卡 ∪ 本副本上等它的这一腿的请求(只升不降;重入的腿把位升在登记上,行上那张卡是首次登记铸的):
1988
+ * 决断口的要人门读它(活卡形与停驻形同一只;停驻卡没有活登记 ⇒ 只剩行上那张卡)。
1989
+ */
1990
+ askDemandsAPerson(row: AskRow, held: HeldLiveLeg): boolean;
1991
+ /**
1992
+ * 🔴 **有问行的卡唯一的人决口**(决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`)live 形 CAS **干净赢下**之后的结清 —— 这条终局是本请求写下的,
1993
+ * 于是这次请求带来的 live 词在这里一处兑掉(调用方 = 决断口 live 臂的赢者那一支;回放 / 冲突 / 提交歧义臂都不进来:那几支没有做任何授予判定):
1994
+ * ① 「本会话放行」(`remember:"session"`):家由卡面那只判官定({@link liveSessionAnswer},读决断口在 CAS 之前握住的那条登记 {@link holdLiveLeg} —— 卡面提示位与写侧同一只);
1995
+ * `seat` ⇒ 进程内会话放行在**结清之前**铸(同一条腿紧跟着的下一问读得到);`server_store` ⇒ 部署名单那一问的会话豁免在结清之后落店;
1996
+ * `none` / 本副本上没有等它的登记(决定打在别的副本上)⇒ 记不住。`rememberApplied` 按真结果说(只在请求带了这一键时在场)。
1997
+ * ② 读根授权(`readRootGrant`)随结清交给本副本上等它的引擎腿(行上没有这一列 ⇒ 只交得给本副本;一条都没有 ⇒ 回执的 `consumerState` 如实说本副本没人消费)。
1998
+ * ③ 「不再询问」(`persistRule`)交唯一兑付函数 {@link redeemCardRule},记录 = 这只问的**行**({@link readCardRuleRecordOfAskRow};任一副本都兑得了;属主 = 门判过的那一位)。
1999
+ * 结清本身与行派生的结清同一只({@link notifyExternalDecision}:结算取行)。`settled` = 本副本上把它当终局消费掉的腿数。
2000
+ */
2001
+ settleLiveDecision(row: AskRow, held: HeldLiveLeg, judgedOwner: string | null, principal: string | undefined, extras: LiveDecisionExtras): Promise<{
2002
+ settled: number;
2003
+ rememberApplied?: boolean;
2004
+ rule?: RuleSlotReceipt;
2005
+ }>;
2006
+ /**
2007
+ * [ref]:自由文本规则的**裁决前**文本预检(决断口 live 形,CAS 之前;回 `undefined` = 放行,回拒 = 400 且这只问没被结算,人改好文本按同一只问再来)。
2008
+ * 触发条件与兑付函数的前置门逐条同源(只在这次决定**真的会**去兑一条编辑过的自由文本规则时才判):编辑放行 / 治理档 / 车道不供 / 无属主 / 行上没有素材 ⇒ 不判
2009
+ * (那几形走「裁决落定 + `rulePersisted:false` + 各自的拒因词」)。素材读的是行(与兑付同一份记录)。
2010
+ */
2011
+ precheckEditedRuleOfAskRow(row: AskRow, judgedOwner: string | null, persistRule: ParsedPersistRule, inputWasEdited: boolean): {
2012
+ message: string;
2013
+ ruleRejectCode?: string;
2014
+ } | undefined;
1917
2015
  /**
1918
2016
  * [ref] 车6:把一张**批级撤卡帧**投给给定的一组连接 —— 逐 ctx 经本腿那一只传输(`deliverHitlNotice`:先本 run 账本、再直写,
1919
- * 与开卡帧同一条律、同一条账本链;账本里的序 = 入链序)。只有呈卡族的腿收撤卡帧(旧族没有撤卡帧)。
2017
+ * 与开卡帧同一条律、同一条账本链;账本里的序 = 入链序)。
1920
2018
  *
1921
2019
  * 空名单不发(零信息的帧只会让壳多一次无意义的对账)。投递永不 reject、**绝不回滚已经落定的持久 CAS** —— 帧是通知,行才是真源;
1922
2020
  * 没送到记一次 `server.hitl.close-frame-dropped`,壳侧的结构补偿是重连 preamble 的全量对账基准。
@@ -1947,7 +2045,7 @@ export declare class ToolApprovalCoordinator {
1947
2045
  * inverse of question's release-unanswered — but no longer a blunt "any one target exits ⇒ kill it" rule,
1948
2046
  * see {@link PendingApproval.onTargetGone}).
1949
2047
  * [ref] 注意([ref] core 点名的火):委派子代的 ask 经 {@link boundAsk} 落 pending 时不带
1950
- * `targetCtxs`/`onTargetGone`(只有 `originTaskId === undefined` 的宿主自身条目才带)——session-scoped
2048
+ * `targetCtxs`/`onTargetGone`(只有 `sourceSessionId === undefined` 的宿主自身条目才带)——session-scoped
1951
2049
  * bg 子代活过宿主 turn 时其未决卡不被这里触碰(TTL/abortSignal 仍兜底)。 */
1952
2050
  runWithContext<T>(ctx: ToolApprovalRunContext, fn: () => Promise<T>): Promise<T>;
1953
2051
  /** 测试/可观测性钩子:该 (owner, session/taskId) broker key 下当前活跃连接数——断言多连接注册/清扫
@@ -1989,122 +2087,44 @@ export declare class ToolApprovalCoordinator {
1989
2087
  private askBroadcast;
1990
2088
  /** {@link askBroadcast} 的本体(计数在外层,一处进出)。 */
1991
2089
  private askBroadcastCounted;
1992
- /** `POST /v1/tool-approvals/:id/respond` — settle a parked approval with the shell's decision. Owner-gated with a
1993
- * 404 (no existence oracle), body validated first (400 is existence-independent) — question/steer parity. The HTTP
1994
- * layer owns auth (gatedSubject + REQUIRE_PRINCIPAL) before calling.
1995
- *
1996
- * [ref] 车2(D1/D2):return type 是 UNION,不是把整个方法标 `async`——askStore 缺席时这个方法逐字同步
1997
- * 完成(D1 现行为不变;现存量测试对它的同步断言/`void` 调用零改动)。在场时才真的变成 Promise(D2 的
1998
- * 「settle 前先赢一把 decideAsk CAS」离不开 await,同步函数做不到)。唯一生产调用点(`routes/runs.ts`)
1999
- * 统一 `await`——`await` 对非 Promise 值是恒等操作,两条路径对它透明。 */
2000
- respond(id: string, principal: string | undefined, body: unknown,
2001
- /** [ref]:发起本次回决的真实 HTTP 请求。**只**沿 PARKED 臂透传给赎回席(那条腿要它做准入解析与
2002
- * 舰队 scope,与 `/decide` 腿同姿势);live 命中路径一个字节都不看它。缺席 = 非 HTTP 调用点
2003
- * (测试/内部),赎回席按「无请求」形处置。 */
2004
- httpReq?: IncomingMessage,
2005
- /** [ref]:本次回决的**部署事实**(协调器自己不读 config;回决路由从能力事实读来交进)。缺席 ⇒ 按「不受理读根授权」读(失败方向 = 拒)。 */
2006
- deployment?: ToolApprovalRespondDeployment): {
2007
- status: number;
2008
- body: unknown;
2009
- } | Promise<{
2010
- status: number;
2011
- body: unknown;
2012
- }>;
2013
- /** [ref]:这条登记**有没有问账行**(有 ⇒ 属主的唯一来源是行上当下的 owner 列;没有 ⇒ 登记记下的那一位是唯一可读的属主事实)。 */
2014
- private registrationHasRow;
2015
- /**
2016
- * [ref]([ref] 的接管登记一臂并进来):**读行判属主**的应答 —— 接管登记恒走这里;活登记在登记记下的属主不认调用方时走这里(行可能已被收编改给调用方)。
2017
- * 属主门读**行当下的** owner:登记上记下的那一格是铸卡(或接管)那一刻的进程内快照,`/v1/adoption` 改写行之后它就落后了(契约:应答口的授权判据取
2018
- * 当下的持久事实,收编之后旧属主手里的卡作废、新属主照常答得了 —— 与耐久决断口同答)。行仍 `STREAM_PENDING` ⇒ {@link answerRegistration}(同一把
2019
- * `decideAsk` CAS,绑门刚读到的那位属主,[ref];活登记上那条在等的腿照常收到决议);行已有终局(别处答了 / 对账器收了,本副本还没闻讯)⇒ 按行的真相答
2020
- * (与晚答口同一张表)。读不出行 ⇒ 不知道属主是谁 ⇒ 与未知 id 同形同码(属主门 fail-closed)。
2021
- */
2022
- private respondByRow;
2023
- /** 一条已过属主门的登记(活登记或接管登记)的应答 —— 两者同一条路:规则文本前门 → 要人门 → CAS → 兑付。
2024
- * `judgedOwner` = 门判过的那位属主([ref]:决议作用域的属主维,CAS 与确认读都绑它;见 `askRowCarriesOwner`)。 */
2025
- private answerRegistration;
2026
- /** 一次 live 回决**落定之后**的两件兑付(部署名单那一问的豁免、「不再询问」的规则)—— 两件都只在 200 那一支、都读同一只资格。
2027
- * `judgedOwner` = 这次决议的门判过的那位属主([ref]:一次决议只读一次属主 —— 决议 CAS、会话放行、规则落店、豁免记账都用这一份,不回头重读登记上的那一格)。 */
2028
- private afterLiveDecision;
2029
- /**
2030
- * **部署名单(`APPROVAL_REQUIRE`)那一问的「本会话放行」只落 server 的会话豁免店**(问的人按自己这一问的事实决定退不退):名单的问是 server 铸的,
2031
- * 名单门在出问之前读这只店(键 = 会话 × wire 工具名,与耐久 `/decide` 的 `remember:"session"` 写下的同形),命中就不出问 —— 引擎看到的
2032
- * 是「这次调用没出问」。不铸进程内授权(那是审批席替引擎的问记的答案;本席不代答名单的问),不交任何东西给引擎的规则店。
2033
- *
2034
- * 只在这次回决**真成了终局、而且终局是本请求写的**之后写(200 那一支 ∧ {@link RulePersistEligibility} 合格;CAS 输 / 条目已被别人结算 ⇒ 不写;
2035
- * 提交歧义臂 —— 行上只证得出「有一条同向决议」,可能是并发的另一路「只批这一次」写的 —— 撤销资格 ⇒ 不写):一次不是自己的放行不留站着的答案。写在结算之后,
2036
- * 所以同一条腿紧跟着的下一问若先于这次写落到名单门,会多出一张卡(方向是多问,不是静默放行)。回执 `rememberApplied` 按这次写的真实结果说:
2037
- * 写成 ⇒ `true`;写失败 / 超时 ⇒ `false` + 一行 warn(这一次照旧放行,与 `/decide` 腿「grant 失败不回滚 approve」同向)。
2038
- * 不是名单的问、记不住的卡(卡上还带着别人的问、强制、授予绑定 ……)、没有会话 ⇒ 原样交回(那几形的回执已由 {@link finishRespond} 定)。
2039
- */
2040
- private recordDeploymentListAnswer;
2041
- /**
2042
- * [ref]:自由文本规则的**裁决前**文本预检 —— 回 `undefined` = 放行(继续正常回决),回一个响应 = 400。
2043
- *
2044
- * 🔴 **触发条件与兑付口的前置门逐条同源**,一个都不许多(这是本方法最容易写错的地方):只有在这次回决
2045
- * **真的会去兑付一条自由文本规则**时才预检。任何一条前置门本来就会把兑付挡掉的形(治理档 ask /
2046
- * 车道不供 / 无属主 / ctrl+g 编辑放行),都**必须**照旧走「裁决落定 + `rulePersisted:false` + 各自的
2047
- * 拒因词」那条老路 —— 否则一次带着坏规则文本的**治理档回决**会被 400 掉,而它本来是能决的:那是把一个
2048
- * 附带愿望的失败升级成主动作的失败,方向完全错。逐门对照见 {@link persistRuleAfterDecision}。
2049
- *
2050
- * 候选臂(`edited !== true`)不进这道门:它的等式是「文本必须在引擎铸的候选里」(`rule_not_offered`),
2051
- * 那是记录级判据、不是文本级判据,`precheckEditedRuleText` 答不了也不该答。
2052
- */
2053
- private precheckEditedRuleBeforeDecision;
2054
- /** [ref]:回执上两个新键的**唯一**成形口 —— 只在这次请求真的走了**自由文本臂**时铸。
2055
- * 候选臂的回执因此逐字节不变(老壳按固定键集解析,多一个键就是一次没人要的 wire 变更)。 */
2056
- private editedArmEcho;
2057
- /** [ref]:`tool_approval.not_pending` 的**唯一**成形口 —— 只在已过属主门的面上调(调用方看不见这只问 ⇒ {@link askNotVisible})。文案逐字不变
2058
- * (存量壳/SDK 按它认这条 404),只 additive 加判别位;`cause` 缺席 = 这台部署没有行可判(D1 无店)或行形不可信(见各调用点)。 */
2090
+ /** [ref]:`tool_approval.not_pending` 的**唯一**成形口 —— 只在按问读口已过属主门之后调(调用方看不见这只问 ⇒ {@link askNotVisible})。文案逐字不变
2091
+ * (存量壳/SDK 按它认这条 404),只 additive 加判别位;`cause` 缺席 = 行形不可信(见各调用点)。 */
2059
2092
  private notPending;
2060
2093
  /**
2061
- * 调用方**看不见**这只问的**唯一**成形口(应答口与按问读口同一只):无行 / 行不是调用方的 / 行读不出(不知道属主是谁 ⇒ 属主门 fail-closed)/
2062
- * 这台部署没有问账可判。404 `not_found.ask` —— 与耐久决断口 `POST /v1/tasks/:taskId/asks/:askId/decision` 的属主门同一个词(两扇门底下是同一只问),
2094
+ * 按问读口上调用方**看不见**这只问的**唯一**成形口:无行 / 行不属路径上的 task / 行不是调用方的 / 行读不出(不知道属主是谁 ⇒ 属主门 fail-closed)。
2095
+ * 404 `not_found.ask` + {@link ASK_NOT_FOUND_UNDER_TASK} —— 与同根的决断口 `POST /v1/tasks/:taskId/asks/:askId/decision` 逐字节同一体(两扇口底下是同一只问),
2063
2096
  * 不带任何状态位:属主门不过与未知 id 逐字节同,404 对看不见它的人不做存在 / 状态神谕。
2064
2097
  */
2065
2098
  private askNotVisible;
2066
2099
  /**
2067
- * `GET /v1/tool-approvals/:approvalId` —— **按问读口**:一只 ask 此刻在哪一态({@link TOOL_APPROVAL_READ_STATES})。与 {@link respond} 同根同门
2068
- * (HTTP 层的鉴权 / 属主身份同一只 `gatedSubject`;看不见这只问 —— 属主不过 / 查无 / 行读不出 / 没有问账 —— 与应答口同答 404 `not_found.ask`({@link askNotVisible}),
2069
- * 无存在性 / 状态谕示)。看不看得见只有一个来源:有行的问 = 店答出的行上当下的属主(按 id 读行,{@link askRowFor} + {@link askRowVisibleTo});
2070
- * 店答不出 ⇒ 看不见,本副本登记上记下的那一位(行上属主的读缓存)不替店作答。没有行的问(问账没上场 / 旧族腿)= 登记记下的那一位(唯一可读的属主事实)。
2100
+ * `GET /v1/tasks/:taskId/asks/:askId` —— **按问读口**:一只 ask 此刻在哪一态({@link TOOL_APPROVAL_READ_STATES})。与决断口同根同门
2101
+ * (路径同一对身份 `taskId` × `askId`;HTTP 层的鉴权 / 属主身份同一只 `gatedSubject`;看不见这只问 —— 查无 / 不属这只 task / 属主不过 / 行读不出 ——
2102
+ * 与决断口同一体 404 `not_found.ask`({@link askNotVisible}),无存在性 / 状态谕示)。看不看得见只有一个来源:店答出的行上当下的 `taskId` 与属主
2103
+ * (按 id 读行,{@link askRowFor} + {@link askRowVisibleUnder});店答不出 ⇒ 看不见,本副本登记上记下的那一位(行上属主的读缓存)不替店作答。
2071
2104
  * 读到的行仍 `STREAM_PENDING`:本副本有在等它的登记 ⇒ `pending`(行投影 = 列表面 `livePending[]` 的同一只投影);没有 ⇒ 它活在别的副本上,
2072
- * 与晚答口同答 404 `tool_approval.not_pending` + `unknown_or_other_replica`(那里才有兑现它的闭包;属主看得见的态);其余行态 → 读态与晚答口的分派同一张表。
2073
- * 纯读:零写、零结算、不碰本地登记(晚答口的 DECIDED 臂会顺手同步本副本的活登记,读口不做)。
2105
+ * 答 404 `tool_approval.not_pending` + `unknown_or_other_replica`(那里才有兑现它的闭包;属主看得见的态);其余行态按 {@link readStateOfRow} 的六态表。
2106
+ * 纯读:零写、零结算、不碰本地登记(与列表面同一读)。
2074
2107
  */
2075
- readApproval(id: string, principal: string | undefined): {
2076
- status: number;
2077
- body: unknown;
2078
- } | Promise<{
2108
+ readAsk(taskId: string, askId: string, principal: string | undefined): Promise<{
2079
2109
  status: number;
2080
2110
  body: unknown;
2081
2111
  }>;
2082
2112
  /**
2083
2113
  * 有行的登记的按问读口 —— 行可见且仍 `STREAM_PENDING` ⇒ `pending`(列表面同一只行投影);否则按行的态答(与读行半场同一张表)。
2084
2114
  * 行读不出(店抛 / 超时)与查无同答 404 —— 活登记与接管登记一样:登记上那一格只是行上属主的读缓存,店答不出时它不替店说「你看得见」
2085
- * (应答口同律:属主门那一读读不出 ⇒ 同一句 404;决议写失败之后读不回行 ⇒ 500,那是「不知道落没落」,不是看得见)。
2115
+ * (7.151.x 及以前的应答口同律;7.152.0 起决断口对「属主门那一读读不出」答 500 `internal.error`、读口答这一句 404;决议写失败之后读不回行 ⇒ 500,那是「不知道落没落」,不是看得见)。
2086
2116
  */
2087
2117
  private readByRow;
2088
- /** {@link readApproval} 的读行半场。 */
2118
+ /** {@link readAsk} 的读行半场。 */
2089
2119
  private readAskRowState;
2090
2120
  /**
2091
2121
  * `PARKED` 行的门读法([ref]):问判官「这张卡的门此刻还是不是该会话当前待决的审批门」。行是终态、不随赎回 / 取消改写,所以只有 checkpoint 知道。
2092
2122
  * `undefined` = **没读到**:没有门读席 / 行上没有 gate token / 读不出(店故障 / 超时,按本协调器的店故障姿势记账 + 一次 warn)。两个读者各自表态:
2093
- * 按问读口读作 `parked`(读口只能说行说的话;只影响**展示**,应答口对同一张卡仍按自己的判官 fail-closed);应答口的受理回执读作「说不出这一代」({@link receiptAnswersNow})。
2123
+ * 按问读口读作 `parked`(读口只能说行说的话;只影响**展示**,决断口对同一张卡仍按自己的判官 fail-closed);决断口的停驻臂读作「门上没站着决定」({@link decideParkedAsk})。
2094
2124
  */
2095
2125
  private readParkedGate;
2096
- /** [ref]:这张停驻卡的门此刻站开在哪一代 —— 门读席读到它仍是该会话当前待决的审批门 ⇒ 它的世代号;没读到 / 门不在待决 ⇒ `undefined`。 */
2097
- private openGateGeneration;
2098
2126
  /** 一条行 → 按问读口的答案(行态六态穷举:新增 `AskState` 而不在此表态 = **编译错**)。 */
2099
2127
  private readStateOfRow;
2100
- /**
2101
- * [ref] —— live 未命中之后的**状态感知分派**(设计 §三的那张表)。
2102
- *
2103
- * 有行的 ask 的 wire 身份就是行的键 ⇒ 按 id **直接读行**(任一副本、重启前后都读得到;不再经任何进程内的桥)。持久店缺席(没有行可判)/ 店在场而行不在 /
2104
- * 行读不出 / 不是调用方的 ⇒ 调用方看不见这只问 ⇒ 404 `not_found.ask`({@link askNotVisible};属主不过与未知同形,无存在性谕示)。行在、调用方是属主、
2105
- * 行仍待决而本副本没有在等它的登记 ⇒ 404 `tool_approval.not_pending` + `unknown_or_other_replica`(那正是「换副本/换端点重试才有意义」的那一因)。
2106
- */
2107
- private respondLate;
2108
2128
  /**
2109
2129
  * 新开的 sync 连接经 **preamble** 呈出的卡 → 登记进这条连接的**消卡订阅**(连接的 `approval_complete` 只投给接下过开卡帧的连接 —— 这些卡的开卡帧
2110
2130
  * 就是 preamble 那一帧)。这几只 ask 在本副本上的最后一条活登记落定时,`deliver` 收一帧 `approval_complete`(落定那一拍铸定的那一只对象)。
@@ -2124,120 +2144,77 @@ export declare class ToolApprovalCoordinator {
2124
2144
  /** settle 咽喉调:一只 ask 在本副本上的最后一条活登记落定 ⇒ 订了它的每条连接按唯一写者规则收一帧消卡(见 {@link watchPresentedCards}),随即退订。 */
2125
2145
  private notifyPresentedCardWatchers;
2126
2146
  /**
2127
- * 一个 wire 身份 → 本副本上**此刻在等它**的那一条活登记(应答口与读口共用这一只读法)。
2128
- * · 有行的 ask:wire 身份 = 行的键 ⇒ 同一只 ask 的活登记(重复登记各一条)里**最早**的那一条(插入序;CAS 单赢,赢后其余登记经
2129
- * 同 askId 的广播口按同一份行真相结清);
2130
- * · 无行的 ask:wire 身份 = 登记本地键 ⇒ 直接取那一条。登记本地键对有行的 ask 不是 wire 身份(它从不上 wire),拿它来问 ⇒ 查无。
2147
+ * 一个 wire 身份 → 本副本上**此刻在等它**的那一条活登记(读口与决断口 live 形握登记共用这一只读法)。wire 身份 = 行的键 ⇒ 同一只 ask 的活登记(重复登记各一条)
2148
+ * 里**最早**的那一条(插入序;CAS 单赢,赢后其余登记经同 askId 的广播口按同一份行真相结清)。登记本地键不是 wire 身份(它从不上 wire),拿它来问 ⇒ 查无。
2131
2149
  */
2132
2150
  private liveEntryFor;
2133
- /** {@link respondLate} 的读行:按 id 读出行,交 {@link dispatchRowTruth}。 */
2134
- private dispatchLateByRow;
2135
2151
  /**
2136
- * 按 wire 身份(= 行的键)读行,给属主门用(应答口 / 晚答口 / 按问读口):读到了 ⇒ 那一行;读得出的「没有这一行」与读不出(店抛或超时,记账)同答 `null`。
2152
+ * 按 wire 身份(= 行的键)读行,给属主门用(按问读口;决断口停驻形的重判读行同用):读到了 ⇒ 那一行;读得出的「没有这一行」与读不出(店抛或超时,记账)同答 `null`。
2137
2153
  * 读不出 = **不知道**属主是谁、这只 ask 落在哪一态 ⇒ 调用方看不见它(与查无同答 404):属主门 fail-closed,受理臂不把未知说成受理,读口不把未知说成待决。
2138
2154
  */
2139
2155
  private askRowFor;
2140
2156
  /**
2141
- * 一只有行的问**此刻的行** —— 应答口 / 按问读口 / 列表面读行的**唯一**入口:{@link askRowFor} 点读(读不出 ⇒ `null` ⇒ 看不见),读到仍待决的行就把这只问在本副本上的登记
2142
- * 对齐到行上当下的属主([ref];先于各口的门判:门判的是调用方,不是这次对齐)。读序号在**发起读之前**取({@link nextRowReadSeq}):晚回来的旧读盖不掉之后发起的读。
2143
- */
2144
- private askRowFollowingOwner;
2145
- /**
2146
- * 一条行(的此刻真相)→ 应答口的答案:属主门 + 受理回执 + 六态穷举分派(闭集:新增 `AskState` 而不在此表态 = **编译错**)。两个入口:本副本没有在等
2147
- * 这只 ask 的登记({@link dispatchLateByRow} 读出行),以及有登记但回决的 CAS 干净地输(行已有终局,`decideAsk` 带回的那条行)—— 一只 ask 的
2148
- * 应答只看行的真相,与本副本有没有残留登记无关。
2149
- */
2150
- private dispatchRowTruth;
2151
- /** [ref]:迟到腿上的 `persistRule` 兑付面 —— 本地条目(规则车道素材的载体)早已随 park 路由散场,
2152
- * 没有任何可对的候选表 ⇒ 如实拒(裁决本身照常受理,与 {@link persistRuleAfterDecision} 的
2153
- * 「失败不翻转裁决」同判)。用既有词 `rule_lane_unavailable`,不为这一支新造词。 */
2154
- private lateRuleRefusal;
2155
- /**
2156
- * [ref] G2 —— DECIDED 行的**幂等回放**([ref] 锚③)。
2157
- *
2158
- * 同向迟到答与**反向**迟到答同判:都是 200 回放**首决**。反向不是 409、不是报错、更不改判 —— 那是
2159
- * 一个 CAS 败者的诚实答:决议早已由首决落定,这次请求只是晚到,响应体把首决交回去,消费端自判向。
2160
- *
2161
- * 权威性四合取与 durable 回决腿的 `decidedRowIsAuthoritative` **同判据**(那处顶注是唯一真源):
2162
- * 决议二值 ∧ 非 provisional ∧ 有 `decidedAtMs` ∧ 态确为 DECIDED。不合形 ⇒ 退回修前 404(绝不把一条
2163
- * 坏行包装成「人的首决」交出去);此处比那条腿更保守地不铸 500,理由是本腿的客户端是壳上那张卡,
2164
- * 它对 404 有成文处置(消卡),对 500 没有。
2165
- */
2166
- private replayDecidedAsk;
2167
- /**
2168
- * [ref] G1 —— PARKED 行的迟到决议:**桥接既有赎回腿**([ref] 锚①「同腿新调用方,零新终局语义」)。
2169
- *
2170
- * 为什么桥接而不是在这里 revive-直续:PARKED 的语义是「候下一 run 重呈或 operator 决议」,而
2171
- * operator 决议早有成文入口(`/decide` 那条链:checkpoint decide CAS → resume)。桥接 = 那条链多一个
2172
- * 调用方,单赢者仍是它的 CAS;直续则要发明第三种赎回形,与 core 的 park/revive 契约重叠。
2173
- *
2174
- * 200 是**受理**语义([ref] 先例):resume 的驱动是 core 内的 fire-and-forget,结果面走 run/events。
2175
- * 非 2xx 原样透出(gate 被别人收走 ⇒ 409 等),绝不粉饰成受理。
2176
- */
2177
- private redeemParkedAsk;
2178
- /**
2179
- * [ref] —— **durable 回决腿的规则位**:PARKED 行的迟到决议携 `persistRule` 时,用**行上**的素材兑付。
2180
- *
2181
- * 回 `undefined` = 这次请求没带 `persistRule`(一个键都不加,老壳的回执逐字节不变);否则回一个
2182
- * `{rulePersisted, ruleRefusal?, …echo}` 片段,由调用点铺进 200 体 —— 与 live 腿 `withFlag` 的键集
2183
- * **同形**(壳的解析器一套判据吃两条腿)。
2184
- *
2185
- * ## 素材从哪来(这是本方法存在的全部理由)
2186
- * live 腿的等式左边是**进程内条目** `PendingApproval.ruleLane`,而 park 路由把条目连同素材一起散场
2187
- * 了(行之外不留任何进程内素材)。本腿因此从**行**取,一件一件对着 live 腿的入参:
2188
- * · `command` = `rule_command` 列(**[ref] 新列**;缺席即本方法唯一的新拒因,见下);
2189
- * · `scope` = `rule_scope_root` 列 ⇒ `{kind:"project", root}`,缺席则**不铸 scope**(core 落 global,
2190
- * = live 腿 `material.scopeRoot` 缺席时逐字同形 —— 绝不在坐标系不明时编一个 root);
2191
- * · 候选表 / `toolName` / 治理位 = 行上的 `card_json`(呈卡帧的同一份;**人看见的就是它**)。
2192
- * ⚠️ 卡上的 `toolName` 带 200 字符的投影帽(`approval-card.ts` 的 `MAX_IDENT`),理论上可被截。
2193
- * **那一支结构性 fail-closed、不会静默存错规则**:规则文本由 `toolName` + 命令派生,截过的名字
2194
- * 让 core 重铸出**另一条**规则 ⇒ 候选臂的文本等式当场不成立(`unknown-candidate`),编辑臂则被
2195
- * core 自己的覆盖门拒。现网不可达(canonical / `mcp__srv__tool` 都远短于 200),记在这里免得
2196
- * 下一个人以为是漏了;
2197
- * · `toolCallId` / `boundInputHash` = 行上的同名列(与 live 腿铸素材时读的是同一个 `req` 的同两件)。
2198
- *
2199
- * ## 三道门与 live 腿逐条同源(顺序也同,理由逐字见 `persistRuleAfterDecision`)
2200
- * 治理档先判(否则一只治理 ask 会拿到「这台部署不供规则」这个更宽的词)→ 车道/属主 → 素材 →
2201
- * `updatedInput`(ctrl+g 编辑放行 ⇒ `rule_input_edited`:生效的是编辑后的调用,而候选是从**原始**
2202
- * 命令铸的)→ 候选臂的文本等式。
2203
- *
2204
- * ## 与 live 腿**刻意不同**的一处:没有裁决前的自由文本预检([ref] 的那道 400)
2205
- * 那道门的语义是「拒的时候这张卡还在,改好再来」;而本腿走到这里时赎回腿的 CAS **已经赢了**
2206
- * (checkpoint 已被消费),卡不可能还在 —— 400 回去只会把一次**已经生效**的放行谎报成失败。
2207
- * 所以编辑臂在本腿上照旧落「裁决受理 + `rulePersisted:false` + `edit-rejected`」那条老路(= [ref]
2208
- * 之前 live 腿的行为),如实登记为本腿的残余。
2209
- */
2210
- private persistRuleFromRow;
2211
- /** [ref]:回执/单飞胜者的**回放形** —— 与首次受理同键集,多一位 `idempotent`,`decision` 恒是**受理时**
2212
- * 那一向(反向重试不改判,与 DECIDED 臂同一条纪律)。 */
2213
- private replayRedeemReceipt;
2157
+ * 🔴 **停驻卡的那一只赎回**([ref] α):准入 → 开格(单飞句柄)→ 一飞(赎回席 → 落行 → 规则位)→ 收格。
2158
+ * 决断口先过属主门、把这一问的词映成 {@link ParkedDecisionRequest},经 {@link decideParkedAsk} 交这里 —— 计费 / 就绪 / 服务凭据三道门、checkpoint 当下的 scope 复核、
2159
+ * 「本会话放行」的铸点、规则位的兑付、决定的落行,一处一份。
2160
+ *
2161
+ * 句柄内的序是硬的(与 live 腿同一条纪律):赎回席非 2xx ⇒ 什么都不落(一次没生效的决定不留记录、不留规则);2xx ⇒ **先**落行(停驻卡的决定记在它的问行上,
2162
+ * 唯一写者 {@link writeAskDecision} 的停驻形),**再**兑规则位。两件都在句柄之内:单飞的后到者 `await` 的就是这枚句柄,它拿到的答案与行上的记录同时成立。
2163
+ * 落行失败(店错 / 超时 / 键被同 task 另一只问抢先占了)不改判:这次决定已经被停驻门受理、续跑已经开始 —— 记一笔 fail-open(登记 tag),回执照常;
2164
+ * 代价是这一问的耐久回放(同键重发)读不到这把键,重发不是回放(店错 ⇒ 首决回显的冲突句;键被另一只问占着 ⇒ 决断口幂等预查的跨问冲突句)。
2165
+ */
2166
+ private runParkedFlight;
2167
+ /** 停驻门受理之后落行(唯一写者的停驻形)。落成 ⇒ 落后的行;没落成 ⇒ `undefined` + 一笔 fail-open(这次决定照常生效,见 {@link runParkedFlight} 顶注)。 */
2168
+ private recordParkedOutcome;
2169
+ /**
2170
+ * 🔴 **耐久决断口对一只停驻的问**([ref] α:留下的那扇口吃下停驻形;此前这里答 `410 gone.ask_parked` 指路 `/decide`)。属主门 `ask.decide` 与体门在调用方
2171
+ * (`routes/runs.ts`)已过;要人门的判词由调用方判好交进来({@link ParkedDecisionRequest.policyMayNotApprove}),这里在「这一次要写」时用。停驻形的两件:
2172
+ * ① **门上已站着一次决定吗**({@link standingParkedDecision}:读停驻门 + 行上的记录)⇒ 站着 ⇒ 交回它(调用方按与 `DECIDED` 行同一条律答:同键 ⇒ 200 回放;否则 409 首决回显)。
2173
+ * ② 没站着(门仍开着 —— 从没被决过,或被引擎重开过)⇒ 交**同一只**赎回({@link runParkedFlight}),受理后决定落行。
2174
+ * 判只在本副本上没有这只问的赎回在飞时做(有 ⇒ 等它落定、从头再读再判);赎回没生效而门此刻已决 ⇒ 也从头再判(答案是门上那一次)。不读进程内回执(7.152.0 起没有受理回执表):本口的回放律读行 + 门。
2175
+ */
2176
+ decideParkedAsk(store: ApprovalAskStore, row: AskRow, request: ParkedDecisionRequest, idempotencyKey: string | undefined): Promise<ParkedAskAnswer>;
2177
+ /**
2178
+ * **这道停驻门属于哪只问**(读口 `listAsksAtGate`:发起会话 = 停驻行的会话 ∧(PARKED ∧ 门上的绑定对相等 ∨ 还没绑上的 PARKING ∧ 这只问自己的调用 id 与展示摘要相等);
2179
+ * 走既有索引,零 DDL;跨过绑定那一拍是同一行同一份卡)—— 两个读者同调这一只:
2180
+ * 续跑腿的规则记录读者与运维队列行的候选投影(同一张卡在队列行上投的候选与兑付读的记录是同一份,下标同一个空间)。
2181
+ * 恰好一行 ⇒ 这张卡的记录是它;零行 ⇒ 没有问行(直停驻卡,读停驻行);多行 / 读抛 / 超时 ⇒ 读不出记录(fail-closed:不退到停驻行 ——
2182
+ * 那会换一份记录兑;队列行同答:不投候选)。
2183
+ */
2184
+ readParkedAskOfGate(sourceSessionId: string, binding: {
2185
+ readonly boundCallId: string;
2186
+ readonly boundInputHash: string;
2187
+ }): Promise<{
2188
+ readonly kind: "row";
2189
+ readonly row: AskRow;
2190
+ } | {
2191
+ readonly kind: "none";
2192
+ } | {
2193
+ readonly kind: "unreadable";
2194
+ }>;
2214
2195
  /**
2215
- * [ref] 车二:回决携规则确认 ⇒ prepare→confirm→redeem(实现在 `rules-consent.ts`,本方法只做门与回显)。
2216
- *
2217
- * 三道门,每道都是**拒绝**而不是降级:
2218
- * ① 裁决必须真落定(200)—— 见调用点注;
2219
- * ② 必须有已验明的 owner —— 规则是**某个人**的持久同意,一条 `owner === null` 的 ask 没有归属人可写;
2220
- * ③ 本 ask 必须登记过规则车道素材(店在场 ∧ 引擎铸过候选 ∧ 命令可读)。
2221
- *
2222
- * 失败**不翻转裁决**:人的「允许这次」已经生效并且已经交给引擎了,把整个回决改判成 4xx 会让一次真实的
2223
- * 放行凭空消失。诚实的形是 200 + `rulePersisted:false`(壳据它告诉人「这次放行了,但『不再询问』没存上」)。
2196
+ * 🔴 **一张卡的人决的唯一写者**(决断口两形同一只;店上两只动词 `decideAsk` / `recordParkedDecision` 在 src 里只有这里调 —— 钉 `test/ask-decision-single-writer.test.ts`)。
2197
+ * · live 形:`STREAM_PENDING → DECIDED` 的单赢者 CAS(批维 + [ref] 属主维),套墙钟上限;**迟到的成功**(这次调用报了超时,决议其实落了盘)⇒
2198
+ * 行过了权威四合取({@link decidedRowFacts})才把同 askId 下还挂着的本地条目按**行**结清(结算取行,[ref]),不让它们等自己的窗再绕一圈。决断口(`routes/runs.ts`)经这里。
2199
+ * · 停驻形:停驻门(续跑腿的门 CAS)**已经受理**之后把记录落在仍 `PARKED` 的行上(态不变,终局恒是那道门);只由停驻赎回的那一飞调({@link runParkedFlight})。
2200
+ * 入参映射只有一只({@link askDecisionRecordOf} / {@link liveDecideInputOf})。抛 = 店错 / 超时(调用方各自的歧义臂接)。
2224
2201
  */
2225
- private persistRuleAfterDecision;
2226
- /** store 在场时的回决 CAS 门(D2)——`respond()` 的异步分支,拆出以保持 `respond()` 本身在 store 缺席
2227
- * 时仍是纯同步函数(D1)。`askStore`/`askId`/`batchId` 由调用方在已窄化的分支里传入(避免非空断言)。 */
2228
- private respondWithCas;
2229
- /** 回决收尾(D1 现行为逐字不变的那一半)——session allow-all 记账 + settle + 200 响应体。原 `respond()`
2230
- * 方法体的逐字搬运([ref] 车2 拆分,行为零改动)。 */
2231
- private finishRespond;
2202
+ writeAskDecision(store: ApprovalAskStore, askId: string, form: {
2203
+ readonly kind: "live";
2204
+ readonly batchId: string;
2205
+ }, owner: string | null, write: LiveAskDecisionWrite): Promise<DecideResult>;
2206
+ writeAskDecision(store: ApprovalAskStore, askId: string, form: {
2207
+ readonly kind: "parked";
2208
+ }, owner: string | null, write: AskDecisionWrite): Promise<RecordParkedDecisionResult>;
2232
2209
  /**
2233
2210
  * 🔴 [ref] —— **起服接管**:把问账里仍 `STREAM_PENDING` 的问接进本审批机的活集合,让 `livePending[]`(及 `/v1/approvals/stream` 的 live 半场、
2234
- * 按问读口、应答口)在重启之后不重开流也看得见、答得了它们。审批机仍是这些读面**唯一**的候选源(哪些问在本副本上有登记):扫问账找待决行的只有这里(起服一次),之后列表行由
2211
+ * 按问读口、决断口)在重启之后不重开流也看得见、答得了它们。审批机仍是这些读面**唯一**的候选源(哪些问在本副本上有登记):扫问账找待决行的只有这里(起服一次),之后列表行由
2235
2212
  * 同一只 {@link livePendingRowOf} 投影,卡帧 = `buildReplayFrame`(开流 preamble 同一只构造)—— 不是 GET 上按属主扫表的第二 reader;列表面对候选逐只点读行(见 {@link listLivePending}),候选集之外的问它不认识。
2236
2213
  *
2237
2214
  * 律(设计稿 `design-[ref].md` §2):接管登记**没有引擎腿在等它**(铸它的进程没了,或它活在别的副本上),与活登记同一只状态机 ——
2238
- * 应答 = 同一把 `decideAsk` CAS({@link answerRegistration}),收敛 = 同一条悬挂轮询腿读行({@link pollSuspendedDecisions});它活多久只由行说了算,
2215
+ * 决定 = 同一把 `decideAsk` CAS(决断口经 {@link writeAskDecision}),收敛 = 同一条悬挂轮询腿读行({@link pollSuspendedDecisions});它活多久只由行说了算,
2239
2216
  * 没有自己的窗(无等待腿的行的到期写者已经存在:对账器段二,同一只政策感知终态 claim,窗 + 宽限 —— 接管不新增竞争者)。
2240
- * 「本副本没有引擎腿在等它」机读披露:列表行与应答回执带 `consumerState:"absent"`({@link ASK_DECISION_CONSUMER_ABSENT})。
2217
+ * 「本副本没有引擎腿在等它」机读披露:列表行与决断口回执带 `consumerState:"absent"`({@link ASK_DECISION_CONSUMER_ABSENT})。
2241
2218
  *
2242
2219
  * 装配点 = `boot/stage-07` 起服收敛之后、reaper / HTTP 之前(local 车道上收敛先把前世问收成 `VOID` ⇒ 这里读到零行,车道无分叉)。
2243
2220
  * 幂等:本副本已有这只 askId 的登记就跳过;每次起服由行重新推导。读失败 ⇒ **拒启**(抛;与起服收敛同一拍、同姿态 —— 照常起来等于让
@@ -2259,25 +2236,6 @@ export declare class ToolApprovalCoordinator {
2259
2236
  * (不发帧 —— 问不是被谁答掉的,编一帧消卡就是撒谎;壳的结构补偿仍是下一次 preamble 的全量对账基准)。还有活登记 ⇒ 订阅留给它的结算。
2260
2237
  */
2261
2238
  private forgetAdoptedAsk;
2262
- /**
2263
- * 🔴 [ref]:**有行的登记,属主跟行走** —— 本协调器每读到这只问仍待决的行一次(悬挂轮询 / 应答口读行 / 读口读行 / 收编后的重读),就把这只问在本副本上的
2264
- * **每一条**登记对齐到行上当下的属主。活登记与接管登记同一条(修前只有接管登记跟,活登记的那一格停在铸卡那一刻:收编之后列表面仍按前属主列、
2265
- * 店写失败 + 确认读也失败的那一支按前属主放行一次)。行的属主只有 `/v1/adoption` 改写;这里只对齐、不判授权(授权照旧在各扇门里按面表判)。
2266
- */
2267
- private followRowOwner;
2268
- /** [ref]:行读的单调序号 —— 每一次会拿来对齐属主的行读在**发起之前**取一个;同一副本内后发起的读看到的行不比先发起的旧(店的单行读按提交序)。 */
2269
- private rowReadSeq;
2270
- private nextRowReadSeq;
2271
- /**
2272
- * [ref]:**收编落定后的重读** —— `approval_ask.owner` 唯一的写者(`/v1/adoption`)在本副本落成回执后由路由调一次:本副本每一只有行的问点读一次
2273
- * (带墙钟期限),仍待决 ⇒ {@link followRowOwner}。读不出 ⇒ 记账(与其它店调用同一只 `noteStoreError`)、这只问原样留着上一次读到的属主,不编;
2274
- * 行没了 / 已终局 ⇒ 不在这里处置(悬挂轮询与应答口各有自己的收法)。射程 = 本副本(多副本部署里别的副本的登记由它们自己的行读跟上;收编的运维前提是先停引擎)。
2275
- */
2276
- followRowOwners(): Promise<{
2277
- read: number;
2278
- followed: number;
2279
- unreadable: number;
2280
- }>;
2281
2239
  /** 这只 askId 在本副本上有几条**有引擎腿在等**的登记(接管登记不算)—— 轮询腿的「被唤醒数」读它。 */
2282
2240
  private waitingRegistrationCount;
2283
2241
  /**
@@ -2289,13 +2247,13 @@ export declare class ToolApprovalCoordinator {
2289
2247
  * (R7:不带主体的调用方列得出它答得了的那几张),其余串 = 只见 `owner === scope` 的条目(null-owner 行对具名主体不列,宁少列不超范围)。
2290
2248
  * 行的 `approvalId` 就是 `respond()` 收的 id(同源可达,[ref] 判据);`expiresAtMs` 照抄登记时单点铸定的窗死线([ref] 三键同一个数)。
2291
2249
  *
2292
- * 🔴 **有行的问,列表只列按问读口会答 `pending` 的**(看不看得见只有一个来源,{@link readApproval} 同一条律):本副本此刻的登记只是**候选**(哪些问在本副本上有登记);
2293
- * 有行的问,列不列它、列给谁只由店答出的行说了算 —— 对每只候选点读行({@link askRowFollowingOwner},与读口 / 应答口同一只 {@link askRowFor}):行读不出(店抛 / 超时)⇒ 看不见 ⇒ 不列
2250
+ * 🔴 **有行的问,列表只列按问读口会答 `pending` 的**(看不看得见只有一个来源,{@link readAsk} 同一条律):本副本此刻的登记只是**候选**(哪些问在本副本上有登记);
2251
+ * 有行的问,列不列它、列给谁只由店答出的行说了算 —— 对每只候选点读行({@link askRowFor},与读口 / 决断口同一只):行读不出(店抛 / 超时)⇒ 看不见 ⇒ 不列
2294
2252
  * (与读口的 `404 not_found.ask` 同隐;店恢复后下一次列表即回),行已离开 `STREAM_PENDING`(别处答了 / 收走了,本副本的登记还没闻讯)⇒ 不列(读口答的是它此刻的态),
2295
- * 行上当下的属主不在 `scope` 内 ⇒ 不列(登记上记下的那一位只是行上属主的读缓存,不替店作答)。没有行的问(问账没上场 / 旧族腿)登记记下的属主是唯一可读的属主事实 ⇒ 照登记列。
2253
+ * 行上当下的属主不在 `scope` 内 ⇒ 不列(登记上记下的那一位只是行上属主的读缓存,不替店作答)。
2296
2254
  * 读行并发发起、各自带 {@link DURABLE_CONVERGE_READ_TIMEOUT_MS} 的墙钟 ⇒ 一次列表至多等一个期限;行体的投影取在读完之后、对每个列出的 wire 身份重取此刻代表它的那条登记
2297
2255
  * ({@link liveEntryFor}):读行期间已结算的不列,读行期间被活登记接替的接管登记按活登记的样子列。
2298
- * 读行的次数 = 本副本此刻**有行的不同 ask 数**(重复登记共用一次读,没有行的问不读),**不按 `scope` 先筛**(登记上的属主只是读缓存,不替店判谁看得见 —— scope 之外的卡也要读一次行才判得出);
2256
+ * 读行的次数 = 本副本此刻**不同 ask 数**(重复登记共用一次读),**不按 `scope` 先筛**(登记上的属主只是读缓存,不替店判谁看得见 —— scope 之外的卡也要读一次行才判得出);
2299
2257
  * 登记数的上界是每个任务 / 每个属主各一个未决帽(`STREAM_APPROVAL_ADMIT_MAX_PER_TASK` / `_PER_OWNER`)加起服接管上限 {@link ADOPT_OPEN_ASKS_MAX},本副本的总数没有全局帽。
2300
2258
  * 列表行 ⊆ 按问读口对同一调用方答 `pending` 的那些;反过来不然 —— `scope` 比读口窄:具名主体的列表不含无主的卡(宁少列),运维列表按 `?owner=` / 全量列、含读口对运维不放行的卡。
2301
2259
  */