@sema-agent/server 7.132.0 → 7.133.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 (402) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +174 -55
  5. package/deploy/sema-up/README.md +19 -1
  6. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
  7. package/deploy/sema-up/chart/templates/server.yaml +5 -2
  8. package/deploy/sema-up/stack/compose.yaml +3 -0
  9. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  10. package/dist/adoption/plan.d.ts +3 -2
  11. package/dist/adoption/plan.js +7 -5
  12. package/dist/adoption/runner.js +3 -10
  13. package/dist/adoption/sql.d.ts +3 -2
  14. package/dist/adoption/sql.js +3 -5
  15. package/dist/adoption/wire.d.ts +4 -1
  16. package/dist/adoption/wire.js +1 -0
  17. package/dist/approval-ask-audit-store.d.ts +31 -13
  18. package/dist/approval-ask-audit-store.js +272 -74
  19. package/dist/approval-ask-machine.d.ts +15 -0
  20. package/dist/approval-ask-machine.js +6 -0
  21. package/dist/approval-ask-retention.d.ts +136 -0
  22. package/dist/approval-ask-retention.js +102 -0
  23. package/dist/approval-card.d.ts +79 -19
  24. package/dist/approval-card.js +44 -13
  25. package/dist/approval-deny-reasons.d.ts +1 -1
  26. package/dist/approval.d.ts +9 -0
  27. package/dist/approval.js +24 -3
  28. package/dist/audit.d.ts +27 -10
  29. package/dist/audit.js +12 -16
  30. package/dist/bake-runner/main.js +3 -2
  31. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  32. package/dist/boot/execution-env.js +9 -7
  33. package/dist/boot/execution-lane.js +11 -0
  34. package/dist/boot/leader.js +2 -0
  35. package/dist/boot/memory-boundary.js +2 -2
  36. package/dist/boot/memory-consolidation.d.ts +5 -4
  37. package/dist/boot/memory-consolidation.js +7 -6
  38. package/dist/boot/org-delivery.d.ts +28 -0
  39. package/dist/boot/org-delivery.js +20 -0
  40. package/dist/boot/reapers.d.ts +3 -0
  41. package/dist/boot/reapers.js +21 -1
  42. package/dist/boot/resolve-spec.d.ts +3 -0
  43. package/dist/boot/resolve-spec.js +60 -81
  44. package/dist/boot/runner-deps.js +1 -0
  45. package/dist/boot/session-faces.d.ts +1 -0
  46. package/dist/boot/session-faces.js +4 -2
  47. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  48. package/dist/boot/stage-06-runners.d.ts +2 -0
  49. package/dist/boot/stage-06-runners.js +6 -3
  50. package/dist/boot/stage-07-capability-layer.d.ts +2 -0
  51. package/dist/boot/stage-07-capability-layer.js +24 -3
  52. package/dist/boot/stage-08-reapers.d.ts +2 -0
  53. package/dist/boot/stage-08-reapers.js +2 -2
  54. package/dist/boot/stage-09-leader.d.ts +3 -0
  55. package/dist/boot/stage-10-http-server.d.ts +3 -0
  56. package/dist/boot/stage-10-http-server.js +5 -6
  57. package/dist/boot/stores.js +2 -2
  58. package/dist/boot/web-admin.d.ts +4 -0
  59. package/dist/boot/web-admin.js +151 -63
  60. package/dist/boot/workflow-orchestration.d.ts +2 -0
  61. package/dist/boot/workflow-orchestration.js +2 -1
  62. package/dist/brain.js +8 -3
  63. package/dist/breaker-key.d.ts +6 -0
  64. package/dist/breaker-key.js +29 -0
  65. package/dist/caller-text-echo.d.ts +9 -6
  66. package/dist/caller-text-echo.js +8 -11
  67. package/dist/capabilities/center-plugins.d.ts +7 -0
  68. package/dist/capabilities/center-plugins.js +1 -1
  69. package/dist/capabilities/composite-members.d.ts +1 -1
  70. package/dist/capabilities/composite-members.js +1 -1
  71. package/dist/capabilities/execution-lane.js +2 -2
  72. package/dist/capabilities/hands-lane.d.ts +21 -0
  73. package/dist/capabilities/hands-lane.js +10 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -4
  75. package/dist/capabilities/mcp-probe.js +27 -4
  76. package/dist/capabilities/scenarios.d.ts +63 -7
  77. package/dist/capabilities/scenarios.js +39 -7
  78. package/dist/capability-facts.d.ts +34 -4
  79. package/dist/capability-facts.js +28 -2
  80. package/dist/center-config-tier.d.ts +69 -0
  81. package/dist/center-config-tier.js +42 -0
  82. package/dist/checkpoint-identity.d.ts +16 -0
  83. package/dist/checkpoint-identity.js +19 -0
  84. package/dist/config-catalog.d.ts +17 -10
  85. package/dist/config-catalog.js +43 -28
  86. package/dist/config-d-migration.d.ts +3 -1
  87. package/dist/config-d-migration.js +2 -2
  88. package/dist/config-dir-trust.d.ts +114 -0
  89. package/dist/config-dir-trust.js +388 -0
  90. package/dist/config-invariants.d.ts +18 -5
  91. package/dist/config-invariants.js +35 -3
  92. package/dist/config-provider.d.ts +6 -1
  93. package/dist/config-provider.js +6 -2
  94. package/dist/config-types.d.ts +71 -14
  95. package/dist/config-types.js +8 -0
  96. package/dist/config.d.ts +13 -0
  97. package/dist/config.js +121 -59
  98. package/dist/delegated-session-owner.d.ts +185 -0
  99. package/dist/delegated-session-owner.js +119 -0
  100. package/dist/device-protocol.d.ts +5 -3
  101. package/dist/device-protocol.js +1 -1
  102. package/dist/device-ws-hub.js +21 -2
  103. package/dist/device-ws-protocol.d.ts +70 -6
  104. package/dist/device-ws-protocol.js +50 -23
  105. package/dist/elicitation.js +3 -2
  106. package/dist/entry-problems.d.ts +34 -0
  107. package/dist/entry-problems.js +14 -0
  108. package/dist/execution-lane-caps.d.ts +49 -10
  109. package/dist/execution-lane-caps.js +43 -4
  110. package/dist/field-conflict.d.ts +43 -0
  111. package/dist/field-conflict.js +20 -0
  112. package/dist/fleet/fleet-bus.d.ts +80 -6
  113. package/dist/fleet/fleet-bus.js +41 -9
  114. package/dist/hooks/classic-stations.d.ts +10 -5
  115. package/dist/hooks/classic-stations.js +4 -4
  116. package/dist/hooks/command-spawn.d.ts +57 -0
  117. package/dist/hooks/command-spawn.js +139 -0
  118. package/dist/hooks/hook-llm.js +2 -2
  119. package/dist/hooks/hook-runner.d.ts +127 -25
  120. package/dist/hooks/hook-runner.js +668 -287
  121. package/dist/hooks/hook-source.d.ts +44 -0
  122. package/dist/hooks/hook-source.js +40 -0
  123. package/dist/http/active-run-conflict.d.ts +5 -13
  124. package/dist/http/active-run-conflict.js +17 -27
  125. package/dist/http/admission.js +103 -60
  126. package/dist/http/approval-sweeps.js +55 -18
  127. package/dist/http/caller-trust.d.ts +77 -0
  128. package/dist/http/caller-trust.js +143 -0
  129. package/dist/http/checkpoint-ctx.d.ts +16 -16
  130. package/dist/http/checkpoint-ctx.js +13 -10
  131. package/dist/http/claimed-run.d.ts +4 -3
  132. package/dist/http/device-placement.d.ts +2 -4
  133. package/dist/http/device-placement.js +2 -1
  134. package/dist/http/dispatch.js +10 -4
  135. package/dist/http/durable-run-leg.d.ts +4 -32
  136. package/dist/http/durable-run-leg.js +34 -10
  137. package/dist/http/owner-access.d.ts +56 -0
  138. package/dist/http/owner-access.js +42 -0
  139. package/dist/http/principal-gate.d.ts +48 -23
  140. package/dist/http/principal-gate.js +39 -12
  141. package/dist/http/readiness.d.ts +11 -5
  142. package/dist/http/readiness.js +10 -3
  143. package/dist/http/request-guards.d.ts +16 -23
  144. package/dist/http/request-guards.js +30 -15
  145. package/dist/http/resume-ctx-read.d.ts +2 -5
  146. package/dist/http/resume-ctx-read.js +7 -4
  147. package/dist/http/resume-legs.d.ts +3 -4
  148. package/dist/http/resume-legs.js +126 -69
  149. package/dist/http/retired-service-deps.d.ts +43 -0
  150. package/dist/http/retired-service-deps.js +18 -0
  151. package/dist/http/route-ctx.d.ts +44 -28
  152. package/dist/http/route-ctx.js +4 -0
  153. package/dist/http/route-table.js +2 -0
  154. package/dist/http/routes/a2a-serve.js +3 -4
  155. package/dist/http/routes/admin-config-refresh.js +1 -1
  156. package/dist/http/routes/admin-drain.js +1 -1
  157. package/dist/http/routes/admin-memory-optout.js +5 -1
  158. package/dist/http/routes/adoption.js +2 -9
  159. package/dist/http/routes/approvals-assistant.js +49 -48
  160. package/dist/http/routes/background.js +3 -2
  161. package/dist/http/routes/capabilities.js +20 -4
  162. package/dist/http/routes/config-catalog.d.ts +3 -3
  163. package/dist/http/routes/config-catalog.js +1 -1
  164. package/dist/http/routes/devices.js +3 -17
  165. package/dist/http/routes/diagnostics.js +5 -1
  166. package/dist/http/routes/images.js +6 -7
  167. package/dist/http/routes/leader.js +1 -8
  168. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  169. package/dist/http/routes/mcp-reconnect.js +3 -2
  170. package/dist/http/routes/memory-bundle.js +1 -1
  171. package/dist/http/routes/memory-compliance.js +1 -1
  172. package/dist/http/routes/memory-consolidation.js +1 -1
  173. package/dist/http/routes/memory-origin.js +1 -1
  174. package/dist/http/routes/memory-policy.d.ts +1 -1
  175. package/dist/http/routes/memory-policy.js +3 -2
  176. package/dist/http/routes/notify-wake.js +8 -21
  177. package/dist/http/routes/observability.js +2 -2
  178. package/dist/http/routes/principal-inbox.d.ts +39 -0
  179. package/dist/http/routes/principal-inbox.js +76 -0
  180. package/dist/http/routes/retention-ops.js +2 -9
  181. package/dist/http/routes/rules.js +5 -18
  182. package/dist/http/routes/runs.d.ts +5 -0
  183. package/dist/http/routes/runs.js +33 -106
  184. package/dist/http/routes/session-sync.js +15 -28
  185. package/dist/http/routes/sessions.js +30 -40
  186. package/dist/http/routes/side-query.js +6 -4
  187. package/dist/http/routes/tasks.js +50 -14
  188. package/dist/http/routes/workflows.d.ts +351 -0
  189. package/dist/http/routes/workflows.js +153 -119
  190. package/dist/http/send.d.ts +24 -3
  191. package/dist/http/send.js +14 -2
  192. package/dist/http/server.d.ts +17 -18
  193. package/dist/http/server.js +15 -13
  194. package/dist/http/stored-body-replay.js +17 -4
  195. package/dist/http/submit-ctx.js +4 -3
  196. package/dist/http/submit-replay.d.ts +4 -3
  197. package/dist/http/submit-replay.js +5 -4
  198. package/dist/http/wire-types.d.ts +10 -7
  199. package/dist/index.d.ts +1 -1
  200. package/dist/index.js +0 -1
  201. package/dist/lane-home-probe.d.ts +78 -9
  202. package/dist/lane-home-probe.js +78 -12
  203. package/dist/leader/endpoint.d.ts +4 -1
  204. package/dist/leader/endpoint.js +11 -10
  205. package/dist/limit-refusal.d.ts +17 -5
  206. package/dist/limit-refusal.js +4 -1
  207. package/dist/mcp-assertion-header.d.ts +31 -10
  208. package/dist/mcp-assertion-header.js +10 -3
  209. package/dist/mcp-tool-faces.js +1 -3
  210. package/dist/memory-project-layer.d.ts +37 -0
  211. package/dist/memory-project-layer.js +46 -0
  212. package/dist/memory-scope.d.ts +23 -16
  213. package/dist/memory-scope.js +24 -8
  214. package/dist/memory-sync-client.d.ts +27 -13
  215. package/dist/memory-sync-client.js +107 -18
  216. package/dist/model-entry-refusal.d.ts +9 -1
  217. package/dist/model-entry-refusal.js +6 -1
  218. package/dist/model-plane-face.d.ts +51 -0
  219. package/dist/model-plane-face.js +24 -0
  220. package/dist/model-provider.d.ts +5 -0
  221. package/dist/model-provider.js +4 -2
  222. package/dist/model-route-endpoint.d.ts +8 -11
  223. package/dist/model-route-endpoint.js +4 -7
  224. package/dist/model-route-env.d.ts +22 -0
  225. package/dist/model-route-env.js +2 -0
  226. package/dist/model-route-gap.d.ts +60 -30
  227. package/dist/model-route-gap.js +21 -15
  228. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  229. package/dist/observability/corrupt-read-seat.js +9 -0
  230. package/dist/observability/err-text.d.ts +6 -0
  231. package/dist/observability/err-text.js +18 -4
  232. package/dist/observability/fail-open.d.ts +35 -9
  233. package/dist/observability/fail-open.js +35 -9
  234. package/dist/observability/metrics.js +1 -0
  235. package/dist/observability/prompt-manifest.d.ts +3 -17
  236. package/dist/observability/prompt-manifest.js +45 -42
  237. package/dist/observability/tool-trace.js +9 -9
  238. package/dist/operator-ask.d.ts +10 -0
  239. package/dist/operator-ask.js +3 -0
  240. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  241. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  242. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  243. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  244. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  245. package/dist/orchestration/workflow-notify-journal.js +27 -34
  246. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  247. package/dist/orchestration/workflow-park-decision.js +118 -0
  248. package/dist/org-delivery-gate.d.ts +81 -0
  249. package/dist/org-delivery-gate.js +59 -0
  250. package/dist/panel-tool-names.d.ts +23 -0
  251. package/dist/panel-tool-names.js +8 -0
  252. package/dist/parked-decide.d.ts +39 -6
  253. package/dist/parked-decide.js +98 -51
  254. package/dist/parked-revive-surface.d.ts +9 -2
  255. package/dist/parked-revive-surface.js +11 -8
  256. package/dist/permission-rule-list.d.ts +1 -1
  257. package/dist/permission-rule-list.js +2 -2
  258. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  259. package/dist/plugins/approval-ask-store-file.js +21 -0
  260. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  261. package/dist/plugins/approval-ask-store-memory.js +34 -2
  262. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  263. package/dist/plugins/approval-ask-store-sql.js +37 -1
  264. package/dist/plugins/blob-backend.d.ts +38 -25
  265. package/dist/plugins/blob-backend.js +29 -19
  266. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  267. package/dist/plugins/breaker-state-sql.js +4 -4
  268. package/dist/plugins/caching-session-store.d.ts +3 -0
  269. package/dist/plugins/caching-session-store.js +3 -0
  270. package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
  271. package/dist/plugins/checkpoint-store-sql.js +20 -2
  272. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  273. package/dist/plugins/file-history-store-sql.js +3 -1
  274. package/dist/plugins/file-run-store.d.ts +5 -13
  275. package/dist/plugins/file-run-store.js +9 -0
  276. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  277. package/dist/plugins/fork-routing-session-store.js +12 -1
  278. package/dist/plugins/host-platform.d.ts +2 -0
  279. package/dist/plugins/host-platform.js +2 -1
  280. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  281. package/dist/plugins/local-checkpoint-store.js +6 -1
  282. package/dist/plugins/local-session-store.d.ts +1 -1
  283. package/dist/plugins/local-session-window.d.ts +39 -0
  284. package/dist/plugins/local-session-window.js +54 -0
  285. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  286. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  287. package/dist/plugins/mailbox-store-sql.js +77 -52
  288. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  289. package/dist/plugins/memory-run-store.d.ts +5 -13
  290. package/dist/plugins/memory-run-store.js +8 -0
  291. package/dist/plugins/one-time-migrations.d.ts +110 -5
  292. package/dist/plugins/one-time-migrations.js +320 -8
  293. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  294. package/dist/plugins/org-delivery-quota-store.js +228 -0
  295. package/dist/plugins/pg-pool.js +39 -7
  296. package/dist/plugins/pg-session-storage.d.ts +17 -4
  297. package/dist/plugins/pg-session-storage.js +29 -6
  298. package/dist/plugins/remote-env-adb.d.ts +6 -12
  299. package/dist/plugins/remote-env-adb.js +12 -2
  300. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  301. package/dist/plugins/remote-env-k8s.js +23 -5
  302. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  303. package/dist/plugins/remote-env-local-docker.js +12 -9
  304. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  305. package/dist/plugins/remote-env-ssh.js +17 -11
  306. package/dist/plugins/run-store-sql.d.ts +16 -14
  307. package/dist/plugins/run-store-sql.js +22 -2
  308. package/dist/plugins/schema-indexes.js +2 -0
  309. package/dist/plugins/send-user-file.js +2 -2
  310. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  311. package/dist/plugins/session-epoch-anchor.js +2 -3
  312. package/dist/plugins/session-store.d.ts +18 -8
  313. package/dist/plugins/session-store.js +15 -4
  314. package/dist/plugins/sql-driver.d.ts +74 -11
  315. package/dist/plugins/sql-driver.js +210 -12
  316. package/dist/plugins/sql-errors.d.ts +23 -0
  317. package/dist/plugins/sql-errors.js +21 -0
  318. package/dist/plugins/store-backend.d.ts +36 -1
  319. package/dist/plugins/store-backend.js +40 -14
  320. package/dist/plugins/store-contracts.d.ts +42 -0
  321. package/dist/plugins/store-contracts.js +1 -0
  322. package/dist/plugins/tidb-pool.d.ts +6 -1
  323. package/dist/plugins/tidb-pool.js +44 -10
  324. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  325. package/dist/plugins/tidb-session-storage.js +2 -2
  326. package/dist/plugins/tidb-session-store.d.ts +24 -4
  327. package/dist/plugins/tidb-session-store.js +28 -4
  328. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  329. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  330. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  331. package/dist/plugins/workflow-run-store-sql.js +50 -9
  332. package/dist/posture-source.d.ts +18 -10
  333. package/dist/posture-source.js +4 -1
  334. package/dist/project-identity.d.ts +45 -6
  335. package/dist/project-identity.js +162 -8
  336. package/dist/project-layer-key.d.ts +28 -0
  337. package/dist/project-layer-key.js +29 -0
  338. package/dist/question.js +3 -2
  339. package/dist/read-deny-entry.d.ts +25 -0
  340. package/dist/read-deny-entry.js +12 -0
  341. package/dist/read-face-posture.d.ts +37 -11
  342. package/dist/read-face-posture.js +32 -3
  343. package/dist/request-key-closure.d.ts +7 -0
  344. package/dist/request-key-closure.js +9 -1
  345. package/dist/request-value-closure.d.ts +5 -0
  346. package/dist/request-value-closure.js +11 -3
  347. package/dist/rule-entry-list.d.ts +26 -2
  348. package/dist/rule-entry-list.js +72 -12
  349. package/dist/rules-consent.js +3 -4
  350. package/dist/run-acceptance.d.ts +19 -3
  351. package/dist/run-acceptance.js +13 -1
  352. package/dist/run-local.js +36 -6
  353. package/dist/runs.d.ts +10 -9
  354. package/dist/runs.js +21 -3
  355. package/dist/runtime-caps-resolver.d.ts +16 -6
  356. package/dist/runtime-caps-resolver.js +18 -5
  357. package/dist/sandbox-pkg-source.d.ts +19 -1
  358. package/dist/sandbox-pkg-source.js +29 -7
  359. package/dist/security.d.ts +87 -9
  360. package/dist/security.js +52 -9
  361. package/dist/session-error-wire.d.ts +19 -2
  362. package/dist/session-error-wire.js +5 -1
  363. package/dist/session-titled-frame.d.ts +33 -0
  364. package/dist/session-titled-frame.js +4 -0
  365. package/dist/session-titler.d.ts +9 -1
  366. package/dist/session-titler.js +15 -4
  367. package/dist/spec-fields.js +21 -2
  368. package/dist/sql-engine-posture.d.ts +3 -1
  369. package/dist/task-cwd.d.ts +1 -1
  370. package/dist/task-mcp.d.ts +3 -3
  371. package/dist/task-mcp.js +7 -66
  372. package/dist/task-settings.d.ts +89 -88
  373. package/dist/task-settings.js +71 -63
  374. package/dist/text-bidi.d.ts +0 -4
  375. package/dist/text-bidi.js +1 -3
  376. package/dist/tighten-only-seats.d.ts +150 -0
  377. package/dist/tighten-only-seats.js +196 -0
  378. package/dist/tool-approval.d.ts +303 -87
  379. package/dist/tool-approval.js +623 -239
  380. package/dist/trace/core-keyset-guard.d.ts +104 -22
  381. package/dist/trace/exit-seat.d.ts +28 -0
  382. package/dist/trace/exit-seat.js +76 -0
  383. package/dist/trace/ledger-events.d.ts +3 -2
  384. package/dist/trace/project.d.ts +80 -12
  385. package/dist/trace/project.js +41 -28
  386. package/dist/trace/projection-table.d.ts +100 -0
  387. package/dist/trace/projection-table.js +130 -0
  388. package/dist/trace/redact.d.ts +54 -0
  389. package/dist/trace/redact.js +778 -152
  390. package/dist/trace/self-minted-wire.d.ts +345 -1
  391. package/dist/trace/self-minted-wire.js +117 -1
  392. package/dist/trace/wire-projection-faces.d.ts +298 -2
  393. package/dist/trace/wire-projection-faces.js +154 -13
  394. package/dist/url-refusal.js +2 -0
  395. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  396. package/dist/web-admin-client/apply-effective.js +56 -5
  397. package/dist/web-admin-client/facade.d.ts +1 -1
  398. package/dist/web-admin-client/facade.js +1 -1
  399. package/dist/web-admin-client/read-face.js +5 -9
  400. package/dist/web-admin-client/skills-mcp.js +4 -5
  401. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  402. package/package.json +7 -3
@@ -1,7 +1,9 @@
1
- import { createHash } from "node:crypto";
2
- import { join } from "node:path";
3
- import { AppendLog, ensureDir, isHostDecider } from "@sema-agent/core";
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { closeSync, existsSync, fsyncSync, openSync, readFileSync, renameSync, unlinkSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { AppendLog, ensureDir, isHostDecider, writeThenLink } from "@sema-agent/core";
4
5
  import { recordFailOpen } from "./observability/fail-open.js";
6
+ import { ownerOfCheckpointScope } from "./security.js";
5
7
  import { replayJsonlSkipping } from "./observability/corrupt-read-seat.js";
6
8
  import { isSettleCause, SETTLE_OUTCOME } from "./approval-deny-reasons.js";
7
9
  export const APPROVAL_ASK_AUDIT_DIR = "approval-ask-audit";
@@ -168,10 +170,157 @@ const LEDGER_SHAPE = {
168
170
  return rec === undefined ? undefined : { rec, outOfSetCause };
169
171
  },
170
172
  };
173
+ function foldLedger(records) {
174
+ const groups = new Map();
175
+ const legClosed = [];
176
+ const shutdownMarks = [];
177
+ const group = (approvalId, line) => {
178
+ let g = groups.get(approvalId);
179
+ if (!g) {
180
+ g = { firstLine: line };
181
+ groups.set(approvalId, g);
182
+ }
183
+ return g;
184
+ };
185
+ for (const { rec, line } of records) {
186
+ switch (rec.kind) {
187
+ case "ask": {
188
+ const g = group(rec.approvalId, line);
189
+ if (g.ask === undefined) {
190
+ g.ask = rec;
191
+ g.askLine = line;
192
+ }
193
+ break;
194
+ }
195
+ case "settle": {
196
+ const g = group(rec.approvalId, line);
197
+ if (g.settle === undefined) {
198
+ g.settle = rec;
199
+ g.settleLine = line;
200
+ }
201
+ break;
202
+ }
203
+ case "late_settle":
204
+ break;
205
+ case "leg_closed":
206
+ legClosed.push({ taskId: rec.taskId, line });
207
+ break;
208
+ case "interrupted_by_shutdown":
209
+ shutdownMarks.push({ taskId: rec.taskId, line });
210
+ break;
211
+ case "crash_converged": {
212
+ const g = group(rec.approvalId, line);
213
+ g.converged = rec;
214
+ g.convergedLine = line;
215
+ break;
216
+ }
217
+ default: {
218
+ const unreachable = rec;
219
+ throw new Error(`approval-ask-audit fold: unreachable record ${String(unreachable)}`);
220
+ }
221
+ }
222
+ }
223
+ return { groups, legClosed, shutdownMarks };
224
+ }
225
+ function legEvidenceOf(g, records, afterLine, beforeLine = Number.POSITIVE_INFINITY) {
226
+ const ask = g.ask;
227
+ if (!ask.legTracked)
228
+ return undefined;
229
+ return records.some((r) => r.taskId === ask.taskId && r.line > afterLine && r.line < beforeLine);
230
+ }
231
+ function judgeOrphan(g, legClosed) {
232
+ if (g.ask === undefined || g.converged !== undefined)
233
+ return undefined;
234
+ if (g.settle === undefined) {
235
+ return legEvidenceOf(g, legClosed, g.askLine ?? 0) === true ? "inconsistent" : "pending";
236
+ }
237
+ if (g.settle.outcome === "allowed" && legEvidenceOf(g, legClosed, g.settleLine ?? 0) === false)
238
+ return "decided";
239
+ return undefined;
240
+ }
241
+ function readLedgerLine(raw) {
242
+ let parsed;
243
+ try {
244
+ parsed = JSON.parse(raw.toString("utf8"));
245
+ }
246
+ catch (err) {
247
+ return { unparsable: err };
248
+ }
249
+ return { rec: readLedgerRecord(parsed, () => { }) };
250
+ }
251
+ function recordOfLine(raw) {
252
+ const read = readLedgerLine(raw);
253
+ return "rec" in read ? read.rec : undefined;
254
+ }
255
+ function replaceFileBytes(target, bytes) {
256
+ const staging = join(dirname(target), ".tmp", `${APPROVAL_ASK_AUDIT_LEDGER}.${process.pid}.${randomBytes(6).toString("hex")}.rotate`);
257
+ try {
258
+ writeThenLink(staging, bytes);
259
+ renameSync(staging, target);
260
+ }
261
+ finally {
262
+ if (existsSync(staging))
263
+ unlinkSync(staging);
264
+ }
265
+ }
266
+ function fsyncDirectory(dir) {
267
+ const fd = openSync(dir, "r");
268
+ try {
269
+ fsyncSync(fd);
270
+ }
271
+ finally {
272
+ closeSync(fd);
273
+ }
274
+ }
275
+ function splitLedgerBytes(bytes) {
276
+ const lines = [];
277
+ let start = 0;
278
+ for (let i = bytes.indexOf(0x0a, start); i !== -1; i = bytes.indexOf(0x0a, start)) {
279
+ lines.push(bytes.subarray(start, i));
280
+ start = i + 1;
281
+ }
282
+ return { lines, tail: bytes.subarray(start) };
283
+ }
284
+ function approvalIdOf(rec) {
285
+ switch (rec.kind) {
286
+ case "ask":
287
+ case "settle":
288
+ case "crash_converged":
289
+ case "late_settle":
290
+ return rec.approvalId;
291
+ case "leg_closed":
292
+ case "interrupted_by_shutdown":
293
+ return undefined;
294
+ default: {
295
+ const unreachable = rec;
296
+ throw new Error(`approval-ask-audit: unreachable record ${String(unreachable)}`);
297
+ }
298
+ }
299
+ }
300
+ function atMsOf(rec) {
301
+ switch (rec.kind) {
302
+ case "ask":
303
+ return rec.mintedAtMs;
304
+ case "settle":
305
+ case "late_settle":
306
+ return rec.settledAtMs;
307
+ case "crash_converged":
308
+ return rec.convergedAtMs;
309
+ case "leg_closed":
310
+ return rec.closedAtMs;
311
+ case "interrupted_by_shutdown":
312
+ return rec.atMs;
313
+ default: {
314
+ const unreachable = rec;
315
+ throw new Error(`approval-ask-audit: unreachable record ${String(unreachable)}`);
316
+ }
317
+ }
318
+ }
171
319
  export class FileApprovalAskAuditStore {
172
320
  ledgerPath;
173
321
  log;
174
322
  openLog;
323
+ fsyncDir;
175
324
  replayed = new Map();
176
325
  replayedLegClosed = [];
177
326
  replayedShutdownMarks = [];
@@ -185,6 +334,7 @@ export class FileApprovalAskAuditStore {
185
334
  askTaskId = new Map();
186
335
  constructor(root, internals) {
187
336
  this.openLog = internals?.appendLog ?? ((p) => new AppendLog(p));
337
+ this.fsyncDir = internals?.fsyncDir ?? fsyncDirectory;
188
338
  const dir = join(root, APPROVAL_ASK_AUDIT_DIR);
189
339
  ensureDir(dir);
190
340
  this.ledgerPath = join(dir, APPROVAL_ASK_AUDIT_LEDGER);
@@ -193,59 +343,20 @@ export class FileApprovalAskAuditStore {
193
343
  corruptLines = 0;
194
344
  replay() {
195
345
  const { records, skipped } = replayJsonlSkipping(this.ledgerPath, "approval-ask-audit", LEDGER_SHAPE);
196
- this.corruptLines = skipped;
197
- let line = 0;
198
- for (const { rec, outOfSetCause } of records) {
199
- line += 1;
200
- if (outOfSetCause)
201
- this.corruptLines += 1;
202
- switch (rec.kind) {
203
- case "ask": {
204
- const g = this.group(rec.approvalId, line);
205
- if (g.ask === undefined) {
206
- g.ask = rec;
207
- g.askLine = line;
208
- }
209
- this.indexAsk(rec);
210
- break;
211
- }
212
- case "settle": {
213
- const g = this.group(rec.approvalId, line);
214
- if (g.settle === undefined) {
215
- g.settle = rec;
216
- g.settleLine = line;
217
- }
218
- this.indexSettle(rec);
219
- break;
220
- }
221
- case "late_settle":
222
- break;
223
- case "leg_closed":
224
- this.replayedLegClosed.push({ taskId: rec.taskId, line });
225
- break;
226
- case "interrupted_by_shutdown":
227
- this.replayedShutdownMarks.push({ taskId: rec.taskId, line });
228
- break;
229
- case "crash_converged": {
230
- const g = this.group(rec.approvalId, line);
231
- g.converged = rec;
232
- g.convergedLine = line;
233
- break;
234
- }
235
- default: {
236
- const unreachable = rec;
237
- throw new Error(`approval-ask-audit replay: unreachable record ${String(unreachable)}`);
238
- }
239
- }
240
- }
241
- }
242
- group(approvalId, line) {
243
- let g = this.replayed.get(approvalId);
244
- if (!g) {
245
- g = { firstLine: line };
346
+ this.corruptLines = skipped + records.filter((r) => r.outOfSetCause).length;
347
+ const fold = foldLedger(records.map(({ rec }, i) => ({ rec, line: i + 1 })));
348
+ for (const [approvalId, g] of fold.groups)
246
349
  this.replayed.set(approvalId, g);
350
+ for (const r of fold.legClosed)
351
+ this.replayedLegClosed.push(r);
352
+ for (const r of fold.shutdownMarks)
353
+ this.replayedShutdownMarks.push(r);
354
+ for (const { rec } of records) {
355
+ if (rec.kind === "ask")
356
+ this.indexAsk(rec);
357
+ else if (rec.kind === "settle")
358
+ this.indexSettle(rec);
247
359
  }
248
- return g;
249
360
  }
250
361
  append(rec) {
251
362
  try {
@@ -346,18 +457,12 @@ export class FileApprovalAskAuditStore {
346
457
  this.convergedRows.push({ row: this.projectRow(g, g.converged.orphanState, g.converged.convergedAtMs, this.causeOf(g)), owner: g.ask.owner });
347
458
  continue;
348
459
  }
349
- let orphanState;
350
- if (g.settle === undefined) {
351
- if (this.legEvidence(g, this.replayedLegClosed, g.askLine ?? 0) === true) {
352
- inconsistent += 1;
353
- continue;
354
- }
355
- orphanState = "pending";
356
- }
357
- else if (g.settle.outcome === "allowed" &&
358
- this.legEvidence(g, this.replayedLegClosed, g.settleLine ?? 0) === false) {
359
- orphanState = "decided";
460
+ const verdict = judgeOrphan(g, this.replayedLegClosed);
461
+ if (verdict === "inconsistent") {
462
+ inconsistent += 1;
463
+ continue;
360
464
  }
465
+ const orphanState = verdict;
361
466
  if (orphanState === undefined)
362
467
  continue;
363
468
  const convergedAtMs = Date.now();
@@ -379,13 +484,7 @@ export class FileApprovalAskAuditStore {
379
484
  causeOf(g) {
380
485
  const after = g.settleLine ?? g.askLine ?? 0;
381
486
  const before = g.convergedLine ?? Number.POSITIVE_INFINITY;
382
- return this.legEvidence(g, this.replayedShutdownMarks, after, before) === true ? "shutdown_before_park" : "crashed_before_park";
383
- }
384
- legEvidence(g, records, afterLine, beforeLine = Number.POSITIVE_INFINITY) {
385
- const ask = g.ask;
386
- if (!ask.legTracked)
387
- return undefined;
388
- return records.some((r) => r.taskId === ask.taskId && r.line > afterLine && r.line < beforeLine);
487
+ return legEvidenceOf(g, this.replayedShutdownMarks, after, before) === true ? "shutdown_before_park" : "crashed_before_park";
389
488
  }
390
489
  projectRow(g, orphanState, convergedAtMs, cause) {
391
490
  const ask = g.ask;
@@ -401,18 +500,117 @@ export class FileApprovalAskAuditStore {
401
500
  orphanState,
402
501
  ...(orphanState === "decided" ? { originalDecision: "approve", ...(g.settle !== undefined ? { decidedAtMs: g.settle.settledAtMs } : {}) } : {}),
403
502
  convergedAtMs,
404
- resumeSafe: orphanState === "pending" && this.legEvidence(g, this.replayedLegClosed, g.askLine ?? 0) === false,
503
+ resumeSafe: orphanState === "pending" && legEvidenceOf(g, this.replayedLegClosed, g.askLine ?? 0) === false,
405
504
  };
406
505
  }
407
506
  listCrashConverged(scope) {
408
507
  const rows = [];
508
+ const owner = scope === undefined ? undefined : ownerOfCheckpointScope(scope);
409
509
  for (const e of this.convergedRows) {
410
- if (scope !== undefined && e.owner !== scope)
510
+ if (owner !== undefined && e.owner !== owner)
411
511
  continue;
412
512
  rows.push(e.row);
413
513
  }
414
514
  return rows;
415
515
  }
516
+ rotateOlderThan(cutoffMs, keepAnchors) {
517
+ let bytes;
518
+ try {
519
+ bytes = readFileSync(this.ledgerPath);
520
+ }
521
+ catch (err) {
522
+ if (err.code === "ENOENT")
523
+ return { droppedAsks: 0, droppedRecords: 0, keptRecords: 0 };
524
+ throw err;
525
+ }
526
+ const { lines, tail } = splitLedgerBytes(bytes);
527
+ const entries = lines.map((raw) => ({ raw, terminated: true, rec: recordOfLine(raw) }));
528
+ if (tail.length > 0)
529
+ entries.push({ raw: tail, terminated: false, rec: recordOfLine(tail) });
530
+ const numbered = entries.flatMap((e, i) => (e.rec !== undefined ? [{ rec: e.rec, line: i + 1 }] : []));
531
+ const fold = foldLedger(numbered);
532
+ const lastAt = new Map();
533
+ const anchorsOf = new Map();
534
+ for (const { rec } of numbered) {
535
+ const id = approvalIdOf(rec);
536
+ if (typeof id !== "string")
537
+ continue;
538
+ lastAt.set(id, Math.max(lastAt.get(id) ?? Number.NEGATIVE_INFINITY, atMsOf(rec)));
539
+ const cells = rec.kind === "ask" ? [rec.taskId, rec.sessionId, rec.sourceTaskId] : rec.kind === "late_settle" ? [rec.taskId, rec.sessionId] : [];
540
+ const list = anchorsOf.get(id) ?? [];
541
+ for (const c of cells)
542
+ if (c !== undefined)
543
+ list.push(c);
544
+ anchorsOf.set(id, list);
545
+ }
546
+ const dropped = new Set();
547
+ for (const [id, at] of lastAt) {
548
+ if (at >= cutoffMs)
549
+ continue;
550
+ if ((anchorsOf.get(id) ?? []).some((a) => keepAnchors.has(a)))
551
+ continue;
552
+ const g = fold.groups.get(id);
553
+ const verdict = g === undefined ? undefined : judgeOrphan(g, fold.legClosed);
554
+ if (verdict === "pending" || verdict === "decided")
555
+ continue;
556
+ dropped.add(id);
557
+ }
558
+ const claimedTasks = new Set();
559
+ for (const [id, g] of fold.groups)
560
+ if (!dropped.has(id) && g.ask !== undefined)
561
+ claimedTasks.add(g.ask.taskId);
562
+ const keep = (rec) => {
563
+ if (rec === undefined)
564
+ return true;
565
+ switch (rec.kind) {
566
+ case "ask":
567
+ case "settle":
568
+ case "crash_converged":
569
+ return !dropped.has(rec.approvalId);
570
+ case "late_settle":
571
+ return rec.approvalId !== null ? !dropped.has(rec.approvalId) : rec.settledAtMs >= cutoffMs;
572
+ case "leg_closed":
573
+ case "interrupted_by_shutdown":
574
+ return atMsOf(rec) >= cutoffMs || claimedTasks.has(rec.taskId) || keepAnchors.has(rec.taskId);
575
+ default: {
576
+ const unreachable = rec;
577
+ throw new Error(`approval-ask-audit rotate: unreachable record ${String(unreachable)}`);
578
+ }
579
+ }
580
+ };
581
+ const kept = entries.filter((e) => keep(e.rec));
582
+ const droppedRecords = entries.length - kept.length;
583
+ if (droppedRecords === 0)
584
+ return { droppedAsks: 0, droppedRecords: 0, keptRecords: entries.length };
585
+ this.log?.close();
586
+ this.log = undefined;
587
+ const NEWLINE = Buffer.from([0x0a]);
588
+ replaceFileBytes(this.ledgerPath, Buffer.concat(kept.flatMap((e) => (e.terminated ? [e.raw, NEWLINE] : [e.raw]))));
589
+ for (const id of dropped) {
590
+ this.replayed.delete(id);
591
+ this.askTaskId.delete(id);
592
+ this.parkExpired.delete(id);
593
+ }
594
+ for (const bucket of [this.askByCallAnchor, this.askBySessionOnly]) {
595
+ for (const [key, ids] of bucket) {
596
+ for (const id of dropped)
597
+ ids.delete(id);
598
+ if (ids.size === 0)
599
+ bucket.delete(key);
600
+ }
601
+ }
602
+ const survivors = this.convergedRows.filter((e) => !dropped.has(e.row.approvalId));
603
+ this.convergedRows.length = 0;
604
+ for (const e of survivors)
605
+ this.convergedRows.push(e);
606
+ try {
607
+ this.fsyncDir(dirname(this.ledgerPath));
608
+ }
609
+ catch (err) {
610
+ recordFailOpen("server.approval-ask-audit.rotate-dir-fsync-failed", `path=${this.ledgerPath} err=${err instanceof Error ? err.message : String(err)}`);
611
+ }
612
+ return { droppedAsks: dropped.size, droppedRecords, keptRecords: kept.length };
613
+ }
416
614
  close() {
417
615
  this.log?.close();
418
616
  this.log = undefined;
@@ -15,6 +15,21 @@ export declare const BATCH_TERMINAL: ReadonlySet<BatchState>;
15
15
  * 都在这里),放这里不引新依赖边。
16
16
  */
17
17
  export declare const MAX_DECISION_NOTE_CHARS = 2048;
18
+ /**
19
+ * 回决回执上「理由记上了吗」(`noteRecorded`)一格的**唯一判官与唯一组句器** —— 两口回决(live
20
+ * `POST /v1/tool-approvals/:id/respond` 与耐久 `POST /v1/tasks/:taskId/asks/:askId/decision`)的每一个 200
21
+ * 回体(PARKED 行经赎回腿受理的那一腿除外:它的理由走检查点回决链、不写 ask 行,尚无「记在哪张行」的定义,契约里点名为未覆盖)都经这两只函数说这件事,
22
+ * 不在各自的回体字面量里手写第二份。
23
+ *
24
+ * 三态同一份契约:请求**没带** `note` ⇒ 键缺席(不是 `false`);带了 ⇒ `true | false`:`true` = **已确认**持久行上那段文本就是这次提交的
25
+ * (逐字相等才算 —— 文本真的相同就不是谎,哪怕是别人写的);`false` = **没确认**(行上是别人的理由 / 这台没有店 / 店抖动而确认读也读不到 ——
26
+ * 不知道不许说成成功),不是「这台部署有没有店」。耐久回决口手里恒有那一行,它的 `false` 就是「行上不是这次那段」。
27
+ */
28
+ export declare function noteLandedOnRow(requestNote: string | undefined, rowNote: string | null): boolean;
29
+ /** {@link noteLandedOnRow} 的组句器:只在请求带了 `note` 时铸 `noteRecorded`(`landed` 由调用方按各自能证明的事实给)。 */
30
+ export declare function noteRecordedReceipt(requestNote: string | undefined, landed: boolean): {
31
+ noteRecorded?: boolean;
32
+ };
18
33
  /** ask 转移合法性(表驱动,含拒绝同值自环——STREAM_PENDING→STREAM_PENDING 不在表里,故 false)。 */
19
34
  export declare function canAskTransition(from: AskState, to: AskState): boolean;
20
35
  /** 批转移合法性,同形。 */
@@ -2,6 +2,12 @@ import { createHash } from "node:crypto";
2
2
  export const ASK_TERMINAL = new Set(["DECIDED", "PARKED", "DENIED", "VOID"]);
3
3
  export const BATCH_TERMINAL = new Set(["ROUTING_BOUND", "ABORTED"]);
4
4
  export const MAX_DECISION_NOTE_CHARS = 2048;
5
+ export function noteLandedOnRow(requestNote, rowNote) {
6
+ return requestNote !== undefined && rowNote === requestNote;
7
+ }
8
+ export function noteRecordedReceipt(requestNote, landed) {
9
+ return requestNote === undefined ? {} : { noteRecorded: landed };
10
+ }
5
11
  const ASK_TRANSITIONS = {
6
12
  STREAM_PENDING: ["DECIDED", "PARKING", "VOID"],
7
13
  PARKING: ["PARKED", "DENIED", "VOID"],
@@ -0,0 +1,136 @@
1
+ /**
2
+ * **审批账本的留存律**(一处成文;问账三形 + local 审计账同一条)。
3
+ *
4
+ * ## 律
5
+ * 一问一旦**结了**,且它**最后一次动静**早于 `now − APPROVAL_ASK_RETENTION_MS`,它在审批账本里的全部记录就在维护拍上**整问**删掉;
6
+ * 没结的问永不按龄删;删只删整问,从不改写留下的记录;每次真删了东西都有读数。`APPROVAL_ASK_RETENTION_MS=0` = 不删(永久保留)。
7
+ *
8
+ * **「结了」= 该问在它那本账里到了终局,且它挂靠的东西都不再能动**。后半句对两本账同一条:
9
+ * · **挂靠**:问行 / 审计组上的三格 —— 发起它的 run(`task_id`)、宿主会话(`session_id`)、发问那条腿的会话(`source_task_id`);
10
+ * · **还能动**:run 账上 `RUN_STATUS_CLASS` 的 live / parked 两类(跑着、停驻在门上);后台子代账上 running / parked 的子代(子代的问
11
+ * 记在**宿主** run 与宿主会话名下 —— 继承链闭包携宿主身份 —— 而子代可以比宿主 run 活得久,所以子代的宿主 run、宿主会话与它自己的会话
12
+ * 都算挂靠);以及 checkpoint 店里**每一只待决的 checkpoint**(停驻不论是谁的 —— run、后台子代、workflow 子代 —— 都是一只待决 checkpoint,
13
+ * 它的会话 = 停驻那条腿的会话 = 那条腿上问行的 `source_task_id`):一个来源盖住所有停驻,不必逐个枚举会停驻的东西。
14
+ * 还能动的东西会回读或续写它挂靠的问 —— 会话授权的争议判据按「这次调用在这条腿上有没有行」读问账(没有行 = 从没问过 ⇒ 一揽子放行可以
15
+ * 代答;拒绝行若被删,就成了代答),停驻问的迟到结算要审计账里那一问的前置事实。所以一次清扫先列出还能动的东西的挂靠集
16
+ * ({@link collectMovableAnchors}),两本账都把挂靠在集里的问整只跳过。
17
+ * 前半句各账一句,判据都住在各自的属主里(本文件不复述,只排期与读数):
18
+ * · 问账(Memory / File / SQL 三形同两只动词,各是一条语句):`reapSettledAsks` —— 行在终态(`ASK_TERMINAL`)且不是 provisional
19
+ * (版本化补偿还能改它)∧ `updatedAtMs` 早于 cutoff ∧ run 不在还能动的集里;`reapEmptyBatches` —— 批是问的容器,批里已经没有问
20
+ * ∧ 批自己的 `updatedAtMs` 也早于 cutoff 才删。
21
+ * · 审计账(`FileApprovalAskAuditStore.rotateOlderThan`,local 车道):这一问不再欠下一次起服收敛一个答案(起服收敛的判官此刻不会把它收成孤儿)
22
+ * ∧ run 不在还能动的集里 ∧ 该问所有记录里最晚的时刻早于 cutoff ⇒ 整问的行一起离开文件,留下的行逐字节不变。
23
+ *
24
+ * ## 为什么挂在维护 tick 上、而不是托管留存车道
25
+ * 那条车道(`boot/retention-lane.ts`)只认 SQL 后端、缺省关,在 local 上根本不存在 —— 用它就做不到「File 与 SQL 同一条律、缺省生效」。
26
+ * 维护 tick 是所有按龄删行的腿的宿主(多副本各扫各的、幂等):问账的删除谓词是纯行谓词,两副本同扫只是一方删到零行。
27
+ *
28
+ * ## 节律
29
+ * 一次清扫至多每 {@link APPROVAL_ASK_RETENTION_PASS_MS} 一次(首拍即跑):窗以天计,清扫的迟到以小时计,无关紧要;而一次清扫的成本
30
+ * (SQL 上按状态扫终态行、local 上重读并重写审计账)不该每分钟付一次。问账一批至多 {@link APPROVAL_ASK_REAP_BATCH} 只,一次清扫内连删到
31
+ * 不满一批为止(积压按批渐进清空,每条语句都短)。
32
+ *
33
+ * ## 读数
34
+ * 每条语句(一次店动词调用)要么删了并交回删掉的行数、要么一行没删就抛 —— 读数按语句累计、计数器按语句当场加,一次清扫半途失败时
35
+ * 已经删掉的照样进 `approval_ask_retention_swept`(带 `incomplete: true`),错误再抛给维护 tick 的节流 catch。删掉的行没有第二次读数的机会。
36
+ */
37
+ import type { ApprovalAskStore } from "./plugins/approval-ask-store-sql.js";
38
+ import type { FileApprovalAskAuditStore } from "./approval-ask-audit-store.js";
39
+ import type { Logger } from "./observability/logger.js";
40
+ import type { Metrics } from "./observability/metrics.js";
41
+ import type { BackgroundAgentRecord } from "@sema-agent/core";
42
+ /** 缺省保留窗:30 天。 */
43
+ export declare const APPROVAL_ASK_RETENTION_DEFAULT_MS: number;
44
+ /**
45
+ * 正值的下限:1 天(低于即钳到 1 天并点名)。还能动的 run 的问本来就不删(见文件头);下限管的是**刚结束**的 run:
46
+ * 客户端在 run 结束后还可能对它的卡做幂等重试 / 晚答(决断口回放首决、晚答口回 409 / 410 而不是 404),一天吸收这一段。
47
+ */
48
+ export declare const APPROVAL_ASK_RETENTION_FLOOR_MS = 86400000;
49
+ /** 两次清扫之间的最短间隔(见文件头「节律」)。 */
50
+ export declare const APPROVAL_ASK_RETENTION_PASS_MS = 3600000;
51
+ /** 问账一批至多删多少只问(批行同界);列 run 账时的一页也取这个数。 */
52
+ export declare const APPROVAL_ASK_REAP_BATCH = 500;
53
+ /**
54
+ * 「还能动」的 run 状态词 —— 从 `RUN_STATUS_CLASS` 派生(parked 类在前、live 类在后),不手抄词表:run 账加一个词,它当场归一类。
55
+ * 🔴 **次序是承重的**(codex 验证轮 V2 / 验证二轮 W2):run 账按状态一词一查,两次查询之间 run 可以换态。停驻 → 跑着 → 再停驻:
56
+ * 途中被**续跑**(parked → live)的 run 在跑着那一查里在;续跑**失败退回**停驻(parked → live → parked,`resume-legs` 的可重试拒臂把 run 放回
57
+ * suspended、checkpoint 不换)在末一查里在。只在途中「跑着 → 停驻 → 跑着」两头都漏 —— 它无害:停驻之后的问只会更新(停驻那一刻的问比
58
+ * cutoff 新),早于 cutoff 的旧问属于已经结束的腿(续跑换新 legKey,争议判据按腿读),迟到决议也早在那些腿续跑时就受理过了;停驻本身另由
59
+ * 待决 checkpoint 那一源盖住。漏一条还要途中换三次态以上。
60
+ */
61
+ export declare const MOVABLE_RUN_STATUSES: readonly string[];
62
+ /** 审计账一次轮转的读数:删掉的问数 / 删掉的行数(含无主的腿记录)/ 留下的行数。 */
63
+ export interface AuditRotationReading {
64
+ droppedAsks: number;
65
+ droppedRecords: number;
66
+ keptRecords: number;
67
+ }
68
+ /** 一次清扫的读数(进 `approval_ask_retention_swept` 行)。 */
69
+ export interface ApprovalAskRetentionReading {
70
+ cutoffMs: number;
71
+ asks: number;
72
+ batches: number;
73
+ auditAsks: number;
74
+ auditRecords: number;
75
+ }
76
+ /** 问账 / 审计账 / run 账各自的窄口(测试用字面量驱动同一段生产代码;生产传整只店)。 */
77
+ export type ApprovalAskReapPort = Pick<ApprovalAskStore, "reapSettledAsks" | "reapEmptyBatches">;
78
+ export type AuditRotationPort = Pick<FileApprovalAskAuditStore, "rotateOlderThan">;
79
+ export interface MovableRunPort {
80
+ listRuns(opts: {
81
+ status?: string;
82
+ limit: number;
83
+ cursor?: {
84
+ createdAt: string;
85
+ taskId: string;
86
+ };
87
+ }): Promise<ReadonlyArray<{
88
+ taskId: string;
89
+ sessionId: string;
90
+ createdAt: string;
91
+ }>>;
92
+ }
93
+ /** checkpoint 店的窄口:每一只待决 checkpoint 的会话(不按门型过滤 —— 运维队列 `listPending` 会藏起门型读不出、却仍能被决的行)。 */
94
+ export interface MovableCheckpointPort {
95
+ listPendingSessionIds(): Promise<readonly string[]>;
96
+ }
97
+ /** 后台子代账的窄口(core `BackgroundAgentStore` 的两只运维面)。 */
98
+ export interface MovableBackgroundAgentPort {
99
+ listScopes?(): Promise<string[]>;
100
+ listByScope(scope: string): Promise<ReadonlyArray<{
101
+ owner: string;
102
+ sessionId?: string;
103
+ parentSessionId?: string;
104
+ rootSessionId?: string;
105
+ status: BackgroundAgentRecord["status"];
106
+ }>>;
107
+ }
108
+ /**
109
+ * 还能动的东西的**挂靠集**(见文件头):run 账上每个 {@link MOVABLE_RUN_STATUSES} 词按 `listRuns` 的键集游标翻页列全,收 run id 与它的会话;
110
+ * 后台子代账逐 scope 一次列全(不带状态过滤 ⇒ 每个 scope 一次快照,子代在两种能动态之间换不会漏),能动的子代收它的 owner(task 作用域 =
111
+ * 宿主 run;会话作用域 = 会话)、宿主会话两格与它自己的会话;checkpoint 店的待决行一次列全,收它的会话。任一账读不出 ⇒ 抛 ⇒ 这次清扫
112
+ * 一行不删(证不出哪些不能动,就不删);
113
+ * 子代账在场却枚举不了 scope(缺 `listScopes`)同样抛。列与删之间新起的东西,它的问都比 cutoff 新,不会被删;终局不会回到能动。
114
+ */
115
+ export declare function collectMovableAnchors(input: {
116
+ runs: MovableRunPort;
117
+ backgroundAgents: MovableBackgroundAgentPort | undefined;
118
+ /** 缺席 = 本部署没有后端(没有可列的停驻;后端在场就一定交得出读口 —— `StoreBackend.checkpointReadView` 必选,没有 checkpoint 店的后端交恒空读口)。调用方取后端自己的那只读口,不看这一世开没开 durable 停驻 —— 前世 / 别的副本留下的停驻照样在店里。 */
119
+ checkpoints: MovableCheckpointPort | undefined;
120
+ }): Promise<ReadonlySet<string>>;
121
+ /**
122
+ * 一次清扫:先列还能动的东西的挂靠集,再用同一个 cutoff 与同一只集敲问账(问 / 批各按批删到不满一批)、再轮转审计账。每条语句的删除数当场进计数
123
+ * `approval_ask_retention_rows_deleted_total{ledger}`;真删了东西 ⇒ 一行 `approval_ask_retention_swept`(半途失败也打,带 `incomplete: true`,
124
+ * 然后把错误原样抛给调用方 —— 维护 tick 的具名节流 catch 接住,连败即 warn)。
125
+ */
126
+ export declare function runApprovalAskRetentionPass(input: {
127
+ askStore: ApprovalAskReapPort | undefined;
128
+ audit: AuditRotationPort | undefined;
129
+ runs: MovableRunPort;
130
+ backgroundAgents: MovableBackgroundAgentPort | undefined;
131
+ checkpoints: MovableCheckpointPort | undefined;
132
+ cutoffMs: number;
133
+ logger: Pick<Logger, "info">;
134
+ metrics: Pick<Metrics, "inc">;
135
+ }): Promise<ApprovalAskRetentionReading>;
136
+ //# sourceMappingURL=approval-ask-retention.d.ts.map