@sema-agent/server 7.139.0 → 7.141.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 (328) hide show
  1. package/MIGRATION.md +471 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +94 -26
  5. package/dist/adoption/runner.js +1 -1
  6. package/dist/adoption/sql.js +1 -1
  7. package/dist/approval-batch-census.d.ts +27 -0
  8. package/dist/approval-batch-census.js +27 -0
  9. package/dist/approval-card.d.ts +37 -22
  10. package/dist/approval-card.js +6 -3
  11. package/dist/approval.d.ts +15 -0
  12. package/dist/approval.js +10 -0
  13. package/dist/audit.d.ts +4 -2
  14. package/dist/audit.js +2 -2
  15. package/dist/bench/s1/live-deps.js +3 -2
  16. package/dist/bench/s1/row.d.ts +5 -2
  17. package/dist/bench/s1/row.js +2 -22
  18. package/dist/boot/adoption.js +1 -1
  19. package/dist/boot/device-lane.d.ts +11 -0
  20. package/dist/boot/device-lane.js +16 -0
  21. package/dist/boot/engine-lease.d.ts +24 -3
  22. package/dist/boot/engine-lease.js +9 -2
  23. package/dist/boot/execution-env.js +18 -12
  24. package/dist/boot/execution-lane.d.ts +8 -0
  25. package/dist/boot/execution-lane.js +6 -1
  26. package/dist/boot/memory-boundary.d.ts +16 -53
  27. package/dist/boot/memory-boundary.js +10 -20
  28. package/dist/boot/memory-consolidation.d.ts +16 -12
  29. package/dist/boot/memory-consolidation.js +24 -13
  30. package/dist/boot/reapers.d.ts +2 -2
  31. package/dist/boot/resolve-spec.d.ts +3 -5
  32. package/dist/boot/resolve-spec.js +9 -8
  33. package/dist/boot/runner-deps.d.ts +3 -3
  34. package/dist/boot/runner-deps.js +1 -0
  35. package/dist/boot/session-faces.d.ts +1 -1
  36. package/dist/boot/session-faces.js +4 -3
  37. package/dist/boot/shutdown.js +5 -0
  38. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  39. package/dist/boot/stage-03-store-backend.js +2 -3
  40. package/dist/boot/stage-04-stores.d.ts +2 -6
  41. package/dist/boot/stage-04-stores.js +5 -5
  42. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  43. package/dist/boot/stage-05-execution-env.js +3 -1
  44. package/dist/boot/stage-06-runners.d.ts +2 -8
  45. package/dist/boot/stage-06-runners.js +3 -3
  46. package/dist/boot/stage-07-capability-layer.d.ts +2 -7
  47. package/dist/boot/stage-07-capability-layer.js +8 -10
  48. package/dist/boot/stage-08-reapers.d.ts +2 -7
  49. package/dist/boot/stage-09-leader.d.ts +2 -7
  50. package/dist/boot/stage-10-http-server.d.ts +2 -7
  51. package/dist/boot/stage-10-http-server.js +6 -4
  52. package/dist/boot/stores.d.ts +3 -6
  53. package/dist/boot/stores.js +37 -44
  54. package/dist/boot/task-list-lane.d.ts +1 -1
  55. package/dist/boot/task-list-lane.js +1 -1
  56. package/dist/boot/web-admin.js +36 -9
  57. package/dist/capabilities/execution-lane.d.ts +2 -2
  58. package/dist/capabilities/scenarios.d.ts +1 -1
  59. package/dist/capability-facts.d.ts +9 -0
  60. package/dist/capability-facts.js +9 -0
  61. package/dist/card-void.d.ts +38 -0
  62. package/dist/card-void.js +23 -0
  63. package/dist/config-catalog.js +12 -8
  64. package/dist/config-provider.d.ts +18 -17
  65. package/dist/config-provider.js +28 -36
  66. package/dist/config-types.d.ts +36 -9
  67. package/dist/config.js +56 -46
  68. package/dist/delegated-session-owner.d.ts +23 -20
  69. package/dist/delegated-session-owner.js +2 -2
  70. package/dist/deployment-shape.d.ts +9 -8
  71. package/dist/deployment-shape.js +4 -4
  72. package/dist/device-store.d.ts +7 -0
  73. package/dist/device-store.js +3 -0
  74. package/dist/execution-config-root.d.ts +22 -0
  75. package/dist/execution-config-root.js +35 -0
  76. package/dist/execution-lane-caps.d.ts +145 -107
  77. package/dist/execution-lane-caps.js +144 -83
  78. package/dist/execution-placement.d.ts +3 -0
  79. package/dist/execution-placement.js +7 -0
  80. package/dist/fleet/drain-entry.d.ts +3 -0
  81. package/dist/hosted-posture.d.ts +8 -0
  82. package/dist/hosted-posture.js +4 -0
  83. package/dist/http/admission.js +3 -3
  84. package/dist/http/caller-trust.d.ts +3 -2
  85. package/dist/http/caller-trust.js +2 -1
  86. package/dist/http/dispatch.js +4 -0
  87. package/dist/http/live-frame.d.ts +24 -0
  88. package/dist/http/live-frame.js +16 -0
  89. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  90. package/dist/http/memory-compliance-failure-reply.js +5 -0
  91. package/dist/http/memory-layer-reply.d.ts +30 -0
  92. package/dist/http/memory-layer-reply.js +24 -0
  93. package/dist/http/resume-legs.js +49 -35
  94. package/dist/http/retired-service-deps.d.ts +1 -1
  95. package/dist/http/retired-service-deps.js +1 -1
  96. package/dist/http/route-table.js +2 -0
  97. package/dist/http/routes/adoption.js +1 -1
  98. package/dist/http/routes/approvals-assistant.js +1 -0
  99. package/dist/http/routes/capabilities.js +5 -4
  100. package/dist/http/routes/diagnostics.d.ts +0 -19
  101. package/dist/http/routes/diagnostics.js +16 -2
  102. package/dist/http/routes/memory-bundle.d.ts +2 -2
  103. package/dist/http/routes/memory-bundle.js +4 -1
  104. package/dist/http/routes/memory-compliance.js +9 -2
  105. package/dist/http/routes/memory-consolidation.js +12 -1
  106. package/dist/http/routes/memory-origin.js +14 -2
  107. package/dist/http/routes/memory-policy.js +7 -2
  108. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  109. package/dist/http/routes/run-permission-mode.js +170 -0
  110. package/dist/http/routes/session-sync.d.ts +3 -6
  111. package/dist/http/routes/session-sync.js +7 -2
  112. package/dist/http/routes/sessions.js +33 -15
  113. package/dist/http/routes/tasks.js +67 -68
  114. package/dist/http/run-read-face.js +3 -3
  115. package/dist/http/send.d.ts +1 -1
  116. package/dist/http/send.js +2 -2
  117. package/dist/http/server.d.ts +14 -27
  118. package/dist/http/server.js +2 -2
  119. package/dist/http/sse-log.d.ts +3 -8
  120. package/dist/http/stored-body-replay.d.ts +3 -3
  121. package/dist/http/stored-body-replay.js +3 -1
  122. package/dist/identity-source.d.ts +1 -1
  123. package/dist/identity-source.js +1 -1
  124. package/dist/instruction-source-notice.d.ts +7 -0
  125. package/dist/instruction-source-notice.js +6 -6
  126. package/dist/lane-home-probe.d.ts +68 -42
  127. package/dist/lane-home-probe.js +53 -30
  128. package/dist/leader/wire.js +5 -4
  129. package/dist/mcp-assertion-header.d.ts +4 -0
  130. package/dist/mcp-assertion-header.js +5 -0
  131. package/dist/memory-bundle-engine.d.ts +16 -9
  132. package/dist/memory-bundle-engine.js +29 -6
  133. package/dist/memory-operator-faces.d.ts +85 -30
  134. package/dist/memory-operator-faces.js +136 -30
  135. package/dist/memory-posture.d.ts +1 -1
  136. package/dist/memory-project-layer.d.ts +3 -21
  137. package/dist/memory-project-layer.js +11 -8
  138. package/dist/memory-scope-stores.d.ts +73 -0
  139. package/dist/memory-scope-stores.js +86 -0
  140. package/dist/memory-scope.d.ts +33 -9
  141. package/dist/memory-scope.js +17 -5
  142. package/dist/memory-sync-client.d.ts +34 -9
  143. package/dist/memory-sync-client.js +108 -28
  144. package/dist/observability/fail-open.d.ts +30 -2
  145. package/dist/observability/fail-open.js +30 -2
  146. package/dist/observability/metrics.js +0 -1
  147. package/dist/observability/run-terminal.d.ts +6 -2
  148. package/dist/observability/run-terminal.js +25 -26
  149. package/dist/observability/secret-env-scrub.d.ts +20 -1
  150. package/dist/observability/secret-env-scrub.js +14 -0
  151. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  152. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  153. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  154. package/dist/orchestration/workflow-notify-journal.js +2 -1
  155. package/dist/permission-mode-admission.d.ts +68 -0
  156. package/dist/permission-mode-admission.js +23 -0
  157. package/dist/permission-rule-list.d.ts +55 -6
  158. package/dist/permission-rule-list.js +52 -5
  159. package/dist/plugins/adoption-log-sql.js +4 -4
  160. package/dist/plugins/approval-ask-store-sql.js +14 -14
  161. package/dist/plugins/approval-nonce-store.js +4 -4
  162. package/dist/plugins/blob-backend.d.ts +4 -4
  163. package/dist/plugins/blob-backend.js +7 -7
  164. package/dist/plugins/breaker-state-sql.js +2 -2
  165. package/dist/plugins/caching-session-store.d.ts +6 -0
  166. package/dist/plugins/caching-session-store.js +3 -0
  167. package/dist/plugins/checkpoint-index-columns.js +2 -2
  168. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  169. package/dist/plugins/checkpoint-store-sql.js +90 -19
  170. package/dist/plugins/device-store-sql.d.ts +5 -2
  171. package/dist/plugins/device-store-sql.js +23 -20
  172. package/dist/plugins/ensure-index.d.ts +1 -2
  173. package/dist/plugins/execution-placement-sql.d.ts +19 -9
  174. package/dist/plugins/execution-placement-sql.js +20 -9
  175. package/dist/plugins/file-history-store-sql.d.ts +2 -2
  176. package/dist/plugins/file-history-store-sql.js +4 -4
  177. package/dist/plugins/file-run-store.d.ts +2 -2
  178. package/dist/plugins/file-run-store.js +1 -1
  179. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  180. package/dist/plugins/fork-routing-session-store.js +2 -61
  181. package/dist/plugins/image-bake-store-sql.js +9 -9
  182. package/dist/plugins/image-index-sql.js +11 -11
  183. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  184. package/dist/plugins/k8s-exec-protocol.js +6 -1
  185. package/dist/plugins/leader-run-store-sql.js +4 -4
  186. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  187. package/dist/plugins/local-checkpoint-store.js +22 -0
  188. package/dist/plugins/local-session-store.d.ts +227 -35
  189. package/dist/plugins/local-session-store.js +518 -37
  190. package/dist/plugins/local-session-window.d.ts +17 -3
  191. package/dist/plugins/local-session-window.js +7 -13
  192. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  193. package/dist/plugins/mailbox-store-sql.js +4 -4
  194. package/dist/plugins/memory-engine-tidb.js +5 -5
  195. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  196. package/dist/plugins/memory-run-store.d.ts +2 -2
  197. package/dist/plugins/memory-run-store.js +1 -1
  198. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  199. package/dist/plugins/one-time-migrations.d.ts +52 -11
  200. package/dist/plugins/one-time-migrations.js +101 -39
  201. package/dist/plugins/org-delivery-quota-store.js +2 -2
  202. package/dist/plugins/outcome-ledger-sql.js +2 -2
  203. package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
  204. package/dist/plugins/permission-rule-store-sql.js +16 -16
  205. package/dist/plugins/pg-pool.js +3 -2
  206. package/dist/plugins/pg-session-storage.d.ts +2 -0
  207. package/dist/plugins/pg-session-storage.js +3 -2
  208. package/dist/plugins/remote-env-adb.d.ts +7 -24
  209. package/dist/plugins/remote-env-adb.js +22 -5
  210. package/dist/plugins/remote-env-device.d.ts +2 -28
  211. package/dist/plugins/remote-env-device.js +2 -1
  212. package/dist/plugins/remote-env-e2b.d.ts +40 -27
  213. package/dist/plugins/remote-env-e2b.js +180 -20
  214. package/dist/plugins/remote-env-file-error.d.ts +1 -1
  215. package/dist/plugins/remote-env-file-error.js +8 -2
  216. package/dist/plugins/remote-env-host.d.ts +19 -35
  217. package/dist/plugins/remote-env-host.js +26 -3
  218. package/dist/plugins/remote-env-k8s.d.ts +22 -14
  219. package/dist/plugins/remote-env-k8s.js +150 -26
  220. package/dist/plugins/remote-env-local-docker.d.ts +27 -24
  221. package/dist/plugins/remote-env-local-docker.js +91 -24
  222. package/dist/plugins/remote-env-ssh.d.ts +4 -24
  223. package/dist/plugins/remote-env-ssh.js +4 -3
  224. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  225. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  226. package/dist/plugins/retention-lane-store-sql.js +2 -2
  227. package/dist/plugins/retention-store-sql.d.ts +1 -1
  228. package/dist/plugins/retention-store-sql.js +6 -6
  229. package/dist/plugins/run-store-sql.d.ts +3 -3
  230. package/dist/plugins/run-store-sql.js +19 -18
  231. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  232. package/dist/plugins/sandbox-read-floor.js +608 -0
  233. package/dist/plugins/schema-consistency.d.ts +6 -6
  234. package/dist/plugins/schema-consistency.js +1 -1
  235. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  236. package/dist/plugins/schema-ensure-legs.js +2 -2
  237. package/dist/plugins/schema-live-columns.d.ts +1 -1
  238. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  239. package/dist/plugins/session-ownership.d.ts +2 -1
  240. package/dist/plugins/session-placement.d.ts +17 -4
  241. package/dist/plugins/session-placement.js +2 -1
  242. package/dist/plugins/session-rules-column.d.ts +1 -1
  243. package/dist/plugins/session-rules-column.js +1 -1
  244. package/dist/plugins/session-store.d.ts +18 -20
  245. package/dist/plugins/session-store.js +4 -12
  246. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  247. package/dist/plugins/session-workspace-cell.js +1 -1
  248. package/dist/plugins/shared-memory-store-sql.js +2 -2
  249. package/dist/plugins/sql-driver.d.ts +10 -5
  250. package/dist/plugins/sql-driver.js +6 -6
  251. package/dist/plugins/sql-errors.js +1 -1
  252. package/dist/plugins/store-backend.d.ts +35 -6
  253. package/dist/plugins/store-backend.js +27 -10
  254. package/dist/plugins/store-contracts.d.ts +9 -2
  255. package/dist/plugins/task-list-store-sql.js +11 -11
  256. package/dist/plugins/tidb-pool.js +7 -6
  257. package/dist/plugins/tidb-session-storage.js +4 -4
  258. package/dist/plugins/tidb-session-store.d.ts +4 -1
  259. package/dist/plugins/tidb-session-store.js +16 -15
  260. package/dist/plugins/tool-result-store-sql.d.ts +2 -2
  261. package/dist/plugins/tool-result-store-sql.js +3 -3
  262. package/dist/plugins/user-input-ledger-sql.js +2 -2
  263. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  264. package/dist/plugins/workflow-run-store-sql.js +19 -19
  265. package/dist/plugins/write-behind-counter.d.ts +2 -3
  266. package/dist/plugins/write-behind-counter.js +5 -5
  267. package/dist/resource-suspend.d.ts +14 -12
  268. package/dist/resource-suspend.js +1 -1
  269. package/dist/resource-window.d.ts +4 -3
  270. package/dist/run-cancel-context.d.ts +34 -0
  271. package/dist/run-cancel-context.js +7 -0
  272. package/dist/run-local.js +14 -19
  273. package/dist/runs.d.ts +47 -16
  274. package/dist/runs.js +112 -113
  275. package/dist/security.d.ts +2 -2
  276. package/dist/server-secret-env.d.ts +2 -1
  277. package/dist/server-secret-env.js +2 -4
  278. package/dist/session-error-wire.d.ts +22 -4
  279. package/dist/session-error-wire.js +16 -0
  280. package/dist/session-incarnation.d.ts +10 -4
  281. package/dist/session-incarnation.js +1 -1
  282. package/dist/session-policy-wire.d.ts +1 -1
  283. package/dist/session-sync-kernel.d.ts +42 -1
  284. package/dist/session-sync-kernel.js +17 -0
  285. package/dist/session-sync.js +16 -4
  286. package/dist/sql-engine-coordinates.d.ts +49 -0
  287. package/dist/sql-engine-coordinates.js +27 -0
  288. package/dist/sql-engine-posture.d.ts +1 -1
  289. package/dist/sql-engine-posture.js +1 -1
  290. package/dist/standing-answer-grant.d.ts +31 -2
  291. package/dist/standing-answer-grant.js +14 -2
  292. package/dist/store-posture.d.ts +1 -1
  293. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  294. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  295. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  296. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  297. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  298. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  299. package/dist/task-a2a.d.ts +1 -1
  300. package/dist/task-a2a.js +5 -6
  301. package/dist/task-mcp.d.ts +21 -8
  302. package/dist/task-mcp.js +17 -9
  303. package/dist/task-settings.d.ts +52 -25
  304. package/dist/task-settings.js +91 -28
  305. package/dist/terminal.d.ts +103 -19
  306. package/dist/terminal.js +72 -20
  307. package/dist/trace/core-keyset-guard.d.ts +79 -2
  308. package/dist/trace/exit-seat.d.ts +7 -0
  309. package/dist/trace/exit-seat.js +1 -0
  310. package/dist/trace/model-segment.d.ts +2 -2
  311. package/dist/trace/redact.d.ts +3 -1
  312. package/dist/trace/redact.js +395 -110
  313. package/dist/trace/self-minted-wire.d.ts +226 -2
  314. package/dist/trace/self-minted-wire.js +79 -0
  315. package/dist/verifier-pause-card.d.ts +8 -0
  316. package/dist/verifier-pause-card.js +19 -0
  317. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  318. package/dist/web-admin-client/apply-effective.js +2 -2
  319. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  320. package/dist/web-admin-client/candidate-gate.js +1 -1
  321. package/dist/web-admin-client/http-client.d.ts +5 -4
  322. package/dist/web-admin-client/http-client.js +2 -2
  323. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  324. package/dist/web-admin-client/read-warnings.js +5 -9
  325. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  326. package/package.json +2 -2
  327. package/wire-changes/server@7.140.0.json +184 -0
  328. package/wire-changes/server@7.141.0.json +367 -0
@@ -149,6 +149,15 @@ export interface ReadRuleOffer {
149
149
  * 缺席(`undefined`)= 没有提议,答空、不计。展示帽(条数、成员前缀、扫描窗)、脱敏与截长归调用方 —— 它们是各腿的展示纪律,不是读法。
150
150
  */
151
151
  export declare function readRuleOfferList(raw: unknown): readonly ReadRuleOffer[];
152
+ /**
153
+ * 一份(已解码的)规则提议列表里,**带着无 `kind` 存量成员**的 batch offer 有几只 —— 判官是 core `readRuleOffers` 给每只读出的 offer 打的 `kindlessForm` 记号
154
+ * (「这一只 batch 里至少一个成员是经无 `kind` 的存量形读的」;与 {@link readRuleOfferList} 同一只读者,不是本仓自己再写一遍「成员没有 `kind` 键」)。
155
+ * 起服普查(`approval-batch-census.ts`)用它给存量行记数:读者那条存量臂退役的前提是「零行还靠它读」。
156
+ *
157
+ * **只数,不落任何痕迹**:读不出的元素(`dropped`)与整只值不是列表(`problem`)是 {@link readRuleOfferList} 的计数口径(`server.rule-offers.offer-dropped`),这里不重复记,
158
+ * 它们也不是「靠存量臂读出来」的 —— 一个读不出的无 `kind` 成员(缺文本键)退役前后同样被丢,不改变任何一行的读法,所以不计入。
159
+ */
160
+ export declare function countKindlessBatchOffers(raw: unknown): number;
152
161
  /**
153
162
  * 卡面/帧面共用的 offer **投影型**(= {@link RuleOfferSchema} 的输出形)。判别位 `kind` 上闭集,
154
163
  * 消费端(SDK/cli 渲染)按 core 契约分臂;`batch.rules` 成员是判别联合(`command` | `directoryRead`),
@@ -441,11 +450,13 @@ export interface AskClassPair {
441
450
  * bypass 姿态下按 `ask_rule` / `hook` 照问的那条壳规则无从落地。缺席 = 老行(core 7.5.0 之前 park 的)/ 集外词(计 [ref] tag)。
442
451
  * [ref] ②(core 7.37.0 [ref])第六 / 七位 `askClass` / `classes`:这一问的类对(经 {@link readAskClassPair};两位同在同缺,与活卡帧 / 呈卡帧的卡
443
452
  * 同名同义同值)—— durable 审批席按类答的依据。缺席 = 老行(core 7.37.0 之前 park 的,续跑不补)/ 读不出(计 [ref] tag)。
444
- * [ref](core 7.51.0 [ref])第八位 `boundGrantAbsence`:这张卡为什么没有授予绑定摘要(经 {@link readClosedWordSeat};与活卡帧 / inbox 行同名同义同值)——
445
- * `not_bindable` = 这一问不绑任何授予(「本会话放行」可按工具记)。缺席 = 技能卡(带摘要;摘要与清单、成因词三位走另一只投影 {@link skillCardFacts},见其顶注)/ 7.51.0 之前停驻的行(core inbox 投
446
- * `unreadable`,队列行如实缺席)/ 集外词(计 [ref] tag)。
453
+ * [ref](core 7.51.0 [ref])第八位 `boundGrantAbsence` / [ref] 起与 `boundGrantDigest` 合成**一臂**:这张卡的授予绑定 —— `tool_approval` 行**恰带**两者之一,
454
+ * 经本仓唯一读口 `grantBindingOf` 读停驻行、`grantBindingArm` 投回(`standing-answer-grant.ts`;与 core 投 inbox 行的那一臂逐形同值):摘要是串 ⇒ 摘要;
455
+ * 否则摘要键不在且行上的词是闭集成员 ⇒ 那个词;否则(7.51.0 之前停驻的行两者都不说 / 集外词 / 摘要在却不是串)⇒ `unreadable`。`not_bindable` = 这一问不绑任何授予
456
+ * (「本会话放行」可按工具记)。摘要读自停驻行本身 —— 不靠整行的检查点摘要,所以 SQL 腿那一次整行读失败也不丢这一臂;要 core 校验的清单与成因词走
457
+ * 另一只投影 {@link skillCardFacts}。
447
458
  */
448
- export type ParkRowFacts = Pick<ToolApprovalPark, "requiresRealApproval" | "ruleOffersAbsence" | "mandated" | "mandate" | "origin" | "askClass" | "classes" | "boundGrantAbsence">;
459
+ export type ParkRowFacts = Pick<ToolApprovalPark, "requiresRealApproval" | "ruleOffersAbsence" | "mandated" | "mandate" | "origin" | "askClass" | "classes" | "boundGrantDigest" | "boundGrantAbsence">;
449
460
  /**
450
461
  * [ref] —— park 行事实的**唯一投影**(`pendingAction` 是寄存行上 core 铸的那一只,读自持久层 ⇒ `unknown`)。
451
462
  *
@@ -465,7 +476,8 @@ export type ParkRowFacts = Pick<ToolApprovalPark, "requiresRealApproval" | "rule
465
476
  * park 孪生座与同步座是 core 同一个 factory 铸的同一闭集,不另起第二份词表;
466
477
  * · `mandate` / `origin` —— 经 {@link readClosedWordSeat}(一座一只 core 成员筛 `isPersistedRuleMandate` / `isAskOrigin`,与 core
467
478
  * `summarizeCheckpoint` 投 inbox 行时是同一只筛 ⇒ 两条耐久读面对同一张行同答;集外词读作缺席 + 计同一个集外 tag);
468
- * · 缺席 ≠ false:各位都只在「真 / 有词」时在场,消费端读**在场**。
479
+ * · 授予绑定([ref])—— 不是「在场才带」的一位,是恰一臂:`grantBindingArm(grantBindingOf(行))`,读法见 {@link ParkRowFacts} 顶注;
480
+ * · 缺席 ≠ false:其余各位都只在「真 / 有词」时在场,消费端读**在场**。
469
481
  *
470
482
  * 🔴 **这是展示/分诊投影,不是权限判据**(core 对两位的定性都是 display metadata:「the resume belts keep reading
471
483
  * the gate's own bit」)。本投影对「在场却读不出」的方向是**缺席**(卡上少一行 ≪ 卡上出现生词);一条要从
@@ -474,28 +486,31 @@ export type ParkRowFacts = Pick<ToolApprovalPark, "requiresRealApproval" | "rule
474
486
  */
475
487
  export declare function parkRowFacts(stored: unknown): ParkRowFacts;
476
488
  /**
477
- * 🔴 **技能卡三位的唯一投影**:授予绑定摘要 `boundGrantDigest`、它哈希的清单 `boundGrants`、分类器没给判词的成因 `classifierNoRuling` ——
489
+ * 🔴 **技能卡两位的唯一投影**:授予绑定摘要哈希的那一份清单 `boundGrants`、分类器没给判词的成因 `classifierNoRuling` ——
478
490
  * 助手收件箱行(`GET /v1/assistant/inbox`)、运维队列行(`GET /v1/approvals` 的 `pending[]`)、`/v1/approvals/stream` 的 `pending` 帧三张停驻读面
479
491
  * **经这一只函数**投它们。同一张停驻的技能卡于是三面同一份字节:运维从队列决这张卡时,看得到批准它还授予了什么。
492
+ * (摘要本身 `boundGrantDigest` 不在这里:它是授予绑定那一臂的一半,队列两面经 {@link parkRowFacts} 从停驻行读 —— core 对串摘要也是原样回显,值相同;
493
+ * [ref] 起这样分,是为了那一臂不依赖整行的检查点摘要读得到读不到。)
480
494
  *
481
- * **输入恒是 core 的检查点摘要**({@link CoreCheckpointSummary},`summarizeCheckpoint` 的产物)—— 三位的校验点单点在 core:摘要是串才回显;清单**只在哈希等于摘要时**才发布
495
+ * **输入恒是 core 的检查点摘要**({@link CoreCheckpointSummary},`summarizeCheckpoint` 的产物)—— 两位的校验点单点在 core:清单**只在哈希等于摘要时**才发布
482
496
  * (「never a list beside a digest that binds another」—— 一份与摘要对不上的清单会让批准人看着一份清单、批的却是另一份绑定);成因词只在闭集成员时回显。
483
- * 本仓**不重算哈希**(core 的 `boundInputHashOf` 不在公开导出面上,清单校验读口 `readBoundBinding` 同样不导出),所以**不许**拿寄存行 `pendingAction` 上的原值直接投 ——
484
- * 原值上的清单是未经哈希校验的(这正是三位此前不上队列行的原因,见 `trace/core-keyset-guard.ts` ⑧b 记账的旧注)。两只店各自拿到「这一行的摘要」的办法不同
485
- * (LOCAL 孪生本来就握着 core 对同一行投的摘要;SQL 孪生对带三位之一的行读一次该行再调 core 的 `summarizeCheckpoint`,见 `plugins/checkpoint-store-sql.ts`),
497
+ * 本仓**不重算哈希**(core 的 `boundInputHashOf` 不在公开导出面上,清单校验读口 `readBoundBinding` 同样不导出),所以**不许**拿寄存行 `pendingAction` 上的原清单直接投 ——
498
+ * 原值上的清单是未经哈希校验的(这正是它此前不上队列行的原因,见 `trace/core-keyset-guard.ts` ⑧b 记账的旧注)。两只店各自拿到「这一行的摘要」的办法不同
499
+ * (LOCAL 孪生本来就握着 core 对同一行投的摘要;SQL 孪生对可能带两位之一的行读一次该行再调 core 的 `summarizeCheckpoint`,见 `plugins/checkpoint-store-sql.ts`),
486
500
  * 但投影只有这一只:OMIT 契约 —— 缺席即缺席,恒不铸 `undefined` 值的键。
487
501
  *
488
502
  * `boundGrants` 是**部署文本**(技能名、清单条目):本函数不脱敏、不转义,与收件箱行逐字同口径 —— 渲染按上下文转义是客户端的事(契约同句)。
489
- * 三位都不进 `card_json`(同步路铸点,另一条纪律)。
503
+ * 两位都不进 `card_json`(同步路铸点,另一条纪律)。
490
504
  *
491
- * 🚧 清单校验读口 `readBoundBinding` 若成为 core 的公开导出,SQL 孪生那一次整行读与 {@link parkRowCarriesSkillCardFacts} 一并退役:`parkRowFacts` 直接读寄存行原值经 core 的读口投三位。
505
+ * 🚧 清单校验读口 `readBoundBinding` 若成为 core 的公开导出,SQL 孪生那一次整行读与 {@link parkRowCarriesSkillCardFacts} 一并退役:`parkRowFacts` 直接读寄存行原值经 core 的读口投两位
506
+ * (`grantBindingOf` 也改成它的薄包装 —— 那时 core 是绑定读法的唯一属主)。
492
507
  */
493
- export type SkillCardFacts = Pick<CoreCheckpointSummary, "boundGrantDigest" | "boundGrants" | "classifierNoRuling">;
508
+ export type SkillCardFacts = Pick<CoreCheckpointSummary, "boundGrants" | "classifierNoRuling">;
494
509
  export declare function skillCardFacts(summary: SkillCardFacts): SkillCardFacts;
495
510
  /**
496
- * 这一行的寄存行(`pendingAction`,读自持久层 ⇒ `unknown`)**有没有可能**让 core 的摘要投出三位里的任何一位 —— 只回答「值不值得为它取一次摘要」,**不投值**:
497
- * `tool_approval` 臂上摘要字段是串(core 只在这时回显摘要与清单),或成因词键在场(是不是闭集成员由 core 的摘要判)。判错的方向只有一个 —— 多取一次摘要(摘要读数为空),
498
- * 绝不漏取:摘要字段不是串 ⇒ core 的摘要既无摘要也无清单;成因词键不在 ⇒ 无成因词 —— 两者都不满足的行,摘要里这三位恒空。普通卡(绝大多数行)因此零额外读。
511
+ * 这一行的寄存行(`pendingAction`,读自持久层 ⇒ `unknown`)**有没有可能**让 core 的摘要投出两位里的任何一位 —— 只回答「值不值得为它取一次摘要」,**不投值**:
512
+ * `tool_approval` 臂上摘要字段是串(core 只在这时回显清单),或成因词键在场(是不是闭集成员由 core 的摘要判)。判错的方向只有一个 —— 多取一次摘要(摘要读数为空),
513
+ * 绝不漏取:摘要字段不是串 ⇒ core 的摘要没有清单;成因词键不在 ⇒ 无成因词 —— 两者都不满足的行,摘要里这两位恒空。普通卡(绝大多数行)因此零额外读。
499
514
  * 只读键在不在 / 是不是串,不读值的内容,所以不需要 {@link readClosedWordSeat} 那样的计数。
500
515
  */
501
516
  export declare function parkRowCarriesSkillCardFacts(stored: unknown): boolean;
@@ -556,12 +571,12 @@ export declare const ApprovalCardSchema: z.ZodObject<{
556
571
  question: "question";
557
572
  plan: "plan";
558
573
  skill: "skill";
559
- shell: "shell";
560
574
  workflow: "workflow";
561
- fetch: "fetch";
562
- "file-write": "file-write";
563
575
  "file-edit": "file-edit";
576
+ "file-write": "file-write";
564
577
  "notebook-edit": "notebook-edit";
578
+ shell: "shell";
579
+ fetch: "fetch";
565
580
  generic: "generic";
566
581
  }>>;
567
582
  inputHasBidi: z.ZodOptional<z.ZodLiteral<true>>;
@@ -710,12 +725,12 @@ export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
710
725
  question: "question";
711
726
  plan: "plan";
712
727
  skill: "skill";
713
- shell: "shell";
714
728
  workflow: "workflow";
715
- fetch: "fetch";
716
- "file-write": "file-write";
717
729
  "file-edit": "file-edit";
730
+ "file-write": "file-write";
718
731
  "notebook-edit": "notebook-edit";
732
+ shell: "shell";
733
+ fetch: "fetch";
719
734
  generic: "generic";
720
735
  }>>;
721
736
  inputHasBidi: z.ZodOptional<z.ZodLiteral<true>>;
@@ -4,6 +4,7 @@ import { redactSecrets } from "./trace/redact.js";
4
4
  import { recordFailOpen } from "./observability/fail-open.js";
5
5
  import { readApprovalCard } from "./approval-content-kind.js";
6
6
  import { capText } from "./caller-text-echo.js";
7
+ import { grantBindingArm, grantBindingOf } from "./standing-answer-grant.js";
7
8
  import { retireParkArmWords, retireStoredCardWords } from "./retired-card-words.js";
8
9
  export const MAX_AGENT_NAME = 200;
9
10
  const MAX_IDENT = 200;
@@ -61,6 +62,10 @@ export function readRuleOfferList(raw) {
61
62
  reading.dropped.forEach((d) => recordOfferDropped(d.problem, d.index));
62
63
  return reading.offers.map(withDetailSeatBounded);
63
64
  }
65
+ export function countKindlessBatchOffers(raw) {
66
+ const reading = readRuleOffers(raw);
67
+ return "problem" in reading ? 0 : reading.offers.filter((o) => o.kindlessForm === true).length;
68
+ }
64
69
  function withoutOverCapDetailSeat(item, index) {
65
70
  if (typeof item !== "object" || item === null)
66
71
  return item;
@@ -335,7 +340,6 @@ export function parkRowFacts(stored) {
335
340
  const mandate = readClosedWordSeat(pendingAction, "mandate");
336
341
  const origin = readClosedWordSeat(pendingAction, "origin");
337
342
  const askClassPair = readAskClassPair(pendingAction);
338
- const boundGrantAbsence = readClosedWordSeat(pendingAction, "boundGrantAbsence");
339
343
  return {
340
344
  ...(readParkRowTrueSeat(pendingAction, "requiresRealApproval") ? { requiresRealApproval: true } : {}),
341
345
  ...(readParkRowTrueSeat(pendingAction, "mandated") ? { mandated: true } : {}),
@@ -343,12 +347,11 @@ export function parkRowFacts(stored) {
343
347
  ...(origin !== undefined ? { origin } : {}),
344
348
  ...(ruleOffersAbsence !== undefined ? { ruleOffersAbsence } : {}),
345
349
  ...(askClassPair ?? {}),
346
- ...(boundGrantAbsence !== undefined ? { boundGrantAbsence } : {}),
350
+ ...grantBindingArm(grantBindingOf(pendingAction)),
347
351
  };
348
352
  }
349
353
  export function skillCardFacts(summary) {
350
354
  return {
351
- ...(summary.boundGrantDigest !== undefined ? { boundGrantDigest: summary.boundGrantDigest } : {}),
352
355
  ...(summary.boundGrants !== undefined ? { boundGrants: summary.boundGrants } : {}),
353
356
  ...(summary.classifierNoRuling !== undefined ? { classifierNoRuling: summary.classifierNoRuling } : {}),
354
357
  };
@@ -95,6 +95,21 @@ export declare function buildNoResponderBootWarns(input: {
95
95
  hint: string;
96
96
  };
97
97
  }>;
98
+ /**
99
+ * 单用户 turnkey 起服行 `tool_policy_single_user_default` 的**载荷**(纯数据 ⇒ `build*`;打不打、用哪只 logger 归 stage-07 的调用点,
100
+ * 打的判据是 {@link singleUserAutoAcceptBaselineApplies})。文案只此一处。
101
+ *
102
+ * 它说的是**部署工具策略层**的姿势:这一层铺的是一条在场的、看效果的 allow-all 基线(`createApprovalBaselinePolicy(config, { kind: "absent" })`),
103
+ * 好让引擎的「写手无裁决」告警不再响 —— 这一层自己不问也不拒。它**不是逐调用的放行**:每次调用仍由本次运行的权限模式与引擎写门裁(`auto` 下 shell 的写 / 删
104
+ * 照样出问并交分类器)。修前这一句写成「ALL write/hand/MCP tool surfaces auto-allowed」,读者(含取证)把它读成逐调用放行,与运行期读数相反。
105
+ */
106
+ export declare function buildSingleUserDefaultPostureNotice(): {
107
+ event: "tool_policy_single_user_default";
108
+ fields: {
109
+ posture: string;
110
+ tighten: string;
111
+ };
112
+ };
98
113
  /**
99
114
  * [ref] 件⑩ —— **center 的 `forceDurableGate` 在无 checkpoint 店的部署上会静默 inert**,补一条 boot 披露。
100
115
  *
package/dist/approval.js CHANGED
@@ -53,6 +53,16 @@ export function buildNoResponderBootWarns(input) {
53
53
  }
54
54
  return out;
55
55
  }
56
+ export function buildSingleUserDefaultPostureNotice() {
57
+ return {
58
+ event: "tool_policy_single_user_default",
59
+ fields: {
60
+ posture: "deployment tool-policy baseline is allow-all — this layer asks no question and refuses nothing of its own (core's per-surface UNGATED enumeration is suppressed for single-user turnkey). " +
61
+ "It is not a per-call verdict: each call is still judged by the run's permission mode and the engine's write gate — a shell write or delete can still be asked, or handed to the classifier under auto",
62
+ tighten: "APPROVAL_REQUIRE / AUTONOMY / commandPolicy (re-surfaces + gates specific surfaces)",
63
+ },
64
+ };
65
+ }
56
66
  export function buildForceDurableGateInertNotice(input) {
57
67
  if (!input.entitlementSourceWired || input.checkpointStorePresent)
58
68
  return undefined;
package/dist/audit.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type SessionPlacementRecord, type StoredPromptEpoch } from "@sema-agent/core";
2
2
  import type { Pool } from "mysql2/promise";
3
3
  import type { Pool as PgPool } from "pg";
4
+ import { type LocalSessionRows } from "./plugins/local-session-window.js";
4
5
  /**
5
6
  * Audit view of a session = its **current context** (the live messages + the last compaction's
6
7
  * summary), i.e. the floor-bounded window — never the full raw transcript. This matches the
@@ -76,10 +77,11 @@ export declare function buildSessionAudit(pool: Pool, sessionId: string, handles
76
77
  * audit face was TiDB-only and a PG/local deployment 404'd the whole web session area. */
77
78
  export declare function buildSessionAuditPg(pool: PgPool, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
78
79
  /** The LOCAL (File) leg — web session area on DB_BACKEND=local: the same view over `LocalSessionWindow.wake`
79
- * (`plugins/local-session-window.ts`). All three legs read one way — a bounded window that carries the epoch anchor below its
80
+ * (`plugins/local-session-window.ts`), read from the local session store's rows (its row projection and its log export — the view's
81
+ * `createdAt` is the row's, as on the SQL twins). All three legs read one way — a bounded window that carries the epoch anchor below its
80
82
  * floor — and on every backend that is what the run reads: the SQL twins' run wakes the same window; the local run wakes the whole
81
83
  * tree, and the local window is cut from that tree's branch, with the anchor walking the branch below the floor. */
82
- export declare function buildSessionAuditLocal(root: string, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
84
+ export declare function buildSessionAuditLocal(rows: LocalSessionRows, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
83
85
  /**
84
86
  * 🔴 **会话视图的读面口 —— `GET /v1/sessions/:id` 的全部取法(整读 / `?tail` / `?before` / `?blobCap` / `?message=N`)共用这一只**。
85
87
  * 次序 = **选 → 脱 → 截**(路由 `http/routes/sessions.ts`):整条消息的选窗不切字符串,先选窗不改任何一条的脱敏读数、只把脱敏的量降到选中的那几条;
package/dist/audit.js CHANGED
@@ -34,8 +34,8 @@ export async function buildSessionAudit(pool, sessionId, handles) {
34
34
  export async function buildSessionAuditPg(pool, sessionId, handles) {
35
35
  return auditFromStorage(await PgSessionStorage.wake(pool, sessionId), sessionId, handles);
36
36
  }
37
- export async function buildSessionAuditLocal(root, sessionId, handles) {
38
- return auditFromStorage(await LocalSessionWindow.wake(root, sessionId), sessionId, handles);
37
+ export async function buildSessionAuditLocal(rows, sessionId, handles) {
38
+ return auditFromStorage(await LocalSessionWindow.wake(rows, sessionId), sessionId, handles);
39
39
  }
40
40
  async function auditFromStorage(storage, sessionId, handles) {
41
41
  if (!storage)
@@ -6,7 +6,7 @@ import { withUnattendedLeg } from "../../unattended-permission-mode.js";
6
6
  import { createBrain } from "../../brain.js";
7
7
  import { buildPricing } from "../../budget.js";
8
8
  import { RemoteContainerExecutionEnv } from "../../plugins/remote-env-e2b.js";
9
- import { E2B_SANDBOX_HOME } from "../../execution-lane-caps.js";
9
+ import { buildLaneHomeClaim } from "../../execution-lane-caps.js";
10
10
  import { createDurableAskPolicy } from "../../approval.js";
11
11
  import { runOracle as runStandaloneOracle } from "./oracle.js";
12
12
  import { makeRepairOracle } from "./repair-oracle-adapter.js";
@@ -68,9 +68,10 @@ const sh = (env) => async (cmd) => {
68
68
  return { code: r.value.exitCode, out: (r.value.stdout + r.value.stderr).trim() };
69
69
  };
70
70
  async function provisionSandbox(rt, role, cellId) {
71
+ const homeSeat = rt.e2bTemplate ? {} : buildLaneHomeClaim({ remoteExec: { provider: "e2b" } });
71
72
  const env = new RemoteContainerExecutionEnv({
72
73
  apiKey: rt.e2bApiKey,
73
- homeDir: E2B_SANDBOX_HOME,
74
+ ...homeSeat,
74
75
  ...(rt.e2bTemplate ? { template: rt.e2bTemplate } : {}),
75
76
  timeoutMs: rt.sandboxTimeoutMs ?? 600_000,
76
77
  metadata: { s1Cell: cellId, s1Role: role },
@@ -34,8 +34,11 @@ export type { RunRecord, OracleVerdicts, DeliveryDecision, CoreStatsSubset, Inte
34
34
  /** The schema version stamped into every row — the field-contract handshake with core's metric tool. */
35
35
  export declare const S1_SCHEMA_VERSION: "s1.v1";
36
36
  export type S1SchemaVersion = typeof S1_SCHEMA_VERSION;
37
- /** The INSTALLED core version, read from node_modules at load(SPEC §0 provenance-honesty——接入审计 L16:
38
- * 硬钉 "1.111.0" 在 core 升到 1.258.x 后让 harness 每行 meta.coreVersion 输出错误溯源;动态读=永不再漂)。 */
37
+ /** The INSTALLED core version (SPEC §0 provenance-honesty — a hard-pinned "1.111.0" once drifted past a core upgrade and stamped every row's
38
+ * `meta.coreVersion` with the wrong provenance). Read from core's own root export `CONTRACT_KIT_ENGINE_VERSION` — the engine's
39
+ * `package.json` version, resolved by the engine itself ("unknown" only under a bundler that severed the module from its package root) —
40
+ * not by walking the installed package's directory from here (the dependency-direction gate, `test/dependency-direction-gate.test.ts` R2,
41
+ * bans reading core's install tree by file-system path). */
39
42
  export declare const S1_CORE_VERSION: string;
40
43
  /** The arm tag as emitted on the wire (lowercase — the s1.v1 contract value; the internal `Arm` is uppercase). The
41
44
  * harness emits a SUBSET of core's `RunRecord["arm"]` (which also carries "sup-vf", an S1b ablation S1 does not run). */
@@ -1,27 +1,7 @@
1
1
  import { buildReport, trulyCorrect, } from "@sema-agent/core/bench";
2
- import { createRequire } from "node:module";
3
- import { readFileSync, existsSync } from "node:fs";
4
- import { dirname, join } from "node:path";
2
+ import { CONTRACT_KIT_ENGINE_VERSION } from "@sema-agent/core";
5
3
  export const S1_SCHEMA_VERSION = "s1.v1";
6
- export const S1_CORE_VERSION = (() => {
7
- try {
8
- const require = createRequire(import.meta.url);
9
- let dir = dirname(require.resolve("@sema-agent/core"));
10
- for (let i = 0; i < 6; i++) {
11
- const pj = join(dir, "package.json");
12
- if (existsSync(pj)) {
13
- const parsed = JSON.parse(readFileSync(pj, "utf8"));
14
- if (parsed.name === "@sema-agent/core" && parsed.version)
15
- return parsed.version;
16
- }
17
- dir = dirname(dir);
18
- }
19
- return "unknown";
20
- }
21
- catch {
22
- return "unknown";
23
- }
24
- })();
4
+ export const S1_CORE_VERSION = CONTRACT_KIT_ENGINE_VERSION;
25
5
  export function armTag(arm) {
26
6
  switch (arm) {
27
7
  case "SOLO":
@@ -5,7 +5,7 @@ export async function runAdoptionBootScan(ctx) {
5
5
  return { scanned: 0, resumed: [], stalled: [], rejected: [], failed: [] };
6
6
  const runner = createAdoptionRunner({
7
7
  store,
8
- dialect: ctx.backend?.kind === "pg" ? "pg" : "tidb",
8
+ dialect: ctx.backend?.kind === "pg" ? "pg" : "mysql",
9
9
  now: ctx.now ?? Date.now,
10
10
  logger: ctx.logger,
11
11
  });
@@ -18,6 +18,7 @@ import type { DeviceStore } from "../device-store.js";
18
18
  import type { ExecutionPlacementSeat } from "../execution-placement.js";
19
19
  import { type DeviceWsHub } from "../device-ws-hub.js";
20
20
  import type { ServiceConfig } from "../config.js";
21
+ import type { DeviceRelayDeclaration } from "../config-types.js";
21
22
  import type { Logger } from "../observability/logger.js";
22
23
  import type { Metrics } from "../observability/metrics.js";
23
24
  import type { StoreBackend } from "../plugins/store-backend.js";
@@ -75,4 +76,14 @@ export declare function createDeviceLane(ctx: DeviceLaneCtx): DeviceLane | undef
75
76
  * 抛而不是 warn:降级的代价由用户承担(他以为命令跑在自己机器上、看到的却是云上一个空目录的结果)。
76
77
  */
77
78
  export declare function assertDeviceLaneWired(isDeviceLane: boolean, lane: DeviceLane | undefined, hasFactory: boolean): void;
79
+ /**
80
+ * 设备入口 × 已绑设备的起服一行(拒的那一半在配置期:device 车道上 `DEVICE_RELAY_URL` 必填,缺席拒起 —— `config.ts` `parseDeviceRelayUrlEnv`;
81
+ * 起不起服不随表里有几条绑定变)。
82
+ *
83
+ * 字面 `none` = 运维声明「设备拨本引擎自己的地址 + `wsPath`」。此刻根会话行上若有设备绑定(writer(device, D) 的格),这些会话的设备从此只能拨那个入口 ——
84
+ * 撤中继声明的回滚序是先恢复引擎自己的入口、再写 `none`,本行让运维看见押在那个入口上的绑定有几条:`device_relay_withdrawn_with_bindings { bindings }`
85
+ * (只交数,不交会话 id)。绑定 0 ⇒ 不响。URL ⇒ 不读表(设备读能力面拨它,与绑定数无关)。
86
+ * 读数 = 设备店的绑定数(唯一读法 `boundDeviceOf` 的聚合);读故障原样抛 ⇒ 起服失败(不折成 0 —— 折 0 就是在有绑定时不响)。
87
+ */
88
+ export declare function noteDeviceRelayBindings(relay: DeviceRelayDeclaration, store: Pick<DeviceStore, "countDeviceBindings">, logger: Pick<Logger, "warn">): Promise<void>;
78
89
  //# sourceMappingURL=device-lane.d.ts.map
@@ -56,4 +56,20 @@ export function assertDeviceLaneWired(isDeviceLane, lane, hasFactory) {
56
56
  "an assembly bug, not a configuration one — refusing to start rather than silently execute in-process (#157)");
57
57
  }
58
58
  }
59
+ export async function noteDeviceRelayBindings(relay, store, logger) {
60
+ switch (relay.kind) {
61
+ case "url":
62
+ return;
63
+ case "none": {
64
+ const bindings = await store.countDeviceBindings();
65
+ if (bindings > 0)
66
+ logger.warn("device_relay_withdrawn_with_bindings", { bindings });
67
+ return;
68
+ }
69
+ default: {
70
+ const unknownKind = relay;
71
+ throw new Error(`noteDeviceRelayBindings: no arm for ${JSON.stringify(unknownKind)}`);
72
+ }
73
+ }
74
+ }
59
75
  //# sourceMappingURL=device-lane.js.map
@@ -130,6 +130,29 @@ export interface EngineLeaseExitReport {
130
130
  /** 成孤儿到自退之间隔了多久;非孤儿退出时键缺席(不编 0)。 */
131
131
  orphanedForMs?: number;
132
132
  }
133
+ /**
134
+ * [ref] —— 租约窗的 wire 读数(`GET /health` 的 `engineLease`;壳持租约的触点节拍据此定,别处起的短窗引擎不再让第二句失败)。
135
+ *
136
+ * ## 报的是什么
137
+ * · `lingerMs` = 本腿**会执行的最短静默窗**:父还活着的窗({@link EngineLeaseDeps.lingerMs})与孤儿窗({@link EngineLeaseOrphanLane.lingerMs},只在看门狗装了时存在)取小。
138
+ * 取**最短**而不是「此刻生效」:此刻生效的窗在父死那一拍从 owned 窗掉到孤儿窗,按旧读数定节拍的壳会在下一次读 `/health` 之前被拆台;
139
+ * 最短窗是配置的性质、不随状态变,壳的触点只要比它密,在任何状态下都留得住引擎。
140
+ * · `tickMs` = 自退检查的采样拍。自退发生在**生效窗**满之后、至多再晚一拍(顶注 8);生效窗恒 ≥ `lingerMs`(`lingerMs` 是各窗里最短的一个),所以触点比 `lingerMs` 密 ⇒ 在任何状态下都先于自退。
141
+ * 读数**不预言**自退时刻:父还活着时生效的是 owned 窗,自退只会更晚。
142
+ *
143
+ * ## 一源
144
+ * 与租约腿自己的行为同一处铸出:`engine_lease_armed` 日志、自退判据用的窗、拍频推导(`tickMs = min(15s, 最短窗)`)和本读数读的是同一组数 ——
145
+ * 不存在第二处去「算一遍租约窗」。一个永远不到期的窗(owned 窗 = `Infinity` 且没有孤儿车道)不是租约:读数整个缺席,不补 0、不把 `Infinity` 送进 JSON。
146
+ */
147
+ export interface EngineLeaseFacts {
148
+ readonly lingerMs: number;
149
+ readonly tickMs: number;
150
+ }
151
+ /** {@link createEngineLeaseTracker} 的把手:`stop()` 收摊;`facts` 现读 —— **腿还在观察**时才有(收摊 / 自退触发之后缺席,says-yes ⟺ 腿在转)。 */
152
+ export interface EngineLeaseHandle {
153
+ stop(): void;
154
+ readonly facts: EngineLeaseFacts | undefined;
155
+ }
133
156
  export interface EngineLeaseDeps {
134
157
  /** 活附着数 = 本副本当前**打开着的 SSE 流**条数(`drainState.attachedStreams`,由 `createHttpServer` 自赋)。 */
135
158
  attachedStreams: () => number;
@@ -167,7 +190,5 @@ export interface EngineLeaseDeps {
167
190
  now?: () => number;
168
191
  }
169
192
  /** 装配并**立刻**起自退检查(装配即 `engine_lease_armed`)。返回停机链用的 `stop()`。 */
170
- export declare function createEngineLeaseTracker(deps: EngineLeaseDeps): {
171
- stop(): void;
172
- };
193
+ export declare function createEngineLeaseTracker(deps: EngineLeaseDeps): EngineLeaseHandle;
173
194
  //# sourceMappingURL=engine-lease.d.ts.map
@@ -1,7 +1,9 @@
1
1
  export const ENGINE_LEASE_TICK_MS = 15_000;
2
2
  export function createEngineLeaseTracker(deps) {
3
3
  const orphanLane = deps.orphan;
4
- const tickMs = deps.tickMs ?? Math.min(ENGINE_LEASE_TICK_MS, deps.lingerMs, orphanLane?.lingerMs ?? Number.POSITIVE_INFINITY);
4
+ const shortestLingerMs = Math.min(deps.lingerMs, orphanLane?.lingerMs ?? Number.POSITIVE_INFINITY);
5
+ const tickMs = deps.tickMs ?? Math.min(ENGINE_LEASE_TICK_MS, shortestLingerMs);
6
+ const leaseFacts = Number.isFinite(shortestLingerMs) ? Object.freeze({ lingerMs: shortestLingerMs, tickMs }) : undefined;
5
7
  const now = deps.now ?? (() => performance.now());
6
8
  let stopped = false;
7
9
  let idleSince = now();
@@ -66,6 +68,11 @@ export function createEngineLeaseTracker(deps) {
66
68
  stopped = true;
67
69
  clearInterval(timer);
68
70
  }
69
- return { stop };
71
+ return {
72
+ stop,
73
+ get facts() {
74
+ return stopped ? undefined : leaseFacts;
75
+ },
76
+ };
70
77
  }
71
78
  //# sourceMappingURL=engine-lease.js.map
@@ -30,12 +30,14 @@ import { derivePkgSourceEnv } from "../sandbox-pkg-source.js";
30
30
  import { effectiveHostWorkspace } from "../task-cwd.js";
31
31
  import { taskInheritEnvRefusal } from "../hosted-posture.js";
32
32
  import { sessionFaceOfHead } from "../session-incarnation.js";
33
+ import { isCodeToken } from "../terminal.js";
33
34
  import { createCacheMissMemory } from "../workspace-cache.js";
34
35
  import { workspaceSnapshotTimeoutOf } from "../workspace-space.js";
35
36
  import { sayEgressPolicyReading } from "../sandbox-egress-policy.js";
36
37
  import { sandboxPathEnvSlots, withSandboxPathEnvSlot } from "./deferred-sandbox-path-env.js";
37
- import { LANE_HOME_UNDECLARED_EVENT, createLaneHomeAbsenceReporter } from "../lane-home-probe.js";
38
- import { REMOTE_EXEC_PROVIDER_WORDS, buildUndeclaredHomeNote, executionLaneHomeDir, executionLaneOf, laneBindsReads, laneIsolated } from "../execution-lane-caps.js";
38
+ import { createLaneHomeAbsenceReporter } from "../lane-home-probe.js";
39
+ import { REMOTE_EXEC_PROVIDER_WORDS, buildLaneHomeBootNote, buildLaneHomeClaim, capabilitiesFor, executionLaneOf, laneBindsReads, laneIsolated, laneSandboxReadFloorState } from "../execution-lane-caps.js";
40
+ import { warnReadDenyFloorUnkept } from "./execution-lane.js";
39
41
  function boundedSessionSetter(map, maxEntries) {
40
42
  return (sid, value) => {
41
43
  map.delete(sid);
@@ -125,7 +127,6 @@ export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
125
127
  }, deps)(ctx);
126
128
  };
127
129
  }
128
- const STORE_ERROR_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
129
130
  const INCARNATION_READ_TIMEOUT = "incarnation_read_timeout";
130
131
  async function occupantOf(seats, sessionId, taskId, boundMs) {
131
132
  let answer;
@@ -141,7 +142,7 @@ async function occupantOf(seats, sessionId, taskId, boundMs) {
141
142
  }
142
143
  catch (e) {
143
144
  const code = e?.code;
144
- return { fault: typeof code === "string" && STORE_ERROR_CODE.test(code) ? code : "incarnation_read_failed" };
145
+ return { fault: isCodeToken(code) ? code : "incarnation_read_failed" };
145
146
  }
146
147
  if (answer === undefined)
147
148
  return { unread: "incarnation_unknown" };
@@ -226,8 +227,7 @@ function hostWorktreeUnwrappedRefusal() {
226
227
  }
227
228
  export function createExecutionEnv(ctx) {
228
229
  const { config, logger, metrics, taskAttachmentStore } = ctx;
229
- const laneHomeDir = executionLaneHomeDir(config);
230
- const homeDirSeat = laneHomeDir !== undefined ? { homeDir: laneHomeDir } : {};
230
+ const homeDirSeat = buildLaneHomeClaim(config);
231
231
  const homeAbsentNotice = { onHomeAbsent: createLaneHomeAbsenceReporter((event, fields) => logger.warn(event, fields)) };
232
232
  const perTaskImage = new PerTaskImageRegistry();
233
233
  const sessionEnvSelection = new SessionEnvironmentSelection();
@@ -245,13 +245,14 @@ export function createExecutionEnv(ctx) {
245
245
  if (config.remoteExec?.provider === "e2b") {
246
246
  executionEnvFactory = e2bExecutionEnvFactory({
247
247
  apiKey: config.remoteExec.apiKey,
248
- ...homeDirSeat,
248
+ ...homeDirSeat, ...homeAbsentNotice,
249
249
  ...(config.remoteExec.template ? { template: config.remoteExec.template } : {}),
250
250
  ...(config.remoteExec.timeoutMs != null ? { timeoutMs: config.remoteExec.timeoutMs } : {}),
251
251
  ...(config.remoteExec.livenessMs != null ? { livenessMs: config.remoteExec.livenessMs } : {}),
252
252
  ...(config.remoteExec.allowInternetAccess != null ? { allowInternetAccess: config.remoteExec.allowInternetAccess } : {}),
253
253
  ...(config.remoteExec.mountPath ? { mountPath: config.remoteExec.mountPath } : {}),
254
254
  ...((env) => (env !== undefined ? { sandboxEnv: env } : {}))(sandboxLaneEnvMerged(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv))),
255
+ sandboxReadFloor: config.sandboxReadFloor,
255
256
  logger,
256
257
  metrics,
257
258
  });
@@ -278,6 +279,7 @@ export function createExecutionEnv(ctx) {
278
279
  ...(config.remoteExec.workspaceSnapshotExclude ? { snapshotExclude: config.remoteExec.workspaceSnapshotExclude } : {}),
279
280
  logger,
280
281
  ...((lane) => ({ ...(lane.env !== undefined ? { podEnv: lane.env } : {}), ...(lane.secretEnv !== undefined ? { podSecretEnv: lane.secretEnv } : {}) }))(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv)),
282
+ sandboxReadFloor: config.sandboxReadFloor,
281
283
  };
282
284
  const brokerImage = config.remoteExec.brokerImage;
283
285
  executionEnvFactory = createK8sRunEnvFactory(k8sCfg, {
@@ -358,7 +360,7 @@ export function createExecutionEnv(ctx) {
358
360
  if (hostScheduler)
359
361
  logger.info(`R7: self-wake scheduler enabled (host lane), store=${schedulerStorePath}`);
360
362
  const hostCfg = {
361
- ...homeDirSeat,
363
+ ...homeDirSeat, ...homeAbsentNotice,
362
364
  ...(config.remoteExec.workspaceBase ? { workspaceBase: config.remoteExec.workspaceBase } : {}),
363
365
  ...(config.remoteExec.commandTimeoutMs != null ? { commandTimeoutMs: config.remoteExec.commandTimeoutMs } : {}),
364
366
  ...(hostScheduler ? { scheduler: hostScheduler } : {}),
@@ -394,6 +396,7 @@ export function createExecutionEnv(ctx) {
394
396
  ...(config.remoteExec.network ? { network: config.remoteExec.network } : {}),
395
397
  ...(config.remoteExec.commandTimeoutMs != null ? { commandTimeoutMs: config.remoteExec.commandTimeoutMs } : {}),
396
398
  ...(config.remoteExec.env ? { env: config.remoteExec.env } : {}),
399
+ sandboxReadFloor: config.sandboxReadFloor,
397
400
  });
398
401
  }
399
402
  if (executionEnvFactory && DEPLOYMENT_SHAPE_PREDICATES.remoteScratchpad.holds(config)) {
@@ -465,16 +468,19 @@ export function createExecutionEnv(ctx) {
465
468
  if (executionEnvFactory) {
466
469
  const isolated = laneIsolated(executionLaneOf(config.remoteExec.provider));
467
470
  const suspendable = DEPLOYMENT_SHAPE_PREDICATES.suspendableHands.holds(config);
471
+ const keepsReadFloor = capabilitiesFor(config).keepsReadFloor;
472
+ const sandboxReadFloor = laneSandboxReadFloorState(config);
468
473
  const sandboxEnvKeys = [...sandboxEnvNamesInForce(config)].sort();
469
- logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
474
+ logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, keepsReadFloor, ...(sandboxReadFloor !== undefined ? { sandboxReadFloor } : {}), ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
470
475
  if (!isolated)
471
476
  logger.warn("remote_exec_real_system", { provider: config.remoteExec.provider, note: buildRealSystemNote(config.remoteExec) });
472
- const homeNote = buildUndeclaredHomeNote(config);
473
- if (homeNote !== undefined)
474
- logger.warn(LANE_HOME_UNDECLARED_EVENT, { provider: config.remoteExec.provider, note: homeNote });
477
+ const homeLine = buildLaneHomeBootNote(config);
478
+ if (homeLine !== undefined)
479
+ logger.warn(homeLine.event, { provider: config.remoteExec.provider, note: homeLine.note });
475
480
  if (executionLaneOf(config.remoteExec.provider) === "host")
476
481
  logger.info("task_inherit_env_honored", { honored: taskInheritEnvRefusal(config) === undefined });
477
482
  }
483
+ warnReadDenyFloorUnkept(config, logger);
478
484
  const lspProvider = config.remoteExec?.provider;
479
485
  const lspLane = executionLaneOf(lspProvider);
480
486
  const lspLaneBindsReads = lspLane !== undefined && laneBindsReads(lspLane);
@@ -1,5 +1,6 @@
1
1
  import { type CrossInvariantView } from "../config-invariants.js";
2
2
  import type { ServiceConfig } from "../config-types.js";
3
+ import { buildReadDenyFloorUnkeptNote } from "../execution-lane-caps.js";
3
4
  import type { Logger } from "../observability/logger.js";
4
5
  /** `config.d/remote-exec.json` 能写进来的车道(文件契约里不带密钥名、可 1:1 映射的两条;e2b/k8s/ssh/adb 要 NAME→值解析,尚未接线)。 */
5
6
  export declare const FILE_SOURCED_LANES: readonly ["host", "local-docker"];
@@ -28,6 +29,13 @@ export declare function composeExecutionLane(config: ServiceConfig, ctx: Executi
28
29
  * 非宿主车道零动作 —— 不解析、不装观察者。
29
30
  */
30
31
  export declare function settleHostLaneShell(config: Pick<ServiceConfig, "remoteExec">, logger: Pick<Logger, "info" | "warn">): Promise<void>;
32
+ /**
33
+ * **读地板的起服一行**:部署要求读拒表的字节地板(`READ_DENY_FLOOR_REQUIRED=true`)而最终车道的执行环境块不守 ⇒ 每条读拒表有行的 run 都在准备期拒 ——
34
+ * 起服先说清后果与出路(`warn read_deny_floor_required_unkept { provider, note }`;判据与句子的唯一属主 `buildReadDenyFloorUnkeptNote`)。
35
+ * 两个入口调同一只(与 {@link settleHostLaneShell} 同形):HTTP 服务在执行环境装配里(`boot/execution-env.ts`,有没有执行环境工厂都调),`run-local` 在宿主车道定下之后 ——
36
+ * 旋钮两个入口都递给引擎(`RunnerDeps.readDenyFloorRequired`),所以两个入口都要先说。不要求 / 车道守地板 ⇒ 零动作。
37
+ */
38
+ export declare function warnReadDenyFloorUnkept(config: Parameters<typeof buildReadDenyFloorUnkeptNote>[0], logger: Pick<Logger, "warn">): void;
31
39
  /**
32
40
  * 车道合成之后的跨域不变量 —— 表(`config-invariants.ts`)里读 `remoteExec.provider` 的那几条,boot 期 `live === next`。
33
41
  * 同步、纯判据:只读 config,不碰文件(测试可以对 `loadConfig()` 的产物直接调它)。
@@ -1,7 +1,7 @@
1
1
  import { loadRemoteExec } from "@sema-agent/settings-schema/node";
2
2
  import { assertLocalConfigDirTrusted } from "../config-dir-trust.js";
3
3
  import { crossInvariant } from "../config-invariants.js";
4
- import { executionLaneOf, laneIsolated } from "../execution-lane-caps.js";
4
+ import { buildReadDenyFloorUnkeptNote, executionLaneOf, laneIsolated } from "../execution-lane-caps.js";
5
5
  import { buildReadFacePostureNotice, settleDerivedReadFace } from "../read-face-posture.js";
6
6
  import { settleHostShellAtBoot } from "../plugins/host-platform.js";
7
7
  export const FILE_SOURCED_LANES = ["host", "local-docker"];
@@ -23,6 +23,11 @@ export async function settleHostLaneShell(config, logger) {
23
23
  return;
24
24
  await settleHostShellAtBoot(logger);
25
25
  }
26
+ export function warnReadDenyFloorUnkept(config, logger) {
27
+ const note = buildReadDenyFloorUnkeptNote(config);
28
+ if (note !== undefined)
29
+ logger.warn("read_deny_floor_required_unkept", { provider: config.remoteExec?.provider, note });
30
+ }
26
31
  export function assertExecutionLaneInvariants(config) {
27
32
  const judge = (id) => crossInvariant(id).check({ live: config, next: config });
28
33
  const leader = judge("leader-host-lane");