@sema-agent/server 7.139.0 → 7.140.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 (194) hide show
  1. package/MIGRATION.md +181 -0
  2. package/USAGE.md +19 -13
  3. package/dist/adoption/runner.js +1 -1
  4. package/dist/adoption/sql.js +1 -1
  5. package/dist/approval-card.d.ts +6 -6
  6. package/dist/bench/s1/live-deps.js +3 -2
  7. package/dist/bench/s1/row.d.ts +5 -2
  8. package/dist/bench/s1/row.js +2 -22
  9. package/dist/boot/adoption.js +1 -1
  10. package/dist/boot/execution-env.js +12 -10
  11. package/dist/boot/execution-lane.d.ts +8 -0
  12. package/dist/boot/execution-lane.js +6 -1
  13. package/dist/boot/memory-boundary.d.ts +14 -51
  14. package/dist/boot/memory-boundary.js +10 -20
  15. package/dist/boot/memory-consolidation.d.ts +15 -11
  16. package/dist/boot/memory-consolidation.js +23 -12
  17. package/dist/boot/resolve-spec.d.ts +3 -5
  18. package/dist/boot/resolve-spec.js +2 -4
  19. package/dist/boot/runner-deps.d.ts +3 -3
  20. package/dist/boot/runner-deps.js +1 -0
  21. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  22. package/dist/boot/stage-03-store-backend.js +2 -3
  23. package/dist/boot/stage-04-stores.d.ts +2 -6
  24. package/dist/boot/stage-04-stores.js +5 -5
  25. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  26. package/dist/boot/stage-06-runners.d.ts +2 -6
  27. package/dist/boot/stage-06-runners.js +2 -2
  28. package/dist/boot/stage-07-capability-layer.d.ts +2 -6
  29. package/dist/boot/stage-08-reapers.d.ts +2 -6
  30. package/dist/boot/stage-09-leader.d.ts +2 -6
  31. package/dist/boot/stage-10-http-server.d.ts +2 -6
  32. package/dist/boot/stage-10-http-server.js +5 -4
  33. package/dist/boot/stores.d.ts +3 -6
  34. package/dist/boot/stores.js +27 -40
  35. package/dist/boot/task-list-lane.d.ts +1 -1
  36. package/dist/boot/task-list-lane.js +1 -1
  37. package/dist/boot/web-admin.js +35 -9
  38. package/dist/capabilities/execution-lane.d.ts +2 -2
  39. package/dist/config-catalog.js +2 -1
  40. package/dist/config-provider.d.ts +14 -13
  41. package/dist/config-provider.js +24 -18
  42. package/dist/config-types.d.ts +11 -2
  43. package/dist/config.js +2 -1
  44. package/dist/delegated-session-owner.d.ts +2 -1
  45. package/dist/delegated-session-owner.js +1 -1
  46. package/dist/deployment-shape.d.ts +9 -8
  47. package/dist/deployment-shape.js +4 -4
  48. package/dist/execution-lane-caps.d.ts +97 -106
  49. package/dist/execution-lane-caps.js +67 -83
  50. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  51. package/dist/http/memory-compliance-failure-reply.js +5 -0
  52. package/dist/http/memory-layer-reply.d.ts +30 -0
  53. package/dist/http/memory-layer-reply.js +24 -0
  54. package/dist/http/resume-legs.js +13 -16
  55. package/dist/http/retired-service-deps.d.ts +1 -1
  56. package/dist/http/retired-service-deps.js +1 -1
  57. package/dist/http/routes/adoption.js +1 -1
  58. package/dist/http/routes/memory-bundle.js +3 -0
  59. package/dist/http/routes/memory-compliance.js +8 -1
  60. package/dist/http/routes/memory-consolidation.js +12 -1
  61. package/dist/http/routes/memory-origin.js +14 -2
  62. package/dist/http/routes/memory-policy.js +5 -0
  63. package/dist/http/routes/sessions.js +28 -11
  64. package/dist/http/routes/tasks.js +4 -2
  65. package/dist/http/server.d.ts +5 -25
  66. package/dist/http/server.js +2 -2
  67. package/dist/identity-source.d.ts +1 -1
  68. package/dist/identity-source.js +1 -1
  69. package/dist/lane-home-probe.d.ts +68 -42
  70. package/dist/lane-home-probe.js +53 -30
  71. package/dist/leader/wire.js +5 -4
  72. package/dist/memory-bundle-engine.d.ts +16 -9
  73. package/dist/memory-bundle-engine.js +29 -6
  74. package/dist/memory-operator-faces.d.ts +85 -30
  75. package/dist/memory-operator-faces.js +136 -30
  76. package/dist/memory-project-layer.d.ts +3 -21
  77. package/dist/memory-project-layer.js +11 -8
  78. package/dist/memory-scope-stores.d.ts +73 -0
  79. package/dist/memory-scope-stores.js +86 -0
  80. package/dist/memory-scope.d.ts +29 -5
  81. package/dist/memory-scope.js +16 -4
  82. package/dist/memory-sync-client.d.ts +20 -7
  83. package/dist/memory-sync-client.js +31 -13
  84. package/dist/plugins/adoption-log-sql.js +4 -4
  85. package/dist/plugins/approval-ask-store-sql.js +14 -14
  86. package/dist/plugins/approval-nonce-store.js +4 -4
  87. package/dist/plugins/blob-backend.d.ts +4 -4
  88. package/dist/plugins/blob-backend.js +7 -7
  89. package/dist/plugins/breaker-state-sql.js +2 -2
  90. package/dist/plugins/checkpoint-index-columns.js +2 -2
  91. package/dist/plugins/checkpoint-store-sql.js +16 -16
  92. package/dist/plugins/device-store-sql.js +19 -19
  93. package/dist/plugins/ensure-index.d.ts +1 -2
  94. package/dist/plugins/execution-placement-sql.d.ts +8 -8
  95. package/dist/plugins/execution-placement-sql.js +8 -8
  96. package/dist/plugins/file-history-store-sql.d.ts +2 -2
  97. package/dist/plugins/file-history-store-sql.js +4 -4
  98. package/dist/plugins/image-bake-store-sql.js +9 -9
  99. package/dist/plugins/image-index-sql.js +11 -11
  100. package/dist/plugins/leader-run-store-sql.js +4 -4
  101. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  102. package/dist/plugins/mailbox-store-sql.js +4 -4
  103. package/dist/plugins/memory-engine-tidb.js +5 -5
  104. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  105. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  106. package/dist/plugins/one-time-migrations.d.ts +10 -9
  107. package/dist/plugins/one-time-migrations.js +36 -36
  108. package/dist/plugins/org-delivery-quota-store.js +2 -2
  109. package/dist/plugins/outcome-ledger-sql.js +2 -2
  110. package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
  111. package/dist/plugins/permission-rule-store-sql.js +16 -16
  112. package/dist/plugins/remote-env-adb.d.ts +7 -24
  113. package/dist/plugins/remote-env-adb.js +22 -5
  114. package/dist/plugins/remote-env-device.d.ts +2 -28
  115. package/dist/plugins/remote-env-device.js +2 -1
  116. package/dist/plugins/remote-env-e2b.d.ts +18 -26
  117. package/dist/plugins/remote-env-e2b.js +51 -4
  118. package/dist/plugins/remote-env-file-error.d.ts +1 -1
  119. package/dist/plugins/remote-env-file-error.js +8 -2
  120. package/dist/plugins/remote-env-host.d.ts +19 -35
  121. package/dist/plugins/remote-env-host.js +26 -3
  122. package/dist/plugins/remote-env-k8s.d.ts +3 -14
  123. package/dist/plugins/remote-env-k8s.js +3 -2
  124. package/dist/plugins/remote-env-local-docker.d.ts +4 -15
  125. package/dist/plugins/remote-env-local-docker.js +5 -4
  126. package/dist/plugins/remote-env-ssh.d.ts +4 -24
  127. package/dist/plugins/remote-env-ssh.js +4 -3
  128. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  129. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  130. package/dist/plugins/retention-lane-store-sql.js +2 -2
  131. package/dist/plugins/retention-store-sql.d.ts +1 -1
  132. package/dist/plugins/retention-store-sql.js +6 -6
  133. package/dist/plugins/run-store-sql.js +15 -15
  134. package/dist/plugins/schema-consistency.d.ts +6 -6
  135. package/dist/plugins/schema-consistency.js +1 -1
  136. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  137. package/dist/plugins/schema-ensure-legs.js +2 -2
  138. package/dist/plugins/schema-live-columns.d.ts +1 -1
  139. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  140. package/dist/plugins/session-rules-column.d.ts +1 -1
  141. package/dist/plugins/session-rules-column.js +1 -1
  142. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  143. package/dist/plugins/session-workspace-cell.js +1 -1
  144. package/dist/plugins/shared-memory-store-sql.js +2 -2
  145. package/dist/plugins/sql-driver.d.ts +10 -5
  146. package/dist/plugins/sql-driver.js +6 -6
  147. package/dist/plugins/sql-errors.js +1 -1
  148. package/dist/plugins/store-backend.d.ts +4 -6
  149. package/dist/plugins/store-backend.js +6 -6
  150. package/dist/plugins/task-list-store-sql.js +11 -11
  151. package/dist/plugins/tidb-pool.js +5 -5
  152. package/dist/plugins/tidb-session-storage.js +4 -4
  153. package/dist/plugins/tidb-session-store.js +13 -13
  154. package/dist/plugins/tool-result-store-sql.d.ts +2 -2
  155. package/dist/plugins/tool-result-store-sql.js +3 -3
  156. package/dist/plugins/user-input-ledger-sql.js +2 -2
  157. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  158. package/dist/plugins/workflow-run-store-sql.js +19 -19
  159. package/dist/plugins/write-behind-counter.d.ts +2 -3
  160. package/dist/plugins/write-behind-counter.js +5 -5
  161. package/dist/resource-suspend.d.ts +14 -12
  162. package/dist/resource-suspend.js +1 -1
  163. package/dist/resource-window.d.ts +4 -3
  164. package/dist/run-local.js +14 -19
  165. package/dist/runs.d.ts +8 -4
  166. package/dist/runs.js +49 -65
  167. package/dist/session-incarnation.d.ts +1 -1
  168. package/dist/session-incarnation.js +1 -1
  169. package/dist/session-policy-wire.d.ts +1 -1
  170. package/dist/sql-engine-posture.d.ts +1 -1
  171. package/dist/sql-engine-posture.js +1 -1
  172. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  173. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  174. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  175. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  176. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  177. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  178. package/dist/task-a2a.js +5 -6
  179. package/dist/task-mcp.d.ts +20 -7
  180. package/dist/task-mcp.js +17 -9
  181. package/dist/terminal.d.ts +27 -0
  182. package/dist/terminal.js +6 -0
  183. package/dist/trace/redact.d.ts +3 -1
  184. package/dist/trace/redact.js +80 -28
  185. package/dist/trace/self-minted-wire.d.ts +58 -0
  186. package/dist/trace/self-minted-wire.js +16 -0
  187. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  188. package/dist/web-admin-client/candidate-gate.js +1 -1
  189. package/dist/web-admin-client/http-client.d.ts +5 -4
  190. package/dist/web-admin-client/http-client.js +2 -2
  191. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  192. package/dist/web-admin-client/read-warnings.js +5 -9
  193. package/package.json +2 -2
  194. package/wire-changes/server@7.140.0.json +184 -0
@@ -1,5 +1,7 @@
1
+ import { type ExecutionEnvCapabilities } from "@sema-agent/core";
1
2
  import { type ExecutionLane as DeclarableLane, type ExecutionLaneRow } from "@sema-agent/settings-schema/execution-lanes";
2
3
  import type { ServiceConfigFlat } from "./config-types.js";
4
+ import { type LaneHomeConfig } from "./lane-home-probe.js";
3
5
  /** 一位能力的三态。`single-user-only` = 车道支持,但只在单用户部署(`requirePrincipal !== true`)开 ——
4
6
  * 多租户下这一位必须关(host 家族的 cwd/scheduler/backgroundShell/LSP 都是这一档,理由同源:
5
7
  * 一个租户的输入不许把 agent 指向 worker 宿主上另一个租户/运维的文件与进程)。 */
@@ -14,7 +16,7 @@ export type ExecutionLane = "in-process" | RemoteExecProvider;
14
16
  * 所以坐标漂了(重命名/搬家/改语义)门会红,注释不会烂在这里。
15
17
  */
16
18
  export interface ExecutionLaneCaps {
17
- /** 调用方送来的 `cwd` 是否被尊重。读者:部署形表行 `callerCwd`([ref] 起本位即判据;改前对账 `task-cwd.ts` 的 `cwdHonored || deviceCwdHonored`)。 */
19
+ /** 调用方送来的 `cwd` 是否被尊重。读者:部署形表行 `callerCwd`(本位即判据;改前对账 `task-cwd.ts` 的 `cwdHonored || deviceCwdHonored`)。 */
18
20
  readonly callerCwd: LaneCapability;
19
21
  /** core 的后台 shell 面(`run_in_background`/`BashOutput`/`KillShell`)。判别式:各 adapter 的
20
22
  * `backgroundCapabilities.supported`(`plugins/remote-env-{host,e2b,k8s}.ts`);host 腿的闸在
@@ -26,96 +28,67 @@ export interface ExecutionLaneCaps {
26
28
  /** LSP。判别式:`boot/execution-env.ts` 的 `lspManager` 两臂(沙箱桥 e2b/k8s;host 本地 NodeLspManager)。 */
27
29
  readonly lsp: LaneCapability;
28
30
  /** SendUserFile 的**沙箱直传腿**(host/in-process 的本机 fs 源是另一条腿,不是本位)。
29
- * 读者:部署形表行 `sandboxSendUserFile`([ref] 起本位即判据;判定依据在 `capabilities/sandbox-file-send.ts` 头注)。 */
31
+ * 读者:部署形表行 `sandboxSendUserFile`(本位即判据;判定依据在 `capabilities/sandbox-file-send.ts` 头注)。 */
30
32
  readonly sandboxSendUserFile: LaneCapability;
31
- /**
32
- * OS 级隔离边界(手跑在容器 / microVM / Kata pod 里,而不是一台真机上)。
33
- * 🔴 [ref] 起**本位即判别式**:全仓读它的唯一布尔口是 {@link laneIsolated}(boot `remote_exec_enabled.isolated` 与
34
- * `remote_exec_real_system` 那一行、`config.d/remote-exec.json` 抢占披露的「隔离降级」判、wire `executionLane.isolated`
35
- * + 诊断面同位、那一行 note 列的沙箱出路 —— 改前 boot 另手写一份 `e2b || k8s || local-docker`,与本表两处各算)。
36
- * 本位的**独立作者** = 各 adapter 对 core 的 `capabilities.isolation` 声明:对账测试拿 core 自己的严格读器 `isIsolated`
37
- * 问每条车道的**真 adapter 实例**,与本表、与 boot 行三方对拍。
38
- * 型上**没有** `single-user-only` 这一档(隔离是车道的结构事实,不随租户面变)⇒ {@link laneIsolated} 的布尔化是穷举、无兜底。
39
- * ⚠️ 口径 = **OS 级边界**(容器即算:共享宿主内核的 `local-docker`、runc 上的 k8s pod 都答 supported),**不是**「独立内核」强度。
40
- * VM 级强度(独立内核:只认 e2b 与 k8s 的 kata / gvisor 运行时,runc / local-docker fail-closed 判否)是**另一个问题、另一个词**:
41
- * 部署形表行 `vmIsolatedHands`(A 值路由读它,路由上下文键 `vmIsolatedExecEnv`;[ref] 拆开同词异义)—— 不是本位的第二份。
42
- */
43
- readonly isolation: Exclude<LaneCapability, "single-user-only">;
44
- /** 可挂起(k8s 以配了 `s3Snapshot` 为前提 —— 「结构上能不能」的口径)。读者:部署形表行 `suspendableHands`(本位 ∧ k8s 快照店;
45
- * [ref] 起 boot `remote_exec_enabled.suspendable` 只读那一行,不再手写车道词)。独立作者 = 各适配器的 `capabilities.suspendable`。 */
46
- readonly suspendable: LaneCapability;
47
- /** `/tmp/scratchpad/<sessionId>` 远端约定。读者:部署形表行 `remoteScratchpad`([ref] 起本位即判据;改前对账 `isRemoteScratchpadLane` 的 Set)。 */
33
+ /** `/tmp/scratchpad/<sessionId>` 远端约定。读者:部署形表行 `remoteScratchpad`(本位即判据;改前对账 `isRemoteScratchpadLane` 的 Set)。 */
48
34
  readonly remoteScratchpad: LaneCapability;
49
- /** 写门走 [ref] 的 `DeferredSandboxPathEnv` 代理裁决(而不是直接拿 worker 本机 fs 裁)。
50
- * 判别式:部署形表行 `sandboxPathAdjudication`(读 `hostFilePlane` 的反面;对账钉逼本位与它同值)。 */
51
- readonly sandboxPathAdjudication: LaneCapability;
52
35
  /** git-worktree 隔离。判别式:`boot/execution-env.ts` 的 host 臂 vs `worktree_isolation_unsupported_lane` warn。 */
53
36
  readonly worktreeIsolation: LaneCapability;
54
- /** 记忆持久面的**自动**表态(部署可用 `MEMORY_PERSISTENCE_CAPABLE` 显式覆盖,那是旋钮不是车道位)。
55
- * 判别式:`boot/memory-boundary.ts` 的 `effectiveMemoryPersistenceCapable`。 */
56
- readonly memoryPersistenceCapable: LaneCapability;
57
- /** 文件平面是否就在 worker 本机(= `hostSemanticsLane`)。🔴 [ref] 起**消费点读本位**,不再各写判别式
58
- * (改前 `resolve-spec` / `stores` / `memory-scope` / `deferred-sandbox-path-env` 各写一份
59
- * `lane === undefined || lane === "host"` 的同义形,分叉过就是记忆边界判错盘)。读本位的真装配点:
60
- * 部署形表行 `sandboxPathAdjudication`(resolve-spec 写门 / parked 赎回腿 /
61
- * 执行环境装配三处的唯一属主)、`memory-scope.ts` 的 `memoryEngineRemoteLanePosture`、
62
- * `boot/memory-boundary.ts` 的 `buildMemoryBoundaryLaneFacts`(stores)。(「本会话没有持久记忆」的披露归引擎判、引擎渲染 ——
63
- * 目录条目 `core/memory.no-persistent-store`,本仓只交 spec 上的事实,不再读本位做判别。)⚠️ `in-process` 在本位上是 YES(hooks/进程内读确实在本机盘上),
64
- * 但它**没有手** —— 问「手在不在本机盘上」要读 {@link handsOnWorkerFilePlane},不是只读本位。 */
65
- readonly hostFilePlane: LaneCapability;
66
- /** core 的 `isRemoteExecutionEnv` 对本车道的判决(鸭子类型,**含 host**)= core 拿没拿到执行环境 = 手带挂没挂。
67
- * 5.26.0 起它决定 `# Memory` 写指令撤不撤。🔴 [ref] 起消费点读本位(改前各写 `config.remoteExec !== undefined`);
68
- * 对账测试拿 core 自己的 `isRemoteExecutionEnv` 问**真 adapter 实例**来核本位的值。 */
69
- readonly coreRemoteExecutionEnv: LaneCapability;
70
- /**
71
- * [ref] / core 7.20.0([ref]):这条车道的适配器**声明**了 `capabilities.canonicalPathAuthoritative`
72
- * 没有 —— 即「我的 `canonicalPath` 是路径落点的权威,整链答不出来是解析器出了事,不是一个我看不见的
73
- * 命名空间」。声明 ⇒ 读边界的执行期复核在解析器沉默时**拒**;缺席 ⇒ 今天每个适配器的读法(词法判决
74
- * 成立、命令照跑)—— **缺席不是「声明为 false」**,所以这一位的 `unsupported` 读作「本车道没表态」。
75
- *
76
- * 判别式:各 adapter 的 `capabilities` 字面量(`plugins/remote-env-{host,ssh,adb,k8s,device,e2b,local-docker}.ts`),
77
- * 由 core 的严格读器 `canonicalPathIsAuthoritative(env)` 读;对账测试逐 lane 拿**真 adapter 实例**问它。
78
- * 本位存在的理由 = 让「新车道/新适配器不表态」变成**编译红**(穷举 switch 少一行即 tsc 红),而不是
79
- * 静默继承一个没人表过态的缺席。
80
- */
81
- readonly canonicalPathAuthority: LaneCapability;
82
37
  /**
83
- * 车PI 修复轮 ②([ref] / clay C-R91A ②,主会话裁「按表不按词」;裁定语义 = **租户不共宿主**)—— 这条车道**分不分租户**。
38
+ * 这条车道**分不分租户**(裁定语义 = **租户不共宿主**)。
84
39
  * · `supported` = 每个租户的命令落在各自的目标上(每任务一只沙箱:e2b / k8s / local-docker;发起者自己的设备:device,
85
40
  * 归属由 deviceId↔principal 绑定验过),或根本没有手(in-process:没有可共享的执行目标);
86
41
  * · `single-user-only` = 所有任务落在**同一个共享目标**上(worker 宿主:host;一台常驻 SSH 对端:ssh;一台 ADB 设备:adb)
87
42
  * ⇒ 只许单用户部署用。
88
43
  * 本位**没有** `unsupported` 这一档(那会读成「谁都不许用」,不是车道事实)—— 型上收窄掉,每条车道必须在两档里表态。
89
- * 🔴 **7.114.0 起本位的值不在本仓写**:七条可声明车道读 settings-schema 词表正本的表行(`executionLaneRow(lane).tenantSeparation`;
44
+ * 🔴 **本位的值不在本仓写**:七条可声明车道读 settings-schema 词表正本的表行(`executionLaneRow(lane).tenantSeparation`;
90
45
  * 中心写闸的 `requirePrincipal ∧ single-user-only` 交叉判与本仓 `multi-tenant-shared-lane` 拒启读的是同一个值,不会分叉);
91
46
  * 只有 `in-process` 一格是本仓自己的事实(它不在表里)。
92
47
  * 唯一消费点是 `config-invariants.ts` 的 `multi-tenant-shared-lane`(经部署形表行 `laneSeparatesTenants` 落成布尔)。本位值与本仓**运行期事实**
93
- * 不矛盾的对账 = `test/execution-lanes-schema-conformance.test.ts`(隔离位 / 共享文件平面 ⇒ 租户档的蕴含 + 唯一一条「不隔离却分租户」
48
+ * 不矛盾的对账 = `test/execution-lanes-schema-conformance.test.ts`(执行环境块的隔离位 / 路径是不是本机的 ⇒ 租户档的蕴含 + 唯一一条「不隔离却分租户」
94
49
  * 的车道 = device 点名);ssh / adb 「两租户同一目标」的行为预言机 = `test/multi-tenant-shared-lane.test.ts`
95
50
  * (两个租户的任务铸出的 env 报同一个 `workspaceHandle().sandboxId`)。
96
51
  */
97
52
  readonly tenantSeparation: Exclude<LaneCapability, "unsupported">;
98
53
  }
99
54
  /**
100
- * per-lane 能力表。**穷举 switch,禁 default 臂**(hands-lane.ts:39-46 先例)。
55
+ * per-lane 能力表。**穷举 switch,禁 default 臂**(hands-lane.ts:39-46 先例)。执行环境自己的能力(隔离 / 可挂起 / 路径是不是本机的 / 有没有手 …)
56
+ * 不在这张表上 —— 它们是引擎能力块,唯一作者 {@link capabilitiesFor}。
101
57
  *
102
58
  * device 行的表态来自 v2 §4.1/§4.3:
103
59
  * · `callerCwd: supported` —— 员工在自己设备的项目目录里干活是这条车道的**存在理由**;host 闸防的
104
60
  * 「跨租户宿主路径穿越」在此结构性不存在(路径落在发起者自己的设备上,归属已由 deviceId↔principal
105
- * 绑定验证),故不要求单用户。(车A-4 前判别式答 false、登记过 {@link PLANNED_LANE_DIVERGENCES},已销行;[ref] 起部署形表行 `callerCwd` 直接读本位。)
106
- * · `sandboxPathAdjudication: supported` —— 自动判真且**这是深思后的正确默认**:写门经 [ref] 代理把四读
107
- * 原语转发到设备取真文件系统事实,云盘永不参与设备写目标的裁决。
61
+ * 绑定验证),故不要求单用户。(部署形表行 `callerCwd` 直接读本位。)
108
62
  * · `remoteScratchpad: supported` —— executor 平台闭集 = darwin|linux,`/tmp/scratchpad/<sessionId>`
109
63
  * 的惰性 mkdir 约定原样适用;不加词则 scratchpad envFact 对模型整块缺席。
110
64
  * · scheduler / backgroundShell / lsp / sandboxSendUserFile / worktreeIsolation = v1 **诚实关闭**
111
65
  * (不是遗漏:设备侧长驻进程、LSP sidecar、直传腿都是 follow-on,声明了就是谎)。
112
- * · `isolation`/`suspendable` = false/false —— 真设备,不隔离不可快照(与 ssh/adb 同宣告);
113
- * `suspendable:false` 在 core 契约里同时断言「工作区在目标上外部持久」,员工机磁盘满足,park-only
114
- * 赎回腿因此合法。
115
- * · `memoryPersistenceCapable: unsupported` —— 设备的手够不着云 SQL 记忆店,默认撤 `# Memory` 写指令
116
- * 恰是诚实形(§4.3.4)。
117
66
  */
118
67
  export declare function executionLaneCaps(lane: ExecutionLane): ExecutionLaneCaps;
68
+ /** {@link capabilitiesFor} 读的部署配置:已装配的 `remoteExec` 里决定块的两键(`ServiceConfig` 的判别联合每一臂结构上都满足)。 */
69
+ export interface CapabilitiesDeployment {
70
+ readonly remoteExec?: {
71
+ readonly provider?: string | undefined;
72
+ readonly s3Snapshot?: unknown;
73
+ } | undefined;
74
+ }
75
+ /**
76
+ * 「这份部署上 run 所在的执行环境能做什么」—— 引擎能力块(八键)的**唯一作者**。
77
+ *
78
+ * 七只适配器的 `capabilities` 由它铸(适配器源码里没有能力字面量);`in-process` 答引擎桩环境的块。读者读块,不另存一位:
79
+ * 起服行 `remote_exec_enabled`(`isolated` / `suspendable` / `keepsReadFloor`)、部署形表行 `sandboxPathAdjudication` / `suspendableHands`、
80
+ * {@link laneIsolated} / {@link laneWiresExecutionEnv} / {@link handsOnWorkerFilePlane}、记忆边界审计的文件平面位。改一条车道的能力 = 改本函数一处,
81
+ * 适配器、行、起服行、wire 同翻(门 `test/execution-env-capabilities-one-source.test.ts`)。
82
+ *
83
+ * 认不出的车道词 ⇒ `undefined`(调用方 fail-closed;生产链上不可达,`loadConfig` 先拒启)。两个重载同 {@link executionLaneOf}:喂已装配的车道词 ⇒ 返回型无 `undefined`。
84
+ */
85
+ export declare function capabilitiesFor(deployment: {
86
+ readonly remoteExec?: {
87
+ readonly provider: RemoteExecProvider;
88
+ readonly s3Snapshot?: unknown;
89
+ } | undefined;
90
+ }): ExecutionEnvCapabilities;
91
+ export declare function capabilitiesFor(deployment: CapabilitiesDeployment): ExecutionEnvCapabilities | undefined;
119
92
  /**
120
93
  * 车道普查全集 = 本仓内部状态名 `in-process` + 词表正本的可声明车道(次序 = 正本声明序;对账测试按它逐 lane 跑真判别式)。
121
94
  * 由正本派生、不手维护(手维护的「全表」已被代码反证漏过行)。
@@ -141,7 +114,7 @@ export declare function executionLaneRow(lane: RemoteExecProvider): ExecutionLan
141
114
  export declare function laneRequiredEnv(lane: RemoteExecProvider): readonly string[];
142
115
  /**
143
116
  * 一个必需 env 的值**算不算缺**的唯一判官 —— 两半各有归属:
144
- * · **空白半边**(空串、只含空白)归契约包:包根导出的 `isBlankCoordinate` 是这件事唯一的实现,契约包的写闸(车道声明保存时)问的是同一只函数,本仓不另抄一份;
117
+ * · **空白半边**(空串、只含空白)归契约包:`isBlankCoordinate`(函数体住在 `execution-lanes` 叶模块,包根转口同一个函数对象)是这件事唯一的实现,契约包的写闸(车道声明保存时)问的是同一只函数,本仓不另抄一份;
145
118
  * · **未设半边**(`undefined`)归本仓:契约包的判官只收字符串,「这一键根本没设」由调用方先判,所以这一臂留在这里。
146
119
  * 合起来:`undefined`、空串、只含空白一律按缺 —— 引擎把空值读成未设,纯空白拼进坐标(镜像名、命名空间、主机名)也只会在第一次用的时候才失败。
147
120
  * 所有车道、所有必需键同判一只,没有「某个键另有一套缺席 / 空白判法」。
@@ -195,18 +168,14 @@ export declare function executionLaneOf(provider: string | undefined): Execution
195
168
  */
196
169
  export declare function deployedExecutionLanes(config: Pick<ServiceConfigFlat, "remoteExec">): readonly ExecutionLane[];
197
170
  /**
198
- * [ref] —— 「这条车道的**手**就在本 worker 的盘上吗」。**两位合取,都读表**(不手抄):
199
- * · `coreRemoteExecutionEnv` —— core 拿到了执行环境 = 手带真挂上(`in-process` 答 NO:core 落 `StubExecutionEnv`);
200
- * · `hostFilePlane` —— 那套手的文件平面就是本 worker 的盘(沙箱 / 远端 / 设备车道答 NO)。
201
- * 今天只有 `host` 两位同 YES。
171
+ * 「这条车道的**手**就在本 worker 的盘上吗」= 块 `io ∧ hostLocalPaths`(读 {@link capabilitiesFor} 的块,不手抄)。今天只有 `host` 两键同真。
202
172
  *
203
- * 🔴 **只读 `hostFilePlane` 是错的**:`in-process` 那一位是 YES(hooks / 进程内读确实在本机盘上),而它
204
- * **没有手**。clay 裁 [ref] ③ 的字面写「判据读 `hostFilePlane`」,意图是同一句的「无手不挂」—— 照字面
205
- * 实现会让无手部署**继续**挂 SendUserFile,与意图相反;本函数按意图实现(收车档 che-MA 写明)。
173
+ * 🔴 **只读 `hostLocalPaths` 是错的**:`in-process` 的桩块那一键是 true(进程内读确实在本机盘上),而它**没有手**(`io: false`)——
174
+ * 只读一键会让无手部署**继续**挂 SendUserFile,与「无手不挂」的意图相反。
206
175
  *
207
176
  * 读者问的都是这一句,**同一只函数**,不许各写一份 `=== "host"`:
208
177
  * ① 部署形表行 `toolsOnThisHost`(`deployment-shape.ts`)—— wire `executionLane.toolsOnThisHost` + 出厂自扫技能与中心 plugin 技能的 `baseDir`;
209
- * ② 部署形表行 `callerOwnsWorkerDisk`(本列 ∧ 单主)—— SendUserFile 本机腿([ref] ③「无手不挂」)、调用方宿主路径(附加目录 / 项目上下文)、指令文件探针;
178
+ * ② 部署形表行 `callerOwnsWorkerDisk`(本列 ∧ 单主)—— SendUserFile 本机腿(「无手不挂」)、调用方宿主路径(附加目录 / 项目上下文)、指令文件探针;
210
179
  * ③ `approval.ts` 的 `buildNoResponderBootWarns` —— 写门的 ask 只在「有手写本机盘」时才会发生(它手里已有车道词,直接读本列)。
211
180
  */
212
181
  export declare function handsOnWorkerFilePlane(lane: ExecutionLane): boolean;
@@ -223,13 +192,15 @@ export declare function handsOnWorkerFilePlane(lane: ExecutionLane): boolean;
223
192
  */
224
193
  export declare function laneBindsReads(lane: ExecutionLane): boolean;
225
194
  /**
226
- * 「这条车道的执行环境**自己读得出家目录**」—— 没声明 `REMOTE_EXEC_HOME_DIR` 时,车道建环境那一拍问一次执行环境的 `$HOME` 填 `ExecutionEnv.homeDir` 的座
227
- * (取值律与座的唯一属主 = `lane-home-probe.ts` 的 `LaneHomeSeat`)。
228
- * · `k8s` / `local-docker` / `ssh` / `adb` —— 家目录是镜像 / 目标机登录用户 / 设备 shell 的属性,执行环境开起来之后一条命令就读得出,真;
229
- * · `device` —— 设备协议(hello / 指令集)没有家目录读数:读它要么走协议新增一格(协议对端在别仓),要么往员工自己的机器上多跑一条未经策略门的命令,都不是本函数能替它定的,假;
230
- * · `host` / `in-process` / `e2b` —— 家目录是车道自己的事实(`executionLaneHomeDir` 在 boot 期就有答案),无物可测,假。
231
- * 起服的「家目录答不出」那一行只留给 **家目录答不出 ∧ 车道又读不了** 的车道({@link buildUndeclaredHomeNote});读得了的车道缺席时由环境自己响(`LaneHomeSeat`)。
232
- * 穷举 switch、无 default 臂:车道加词而此处不表态 = 编译红。
195
+ * 「这条车道的执行环境**自己读得出家目录**」—— 读得出 ⇒ 读数是真源:适配器持一只 `LaneHomeSeat`(取值律与座的唯一属主 = `lane-home-probe.ts`),
196
+ * 部署给的主张({@link buildLaneHomeClaim})在每只环境开起来时被证,不一致 ⇒ 那只环境不开;没有主张 ⇒ 读数填 `ExecutionEnv.homeDir` 的座。
197
+ * · `k8s` / `local-docker` / `ssh` / `adb` / `e2b` —— 家目录是镜像 / 目标机登录用户 / 设备 shell / 沙箱模板用户的属性,执行环境开起来之后一条命令就读得出(e2b:`commands.run`
198
+ * 不带 user ⇒ 模板的缺省用户,自定义模板可以换掉它),真;
199
+ * · `host` —— 命令是本进程的子进程,子进程拿到的 `HOME` 由适配器自己组合(继承面 + 会话 `settings.env` 授予),不 spawn 就读得出,真;
200
+ * · `device` —— 设备协议(hello / 指令集)没有家目录读数:读它要么走协议新增一格(协议对端在别仓),要么往员工自己的机器上多跑一条未经策略门的命令,都不是本函数能替它定的,假
201
+ * (声明就是座,起服披露「来自声明、未实测」,见 {@link buildLaneHomeBootNote});
202
+ * · `in-process` —— 没有手,无环境可读,假。
203
+ * 穷举 switch、无 default 臂:车道加词而此处不表态 = 编译红。对拍钉:读得出 ⟺ 该车道的适配器源码恰持一只座(`test/lane-home-claim-verified.test.ts`)。
233
204
  */
234
205
  export declare function laneMeasuresHome(lane: ExecutionLane): boolean;
235
206
  /** 车道行声明的读面缺省(`READ_FACE` 缺席时,这条车道自己的那一份)。 */
@@ -244,25 +215,24 @@ export type LaneReadFaceDefault = "open" | "roots";
244
215
  *
245
216
  * 🔴 这是**部署信任决定**不是技术默认:`open` 读面在沙箱里等于「沙箱能看见的都可读」—— 共享卷 / 镜像内凭据 / bind mount 进沙箱的宿主文件,在 `roots` 面上本有强制问
246
217
  * (`bypass` 也清不掉),`open` 面零问。所以声明是**显式属性**(可审计,本函数的每个臂都要有人写),告诫句 {@link LANE_OPEN_READ_FACE_CAUTION} 随它走。
247
- * 穷举 switch、无 default 臂:车道加词而此处不表态 = 编译红。与能力表 `isolation` 位的关系由对账测试钉死(`open` ⟺ `laneIsolated`)。
218
+ * 穷举 switch、无 default 臂:车道加词而此处不表态 = 编译红。与执行环境块 `isolation` 的关系由对账测试钉死(`open` ⟺ `laneIsolated`)。
248
219
  */
249
220
  export declare function laneReadFaceDefault(lane: ExecutionLane): LaneReadFaceDefault;
250
221
  /** 声明 `open` 的那一句**挂载告诫**(运维面指路句与车道文档同读这一句):把宿主目录 / 共享卷挂进隔离沙箱的部署,在 `open` 面上宿主文件对模型零问可读。 */
251
222
  export declare const LANE_OPEN_READ_FACE_CAUTION = "a deployment that mounts host paths or shared volumes into the sandbox (hostPath, bind mount) exposes those host files to reads on an open face \u2014 pin READ_FACE=roots or add read-deny rows (READ_DENY_PATTERNS) for them";
252
223
  /**
253
- * [ref] —— 「这条车道的手在不在 OS 级隔离边界里」。**全仓唯一**的布尔判别式(读表 `isolation` 位,见该位头注的读者清单)。
254
- * 穷举 switch、无 default 臂:`isolation` 的型只有两档,加档 = 编译红。
255
- *
256
- * ⚠️ 本函数对 `in-process` 也答(表上那一行是 unsupported ⇒ false)—— 那一格是「表」的完整性,不是 wire 的说法:
257
- * 无手部署**没有执行边界可言**,wire 上 `executionLane.isolated` 按 present-iff 缺席(`capabilities/execution-lane.ts`),
258
- * 不是 false。boot 行只在装出了执行环境工厂时才打,够不着那一格。
224
+ * 「这条车道的手在不在 OS 级隔离边界里」= 块 `isolation`(读 {@link capabilitiesFor} 的块)。**全仓唯一**的布尔口:boot `remote_exec_enabled.isolated` 与
225
+ * `remote_exec_real_system` 那一行、`config.d/remote-exec.json` 抢占披露的「隔离降级」判、wire `executionLane.isolated` + 诊断面同位、那一行 note 列的沙箱出路、
226
+ * 部署面 `lanes.json` 的 `isolation` 列。
227
+ * ⚠️ 口径 = **OS 级边界**(容器即算),**不是**「独立内核」强度 —— 那是部署形表行 `vmIsolatedHands`(A 值路由读它),不是本函数的第二份。
228
+ * ⚠️ 本函数对 `in-process` 也答(桩块 false)—— 那一格是「表」的完整性,不是 wire 的说法:无手部署**没有执行边界可言**,wire 上 `executionLane.isolated`
229
+ * 按 present-iff 缺席(`capabilities/execution-lane.ts`),不是 false。
259
230
  */
260
231
  export declare function laneIsolated(lane: ExecutionLane): boolean;
261
232
  /**
262
- * core 拿没拿到执行环境 = 这条车道**有没有手**(能力表 `coreRemoteExecutionEnv` 位)的唯一布尔口。读者四处:路由的「有没有执行环境」(`boot/resolve-spec.ts`)、
263
- * wire `executionLane.isolated` 的在场判据(`capabilities/execution-lane.ts`)、记忆边界审计的车道位(`boot/memory-boundary.ts`)、场景详情的附件供给集
264
- * (`boot/stage-07-capability-layer.ts` 把它填进 `ScenarioDeps.handsLane`:「这一 run 有没有工作区」的车道半场)—— 同读这一只,没有各写一份 `=== "supported"`。
265
- * 穷举 switch、无 default 臂:该位的型三档(supported / unsupported / single-user-only)都要表态,加档 = 编译红。
233
+ * 这条车道**有没有手**(块 `io`:文件与 shell 两面真到达目标;`in-process` 的桩块 false)的唯一布尔口。读者四处:路由的「有没有执行环境」(`boot/resolve-spec.ts`)、
234
+ * wire `executionLane.isolated` 的在场判据(`capabilities/execution-lane.ts`)、场景详情的附件供给集(`boot/stage-07-capability-layer.ts` 把它填进
235
+ * `ScenarioDeps.handsLane`:「这一 run 有没有工作区」的车道半场)、起服家目录那一行({@link buildLaneHomeBootNote})—— 同读这一只。
266
236
  */
267
237
  export declare function laneWiresExecutionEnv(lane: ExecutionLane): boolean;
268
238
  /** 一条**已登记**的分叉:表写的是目标态,今天的判别式还答别的。 */
@@ -290,11 +260,10 @@ export declare const PLANNED_LANE_DIVERGENCES: readonly PlannedLaneDivergence[];
290
260
  /**
291
261
  * E2B 沙箱里 agent 跑成的那个用户的 home。
292
262
  *
293
- * 这是 **E2B 平台的事实**,不是本仓的猜:E2B 的基础模板建 `user` 这个用户,每个 sandbox 的进程都以它
294
- * 运行,home 恒 `/home/user`;本仓 adapter 自己的工作区根默认值(`plugins/remote-env-e2b.ts` 的
295
- * `DEFAULT_MOUNT_PATH`)用的就是同一个目录。**若某个部署的自定义模板换了用户**,运维用
296
- * `REMOTE_EXEC_HOME_DIR` 显式声明覆盖 —— 那条旋钮恒赢,见 {@link executionLaneHomeDir}。
297
- * ⚠️ 本值**未经真机实测**(本批无 e2b 真机),按平台约定 + 仓内既有默认常量登记。
263
+ * 这是 **E2B 平台的约定**:E2B 的基础模板建 `user` 这个用户,`commands.run` 不带 user 时以模板的缺省用户运行(SDK 2.36.0,envd ≥ 0.4.0),
264
+ * 基础模板上 home = `/home/user`;本仓 adapter 自己的工作区根默认值(`plugins/remote-env-e2b.ts` 的 `DEFAULT_MOUNT_PATH`)用的就是同一个目录。
265
+ * 它是 e2b 车道的**出厂主张**(声明缺席时),不是真源:每只沙箱建起来 / 恢复时与沙箱里的 `$HOME` 对证,自定义模板换了用户 ⇒ 那只沙箱不开,
266
+ * 拒句点名两值、改法 = 把 `REMOTE_EXEC_HOME_DIR` 设成实测值(那条旋钮恒赢,见 {@link executionLaneHomeDir})。
298
267
  */
299
268
  export declare const E2B_SANDBOX_HOME = "/home/user";
300
269
  /** {@link executionLaneHomeDir} 读的那两位部署配置(`ServiceConfig` 结构上满足)。 */
@@ -306,7 +275,7 @@ export interface LaneHomeDeployment {
306
275
  readonly remoteExecHomeDir?: string | undefined;
307
276
  }
308
277
  /**
309
- * 「**这条部署的执行环境**以哪个 home 运行」—— `~/…` 形权限规则(`Edit(~/.ssh/**)`)唯一的基。
278
+ * 「**这条部署的执行环境**以哪个 home 运行」的 boot 期答案(主张)—— `~/…` 形权限规则(`Edit(~/.ssh/**)`)唯一的基。
310
279
  *
311
280
  * ## 病(接入审计 M13 / DEBTS [ref]④)
312
281
  * core 的 `ExecutionEnv.homeDir` 是**由 adapter 声明**的座(`engine/harness/types.d.ts`,可选):
@@ -315,14 +284,14 @@ export interface LaneHomeDeployment {
315
284
  * (`task-settings.ts` 的 `rejectUnmatchableSettingsNames`)在 home 未知时整表拒 `~/` 形 ——
316
285
  * **于是远端部署根本写不出 `~/` 规则**,恒 422。
317
286
  *
318
- * ## 本函数 = **boot 期就答得出的** home 的单一属主
287
+ * ## 本函数 = **boot 期就答得出的** home(主张)的单一属主
319
288
  * 三个消费面读同一份,不许各算各的(两处不同 = 一条规则在 422 门上被拒、却在引擎里编得出来,或反之):
320
- * ① 每只 adapter 的 `homeDir` 座的**声明那一半**(`boot/execution-env.ts` 把本函数的答案递进 adapter 配置;
321
- * k8s / local-docker / ssh / adb 四条车道的座 = 本函数答案 ∨ 车道建环境时实测,取值律在 `lane-home-probe.ts` 的 `LaneHomeSeat`);
289
+ * ① 每只 adapter 的 `homeDir` 座的**主张那一半**(`boot/execution-env.ts` 把 {@link buildLaneHomeClaim} 递进 adapter 配置;读得出家目录的车道
290
+ * ({@link laneMeasuresHome})在每只环境开起来时拿读数证它,不一致 ⇒ 那只环境不开;没有主张 ⇒ 座 = 读数,取值律在 `lane-home-probe.ts` 的 `LaneHomeSeat`);
322
291
  * ② 规则基 `PathRuleBases.home`(`boot/resolve-spec.ts` / `boot/parked-revive-gate.ts` 的 `pathAdjudication.taskHome`);
323
292
  * ③ 422 前置门与能力披露(`task-settings.ts` / `deployment-governance.ts`)。
324
293
  * ②③ 在下单那一刻就要答,那一刻执行环境还没开 —— 它们只读本函数,**读不到实测值**:没声明的 k8s / local-docker / ssh / adb 部署上,座有实测值而 ②③ 仍按「缺席」办
325
- * (`~/` 形规则下单拒 —— 偏严的方向,不会出现「门放行而引擎编不出」)。
294
+ * (`~/` 形规则下单拒 —— 偏严的方向,不会出现「门放行而引擎编不出」);本函数答了的部署上,②③ 按主张办,而主张对不上的环境根本不开(①)。
326
295
  *
327
296
  * ## 一条规则,不是七条特判
328
297
  * **运维显式声明恒赢**(`REMOTE_EXEC_HOME_DIR`,部署级旋钮,不挂任何客户端表态);没有声明时,
@@ -333,21 +302,43 @@ export interface LaneHomeDeployment {
333
302
  * · `k8s` / `local-docker` —— home 是**镜像**的属性,boot 期无从得知;
334
303
  * · `ssh` —— home 是**目标机上那个登录用户**的属性(root 是 `/root`、macOS 是 `/Users/<u>`),
335
304
  * 连上之前无从得知,而 422 门要在下单那一刻回答;
336
- * · `adb` —— Android 没有 POSIX 意义上的登录 home;
305
+ * · `adb` —— 设备 shell 的属性(Android 没有 POSIX 意义上的登录 home),连上之前无从得知;
337
306
  * · `device` —— 员工自己的机器,运行期才连进来。
338
307
  * 这五条一律**缺席**(诚实:不猜一个目录去守)。缺席的后果是 `~/` 规则在下单时被 422 响亮拒,
339
308
  * 与 core 的 `missingBase:"home"` 同向 —— 这正是负控要的那一格。其中 `k8s` / `local-docker` / `ssh` / `adb` 的**引擎手里那一只座**另有实测的来源
340
309
  * (建环境时问 `$HOME`,{@link laneMeasuresHome});本函数不替它回答 —— boot 期确实不知道。
310
+ * 本函数答出的每一个值(声明,或 host / e2b 的出厂答案)都只是主张:读得出家目录的车道在环境开起来时证它({@link laneMeasuresHome})。
341
311
  *
342
312
  * 认不出的车道 ⇒ `undefined`(调用方 fail-closed)。生产链上不可达:`loadConfig` 的 [ref] 拒启门先咬。
343
313
  */
344
314
  export declare function executionLaneHomeDir(deployment: LaneHomeDeployment): string | undefined;
345
315
  /**
346
- * 「这条部署的执行车道**有手**、家目录答不出、**而车道又没有读数办法**」时起服那一行的 `note`(纯字符串 ⇒ `build*`);否则 `undefined`(不出这一行)。
347
- * 判据只读 {@link executionLaneHomeDir}(boot 期的家目录)、能力表 `coreRemoteExecutionEnv` 位(有没有手)与 {@link laneMeasuresHome}(读不读得出):不另写车道清单。
348
- * 读得出的车道(k8s / local-docker / ssh / adb)没声明时由环境建起来那一拍实测,实测缺席才由那只环境响同一只事件码(`LaneHomeSeat`)—— 起服不替它们先说。
349
- * 代价如实:引擎 7.52.0 起家锚拒读行放不下 ⇒ 每一次泄内容的递归读在全 shell 面强制问人(allow / 模式 / bypass 都放不掉)、只读面拒;`~/` 形规则在下单时
350
- * 就被 422 拒。出路只有一条:声明执行环境的家目录(`$HOME` 读出来的那个绝对路径)。这句话陈述的是事实,不是告警 —— 要它消失就声明家目录。
316
+ * 部署交给适配器的家目录主张 —— `LaneHomeConfig` 的 `homeDir` / `homeDirSource` 两键(纯数据 ⇒ `build*`;唯一构造点:boot 装配、run-local 的 host 腿与
317
+ * leader 静态 e2b 腿都展开它)。值 = {@link executionLaneHomeDir};来源 = 运维声明在场 ⇒ `declared`,否则 `lane`(车道出厂答案)—— 只进拒句的改法。
318
+ * 本函数答不出(车道 boot 期不可知、运维也没声明)⇒ `{}`:适配器没有主张,读得出的车道自己量。
351
319
  */
352
- export declare function buildUndeclaredHomeNote(deployment: LaneHomeDeployment): string | undefined;
320
+ export declare function buildLaneHomeClaim(deployment: LaneHomeDeployment): Pick<LaneHomeConfig, "homeDir" | "homeDirSource">;
321
+ /**
322
+ * 起服关于本部署执行环境家目录的那一行(纯数据 ⇒ `build*`):`{ event, note }`,或 `undefined`(不出这一行)。只有**读不了**家目录的车道才由起服说 ——
323
+ * 读得出的车道({@link laneMeasuresHome})在每只环境开起来时自己证 / 自己量,出问题由那只环境说(拒,或同一只 `execution_lane_home_undeclared`)。
324
+ * · 无手(in-process)/ 认不出的车道 ⇒ 不出;
325
+ * · 读不了 ∧ 没有答案 ⇒ `execution_lane_home_undeclared`:代价如实(引擎 7.52.0 起家锚拒读行放不下 ⇒ 每一次泄内容的递归读在全 shell 面强制问人、只读面拒;
326
+ * `~/` 形规则下单 422),出路 = 声明家目录;
327
+ * · 读不了 ∧ 声明了 ⇒ `execution_lane_home_unmeasured`:座 = 声明、没有读数证过它 —— 对不上时规则守错目录,运维要守住「声明 = 环境里命令看到的 `$HOME`」。
328
+ * 判据只读 {@link executionLaneHomeDir}、{@link laneWiresExecutionEnv}(有没有手)与 {@link laneMeasuresHome}(读不读得出):不另写车道清单。
329
+ * 这两句陈述的是事实,不是告警 —— 要它们消失,换读得出家目录的车道(或对未声明的那一句:声明家目录)。
330
+ */
331
+ export declare function buildLaneHomeBootNote(deployment: LaneHomeDeployment): {
332
+ readonly event: string;
333
+ readonly note: string;
334
+ } | undefined;
335
+ /**
336
+ * 「部署要求读拒表的字节地板(`READ_DENY_FLOOR_REQUIRED=true`),而本部署车道的执行环境块不守地板」时起服那一行的 `note`(纯字符串 ⇒ `build*`);否则 `undefined`。
337
+ * 判据只读部署的要求与 {@link capabilitiesFor} 的 `keepsReadFloor`(认不出的车道答不出块 ⇒ 按不守说,不静默)。`in-process` 的桩块守地板 ⇒ 不出。
338
+ * 句子点名车道与键:这条车道上每个读拒表有行的 run(出厂读拒档在岗时就有行)都在准备期拒,一个命令都不起 —— 起服先把后果与两条出路说出来,
339
+ * 不让运维从第一条 409 才知道。
340
+ */
341
+ export declare function buildReadDenyFloorUnkeptNote(deployment: CapabilitiesDeployment & {
342
+ readonly readDenyFloorRequired: boolean;
343
+ }): string | undefined;
353
344
  //# sourceMappingURL=execution-lane-caps.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { homedir } from "node:os";
2
- import { EXECUTION_LANE_WORDS as DECLARABLE_LANE_WORDS, EXECUTION_LANES } from "@sema-agent/settings-schema/execution-lanes";
3
- import { isBlankCoordinate } from "@sema-agent/settings-schema";
4
- import { DECLARE_HOME_REMEDY, buildHomeAbsentNote } from "./lane-home-probe.js";
2
+ import { StubExecutionEnv } from "@sema-agent/core";
3
+ import { EXECUTION_LANE_WORDS as DECLARABLE_LANE_WORDS, EXECUTION_LANES, isBlankCoordinate } from "@sema-agent/settings-schema/execution-lanes";
4
+ import { DECLARE_HOME_REMEDY, LANE_HOME_UNDECLARED_EVENT, LANE_HOME_UNMEASURED_EVENT, buildHomeAbsentNote, buildHomeUnmeasuredNote } from "./lane-home-probe.js";
5
5
  const NO = "unsupported";
6
6
  const YES = "supported";
7
7
  const SU = "single-user-only";
@@ -14,15 +14,8 @@ export function executionLaneCaps(lane) {
14
14
  scheduler: NO,
15
15
  lsp: NO,
16
16
  sandboxSendUserFile: NO,
17
- isolation: NO,
18
- suspendable: NO,
19
17
  remoteScratchpad: NO,
20
- sandboxPathAdjudication: NO,
21
18
  worktreeIsolation: NO,
22
- memoryPersistenceCapable: NO,
23
- hostFilePlane: YES,
24
- coreRemoteExecutionEnv: NO,
25
- canonicalPathAuthority: NO,
26
19
  tenantSeparation: YES,
27
20
  };
28
21
  case "host":
@@ -32,15 +25,8 @@ export function executionLaneCaps(lane) {
32
25
  scheduler: SU,
33
26
  lsp: SU,
34
27
  sandboxSendUserFile: NO,
35
- isolation: NO,
36
- suspendable: NO,
37
28
  remoteScratchpad: NO,
38
- sandboxPathAdjudication: NO,
39
29
  worktreeIsolation: YES,
40
- memoryPersistenceCapable: YES,
41
- hostFilePlane: YES,
42
- coreRemoteExecutionEnv: YES,
43
- canonicalPathAuthority: YES,
44
30
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
45
31
  };
46
32
  case "e2b":
@@ -50,15 +36,8 @@ export function executionLaneCaps(lane) {
50
36
  scheduler: NO,
51
37
  lsp: NO,
52
38
  sandboxSendUserFile: YES,
53
- isolation: YES,
54
- suspendable: YES,
55
39
  remoteScratchpad: YES,
56
- sandboxPathAdjudication: YES,
57
40
  worktreeIsolation: NO,
58
- memoryPersistenceCapable: NO,
59
- hostFilePlane: NO,
60
- coreRemoteExecutionEnv: YES,
61
- canonicalPathAuthority: YES,
62
41
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
63
42
  };
64
43
  case "k8s":
@@ -68,15 +47,8 @@ export function executionLaneCaps(lane) {
68
47
  scheduler: NO,
69
48
  lsp: NO,
70
49
  sandboxSendUserFile: YES,
71
- isolation: YES,
72
- suspendable: YES,
73
50
  remoteScratchpad: YES,
74
- sandboxPathAdjudication: YES,
75
51
  worktreeIsolation: NO,
76
- memoryPersistenceCapable: NO,
77
- hostFilePlane: NO,
78
- coreRemoteExecutionEnv: YES,
79
- canonicalPathAuthority: YES,
80
52
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
81
53
  };
82
54
  case "ssh":
@@ -86,15 +58,8 @@ export function executionLaneCaps(lane) {
86
58
  scheduler: NO,
87
59
  lsp: NO,
88
60
  sandboxSendUserFile: SU,
89
- isolation: NO,
90
- suspendable: NO,
91
61
  remoteScratchpad: YES,
92
- sandboxPathAdjudication: YES,
93
62
  worktreeIsolation: NO,
94
- memoryPersistenceCapable: NO,
95
- hostFilePlane: NO,
96
- coreRemoteExecutionEnv: YES,
97
- canonicalPathAuthority: YES,
98
63
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
99
64
  };
100
65
  case "adb":
@@ -104,15 +69,8 @@ export function executionLaneCaps(lane) {
104
69
  scheduler: NO,
105
70
  lsp: NO,
106
71
  sandboxSendUserFile: NO,
107
- isolation: NO,
108
- suspendable: NO,
109
72
  remoteScratchpad: NO,
110
- sandboxPathAdjudication: YES,
111
73
  worktreeIsolation: NO,
112
- memoryPersistenceCapable: NO,
113
- hostFilePlane: NO,
114
- coreRemoteExecutionEnv: YES,
115
- canonicalPathAuthority: YES,
116
74
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
117
75
  };
118
76
  case "local-docker":
@@ -122,15 +80,8 @@ export function executionLaneCaps(lane) {
122
80
  scheduler: NO,
123
81
  lsp: NO,
124
82
  sandboxSendUserFile: NO,
125
- isolation: YES,
126
- suspendable: NO,
127
83
  remoteScratchpad: YES,
128
- sandboxPathAdjudication: YES,
129
84
  worktreeIsolation: NO,
130
- memoryPersistenceCapable: NO,
131
- hostFilePlane: NO,
132
- coreRemoteExecutionEnv: YES,
133
- canonicalPathAuthority: YES,
134
85
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
135
86
  };
136
87
  case "device":
@@ -140,19 +91,47 @@ export function executionLaneCaps(lane) {
140
91
  scheduler: NO,
141
92
  lsp: NO,
142
93
  sandboxSendUserFile: NO,
143
- isolation: NO,
144
- suspendable: NO,
145
94
  remoteScratchpad: YES,
146
- sandboxPathAdjudication: YES,
147
95
  worktreeIsolation: NO,
148
- memoryPersistenceCapable: NO,
149
- hostFilePlane: NO,
150
- coreRemoteExecutionEnv: YES,
151
- canonicalPathAuthority: YES,
152
96
  tenantSeparation: executionLaneRow(lane).tenantSeparation,
153
97
  };
154
98
  }
155
99
  }
100
+ const IN_PROCESS_BLOCK = new StubExecutionEnv().capabilities;
101
+ const HOST_BLOCK = Object.freeze({ isolation: false, suspendable: false, sharesProcessTable: true, canonicalPathAuthoritative: true, hostLocalPaths: true, externalContentTarget: false, io: true, keepsReadFloor: false });
102
+ const E2B_BLOCK = Object.freeze({ isolation: true, suspendable: true, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: false, io: true, keepsReadFloor: false });
103
+ const K8S_BLOCK = Object.freeze({ isolation: true, suspendable: false, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: false, io: true, keepsReadFloor: false });
104
+ const K8S_SNAPSHOT_BLOCK = Object.freeze({ ...K8S_BLOCK, suspendable: true });
105
+ const LOCAL_DOCKER_BLOCK = Object.freeze({ isolation: true, suspendable: false, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: false, io: true, keepsReadFloor: false });
106
+ const SSH_BLOCK = Object.freeze({ isolation: false, suspendable: false, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: false, io: true, keepsReadFloor: false });
107
+ const ADB_BLOCK = Object.freeze({ isolation: false, suspendable: false, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: false, io: true, keepsReadFloor: false });
108
+ const DEVICE_BLOCK = Object.freeze({ isolation: false, suspendable: false, sharesProcessTable: false, canonicalPathAuthoritative: true, hostLocalPaths: false, externalContentTarget: true, io: true, keepsReadFloor: false });
109
+ function laneBlock(lane, snapshotStore) {
110
+ switch (lane) {
111
+ case "in-process":
112
+ return IN_PROCESS_BLOCK;
113
+ case "host":
114
+ return HOST_BLOCK;
115
+ case "e2b":
116
+ return E2B_BLOCK;
117
+ case "k8s":
118
+ return snapshotStore ? K8S_SNAPSHOT_BLOCK : K8S_BLOCK;
119
+ case "local-docker":
120
+ return LOCAL_DOCKER_BLOCK;
121
+ case "ssh":
122
+ return SSH_BLOCK;
123
+ case "adb":
124
+ return ADB_BLOCK;
125
+ case "device":
126
+ return DEVICE_BLOCK;
127
+ }
128
+ }
129
+ export function capabilitiesFor(deployment) {
130
+ const lane = executionLaneOf(deployment.remoteExec?.provider);
131
+ if (lane === undefined)
132
+ return undefined;
133
+ return laneBlock(lane, lane === "k8s" && Boolean(deployment.remoteExec?.s3Snapshot));
134
+ }
156
135
  export const ALL_EXECUTION_LANES = Object.freeze(["in-process", ...DECLARABLE_LANE_WORDS]);
157
136
  const EXECUTION_LANE_SET = new Set(ALL_EXECUTION_LANES);
158
137
  export function isExecutionLane(word) {
@@ -210,8 +189,8 @@ export function deployedExecutionLanes(config) {
210
189
  return [executionLaneOf(config.remoteExec?.provider)];
211
190
  }
212
191
  export function handsOnWorkerFilePlane(lane) {
213
- const caps = executionLaneCaps(lane);
214
- return caps.hostFilePlane === "supported" && caps.coreRemoteExecutionEnv === "supported";
192
+ const block = laneBlock(lane, false);
193
+ return block.io && block.hostLocalPaths;
215
194
  }
216
195
  export function laneBindsReads(lane) {
217
196
  switch (lane) {
@@ -233,11 +212,11 @@ export function laneMeasuresHome(lane) {
233
212
  case "local-docker":
234
213
  case "ssh":
235
214
  case "adb":
215
+ case "e2b":
216
+ case "host":
236
217
  return true;
237
218
  case "device":
238
- case "host":
239
219
  case "in-process":
240
- case "e2b":
241
220
  return false;
242
221
  }
243
222
  }
@@ -257,23 +236,10 @@ export function laneReadFaceDefault(lane) {
257
236
  }
258
237
  export const LANE_OPEN_READ_FACE_CAUTION = "a deployment that mounts host paths or shared volumes into the sandbox (hostPath, bind mount) exposes those host files to reads on an open face — pin READ_FACE=roots or add read-deny rows (READ_DENY_PATTERNS) for them";
259
238
  export function laneIsolated(lane) {
260
- const isolation = executionLaneCaps(lane).isolation;
261
- switch (isolation) {
262
- case "supported":
263
- return true;
264
- case "unsupported":
265
- return false;
266
- }
239
+ return laneBlock(lane, false).isolation;
267
240
  }
268
241
  export function laneWiresExecutionEnv(lane) {
269
- const wired = executionLaneCaps(lane).coreRemoteExecutionEnv;
270
- switch (wired) {
271
- case "supported":
272
- return true;
273
- case "unsupported":
274
- case "single-user-only":
275
- return false;
276
- }
242
+ return laneBlock(lane, false).io;
277
243
  }
278
244
  export const PLANNED_LANE_DIVERGENCES = Object.freeze([]);
279
245
  export const E2B_SANDBOX_HOME = "/home/user";
@@ -298,14 +264,32 @@ export function executionLaneHomeDir(deployment) {
298
264
  return undefined;
299
265
  }
300
266
  }
301
- export function buildUndeclaredHomeNote(deployment) {
302
- if (executionLaneHomeDir(deployment) !== undefined)
303
- return undefined;
267
+ export function buildLaneHomeClaim(deployment) {
268
+ const home = executionLaneHomeDir(deployment);
269
+ if (home === undefined)
270
+ return {};
271
+ return { homeDir: home, homeDirSource: deployment.remoteExecHomeDir !== undefined ? "declared" : "lane" };
272
+ }
273
+ export function buildLaneHomeBootNote(deployment) {
304
274
  const lane = executionLaneOf(deployment.remoteExec?.provider);
305
- if (lane === undefined || executionLaneCaps(lane).coreRemoteExecutionEnv !== "supported")
275
+ if (lane === undefined || !laneWiresExecutionEnv(lane))
306
276
  return undefined;
307
277
  if (laneMeasuresHome(lane))
308
278
  return undefined;
309
- return buildHomeAbsentNote(lane, "REMOTE_EXEC_HOME_DIR is unset, and this lane cannot read its execution environment's home", DECLARE_HOME_REMEDY);
279
+ const home = executionLaneHomeDir(deployment);
280
+ if (home === undefined)
281
+ return { event: LANE_HOME_UNDECLARED_EVENT, note: buildHomeAbsentNote(lane, "REMOTE_EXEC_HOME_DIR is unset, and this lane cannot read its execution environment's home", DECLARE_HOME_REMEDY) };
282
+ return { event: LANE_HOME_UNMEASURED_EVENT, note: buildHomeUnmeasuredNote(lane, home) };
283
+ }
284
+ export function buildReadDenyFloorUnkeptNote(deployment) {
285
+ if (!deployment.readDenyFloorRequired)
286
+ return undefined;
287
+ if (capabilitiesFor(deployment)?.keepsReadFloor === true)
288
+ return undefined;
289
+ const lane = executionLaneOf(deployment.remoteExec?.provider) ?? String(deployment.remoteExec?.provider);
290
+ return (`READ_DENY_FLOOR_REQUIRED=true, but the "${lane}" execution lane does not keep the read-deny byte floor (a program its commands run can open a path ` +
291
+ `the read-deny table refuses). Every run whose read-deny table has rows — the shipped default tiers put rows there unless READ_DENY_BUILTIN_TIERS=none — ` +
292
+ `is refused before any command starts (config.read_deny_floor_unkept; a synchronous submit answers 409). ` +
293
+ `Either run on a lane that keeps the floor, or unset READ_DENY_FLOOR_REQUIRED to run with one operator notice per run instead.`);
310
294
  }
311
295
  //# sourceMappingURL=execution-lane-caps.js.map
@@ -8,7 +8,9 @@
8
8
  * core 的另外三只 409 与 `ControlPlaneCorruptError` 全落 500 `internal.error` —— 「同一个 requestId 拿去抹另一个会话」这种**调用方自己
9
9
  * 能改**的错被说成服务器坏了。两份分类 = 两个判官,少的那份恒是静默的一份。现在**码与状态**只在这里判一次,两面同读。
10
10
  *
11
- * ## 规则(三层,与 operator 面既有层序逐字同序)
11
+ * ## 规则(三层,与 operator 面既有层序逐字同序;另有本服务自铸的一只,先判)
12
+ * ⓪ 本服务的抹除店护栏拒 {@link MemoryErasureStoreUnjudged} —— 409 `memory.erasure_store_unjudged`(抹除落到部署的店之外的那只店:本部署此刻判不了
13
+ * 同一个 `requestId` 跨店的幂等;什么都没删)。文案按受众,同下一节的规则;
12
14
  * ① core 的**本口专属**码(闭集穷举 `switch`,见 {@link sentCoreCode})—— 码与状态两面同;文案按受众(下一节,一条规则);
13
15
  * ② **店形拒**两码 `memory.target_outside_store`(core 7.31.1 [ref])/ `memory.scope_home_not_directory`(core 7.44.0 [ref])—— 跨面 store 状态码,409、码原样
14
16
  * (判据 `memory-store-refusal.ts` 一只;运维行 `memory_store_form_refused { code, path?, form? }` 两受众同一只铸点,路径只在那里);