@sema-agent/server 7.150.0 → 7.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/MIGRATION.md +451 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +144 -87
  5. package/deploy/sema-up/README.md +11 -4
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +7 -6
  14. package/deploy/sema-up/kube-up.sh +6 -6
  15. package/deploy/sema-up/lib/flagshape.sh +36 -8
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/deploy/sema-up/machines.example.yaml +3 -1
  19. package/deploy/sema-up/sema-up.sh +22 -16
  20. package/dist/adoption/import.js +3 -3
  21. package/dist/approval-ask-audit-store.d.ts +1 -1
  22. package/dist/approval-ask-machine.d.ts +4 -10
  23. package/dist/approval-ask-retention.d.ts +1 -1
  24. package/dist/approval-card.d.ts +12 -14
  25. package/dist/approval-gate-currency.d.ts +9 -9
  26. package/dist/approval-gate-currency.js +3 -4
  27. package/dist/approval-hmac.d.ts +17 -1
  28. package/dist/approval-hmac.js +7 -1
  29. package/dist/approval-queue-kind.d.ts +1 -1
  30. package/dist/approval.d.ts +2 -2
  31. package/dist/approval.js +2 -2
  32. package/dist/auth-bridge.d.ts +20 -0
  33. package/dist/auth-bridge.js +9 -0
  34. package/dist/background-session-reap.d.ts +1 -1
  35. package/dist/bake-runner/main.d.ts +4 -2
  36. package/dist/bind-host.d.ts +3 -6
  37. package/dist/bind-host.js +4 -7
  38. package/dist/boot/budget-tracing.js +1 -1
  39. package/dist/boot/coordinators.d.ts +1 -1
  40. package/dist/boot/coordinators.js +9 -10
  41. package/dist/boot/device-lane.js +2 -0
  42. package/dist/boot/engine-lease.d.ts +5 -0
  43. package/dist/boot/engine-lease.js +1 -0
  44. package/dist/boot/execution-env.d.ts +9 -14
  45. package/dist/boot/execution-env.js +85 -22
  46. package/dist/boot/execution-lane.js +32 -5
  47. package/dist/boot/late-binds.d.ts +8 -4
  48. package/dist/boot/late-binds.js +7 -1
  49. package/dist/boot/leader.d.ts +31 -30
  50. package/dist/boot/leader.js +38 -28
  51. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  52. package/dist/boot/leg-path-adjudication.js +18 -0
  53. package/dist/boot/memory-consolidation.d.ts +3 -2
  54. package/dist/boot/memory-consolidation.js +6 -6
  55. package/dist/boot/parked-revive-gate.js +3 -15
  56. package/dist/boot/reapers.d.ts +6 -1
  57. package/dist/boot/reapers.js +13 -2
  58. package/dist/boot/resolve-spec.d.ts +3 -3
  59. package/dist/boot/resolve-spec.js +43 -48
  60. package/dist/boot/runner-deps.d.ts +46 -35
  61. package/dist/boot/runner-deps.js +94 -91
  62. package/dist/boot/session-age-out.d.ts +36 -0
  63. package/dist/boot/session-age-out.js +101 -0
  64. package/dist/boot/session-faces.d.ts +5 -14
  65. package/dist/boot/session-faces.js +9 -5
  66. package/dist/boot/shutdown.d.ts +6 -0
  67. package/dist/boot/shutdown.js +10 -4
  68. package/dist/boot/stage-01-config.js +2 -0
  69. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  70. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  71. package/dist/boot/stage-05-execution-env.js +3 -2
  72. package/dist/boot/stage-06-runners.d.ts +9 -4
  73. package/dist/boot/stage-06-runners.js +24 -9
  74. package/dist/boot/stage-07-capability-layer.d.ts +8 -4
  75. package/dist/boot/stage-07-capability-layer.js +3 -2
  76. package/dist/boot/stage-08-reapers.d.ts +8 -4
  77. package/dist/boot/stage-08-reapers.js +4 -2
  78. package/dist/boot/stage-09-leader.d.ts +12 -5
  79. package/dist/boot/stage-09-leader.js +14 -5
  80. package/dist/boot/stage-10-http-server.d.ts +19 -5
  81. package/dist/boot/stage-10-http-server.js +14 -21
  82. package/dist/boot/stores.js +7 -4
  83. package/dist/boot/web-admin.js +5 -8
  84. package/dist/boot/workflow-orchestration.d.ts +7 -2
  85. package/dist/boot/workflow-orchestration.js +24 -7
  86. package/dist/bounded-rotation.d.ts +29 -0
  87. package/dist/bounded-rotation.js +24 -0
  88. package/dist/capabilities/approvals-push.d.ts +3 -3
  89. package/dist/capabilities/scenarios.d.ts +28 -13
  90. package/dist/capabilities/scenarios.js +2 -2
  91. package/dist/capability-facts.d.ts +43 -32
  92. package/dist/capability-facts.js +45 -51
  93. package/dist/card-rule-offers.d.ts +32 -0
  94. package/dist/card-rule-offers.js +130 -0
  95. package/dist/center-credential.d.ts +25 -6
  96. package/dist/center-credential.js +25 -5
  97. package/dist/config-catalog.d.ts +26 -7
  98. package/dist/config-catalog.js +26 -22
  99. package/dist/config-dir-trust.js +4 -2
  100. package/dist/config-invariants.d.ts +20 -8
  101. package/dist/config-invariants.js +55 -12
  102. package/dist/config-lkg.d.ts +5 -19
  103. package/dist/config-lkg.js +8 -62
  104. package/dist/config-provider.d.ts +1 -1
  105. package/dist/config-root-migration.d.ts +2 -2
  106. package/dist/config-types.d.ts +38 -42
  107. package/dist/config.d.ts +58 -7
  108. package/dist/config.js +90 -40
  109. package/dist/control-socket.d.ts +51 -0
  110. package/dist/control-socket.js +115 -0
  111. package/dist/deployment-governance.d.ts +2 -1
  112. package/dist/deployment-shape.d.ts +9 -1
  113. package/dist/deployment-shape.js +2 -1
  114. package/dist/device-protocol.d.ts +5 -4
  115. package/dist/device-protocol.js +1 -1
  116. package/dist/device-ws-hub.d.ts +7 -0
  117. package/dist/device-ws-hub.js +10 -3
  118. package/dist/device-ws-protocol.d.ts +63 -10
  119. package/dist/device-ws-protocol.js +56 -25
  120. package/dist/elicitation.js +2 -2
  121. package/dist/engine-identity.d.ts +19 -7
  122. package/dist/engine-identity.js +10 -2
  123. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  124. package/dist/entry-problems.d.ts +40 -3
  125. package/dist/entry-problems.js +3 -1
  126. package/dist/execution-env-refusal.d.ts +29 -0
  127. package/dist/execution-env-refusal.js +8 -0
  128. package/dist/execution-lane-caps.d.ts +3 -1
  129. package/dist/field-conflict.d.ts +1 -1
  130. package/dist/file-history-capture.d.ts +11 -4
  131. package/dist/file-history-capture.js +9 -6
  132. package/dist/file-history-disclosure.d.ts +7 -5
  133. package/dist/file-history-disclosure.js +7 -5
  134. package/dist/fleet/drain-entry.d.ts +4 -0
  135. package/dist/fleet/engine-signal.d.ts +12 -29
  136. package/dist/fleet/engine-signal.js +1 -7
  137. package/dist/fleet-client.js +2 -5
  138. package/dist/gate-settlement.d.ts +1 -8
  139. package/dist/gate-settlement.js +0 -4
  140. package/dist/history-anchor.js +1 -1
  141. package/dist/hitl-delivery.d.ts +2 -3
  142. package/dist/hitl-delivery.js +0 -2
  143. package/dist/hooks/hook-llm.js +4 -2
  144. package/dist/hooks/hook-runner.d.ts +3 -2
  145. package/dist/hooks/hook-runner.js +18 -3
  146. package/dist/host-decision.d.ts +11 -11
  147. package/dist/host-lsp-manager.d.ts +2 -2
  148. package/dist/http/active-run-conflict.d.ts +35 -2
  149. package/dist/http/active-run-conflict.js +48 -19
  150. package/dist/http/admission.js +17 -2
  151. package/dist/http/approval-sweeps.d.ts +1 -1
  152. package/dist/http/approval-sweeps.js +10 -7
  153. package/dist/http/checkpoint-ctx.d.ts +4 -0
  154. package/dist/http/checkpoint-ctx.js +2 -0
  155. package/dist/http/dispatch.d.ts +8 -3
  156. package/dist/http/dispatch.js +59 -32
  157. package/dist/http/durable-run-leg.js +16 -17
  158. package/dist/http/health-reader.d.ts +16 -9
  159. package/dist/http/health-reader.js +2 -1
  160. package/dist/http/health-self-report.d.ts +9 -1
  161. package/dist/http/health-self-report.js +3 -1
  162. package/dist/http/owner-access.d.ts +33 -14
  163. package/dist/http/owner-access.js +40 -10
  164. package/dist/http/principal-gate.d.ts +49 -21
  165. package/dist/http/principal-gate.js +61 -11
  166. package/dist/http/request-channel.d.ts +23 -0
  167. package/dist/http/request-channel.js +9 -0
  168. package/dist/http/request-guards.js +17 -2
  169. package/dist/http/resume-ctx-read.js +42 -3
  170. package/dist/http/resume-legs.d.ts +4 -3
  171. package/dist/http/resume-legs.js +367 -117
  172. package/dist/http/route-ctx.d.ts +91 -15
  173. package/dist/http/route-ctx.js +17 -0
  174. package/dist/http/route-table.d.ts +5 -1
  175. package/dist/http/route-table.js +4 -0
  176. package/dist/http/routes/admin-config-refresh.js +3 -3
  177. package/dist/http/routes/admin-drain.d.ts +3 -0
  178. package/dist/http/routes/admin-drain.js +7 -7
  179. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  180. package/dist/http/routes/admin-memory-optout.js +3 -3
  181. package/dist/http/routes/adoption.js +3 -5
  182. package/dist/http/routes/agents-roster.js +2 -3
  183. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  184. package/dist/http/routes/approvals-assistant.js +99 -51
  185. package/dist/http/routes/background.d.ts +3 -3
  186. package/dist/http/routes/capabilities.d.ts +4 -0
  187. package/dist/http/routes/capabilities.js +38 -10
  188. package/dist/http/routes/config-catalog.js +2 -2
  189. package/dist/http/routes/devices.js +1 -1
  190. package/dist/http/routes/diagnostics.d.ts +3 -3
  191. package/dist/http/routes/diagnostics.js +19 -7
  192. package/dist/http/routes/fleet.js +10 -8
  193. package/dist/http/routes/images.js +10 -10
  194. package/dist/http/routes/memory-bundle.js +3 -3
  195. package/dist/http/routes/memory-compliance.js +3 -3
  196. package/dist/http/routes/memory-consolidation.js +2 -2
  197. package/dist/http/routes/memory-origin.js +3 -3
  198. package/dist/http/routes/memory-policy.js +2 -2
  199. package/dist/http/routes/observability.js +3 -3
  200. package/dist/http/routes/projects.d.ts +3 -2
  201. package/dist/http/routes/projects.js +4 -5
  202. package/dist/http/routes/retention-ops.js +3 -3
  203. package/dist/http/routes/rules.js +5 -5
  204. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  205. package/dist/http/routes/run-permission-mode.js +2 -2
  206. package/dist/http/routes/runs.d.ts +4 -9
  207. package/dist/http/routes/runs.js +171 -65
  208. package/dist/http/routes/session-sync.d.ts +22 -9
  209. package/dist/http/routes/session-sync.js +204 -107
  210. package/dist/http/routes/sessions-list.js +13 -7
  211. package/dist/http/routes/sessions.js +30 -15
  212. package/dist/http/routes/tasks.js +46 -41
  213. package/dist/http/routes/trace-usage.js +2 -2
  214. package/dist/http/routes/workflows.js +1 -1
  215. package/dist/http/server.d.ts +30 -30
  216. package/dist/http/server.js +16 -4
  217. package/dist/http/submit-ctx.d.ts +1 -1
  218. package/dist/http/submit-ctx.js +7 -4
  219. package/dist/http/wire-types.d.ts +14 -4
  220. package/dist/human-facing-args.d.ts +33 -0
  221. package/dist/human-facing-args.js +33 -0
  222. package/dist/identity-source.d.ts +20 -3
  223. package/dist/identity-source.js +14 -0
  224. package/dist/index.d.ts +5 -1
  225. package/dist/k8s-api-credentials.d.ts +29 -0
  226. package/dist/k8s-api-credentials.js +25 -0
  227. package/dist/lane-home-probe.d.ts +3 -7
  228. package/dist/lane-home-probe.js +2 -2
  229. package/dist/leader/diffup.d.ts +19 -0
  230. package/dist/leader/diffup.js +7 -0
  231. package/dist/leader/leader.d.ts +116 -11
  232. package/dist/leader/leader.js +69 -5
  233. package/dist/leader/repair-wire.js +2 -2
  234. package/dist/leader/run-entry.d.ts +2 -1
  235. package/dist/leader/run-entry.js +1 -1
  236. package/dist/leader/wire.d.ts +42 -132
  237. package/dist/leader/wire.js +81 -67
  238. package/dist/leg-facts.d.ts +13 -5
  239. package/dist/leg-facts.js +2 -1
  240. package/dist/memory-scope.d.ts +23 -11
  241. package/dist/memory-scope.js +18 -6
  242. package/dist/memory-sync-client.d.ts +30 -2
  243. package/dist/memory-sync-client.js +16 -9
  244. package/dist/model-entry-headers.d.ts +9 -10
  245. package/dist/model-entry-headers.js +0 -4
  246. package/dist/model-entry-refusal.d.ts +7 -4
  247. package/dist/model-entry-refusal.js +11 -5
  248. package/dist/model-plane-face.d.ts +1 -1
  249. package/dist/model-plane-face.js +3 -1
  250. package/dist/model-route-endpoint.d.ts +13 -7
  251. package/dist/model-route-endpoint.js +14 -11
  252. package/dist/model-select.d.ts +22 -0
  253. package/dist/model-select.js +9 -0
  254. package/dist/model-unreachable-notice.d.ts +11 -0
  255. package/dist/model-unreachable-notice.js +4 -4
  256. package/dist/object-store-buckets.d.ts +640 -6
  257. package/dist/object-store-buckets.js +166 -0
  258. package/dist/observability/err-text.d.ts +7 -0
  259. package/dist/observability/err-text.js +5 -0
  260. package/dist/observability/fail-open.d.ts +25 -17
  261. package/dist/observability/fail-open.js +25 -17
  262. package/dist/observability/logger.js +3 -1
  263. package/dist/observability/metrics.js +1 -0
  264. package/dist/operator-roster.d.ts +68 -0
  265. package/dist/operator-roster.js +32 -0
  266. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  267. package/dist/orchestration/workflow-notify-journal.js +12 -1
  268. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  269. package/dist/orchestration/workflow-park-decision.js +49 -10
  270. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  271. package/dist/orchestration/workflow-park-holder.js +98 -0
  272. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  273. package/dist/orchestration/workflow-record-fence.js +42 -0
  274. package/dist/outbound-dispatcher.d.ts +71 -8
  275. package/dist/outbound-dispatcher.js +48 -7
  276. package/dist/owner-faces.d.ts +2 -2
  277. package/dist/parked-decide.d.ts +106 -55
  278. package/dist/parked-decide.js +153 -117
  279. package/dist/peer-directory.d.ts +2 -2
  280. package/dist/peer-inbound-face.d.ts +2 -6
  281. package/dist/peer-inbound-face.js +0 -3
  282. package/dist/permission-mode-admission.d.ts +74 -5
  283. package/dist/permission-mode-admission.js +56 -3
  284. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  285. package/dist/plugins/adoption-log-sql.js +7 -1
  286. package/dist/plugins/approval-ask-store-file.d.ts +14 -2
  287. package/dist/plugins/approval-ask-store-file.js +11 -0
  288. package/dist/plugins/approval-ask-store-memory.d.ts +10 -1
  289. package/dist/plugins/approval-ask-store-memory.js +35 -10
  290. package/dist/plugins/approval-ask-store-sql.d.ts +69 -4
  291. package/dist/plugins/approval-ask-store-sql.js +45 -5
  292. package/dist/plugins/approval-exemption-store.js +3 -0
  293. package/dist/plugins/approval-nonce-store.js +2 -0
  294. package/dist/plugins/blob-backend.d.ts +83 -7
  295. package/dist/plugins/blob-backend.js +57 -6
  296. package/dist/plugins/breaker-state-sql.js +2 -0
  297. package/dist/plugins/caching-session-store.d.ts +9 -15
  298. package/dist/plugins/caching-session-store.js +6 -0
  299. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  300. package/dist/plugins/checkpoint-index-columns.js +3 -6
  301. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  302. package/dist/plugins/checkpoint-store-face.js +134 -55
  303. package/dist/plugins/device-store-sql.js +6 -0
  304. package/dist/plugins/error-origin.d.ts +18 -0
  305. package/dist/plugins/error-origin.js +10 -0
  306. package/dist/plugins/execution-placement-sql.js +6 -6
  307. package/dist/plugins/image-bake-store-sql.js +6 -0
  308. package/dist/plugins/image-index-sql.js +4 -0
  309. package/dist/plugins/landed-attendants.d.ts +212 -0
  310. package/dist/plugins/landed-attendants.js +161 -0
  311. package/dist/plugins/leader-run-store-sql.js +4 -0
  312. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  313. package/dist/plugins/local-checkpoint-store.js +38 -49
  314. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  315. package/dist/plugins/local-session-live-reference.js +39 -0
  316. package/dist/plugins/local-session-store.d.ts +71 -33
  317. package/dist/plugins/local-session-store.js +129 -27
  318. package/dist/plugins/memory-engine-pg.js +4 -0
  319. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  320. package/dist/plugins/memory-engine-tidb.js +4 -0
  321. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  322. package/dist/plugins/memory-sync-store-pg.js +5 -0
  323. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  324. package/dist/plugins/one-time-migrations.d.ts +104 -80
  325. package/dist/plugins/one-time-migrations.js +226 -132
  326. package/dist/plugins/org-delivery-quota-store.js +4 -1
  327. package/dist/plugins/outcome-ledger-sql.js +2 -0
  328. package/dist/plugins/permission-rule-store-sql.js +11 -4
  329. package/dist/plugins/pg-cost-quota.js +4 -0
  330. package/dist/plugins/pg-pool.js +35 -10
  331. package/dist/plugins/pg-rate-limiter.js +2 -0
  332. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  333. package/dist/plugins/posix-shell-fs.js +4 -1
  334. package/dist/plugins/remote-env-adb.d.ts +19 -15
  335. package/dist/plugins/remote-env-adb.js +41 -15
  336. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  337. package/dist/plugins/remote-env-connect-seat.js +72 -0
  338. package/dist/plugins/remote-env-device.d.ts +22 -5
  339. package/dist/plugins/remote-env-device.js +106 -8
  340. package/dist/plugins/remote-env-e2b.d.ts +15 -6
  341. package/dist/plugins/remote-env-e2b.js +42 -32
  342. package/dist/plugins/remote-env-file-error.js +6 -2
  343. package/dist/plugins/remote-env-host.d.ts +46 -10
  344. package/dist/plugins/remote-env-host.js +124 -52
  345. package/dist/plugins/remote-env-k8s.d.ts +109 -41
  346. package/dist/plugins/remote-env-k8s.js +160 -54
  347. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  348. package/dist/plugins/remote-env-local-docker.js +34 -41
  349. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  350. package/dist/plugins/remote-env-ssh.js +60 -59
  351. package/dist/plugins/remote-shell.d.ts +98 -1
  352. package/dist/plugins/remote-shell.js +218 -0
  353. package/dist/plugins/replica-registration.d.ts +1 -1
  354. package/dist/plugins/replica-registration.js +1 -1
  355. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  356. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  357. package/dist/plugins/retention-lane-store-sql.js +4 -0
  358. package/dist/plugins/retention-sql.d.ts +20 -2
  359. package/dist/plugins/retention-sql.js +11 -0
  360. package/dist/plugins/run-store-sql.d.ts +21 -2
  361. package/dist/plugins/run-store-sql.js +31 -7
  362. package/dist/plugins/s3-presign.d.ts +23 -0
  363. package/dist/plugins/s3-presign.js +37 -3
  364. package/dist/plugins/scenario-prefix-switch-m42.d.ts +1 -1
  365. package/dist/plugins/scenario-prefix-switch-m42.js +2 -2
  366. package/dist/plugins/scheduler-support.d.ts +2 -2
  367. package/dist/plugins/scheduler-support.js +0 -3
  368. package/dist/plugins/schema-consistency.d.ts +4 -2
  369. package/dist/plugins/schema-consistency.js +19 -2
  370. package/dist/plugins/schema-indexes.js +2 -0
  371. package/dist/plugins/send-file-ledger.d.ts +2 -2
  372. package/dist/plugins/send-file-ledger.js +5 -2
  373. package/dist/plugins/send-user-file.d.ts +3 -4
  374. package/dist/plugins/send-user-file.js +56 -52
  375. package/dist/plugins/serving-requirement.d.ts +26 -7
  376. package/dist/plugins/serving-requirement.js +11 -4
  377. package/dist/plugins/session-birth.d.ts +6 -2
  378. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  379. package/dist/plugins/session-blob-claim-token.js +20 -0
  380. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  381. package/dist/plugins/session-blob-namespace.js +116 -0
  382. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  383. package/dist/plugins/session-ext-table.d.ts +14 -1
  384. package/dist/plugins/session-ext-table.js +5 -1
  385. package/dist/plugins/session-row-sql.d.ts +49 -2
  386. package/dist/plugins/session-row-sql.js +56 -13
  387. package/dist/plugins/session-store-sql.d.ts +34 -18
  388. package/dist/plugins/session-store-sql.js +98 -17
  389. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  390. package/dist/plugins/shared-memory-store-sql.js +6 -2
  391. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  392. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  393. package/dist/plugins/sql-driver.d.ts +2 -1
  394. package/dist/plugins/sql-driver.js +18 -3
  395. package/dist/plugins/sql-errors.d.ts +11 -6
  396. package/dist/plugins/sql-errors.js +5 -6
  397. package/dist/plugins/sql-json-column.d.ts +1 -1
  398. package/dist/plugins/stop-then-start-sentence.d.ts +10 -4
  399. package/dist/plugins/stop-then-start-sentence.js +14 -10
  400. package/dist/plugins/stop-then-start.d.ts +109 -0
  401. package/dist/plugins/stop-then-start.js +104 -0
  402. package/dist/plugins/store-backend.d.ts +84 -15
  403. package/dist/plugins/store-backend.js +236 -72
  404. package/dist/plugins/store-boundary.d.ts +57 -0
  405. package/dist/plugins/store-boundary.js +139 -0
  406. package/dist/plugins/store-contracts.d.ts +17 -0
  407. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  408. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  409. package/dist/plugins/store-fault.d.ts +26 -7
  410. package/dist/plugins/store-fault.js +18 -2
  411. package/dist/plugins/task-attachment-store.d.ts +2 -1
  412. package/dist/plugins/task-attachment-store.js +14 -1
  413. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  414. package/dist/plugins/task-list-store-sql.js +10 -8
  415. package/dist/plugins/tidb-cost-quota.js +4 -0
  416. package/dist/plugins/tidb-pool.js +21 -25
  417. package/dist/plugins/tidb-rate-limiter.js +4 -0
  418. package/dist/plugins/user-input-ledger-sql.js +4 -0
  419. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  420. package/dist/plugins/workflow-run-store-sql.js +64 -4
  421. package/dist/plugins/workspace-custody.d.ts +4 -3
  422. package/dist/plugins/workspace-fill.d.ts +4 -7
  423. package/dist/plugins/workspace-fill.js +2 -1
  424. package/dist/plugins/write-behind-counter.js +5 -0
  425. package/dist/project-context.d.ts +0 -2
  426. package/dist/project-context.js +4 -8
  427. package/dist/project-registry.d.ts +46 -0
  428. package/dist/project-registry.js +44 -0
  429. package/dist/question.d.ts +2 -1
  430. package/dist/question.js +5 -13
  431. package/dist/request-form.d.ts +6 -1
  432. package/dist/request-form.js +4 -1
  433. package/dist/request-key-closure.js +1 -1
  434. package/dist/request-value-closure.d.ts +4 -0
  435. package/dist/request-value-closure.js +10 -0
  436. package/dist/rule-issue-reading.d.ts +1 -1
  437. package/dist/rules-consent.d.ts +1 -1
  438. package/dist/run-acceptance.d.ts +3 -2
  439. package/dist/run-acceptance.js +4 -6
  440. package/dist/run-local.js +9 -9
  441. package/dist/runs.d.ts +54 -16
  442. package/dist/runs.js +67 -13
  443. package/dist/runtime-governance.d.ts +5 -4
  444. package/dist/security.d.ts +30 -32
  445. package/dist/security.js +41 -7
  446. package/dist/sema-config-dir.d.ts +2 -1
  447. package/dist/server-secret-env.d.ts +12 -10
  448. package/dist/server-secret-env.js +24 -15
  449. package/dist/session-bindings.d.ts +82 -0
  450. package/dist/session-bindings.js +18 -0
  451. package/dist/session-children-retire.d.ts +2 -2
  452. package/dist/session-children-retire.js +2 -6
  453. package/dist/session-deletion.d.ts +16 -1
  454. package/dist/session-error-wire.d.ts +3 -3
  455. package/dist/session-error-wire.js +3 -3
  456. package/dist/session-incarnation.d.ts +10 -0
  457. package/dist/session-incarnation.js +10 -1
  458. package/dist/session-kind.d.ts +57 -0
  459. package/dist/session-kind.js +22 -0
  460. package/dist/session-row.d.ts +21 -1
  461. package/dist/session-row.js +7 -1
  462. package/dist/session-sync-kernel.d.ts +24 -14
  463. package/dist/session-sync-kernel.js +3 -6
  464. package/dist/session-sync.d.ts +25 -103
  465. package/dist/session-sync.js +14 -76
  466. package/dist/session-titler.d.ts +10 -3
  467. package/dist/session-titler.js +19 -6
  468. package/dist/ssh-host-key.d.ts +5 -0
  469. package/dist/ssh-host-key.js +3 -0
  470. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  471. package/dist/stores-sql/blob-index-sql.js +40 -21
  472. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  473. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  474. package/dist/stores-sql/file-history-store-sql.d.ts +113 -15
  475. package/dist/stores-sql/file-history-store-sql.js +205 -95
  476. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  477. package/dist/stores-sql/pg-session-storage.js +37 -13
  478. package/dist/stores-sql/retention-store-sql.d.ts +1 -9
  479. package/dist/stores-sql/retention-store-sql.js +5 -19
  480. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  481. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  482. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  483. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  484. package/dist/stores-sql/tidb-session-store.js +37 -13
  485. package/dist/submission-exit.d.ts +3 -2
  486. package/dist/submission-exit.js +9 -1
  487. package/dist/task-cwd.d.ts +2 -2
  488. package/dist/task-settings.d.ts +7 -5
  489. package/dist/task-settings.js +3 -3
  490. package/dist/terminal.d.ts +33 -2
  491. package/dist/terminal.js +139 -9
  492. package/dist/tool-approval.d.ts +465 -507
  493. package/dist/tool-approval.js +606 -1222
  494. package/dist/trace/core-keyset-guard.d.ts +1 -1
  495. package/dist/trace/ledger-events.d.ts +3 -3
  496. package/dist/trace/project.d.ts +2 -3
  497. package/dist/trace/redact.js +3 -2
  498. package/dist/trace/self-minted-wire.d.ts +571 -178
  499. package/dist/trace/self-minted-wire.js +189 -56
  500. package/dist/web-admin-client/apply-effective.js +2 -2
  501. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  502. package/dist/web-admin-client/read-warnings.js +1 -1
  503. package/dist/web-admin-client/types.d.ts +1 -1
  504. package/dist/workspace-space.d.ts +10 -4
  505. package/dist/workspace-space.js +4 -1
  506. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +79 -28
  507. package/package.json +7 -3
  508. package/scripts/embed-minimal.mjs +3 -3
  509. package/wire-changes/server@7.151.0.json +762 -0
  510. package/wire-changes/server@7.152.0.json +900 -0
  511. package/dist/config-d-migration.d.ts +0 -37
  512. package/dist/config-d-migration.js +0 -60
  513. package/dist/http/session-inherit-env.d.ts +0 -36
  514. package/dist/http/session-inherit-env.js +0 -6
@@ -1,11 +1,11 @@
1
1
  import { writeLogText } from "../observability/logger.js";
2
2
  import { spawn } from "node:child_process";
3
3
  import os from "node:os";
4
- import path from "node:path";
4
+ import path, {} from "node:path";
5
5
  import { anchoredPath, anchorUnder, joinedPath } from "./exec-path-law.js";
6
6
  import fs from "node:fs/promises";
7
7
  import { randomBytes } from "node:crypto";
8
- import { openSync, closeSync, readSync, statSync, truncateSync, unlinkSync, mkdirSync, rmdirSync, mkdtempSync, existsSync, realpathSync, accessSync, constants as FS_CONST } from "node:fs";
8
+ import { openSync, closeSync, readSync, statSync, truncateSync, unlinkSync, mkdirSync, rmdirSync, mkdtempSync, existsSync, accessSync, renameSync, constants as FS_CONST } from "node:fs";
9
9
  import { StringDecoder } from "node:string_decoder";
10
10
  import { armPipeDestroyGrace, numEnvOr } from "./remote-shell.js";
11
11
  import { buildLivenessCut, commandBoundsOf } from "../exec-bounds.js";
@@ -13,7 +13,7 @@ import { buildCapturedOutput, createCutError } from "../exec-cut.js";
13
13
  import { hostBackgroundShellEnabled, hostExecSpoolEnabled } from "../config.js";
14
14
  import { IS_WIN32, resolveHostShell, hostShell, pinHostShell, spawnGroupOptions, killTreeHard, killTreeSoft, hardKillGroupNow, collapseWin32EnvKeys, adoptHostForegroundChild } from "./host-platform.js";
15
15
  import { BackgroundShellManager, seedMemStream, feedMemStream, drainMemStream } from "./background-shell-support.js";
16
- import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, walkSymlinkChain, markTruncated, SchedulerError, BackgroundShellError, physicalPathOf as kernelRealPathOf, } from "@sema-agent/core";
16
+ import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, walkSymlinkChain, markTruncated, SchedulerError, BackgroundShellError, physicalPathOf, } from "@sema-agent/core";
17
17
  import { capabilitiesFor } from "../execution-lane-caps.js";
18
18
  import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
19
19
  import { LaneHomeSeat, laneHomeRefusal } from "../lane-home-probe.js";
@@ -21,7 +21,10 @@ import { composeHostSubprocessEnv, hostSubprocessEnv, withheldFromHostSubprocess
21
21
  import { nameTooLongCode } from "./remote-env-file-error.js";
22
22
  import { trackEphemeralHostWorkspace, untrackEphemeralHostWorkspace } from "./host-workspace-registry.js";
23
23
  import { createWorkspaceCustody } from "./workspace-custody.js";
24
+ import { canonicalPathOf, pathIsWithin, presentOnDisk } from "../memory-scope.js";
25
+ import { errorCodeOf } from "../observability/err-text.js";
24
26
  import { OWNER_ONLY_FILE_MODE } from "./owner-only-file-mode.js";
27
+ import { createConnectSeat, withdrawOnAbort } from "./remote-env-connect-seat.js";
25
28
  const PROVIDER = "host";
26
29
  const DEFAULT_COMMAND_TIMEOUT_MS = 30 * 60_000;
27
30
  const inflightFsDrainWaitMs = () => numEnvOr("HOST_FS_DRAIN_WAIT_MS", 10_000, 1);
@@ -39,6 +42,7 @@ const unsupported = (op) => ({
39
42
  });
40
43
  const BORROWED = Object.freeze({ kind: "borrowed" });
41
44
  const RELEASED = Object.freeze({ kind: "released" });
45
+ const NO_ROOTS = Object.freeze([]);
42
46
  const UNSUPPORTED_SCHEDULER_CAPS = {
43
47
  supported: false,
44
48
  maxScheduledPerScope: 0,
@@ -130,20 +134,26 @@ export class RemoteHostExecutionEnv {
130
134
  return this.spoolRootDir;
131
135
  }
132
136
  tenure;
137
+ hasLeft = false;
133
138
  preparing;
139
+ seat = createConnectSeat({
140
+ live: () => (this.prepared && !this.destroyed ? this.handle : undefined),
141
+ inFlight: () => (this.prepared ? undefined : this.preparing?.then(() => this.preparedAnswer(), (e) => this.prepareFailed(e))),
142
+ establish: (config) => withdrawOnAbort(this.ensurePrepared().then(() => this.preparedAnswer(), (e) => this.prepareFailed(e)), config?.abortSignal),
143
+ });
134
144
  handle;
135
145
  constructor(config = {}) {
136
146
  if (config.workspaceDir) {
137
- this.workspaceDir = path.resolve(config.workspaceDir);
147
+ this.workspaceDir = hostSeatPath(config.workspaceDir);
138
148
  const shared = config.custody?.sharedRoot;
139
- this.tenure = shared !== undefined ? { kind: "held", root: path.resolve(shared) } : BORROWED;
149
+ this.tenure = shared !== undefined ? { kind: "held", roots: [hostSeatPath(shared)] } : BORROWED;
140
150
  }
141
151
  else {
142
- const base = config.workspaceBase ?? os.tmpdir();
152
+ const base = hostSeatPath(config.workspaceBase ?? os.tmpdir());
143
153
  const id = config.id ?? randomBytes(6).toString("hex");
144
154
  const suffix = randomBytes(4).toString("hex");
145
- this.workspaceDir = path.resolve(base, `sema-host-${sanitizeId(id)}-${suffix}`);
146
- this.tenure = { kind: "held", root: this.workspaceDir };
155
+ this.workspaceDir = anchorUnder(path, base, `sema-host-${sanitizeId(id)}-${suffix}`);
156
+ this.tenure = { kind: "held", roots: [this.workspaceDir] };
147
157
  }
148
158
  const inheritEnvProblem = inheritEnvPolicyProblem(config.inheritEnv);
149
159
  if (inheritEnvProblem !== undefined)
@@ -171,11 +181,18 @@ export class RemoteHostExecutionEnv {
171
181
  return this.teardownSettled;
172
182
  }
173
183
  leftover = undefined;
184
+ get left() {
185
+ return this.hasLeft;
186
+ }
174
187
  get settled() {
175
- return this.teardownSettled && this.tenure.kind !== "held";
188
+ return this.teardownSettled && this.hasLeft;
189
+ }
190
+ get heldRoots() {
191
+ return this.tenure.kind === "held" ? this.tenure.roots : NO_ROOTS;
176
192
  }
177
- get heldWorkspace() {
178
- return this.tenure.kind === "held" ? this.tenure.root : undefined;
193
+ assumeRoot(root) {
194
+ this.tenure = { kind: "held", roots: this.tenure.kind === "held" ? [...this.tenure.roots, root] : [root] };
195
+ trackUnlessAbsent(root);
179
196
  }
180
197
  workspaceHandle() {
181
198
  return this.handle;
@@ -185,18 +202,14 @@ export class RemoteHostExecutionEnv {
185
202
  return unsupported("connect(snapshotId)");
186
203
  if (this.destroyed)
187
204
  return { ok: false, error: new RemoteExecutionError("connect_failed", "execution env already destroyed") };
188
- if (config?.abortSignal?.aborted)
189
- return { ok: false, error: new RemoteExecutionError("aborted", "connect aborted") };
190
- try {
191
- await this.ensurePrepared();
192
- }
193
- catch (e) {
194
- return { ok: false, error: new RemoteExecutionError("connect_failed", `failed to create host workspace ${this.workspaceDir}: ${errMsg(e)}`, asError(e)) };
195
- }
196
- if (config?.secrets?.length) {
197
- }
205
+ return this.seat.connect(config);
206
+ }
207
+ preparedAnswer() {
198
208
  return ok(this.handle);
199
209
  }
210
+ prepareFailed(e) {
211
+ return { ok: false, error: new RemoteExecutionError("connect_failed", `failed to create host workspace ${this.workspaceDir}: ${errMsg(e)}`, asError(e)) };
212
+ }
200
213
  async suspendVM(_options) {
201
214
  return unsupported("suspendVM");
202
215
  }
@@ -240,17 +253,37 @@ export class RemoteHostExecutionEnv {
240
253
  catch { }
241
254
  this.spoolRootDir = undefined;
242
255
  }
256
+ this.hasLeft = true;
243
257
  const tenure = this.tenure;
244
258
  if (tenure.kind !== "held")
245
259
  return;
246
260
  this.tenure = RELEASED;
247
- if (this.cfg.custody?.heldElsewhere(this, tenure.root) === true)
248
- return;
249
- try {
250
- await fs.rm(tenure.root, { recursive: true, force: true });
251
- untrackEphemeralHostWorkspace(tenure.root);
261
+ const tombs = [];
262
+ for (const root of tenure.roots) {
263
+ if (this.cfg.custody?.passOn(this, root) === true)
264
+ continue;
265
+ const tomb = removalTombOf(root);
266
+ try {
267
+ renameSync(root, tomb);
268
+ }
269
+ catch (e) {
270
+ if (e?.code === "ENOENT")
271
+ untrackEphemeralHostWorkspace(root);
272
+ else
273
+ trackUnlessAbsent(root);
274
+ continue;
275
+ }
276
+ trackEphemeralHostWorkspace(tomb);
277
+ untrackEphemeralHostWorkspace(root);
278
+ tombs.push(tomb);
252
279
  }
253
- catch {
280
+ for (const tomb of tombs) {
281
+ try {
282
+ await fs.rm(tomb, { recursive: true, force: true });
283
+ untrackEphemeralHostWorkspace(tomb);
284
+ }
285
+ catch {
286
+ }
254
287
  }
255
288
  }
256
289
  async cleanup() {
@@ -1294,8 +1327,8 @@ export class RemoteHostExecutionEnv {
1294
1327
  .mkdir(this.workspaceDir, { recursive: true })
1295
1328
  .then(() => {
1296
1329
  this.prepared = true;
1297
- if (this.tenure.kind === "held")
1298
- trackEphemeralHostWorkspace(this.tenure.root);
1330
+ for (const root of this.heldRoots)
1331
+ trackUnlessAbsent(root);
1299
1332
  })
1300
1333
  .catch((e) => {
1301
1334
  this.preparing = undefined;
@@ -1327,7 +1360,7 @@ export class RemoteHostExecutionEnv {
1327
1360
  return false;
1328
1361
  const real = (x) => {
1329
1362
  try {
1330
- return kernelRealPathOf(x);
1363
+ return physicalPathOf(x);
1331
1364
  }
1332
1365
  catch {
1333
1366
  return undefined;
@@ -1408,6 +1441,13 @@ export class RemoteHostExecutionEnv {
1408
1441
  return new FileError("unknown", msg, p);
1409
1442
  }
1410
1443
  }
1444
+ export function hostSeatPath(p, pathApi = path) {
1445
+ if (pathApi.sep === "\\" && /^[A-Za-z]:(?![\\/])/.test(p)) {
1446
+ const driveCwd = pathApi.resolve(p.slice(0, 2));
1447
+ return p.length === 2 ? driveCwd : anchorUnder(pathApi, driveCwd, p.slice(2));
1448
+ }
1449
+ return anchoredPath(pathApi, process.cwd(), p);
1450
+ }
1411
1451
  function sanitizeId(id) {
1412
1452
  return id.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 64) || "task";
1413
1453
  }
@@ -1427,39 +1467,71 @@ function asError(e) {
1427
1467
  function signalNumber(signal) {
1428
1468
  return os.constants.signals[signal];
1429
1469
  }
1470
+ function heldRootContaining(custody, dir) {
1471
+ const found = [];
1472
+ custody.holder((m) => {
1473
+ const root = m.heldRoots.find((r) => pathIsWithin(r, dir, canonicalPathOf));
1474
+ if (root !== undefined)
1475
+ found.push(root);
1476
+ return root !== undefined;
1477
+ });
1478
+ return found[0];
1479
+ }
1480
+ function passOnRoot(custody, self, root) {
1481
+ if (custody.holder((m) => m !== self && m.heldRoots.includes(root)) !== undefined)
1482
+ return true;
1483
+ const unreadable = [];
1484
+ const occupant = custody.holder((m) => {
1485
+ if (m === self || m.left)
1486
+ return false;
1487
+ try {
1488
+ return pathIsWithin(root, m.cwd, canonicalPathOf);
1489
+ }
1490
+ catch (error) {
1491
+ unreadable.push({ dir: m.cwd, error });
1492
+ return false;
1493
+ }
1494
+ });
1495
+ if (occupant !== undefined) {
1496
+ occupant.assumeRoot(root);
1497
+ return true;
1498
+ }
1499
+ const first = unreadable[0];
1500
+ if (first === undefined)
1501
+ return false;
1502
+ trackUnlessAbsent(root);
1503
+ writeLogText("stderr", `RemoteHostExecutionEnv: kept ${root} instead of removing it — could not read whether the working directory ${first.dir} lies inside it ` +
1504
+ `(${errorCodeOf(first.error) ?? "unreadable"}); nobody takes it over, and the exit-time sweep removes it`);
1505
+ return true;
1506
+ }
1507
+ function trackUnlessAbsent(root) {
1508
+ let absent;
1509
+ try {
1510
+ absent = !presentOnDisk(root);
1511
+ }
1512
+ catch {
1513
+ absent = false;
1514
+ }
1515
+ if (!absent)
1516
+ trackEphemeralHostWorkspace(root);
1517
+ }
1518
+ function removalTombOf(root) {
1519
+ return anchorUnder(path, path.dirname(root), `.${path.basename(root)}.removing-${randomBytes(4).toString("hex")}`);
1520
+ }
1430
1521
  export function hostExecutionEnvFactory(config = {}, legOf = () => ({})) {
1431
1522
  const custody = createWorkspaceCustody();
1432
- const heldElsewhere = (self, root) => custody.holder((m) => m !== self && m.heldWorkspace === root) !== undefined;
1523
+ const passOn = (self, root) => passOnRoot(custody, self, root);
1433
1524
  return (ctx) => {
1434
1525
  const { minted, ...leg } = legOf(ctx);
1435
1526
  const identity = ctx.taskId ?? ctx.sessionId;
1436
1527
  return custody.envOf(identity, () => {
1437
1528
  const dir = leg.workspaceDir ?? config.workspaceDir;
1438
- const sharedRoot = dir === undefined ? undefined : custody.holder((m) => m.heldWorkspace !== undefined && dirWithin(dir, m.heldWorkspace))?.heldWorkspace;
1439
- const env = new RemoteHostExecutionEnv({ ...config, ...leg, id: config.id ?? identity, custody: { heldElsewhere, ...(sharedRoot !== undefined ? { sharedRoot } : {}) } });
1529
+ const sharedRoot = dir === undefined ? undefined : heldRootContaining(custody, hostSeatPath(dir));
1530
+ const env = new RemoteHostExecutionEnv({ ...config, ...leg, id: config.id ?? identity, custody: { passOn, ...(sharedRoot !== undefined ? { sharedRoot } : {}) } });
1440
1531
  minted?.(env);
1441
1532
  return env;
1442
1533
  });
1443
1534
  };
1444
1535
  }
1445
- function dirWithin(dir, root) {
1446
- const inside = (d, r) => {
1447
- const rel = path.relative(r, d);
1448
- return rel === "" || (rel.split(path.sep)[0] !== ".." && !path.isAbsolute(rel));
1449
- };
1450
- return inside(path.resolve(dir), path.resolve(root)) || inside(physicalPathOf(dir), physicalPathOf(root));
1451
- }
1452
- function physicalPathOf(p) {
1453
- let head = path.resolve(p);
1454
- const tail = [];
1455
- while (!existsSync(head)) {
1456
- const up = path.dirname(head);
1457
- if (up === head)
1458
- return path.resolve(p);
1459
- tail.unshift(path.basename(head));
1460
- head = up;
1461
- }
1462
- return path.join(realpathSync(head), ...tail);
1463
- }
1464
1536
  export { localDockerExecutionEnvFactory, RemoteLocalDockerExecutionEnv } from "./remote-env-local-docker.js";
1465
1537
  //# sourceMappingURL=remote-env-host.js.map
@@ -2,13 +2,46 @@ import { type SpaceReclaimer, type WorkspaceSpacePolicy, type CacheReclaimReason
2
2
  import { type SpaceCommitFence } from "../workspace-space-commit.js";
3
3
  import { type CacheMissMemory, type WorkspaceCacheCapability } from "../workspace-cache.js";
4
4
  import { type SandboxEgressGap, type SandboxIpv6 } from "../sandbox-egress-policy.js";
5
- import { FileError, ExecutionError, RemoteExecutionError, type ExecutionEnv, type ExecResult, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, type BackgroundShellCapability, type BackgroundShellId, type BackgroundShellError, type BackgroundSpawnOptions, type BackgroundPoll, type ExecutionEnvCapabilities } from "@sema-agent/core";
5
+ import { type K8sApiCredentialFact } from "../k8s-api-credentials.js";
6
+ import { FileError, ExecutionError, RemoteExecutionError, type ExecutionEnv, type ExecResult, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type BoundFileObject, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, type BackgroundShellCapability, type BackgroundShellId, type BackgroundShellError, type BackgroundSpawnOptions, type BackgroundPoll, type ExecutionEnvCapabilities } from "@sema-agent/core";
6
7
  import { type SandboxReadFloorKnob } from "../execution-lane-caps.js";
7
8
  import { type SandboxReadFloor } from "./sandbox-read-floor.js";
8
9
  import type { PodSpecPatch } from "./k8s-exec-protocol.js";
9
10
  import { type LaneHomeConfig } from "../lane-home-probe.js";
11
+ import { type ConnectResult } from "./remote-env-connect-seat.js";
10
12
  type ExecOpts = Parameters<ExecutionEnv["exec"]>[1];
11
13
  export { buildBgRunnerScript, buildBgLauncherScript, buildBgPollScript, buildBgKillScript, buildBgDisposeScript, buildDetachCapableExec, buildKillAllScript, parseBgPollOutput, type ParsedBgPoll, } from "./k8s-bg-scripts.js";
14
+ /**
15
+ * This process's in-cluster identity: the platform's `KUBERNETES_SERVICE_*` and the mounted service-account files. `readMounted` throws when the file is unreadable.
16
+ * (In this file a bare `read(` names a control-plane GET — the RBAC table's source reader classifies every one — so the mount reader carries its own name.)
17
+ */
18
+ export interface InClusterIdentity {
19
+ readonly host: string | undefined;
20
+ readonly port: string | undefined;
21
+ readMounted(file: "token" | "ca.crt"): string;
22
+ }
23
+ /** What the control plane can be reached with — or the ONE missing fact (with the adapter code its request-time refusal carries). */
24
+ export type K8sApiAccess = {
25
+ readonly ok: true;
26
+ readonly apiUrl: string;
27
+ readonly token: string;
28
+ readonly ca: string | undefined;
29
+ } | {
30
+ readonly ok: false;
31
+ readonly fact: K8sApiCredentialFact;
32
+ readonly code: "connect_failed" | "auth_failed";
33
+ };
34
+ /**
35
+ * The ONE judge of "does this lane have cluster API credentials": explicit config (`K8S_API_URL` / `K8S_TOKEN` / `K8S_CA_CERT_B64`, `K8S_INSECURE_TLS`) first, the
36
+ * in-cluster service account second, per piece. The request-time reader ({@link RemoteK8sExecutionEnv}'s `creds()`), the boot gate and the per-run credential
37
+ * reading all read THIS function — what the boot refuses on is exactly what every request would have thrown on. (No kubeconfig: this lane never reads one.)
38
+ */
39
+ export declare function resolveK8sApiAccess(cfg: {
40
+ readonly apiUrl?: string | undefined;
41
+ readonly token?: string | undefined;
42
+ readonly caCert?: string | undefined;
43
+ readonly insecureTls?: boolean | undefined;
44
+ }, inCluster?: InClusterIdentity): K8sApiAccess;
12
45
  export interface K8sEnvConfig extends LaneHomeConfig {
13
46
  /** API server URL. Default: in-cluster (`https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT`). */
14
47
  apiUrl?: string;
@@ -175,13 +208,6 @@ export { type PodSpecPatch, applyPodSpecPatch } from "./k8s-exec-protocol.js";
175
208
  import { type SandboxPodApi, type SandboxPodListing } from "./k8s-pod-reaper.js";
176
209
  import { type SandboxLeaseEntryInput } from "../sandbox-git-lease.js";
177
210
  import type { WorkspaceFill } from "./workspace-fill.js";
178
- type ConnectResult = {
179
- ok: true;
180
- value: WorkspaceHandle;
181
- } | {
182
- ok: false;
183
- error: RemoteExecutionError;
184
- };
185
211
  /** Minimal exec-socket surface (what we use of `ws`) so tests can inject a fake. */
186
212
  export interface ExecSocket {
187
213
  on(event: "open" | "message" | "close" | "error", listener: (...args: unknown[]) => void): void;
@@ -200,6 +226,21 @@ export interface K8sRequestOptions {
200
226
  signal?: AbortSignal;
201
227
  contentType?: string;
202
228
  }
229
+ /**
230
+ * The control plane's reading of this lane's credentials, a closed set: `missing` (the judge's fact — nothing to send), `rejected` (the cluster answered HTTP 401),
231
+ * `accepted` (a 2xx answer: the credentials work), `unproven` (any other answer, or none — see {@link RemoteK8sExecutionEnv.apiCredentialReading}).
232
+ */
233
+ export type ApiCredentialReading = {
234
+ readonly state: "missing";
235
+ readonly fact: K8sApiCredentialFact;
236
+ } | {
237
+ readonly state: "rejected";
238
+ } | {
239
+ readonly state: "accepted";
240
+ } | {
241
+ readonly state: "unproven";
242
+ readonly detail: string;
243
+ };
203
244
  export interface K8sEnvDeps {
204
245
  request?: (method: string, apiPath: string, body?: unknown, opts?: K8sRequestOptions) => Promise<{
205
246
  status: number;
@@ -209,6 +250,8 @@ export interface K8sEnvDeps {
209
250
  connectOnce?: (signal?: AbortSignal) => Promise<ConnectResult>;
210
251
  /** Worker-side object-store requests (the space pointer, listing, deletes). Default: global `fetch`; either way the request goes out through the egress exit (an endpoint that answers with a redirect is refused, never followed). */
211
252
  fetch?: typeof fetch;
253
+ /** This process's in-cluster identity (default: the process env's `KUBERNETES_SERVICE_*` and the mounted service-account files); a test replaces it. */
254
+ inCluster?: () => InClusterIdentity;
212
255
  /** 这只环境手里的读地板模块(缺席 ⇒ `createSandboxReadFloor` 按旋钮选;钉注入守地板的模块)。能力块的 `keepsReadFloor` 读它的状态。 */
213
256
  readFloor?: SandboxReadFloor;
214
257
  }
@@ -325,11 +368,15 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
325
368
  private connectInFlight?;
326
369
  /** The resume among them, with the snapshot it restores: a second `resumeVM` of the same snapshot shares it (one restore, one pod). */
327
370
  private resumeInFlight?;
328
- /** The env's refusal — a fact of this env until `destroy`, written once ({@link holdRefusal}) and answered as it stands to every later connect (and to
329
- * every later pod creation: {@link provision}): the same refusal, zero pods, zero store requests, no second line. Two causes write it:
330
- * the space restore (`latest` names an archive that is there and did not come back — {@link restoreSnapshot}) and the pod's admission (the cluster created
331
- * the pod and it ended `Failed` before it ran — {@link createPod}). Neither goes away by asking again: the same request answers the same. */
332
- private connectRefusal?;
371
+ /**
372
+ * This env's connect seat (`remote-env-connect-seat.ts`): the one order of `connect` — a refusal the env holds ⇒ answered as it stands · a walk in flight
373
+ * ({@link connectInFlight}) ⇒ its answer · a pod already holding the workspace ⇒ its handle · otherwise one walk ({@link establish}). The seat holds the env's
374
+ * refusal — a standing one, spelled by the seat's refusal table (a missing snapshot bucket, an archive that is there and did not come back, the cluster
375
+ * refusing the pod at admission, the member-credential broker that cannot be set up, a fill refused the same on any pod, a home the pod answered against
376
+ * the claim, a session row with no occupant token): a fact of this env until `destroy`, answered to every later connect and every later pod creation
377
+ * ({@link provision}) — zero pods, zero store requests, no second line. A refusal that heals by itself (a quota, a store that did not answer) is not held.
378
+ */
379
+ private readonly seat;
333
380
  /** core `ExecutionEnv.homeDir`([ref]):pod 里执行用户的 home —— 声明在场 ⇒ 声明(开环境那一拍与 `$HOME` 对证过),否则 pod 就绪那一拍实测的 `$HOME`,见 {@link LaneHomeSeat}。读时才取(没声明时 pod 起来之前缺席)。 */
334
381
  get homeDir(): string | undefined;
335
382
  /** 家目录的座(声明在场 ⇒ 开环境那一拍对证 · 否则 pod 就绪那一拍实测 · 实测缺席 ⇒ 缺席 + 一行 warn)。与其余读得出家目录的车道同一只判官、同一句拒。 */
@@ -371,8 +418,18 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
371
418
  get lifetimeMs(): number;
372
419
  private resolve;
373
420
  workspaceHandle(): WorkspaceHandle;
374
- /** Resolved lazily so an in-cluster pod picks up its service account without explicit config. */
421
+ /** Resolved lazily so an in-cluster pod picks up its service account without explicit config ({@link resolveK8sApiAccess} is the one judge). */
375
422
  private creds;
423
+ /** The missing credential fact of this env's control-plane access, or `undefined` (nothing missing) — {@link resolveK8sApiAccess}, the one judge. */
424
+ missingApiCredential(): K8sApiCredentialFact | undefined;
425
+ /**
426
+ * The control plane's reading of this lane's credentials, asked once per run before its env is minted ({@link readSandboxApiCredentials}): the judge's missing fact
427
+ * ({@link missingApiCredential}), else one SelfSubjectAccessReview (answered for every authenticated caller) — an HTTP 401 is the cluster rejecting the credentials,
428
+ * a 2xx the cluster accepting them. ONLY a positive proof of rejection refuses: any other answer (403, 5xx, a request that threw or timed out) is `unproven` — another
429
+ * fact (a Role, an outage) that the lane's own connect answers loudly and retries within its own bounds; refusing the run on it would turn every API blip into a failed run.
430
+ * The caller counts an `unproven` reading (a registered fail-open arm). Never throws.
431
+ */
432
+ apiCredentialReading(): Promise<ApiCredentialReading>;
376
433
  /** Control-plane REST call (pod create/get/delete), bounded by rpcTimeoutMs. Injectable for tests. */
377
434
  private request;
378
435
  private openExec;
@@ -381,18 +438,20 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
381
438
  * ({@link awaitSpaceCommit}: the run store's commit row), then read `<prefix>/<incarnation>/space/latest`: present ⇒
382
439
  * restore it through {@link restoreSnapshot} (the one tar download, shared with `resumeVM`; an archive that is gone ⇒
383
440
  * loud `workspace_latest_dangling`, the pointer deleted, an empty workspace); absent (404 — the key, with the bucket there) ⇒ a fresh pod; a read that
384
- * FAILS ⇒ a loud `connect_failed` — a 404 `NoSuchBucket` included ({@link refuseMissingBucket}) — never a silent fresh workspace (a run that believes it resumed while it did not is
441
+ * FAILS ⇒ a loud refusal — `connect_failed` (that attempt's: the next connect reads again), or, for a 404 `NoSuchBucket`, the env's standing
442
+ * `env.snapshot_bucket_missing` ({@link refuseMissingBucket}) — never a silent fresh workspace (a run that believes it resumed while it did not is
385
443
  * the worst form). Once the pod holds the workspace, this env arms its fence seat (its destroy will commit).
386
444
  * The same walk ({@link establish}) is the restore point of a parked run's resumed leg whose park packed nothing ({@link resumeVM}).
387
445
  * Persistence off / no store ⇒ a fresh pod, exactly as before. Persistence on but no such session (the occupant absent) ⇒ a
388
- * fresh pod and one `workspace_space_unavailable` line (no restore by any other key). The occupant read FAULTED ⇒ the same
389
- * loud `connect_failed` as a failed `latest` read, no pod ({@link provision} refuses it — every entry that would create one).
390
- * One connect in flight per env: a connect that arrives while another is running — the explicit one, the lazy one of the first operation,
391
- * `reconnect` — gets THAT connect's answer (one pod creation, one restore, one refusal line), not a walk of its own; the share is for a connect in flight
392
- * only (a connect that failed is not remembered by it — how long a failure stands is {@link connectRefusal}'s). The abort signal of the connect that
393
- * started is the one in force.
394
- * One refusal per env: a refusal this env holds ({@link connectRefusal} — a restore that did not come back, a pod the cluster refused at admission) is answered
395
- * as it stands to every later connect on every lane — the previous commit is not waited on again, `latest` is not read again, no pod is created.
446
+ * fresh pod and one `workspace_space_unavailable` line (no restore by any other key). The occupant read FAULTED ⇒ a refusal worded as a
447
+ * failed `latest` read, no pod ({@link provision} refuses it — every entry that would create one; {@link refuseUnreadableOccupant} spells its two facts).
448
+ * `connect` is idempotent — the one order of the env's {@link seat}: a refusal this env holds (a restore that did not come back, a pod the cluster refused at
449
+ * admission, a missing bucket …) is answered as it stands to every later connect on every lane — the previous commit is not waited on again, `latest` is not
450
+ * read again, no pod is created; a walk in flight (the explicit connect, the lazy one of the first operation, `reconnect`, a resume) ⇒ THAT walk's answer (one pod
451
+ * creation, one restore, one refusal line), a caller's abort withdrawing only its own wait; a pod already holding the workspace ⇒ its handle, nothing created
452
+ * (the engine's restore seat is commonly not the first connection: a delegated child touched the env during its placement check); otherwise one walk. A
453
+ * failure that is not held (a pod that could not be created, a space read that failed) ⇒ the next connect walks afresh. The abort signal of the connect that
454
+ * started the walk is the one in force for the walk.
396
455
  */
397
456
  connect(config?: RemoteConnectConfig): Promise<ConnectResult>;
398
457
  /** The one walk of a connect ({@link connect} runs it once at a time) — also the resumed leg's walk when its park packed nothing ({@link restorePointOf},
@@ -402,7 +461,7 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
402
461
  * The restore point's fill (`workspace-fill.ts`): a pod whose workspace this env just minted or restored is handed over only once the fill seat placed
403
462
  * its content — through {@link fillChannel} (this adapter's own exec, never the public face: inside a connect the public face waits on that very connect).
404
463
  * A fill that does not complete releases the pod (no tool and no run-end snapshot may see a half-filled workspace); a refusal that would answer the same
405
- * again (`standing`) is held for the env ({@link holdRefusal}). No seat ⇒ the pod as it came. `origin` tells the seat whether the workspace was minted
464
+ * again (`standing`) is held for the env (its {@link seat}). No seat ⇒ the pod as it came. `origin` tells the seat whether the workspace was minted
406
465
  * (a new pod with nothing restored: the space off / unavailable / without `latest`, or a dangling restore point — `latest` or a park snapshot whose archive is gone)
407
466
  * or restored (the space's `latest`, or a park snapshot whose archive came back). A park that packed nothing resumes through a new connect, so it reads as that connect does.
408
467
  */
@@ -430,21 +489,22 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
430
489
  /** The space lane is on but this run's session has no occupant (no such session — {@link SpaceOccupant}) — said once per env
431
490
  * (at connect, or at a destroy with a pod). `reason` = the reading's word. */
432
491
  private sayUnavailable;
433
- /** Hold `error` as this env's refusal ({@link connectRefusal}) and answer it — the ONE writer of the slot (the restore and the pod's admission both write through it). */
434
- private holdRefusal;
435
492
  /**
436
493
  * The cluster created this env's pod and it ended `Failed` (or `Succeeded`) before it ever ran — the kubelet refused it at admission
437
494
  * (`SysctlForbidden` when `K8S_SANDBOX_IPV6=disabled` meets a kubelet that does not allow the two sysctls, a node-affinity miss, no capacity on the
438
- * node …): the env's refusal ({@link holdRefusal}), in the one `connect_failed` form with the kubelet's reason in the sentence — so the operation that meets
495
+ * node …): the env's refusal (held by its {@link seat}: `env.sandbox_refused`, standing) with the kubelet's reason in the sentence — so the operation that meets
439
496
  * it, and every later one, says what the cluster said, instead of a new pod per operation. One `sandbox_pod_refused{pod, phase, reason, detail}` line per env
440
497
  * (`detail` = the kubelet's own text, cut). A retry of the run builds a fresh env, which asks the cluster afresh.
441
498
  */
442
499
  private refusePod;
443
500
  /**
444
- * A lane that is on is keyed by an occupant read that FAULTED (`unreadable`) ⇒ this env creates no pod: the refusal, in the one
445
- * space-read failure form ({@link spaceReadFailed} — a failed `latest` / commit-row read says the same), naming the knob of every
446
- * lane that refuses; one `workspace_space_unreadable_occupant{sessionId, code}` line per env. `code` = the store error's code,
447
- * never its text. Not a knob: there is no honest way to run a space we could not read — a retry of the run reads it again.
501
+ * A lane that is on is keyed by an occupant read that FAULTED (`unreadable`) ⇒ this env creates no pod: the refusal, worded as the space-read failures are
502
+ * (a failed `latest` / commit-row read says the same head), naming the knob of every lane that refuses; one `workspace_space_unreadable_occupant{sessionId, code}`
503
+ * line per env. `code` = the store error's code, never its text. Not a knob: there is no honest way to run a space we could not read. Two facts, by the code:
504
+ * - `session.incarnation_missing` — the session row is there and carries no occupant token: a data defect that answers the same to every read ⇒ standing
505
+ * (`env.occupant_missing`, held by the {@link seat}); the way out is the row (give it its token, or delete the session) or the knob;
506
+ * - any other code (the read timed out, the store failed, an answer the projection could not read) ⇒ it heals by itself: a retry of the run reads it again
507
+ * (`connect_failed`). The reading is this env's, fixed at construction, so this env answers it to every operation all the same.
448
508
  */
449
509
  private refuseUnreadableOccupant;
450
510
  /** Every space-lane operator line: the space is named by its incarnation's log prefix only ({@link snapshotLine} does the rest). */
@@ -457,12 +517,11 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
457
517
  * here, before any request ({@link refuseUnreadableOccupant}): never retried (the reading is this env's, fixed at construction). */
458
518
  private provision;
459
519
  /**
460
- * Lazy-connect on first use — 🔴 core NEVER calls `connect()` (verified: the Runner only calls `resumeVM` on
461
- * the resume path), so an adapter that demands an explicit connect can never work through the production
462
- * hand-tool path (lazy-connect belongs in the adapter). `destroyed` is terminal. Concurrent first ops share ONE pod create — through
463
- * {@link connect}'s one connect in flight, the same seat the explicit connect shares. How long a failure stands is {@link connect}'s: a failure of that
464
- * attempt (a pod that could not be created, a space read that failed) ⇒ the next op connects afresh; the env's refusal ({@link connectRefusal}) ⇒ the
465
- * next op's connect answers that same refusal at once.
520
+ * Lazy-connect on first use — an operation may meet the env before anything connected it (a delegated child's placement check, a factory layer writing into
521
+ * the env before handing it over), so the adapter connects itself; the engine's explicit connect at the leg's restore seat then finds it connected (the
522
+ * {@link seat}'s idempotent order). `destroyed` is terminal. Concurrent first ops share ONE pod create — through {@link connect}'s one walk in flight, the same
523
+ * seat the explicit connect shares. How long a failure stands is the seat's: a failure of that attempt (a pod that could not be created, a space read that
524
+ * failed) ⇒ the next op connects afresh; the env's held refusal ⇒ the next op's connect answers that same refusal at once.
466
525
  */
467
526
  private ensureConnected;
468
527
  /**
@@ -554,7 +613,7 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
554
613
  * snapshotKey()+s3Presign() pair so the two call sites can't diverge.
555
614
  */
556
615
  private presignSnapshot;
557
- /** The key prefix of every snapshot object this env signs — the ONE reading of `keyPrefix` (unset ⇒ the default); its form is judged in {@link presignSnapshot}. */
616
+ /** The key prefix of every snapshot object this env signs — `workspaceSnapshotPrefixOf`, the ONE reading of `keyPrefix` (unset ⇒ the default; the boot bucket check lists under the same reading); its form is judged in {@link presignSnapshot}. */
558
617
  private snapshotKeyPrefix;
559
618
  /** A lane's partition prefix inside the bucket — the ONE place it is spelled (`presignSnapshot` signs under it; the reclaim reads the listing against it).
560
619
  * The partition segment is validated by `presignSnapshot` before a URL is signed. */
@@ -591,8 +650,8 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
591
650
  * The store answered `404 NoSuchBucket` — to the space's `latest` read (`read: "pointer"`) or to a restore's archive GET (`read: "archive"`, either lane:
592
651
  * the pod relays the store's answer, {@link restoreSnapshot}): the workspace snapshot bucket does not exist, so this workspace can be neither restored nor
593
652
  * saved — a run started on it would work on an empty /workspace and lose everything it wrote. One fact, one consequence on both lanes and both reads: the
594
- * env's refusal ({@link holdRefusal}) naming the bucket and the knob that picks it — the pointer read in the one space-read failure form ({@link spaceReadFailed}),
595
- * the archive read in the same words — and one `workspace_snapshot_bucket_missing{bucket, code, effect}` line per env, carrying `space` on the space lane and
653
+ * env's refusal (`env.snapshot_bucket_missing`, standing, held by the {@link seat}) naming the bucket and the knob that picks it — the pointer read worded as the
654
+ * space-read failures are ({@link spaceReadFailed}), the archive read in the same words — and one `workspace_snapshot_bucket_missing{bucket, code, effect}` line per env, carrying `space` on the space lane and
596
655
  * `sessionId` on the park lane (the refusal stands until destroy: later connects and operations answer it without another read or line; a retry of the run
597
656
  * builds a fresh env, which asks the store afresh — a bucket created in between is found). The boot probe (`snapshot-bucket-presence.ts`) refuses a boot
598
657
  * where the bucket is already missing; this is the same judgement ({@link isNoSuchBucketAnswer}) for a bucket that went missing afterwards or that the probe
@@ -706,7 +765,7 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
706
765
  * - space: the archive `latest` names is THERE and did not come back ({@link RestoreFailureClass}): the run is refused all the
707
766
  * same — never an empty workspace (the user's changes are still in the bucket) — with exactly one `workspace_restore_failed`
708
767
  * line (its `attempts`; an attempt that failed before one that succeeded is no line) and a refusal naming the two ways out,
709
- * held for the env ({@link connectRefusal}).
768
+ * held for the env by its {@link seat} (`env.sandbox_refused`, standing).
710
769
  * A pod that could not be created is that attempt's failure, not the archive's: returned as it is — no line, nothing held, the
711
770
  * next connect tries again. An abort during the pause ends the restore `aborted` (not the archive's either).
712
771
  */
@@ -877,6 +936,8 @@ export declare class RemoteK8sExecutionEnv implements RemoteExecutionEnv, Backgr
877
936
  * 循环(上限 64、只锚不折、遇环即止),脚本与读法的单一属主在 `remote-shell.ts`,四条 shell 腿共用同一份。
878
937
  * 缺席读法用不上(本腿在场);`ok:false` 由 core 读作「这一次没有跳」,永不是拒绝。 */
879
938
  canonicalChain(p: string, abortSignal?: AbortSignal): Promise<Result<SymlinkChain, FileError>>;
939
+ /** 绑定读(逐答重绑,Linux 读法;脚本与读法的单一属主在 `remote-shell.ts`,四条 shell 腿共用同一份)。 */
940
+ openBound(p: string, abortSignal?: AbortSignal): Promise<Result<BoundFileObject, FileError>>;
880
941
  canonicalPath(p: string, abortSignal?: AbortSignal): Promise<Result<string, FileError>>;
881
942
  exists(p: string, abortSignal?: AbortSignal): Promise<Result<boolean, FileError>>;
882
943
  createDir(p: string, options?: {
@@ -925,6 +986,13 @@ export declare function createSpaceReclaimer(config: K8sEnvConfig, deps?: K8sEnv
925
986
  * nodes that join after boot are read at the next boot. Never throws (a read failure is an `unreadable` gap).
926
987
  */
927
988
  export declare function checkSandboxEgressPolicy(config: K8sEnvConfig, deps?: K8sEnvDeps): Promise<SandboxEgressGap[]>;
989
+ /**
990
+ * The missing cluster-API credential fact of this k8s config's control-plane access ({@link RemoteK8sExecutionEnv.missingApiCredential}), or `undefined`. The boot
991
+ * gate's judgment: the one judge ({@link resolveK8sApiAccess}) over the config and the process's in-cluster identity. Never throws.
992
+ */
993
+ export declare function sandboxApiCredentialFact(config: K8sEnvConfig, deps?: K8sEnvDeps): K8sApiCredentialFact | undefined;
994
+ /** The control plane's reading of this lane's credentials ({@link RemoteK8sExecutionEnv.apiCredentialReading}; a control-plane env, no pod). Never throws. */
995
+ export declare function readSandboxApiCredentials(config: K8sEnvConfig, deps?: K8sEnvDeps): Promise<ApiCredentialReading>;
928
996
  /** The boot reading of one sandbox Secret seat for this k8s config ({@link RemoteK8sExecutionEnv.secretSeatReading}; a control-plane env, no pod). Never throws. */
929
997
  export declare function readSandboxSecretSeat(config: K8sEnvConfig, seat: SandboxSecretSeatKind, deps?: K8sEnvDeps): Promise<SandboxSecretSeat>;
930
998
  /**