@sema-agent/server 7.132.0 → 7.134.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 (473) hide show
  1. package/MIGRATION.md +353 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +301 -64
  5. package/deploy/sema-up/README.md +35 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
  9. package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
  10. package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
  11. package/deploy/sema-up/chart/templates/server.yaml +19 -2
  12. package/deploy/sema-up/chart/values-full-single.yaml +5 -1
  13. package/deploy/sema-up/chart/values.yaml +34 -0
  14. package/deploy/sema-up/stack/compose.yaml +3 -0
  15. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  16. package/dist/adoption/plan.d.ts +3 -2
  17. package/dist/adoption/plan.js +7 -5
  18. package/dist/adoption/runner.js +3 -10
  19. package/dist/adoption/sql.d.ts +3 -2
  20. package/dist/adoption/sql.js +3 -5
  21. package/dist/adoption/wire.d.ts +4 -1
  22. package/dist/adoption/wire.js +1 -0
  23. package/dist/approval-ask-audit-store.d.ts +32 -14
  24. package/dist/approval-ask-audit-store.js +272 -74
  25. package/dist/approval-ask-machine.d.ts +15 -0
  26. package/dist/approval-ask-machine.js +6 -0
  27. package/dist/approval-ask-retention.d.ts +136 -0
  28. package/dist/approval-ask-retention.js +102 -0
  29. package/dist/approval-card.d.ts +83 -23
  30. package/dist/approval-card.js +45 -15
  31. package/dist/approval-content-kind.d.ts +5 -2
  32. package/dist/approval-content-kind.js +16 -3
  33. package/dist/approval-deny-reasons.d.ts +1 -1
  34. package/dist/approval-gate-currency.d.ts +72 -0
  35. package/dist/approval-gate-currency.js +94 -0
  36. package/dist/approval.d.ts +15 -0
  37. package/dist/approval.js +55 -17
  38. package/dist/audit.d.ts +27 -10
  39. package/dist/audit.js +12 -16
  40. package/dist/bake-runner/main.js +3 -2
  41. package/dist/boot/coordinators.d.ts +6 -1
  42. package/dist/boot/coordinators.js +6 -3
  43. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  44. package/dist/boot/execution-env.js +9 -7
  45. package/dist/boot/execution-lane.js +11 -0
  46. package/dist/boot/leader.d.ts +2 -0
  47. package/dist/boot/leader.js +4 -1
  48. package/dist/boot/memory-boundary.js +2 -2
  49. package/dist/boot/memory-consolidation.d.ts +5 -4
  50. package/dist/boot/memory-consolidation.js +7 -6
  51. package/dist/boot/org-delivery.d.ts +28 -0
  52. package/dist/boot/org-delivery.js +20 -0
  53. package/dist/boot/read-deny-anchor-audit.js +2 -2
  54. package/dist/boot/reapers.d.ts +3 -0
  55. package/dist/boot/reapers.js +21 -1
  56. package/dist/boot/resolve-spec.d.ts +3 -0
  57. package/dist/boot/resolve-spec.js +60 -81
  58. package/dist/boot/runner-deps.d.ts +18 -5
  59. package/dist/boot/runner-deps.js +10 -0
  60. package/dist/boot/session-faces.d.ts +1 -0
  61. package/dist/boot/session-faces.js +4 -2
  62. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  63. package/dist/boot/stage-06-runners.d.ts +6 -3
  64. package/dist/boot/stage-06-runners.js +20 -4
  65. package/dist/boot/stage-07-capability-layer.d.ts +4 -1
  66. package/dist/boot/stage-07-capability-layer.js +24 -3
  67. package/dist/boot/stage-08-reapers.d.ts +4 -1
  68. package/dist/boot/stage-08-reapers.js +2 -2
  69. package/dist/boot/stage-09-leader.d.ts +5 -1
  70. package/dist/boot/stage-09-leader.js +2 -2
  71. package/dist/boot/stage-10-http-server.d.ts +5 -1
  72. package/dist/boot/stage-10-http-server.js +6 -6
  73. package/dist/boot/stores.d.ts +8 -0
  74. package/dist/boot/stores.js +10 -14
  75. package/dist/boot/web-admin.d.ts +10 -0
  76. package/dist/boot/web-admin.js +162 -65
  77. package/dist/boot/workflow-orchestration.d.ts +2 -0
  78. package/dist/boot/workflow-orchestration.js +2 -1
  79. package/dist/brain.js +8 -3
  80. package/dist/breaker-key.d.ts +6 -0
  81. package/dist/breaker-key.js +29 -0
  82. package/dist/budget.js +5 -1
  83. package/dist/caller-text-echo.d.ts +11 -6
  84. package/dist/caller-text-echo.js +10 -12
  85. package/dist/canonical-json.d.ts +2 -41
  86. package/dist/canonical-json.js +2 -13
  87. package/dist/capabilities/center-plugins.d.ts +7 -0
  88. package/dist/capabilities/center-plugins.js +1 -1
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/execution-lane.js +2 -2
  92. package/dist/capabilities/hands-lane.d.ts +21 -0
  93. package/dist/capabilities/hands-lane.js +10 -0
  94. package/dist/capabilities/mcp-probe.d.ts +36 -4
  95. package/dist/capabilities/mcp-probe.js +29 -6
  96. package/dist/capabilities/scenarios.d.ts +63 -7
  97. package/dist/capabilities/scenarios.js +39 -7
  98. package/dist/capability-facts.d.ts +36 -4
  99. package/dist/capability-facts.js +30 -4
  100. package/dist/center-config-tier.d.ts +69 -0
  101. package/dist/center-config-tier.js +42 -0
  102. package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
  103. package/dist/checkpoint-ctx-seal-m28.js +19 -0
  104. package/dist/checkpoint-identity.d.ts +16 -0
  105. package/dist/checkpoint-identity.js +19 -0
  106. package/dist/config-catalog.d.ts +17 -10
  107. package/dist/config-catalog.js +43 -28
  108. package/dist/config-d-migration.d.ts +3 -1
  109. package/dist/config-d-migration.js +2 -2
  110. package/dist/config-dir-trust.d.ts +114 -0
  111. package/dist/config-dir-trust.js +388 -0
  112. package/dist/config-invariants.d.ts +18 -5
  113. package/dist/config-invariants.js +35 -3
  114. package/dist/config-provider.d.ts +6 -1
  115. package/dist/config-provider.js +6 -2
  116. package/dist/config-types.d.ts +71 -14
  117. package/dist/config-types.js +8 -0
  118. package/dist/config.d.ts +13 -0
  119. package/dist/config.js +121 -59
  120. package/dist/delegated-session-owner.d.ts +185 -0
  121. package/dist/delegated-session-owner.js +119 -0
  122. package/dist/device-protocol.d.ts +5 -3
  123. package/dist/device-protocol.js +1 -1
  124. package/dist/device-ws-hub.js +21 -2
  125. package/dist/device-ws-protocol.d.ts +70 -6
  126. package/dist/device-ws-protocol.js +50 -23
  127. package/dist/elicitation.js +3 -2
  128. package/dist/entry-problems.d.ts +34 -0
  129. package/dist/entry-problems.js +14 -0
  130. package/dist/execution-lane-caps.d.ts +49 -10
  131. package/dist/execution-lane-caps.js +43 -4
  132. package/dist/field-conflict.d.ts +44 -0
  133. package/dist/field-conflict.js +21 -0
  134. package/dist/file-history-disclosure.d.ts +34 -5
  135. package/dist/file-history-disclosure.js +2 -2
  136. package/dist/fleet/fleet-bus.d.ts +84 -6
  137. package/dist/fleet/fleet-bus.js +42 -9
  138. package/dist/hooks/classic-stations.d.ts +10 -5
  139. package/dist/hooks/classic-stations.js +4 -4
  140. package/dist/hooks/command-spawn.d.ts +57 -0
  141. package/dist/hooks/command-spawn.js +139 -0
  142. package/dist/hooks/hook-llm.js +2 -2
  143. package/dist/hooks/hook-runner.d.ts +127 -25
  144. package/dist/hooks/hook-runner.js +668 -287
  145. package/dist/hooks/hook-source.d.ts +44 -0
  146. package/dist/hooks/hook-source.js +40 -0
  147. package/dist/http/active-run-conflict.d.ts +5 -13
  148. package/dist/http/active-run-conflict.js +17 -27
  149. package/dist/http/admission.js +111 -60
  150. package/dist/http/approval-sweeps.js +58 -19
  151. package/dist/http/caller-trust.d.ts +77 -0
  152. package/dist/http/caller-trust.js +143 -0
  153. package/dist/http/checkpoint-ctx.d.ts +173 -18
  154. package/dist/http/checkpoint-ctx.js +171 -12
  155. package/dist/http/claimed-run.d.ts +4 -3
  156. package/dist/http/device-placement.d.ts +2 -4
  157. package/dist/http/device-placement.js +2 -1
  158. package/dist/http/dispatch.js +13 -7
  159. package/dist/http/durable-run-leg.d.ts +4 -32
  160. package/dist/http/durable-run-leg.js +37 -12
  161. package/dist/http/idempotency.d.ts +2 -2
  162. package/dist/http/idempotency.js +2 -2
  163. package/dist/http/owner-access.d.ts +56 -0
  164. package/dist/http/owner-access.js +42 -0
  165. package/dist/http/principal-gate.d.ts +78 -27
  166. package/dist/http/principal-gate.js +64 -14
  167. package/dist/http/readiness.d.ts +11 -5
  168. package/dist/http/readiness.js +10 -3
  169. package/dist/http/refusal-body.d.ts +12 -0
  170. package/dist/http/refusal-body.js +11 -0
  171. package/dist/http/request-guards.d.ts +16 -32
  172. package/dist/http/request-guards.js +31 -30
  173. package/dist/http/resume-ctx-read.d.ts +50 -6
  174. package/dist/http/resume-ctx-read.js +33 -7
  175. package/dist/http/resume-legs.d.ts +5 -5
  176. package/dist/http/resume-legs.js +163 -91
  177. package/dist/http/retired-service-deps.d.ts +43 -0
  178. package/dist/http/retired-service-deps.js +18 -0
  179. package/dist/http/route-ctx.d.ts +44 -37
  180. package/dist/http/route-ctx.js +4 -0
  181. package/dist/http/route-table.js +2 -0
  182. package/dist/http/routes/a2a-serve.js +3 -4
  183. package/dist/http/routes/admin-config-refresh.js +1 -1
  184. package/dist/http/routes/admin-drain.js +1 -1
  185. package/dist/http/routes/admin-memory-optout.js +5 -1
  186. package/dist/http/routes/adoption.js +2 -9
  187. package/dist/http/routes/agents-roster.js +2 -3
  188. package/dist/http/routes/approvals-assistant.js +91 -56
  189. package/dist/http/routes/background.js +3 -2
  190. package/dist/http/routes/capabilities.js +20 -4
  191. package/dist/http/routes/config-catalog.d.ts +3 -3
  192. package/dist/http/routes/config-catalog.js +1 -1
  193. package/dist/http/routes/devices.js +3 -17
  194. package/dist/http/routes/diagnostics.d.ts +3 -3
  195. package/dist/http/routes/diagnostics.js +6 -2
  196. package/dist/http/routes/fleet.js +4 -4
  197. package/dist/http/routes/images.js +6 -7
  198. package/dist/http/routes/leader.js +1 -8
  199. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  200. package/dist/http/routes/mcp-reconnect.js +3 -2
  201. package/dist/http/routes/memory-bundle.js +1 -1
  202. package/dist/http/routes/memory-compliance.js +1 -1
  203. package/dist/http/routes/memory-consolidation.js +1 -1
  204. package/dist/http/routes/memory-origin.d.ts +1 -1
  205. package/dist/http/routes/memory-origin.js +1 -1
  206. package/dist/http/routes/memory-policy.d.ts +1 -1
  207. package/dist/http/routes/memory-policy.js +3 -2
  208. package/dist/http/routes/notify-wake.js +8 -21
  209. package/dist/http/routes/observability.js +2 -2
  210. package/dist/http/routes/principal-inbox.d.ts +39 -0
  211. package/dist/http/routes/principal-inbox.js +76 -0
  212. package/dist/http/routes/retention-ops.js +2 -9
  213. package/dist/http/routes/rules.js +9 -22
  214. package/dist/http/routes/runs.d.ts +5 -0
  215. package/dist/http/routes/runs.js +63 -115
  216. package/dist/http/routes/session-sync.d.ts +3 -2
  217. package/dist/http/routes/session-sync.js +53 -48
  218. package/dist/http/routes/sessions-list.d.ts +1 -1
  219. package/dist/http/routes/sessions-list.js +3 -4
  220. package/dist/http/routes/sessions.js +33 -43
  221. package/dist/http/routes/side-query.js +6 -4
  222. package/dist/http/routes/tasks.js +71 -30
  223. package/dist/http/routes/trace-usage.js +7 -9
  224. package/dist/http/routes/workflows.d.ts +351 -0
  225. package/dist/http/routes/workflows.js +153 -119
  226. package/dist/http/run-declared-families.d.ts +16 -0
  227. package/dist/http/run-declared-families.js +12 -0
  228. package/dist/http/send.d.ts +24 -3
  229. package/dist/http/send.js +14 -2
  230. package/dist/http/server.d.ts +23 -18
  231. package/dist/http/server.js +20 -15
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +4 -3
  234. package/dist/http/submit-ctx.js +23 -6
  235. package/dist/http/submit-replay.d.ts +4 -3
  236. package/dist/http/submit-replay.js +5 -4
  237. package/dist/http/wire-types.d.ts +17 -10
  238. package/dist/index.d.ts +3 -1
  239. package/dist/index.js +1 -1
  240. package/dist/lane-home-probe.d.ts +78 -9
  241. package/dist/lane-home-probe.js +78 -12
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/leader/wire.d.ts +4 -0
  245. package/dist/leader/wire.js +8 -7
  246. package/dist/limit-refusal.d.ts +17 -5
  247. package/dist/limit-refusal.js +4 -1
  248. package/dist/main.js +1 -1
  249. package/dist/mcp-assertion-header.d.ts +31 -10
  250. package/dist/mcp-assertion-header.js +10 -3
  251. package/dist/memory-origin-fence.js +2 -2
  252. package/dist/memory-project-layer.d.ts +37 -0
  253. package/dist/memory-project-layer.js +46 -0
  254. package/dist/memory-scope.d.ts +23 -16
  255. package/dist/memory-scope.js +24 -8
  256. package/dist/memory-sync-client.d.ts +27 -13
  257. package/dist/memory-sync-client.js +107 -18
  258. package/dist/model-compat.d.ts +1 -1
  259. package/dist/model-entry-refusal.d.ts +9 -1
  260. package/dist/model-entry-refusal.js +6 -1
  261. package/dist/model-plane-face.d.ts +51 -0
  262. package/dist/model-plane-face.js +24 -0
  263. package/dist/model-provider.d.ts +5 -0
  264. package/dist/model-provider.js +4 -2
  265. package/dist/model-route-endpoint.d.ts +8 -11
  266. package/dist/model-route-endpoint.js +4 -7
  267. package/dist/model-route-env.d.ts +22 -0
  268. package/dist/model-route-env.js +2 -0
  269. package/dist/model-route-gap.d.ts +60 -30
  270. package/dist/model-route-gap.js +21 -15
  271. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  272. package/dist/observability/corrupt-read-seat.js +9 -0
  273. package/dist/observability/err-text.d.ts +6 -0
  274. package/dist/observability/err-text.js +18 -4
  275. package/dist/observability/fail-open.d.ts +35 -9
  276. package/dist/observability/fail-open.js +35 -9
  277. package/dist/observability/metrics.js +1 -0
  278. package/dist/observability/prompt-manifest.d.ts +22 -25
  279. package/dist/observability/prompt-manifest.js +54 -50
  280. package/dist/observability/tool-trace.js +9 -10
  281. package/dist/operator-ask.d.ts +10 -0
  282. package/dist/operator-ask.js +3 -0
  283. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  284. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  285. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  286. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  287. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  288. package/dist/orchestration/workflow-notify-journal.js +27 -34
  289. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  290. package/dist/orchestration/workflow-park-decision.js +119 -0
  291. package/dist/org-delivery-gate.d.ts +81 -0
  292. package/dist/org-delivery-gate.js +59 -0
  293. package/dist/panel-tool-names.d.ts +23 -0
  294. package/dist/panel-tool-names.js +8 -0
  295. package/dist/parked-decide.d.ts +43 -11
  296. package/dist/parked-decide.js +100 -51
  297. package/dist/parked-revive-surface.d.ts +9 -2
  298. package/dist/parked-revive-surface.js +11 -8
  299. package/dist/permission-rule-list.d.ts +1 -1
  300. package/dist/permission-rule-list.js +2 -2
  301. package/dist/permission-rule-vocab.d.ts +1 -23
  302. package/dist/permission-rule-vocab.js +0 -13
  303. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  304. package/dist/plugins/approval-ask-store-file.js +21 -0
  305. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  306. package/dist/plugins/approval-ask-store-memory.js +34 -2
  307. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  308. package/dist/plugins/approval-ask-store-sql.js +37 -1
  309. package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
  310. package/dist/plugins/approval-payload-fingerprint.js +1 -1
  311. package/dist/plugins/blob-backend.d.ts +38 -25
  312. package/dist/plugins/blob-backend.js +29 -19
  313. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  314. package/dist/plugins/breaker-state-sql.js +4 -4
  315. package/dist/plugins/caching-session-store.d.ts +4 -1
  316. package/dist/plugins/caching-session-store.js +7 -3
  317. package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
  318. package/dist/plugins/checkpoint-store-sql.js +65 -3
  319. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  320. package/dist/plugins/file-history-store-sql.js +3 -1
  321. package/dist/plugins/file-run-store.d.ts +5 -13
  322. package/dist/plugins/file-run-store.js +9 -0
  323. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  324. package/dist/plugins/fork-routing-session-store.js +12 -1
  325. package/dist/plugins/host-platform.d.ts +2 -0
  326. package/dist/plugins/host-platform.js +2 -1
  327. package/dist/plugins/local-checkpoint-store.d.ts +15 -2
  328. package/dist/plugins/local-checkpoint-store.js +32 -1
  329. package/dist/plugins/local-session-store.d.ts +13 -10
  330. package/dist/plugins/local-session-store.js +23 -14
  331. package/dist/plugins/local-session-window.d.ts +45 -0
  332. package/dist/plugins/local-session-window.js +38 -0
  333. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  334. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  335. package/dist/plugins/mailbox-store-sql.js +77 -52
  336. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  337. package/dist/plugins/memory-run-store.d.ts +5 -13
  338. package/dist/plugins/memory-run-store.js +8 -0
  339. package/dist/plugins/one-time-migrations.d.ts +121 -5
  340. package/dist/plugins/one-time-migrations.js +332 -8
  341. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  342. package/dist/plugins/org-delivery-quota-store.js +228 -0
  343. package/dist/plugins/permission-rule-store-file.js +10 -6
  344. package/dist/plugins/permission-rule-store-sql.js +8 -8
  345. package/dist/plugins/pg-pool.js +39 -7
  346. package/dist/plugins/pg-session-storage.d.ts +18 -5
  347. package/dist/plugins/pg-session-storage.js +68 -23
  348. package/dist/plugins/remote-env-adb.d.ts +6 -12
  349. package/dist/plugins/remote-env-adb.js +12 -2
  350. package/dist/plugins/remote-env-device.d.ts +14 -7
  351. package/dist/plugins/remote-env-device.js +23 -15
  352. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  353. package/dist/plugins/remote-env-k8s.js +23 -5
  354. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  355. package/dist/plugins/remote-env-local-docker.js +12 -9
  356. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  357. package/dist/plugins/remote-env-ssh.js +17 -11
  358. package/dist/plugins/run-store-sql.d.ts +16 -14
  359. package/dist/plugins/run-store-sql.js +22 -2
  360. package/dist/plugins/schema-indexes.js +2 -0
  361. package/dist/plugins/send-user-file.js +2 -2
  362. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  363. package/dist/plugins/session-epoch-anchor.js +2 -3
  364. package/dist/plugins/session-ownership.d.ts +11 -0
  365. package/dist/plugins/session-ownership.js +11 -0
  366. package/dist/plugins/session-placement.d.ts +12 -14
  367. package/dist/plugins/session-placement.js +2 -15
  368. package/dist/plugins/session-store.d.ts +18 -8
  369. package/dist/plugins/session-store.js +15 -4
  370. package/dist/plugins/sql-driver.d.ts +74 -11
  371. package/dist/plugins/sql-driver.js +210 -12
  372. package/dist/plugins/sql-errors.d.ts +23 -0
  373. package/dist/plugins/sql-errors.js +21 -0
  374. package/dist/plugins/store-backend.d.ts +36 -1
  375. package/dist/plugins/store-backend.js +40 -14
  376. package/dist/plugins/store-contracts.d.ts +42 -0
  377. package/dist/plugins/store-contracts.js +1 -0
  378. package/dist/plugins/tidb-pool.d.ts +6 -1
  379. package/dist/plugins/tidb-pool.js +44 -10
  380. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  381. package/dist/plugins/tidb-session-storage.js +2 -2
  382. package/dist/plugins/tidb-session-store.d.ts +25 -5
  383. package/dist/plugins/tidb-session-store.js +67 -21
  384. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  385. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  386. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  387. package/dist/plugins/workflow-run-store-sql.js +50 -9
  388. package/dist/posture-source.d.ts +18 -10
  389. package/dist/posture-source.js +4 -1
  390. package/dist/project-identity.d.ts +45 -6
  391. package/dist/project-identity.js +162 -8
  392. package/dist/project-layer-key.d.ts +28 -0
  393. package/dist/project-layer-key.js +29 -0
  394. package/dist/question.js +3 -2
  395. package/dist/read-deny-entry.d.ts +25 -0
  396. package/dist/read-deny-entry.js +12 -0
  397. package/dist/read-face-posture.d.ts +37 -11
  398. package/dist/read-face-posture.js +32 -3
  399. package/dist/request-key-closure.d.ts +7 -0
  400. package/dist/request-key-closure.js +9 -1
  401. package/dist/request-tool-axes.d.ts +12 -0
  402. package/dist/request-tool-axes.js +20 -0
  403. package/dist/request-value-closure.d.ts +5 -0
  404. package/dist/request-value-closure.js +11 -3
  405. package/dist/rule-entry-list.d.ts +26 -2
  406. package/dist/rule-entry-list.js +72 -12
  407. package/dist/rules-consent.js +3 -4
  408. package/dist/run-acceptance.d.ts +19 -3
  409. package/dist/run-acceptance.js +13 -1
  410. package/dist/run-local.js +37 -6
  411. package/dist/runs.d.ts +12 -10
  412. package/dist/runs.js +25 -6
  413. package/dist/runtime-caps-resolver.d.ts +16 -6
  414. package/dist/runtime-caps-resolver.js +18 -5
  415. package/dist/sandbox-pkg-source.d.ts +19 -1
  416. package/dist/sandbox-pkg-source.js +29 -7
  417. package/dist/sealed-key.d.ts +32 -0
  418. package/dist/sealed-key.js +55 -1
  419. package/dist/security.d.ts +95 -15
  420. package/dist/security.js +52 -9
  421. package/dist/session-error-wire.d.ts +31 -7
  422. package/dist/session-error-wire.js +9 -2
  423. package/dist/session-sync-kernel.d.ts +37 -10
  424. package/dist/session-sync-kernel.js +10 -0
  425. package/dist/session-titled-frame.d.ts +33 -0
  426. package/dist/session-titled-frame.js +4 -0
  427. package/dist/session-titler.d.ts +9 -1
  428. package/dist/session-titler.js +15 -4
  429. package/dist/spec-fields.js +21 -2
  430. package/dist/sql-engine-posture.d.ts +3 -1
  431. package/dist/task-a2a.js +4 -3
  432. package/dist/task-cwd.d.ts +1 -1
  433. package/dist/task-mcp.d.ts +5 -5
  434. package/dist/task-mcp.js +27 -74
  435. package/dist/task-settings.d.ts +93 -88
  436. package/dist/task-settings.js +71 -63
  437. package/dist/text-bidi.d.ts +0 -4
  438. package/dist/text-bidi.js +1 -3
  439. package/dist/tighten-only-seats.d.ts +150 -0
  440. package/dist/tighten-only-seats.js +196 -0
  441. package/dist/tool-approval.d.ts +451 -136
  442. package/dist/tool-approval.js +733 -256
  443. package/dist/tool-rule-names.d.ts +6 -0
  444. package/dist/trace/core-keyset-guard.d.ts +108 -25
  445. package/dist/trace/exit-seat.d.ts +40 -0
  446. package/dist/trace/exit-seat.js +130 -0
  447. package/dist/trace/ledger-events.d.ts +6 -3
  448. package/dist/trace/project.d.ts +98 -13
  449. package/dist/trace/project.js +57 -32
  450. package/dist/trace/projection-table.d.ts +100 -0
  451. package/dist/trace/projection-table.js +130 -0
  452. package/dist/trace/redact.d.ts +57 -0
  453. package/dist/trace/redact.js +962 -168
  454. package/dist/trace/self-minted-wire.d.ts +349 -1
  455. package/dist/trace/self-minted-wire.js +118 -1
  456. package/dist/trace/wire-projection-faces.d.ts +304 -2
  457. package/dist/trace/wire-projection-faces.js +160 -13
  458. package/dist/url-refusal.js +2 -0
  459. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  460. package/dist/web-admin-client/apply-effective.js +56 -5
  461. package/dist/web-admin-client/facade.d.ts +1 -1
  462. package/dist/web-admin-client/facade.js +1 -1
  463. package/dist/web-admin-client/read-face.js +5 -9
  464. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  465. package/dist/web-admin-client/skills-mcp.js +6 -8
  466. package/dist/web-admin-client/types.d.ts +1 -1
  467. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  468. package/package.json +8 -4
  469. package/scripts/drain-check-local.mjs +34 -2
  470. package/scripts/drain-check.mysql.sql +20 -2
  471. package/scripts/drain-check.pg.sql +20 -2
  472. package/dist/mcp-tool-faces.d.ts +0 -69
  473. package/dist/mcp-tool-faces.js +0 -106
@@ -0,0 +1,8 @@
1
+ export const PANEL_MAX_TOOL_NAMES = 200;
2
+ export function buildBoundedToolNames(names) {
3
+ return {
4
+ toolNames: names.slice(0, PANEL_MAX_TOOL_NAMES),
5
+ ...(names.length > PANEL_MAX_TOOL_NAMES ? { toolNamesTruncated: true } : {}),
6
+ };
7
+ }
8
+ //# sourceMappingURL=panel-tool-names.js.map
@@ -9,10 +9,12 @@
9
9
  * 行永 parked、生命周期分叉)。
10
10
  */
11
11
  import type { HostDecision } from "./host-decision.js";
12
- import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, QuestionAnswer, ResumeOutcome, TaskRegistry, ToolExecuteContext, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
12
+ import type { DecideBinding } from "./http/wire-types.js";
13
+ import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, CheckpointToken, QuestionAnswer, RunInternals, TaskRegistry, ToolExecuteContext, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
13
14
  import type { ParkedReviveSurfaceFactory } from "./parked-revive-surface.js";
14
15
  import type { RebuiltInheritedGate } from "./boot/parked-revive-gate.js";
15
16
  import { type WorkflowRunParkKey, type WorkflowAgentSessionIndex } from "./orchestration/workflow-agent-session-index.js";
17
+ import type { WorkflowParkDecisionStore, WorkflowParkOutcome } from "./orchestration/workflow-park-decision.js";
16
18
  import { type SessionFaceReader } from "./session-incarnation.js";
17
19
  export interface ParkedAgentMatch {
18
20
  handle: string;
@@ -90,6 +92,36 @@ export declare function findParkOrigin(sources: ParkOriginSources, cp: {
90
92
  scope: string;
91
93
  sessionId: string;
92
94
  }): Promise<ParkOrigin | undefined>;
95
+ /** 起跑读者的源(就是 `ServiceDeps` 上那几只;任一缺席 ⇒ 这台部署没有这条车道,读者只交回调用方自己带的那一份)。 */
96
+ export interface HeldWorkflowParkDecisionSources {
97
+ readonly workflowParkDecisions?: WorkflowParkDecisionStore;
98
+ readonly checkpointStore?: {
99
+ get(token: CheckpointToken): Promise<{
100
+ readonly status: string;
101
+ readonly scope: string;
102
+ readonly sessionId: string;
103
+ } | null>;
104
+ };
105
+ readonly workflowAgentSessionIndex?: WorkflowAgentSessionIndex;
106
+ readonly workflowRunStore?: Pick<WorkflowRunStore, "get">;
107
+ }
108
+ /** `RunInternals.workflowParkedResume` 的一条(形直接取 core 的那一位)。 */
109
+ type ParkedResumeEntry = NonNullable<RunInternals["workflowParkedResume"]>[number];
110
+ /**
111
+ * 🔴 **决定进引擎的唯一读者** —— 每一只起跑器(durable run 腿、续跑腿流形与 verify 形、同步流腿、同步 JSON 腿)开跑之前调一次,
112
+ * 产物原样摊进那一跑的 `RunInternals`(部署方铸的 TRUSTED internals:不是 `TaskSpec` 字段、不是工具参数 —— 模型永远不能自己决定一次审批)。
113
+ *
114
+ * 产物 = 调用方自己带的那一份(`carried`:`/decide` 的投递跑带着它刚受理、行还没落的那条决定)∪ 这个会话的决定行(律与寿命的属主 =
115
+ * `orchestration/workflow-park-decision.ts` 文件头),同一张卡以 `carried` 为准(它是要取代行上旧决定的那一个)。行这一侧逐条:
116
+ * · 子代卡此刻**仍 pending** 才供:读回 `null` / 状态不是 `pending` ⇒ 不供(引擎对「记着停驻、卡却已不 pending」的序数,有条目 ⇒ 当确认
117
+ * 结算、没条目 ⇒ 拒续跑 —— 供一条过期条目会把后者改成前者);读卡抛 ⇒ 不供并计 `server.workflow-park-decision.card-unreadable`
118
+ * (这一读失败不代表引擎随后的那一读也失败;不供的方向是这一跑不带它、行留着给下一跑 —— 绝不把它变成一次确认);
119
+ * · 投递目标 = 这张卡**当下**的持有者 run(`findParkOrigin`,与 `/decide` 路由同一只判官):持有者判不出唯一一条(分叉 / 证不了 / 卡
120
+ * 已在新 token 下再停)⇒ 不供(引擎只把条目交给 `resumeFromRunId` 恰是持有者的续跑;没有唯一持有者就没有可交付的那一跑)。
121
+ * 决定店读抛(local 账本闸合上 / SQL 一行坏体)⇒ 与读卡失败同律:这一店当「没有可供的行」,只交回 `carried`,计 `server.workflow-park-decision.store-unreadable`
122
+ * (不跳过坏行照供其余:读不出的那一行可能正是取代了旧决定的那一笔;不拒起跑:不供是安全方向,卡仍 pending、可再决)。决定的写口照旧由店闸住。
123
+ */
124
+ export declare function heldWorkflowParkDecisions(sources: HeldWorkflowParkDecisionSources, hostSessionId: string, carried?: readonly ParkedResumeEntry[]): Promise<Pick<RunInternals, "workflowParkedResume">>;
93
125
  /**
94
126
  * pending checkpoint → parked bg 行匹配。
95
127
  *
@@ -173,11 +205,7 @@ export interface ParkedDecideRequest {
173
205
  reason?: string;
174
206
  /** D-1 decision-binding echo(操作员在 GET 看到的 boundCallId/boundInputHash 原样透传;server
175
207
  * 绝不重算,core resume 侧做 fail-closed 等值校验——与 legacy 腿同姿势)。 */
176
- binding?: {
177
- boundCallId?: string;
178
- boundInputHash?: string;
179
- updatedInput?: unknown;
180
- };
208
+ binding?: Omit<DecideBinding, "checkpointToken">;
181
209
  /** body 带了 `remember:"session"` 时路由传入的 grant 执行器([ref] 候裁② 的 server 侧修,经两轮
182
210
  * 行为探针实证):豁免必须锚在**行的 root/host 会话 id**——部署侧三个豁免探针(policy 层/fs-write
183
211
  * 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`sourceTaskId` 只在
@@ -216,8 +244,10 @@ export interface ParkedDecideResult {
216
244
  * · `hostDecision` = 结算**事实**逐字上 outcome;`gateOutcome` 一格 server **永不**填(core 对宿主
217
245
  * 自铸的结算词是 pre-CAS 响亮拒)。
218
246
  * · `answer` 原样透传([ref]:header 逐字匹配等语义校验全在 core,server 不预判)。
247
+ * · `feedback`(core 7.54.0):绑定里有就原样上 outcome —— 决定口只在人的放行上收它(拒决 / 策略的决定上带它是门口 400),本铸点不再按判词剪
248
+ * (剪 = 静默丢一段人写的话;门口已拒的形到不了这里,引擎在 claim 前再判一次);什么算写了字(空白读作没写)是引擎的读法,本铸点不 trim。
219
249
  */
220
- export declare function buildParkedResumeOutcome(req: ParkedDecideRequest): ResumeOutcome;
250
+ export declare function buildParkedResumeOutcome(req: ParkedDecideRequest): WorkflowParkOutcome;
221
251
  /**
222
252
  * S-185 车CM —— **第三条车道的计划**(纯函数;驱动本身归 resume 家族的那条腿,见下方「为什么不自建驱动」)。
223
253
  *
@@ -234,12 +264,13 @@ export declare function buildParkedResumeOutcome(req: ParkedDecideRequest): Resu
234
264
  * decided, the deployment resumes this run (resumeFromRunId: …)」。
235
265
  * ⇒ 第三条车道 = **把决定挂在宿主会话的下一跑上**,而那一跑必须走 resume 家族**既有**的那条腿
236
266
  * (`notify-wake.ts` 的成文纪律:wake 会烧模型,所以复用 `ctx.legs.resumeWake`,「而不是在本域自建第二条
237
- * 驱动路径」)。本函数因此只出**计划**:宿主会话 + 要注入的消息 + 要随 internals 走的那一条决定。
267
+ * 驱动路径」)。本函数因此只出**计划**:宿主会话 + 要注入的消息 + 要落成决定行的那一条决定(调用方受理时落行,宿主会话的每一跑
268
+ * 开跑前经那一只读者把它放进 internals)。
238
269
  *
239
270
  * ## 诚实边界(登记,不假装没有)
240
271
  * · **模型中介**:决定送达宿主之后,真正的赎回发生在宿主再调一次 `Workflow({resumeFromRunId})` 时。
241
- * core 的 park 回执逐字告诉模型这件事,但它不是一条确定性的机器腿。宿主没照做 ⇒ 卡仍 pending、
242
- * 人可再决(**不会**静默吃掉批准)。
272
+ * core 的 park 回执逐字告诉模型这件事,但它不是一条确定性的机器腿。宿主没照做 ⇒ 卡仍 pending、决定行还在:
273
+ * 宿主会话的下一跑(谁起的都算)照带它,同一个决定重投再触发一次投递(**不会**静默吃掉批准)。
243
274
  * · **`inheritedGate` 不供**:那是「跨进程重供 checkpoint 的父约束」的席位,而 wa* 行不带父约束链;
244
275
  * 同进程时 core 的内存 registry 自动重供,跨进程且该 cp 带 `requiresParentConstraint` 时 core 响亮拒
245
276
  * (`resume.parent_constraint_missing`)⇒ 该 ordinal 再 park 一次,不会 fail-open。
@@ -257,7 +288,7 @@ export type WorkflowParkedDecidePlan = {
257
288
  hostSessionId: string;
258
289
  runId: string;
259
290
  message: string;
260
- outcome: ResumeOutcome;
291
+ outcome: WorkflowParkOutcome;
261
292
  } | {
262
293
  ok: false;
263
294
  deny: ParkedDecideResult;
@@ -311,4 +342,5 @@ export declare function planWorkflowParkedDecide(origin: Extract<ParkOrigin, {
311
342
  * re-park 诚实可见,操作员可再决。
312
343
  */
313
344
  export declare function decideParkedAgent(deps: ParkedDecideDeps, req: ParkedDecideRequest, match: ParkedAgentMatch): Promise<ParkedDecideResult>;
345
+ export {};
314
346
  //# sourceMappingURL=parked-decide.d.ts.map
@@ -1,9 +1,11 @@
1
1
  import { readClosedWordSeat } from "./approval-card.js";
2
2
  import { routeWorkflowPark } from "./orchestration/workflow-agent-session-index.js";
3
+ import { recordFailOpen } from "./observability/fail-open.js";
3
4
  import { defaultSubagentTailBus } from "./fleet/subagent-tail-bus.js";
4
- import { backgroundScopesForCheckpointScope, decodeCheckpointScope } from "./security.js";
5
+ import { backgroundScopesForCheckpointScope, decodeCheckpointScope, ownerOfCheckpointScope } from "./security.js";
5
6
  import { ASK_USER_QUESTION_TOOL_NAME } from "./approval-content-kind.js";
6
7
  import { sameSessionOccupant } from "./session-incarnation.js";
8
+ import { refusalBody, resumeRefusalFacts } from "./http/refusal-body.js";
7
9
  export async function findParkOrigin(sources, cp) {
8
10
  if (sources.agentStore !== undefined) {
9
11
  let match;
@@ -51,6 +53,33 @@ export async function findParkOrigin(sources, cp) {
51
53
  return undefined;
52
54
  }
53
55
  }
56
+ export async function heldWorkflowParkDecisions(sources, hostSessionId, carried) {
57
+ const entries = [...(carried ?? [])];
58
+ const { workflowParkDecisions: decisions, checkpointStore: cs, workflowAgentSessionIndex: workflowIndex, workflowRunStore } = sources;
59
+ if (decisions !== undefined && cs !== undefined && workflowIndex !== undefined && workflowRunStore !== undefined) {
60
+ const own = new Set(entries.map((e) => String(e.token)));
61
+ const held = await decisions.listByHostSession(hostSessionId).then((rows) => ({ rows }), (err) => ({ err }));
62
+ if ("err" in held) {
63
+ recordFailOpen("server.workflow-park-decision.store-unreadable", `hostSessionId=${hostSessionId} err=${held.err instanceof Error ? held.err.message : String(held.err)}`);
64
+ return entries.length > 0 ? { workflowParkedResume: entries } : {};
65
+ }
66
+ for (const row of held.rows) {
67
+ if (own.has(String(row.token)))
68
+ continue;
69
+ const card = await cs.get(row.token).then((cp) => ({ cp }), (err) => ({ err }));
70
+ if ("err" in card) {
71
+ recordFailOpen("server.workflow-park-decision.card-unreadable", `runId=${row.runId} err=${card.err instanceof Error ? card.err.message : String(card.err)}`);
72
+ continue;
73
+ }
74
+ if (card.cp === null || card.cp.status !== "pending")
75
+ continue;
76
+ const origin = await findParkOrigin({ workflowIndex, workflowRunStore }, { token: row.token, scope: card.cp.scope, sessionId: card.cp.sessionId });
77
+ if (origin?.kind === "workflow")
78
+ entries.push({ runId: origin.runId, token: row.token, outcome: row.outcome });
79
+ }
80
+ }
81
+ return entries.length > 0 ? { workflowParkedResume: entries } : {};
82
+ }
54
83
  function quiet(warn, event, fields) {
55
84
  try {
56
85
  warn?.(event, fields);
@@ -96,6 +125,7 @@ export function buildParkedResumeOutcome(req) {
96
125
  boundInputHash: req.binding?.boundInputHash ?? persistedHash,
97
126
  decision: req.decision === "approve" ? "allow" : "deny",
98
127
  ...(req.decision === "approve" && req.binding?.updatedInput !== undefined ? { updatedInput: req.binding.updatedInput } : {}),
128
+ ...(req.binding?.feedback !== undefined ? { feedback: req.binding.feedback } : {}),
99
129
  ...(req.answer !== undefined ? { answer: req.answer } : {}),
100
130
  ...(req.reason !== undefined ? { reason: req.reason } : {}),
101
131
  hostDecision: req.hostDecision,
@@ -106,21 +136,25 @@ export function denyWorkflowParksUnreadable(origin) {
106
136
  case "older_engine":
107
137
  return {
108
138
  status: 409,
109
- body: {
110
- error: "this decision cannot be matched to the pending step it belongs to: the run's record was written by an earlier engine version, which did not record which run is waiting on each pending step — and that record is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resume the run itself instead — `Workflow({resumeFromRunId})` with the runId below — and once the resumed run is waiting on this step again it records itself as the one waiting, after which deciding here works normally. Only if the engine also refuses that resume is the run truly unrecoverable",
139
+ body: refusalBody({
111
140
  errorCode: "decide.workflow_parks_unreadable",
112
- runId: origin.runId,
113
- },
141
+ message: "this decision cannot be matched to the pending step it belongs to: the run's record was written by an earlier engine version, which did not record which run is waiting on each pending step — and that record is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resume the run itself instead — `Workflow({resumeFromRunId})` with the runId below — and once the resumed run is waiting on this step again it records itself as the one waiting, after which deciding here works normally. Only if the engine also refuses that resume is the run truly unrecoverable",
142
+ facts: {
143
+ runId: origin.runId,
144
+ },
145
+ }),
114
146
  };
115
147
  case "unreadable":
116
148
  return {
117
149
  status: 409,
118
- body: {
119
- error: "this decision cannot be matched to the pending step it belongs to: this run's record cannot be read (the list of pending steps the run owns is damaged: one of its entries is malformed, or it is not a list at all) — and that list is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resuming does not clear this: the damaged record keeps naming this step whatever runs after it, so the decision stays undeliverable until whoever operates this deployment repairs that record (the runId below); after that, deciding here works normally. When the response also carries readableHolderRunId, that run's record is readable and is the latest one waiting on this step — it is where the work can be carried on, but the damaged record above still keeps this decision from being delivered until that record is fixed",
150
+ body: refusalBody({
120
151
  errorCode: "decide.workflow_parks_unreadable",
121
- runId: origin.runId,
122
- ...(origin.readableHolderRunId !== undefined ? { readableHolderRunId: origin.readableHolderRunId } : {}),
123
- },
152
+ message: "this decision cannot be matched to the pending step it belongs to: this run's record cannot be read (the list of pending steps the run owns is damaged: one of its entries is malformed, or it is not a list at all) — and that list is the only proof that the approval you are deciding belongs to this run. The decision is therefore NOT delivered, rather than answered with a receipt nothing can redeem: the approval card stays pending and nothing is forged. Resuming does not clear this: the damaged record keeps naming this step whatever runs after it, so the decision stays undeliverable until whoever operates this deployment repairs that record (the runId below); after that, deciding here works normally. When the response also carries readableHolderRunId, that run's record is readable and is the latest one waiting on this step — it is where the work can be carried on, but the damaged record above still keeps this decision from being delivered until that record is fixed",
153
+ facts: {
154
+ runId: origin.runId,
155
+ ...(origin.readableHolderRunId !== undefined ? { readableHolderRunId: origin.readableHolderRunId } : {}),
156
+ },
157
+ }),
124
158
  };
125
159
  default: {
126
160
  const unhandled = origin.cause;
@@ -131,11 +165,13 @@ export function denyWorkflowParksUnreadable(origin) {
131
165
  export function denyWorkflowParkForked(origin) {
132
166
  return {
133
167
  status: 409,
134
- body: {
135
- error: "this decision cannot be delivered: the same run was resumed more than once and every resumed copy listed in runIds is waiting on this same step, so there is no single run to hand the decision to. Nothing was delivered and the approval card stays pending. Resume one of the runs listed in runIds; once that run is waiting on this step again, deciding here works normally",
168
+ body: refusalBody({
136
169
  errorCode: "decide.workflow_park_forked",
137
- runIds: [...origin.runIds],
138
- },
170
+ message: "this decision cannot be delivered: the same run was resumed more than once and every resumed copy listed in runIds is waiting on this same step, so there is no single run to hand the decision to. Nothing was delivered and the approval card stays pending. Resume one of the runs listed in runIds; once that run is waiting on this step again, deciding here works normally",
171
+ facts: {
172
+ runIds: [...origin.runIds],
173
+ },
174
+ }),
139
175
  };
140
176
  }
141
177
  export function planWorkflowParkedDecide(origin, req) {
@@ -144,11 +180,13 @@ export function planWorkflowParkedDecide(origin, req) {
144
180
  ok: false,
145
181
  deny: {
146
182
  status: 400,
147
- body: {
148
- error: "remember:\"session\" is not supported for this approval: accepting it here only means the decision was handed on for delivery, not that the engine has applied it — an exemption granted now could outlive a decision the engine later rejects. Re-issue the decide without `remember`; the decision itself is accepted normally that way.",
183
+ body: refusalBody({
149
184
  errorCode: "decide.workflow_remember_unsupported",
150
- runId: origin.runId,
151
- },
185
+ message: "remember:\"session\" is not supported for this approval: accepting it here only means the decision was handed on for delivery, not that the engine has applied it — an exemption granted now could outlive a decision the engine later rejects. Re-issue the decide without `remember`; the decision itself is accepted normally that way.",
186
+ facts: {
187
+ runId: origin.runId,
188
+ },
189
+ }),
152
190
  },
153
191
  };
154
192
  }
@@ -158,11 +196,13 @@ export function planWorkflowParkedDecide(origin, req) {
158
196
  ok: false,
159
197
  deny: {
160
198
  status: 409,
161
- body: {
162
- error: "this run was started on its own rather than from a session, so this deployment has nowhere to deliver the decision. Nothing was decided and the approval is still pending — resume the run yourself with the runId below and decide it there",
199
+ body: refusalBody({
163
200
  errorCode: "decide.workflow_host_unknown",
164
- runId: origin.runId,
165
- },
201
+ message: "this run was started on its own rather than from a session, so this deployment has nowhere to deliver the decision. Nothing was decided and the approval is still pending — resume the run yourself with the runId below and decide it there",
202
+ facts: {
203
+ runId: origin.runId,
204
+ },
205
+ }),
166
206
  },
167
207
  };
168
208
  }
@@ -181,29 +221,31 @@ export function planWorkflowParkedDecide(origin, req) {
181
221
  function sessionGone(taskId) {
182
222
  return {
183
223
  status: 409,
184
- body: {
185
- error: "the session this agent belongs to was deleted (or deleted and started again under the same id) while its approval waited, so the approval no longer applies — nothing was resumed",
224
+ body: refusalBody({
186
225
  errorCode: "decide.not_parked",
187
- taskId,
188
- },
226
+ message: "the session this agent belongs to was deleted (or deleted and started again under the same id) while its approval waited, so the approval no longer applies — nothing was resumed",
227
+ facts: {
228
+ taskId,
229
+ },
230
+ }),
189
231
  };
190
232
  }
191
233
  export async function decideParkedAgent(deps, req, match) {
192
234
  const row = match.row;
193
235
  const rememberRoot = req.grantRemember !== undefined ? grantRootOf(row) : undefined;
194
236
  if (req.grantRemember !== undefined && rememberRoot === undefined) {
195
- return { status: 400, body: { error: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", errorCode: "decide.parked_remember_unsupported", taskId: match.handle } };
237
+ return { status: 400, body: refusalBody({ errorCode: "decide.parked_remember_unsupported", message: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", facts: { taskId: match.handle } }) };
196
238
  }
197
239
  const pendingTool = req.pendingAction?.toolName;
198
240
  if (pendingTool === ASK_USER_QUESTION_TOOL_NAME && req.decision === "approve" && req.answer === undefined) {
199
- return { status: 400, body: { error: "pending action is AskUserQuestion — approve requires body.answer (the operator's answers[]); deny needs none", errorCode: "decide.parked_answer_required", taskId: match.handle } };
241
+ return { status: 400, body: refusalBody({ errorCode: "decide.parked_answer_required", message: "pending action is AskUserQuestion — approve requires body.answer (the operator's answers[]); deny needs none", facts: { taskId: match.handle } }) };
200
242
  }
201
243
  if (row.name === undefined) {
202
- return { status: 409, body: { error: "parked row carries no agent name — the revive path requires a named agent (row damaged?)", errorCode: "decide.row_unrevivable", taskId: match.handle } };
244
+ return { status: 409, body: refusalBody({ errorCode: "decide.row_unrevivable", message: "parked row carries no agent name — the revive path requires a named agent (row damaged?)", facts: { taskId: match.handle } }) };
203
245
  }
204
246
  const root = row.rootSessionId;
205
247
  if (root === undefined) {
206
- return { status: 409, body: { error: "this agent's row carries no root session anchor — the revive path cannot tell which session this approval belongs to (row damaged?)", errorCode: "decide.row_unrevivable", taskId: match.handle } };
248
+ return { status: 409, body: refusalBody({ errorCode: "decide.row_unrevivable", message: "this agent's row carries no root session anchor — the revive path cannot tell which session this approval belongs to (row damaged?)", facts: { taskId: match.handle } }) };
207
249
  }
208
250
  const faceBefore = await deps.sessionFaceOf(root);
209
251
  if (faceBefore === undefined)
@@ -214,14 +256,14 @@ export async function decideParkedAgent(deps, req, match) {
214
256
  if (!claim.ok) {
215
257
  switch (claim.reason) {
216
258
  case "store_unreachable":
217
- return { status: 503, body: { error: "the durable agent store is unreachable — retry", errorCode: "decide.store_unreachable", taskId: match.handle } };
259
+ return { status: 503, body: refusalBody({ errorCode: "decide.store_unreachable", message: "the durable agent store is unreachable — retry", facts: { taskId: match.handle } }) };
218
260
  case "claim_lost":
219
- return { status: 409, body: { error: "the parked agent is already claimed — either a concurrent decide won (re-check the pending list), or a stale claim is pending automatic cleanup (retry after the stale-claim window)", errorCode: "decide.claim_lost", taskId: match.handle } };
261
+ return { status: 409, body: refusalBody({ errorCode: "decide.claim_lost", message: "the parked agent is already claimed — either a concurrent decide won (re-check the pending list), or a stale claim is pending automatic cleanup (retry after the stale-claim window)", facts: { taskId: match.handle } }) };
220
262
  case "binding_broken":
221
263
  case "checkpoint_not_pending":
222
- return { status: 409, body: { error: "the approval gate moved under this decide (re-parked or already settled) — re-check the pending list", errorCode: "decide.gate_moved", taskId: match.handle } };
264
+ return { status: 409, body: refusalBody({ errorCode: "decide.gate_moved", message: "the approval gate moved under this decide (re-parked or already settled) — re-check the pending list", facts: { taskId: match.handle } }) };
223
265
  default:
224
- return { status: 409, body: { error: "the parked agent moved under this decide (stopped or already decided)", errorCode: "decide.not_parked", taskId: match.handle } };
266
+ return { status: 409, body: refusalBody({ errorCode: "decide.not_parked", message: "the parked agent moved under this decide (stopped or already decided)", facts: { taskId: match.handle } }) };
225
267
  }
226
268
  }
227
269
  const ticket = claim.ticket;
@@ -281,7 +323,7 @@ export async function decideParkedAgent(deps, req, match) {
281
323
  toolCallId: `drv-${ticket.claimId}`,
282
324
  ...(surface.mountsCallerTool !== undefined ? { mountsCallerTool: surface.mountsCallerTool } : {}),
283
325
  ...(deps.approverSeatFor !== undefined && seatRoot !== undefined
284
- ? { onAsk: deps.approverSeatFor({ owner: decodeCheckpointScope(req.scope) ?? null, taskId: match.handle, sessionId: seatRoot }) }
326
+ ? { onAsk: deps.approverSeatFor({ owner: ownerOfCheckpointScope(req.scope), taskId: match.handle, sessionId: seatRoot }) }
285
327
  : {}),
286
328
  reviveClaim: {
287
329
  row: { ...ticket.row, parkClaimId: ticket.claimId },
@@ -302,12 +344,14 @@ export async function decideParkedAgent(deps, req, match) {
302
344
  const disp = await rollback("execute_threw");
303
345
  return {
304
346
  status: 500,
305
- body: {
306
- error: `revive failed before the resume was driven: ${e instanceof Error ? e.message : String(e)}`,
347
+ body: refusalBody({
307
348
  errorCode: "decide.revive_failed",
308
- taskId: match.handle,
309
- rollback: disp,
310
- },
349
+ message: `revive failed before the resume was driven: ${e instanceof Error ? e.message : String(e)}`,
350
+ facts: {
351
+ taskId: match.handle,
352
+ rollback: disp,
353
+ },
354
+ }),
311
355
  };
312
356
  }
313
357
  const isErr = typeof receipt === "object" && receipt !== null && receipt.isError === true;
@@ -319,23 +363,28 @@ export async function decideParkedAgent(deps, req, match) {
319
363
  const cause = readClosedWordSeat(receiptDetails, "cause");
320
364
  return {
321
365
  status: 422,
322
- body: {
323
- error: typeof content === "string" ? content : "the parked resume failed during startup",
366
+ body: refusalBody({
324
367
  errorCode: "parked_resume.startup_failed",
325
- taskId: match.handle,
326
- rollback: disp,
327
- ...(cause !== undefined ? { cause } : {}),
328
- },
368
+ message: typeof content === "string" ? content : "the parked resume failed during startup",
369
+ facts: {
370
+ taskId: match.handle,
371
+ rollback: disp,
372
+ ...(cause !== undefined ? { cause } : {}),
373
+ ...resumeRefusalFacts(receiptDetails.detail),
374
+ },
375
+ }),
329
376
  };
330
377
  }
331
378
  return {
332
379
  status: 409,
333
- body: {
334
- error: typeof content === "string" ? content : "revive was rejected by the delegation tool",
380
+ body: refusalBody({
335
381
  errorCode: "decide.revive_rejected",
336
- taskId: match.handle,
337
- rollback: disp,
338
- },
382
+ message: typeof content === "string" ? content : "revive was rejected by the delegation tool",
383
+ facts: {
384
+ taskId: match.handle,
385
+ rollback: disp,
386
+ },
387
+ }),
339
388
  };
340
389
  }
341
390
  return { status: 200, body: { taskId: match.handle, status: "resuming", decision: req.decision } };
@@ -19,15 +19,22 @@
19
19
  * 这里的第 ② 条是同一条事实在交座这一处的判据(规则只写在这里,腿只负责读两次)。根删除时把子孙的 parked 卡一并作废 = S-790 件 B
20
20
  * (`boot/session-faces.ts` 的删除协调器)。
21
21
  * · 只对**一层**行填座(`rootSessionId` 在场且 = `parentSessionId`:派它的 run 就是根会话的 run,列表正是那个 run 的挂载)。更深的行
22
- * (孙代:派它的是一个子代,它的挂载是继承裁剪后的子集,行上读不出来)不填 —— 用 boot 期那只裸 Agent、无座 = core 的 fail-closed 臂;
22
+ * (孙代:派它的是一个子代,它的挂载是继承裁剪后的子集,行上读不出来)不填 —— 无座 = core 的 fail-closed 臂;
23
23
  * 行上带继承组成是 core #1112(7.32.x)的半场,到货再改读行。
24
24
  * 近似如实记:重解的列表是**部署缺省**那一份,读不回那一 run 的逐请求差异(`settings.webSearch` 后端、center overlay 场景)——
25
25
  * 座只判 bundle 实例的成员性,继承面是 `[...web, ...scaffolds]`,那两项差异不改变谁在面内。
26
+ *
27
+ * **属主来源(S-1770 / S-1808)与交座是两个独立判据**:赎回工具的停驻挂点(复活的子代再要审批时停驻,`plugins/session-store.ts`)按委派继承律定宿主行属主,
28
+ * 律要的是**委派树根的见证**:根 id(行上本来就带 `rootSessionId`)+ 判断那一刻读到的根行住客(赎回腿 claim 前后两读的那一位 —— 两读不是同一位时赎回腿整条拒,
29
+ * 走不到这里;读数缺席 ⇒ 见证不带住客,挂点那一刻根行在 ⇒ 停驻否决)。所以**每一行**都交出它({@link ScenarioContext} 的 `delegationRoot`):交座的一层行以
30
+ * `{ sessionId: root, delegationRoot }` 重解,不交座的行(更深的行、根住客已变的一层行、读数缺席)以 `{ delegationRoot }` 重解 —— 只喂停驻挂点,不挂任何会话级设施、
31
+ * 不带 principal,交座判据(上面三条)一个字不动。行上没有根 ⇒ boot 期那只裸 Agent(没有根可交 ⇒ 律给哨兵)。挂点那一刻根行已不在 ⇒ 律给哨兵;在而不是见证的那一位
32
+ * (批准之后删了、同 id 被重新登记)⇒ 停驻否决 —— 两件都在挂点那一侧判,与这里无关。
26
33
  */
27
34
  import { type BackgroundAgentRecord, type ToolSpec } from "@sema-agent/core";
28
35
  import type { Scenario } from "./capabilities/scenarios.js";
29
36
  import { type SessionFace } from "./session-incarnation.js";
30
- /** 一次赎回用的面:驱动的 Agent 工具 + (一层行时)与它同出一张列表的继承座。 */
37
+ /** 一次赎回用的面:驱动的 Agent 工具(它的停驻挂点绑着行上的根)+ (交座时)与它同出一张列表的继承座。 */
31
38
  export interface ParkedReviveSurface {
32
39
  readonly reviveTool: ToolSpec;
33
40
  /** 缺席 = 不交座(core fail-closed:复活的子代不继承任何场景层工具)。 */
@@ -7,18 +7,21 @@ export function createParkedReviveSurface(defaultScenario) {
7
7
  return undefined;
8
8
  return (row, identity) => {
9
9
  const root = row.rootSessionId;
10
- if (root === undefined || row.parentSessionId !== root)
10
+ if (root === undefined)
11
11
  return { reviveTool: bootTool };
12
- const face = identity.root;
13
- if (face === undefined || !sameSessionOccupant(face.before, face.after))
14
- return { reviveTool: bootTool };
15
- if ((face.before.owner ?? undefined) !== identity.principal || (face.after.owner ?? undefined) !== identity.principal)
16
- return { reviveTool: bootTool };
17
- const tools = defaultScenario({}, identity.principal, { sessionId: root }).tools;
12
+ const seated = holdsSeat(row.parentSessionId === root, identity);
13
+ const delegationRoot = { sessionId: root, incarnation: identity.root?.after.incarnation ?? null };
14
+ const tools = (seated ? defaultScenario({}, identity.principal, { sessionId: root, delegationRoot }) : defaultScenario({}, undefined, { delegationRoot })).tools;
18
15
  const reviveTool = agentOf(tools);
19
16
  if (reviveTool === undefined)
20
17
  return { reviveTool: bootTool };
21
- return { reviveTool, mountsCallerTool: (t) => tools.includes(t) };
18
+ return seated ? { reviveTool, mountsCallerTool: (t) => tools.includes(t) } : { reviveTool };
22
19
  };
23
20
  }
21
+ function holdsSeat(oneLevel, identity) {
22
+ const face = identity.root;
23
+ if (!oneLevel || face === undefined || !sameSessionOccupant(face.before, face.after))
24
+ return false;
25
+ return (face.before.owner ?? undefined) === identity.principal && (face.after.owner ?? undefined) === identity.principal;
26
+ }
24
27
  //# sourceMappingURL=parked-revive-surface.js.map
@@ -6,7 +6,7 @@
6
6
  * `TaskSpec.allowedTools`(`task-settings.ts` 的 `applyTaskSettings`),运维的 `APPROVAL_GRANT` 投 `RunnerDeps.allowedTools`
7
7
  * (`boot/runner-deps.ts` 的部署姿态座席族)。本口的 `behavior` 型直接是 core 的 `PermissionRule["behavior"]`(不手抄:core 收窄,这里跟着收窄)。
8
8
  *
9
- * 为什么住在一只叶模块里(不留在 `task-settings.ts`):本模块只 import core 与 `text-bidi.ts`(纯叶),读者引它不成环。
9
+ * 为什么住在一只叶模块里(不留在 `task-settings.ts`):本模块只 import core 与契约包 settings-schema(纯叶),读者引它不成环。
10
10
  */
11
11
  import { type PathRuleBases, type PermissionRule, type ToolPolicy } from "@sema-agent/core";
12
12
  /** 一张表里规则条数的上限 —— 请求腿 wire 门(`task-settings.ts` 的 deny / ask 两桶判形)读的也是这一个名字:core 的缺省帽是 256,
@@ -1,5 +1,5 @@
1
1
  import { createPermissionRulePolicy } from "@sema-agent/core";
2
- import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
2
+ import { stripControlAndBidi } from "@sema-agent/settings-schema";
3
3
  export const MAX_PERMISSION_RULES_PER_LIST = 1_000;
4
4
  export function createRuleListPolicy(names, behavior, source, pathBases) {
5
5
  try {
@@ -10,7 +10,7 @@ export function createRuleListPolicy(names, behavior, source, pathBases) {
10
10
  });
11
11
  }
12
12
  catch (e) {
13
- const coreMsg = (e instanceof Error ? e.message : String(e)).replace(CONTROL_AND_BIDI_STRIP_RE, "");
13
+ const coreMsg = stripControlAndBidi(e instanceof Error ? e.message : String(e));
14
14
  throw new Error(`${source.replace("settings.", "")} has rule(s) core cannot compile — ${coreMsg}`, { cause: e });
15
15
  }
16
16
  }
@@ -1,4 +1,4 @@
1
- import type { RuleApprovalRecord, RuleBehavior } from "@sema-agent/core";
1
+ import type { RuleBehavior } from "@sema-agent/core";
2
2
  /**
3
3
  * `PersistedRuleTool` **不再是闭词表**(core 7.9.0 / [ref]):工具名自 core 的**目录**派生
4
4
  * (`pathTarget` 声明 ⇒ 路径文法;`Bash` ⇒ 命令文法),型是 `string`。于是本文件对它的处置从
@@ -9,15 +9,6 @@ import type { RuleApprovalRecord, RuleBehavior } from "@sema-agent/core";
9
9
  * (既非命令文法也非路径文法 ⇒ 这条行永远匹配不上任何调用),两只店与票口一律拒。
10
10
  */
11
11
  export declare function isPersistedRuleTool(name: string): boolean;
12
- /**
13
- * `PersistedRuleMatch` 七员(core 顶注逐字):`exact` / `prefix`(历史 colon-star,永久兼容读、复合前缀形的
14
- * 唯一拼写)/ `wildcard`([ref] 尾 space-star,单命令体上与 prefix **同一谓词**,建议面自此铸它)/
15
- * `subpath`(Read 目录形,永不容纳任何命令)/ `path`(core 7.9.0 [ref]:路径族 deny/ask/allow 的模式文法
16
- * —— `//abs`、`~/`、`/root-relative`、cwd 相对,段内 `*`、跨段 `**`)/ `name` / `name_prefix`(core 7.43.0 #1318:`Skill` 的名字文法 ——
17
- * `Skill(<名>)` 精确、`Skill(<前缀>:*)` 名字前缀、无词界;技能卡的建议行 `match: "name"`)/ `host` / `subdomain`(core 7.49.0 #1365:
18
- * `WebFetch(domain:<host>)` 精确主机、`WebFetch(domain:*.<域>)` 域下每个主机 —— 只有 allow 形)。
19
- */
20
- export declare const PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildcard", "subpath", "path", "name", "name_prefix", "host", "subdomain"];
21
12
  /**
22
13
  * S-511 —— `RuleBehavior` 每一员在**无同意仪式的直接写口**(`POST /v1/rules`)上的逐员表态。
23
14
  *
@@ -44,19 +35,6 @@ export type DirectWritableRuleBehavior = {
44
35
  }[RuleBehavior];
45
36
  /** 判别式谓词(收窄到 {@link DirectWritableRuleBehavior}):端点判过之后,`allow` 在**类型上**到不了写家。 */
46
37
  export declare function isDirectWritableRuleBehavior(behavior: RuleBehavior): behavior is DirectWritableRuleBehavior;
47
- /** [ref] §2.3 B3:batch offer 成员的判别位(`command` = 历史逐段 Bash 规则;`directoryRead` = cd 段铸的目录只读授权)。 */
48
- export declare const RULE_OFFER_BATCH_MEMBER_KINDS: readonly ["command", "directoryRead"];
49
- /** [ref] §3.5:一段「为什么仍未被覆盖」的闭三词集(`redirection` 永久逐次 / `no_rule_form` 无可覆盖形 / `cap_overflow` 去重+帽挤出)。 */
50
- export declare const UNCOVERED_SEGMENT_REASONS: readonly ["redirection", "no_rule_form", "cap_overflow"];
51
- /** [ref] §3.3-5:卡编辑面的 breadth 警告码(记录 `edited.warnings` 存的就是这两个字面)。 */
52
- export declare const EDITED_RULE_BREADTH_WARNING_CODES: readonly ["broad_prefix", "compound_prefix"];
53
- /**
54
- * [ref] §4.5 / [ref] §3.5 —— 审批记录的**形版本号**(core `RuleApprovalRecord.schema`,本批 3→4;[ref] 三态 behavior 进候选行)。
55
- * 类型绑 core 的字面型:core 再升号 ⇒ 这里编译红,两只 durable 店(SQL 双方言 + File)的 stale 判别与写侧钉
56
- * 同批随之;判别是**等式**(`!==`)不是下限 —— 旧号的行按 stale 信封交还(不迁移、不 widen、不丢行),
57
- * pending 卡短命,重触发即取新卡(B7/B8 既诺)。
58
- */
59
- export declare const RULE_APPROVAL_RECORD_SCHEMA: RuleApprovalRecord["schema"];
60
38
  /**
61
39
  * 一次撤销之后「这条规则还活着吗」的**三词闭集**(core 7.25.0 [ref]:`RemovalLiveness`)。
62
40
  * `"yes"` = 店说它还在(add-wins:撤销期间又落了一次新批准);`"no"` = 店说它不在了;
@@ -2,9 +2,6 @@ import { ruleToolGrammarOf } from "@sema-agent/core";
2
2
  export function isPersistedRuleTool(name) {
3
3
  return ruleToolGrammarOf(name) !== undefined;
4
4
  }
5
- export const PERSISTED_RULE_MATCHES = ["exact", "prefix", "wildcard", "subpath", "path", "name", "name_prefix", "host", "subdomain"];
6
- const MATCHES_PIN = true;
7
- void MATCHES_PIN;
8
5
  export const DIRECT_RULE_WRITE_ADMITS = {
9
6
  allow: false,
10
7
  deny: true,
@@ -13,14 +10,4 @@ export const DIRECT_RULE_WRITE_ADMITS = {
13
10
  export function isDirectWritableRuleBehavior(behavior) {
14
11
  return DIRECT_RULE_WRITE_ADMITS[behavior];
15
12
  }
16
- export const RULE_OFFER_BATCH_MEMBER_KINDS = ["command", "directoryRead"];
17
- const MEMBER_KINDS_PIN = true;
18
- void MEMBER_KINDS_PIN;
19
- export const UNCOVERED_SEGMENT_REASONS = ["redirection", "no_rule_form", "cap_overflow"];
20
- const REASONS_PIN = true;
21
- void REASONS_PIN;
22
- export const EDITED_RULE_BREADTH_WARNING_CODES = ["broad_prefix", "compound_prefix"];
23
- const WARNING_CODES_PIN = true;
24
- void WARNING_CODES_PIN;
25
- export const RULE_APPROVAL_RECORD_SCHEMA = 4;
26
13
  //# sourceMappingURL=permission-rule-vocab.js.map
@@ -22,7 +22,7 @@ export declare const ASK_JOURNAL_COMPACT_GROWTH = 2;
22
22
  * 账本的**动词闭集**([ref] 形)。运行期的词表判定与编译期的穷尽 `switch` 读同一份:
23
23
  * 往这里加一个词,{@link FileApprovalAskStore.replayOp} 的 switch 立刻编译红(漏一口不可能发布)。
24
24
  */
25
- declare const JOURNAL_OPS: readonly ["ensureAsk", "transitionAsk", "decideAsk", "claimTerminal", "claimTerminalRefuse", "expireAsk", "bindBatch", "abortBatch", "deferReconcile", "resolveProvisional", "deleteByTask"];
25
+ declare const JOURNAL_OPS: readonly ["ensureAsk", "transitionAsk", "decideAsk", "claimTerminal", "claimTerminalRefuse", "expireAsk", "bindBatch", "abortBatch", "deferReconcile", "resolveProvisional", "deleteByTask", "reapSettledAsks", "reapEmptyBatches"];
26
26
  type JournalOpWord = (typeof JOURNAL_OPS)[number];
27
27
  /** 运行期词表(上面的数组)与类型面动词维({@link JournalCall})的**双向**对表 —— 任一边加词而另一边
28
28
  * 没跟上,这个别名解析成 `never`,{@link JOURNAL_OP_TABLE_GATE} 的赋值当场编译红。 */
@@ -96,6 +96,17 @@ type JournalCall = {
96
96
  } | {
97
97
  op: "deleteByTask";
98
98
  taskId: string;
99
+ }
100
+ /** 留存律的问账两半(挂靠集落成数组;Set 不是 JSON)。更老的读者不认这两个动词 ⇒ 拒启并点名出路(与 `claimTerminalRefuse` 同一条降级纪律)。 */
101
+ | {
102
+ op: "reapSettledAsks";
103
+ cutoffMs: number;
104
+ limit: number;
105
+ keepAnchors: string[];
106
+ } | {
107
+ op: "reapEmptyBatches";
108
+ cutoffMs: number;
109
+ limit: number;
99
110
  };
100
111
  export declare class FileApprovalAskStore implements ApprovalAskStore {
101
112
  /** 语义内核(转移判定的唯一真源)。本类对它只做两件事:重放、代理。 */
@@ -171,6 +182,10 @@ export declare class FileApprovalAskStore implements ApprovalAskStore {
171
182
  deferReconcile(askId: string, expectedState: AskState, expectedRev: number, nowMs: number): Promise<boolean>;
172
183
  resolveProvisional(askId: string, from: AskState, to: AskState, patch: AskTransitionPatch): Promise<boolean>;
173
184
  deleteByTask(taskId: string): Promise<void>;
185
+ /** 留存律的问行半场(谓词在内核,见接口注)。空的一次(内核的纯读选择为空)不落账本、不碰内存;否则照常「先落账、再翻内存」。 */
186
+ reapSettledAsks(cutoffMs: number, limit: number, keepAnchors: ReadonlySet<string>): Promise<number>;
187
+ /** 留存律的批行半场(同上)。 */
188
+ reapEmptyBatches(cutoffMs: number, limit: number): Promise<number>;
174
189
  listByState(state: AskState, limit: number): Promise<AskRow[]>;
175
190
  listPendingByTask(taskId: string, signal?: AbortSignal): Promise<AskRow[]>;
176
191
  listPendingBySession(sessionId: string, owner: string | null, signal?: AbortSignal): Promise<AskRow[]>;