@sema-agent/server 7.150.0 → 7.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -3,30 +3,30 @@ import { parseNumOrFail } from "../config.js";
3
3
  import { execFileSync } from "node:child_process";
4
4
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
5
5
  import { join } from "node:path";
6
+ import { randomUUID } from "node:crypto";
6
7
  import { tmpdir } from "node:os";
7
- import { Runner, combinePolicies, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, delimitUntrusted, hasDestroy, } from "@sema-agent/core";
8
+ import { Runner, delimitUntrusted, hasDestroy, } from "@sema-agent/core";
8
9
  import { leaderEntryRefusal, leaderRunEntry } from "./run-entry.js";
9
10
  import { buildCheckpointCtx } from "../http/checkpoint-ctx.js";
11
+ import { submissionPermissionModeWrite } from "../permission-mode-admission.js";
10
12
  import { serviceVersion } from "../service-version.js";
11
13
  import { RemoteContainerExecutionEnv } from "../plugins/remote-env-e2b.js";
12
14
  import { buildLaneHomeClaim } from "../execution-lane-caps.js";
13
15
  const e2bBaseTemplateHomeSeat = buildLaneHomeClaim({ remoteExec: { provider: "e2b" } });
14
- import { createDurableAskPolicy } from "../approval.js";
15
16
  import { gitSubprocessEnv } from "../server-secret-env.js";
16
- import { presignS3Url } from "../plugins/s3-presign.js";
17
- import { buildUploadScript, buildUploadLoopScript, uploadLoopCommand, uploadLoopScriptPath, uploadStepSuffix, fetchUploadedDiff, withStaging, UPLOAD_LOOP_PERIOD_SEC } from "./diffup.js";
17
+ import { buildLeaderDiffUrls, buildUploadScript, buildUploadLoopScript, uploadLoopCommand, uploadLoopScriptPath, uploadStepSuffix, fetchUploadedDiff, withStaging, UPLOAD_LOOP_PERIOD_SEC } from "./diffup.js";
18
18
  import { pullDiff, safeRev } from "./diffout.js";
19
- import { runLeaderTask, withLeaderLeg } from "./leader.js";
19
+ import { LEADER_APPROVAL_SCOPE, leaderLegDurability, runLeaderTask, staticLaneWorkerPark, withLeaderLeg } from "./leader.js";
20
20
  import { attachRepairLoopDeps } from "./repair-wire.js";
21
21
  import { routePlanWithFallback, validateSubtasks } from "./planner.js";
22
- import { createEngineNoticeSeat } from "../boot/runner-deps.js";
23
22
  import { buildInternalRunCtx } from "../internal-run-env.js";
24
23
  import { currentSubject } from "../observability/principal-context.js";
25
24
  import { partsOf } from "../owner-brands.js";
26
25
  import { taskSpecIdentityOf } from "../engine-identity.js";
27
26
  import { redactHead } from "../observability/run-terminal.js";
27
+ import { seatText } from "../trace/exit-seat.js";
28
+ import { SIGV4_PRESIGN_MAX_SEC } from "../object-store-buckets.js";
28
29
  const REPAIR_LOOP_WIRED = true;
29
- export const LEADER_APPROVAL_SCOPE = "_leader";
30
30
  export function leaderResourceScope(workerId) {
31
31
  return `_leader-resource-${workerId}`;
32
32
  }
@@ -104,6 +104,12 @@ function parseNumOrFailNonNegative(name, raw) {
104
104
  throw new Error(`env ${name}=${n} must not be negative`);
105
105
  return n;
106
106
  }
107
+ export function leaderDiffUrlTtlRefusal(presignTtlSec) {
108
+ if (presignTtlSec <= SIGV4_PRESIGN_MAX_SEC)
109
+ return undefined;
110
+ const maxTimeoutMs = (SIGV4_PRESIGN_MAX_SEC - 600) * 1000;
111
+ return `LEADER_TIMEOUT_MS makes the leader's diff-out links live ${presignTtlSec} s (the worker timeout + 600 s), longer than a presigned URL can (at most ${SIGV4_PRESIGN_MAX_SEC} s (7 days)) — set LEADER_TIMEOUT_MS to at most ${maxTimeoutMs}`;
112
+ }
107
113
  export function leaderResourceConfig(env = process.env) {
108
114
  const leaderTimeoutMs = Math.max(600_000, Math.floor(parseNumOrFailNonNegative("LEADER_TIMEOUT_MS", env.LEADER_TIMEOUT_MS) || 0) || 86_400_000);
109
115
  const workerMaxTurns = Math.floor(parseNumOrFailNonNegative("LEADER_WORKER_MAX_TURNS", env.LEADER_WORKER_MAX_TURNS) || 0) || 10_000;
@@ -199,22 +205,28 @@ export function createLeaderRunner(cfg) {
199
205
  };
200
206
  const ident = cfg.git ?? { name: "leader", email: "leader@local" };
201
207
  const { leaderTimeoutMs, workerLimits, presignTtlSec, resourceSuspend: resourceCfg } = leaderResourceConfig();
208
+ const ttlRefusal = cfg.s3 !== undefined ? leaderDiffUrlTtlRefusal(presignTtlSec) : undefined;
209
+ if (ttlRefusal !== undefined)
210
+ throw new Error(ttlRefusal);
202
211
  const { repairRounds, repairBudgetUsd, repairLoopOn, measureGatesOn, repairLoopAttempts, oracleFlakyK, replanBudgetUsd, } = leaderLoopConfig({ repairRounds: cfg.repairRounds });
203
- const onNoticeSeat = createEngineNoticeSeat(cfg.logger);
204
- const governanceSeat = cfg.governance ?? {};
205
- const deploymentPostureSeat = () => cfg.deploymentPosture?.() ?? {};
206
- const tracerSeat = cfg.tracer ? { tracer: cfg.tracer } : {};
207
- const modsSeat = cfg.mods ? { mods: cfg.mods } : {};
208
- const handsSeat = cfg.hands ? { hands: cfg.hands } : {};
209
- const servedTableSeat = { models: cfg.models, roles: cfg.roles, ...(cfg.tiers ? { tiers: cfg.tiers } : {}) };
210
- const usageWindowSeat = cfg.usageWindows && cfg.usageWindowStore ? { usageWindows: cfg.usageWindows, usageWindowStore: cfg.usageWindowStore } : {};
211
- const promptSourceSeat = cfg.promptSource ? { promptSource: cfg.promptSource } : {};
212
- const onErrorSeat = cfg.onError ? { onError: cfg.onError } : {};
213
- const principalSpec = () => {
214
- const subject = currentSubject();
215
- return taskSpecIdentityOf(subject === undefined ? undefined : partsOf(subject));
212
+ const mintLegSessionId = (stem) => `leader-${stem}-${Date.now()}-${randomUUID()}`;
213
+ const bindLegSlot = (key, env) => {
214
+ const release = cfg.legSlots.bind(key, env);
215
+ if (release === undefined)
216
+ cfg.logger?.warn?.("sandbox_path_env_slot_at_capacity", { sessionId: key, leg: "leader" });
217
+ return release ?? (() => { });
218
+ };
219
+ const withLegSlot = (runner, env, key) => {
220
+ const orig = runner.runTaskStream.bind(runner);
221
+ runner.runTaskStream = (...args) => {
222
+ const release = bindLegSlot(key, env);
223
+ const stream = orig(...args);
224
+ void stream.result().then(release, release);
225
+ return stream;
226
+ };
227
+ return runner;
216
228
  };
217
- const mkRepair = (rawEnv, repoDir, oracleFiles, entry) => {
229
+ const mkRepair = (rawEnv, repoDir, oracleFiles, birth) => {
218
230
  if (repairRounds <= 0)
219
231
  return undefined;
220
232
  return {
@@ -227,7 +239,6 @@ export function createLeaderRunner(cfg) {
227
239
  throw new Error(`oracle still present after remove (${f.path}) — refusing repair (measurement integrity)`);
228
240
  }
229
241
  try {
230
- const runner = new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat, executionEnv: rawEnv, rootPath: repoDir });
231
242
  const objective = [
232
243
  `The integrated project at ${repoDir} fails its build/test. Make the MINIMAL change to the working tree so this command exits 0 (cd into the repo and run it yourself to confirm):`,
233
244
  ` ${testCmd}`,
@@ -236,17 +247,20 @@ export function createLeaderRunner(cfg) {
236
247
  ``,
237
248
  delimitUntrusted("FAILING OUTPUT (untrusted)", errorText),
238
249
  ].join("\n");
250
+ const repairSessionId = mintLegSessionId(`repair-${round}`);
251
+ const runner = withLegSlot(new Runner({ ...cfg.plane(), executionEnv: rawEnv, rootPath: repoDir }), rawEnv, repairSessionId);
239
252
  const res = await runner
240
253
  .runTaskStream(withLeaderLeg({
241
254
  objective,
242
- ...principalSpec(),
243
- sessionId: `leader-repair-${Date.now()}-${round}`,
255
+ sessionId: repairSessionId,
244
256
  signal,
245
257
  limits: { maxCostUsd: repairBudgetUsd, maxWalltimeMs: Math.max(300_000, Math.floor(leaderTimeoutMs / 2)) },
246
- }, entry))
258
+ }, birth, { slotKey: repairSessionId, durability: leaderLegDurability({ continuation: "in_run" }), executor: { kind: "fresh" } }))
247
259
  .result();
248
- if (res.terminal.kind !== "completed")
249
- throw new Error(`repair round ${round} did not complete (status=${outwardPlane(res.terminal).status})`);
260
+ if (res.terminal.kind !== "completed") {
261
+ const plane = outwardPlane(res.terminal);
262
+ throw new Error(`repair round ${round} did not complete (status=${plane.status}${plane.errorMessage !== undefined ? `: ${plane.errorMessage}` : ""})`);
263
+ }
250
264
  return { costUsd: res.stats?.costMicroUsd !== undefined ? res.stats.costMicroUsd / 1e6 : undefined, note: res.result?.slice(0, 200) };
251
265
  }
252
266
  finally {
@@ -274,6 +288,8 @@ export function createLeaderRunner(cfg) {
274
288
  const refused = leaderEntryRefusal(entry);
275
289
  if (refused !== undefined)
276
290
  return { ok: false, reports: [], cancelled: false, error: refused };
291
+ const subject = currentSubject();
292
+ const birth = { entry, identity: taskSpecIdentityOf(subject === undefined ? undefined : partsOf(subject)), govern: cfg.govern, baseline: cfg.baseline, auth: cfg.auth };
277
293
  const injectOracles = async (env) => {
278
294
  const ofs = body.oracleFiles ?? [];
279
295
  if (ofs.length === 0)
@@ -295,15 +311,21 @@ export function createLeaderRunner(cfg) {
295
311
  if (Array.isArray(body.subtasks) && body.subtasks.length > 0) {
296
312
  return validateSubtasks(body.subtasks);
297
313
  }
298
- const planRunner = new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat });
314
+ const planRunner = new Runner({ ...cfg.plane() });
315
+ const routeAuth = birth.auth(undefined);
299
316
  const runRoute = async (prompt) => {
300
317
  const res = await planRunner.runTaskStream({
301
318
  objective: prompt,
302
- ...principalSpec(),
303
- sessionId: `leader-route-${Date.now()}`,
319
+ ...birth.identity,
320
+ getApiKeyAndHeaders: routeAuth,
321
+ sessionId: mintLegSessionId("route"),
304
322
  signal,
305
323
  ...(cfg.routerModel ? { model: cfg.routerModel } : { modelRole: "classifier" }),
306
324
  }).result();
325
+ if (res.terminal.kind !== "completed") {
326
+ const plane = outwardPlane(res.terminal);
327
+ cfg.logger?.warn?.("plan_route_run_incomplete", { status: plane.status, ...(plane.errorMessage !== undefined ? { err: seatText("operator-log-error", plane.errorMessage) } : {}) });
328
+ }
307
329
  return res.result ?? "";
308
330
  };
309
331
  const { subs, collapsed, rawSample } = await routePlanWithFallback(body.objective, runRoute, {
@@ -315,23 +337,18 @@ export function createLeaderRunner(cfg) {
315
337
  return subs;
316
338
  };
317
339
  const provisionWorker = async (sub) => {
318
- const sessionId = `leader-${sub.workerId}-${Date.now()}`;
319
- const durable = cfg.durable?.();
340
+ const sessionId = mintLegSessionId(sub.workerId);
341
+ const factory = cfg.s3 !== undefined && cfg.envFactory !== undefined ? { s3: cfg.s3, envFactory: cfg.envFactory } : undefined;
342
+ const park = factory !== undefined ? cfg.durable?.() : staticLaneWorkerPark(cfg.durable?.(), cfg.approvalListInForce());
320
343
  const resumeBody = { ...entry, objective: sub.spec.objective };
321
- const storedResumeCtx = durable !== undefined ? buildCheckpointCtx({ body: resumeBody, unattendedLeg: true, writerVersion: serviceVersion() }, durable.ctxSealer, sessionId) : undefined;
322
- let durableSpec = {};
323
- if (durable && storedResumeCtx !== undefined) {
324
- const d = durable;
325
- durableSpec = {
326
- toolPolicy: combinePolicies(createDurableQuestionPolicy(), createDurableAskPolicy({ requireApproval: d.requireApproval, ...(d.deny ? { deny: d.deny } : {}), ...(d.autoBudget ? { autoBudget: d.autoBudget } : {}), ...(d.neverAuto ? { neverAuto: d.neverAuto } : {}) })),
327
- checkpointStore: d.checkpointStore,
328
- durableApproval: { scope: LEADER_APPROVAL_SCOPE, ...(d.ttlMs ? { ttlMs: d.ttlMs } : {}) },
329
- onQuestion: QUESTION_AWAITS_RESUME,
330
- };
331
- await d.checkpointStore.putCtx(sessionId, storedResumeCtx).catch((e) => {
344
+ const storedResumeCtx = park !== undefined ? buildCheckpointCtx({ body: resumeBody, unattendedLeg: true, writerVersion: serviceVersion(), permissionModeWrite: submissionPermissionModeWrite(resumeBody) }, park.ctxSealer, sessionId) : undefined;
345
+ const durability = leaderLegDurability(park === undefined || storedResumeCtx === undefined
346
+ ? { continuation: "replay", resumeCtx: "unwritten" }
347
+ : await park.checkpointStore.putCtx(sessionId, storedResumeCtx).then(() => ({ continuation: "replay", resumeCtx: "landed", park }), (e) => {
332
348
  cfg.logger?.warn?.("leader_putctx_failed", { workerId: sub.workerId, err: redactHead(e instanceof Error ? e.message : String(e), 2000) });
333
- });
334
- }
349
+ return { continuation: "replay", resumeCtx: "lost" };
350
+ }));
351
+ const durable = durability.kind === "durable" ? durability.park : undefined;
335
352
  let resourceSpec = {};
336
353
  const repairLoopActive = repairLoopOn && REPAIR_LOOP_WIRED;
337
354
  if (repairLoopActive && resourceCfg) {
@@ -348,8 +365,8 @@ export function createLeaderRunner(cfg) {
348
365
  else if (resourceCfg && !repairLoopActive) {
349
366
  cfg.logger?.warn?.("leader_resource_suspend_inactive", {
350
367
  workerId: sub.workerId,
351
- reason: !durable
352
- ? "no durable checkpoint store"
368
+ reason: durability.kind === "transient"
369
+ ? durability.why
353
370
  : !cfg.toolResultStore
354
371
  ? "no durable tool-result store"
355
372
  : "no durable session store",
@@ -360,8 +377,8 @@ export function createLeaderRunner(cfg) {
360
377
  if (!d || storedResumeCtx === undefined)
361
378
  return runner;
362
379
  const orig = runner.runTaskStream.bind(runner);
363
- runner.runTaskStream = (spec, resume) => {
364
- const stream = orig(spec, resume);
380
+ runner.runTaskStream = (...args) => {
381
+ const stream = orig(...args);
365
382
  const iv = setInterval(() => {
366
383
  void d.checkpointStore.putCtx(sessionId, storedResumeCtx).catch(() => { });
367
384
  }, 45_000);
@@ -371,16 +388,11 @@ export function createLeaderRunner(cfg) {
371
388
  };
372
389
  return runner;
373
390
  };
374
- if (cfg.s3 && cfg.envFactory) {
375
- const s3 = cfg.s3;
376
- const envFactory = cfg.envFactory;
391
+ if (factory !== undefined) {
392
+ const { s3, envFactory } = factory;
377
393
  const baseSha = body.baseSha;
378
394
  const seedCmd = body.seedCmd;
379
- const key = `${s3.keyPrefix ?? "leader-diff"}/${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}/${sub.workerId}.patch`;
380
- const ttl = presignTtlSec;
381
- const base = { endpoint: s3.endpoint, bucket: s3.bucket, accessKey: s3.accessKey, secretKey: s3.secretKey, ...(s3.region ? { region: s3.region } : {}), key, expiresSec: ttl };
382
- const putUrl = presignS3Url({ ...base, method: "PUT" });
383
- const getUrl = presignS3Url({ ...base, method: "GET" });
395
+ const { putUrl, getUrl } = buildLeaderDiffUrls(s3, sub.workerId, presignTtlSec);
384
396
  const script = buildUploadScript({ repoDir: repo, baseSha, putUrl, workDir: W });
385
397
  const stage = async (env) => {
386
398
  await stageWorkerEnv(env, { seedCmd, repo, branch: sub.branch, uploadScriptPath: `${W}/.leader-upload.sh`, uploadScript: script });
@@ -389,21 +401,22 @@ export function createLeaderRunner(cfg) {
389
401
  return {
390
402
  workerId: sub.workerId, sessionId, branch: sub.branch,
391
403
  baseSha,
392
- runner: keepCtxWarm(new Runner({
393
- brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat,
404
+ runner: keepCtxWarm(new Runner({ ...cfg.plane(),
394
405
  ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}),
395
406
  ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}),
396
407
  executionEnvFactory: async (ctx) => {
397
408
  const env = await envFactory(ctx);
398
409
  assertLeaderOwnedEnvReapable(env, "leader worker sandbox");
410
+ const releaseSlot = bindLegSlot(sessionId, env);
399
411
  return withStaging(env, stage, async (e) => {
412
+ releaseSlot();
400
413
  await stopUploadLoop(e, sub.workerId);
401
414
  await sh(e)(`cd ${repo} && git add -A && git -c user.name='leader-belt' -c user.email='belt@leader' commit -qm 'belt: auto-commit uncommitted worker output' || true; sh ${W}/.leader-upload.sh`);
402
415
  });
403
416
  },
404
417
  })),
405
418
  fetchDiff: () => fetchUploadedDiff(getUrl),
406
- spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...durableSpec, ...resourceSpec, ...principalSpec(), objective: `${sub.spec.objective}${uploadStepSuffix(W)}` }, resumeBody),
419
+ spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...resourceSpec, objective: `${sub.spec.objective}${uploadStepSuffix(W)}` }, birth, { slotKey: sessionId, durability, executor: { kind: "fresh" } }),
407
420
  };
408
421
  }
409
422
  if (!cfg.e2bApiKey)
@@ -415,15 +428,15 @@ export function createLeaderRunner(cfg) {
415
428
  const baseSha = await sh(env)(`cd ${repo} && git rev-parse HEAD`);
416
429
  return {
417
430
  workerId: sub.workerId, sessionId, branch: sub.branch, baseSha,
418
- runner: keepCtxWarm(new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat, ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}), ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}), executionEnv: env })),
431
+ runner: keepCtxWarm(withLegSlot(new Runner({ ...cfg.plane(), ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}), ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}), executionEnv: env }), env, sessionId)),
419
432
  diffEnv: env,
420
433
  destroy: () => env.destroy().then(() => { }),
421
- spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...durableSpec, ...resourceSpec, ...principalSpec() }, resumeBody),
434
+ spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...resourceSpec }, birth, { slotKey: sessionId, durability, executor: { kind: "fresh" } }),
422
435
  };
423
436
  };
424
437
  const provisionIntegrationSandbox = async () => {
425
438
  if (cfg.envFactory) {
426
- const integSessionId = `leader-integ-${Date.now()}`;
439
+ const integSessionId = mintLegSessionId("integ");
427
440
  const env = await cfg.envFactory(buildInternalRunCtx(integSessionId));
428
441
  const reap = createEnvReaper(env, "leader integration sandbox");
429
442
  try {
@@ -436,7 +449,7 @@ export function createLeaderRunner(cfg) {
436
449
  }
437
450
  const rawEnv = env;
438
451
  const oracleFiles = body.oracleFiles ?? [];
439
- const repair = mkRepair(rawEnv, repo, oracleFiles, entry);
452
+ const repair = mkRepair(rawEnv, repo, oracleFiles, birth);
440
453
  return { env: asIntegrationEnv(env), destroy: reap, ...(repair ? { repair } : {}) };
441
454
  }
442
455
  if (!cfg.e2bApiKey)
@@ -454,11 +467,12 @@ export function createLeaderRunner(cfg) {
454
467
  await env.destroy().catch(() => { });
455
468
  throw e;
456
469
  }
457
- return { env: asIntegrationEnv(env), destroy: () => env.destroy().then(() => { }), ...(mkRepair(env, repo, body.oracleFiles ?? [], entry) ? { repair: mkRepair(env, repo, body.oracleFiles ?? [], entry) } : {}) };
470
+ const repair = mkRepair(env, repo, body.oracleFiles ?? [], birth);
471
+ return { env: asIntegrationEnv(env), destroy: () => env.destroy().then(() => { }), ...(repair ? { repair } : {}) };
458
472
  };
459
473
  const push = createCoordinatorPush(body.durableRemote, body.targetRef, ident);
460
474
  const deps = {
461
- entry,
475
+ birth,
462
476
  signal,
463
477
  plan,
464
478
  provisionWorker,
@@ -476,7 +490,7 @@ export function createLeaderRunner(cfg) {
476
490
  const resolveRepair = async (solo, _sub) => {
477
491
  let env;
478
492
  if (cfg.envFactory) {
479
- const graderSessionId = `leader-grader-${Date.now()}`;
493
+ const graderSessionId = mintLegSessionId("grader");
480
494
  env = await cfg.envFactory(buildInternalRunCtx(graderSessionId));
481
495
  }
482
496
  else {
@@ -1,7 +1,7 @@
1
1
  /**
2
- * 一条腿的**部署事实**(执行车道 · run 技能名册 · 受理见证 · 登记的工作目录 · 继承的项目上下文)—— server 自有的载体,**不搭引擎 spec 的车**。
2
+ * 一条腿的**部署事实**(执行车道 · run 技能名册 · 受理见证 · 会话绑定 · 继承的项目上下文 · 登记簿默认读层的种子项目)—— server 自有的载体,**不搭引擎 spec 的车**。
3
3
  *
4
- * 规则:`TaskSpec` 是引擎的类型面,上面只放引擎读的成员。本仓装配器(`boot/resolve-spec.ts` 的 `createResolveSpec`)同时还判出五件
4
+ * 规则:`TaskSpec` 是引擎的类型面,上面只放引擎读的成员。本仓装配器(`boot/resolve-spec.ts` 的 `createResolveSpec`)同时还判出六件
5
5
  * 只有 server 自己读的事实 —— 它们以装配器**自己的输出对象**为键登记在这一张表里(单一铸点 {@link mintLegFacts}),由两只漏斗
6
6
  * (受理 `http/admission.ts` 的 `prepareSpec` · 续跑 `http/resume-legs.ts` 的 `resolveResumeSpec`)在拿到装配输出的**同一只对象**时
7
7
  * 读一次(唯一读口 {@link legFactsOf},读在 `stampSpecRoot` 复制之前),此后作普通值随 `PreparedTaskSubmission.legFacts` /
@@ -19,6 +19,8 @@ import type { ScenarioHands } from "./capabilities/hands-lane.js";
19
19
  import type { RunSkillEntry } from "./capabilities/skills.js";
20
20
  import type { DelegationRootWitness } from "./delegated-session-owner.js";
21
21
  import type { ProjectContext } from "./project-context.js";
22
+ import type { MemorySeed } from "./project-registry.js";
23
+ import type { SessionBindings } from "./session-bindings.js";
22
24
  /** 一条腿的部署事实(冻结记录)。 */
23
25
  export interface LegFacts {
24
26
  /** 执行车道:`none` ⇒ 无手孪生 Runner。读者 = 生产选路器。 */
@@ -28,15 +30,21 @@ export interface LegFacts {
28
30
  /** 受理时读根会话行的那一读(会话 id + 住客)。读者 = 腿的会话行记录座(`session-workspace.ts`)。 */
29
31
  readonly sessionWitness: DelegationRootWitness;
30
32
  /**
31
- * 这次提交的根会话登记的工作目录(提交体 `cwd` 经唯一写口 `setSessionCwd` 登记的那一枚;装配器在登记之后读一次)。缺席 = 没登记。
32
- * 读者 = 三只组合入口(同步 / 后台 / 续跑腿的梯子与验证门):经 `compositionLegRoot`(`task-cwd.ts`)交给它们驱动的每一条腿当交活方的工作目录。
33
+ * 这条腿要写在根会话上的绑定(工作目录 · shell 环境 · 继承策略;装配器只算)。读者 = run 认领之后的唯一提交点(`session-bindings.ts` 的 `commitLegBindings`):
34
+ * 受理的那一刻写这一笔,写了之后才收场 `refused` 的提交由提交出口按回执撤回;以及三只组合入口(同步 / 后台 / 续跑腿的梯子与验证门):工作目录那一格
35
+ * (这条腿跑在的那一枚)经 `compositionLegRoot`(`task-cwd.ts`)交给它们驱动的每一条腿当交活方的工作目录。
33
36
  */
34
- readonly registeredCwd?: string;
37
+ readonly sessionBindings: SessionBindings;
35
38
  /**
36
39
  * 这条 run 继承到的项目上下文(`project-context.ts`):新提交腿在装配器头部判出的那一份,续跑腿是从续跑重建输入重放的那一份。缺席 = 没继承。
37
40
  * 读者 = 提交腿写续跑重建输入的那一笔(`submit-ctx.ts` `persistSubmissionCtx` → `CheckpointCtx.projectContext`):判一次、随 run 冻结。
38
41
  */
39
42
  readonly projectContext?: ProjectContext;
43
+ /**
44
+ * 这条 run 的登记簿默认读层种子(`project-registry.ts`:种子项目 + 判出它的那一位观者;`null` = 提交带了项目、判过,无):新提交腿判出的,续跑腿是从续跑重建输入重放的那一份。
45
+ * 缺席 = 没什么可判(提交没带项目)或没判过(续跑重放的行早于种子判)。读者 = 提交腿写续跑重建输入的那一笔(`submit-ctx.ts` `persistSubmissionCtx` → `CheckpointCtx.memorySeed`):判一次、随 run 冻结。
46
+ */
47
+ readonly memorySeed?: MemorySeed | null;
40
48
  }
41
49
  /**
42
50
  * 铸事实(**单一属主**:只允许 `createResolveSpec` 的出口调用)。同一只对象被第二次铸 ⇒ 当场抛 —— 两个写者是漂移的成因,
package/dist/leg-facts.js CHANGED
@@ -6,8 +6,9 @@ export function mintLegFacts(resolved, facts) {
6
6
  hands: facts.hands,
7
7
  skills: Object.freeze(facts.skills.map((e) => Object.freeze({ ...e }))),
8
8
  sessionWitness: Object.freeze({ ...facts.sessionWitness }),
9
- ...(facts.registeredCwd !== undefined ? { registeredCwd: facts.registeredCwd } : {}),
9
+ sessionBindings: Object.freeze({ ...facts.sessionBindings, ...(facts.sessionBindings.shellEnv !== undefined ? { shellEnv: Object.freeze({ ...facts.sessionBindings.shellEnv }) } : {}) }),
10
10
  ...(facts.projectContext !== undefined ? { projectContext: Object.freeze({ ...facts.projectContext }) } : {}),
11
+ ...(facts.memorySeed !== undefined ? { memorySeed: facts.memorySeed === null ? null : Object.freeze({ projectId: facts.memorySeed.projectId, viewer: Object.freeze({ ...facts.memorySeed.viewer }) }) } : {}),
11
12
  }));
12
13
  return resolved;
13
14
  }
@@ -175,27 +175,39 @@ export declare function memoryEngineRootFor(config: Pick<ServiceConfig, "memoryE
175
175
  * 记忆搬到 `<localDataRoot>/memory-work`,存量记忆与控制面升级后隐形)。 */
176
176
  export declare function fileMemoryEngineRoot(config: Pick<ServiceConfig, "memoryEngineDir">, fallbackRoot?: string): string;
177
177
  /**
178
- * 一条路径的**规范形**(给 {@link judgeMemoryRootOutsideDataRoot} 的 `canonical` 座用的生产实现):
179
- * · 既存的绝对路径 ⇒ **原样**交给 `realpath`(`.native`:大小写不敏感的文件系统上返回盘上的拼写;符号链接、macOS 的 `/var` → `/private/var` 在这一步展平)。
178
+ * 一段路径**在不在盘**的唯一读法(三态,{@link canonicalPathOf} 逐段走用它;host 车道托管判在「读不出就不删」那一臂登记根时也读它):
179
+ * · `stat` 得动(跟随符号链接)⇒ `true`(在);
180
+ * · `ENOENT` / `ENOTDIR`(这一处不存在、悬空链接的目标不存在、中间一段不是目录)⇒ `false`(不在);
181
+ * · 其余错误(`EACCES` 没有搜索权限的段、`ELOOP` 链接成环、I/O 错误……)⇒ **原样抛**(读不出)。读不出不是「不在」:把它读成不在,
182
+ * 下游的路径包含判就会把一处它根本看不见的目录判成「不在根里」—— 那正是删除面上的 fail-open。
183
+ */
184
+ export declare function presentOnDisk(p: string): boolean;
185
+ /**
186
+ * 一条路径的**规范形**(给 {@link judgeMemoryRootOutsideDataRoot} 的 `canonical` 座用的生产实现;host 车道的工作区托管判也读它):
187
+ * · 在盘的绝对路径 ⇒ **原样**交给 `realpath`(core `physicalPathOf` = realpath(3):大小写不敏感的文件系统上返回盘上的拼写;符号链接、macOS 的 `/var` → `/private/var` 在这一步展平)。
180
188
  * 不先在字串上折 `..`:操作系统在展开符号链接**之后**才折 `..`,`/link/..` 的真身是链接目标的父目录,字串折叠会把它读成 `/`;
181
- * · 其余(尚不存在 / 相对)⇒ 绝对化(**不折叠**)后逐段走:既存的前缀每进一段取一次 `realpath`(符号链接在这一步展开),`..` 折在**已展开**的前缀上 ——
182
- * 与操作系统同序(`/别名/../新目录` 的真身在链接目标的父目录下;先在字串上折会读成别名的父目录,判到另一只挂载上);第一段不存在起,余下是尚不存在的尾巴
189
+ * · 其余(尚不在盘 / 相对)⇒ 绝对化(**不折叠**)后逐段走:在盘的前缀每进一段取一次 `realpath`(符号链接在这一步展开),`..` 折在**已展开**的前缀上 ——
190
+ * 与操作系统同序(`/别名/../新目录` 的真身在链接目标的父目录下;先在字串上折会读成别名的父目录,判到另一只挂载上);第一段不在盘起,余下是尚不在盘的尾巴
183
191
  * (尾巴只做字串规范化,与 `mkdir -p` 建出来的同形)。
184
192
  *
185
- * 为什么按「最深既存祖先」而不是直接 `realpath(p)`:boot 期记忆根常常还没建出来(新数据根),`realpath` 对不存在的路径抛 ENOENT,
186
- * 而数据根那一侧已经存在、会被展平 —— 两侧拼写空间不一样,同一个目录会被读成「不在其下」。祖先用 `existsSync` 找(它对 ENOENT / ENOTDIR / EACCES / ELOOP
187
- * 一律答 `false`,不抛),所以走到的那一级一定 stat 得动;`realpath` 仍可能在「探完到取值之间目录被挪走 / 搜索权限被收」的竞态里抛 ——
188
- * 不在本函数里吞(吞了就是一条无声的降级臂),由 boot 调用点接住并响亮报一行(`memory_engine_dir_check_unavailable`),起服照常。
193
+ * 为什么按「最深在盘祖先」而不是直接 `realpath(p)`:boot 期记忆根常常还没建出来(新数据根),`realpath` 对不存在的路径抛 ENOENT,
194
+ * 而数据根那一侧已经存在、会被展平 —— 两侧拼写空间不一样,同一个目录会被读成「不在其下」。
195
+ *
196
+ * **读不出就抛**:每一段在不在盘读 {@link presentOnDisk}(三态)—— 不在(`ENOENT` / `ENOTDIR`)才接成尾巴;没有搜索权限的段、成环的链接、`realpath` 在
197
+ * 「探完到取值之间目录被挪走 / 搜索权限被收」的竞态里失败,一律**原样抛**,不在本函数里吞(吞了就是一条无声的降级臂:把看不见的一段当成「还不存在」,包含判就答
198
+ * 「不在里面」)。调用方各自接住、按自己的面响亮说「查不了」:起服记忆根判(`memory_engine_dir_check_unavailable`)· 配置根判(`sema_config_root_workspace_check_unavailable`)·
199
+ * 店的持久性取证(`path_unresolvable`)· host 车道托管判(铸时 ⇒ 这条腿不铸;删前 ⇒ 不删、留给退出兜底)。
189
200
  *
190
- * 取舍:尾巴(不存在的那几段)只比规范化字串,**不折大小写**,尾巴里的 `..` 按字串折:两个只差大小写、且都还不存在的拼写在大小写不敏感的盘上会被读成两处 ——
201
+ * 取舍:尾巴(不在盘的那几段)只比规范化字串,**不折大小写**,尾巴里的 `..` 按字串折:两个只差大小写、且都还不在盘的拼写在大小写不敏感的盘上会被读成两处 ——
191
202
  * 方向是多报一条 warn(这条判据的失败方向),不会漏报。
192
203
  */
193
204
  export declare function canonicalPathOf(p: string): string;
194
205
  /**
195
206
  * **路径包含**(含相等)的判官:`child` 是不是 `root` 本身或它的后代 —— `path.relative(canonical(root), canonical(child))` 不是 `..`、不以 `..` 加分隔符起头、也不是绝对路径(跨盘符)。
196
207
  * `..` 要按**整段**判:名为 `..data` 的子目录在其下;`startsWith("..")` 会把它读成在其外。`canonical` 座缺省 `path.resolve`(字串规范形),boot 递 {@link canonicalPathOf} 取符号链接展平后的形;
197
- * 两侧同一只座(先 root、后 child)。读者两处:记忆根「在数据根之外」那一判({@link judgeMemoryRootOutsideDataRoot})与起服时「配置根是不是工作区的祖先」那一判(`sema-config-dir.ts`);
198
- * 树里别处内联的同形表达式(`boot/deployment-mods.ts` · `plugins/local-data-dir-modes-m39.ts` · `plugins/remote-env-host.ts` · `plugins/worktree-isolation.ts`)不在本次收口范围。
208
+ * 两侧同一只座(先 root、后 child)。读者三处:记忆根「在数据根之外」那一判({@link judgeMemoryRootOutsideDataRoot})、起服时「配置根是不是工作区的祖先」那一判(`sema-config-dir.ts`)
209
+ * 与 host 车道工厂托管的两判(`plugins/remote-env-host.ts`,座 = {@link canonicalPathOf}:铸时「腿的目录落在哪只本服务铸的临时根里」· 删前「此刻谁的工作目录在这只根里」);
210
+ * 树里别处内联的同形表达式(`boot/deployment-mods.ts` · `plugins/local-data-dir-modes-m39.ts` · `plugins/remote-env-host.ts` 的残余镜像写判 · `plugins/worktree-isolation.ts`)不在本次收口范围。
199
211
  */
200
212
  export declare function pathIsWithin(root: string, child: string, canonical?: (p: string) => string): boolean;
201
213
  /** {@link judgeMemoryRootOutsideDataRoot} 的读数:记忆引擎的根落在本机数据根**之外**。三键即 boot 日志行的字段(`hint` 是一句带两条真路径的人话)。 */
@@ -1,6 +1,6 @@
1
- import { existsSync, realpathSync } from "node:fs";
1
+ import { statSync } from "node:fs";
2
2
  import { dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
3
- import { FileMemoryEngineBackend, readMemoryLedgerForm, resolveMemoryEngineRoot, deriveControlPlaneDir, formatUserScope, formatProjScope, normalizeMemorySpec } from "@sema-agent/core";
3
+ import { FileMemoryEngineBackend, physicalPathOf, readMemoryLedgerForm, resolveMemoryEngineRoot, deriveControlPlaneDir, formatUserScope, formatProjScope, normalizeMemorySpec } from "@sema-agent/core";
4
4
  import { capabilitiesFor, executionLaneOf } from "./execution-lane-caps.js";
5
5
  import { errorCodeOf, errorKindOf } from "./observability/err-text.js";
6
6
  import { assertMemoryScopeWidth } from "./plugins/memory-key-guards.js";
@@ -111,9 +111,21 @@ export function memoryEngineRootFor(config, localRoot) {
111
111
  export function fileMemoryEngineRoot(config, fallbackRoot) {
112
112
  return resolveMemoryEngineRoot(config.memoryEngineDir ?? fallbackRoot);
113
113
  }
114
+ export function presentOnDisk(p) {
115
+ try {
116
+ statSync(p);
117
+ return true;
118
+ }
119
+ catch (e) {
120
+ const code = e?.code;
121
+ if (code === "ENOENT" || code === "ENOTDIR")
122
+ return false;
123
+ throw e;
124
+ }
125
+ }
114
126
  export function canonicalPathOf(p) {
115
- if (isAbsolute(p) && existsSync(p))
116
- return realpathSync.native(p);
127
+ if (isAbsolute(p) && presentOnDisk(p))
128
+ return physicalPathOf(p);
117
129
  const abs = isAbsolute(p) ? p : `${process.cwd()}${sep}${p}`;
118
130
  const { root } = parse(abs);
119
131
  let existing = root;
@@ -133,8 +145,8 @@ export function canonicalPathOf(p) {
133
145
  continue;
134
146
  }
135
147
  const next = join(existing, seg);
136
- if (existsSync(next))
137
- existing = realpathSync.native(next);
148
+ if (presentOnDisk(next))
149
+ existing = physicalPathOf(next);
138
150
  else
139
151
  tail.push(seg);
140
152
  }
@@ -1,4 +1,4 @@
1
- import { type memorySyncReportOf, type MemorySyncTransport } from "@sema-agent/core";
1
+ import { type memorySyncReportOf, type MemorySyncLayerReport, type MemorySyncTransport } from "@sema-agent/core";
2
2
  import type { ServiceConfig } from "./config-types.js";
3
3
  import type { MemoryScopeStores } from "./memory-scope-stores.js";
4
4
  import { type OneTimeMigrationWindow } from "./plugins/one-time-migrations.js";
@@ -48,10 +48,37 @@ export declare function memorySyncCursorDirFor(memoryEngineDir: string): string;
48
48
  * 加一个词 ⇒ {@link wayOutSentence} 的穷尽 switch 编译红(句子先写好,词才上得了 wire)。
49
49
  */
50
50
  export type MemorySyncWayOut = "delete_cursor";
51
- /** ⑦ 一层停驻的读数(读面与运维行同读这一只记录;不带盘路径 —— 路径只进运维行)。 */
51
+ /** 引擎游标拒的 `detail`(轴 + 游标在那一轴上是缺席还是别的值);型取自引擎的同步报告,本仓不另写一份。 */
52
+ type CursorRefusalDetail = NonNullable<Extract<MemorySyncLayerReport, {
53
+ readonly outcome: "refused";
54
+ }>["detail"]>;
55
+ /** 一层为什么停驻(铸记录的输入):`kind` 与引擎读数经记录上 wire,`why` 句只进运维行的 `note`(不在记录里)。 */
56
+ type ParkCause = {
57
+ readonly kind: "cursor_refused";
58
+ readonly detail: CursorRefusalDetail | undefined;
59
+ } | {
60
+ readonly kind: "cursor_unusable";
61
+ readonly why: string;
62
+ };
63
+ /**
64
+ * ⑦ 停驻成因的闭集(词 = {@link ParkCause} 的 `kind`):`cursor_refused` = 同步引擎在游标上拒了这一层(轴与读数见 `axis` / `found`);`cursor_unusable` = 游标文件读不成游标。
65
+ * 与运维行的 `reason`(本轮的触发原因)是两回事 —— 本词答「为什么停」,不答「哪一轮撞上它」。
66
+ */
67
+ export type MemorySyncParkCause = ParkCause["kind"];
68
+ /** 引擎游标拒读数的两个闭集(型取自引擎的同步报告,本仓不另写一份):被拒的是哪一轴;游标在那一轴上是缺席(`absent`)还是绑着别的值(`other`)。 */
69
+ export type MemorySyncCursorAxis = CursorRefusalDetail["axis"];
70
+ export type MemorySyncCursorFound = CursorRefusalDetail["found"];
71
+ /**
72
+ * ⑦ 一层停驻的记录(读面与运维行同读这一只;**整条**就是 `memory-status.memorySync.parked[]` 的条目,所以它不带盘路径 —— 路径只进运维行)。
73
+ * 在场律:`cause` 恒在;`axis` / `found` ⇔ 成因是 `cursor_refused` 且引擎的读数在闭集内(别的成因、读数不在闭集 ⇒ 两键缺席,不是 `undefined` 值)。
74
+ * 加一个键 ⇒ 它就上 wire:自铸登记表的键集(`memorySyncParkedKey`)按本型 `satisfies`,漏登是编译红。唯一铸点 = {@link parkedLayerOf}。
75
+ */
52
76
  export interface MemorySyncParkedLayer {
53
77
  readonly scope: string;
54
78
  readonly wayOut: MemorySyncWayOut;
79
+ readonly cause: MemorySyncParkCause;
80
+ readonly axis?: MemorySyncCursorAxis;
81
+ readonly found?: MemorySyncCursorFound;
55
82
  }
56
83
  /** M31 一次的读数(测试按它断言)。`window: "closed"` ⇒ 一行都没读。 */
57
84
  export interface SyncCursorRelocationM31Report {
@@ -134,4 +161,5 @@ export declare function startMemorySyncRunner(deps: {
134
161
  stores: MemoryScopeStores;
135
162
  log: MemorySyncLog;
136
163
  }): MemorySyncRunner;
164
+ export {};
137
165
  //# sourceMappingURL=memory-sync-client.d.ts.map
@@ -55,6 +55,18 @@ export function memorySyncCursorDirFor(memoryEngineDir) {
55
55
  }
56
56
  const CURSOR_AXES = { scope: true, peer: true, store: true, incarnation: true };
57
57
  const CURSOR_FOUND = { absent: true, other: true };
58
+ function parkedLayerOf(scope, cause, wayOut) {
59
+ switch (cause.kind) {
60
+ case "cursor_refused":
61
+ return Object.freeze({ scope, wayOut, cause: cause.kind, ...(cause.detail !== undefined ? { axis: cause.detail.axis, found: cause.detail.found } : {}) });
62
+ case "cursor_unusable":
63
+ return Object.freeze({ scope, wayOut, cause: cause.kind });
64
+ default: {
65
+ const unhandled = cause;
66
+ throw new Error(`memory sync: unknown park cause ${JSON.stringify(unhandled)}`);
67
+ }
68
+ }
69
+ }
58
70
  function wayOutSentence(wayOut, cursorPath) {
59
71
  switch (wayOut) {
60
72
  case "delete_cursor":
@@ -81,16 +93,12 @@ function parkCauseSentence(cause) {
81
93
  }
82
94
  }
83
95
  class MemorySyncLayerParked extends Error {
84
- scope;
85
96
  cursorPath;
86
- parkCause;
87
- wayOut;
97
+ layer;
88
98
  constructor(scope, cursorPath, parkCause, wayOut = "delete_cursor") {
89
99
  super(`memory sync: layer ${JSON.stringify(scope)} parked — ${parkCauseSentence(parkCause)}; ${wayOutSentence(wayOut, cursorPath)}`);
90
- this.scope = scope;
91
100
  this.cursorPath = cursorPath;
92
- this.parkCause = parkCause;
93
- this.wayOut = wayOut;
101
+ this.layer = parkedLayerOf(scope, parkCause, wayOut);
94
102
  }
95
103
  }
96
104
  function cursorRefusalOf(err) {
@@ -354,8 +362,7 @@ export function createMemorySyncRunner(opts) {
354
362
  let parkedLayers = [];
355
363
  const logLayerFailure = (reason, scope, err) => {
356
364
  if (err instanceof MemorySyncLayerParked) {
357
- const refused = err.parkCause.kind === "cursor_refused" ? err.parkCause.detail : undefined;
358
- opts.log.warn("memory_sync_layer_parked", { reason, scope, cursorPath: err.cursorPath, ...(refused !== undefined ? { axis: refused.axis, found: refused.found } : {}), wayOut: err.wayOut, note: err.message });
365
+ opts.log.warn("memory_sync_layer_parked", { reason, cursorPath: err.cursorPath, ...err.layer, note: err.message });
359
366
  }
360
367
  else {
361
368
  opts.log.warn("memory_sync_layer_failed", { reason, scope, cursorPath: memorySyncCursorPath(memoryEngineDir, scope), err: errorText(err) });
@@ -386,7 +393,7 @@ export function createMemorySyncRunner(opts) {
386
393
  catch (err) {
387
394
  calls.push({ scope, thrown: err });
388
395
  if (err instanceof MemorySyncLayerParked)
389
- parkedNow.push({ scope, wayOut: err.wayOut });
396
+ parkedNow.push(err.layer);
390
397
  logLayerFailure(reason, scope, err);
391
398
  }
392
399
  }