@sema-agent/server 7.144.0 → 7.146.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 (305) hide show
  1. package/MIGRATION.md +621 -0
  2. package/README.md +3 -0
  3. package/README.zh-CN.md +1 -0
  4. package/USAGE.md +233 -54
  5. package/deploy/facts/CHANGES.json +25 -0
  6. package/deploy/facts/README.md +57 -0
  7. package/deploy/facts/lanes.json +54 -0
  8. package/deploy/facts/lanes.schema.json +57 -0
  9. package/deploy/facts/sandbox-rbac.json +113 -0
  10. package/deploy/facts/sandbox-rbac.schema.json +74 -0
  11. package/deploy/facts/sealed-key.json +9 -0
  12. package/deploy/facts/sealed-key.schema.json +52 -0
  13. package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
  14. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
  15. package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
  16. package/deploy/sema-up/chart/templates/server.yaml +4 -0
  17. package/deploy/sema-up/chart/values.yaml +7 -0
  18. package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
  19. package/dist/adoption/import-limits.d.ts +6 -0
  20. package/dist/adoption/import-limits.js +7 -0
  21. package/dist/adoption/import.d.ts +62 -0
  22. package/dist/adoption/import.js +107 -0
  23. package/dist/adoption/wire.d.ts +52 -0
  24. package/dist/adoption/wire.js +9 -0
  25. package/dist/approval-ask-machine.d.ts +2 -2
  26. package/dist/approval-card.d.ts +3 -12
  27. package/dist/approval-card.js +0 -4
  28. package/dist/approval-gate-currency.d.ts +1 -1
  29. package/dist/approval-gate-currency.js +1 -1
  30. package/dist/approval-reconciler.d.ts +1 -1
  31. package/dist/audit.d.ts +2 -21
  32. package/dist/audit.js +0 -9
  33. package/dist/boot/deployment-mods.d.ts +11 -1
  34. package/dist/boot/deployment-mods.js +15 -2
  35. package/dist/boot/device-lane.js +2 -0
  36. package/dist/boot/engine-lease.d.ts +193 -21
  37. package/dist/boot/engine-lease.js +146 -20
  38. package/dist/boot/execution-env.d.ts +4 -0
  39. package/dist/boot/execution-env.js +12 -0
  40. package/dist/boot/exit-boundary.d.ts +50 -0
  41. package/dist/boot/exit-boundary.js +32 -0
  42. package/dist/boot/exit-last.d.ts +20 -4
  43. package/dist/boot/exit-last.js +21 -4
  44. package/dist/boot/governance-seams.js +1 -0
  45. package/dist/boot/memory-consolidation.d.ts +29 -17
  46. package/dist/boot/memory-consolidation.js +26 -15
  47. package/dist/boot/reapers.d.ts +12 -4
  48. package/dist/boot/reapers.js +39 -15
  49. package/dist/boot/resolve-spec.d.ts +2 -0
  50. package/dist/boot/resolve-spec.js +38 -15
  51. package/dist/boot/runner-deps.js +1 -1
  52. package/dist/boot/session-faces.d.ts +1 -1
  53. package/dist/boot/session-faces.js +6 -4
  54. package/dist/boot/shutdown.js +27 -9
  55. package/dist/boot/stage-01-config.js +1 -1
  56. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  57. package/dist/boot/stage-03-store-backend.js +2 -2
  58. package/dist/boot/stage-04-stores.d.ts +1 -0
  59. package/dist/boot/stage-05-execution-env.d.ts +3 -0
  60. package/dist/boot/stage-05-execution-env.js +3 -3
  61. package/dist/boot/stage-06-runners.d.ts +3 -0
  62. package/dist/boot/stage-06-runners.js +11 -10
  63. package/dist/boot/stage-07-capability-layer.d.ts +3 -0
  64. package/dist/boot/stage-07-capability-layer.js +7 -2
  65. package/dist/boot/stage-08-reapers.d.ts +3 -0
  66. package/dist/boot/stage-08-reapers.js +3 -3
  67. package/dist/boot/stage-09-leader.d.ts +4 -1
  68. package/dist/boot/stage-10-http-server.d.ts +4 -1
  69. package/dist/boot/stage-10-http-server.js +4 -3
  70. package/dist/boot/stores.d.ts +1 -0
  71. package/dist/boot/stores.js +35 -19
  72. package/dist/boot/workflow-orchestration.d.ts +1 -1
  73. package/dist/boot/workflow-orchestration.js +2 -1
  74. package/dist/capabilities/composite-members.d.ts +3 -1
  75. package/dist/capabilities/composite-members.js +3 -1
  76. package/dist/capabilities/scenarios.d.ts +2 -2
  77. package/dist/capability-facts.d.ts +18 -1
  78. package/dist/capability-facts.js +25 -7
  79. package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
  80. package/dist/config-catalog.js +13 -4
  81. package/dist/config-d-migration.d.ts +3 -2
  82. package/dist/config-provider.d.ts +2 -2
  83. package/dist/config-types.d.ts +43 -4
  84. package/dist/config.d.ts +6 -1
  85. package/dist/config.js +67 -11
  86. package/dist/deleted-session-ids.d.ts +19 -0
  87. package/dist/deleted-session-ids.js +26 -0
  88. package/dist/deploy-facts.d.ts +155 -0
  89. package/dist/deploy-facts.js +94 -0
  90. package/dist/device-ws-hub.d.ts +48 -3
  91. package/dist/device-ws-hub.js +48 -2
  92. package/dist/error-code-family.d.ts +35 -0
  93. package/dist/error-code-family.js +26 -0
  94. package/dist/fleet/drain-entry.d.ts +39 -3
  95. package/dist/fleet/drain-entry.js +6 -0
  96. package/dist/fleet/fleet-bus.d.ts +15 -4
  97. package/dist/fleet/fleet-bus.js +17 -3
  98. package/dist/hooks/branch-transcript.d.ts +1 -1
  99. package/dist/hooks/branch-transcript.js +1 -0
  100. package/dist/hooks/classic-stations.d.ts +25 -8
  101. package/dist/hooks/classic-stations.js +29 -3
  102. package/dist/hooks/hook-runner.d.ts +33 -16
  103. package/dist/hooks/hook-runner.js +166 -73
  104. package/dist/hooks/hook-source.d.ts +14 -2
  105. package/dist/hooks/hook-source.js +8 -0
  106. package/dist/http/active-run-conflict.d.ts +1 -1
  107. package/dist/http/active-run-conflict.js +1 -1
  108. package/dist/http/admission.js +13 -2
  109. package/dist/http/checkpoint-ctx.d.ts +60 -71
  110. package/dist/http/checkpoint-ctx.js +35 -40
  111. package/dist/http/dispatch.js +18 -2
  112. package/dist/http/durable-run-leg.d.ts +5 -0
  113. package/dist/http/durable-run-leg.js +8 -6
  114. package/dist/http/execution-context.d.ts +4 -0
  115. package/dist/http/execution-context.js +9 -0
  116. package/dist/http/health-self-report.d.ts +6 -2
  117. package/dist/http/health-self-report.js +3 -2
  118. package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
  119. package/dist/http/memory-compliance-failure-reply.js +2 -15
  120. package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
  121. package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
  122. package/dist/http/principal-gate.d.ts +35 -12
  123. package/dist/http/principal-gate.js +16 -12
  124. package/dist/http/request-guards.d.ts +1 -1
  125. package/dist/http/request-guards.js +5 -5
  126. package/dist/http/resume-legs.d.ts +22 -0
  127. package/dist/http/resume-legs.js +31 -20
  128. package/dist/http/route-ctx.d.ts +26 -10
  129. package/dist/http/route-table.js +2 -0
  130. package/dist/http/routes/adoption.d.ts +11 -0
  131. package/dist/http/routes/adoption.js +80 -6
  132. package/dist/http/routes/agents-roster.js +1 -0
  133. package/dist/http/routes/approvals-assistant.d.ts +20 -1
  134. package/dist/http/routes/approvals-assistant.js +29 -7
  135. package/dist/http/routes/background.js +1 -0
  136. package/dist/http/routes/capabilities.js +4 -1
  137. package/dist/http/routes/diagnostics.d.ts +9 -14
  138. package/dist/http/routes/diagnostics.js +10 -20
  139. package/dist/http/routes/engine.d.ts +31 -0
  140. package/dist/http/routes/engine.js +81 -0
  141. package/dist/http/routes/memory-bundle.js +3 -0
  142. package/dist/http/routes/memory-consolidation.js +3 -5
  143. package/dist/http/routes/memory-origin.d.ts +1 -1
  144. package/dist/http/routes/memory-origin.js +2 -4
  145. package/dist/http/routes/memory-policy.js +5 -1
  146. package/dist/http/routes/observability.js +3 -6
  147. package/dist/http/routes/rules.d.ts +1 -1
  148. package/dist/http/routes/rules.js +5 -2
  149. package/dist/http/routes/runs.js +7 -3
  150. package/dist/http/routes/session-sync.js +24 -25
  151. package/dist/http/routes/sessions-list.d.ts +1 -1
  152. package/dist/http/routes/sessions.js +4 -0
  153. package/dist/http/routes/tasks.js +35 -14
  154. package/dist/http/routes/trace-usage.js +1 -1
  155. package/dist/http/run-concurrency-cap.d.ts +86 -0
  156. package/dist/http/run-concurrency-cap.js +54 -0
  157. package/dist/http/run-meta.d.ts +14 -7
  158. package/dist/http/run-meta.js +5 -2
  159. package/dist/http/server.d.ts +27 -16
  160. package/dist/http/server.js +21 -3
  161. package/dist/http/stored-body-replay.d.ts +9 -6
  162. package/dist/http/stored-body-replay.js +19 -5
  163. package/dist/http/submit-ctx.d.ts +12 -0
  164. package/dist/http/submit-ctx.js +23 -0
  165. package/dist/http/wire-types.d.ts +8 -3
  166. package/dist/json-body-limit.d.ts +8 -0
  167. package/dist/json-body-limit.js +2 -0
  168. package/dist/leader/diffout.d.ts +1 -1
  169. package/dist/local-data-root.d.ts +2 -2
  170. package/dist/memory-operator-faces.d.ts +9 -4
  171. package/dist/memory-scope-stores.d.ts +9 -7
  172. package/dist/memory-scope-stores.js +3 -14
  173. package/dist/memory-scope.d.ts +36 -0
  174. package/dist/memory-scope.js +32 -1
  175. package/dist/net-address.d.ts +53 -0
  176. package/dist/net-address.js +111 -0
  177. package/dist/observability/fail-open.d.ts +28 -12
  178. package/dist/observability/fail-open.js +28 -12
  179. package/dist/orchestration/workflow-notify-journal.js +2 -3
  180. package/dist/org-delivery-gate.js +1 -1
  181. package/dist/peer-directory.d.ts +6 -12
  182. package/dist/peer-directory.js +5 -1
  183. package/dist/plugins/approval-ask-store-file.d.ts +16 -2
  184. package/dist/plugins/approval-ask-store-file.js +21 -1
  185. package/dist/plugins/approval-ask-store-memory.d.ts +8 -2
  186. package/dist/plugins/approval-ask-store-memory.js +11 -8
  187. package/dist/plugins/caching-session-store.d.ts +6 -1
  188. package/dist/plugins/caching-session-store.js +6 -0
  189. package/dist/plugins/checkpoint-store-face.d.ts +426 -0
  190. package/dist/plugins/checkpoint-store-face.js +152 -0
  191. package/dist/plugins/file-run-store.d.ts +13 -7
  192. package/dist/plugins/file-run-store.js +12 -13
  193. package/dist/plugins/fork-routing-session-store.d.ts +6 -2
  194. package/dist/plugins/fork-routing-session-store.js +2 -2
  195. package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
  196. package/dist/plugins/local-checkpoint-store.d.ts +16 -5
  197. package/dist/plugins/local-checkpoint-store.js +25 -6
  198. package/dist/plugins/local-session-store.d.ts +80 -21
  199. package/dist/plugins/local-session-store.js +79 -22
  200. package/dist/plugins/memory-engine-pg.d.ts +29 -6
  201. package/dist/plugins/memory-engine-pg.js +96 -214
  202. package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
  203. package/dist/plugins/memory-engine-sql-apply.js +358 -0
  204. package/dist/plugins/memory-engine-tidb.d.ts +35 -9
  205. package/dist/plugins/memory-engine-tidb.js +97 -227
  206. package/dist/plugins/memory-key-guards.d.ts +1 -1
  207. package/dist/plugins/memory-origin-law.d.ts +3 -3
  208. package/dist/plugins/memory-run-store.d.ts +2 -0
  209. package/dist/plugins/memory-run-store.js +6 -0
  210. package/dist/plugins/one-time-migrations.d.ts +32 -56
  211. package/dist/plugins/one-time-migrations.js +27 -119
  212. package/dist/plugins/permission-rule-store-file.d.ts +17 -3
  213. package/dist/plugins/permission-rule-store-file.js +8 -1
  214. package/dist/plugins/pg-pool.js +1 -1
  215. package/dist/plugins/pg-session-storage.d.ts +17 -4
  216. package/dist/plugins/pg-session-storage.js +8 -4
  217. package/dist/plugins/run-store-sql.d.ts +4 -0
  218. package/dist/plugins/run-store-sql.js +5 -2
  219. package/dist/plugins/schema-ensure-legs.js +2 -2
  220. package/dist/plugins/session-fork.d.ts +31 -9
  221. package/dist/plugins/session-fork.js +3 -2
  222. package/dist/plugins/session-placement.d.ts +4 -2
  223. package/dist/plugins/session-store.d.ts +1 -1
  224. package/dist/plugins/sql-json-column.d.ts +5 -1
  225. package/dist/plugins/store-backend.d.ts +11 -8
  226. package/dist/plugins/store-backend.js +8 -7
  227. package/dist/plugins/store-contracts.d.ts +1 -11
  228. package/dist/plugins/store-contracts.js +0 -9
  229. package/dist/plugins/store-sweep.d.ts +63 -0
  230. package/dist/plugins/store-sweep.js +48 -0
  231. package/dist/plugins/tidb-pool.js +1 -1
  232. package/dist/plugins/tidb-session-store.d.ts +16 -3
  233. package/dist/plugins/tidb-session-store.js +8 -4
  234. package/dist/prompt-screen.d.ts +18 -0
  235. package/dist/prompt-screen.js +5 -0
  236. package/dist/rules-consent.d.ts +56 -51
  237. package/dist/rules-consent.js +86 -14
  238. package/dist/run-acceptance.d.ts +40 -10
  239. package/dist/run-acceptance.js +38 -5
  240. package/dist/run-cancel-context.d.ts +4 -1
  241. package/dist/run-cancel-context.js +2 -1
  242. package/dist/runs.js +2 -2
  243. package/dist/sandbox-egress-policy.js +6 -11
  244. package/dist/sandbox-rbac-rules.d.ts +88 -0
  245. package/dist/sandbox-rbac-rules.js +80 -0
  246. package/dist/sealed-key-layout.d.ts +17 -0
  247. package/dist/sealed-key-layout.js +4 -0
  248. package/dist/sealed-key.js +5 -5
  249. package/dist/security.d.ts +48 -9
  250. package/dist/security.js +9 -2
  251. package/dist/session-agent.d.ts +39 -0
  252. package/dist/session-agent.js +16 -0
  253. package/dist/session-error-wire.d.ts +4 -4
  254. package/dist/session-notify-door.d.ts +5 -3
  255. package/dist/session-resident-background.d.ts +57 -0
  256. package/dist/session-resident-background.js +20 -0
  257. package/dist/session-sync-kernel.d.ts +53 -14
  258. package/dist/session-sync-kernel.js +70 -1
  259. package/dist/session-sync.d.ts +5 -3
  260. package/dist/session-workspace.d.ts +1 -0
  261. package/dist/session-workspace.js +1 -0
  262. package/dist/sighup-idle.d.ts +9 -7
  263. package/dist/sighup-idle.js +4 -5
  264. package/dist/spec-fields.d.ts +16 -0
  265. package/dist/spec-fields.js +7 -0
  266. package/dist/stored-request-env-credentials-m38.d.ts +3 -0
  267. package/dist/stored-request-env-credentials-m38.js +8 -0
  268. package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
  269. package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +33 -429
  270. package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +70 -209
  271. package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
  272. package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
  273. package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
  274. package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
  275. package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
  276. package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
  277. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
  278. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
  279. package/dist/task-settings.d.ts +59 -4
  280. package/dist/task-settings.js +50 -4
  281. package/dist/tool-approval.d.ts +2 -2
  282. package/dist/trace/core-keyset-guard.d.ts +8 -7
  283. package/dist/trace/engine-notice-wire.d.ts +1 -1
  284. package/dist/trace/engine-notice-wire.js +2 -0
  285. package/dist/trace/exit-seat.d.ts +6 -0
  286. package/dist/trace/exit-seat.js +1 -0
  287. package/dist/trace/model-segment.d.ts +3 -2
  288. package/dist/trace/model-segment.js +16 -8
  289. package/dist/trace/project.js +9 -0
  290. package/dist/trace/redact.d.ts +79 -4
  291. package/dist/trace/redact.js +523 -123
  292. package/dist/trace/self-minted-wire.d.ts +391 -1
  293. package/dist/trace/self-minted-wire.js +145 -0
  294. package/dist/trace/wire-projection-faces.d.ts +1 -1
  295. package/dist/trace/wire-projection-faces.js +1 -1
  296. package/dist/usage-analytics.d.ts +4 -0
  297. package/package.json +12 -4
  298. package/scripts/drain-check-local.mjs +8 -29
  299. package/scripts/drain-check.mysql.sql +3 -24
  300. package/scripts/drain-check.pg.sql +3 -24
  301. package/skills/update-config.md +1 -1
  302. package/wire-changes/server@7.145.0.json +146 -0
  303. package/wire-changes/server@7.146.0.json +3221 -0
  304. package/dist/approval-batch-census.d.ts +0 -27
  305. package/dist/approval-batch-census.js +0 -27
@@ -1042,6 +1042,10 @@ export interface ServiceConfigFlat {
1042
1042
  * 形会把全员折叠成单键,per-remote 层退化成共享预算而非公平层,`off` + 全局帽 64 是诚实形)。
1043
1043
  * 坏值拒启([ref] A 档),词表与拒因见 config.ts `parseDevicePreAuthPerRemoteEnv`。 */
1044
1044
  maxPreAuthPerRemote?: number | "off";
1045
+ /** `DEVICE_TRUSTED_PROXY_CIDRS`([ref];缺席 = 名单空 = 不读任何代理头,帽键 = socket 对端)= per-remote 帽键的可信代理
1046
+ * 名单(规范 CIDR 文本)。socket 对端落在名单内,汇聚端才读 `X-Forwarded-For`、取自右向左第一个名单外地址作帽键。
1047
+ * 坏项拒启([ref] A 档),拒因见 config.ts `parseDeviceTrustedProxyCidrsEnv`;唯一消费点 = `boot/device-lane.ts` 透传汇聚端。 */
1048
+ trustedProxyCidrs?: readonly string[];
1045
1049
  /** `DEVICE_ENROLL_TOKEN_TTL_SEC`(§4.7 第五个旋钮;默认 900 = §7-T5 ① 的 15min)= enrollment
1046
1050
  * token 的有效期**时长**(整秒,自 **DB now** 起算 —— 时间权威是库,不是副本墙钟)。唯一消费点 =
1047
1051
  * 签发动词 `POST /v1/devices/enroll-tokens`(`http/routes/devices.ts`);[ref] 之前它刻意未铸
@@ -1299,6 +1303,10 @@ export interface ServiceConfigFlat {
1299
1303
  attachmentMimeAllowlist?: string[];
1300
1304
  /** D-1 未绑定附件 TTL(上传后从未被任何 task 引用的行,过期由 reaper 收割;缺省 24h)。 */
1301
1305
  attachmentUnboundTtlMs: number;
1306
+ /** 收编批量导入 `POST /v1/adoption/:id/sessions`:每请求最多几个会话信封(`ADOPTION_IMPORT_MAX_SESSIONS`;缺省 / 地板见 `adoption/import-limits.ts`)。 */
1307
+ adoptionImportMaxSessions: number;
1308
+ /** 收编批量导入:每个会话信封最多多少字节(信封 JSON 的 UTF-8 字节;`ADOPTION_IMPORT_MAX_SESSION_BYTES`;缺省 / 地板 / 上帽见 `adoption/import-limits.ts`)。 */
1309
+ adoptionImportMaxSessionBytes: number;
1302
1310
  /** Header carrying the authenticated principal (S6). Identity never comes from the body. */
1303
1311
  principalHeader: string;
1304
1312
  /** Require the principal header on task requests (set true in multi-tenant production). */
@@ -1365,6 +1373,15 @@ export interface ServiceConfigFlat {
1365
1373
  * 只在单用户形(`REQUIRE_PRINCIPAL` 未开)且名单为空时成立 —— 否则拒启(`config-invariants.ts` 的 `operator-single-user`:一个事实一个来源)。
1366
1374
  * env 独有(没有中心写位),起服冻结。读法只有 `explicitOperatorOk` / `operatorRosterPresent` 两只。 */
1367
1375
  operatorSingleUser?: boolean;
1376
+ /**
1377
+ * `SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT` —— 「出示这台部署的 service 凭据、不报主体的调用方是谁」的**唯一声明座**。缺省 `true`(不设 = 今天的读法):
1378
+ * 它代部署本人说话(fleet 调用方,运维聚合口的 service 臂);`false` ⇒ 它是**无身份调用方**,各面按既有的「过了凭据门、没有主体」那一臂答
1379
+ * (fleet 读面 401 identity、运维聚合口 401 operator、舰队流多租 401 principal_required / 单用户落 `default`、写档 401 identity、无主 placed 子代 404)。
1380
+ * 只改一处:`http/principal-gate.ts` 的 `actsForDeployment` 多这一个合取项 —— 它的两个读者(fleet 调用方的凭据臂、`/metrics*` 的 service 臂)一次继承,
1381
+ * 零新拒码、零新闸点;自报位 `/health.auth.serviceTokenActsForDeployment` = 配了 service 凭据 ∧ 本位。没配 service 凭据的部署上声明 `false` 是空真(那一臂本来就够不着)。
1382
+ * env 独有(词表布尔,词表外拒启;没有 `config.d` 文件形、没有中心写位),起服读一次、热路径够不着(不是热键)。
1383
+ */
1384
+ serviceTokenActsForDeployment: boolean;
1368
1385
  /**
1369
1386
  * DESIGN-278 §5 S2([ref])—— `GET /v1/config/catalog`(配置目录自描述端点)的显式旋钮。
1370
1387
  * 默认 **ON**(设计稿 §0.5:合规部署可关)。端点本身已是 operator-only(`explicitOperatorOk`,
@@ -1615,7 +1632,7 @@ export interface ServiceConfigFlat {
1615
1632
  * tools for a declared `plan` itself, and no plan entry clamps the hands (only `AUTONOMY=read-only` does). */
1616
1633
  planModeEnabled: boolean;
1617
1634
  /**
1618
- * `HOOKS_TIMEOUT_MS` —— 请求 `settings.hooks` 那张 mods 注册(`settings.hooks`)每个 handler 的时间预算(ms;一个事件跑一遍本请求的钩子条目)。
1635
+ * `HOOKS_TIMEOUT_MS` —— 请求 hooks 的每张车道注册(`settings.hooks` / `settings.hooks.managed`,各一份同值)每个 handler 的时间预算(ms;一个事件跑一遍这条车道的钩子条目)。
1619
1636
  * **缺席 = 不铸键**;唯一读法 = `hooks/hook-runner.ts` 的 `settingsHooksBudgetMs`(未设 ⇒ 600000,单条命令超时的上限;这只数是引擎的钟,不是钩子子进程的墙钟)。
1620
1637
  *
1621
1638
  * 🔴 `0` 是有效值(引擎按字面:零预算,下一个定时器拍就到期),不是「未设」;
@@ -1891,7 +1908,7 @@ export interface ServiceConfigFlat {
1891
1908
  * under the shared-engine shape (several shell sessions on one config, engine rides the FIRST shell's process
1892
1909
  * group per the T11 anti-orphan call) other live sessions may still be using this engine, so an unconditional
1893
1910
  * drain kills a peer mid-turn (499) and 503s new submits. Instead SIGHUP arms an idle watch: shut down only
1894
- * after `inflight()` (bg/resume legs + live streams) has been 0 for this long, WITHOUT flipping `draining`
1911
+ * after `inflight()` (bg/resume legs + live streams — the blocking set `http + leader`; session-resident background shells/monitors are in the `/health.inflight` total but do not block) has been 0 for this long, WITHOUT flipping `draining`
1895
1912
  * (peers stay fully served). A true orphan (last window closed) self-terminates when the window expires —
1896
1913
  * T11 stands, just bounded instead of immediate. A SECOND SIGHUP (or SIGTERM) escalates to the normal drain
1897
1914
  * path. Default 120s, floor 5s. Env: SIGHUP_IDLE_GRACE_MS. */
@@ -1940,6 +1957,20 @@ export interface ServiceConfigFlat {
1940
1957
  * `SEMA_PARENT_PID` 在不在场(operator-knob 铁律)。 Env: `ENGINE_ORPHAN_LINGER_MS`(默认 2000,闭区间
1941
1958
  * [1000, 86400000])。 */
1942
1959
  engineOrphanLingerMs: number;
1960
+ /** [ref]:**首次附着前**的宽限窗 —— 引擎起服以来还没有过任何非探针 HTTP 请求(态「候首触」)时,三合取要**持续**成立多久才自退;
1961
+ * 生效窗 = `max(`{@link engineLingerMs}`, 本值)`(宽限只拉长不缩短;`ENGINE_AUTO_EXIT` 关着 ⇒ owned 窗 = ∞ ⇒ 它也是 ∞)。首个非探针请求
1962
+ * 到达之后回到 {@link engineLingerMs}、单向;父死之后一律 {@link engineOrphanLingerMs}(孤儿压过候首触)。默认 **180000**:防的是一次性
1963
+ * `-p` 壳在 spawn 与首次接触之间被饿住(高载宿主 / CI)超过 owned 窗 —— 从没被碰过的引擎此前按 owned 窗自退,壳醒来起步失败。
1964
+ * `0` = 不给额外宽限(逐字回到本键之前的行为);小于 owned 窗的值同样落成 owned 窗。与两只静默窗**同一只校验器、同一对上下界**,
1965
+ * 多放行字面 `0`(别的零形照常拒);`1..999`(秒当毫秒)与其余坏值**拒启**;解析**无条件**(operator-knob 铁律)。 Env: `ENGINE_FIRST_ATTACH_MS`(默认 180000,
1966
+ * 取值 `0` 或闭区间 [1000, 86400000])。 */
1967
+ engineFirstAttachMs: number;
1968
+ /** [ref]([ref] v3):**交接车道**的静默窗 —— 壳经 `POST /v1/engine/handover` 把引擎交给后台、自己退出之后,三合取(无附着 ∧ 无在飞 ∧
1969
+ * 无运行中、引擎一退就会被收掉的后台 shell)要**持续**成立多久才自退。下一只壳 `POST /v1/engine/attach` 即离开本车道。默认 **1800000**(30 min):
1970
+ * 防的是「用户忘了后台引擎」,不是上限 —— 后台 shell 在跑时本窗不起算(那正是选「后台继续」的意思)。与其余三只窗**同一只校验器**,下界单独是
1971
+ * 60000(交接后的窗比壳重启窗还短没有意义);坏值**拒启**;解析**无条件**(operator-knob 铁律,不看 `ENGINE_AUTO_EXIT` / `SEMA_PARENT_PID`)。
1972
+ * Env: `ENGINE_HANDOVER_LINGER_MS`(默认 1800000,闭区间 [60000, 86400000])。 */
1973
+ engineHandoverLingerMs: number;
1943
1974
  /** E23 (shell-host contract): inbound MCP elicitation HITL. When enabled, the service mounts `RunnerDeps.onElicit` + the
1944
1975
  * `POST /v1/elicitations/:id/respond` route so an opted-in MCP server (`McpServerSpec.elicitation`, itself default
1945
1976
  * OFF) can ask the END USER for input mid-tool-call. LIVE-ONLY (no durable suspend; lost on crash/replica-change).
@@ -2170,6 +2201,14 @@ export interface ServiceConfigFlat {
2170
2201
  logLevel: "debug" | "info" | "warn" | "error";
2171
2202
  /** Per-principal request cap per minute on task/run endpoints. 0 disables. */
2172
2203
  rateLimitPerMin: number;
2204
+ /** `RUN_MAX_CONCURRENT`:本副本**在飞 run 的全局上限**(整数,0 / 缺省 = 不设)。一条新提交要起 run 时,在飞数已到帽 ⇒ 429 `limit.rate_exceeded`
2205
+ * + 机读 `reason: "run_concurrency_cap"` + `retryAfterSec: 5`(同值 `Retry-After` 头)。数的是 `inflightRuns ∪ steerableRuns`(与 `drainState.inflight` 同源);
2206
+ * 判点在三个提交门(`POST /v1/runs` 与 A2A `message/send`、`POST /v1/tasks`、`POST /v1/tasks/stream`)的幂等重放之后;续跑 / 唤醒 / 审批作答不判。
2207
+ * 属主 `http/run-concurrency-cap.ts`。 */
2208
+ runMaxConcurrent: number;
2209
+ /** `RUN_MAX_CONCURRENT_PER_PRINCIPAL`:同一**已验提交主体**(`gatedPrincipal`,与成本配额门同键)在本副本的在飞 run 上限(整数,0 / 缺省 = 不设)。
2210
+ * 无主体请求(无头 service 凭据)不判这一帽,只受 {@link ServiceConfigFlat.runMaxConcurrent}。 */
2211
+ runMaxConcurrentPerPrincipal: number;
2173
2212
  /** Operator CEILING on per-task cost (USD) / tokens (1.37 budget gate). A request may ask for a
2174
2213
  * LOWER limit but is capped to this; 0/unset = no ceiling. The review gateway sets these to stop a
2175
2214
  * single task from burning the shared cloud key. Enforced by core (failed + errorCode budget.*). */
@@ -2337,11 +2376,11 @@ export type ServiceMemoryConfig = Pick<ServiceConfigFlat, "memoryEngineEnabled"
2337
2376
  * 三者都是 operator 在配置面写下的**治理声明**(与 autonomy/commandPolicy 同族),不是存储旋钮
2338
2377
  * ——`retentionPolicy` 尤其容易被误归 store 组:它的消费点是 core 的启动期能力校验与将来的调度面,
2339
2378
  * config 这一层它只是一句声明。 */
2340
- export type ServiceAuthConfig = Pick<ServiceConfigFlat, "authToken" | "authTokens" | "allowUnauthedWrites" | "corsOrigins" | "principalHeader" | "requirePrincipal" | "autonomy" | "commandPolicy" | "compliancePosture" | "lockedConfigKeys" | "configCatalogEnabled" | "retentionPolicy" | "retentionSweep" | "operatorPrincipals" | "operatorSingleUser" | "principalJwtPubkeys" | "principalJwtIss" | "principalJwtAud" | "authBridgeIssuer" | "principalJwtMaxTtlSec" | "bindHost" | "bindHostSource">;
2379
+ export type ServiceAuthConfig = Pick<ServiceConfigFlat, "authToken" | "authTokens" | "allowUnauthedWrites" | "corsOrigins" | "principalHeader" | "requirePrincipal" | "autonomy" | "commandPolicy" | "compliancePosture" | "lockedConfigKeys" | "configCatalogEnabled" | "retentionPolicy" | "retentionSweep" | "operatorPrincipals" | "operatorSingleUser" | "serviceTokenActsForDeployment" | "principalJwtPubkeys" | "principalJwtIss" | "principalJwtAud" | "authBridgeIssuer" | "principalJwtMaxTtlSec" | "bindHost" | "bindHostSource">;
2341
2380
  /** 组:orchestration(编排 + 执行车道 + 沙箱面 + workflow/后台 agent 存留)。 */
2342
2381
  export type ServiceOrchestrationConfig = Pick<ServiceConfigFlat, "sandboxGit" | "remoteExec" | "remoteExecHomeDir" | "requireExecutionLane" | "worktreeIsolation" | "leaderEnabled" | "leaderFanoutEnabled" | "routerEnabled" | "selfOrchestrationEnabled" | "selfOrchestrationModels" | "selfOrchestrationWorkerIsolation" | "forkEnabled" | "experimentalObserverAgents" | "schedulerEnabled" | "schedulerSessionWakeup" | "schedulerSessionLifetime" | "schedulerStorePath" | "planModeEnabled" | "hooksTimeoutMs" | "workflowRunStoreBackend" | "workflowOrphanGraceMs" | "workflowJournalRetentionMs" | "workflowRunRetentionMs" | "usageWindows" | "workflowAgentsReadOnly" | "workflowSizeGuideline" | "backgroundAgentRetentionMs" | "backgroundAgentStaleRunningMs" | "backgroundAgentParkClaimStaleMs" | "delegationEntryCaps" | "rosterRetentionMs" | "leaderRunStaleMs" | "scratchpadSweepTtlMs" | "sandboxPkgSource" | "sandboxPkgSourceCustom" | "sessionAutoTitle" | "sessionAutoTitleSource" | "selectEnvironmentTool" | "envFactsEnabled" | "toolDeferLongtail" | "lspEnabled" | "lspHostEnabled" | "lspEnvAllow" | "imageBakes" | "readFace" | "readFaceSource" | "taskWriteFaceEscalation" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "readDenyFloorRequired" | "sandboxReadFloor" | "agentConfigDir" | "configLkgPath" | "configLkgEnabled">;
2343
2382
  /** 组:limitsHttp(HTTP 面 + 各类上限/配额/回收窗)。 */
2344
- export type ServiceLimitsHttpConfig = Pick<ServiceConfigFlat, "port" | "attachmentOrphanGraceMs" | "workspaceFileMaxBytes" | "attachmentMaxBytes" | "attachmentMimeAllowlist" | "attachmentUnboundTtlMs" | "infraCostRates" | "drainGraceMs" | "drainSecondSignalMinGapMs" | "sighupIdleGraceMs" | "parentPid" | "engineAutoExit" | "engineLingerMs" | "engineOrphanLingerMs" | "rateLimitPerMin" | "maxTaskCostUsd" | "maxTaskTokens" | "maxPrincipalCostUsd" | "costQuotaWindowSec" | "reapIntervalSec" | "runStaleSec" | "toolResultTtlSec">;
2383
+ export type ServiceLimitsHttpConfig = Pick<ServiceConfigFlat, "port" | "attachmentOrphanGraceMs" | "workspaceFileMaxBytes" | "attachmentMaxBytes" | "attachmentMimeAllowlist" | "attachmentUnboundTtlMs" | "adoptionImportMaxSessions" | "adoptionImportMaxSessionBytes" | "infraCostRates" | "drainGraceMs" | "drainSecondSignalMinGapMs" | "sighupIdleGraceMs" | "parentPid" | "engineAutoExit" | "engineLingerMs" | "engineOrphanLingerMs" | "engineFirstAttachMs" | "engineHandoverLingerMs" | "rateLimitPerMin" | "runMaxConcurrent" | "runMaxConcurrentPerPrincipal" | "maxTaskCostUsd" | "maxTaskTokens" | "maxPrincipalCostUsd" | "costQuotaWindowSec" | "reapIntervalSec" | "runStaleSec" | "toolResultTtlSec">;
2345
2384
  /** 组:observability(可观测)。 */
2346
2385
  export type ServiceObservabilityConfig = Pick<ServiceConfigFlat, "metricsToken" | "traceToken" | "toolTrace" | "traceThinking" | "logLevel" | "otel">;
2347
2386
  /** 组:integrations(外部集成)。`mcpServers` / `a2aPeers` 由 web-admin 适配器填(无 env 腿),归本组。 */
package/dist/config.d.ts CHANGED
@@ -502,11 +502,16 @@ export declare function parseCapEnv(name: string, raw: string | undefined): {
502
502
  * 这里**不改解析**(让配置根跟着 `LOCAL_DATA_ROOT` 走,会让现有部署的 config.d 当场失踪 —— 代价比
503
503
  * 分家本身大得多)。只回一个「分家了,两个根分别是什么」的事实,由 boot 期打告警,合一旋钮 = `CONFIG_LOCAL_DIR`。
504
504
  *
505
- * @returns 分家时回两个根;一致(或已被 CONFIG_LOCAL_DIR/AGENT_DATA_DIR 统一)时回 undefined。
505
+ * 判的是「**一声不响**的分家」,不是「两个根不同」:合一旋钮一旦给出就是运维表过的态 —— `CONFIG_LOCAL_DIR`
506
+ * 等于数据根 = 合一,不等 = 有意分家,两者都不报。只有配置根是**推导**来的(`AGENT_DATA_DIR` / 家目录缺省)
507
+ * 且 ≠ 数据根,才可能是没人表过态的分家 ⇒ 报。
508
+ *
509
+ * @returns 一声不响的分家时回两个根;一致、或 `CONFIG_LOCAL_DIR` 显式在场(等 = 合一,不等 = 有意分家)时回 undefined。
506
510
  */
507
511
  export declare function splitLocalRoots(a: {
508
512
  /** optional:类型上可缺席(config-types 里是 `localDataRoot?`)——缺席时无从比较,判为不分家。 */
509
513
  localDataRoot: string | undefined;
514
+ /** `CONFIG_LOCAL_DIR`(`loadConfig` 已把空串归为缺席):在场 ⇒ 运维用合一旋钮表过态,本函数不再判。 */
510
515
  configLocalDir: string | undefined;
511
516
  agentDataDir: string | undefined;
512
517
  home: string;
package/dist/config.js CHANGED
@@ -3,7 +3,7 @@ import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF, mintCapabilityKeys } from "./mod
3
3
  import { homedir } from "node:os";
4
4
  import { isAbsolute, join, posix as posixPath } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
- import { compileAllowList, inheritEnvPolicyProblem, BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, isModelPriced, PROTOCOL_TABLE, RECOMMENDED_SENSITIVE_PATTERNS, judgeRuleToolName, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, principalInboxConsumerOf, carriesCredential } from "@sema-agent/core";
6
+ import { compileAllowList, inheritEnvPolicyProblem, BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, isModelPriced, PROTOCOL_TABLE, RECOMMENDED_SENSITIVE_PATTERNS, judgeRuleToolName, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, principalInboxConsumerOf, carriesCredential, isReplicableScope } from "@sema-agent/core";
7
7
  import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES, WEB_ADMIN_ENV, retiredEnvRefusal, stripControlAndBidi } from "@sema-agent/settings-schema";
8
8
  import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
9
9
  import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
@@ -16,6 +16,7 @@ import { projectLayerOwnerOf } from "./project-layer-key.js";
16
16
  import { DEFAULT_QUESTION_THROTTLE } from "./question.js";
17
17
  import { GIT_API_KINDS, isGitApiKind } from "./git-api-kind.js";
18
18
  import { CONFIG_PROVIDER_WORDS, RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC, RESILIENCE_DEFAULTS, TASK_WRITE_FACE_ESCALATIONS, MAX_TIMER_DELAY_MS, AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS, DRAIN_GRACE_FLOOR_MS, DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS, DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS, FIRST_BYTE_TIMEOUT_BOUNDS, FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS, fleetScopeOf, DEVICE_DELIVERY_TIMEOUT_BOUNDS, DEVICE_EXEC_TIMEOUT_BOUNDS, inWholeNumberBounds, wholeNumberBoundsRule } from "./config-types.js";
19
+ import { parseTrustedProxyCidr } from "./net-address.js";
19
20
  import { DEVICE_HELLO_ACK_BOUNDS } from "./device-ws-protocol.js";
20
21
  import { FLEET_ADVERTISE_ADDRESS_ENV, FLEET_GENERATION_ENV, FLEET_SCOPE_ENV, SERVING_LEASE_TTL_FLOOR_MS, isCanonicalGeneration } from "@sema-agent/settings-schema/fleet";
21
22
  import { ScopeId } from "@sema-agent/settings-schema/api/scopes";
@@ -59,6 +60,7 @@ import { allowlistedEnv } from "./server-secret-env.js";
59
60
  import { ENV_NAME_ALLOWLIST_KNOBS, ENV_NAME_ALLOWLIST_KNOB_NAMES, describeAllowlistPostures } from "./env-name-allowlist-knobs.js";
60
61
  import { APPROVAL_ASK_RETENTION_DEFAULT_MS, APPROVAL_ASK_RETENTION_FLOOR_MS } from "./approval-ask-retention.js";
61
62
  import { parseModsDeclaration } from "./mods-declaration.js";
63
+ import { ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT, ADOPTION_IMPORT_MAX_SESSIONS_FLOOR, ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING, ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT, ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR } from "./adoption/import-limits.js";
62
64
  import { buildDeclaredEngineWithoutCoordinatesRefusal, missingSqlCoordinateKeys } from "./sql-engine-coordinates.js";
63
65
  export { RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC } from "./config-types.js";
64
66
  function csv(name) {
@@ -274,6 +276,11 @@ function clampEnvWithWarn(name, fallback, min, max = Number.POSITIVE_INFINITY) {
274
276
  CONFIG_WARNINGS.push({ env: name, raw: env(name, fallback), used: String(used), kind: "clamped" });
275
277
  return used;
276
278
  }
279
+ function countEnvClamped(name, fallback, min, max = Number.POSITIVE_INFINITY) {
280
+ if (!Number.isInteger(numEnv(name, String(fallback))))
281
+ throw new Error(`env ${name}=${env(name, String(fallback))} must be a whole number (it is a count)`);
282
+ return clampEnvWithWarn(name, String(fallback), min, max);
283
+ }
277
284
  function numEnvOr(name, fallback) {
278
285
  const raw = process.env[name];
279
286
  if (raw === undefined || raw === "")
@@ -439,6 +446,19 @@ function parseDevicePreAuthPerRemoteEnv() {
439
446
  }
440
447
  return n;
441
448
  }
449
+ function parseDeviceTrustedProxyCidrsEnv(raw) {
450
+ if (raw === undefined || raw === "")
451
+ return undefined;
452
+ const items = raw.split(",").map((item) => item.replace(/^[ \t]+|[ \t]+$/g, ""));
453
+ return items.map((item, i) => {
454
+ const r = parseTrustedProxyCidr(item);
455
+ if (r.ok)
456
+ return r.text;
457
+ throw new Error(`env DEVICE_TRUSTED_PROXY_CIDRS item ${i + 1} of ${items.length} (${JSON.stringify(item)}) ${r.flaw}. ` +
458
+ `This list names the reverse proxies whose X-Forwarded-For the device pre-auth cap trusts — list only your own proxies, comma-separated ` +
459
+ `(e.g. 10.0.0.0/8,fd00::/8); unset it to read no proxy header at all (the cap is then keyed on the socket peer).`);
460
+ });
461
+ }
442
462
  function parseFileHistoryRetention() {
443
463
  const raw = process.env.FILE_HISTORY_RETENTION_KEEP;
444
464
  if (raw === undefined || raw === "")
@@ -1590,19 +1610,30 @@ function parentPidEnv() {
1590
1610
  return { parentPid: n };
1591
1611
  }
1592
1612
  const ENGINE_LINGER_FLOOR_MS = 1_000;
1613
+ const ENGINE_HANDOVER_LINGER_FLOOR_MS = 60_000;
1593
1614
  const ENGINE_LINGER_CEIL_MS = 24 * 60 * 60 * 1_000;
1594
- function lingerMsEnv(name, raw, defaultMs, disableHint) {
1615
+ function engineWindowZeroSentence(zero) {
1616
+ switch (zero.kind) {
1617
+ case "refused":
1618
+ return `There is no "disable" value here — ${zero.disableHint}`;
1619
+ case "noGrace":
1620
+ return `the literal "0" is the one value below the floor accepted here — ${zero.offHint}`;
1621
+ }
1622
+ }
1623
+ function lingerMsEnv(name, raw, defaultMs, floorMs, zero) {
1595
1624
  if (raw === undefined || raw.trim() === "")
1596
1625
  return defaultMs;
1626
+ if (zero.kind === "noGrace" && raw.trim() === "0")
1627
+ return 0;
1597
1628
  const n = parseNumOrFail(name, raw);
1598
- if (!Number.isSafeInteger(n) || n < ENGINE_LINGER_FLOOR_MS || n > ENGINE_LINGER_CEIL_MS) {
1629
+ if (!Number.isSafeInteger(n) || n < floorMs || n > ENGINE_LINGER_CEIL_MS) {
1599
1630
  throw new Error(`env ${name}="${raw}" must be an INTEGER number of MILLISECONDS in ` +
1600
- `[${ENGINE_LINGER_FLOOR_MS}, ${ENGINE_LINGER_CEIL_MS}] (1s … 24h) — it is how long ` +
1631
+ `[${floorMs}, ${ENGINE_LINGER_CEIL_MS}] (${floorMs / 1_000}s … 24h) — it is how long ` +
1601
1632
  `"nobody attached, no run in flight, no HTTP touch" must hold CONTINUOUSLY before the engine self-exits. ` +
1602
1633
  `A value like "60" is the seconds-for-milliseconds slip: a 60ms window kills the engine inside a shell's own ` +
1603
1634
  `restart gap. A value like "1e100" passes a naive "is it a positive integer" check but the elapsed clock can ` +
1604
1635
  `NEVER reach it, which silently turns self-exit off while looking configured. ` +
1605
- `There is no "disable" value here — ${disableHint}`);
1636
+ engineWindowZeroSentence(zero));
1606
1637
  }
1607
1638
  return n;
1608
1639
  }
@@ -1757,6 +1788,10 @@ function parseMemoryDomain(ctx) {
1757
1788
  if (scope === undefined) {
1758
1789
  throw new Error("MEMORY_SYNC_URL is set but no sync scope is derivable (memory engine off or multi-tenant without an explicit scope) — set MEMORY_SYNC_SCOPE, or run the single-user file memory engine with a typed MEMORY_SCOPE (e.g. user:<tenant>) so it provides one");
1759
1790
  }
1791
+ if (!isReplicableScope(scope)) {
1792
+ throw new Error(`${memorySyncScopeRaw !== undefined ? "MEMORY_SYNC_SCOPE" : "MEMORY_SCOPE"} names a userlocal: memory layer as the sync layer — that layer family never leaves the store it is written in ` +
1793
+ "(the engine refuses to sync it before any read or request), so this sync leg would fail every round. Set MEMORY_SYNC_SCOPE to a layer that may be replicated, or unset MEMORY_SYNC_URL.");
1794
+ }
1760
1795
  if (carriesCredential(scope)) {
1761
1796
  throw new Error(`${memorySyncScopeRaw !== undefined ? "MEMORY_SYNC_SCOPE" : "MEMORY_SCOPE"} (the memory sync layer's name) holds a credential-shaped part — the layer name travels verbatim in every sync request path and report, so it is refused, never cleaned: rename the layer`);
1762
1797
  }
@@ -1915,6 +1950,7 @@ function parseAuthDomain(ctx) {
1915
1950
  ...parseGovernanceDeclarations(),
1916
1951
  operatorPrincipals: csv("OPERATOR_PRINCIPALS"),
1917
1952
  operatorSingleUser: boolEnv("OPERATOR_SINGLE_USER", false),
1953
+ serviceTokenActsForDeployment: boolEnv("SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT", true),
1918
1954
  configCatalogEnabled: boolEnv("CONFIG_CATALOG_ENABLED", true),
1919
1955
  principalJwtPubkeys,
1920
1956
  principalJwtIss,
@@ -2062,6 +2098,7 @@ function parseOrchestrationDomain(ctx) {
2062
2098
  ...((n) => (n !== undefined ? { maxInflightPerDevice: n } : {}))(parseDeviceBoundedIntEnv("DEVICE_MAX_INFLIGHT_PER_DEVICE", process.env.DEVICE_MAX_INFLIGHT_PER_DEVICE, DEVICE_HELLO_ACK_BOUNDS.maxInflight)),
2063
2099
  ...((n) => (n !== undefined ? { maxPreAuthPerRemote: n } : {}))(parseDevicePreAuthPerRemoteEnv()),
2064
2100
  ...((n) => (n !== undefined ? { enrollTokenTtlSec: n } : {}))(parseDeviceEnrollTokenTtlEnv()),
2101
+ ...((n) => (n !== undefined ? { trustedProxyCidrs: n } : {}))(parseDeviceTrustedProxyCidrsEnv(process.env.DEVICE_TRUSTED_PROXY_CIDRS)),
2065
2102
  relay: parseDeviceRelayUrlEnv(process.env.DEVICE_RELAY_URL),
2066
2103
  ...(process.env.DEVICE_SUPERSEDE ? { supersede: enumEnv("DEVICE_SUPERSEDE", "stale_only", ["stale_only", "deny"]) } : {}),
2067
2104
  }
@@ -2158,6 +2195,8 @@ function parseLimitsHttpDomain() {
2158
2195
  ? { attachmentMimeAllowlist: csv("ATTACHMENT_MIME_ALLOWLIST").map((s) => s.toLowerCase()) }
2159
2196
  : {}),
2160
2197
  attachmentUnboundTtlMs: clampEnvWithWarn("ATTACHMENT_UNBOUND_TTL_MS", String(24 * 3600 * 1000), LIMITS_HTTP_FLOORS.attachmentUnboundTtlMs),
2198
+ adoptionImportMaxSessions: countEnvClamped("ADOPTION_IMPORT_MAX_SESSIONS", ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT, ADOPTION_IMPORT_MAX_SESSIONS_FLOOR),
2199
+ adoptionImportMaxSessionBytes: countEnvClamped("ADOPTION_IMPORT_MAX_SESSION_BYTES", ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT, ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR, ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING),
2161
2200
  infraCostRates: {
2162
2201
  toolCallMicroUsd: clampEnvWithWarn("INFRA_COST_TOOL_CALL", "0", 0),
2163
2202
  sandboxSecMicroUsd: clampEnvWithWarn("INFRA_COST_SANDBOX_SEC", "0", 0),
@@ -2173,9 +2212,23 @@ function parseLimitsHttpDomain() {
2173
2212
  sighupIdleGraceMs: clampEnvWithWarn("SIGHUP_IDLE_GRACE_MS", String(120_000), 5_000),
2174
2213
  ...parentPidEnv(),
2175
2214
  engineAutoExit: boolEnv("ENGINE_AUTO_EXIT", false),
2176
- engineLingerMs: lingerMsEnv("ENGINE_LINGER_MS", process.env.ENGINE_LINGER_MS, 60_000, "set ENGINE_AUTO_EXIT=false to turn self-exit off entirely."),
2177
- engineOrphanLingerMs: lingerMsEnv("ENGINE_ORPHAN_LINGER_MS", process.env.ENGINE_ORPHAN_LINGER_MS, 2_000, "this window only applies once the SEMA_PARENT_PID process is gone — unset SEMA_PARENT_PID to stop watching the parent at all."),
2215
+ engineLingerMs: lingerMsEnv("ENGINE_LINGER_MS", process.env.ENGINE_LINGER_MS, 60_000, ENGINE_LINGER_FLOOR_MS, { kind: "refused", disableHint: "set ENGINE_AUTO_EXIT=false to turn self-exit off entirely." }),
2216
+ engineOrphanLingerMs: lingerMsEnv("ENGINE_ORPHAN_LINGER_MS", process.env.ENGINE_ORPHAN_LINGER_MS, 2_000, ENGINE_LINGER_FLOOR_MS, {
2217
+ kind: "refused",
2218
+ disableHint: "this window only applies once the SEMA_PARENT_PID process is gone — unset SEMA_PARENT_PID to stop watching the parent at all.",
2219
+ }),
2220
+ engineFirstAttachMs: lingerMsEnv("ENGINE_FIRST_ATTACH_MS", process.env.ENGINE_FIRST_ATTACH_MS, 180_000, ENGINE_LINGER_FLOOR_MS, {
2221
+ kind: "noGrace",
2222
+ offHint: "it means no extra grace before the first non-probe request (the window is then ENGINE_LINGER_MS, as before this knob existed); " +
2223
+ "set ENGINE_AUTO_EXIT=false to turn self-exit off entirely.",
2224
+ }),
2225
+ engineHandoverLingerMs: lingerMsEnv("ENGINE_HANDOVER_LINGER_MS", process.env.ENGINE_HANDOVER_LINGER_MS, 1_800_000, ENGINE_HANDOVER_LINGER_FLOOR_MS, {
2226
+ kind: "refused",
2227
+ disableHint: "this window only applies after a shell hands the engine over (POST /v1/engine/handover) — a shell that never does so never uses it; set ENGINE_AUTO_EXIT=false and unset SEMA_PARENT_PID to turn self-exit off entirely.",
2228
+ }),
2178
2229
  rateLimitPerMin: numEnv("RATE_LIMIT_RPM", "0"),
2230
+ runMaxConcurrent: nonNegativeIntEnv("RUN_MAX_CONCURRENT", "在飞 run 全局并发帽"),
2231
+ runMaxConcurrentPerPrincipal: nonNegativeIntEnv("RUN_MAX_CONCURRENT_PER_PRINCIPAL", "按主体在飞 run 并发帽"),
2179
2232
  maxTaskCostUsd: numEnv("MAX_TASK_COST_USD", "0"),
2180
2233
  maxTaskTokens: numEnv("MAX_TASK_TOKENS", "0"),
2181
2234
  maxPrincipalCostUsd: numEnv("MAX_PRINCIPAL_COST_USD", "0"),
@@ -2484,7 +2537,7 @@ const MEMORY_GROUP_KEYS = [
2484
2537
  const AUTH_GROUP_KEYS = [
2485
2538
  "authToken", "authTokens", "allowUnauthedWrites", "corsOrigins", "principalHeader", "requirePrincipal", "autonomy",
2486
2539
  "commandPolicy", "compliancePosture", "lockedConfigKeys", "retentionPolicy", "retentionSweep",
2487
- "operatorPrincipals", "operatorSingleUser", "configCatalogEnabled", "principalJwtPubkeys", "principalJwtIss", "principalJwtAud",
2540
+ "operatorPrincipals", "operatorSingleUser", "serviceTokenActsForDeployment", "configCatalogEnabled", "principalJwtPubkeys", "principalJwtIss", "principalJwtAud",
2488
2541
  "principalJwtMaxTtlSec", "authBridgeIssuer", "bindHost", "bindHostSource",
2489
2542
  ];
2490
2543
  const ORCHESTRATION_GROUP_KEYS = [
@@ -2501,8 +2554,9 @@ const ORCHESTRATION_GROUP_KEYS = [
2501
2554
  const LIMITS_HTTP_GROUP_KEYS = [
2502
2555
  "port", "attachmentOrphanGraceMs", "workspaceFileMaxBytes", "attachmentMaxBytes", "attachmentMimeAllowlist",
2503
2556
  "attachmentUnboundTtlMs", "infraCostRates", "drainGraceMs", "drainSecondSignalMinGapMs", "sighupIdleGraceMs", "parentPid",
2504
- "engineAutoExit", "engineLingerMs", "engineOrphanLingerMs",
2505
- "rateLimitPerMin", "maxTaskCostUsd",
2557
+ "engineAutoExit", "engineLingerMs", "engineOrphanLingerMs", "engineFirstAttachMs", "engineHandoverLingerMs",
2558
+ "rateLimitPerMin", "runMaxConcurrent", "runMaxConcurrentPerPrincipal", "maxTaskCostUsd",
2559
+ "adoptionImportMaxSessions", "adoptionImportMaxSessionBytes",
2506
2560
  "maxTaskTokens", "maxPrincipalCostUsd", "costQuotaWindowSec", "reapIntervalSec", "runStaleSec", "toolResultTtlSec",
2507
2561
  ];
2508
2562
  const OBSERVABILITY_GROUP_KEYS = ["metricsToken", "traceToken", "toolTrace", "traceThinking", "logLevel", "otel"];
@@ -2729,7 +2783,9 @@ export function parseCapEnv(name, raw) {
2729
2783
  return { value: n };
2730
2784
  }
2731
2785
  export function splitLocalRoots(a) {
2732
- const configRoot = a.configLocalDir ?? a.agentDataDir ?? join(a.home, ".ai-agent");
2786
+ if (a.configLocalDir !== undefined)
2787
+ return undefined;
2788
+ const configRoot = a.agentDataDir ?? join(a.home, ".ai-agent");
2733
2789
  if (!a.localDataRoot || a.localDataRoot === configRoot)
2734
2790
  return undefined;
2735
2791
  return { dataRoot: a.localDataRoot, configRoot };
@@ -0,0 +1,19 @@
1
+ import type { DeploymentShapeInput } from "./deployment-shape.js";
2
+ /** 表的条数上限(一条约百字节量级)。引擎的会话暂存自己按会话数有上限(超了整会话驱逐最旧);本表的上限比它宽得多。 */
3
+ export declare const DELETED_SESSION_ID_CAP = 50000;
4
+ /**
5
+ * **铸点**(唯一):本进程的在线删除协调器在删除会话本体之前记一笔 —— 围栏先立,id 才空出来。删除随后失败也无害:
6
+ * 这一笔只拒「别的属主」,而会话还在时别的属主本来就用不了它。
7
+ * 同一只 id 再删一次:这一次的删前属主对已记的每一位都等价(同一只等价律判)⇒ 收进集合(前几位一位不丢 —— 等价律有方向、不传递,只记最新一位会让
8
+ * 「哨兵删 → 无主重登再删 → `default` 用」绕过「哨兵 ≢ `default`」);对某一位不等价 ⇒ 记成「谁都不是」。后一次删除从不覆盖前一位(前一位的暂存仍可能在本进程)。
9
+ * `deployment` = 部署形(等价律的窄互认臂读它;调用方递 `ServiceConfig` 整份)。
10
+ */
11
+ export declare function retireSessionId(sessionId: string, owner: string | null, deployment: DeploymentShapeInput<"principal">): void;
12
+ /**
13
+ * **读点**(唯一;执行上下文解析器 `http/execution-context.ts` 步 ① 调):这只 id 在本进程被删过、而删前的属主不是 `owner` ⇒ `true`(解析器拒)。
14
+ * `owner` = 这条执行要服务的属主(根会话行上那一读的住客);`undefined` = 判不出 ⇒ 删过就为真(fail-closed)。
15
+ * 同一位 = 对**每一位**删前属主,会话属主等价律 `sameSessionOwner(deployment, 删前属主, owner)` 都成立(删前属主是行上记下的那一格,本次住客是这一次的调用方);
16
+ * 被互不等价的属主各删过一次的 id 对谁都为真。
17
+ */
18
+ export declare function sessionIdRetiredFor(sessionId: string, owner: string | null | undefined, deployment: DeploymentShapeInput<"principal">): boolean;
19
+ //# sourceMappingURL=deleted-session-ids.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { recordFailOpen } from "./observability/fail-open.js";
2
+ import { sameSessionOwner } from "./security.js";
3
+ export const DELETED_SESSION_ID_CAP = 50_000;
4
+ const DELETED_UNDER_SEVERAL = Symbol("deleted under several owners");
5
+ const formerOwners = new Map();
6
+ export function retireSessionId(sessionId, owner, deployment) {
7
+ const prior = formerOwners.get(sessionId);
8
+ const recorded = prior === undefined ? [owner] : sessionIdRetiredFor(sessionId, owner, deployment) ? DELETED_UNDER_SEVERAL : prior === DELETED_UNDER_SEVERAL || prior.includes(owner) ? prior : [...prior, owner];
9
+ formerOwners.delete(sessionId);
10
+ formerOwners.set(sessionId, recorded);
11
+ if (formerOwners.size <= DELETED_SESSION_ID_CAP)
12
+ return;
13
+ const oldest = formerOwners.keys().next().value;
14
+ if (oldest !== undefined)
15
+ formerOwners.delete(oldest);
16
+ recordFailOpen("server.session-id-tombstone.evicted", `cap=${DELETED_SESSION_ID_CAP}`);
17
+ }
18
+ export function sessionIdRetiredFor(sessionId, owner, deployment) {
19
+ const former = formerOwners.get(sessionId);
20
+ if (former === undefined)
21
+ return false;
22
+ if (owner === undefined || former === DELETED_UNDER_SEVERAL)
23
+ return true;
24
+ return !former.every((f) => sameSessionOwner(deployment, f, owner));
25
+ }
26
+ //# sourceMappingURL=deleted-session-ids.js.map
@@ -0,0 +1,155 @@
1
+ /**
2
+ * 随包的引擎部署事实(npm 包内 `deploy/facts/`)—— 成员集、Schema 方言、形变登记表的**唯一定义处**,以及其中两份成员(车道 / 钥匙保管目录)的投影与 Schema。
3
+ *
4
+ * ## 成员律
5
+ * `deploy/facts/` 只装**引擎自己的部署要求**:引擎发出的 API 调用、引擎按名读的键与目录、引擎要求先存在的条件。每一份都有引擎属主,都是生成物
6
+ * (唯一生成器 `scripts/gen-deploy-lanes.ts`,`--check` 与 `test/deploy-lane-projections.test.ts` 钉「入库 ≡ 生成物」),从不手写。
7
+ * 部署方拥有的策略实例(引擎读来诊断、不据以发调用的东西,例如沙箱出网的 NetworkPolicy)不是成员。
8
+ * 每个成员 `<m>` = 数据 `<m>.json` + 一份机器可读 Schema `<m>.schema.json`;另有一份形变登记 `CHANGES.json`。三类文件都是 npm 子路径
9
+ * `@sema-agent/server/deploy/facts/<文件>`(子路径 = 包内文件路径)。
10
+ * · `lanes`:每条执行车道的租户档、隔离位、必需键 —— 投影自 settings-schema 车道表与执行环境能力块({@link LANE_FACTS_SCHEMA};行由生成器从同一个车道模型渲出,
11
+ * 安装器那张旧车道表的 `users` / `isolation` 两列也从这些行派生,同源零双写);
12
+ * · `sandbox-rbac`:k8s 沙箱服务账号的 RBAC 规则表 —— 表与 Schema 都在 `src/sandbox-rbac-rules.ts`(和表放一起);
13
+ * · `sealed-key`:钥匙保管目录的安装契约 —— 投影自 `src/sealed-key-layout.ts` 的布局常量与配置读法「`SEALED_KEY_DIR` 须是绝对路径」({@link SEALED_KEY_FACTS})。
14
+ *
15
+ * ## 契约:「未登记的加性形变,或未抬版的破坏性形变 ⇒ 红」
16
+ * 发车链对**上一个已发 tag** 里的同名 Schema 求差(`scripts/deploy-facts-gate.ts`;CI 浅克隆读不到 tag,这道判据在发车链跑),
17
+ * 差异逐条分成加性 / 破坏性,与 {@link FACTS_SCHEMA_CHANGES} 里本版新登记的条目对账。**加性只有一种:新增一个可选属性**;其余任何形变
18
+ * (删属性、改类型、可选 ⇄ 必有、新增必有属性、`items` 形变、闭集增 / 删词、`const` 变、`minItems` / `uniqueItems` / `x-uniqueKey` 变)都是破坏性。
19
+ * 值的含义变了而 Schema 不变(例如重新定义某个闭集词)门判不出 —— 改动者登记一条 `breaking` 并写明 `why`,复审按这一条问。
20
+ *
21
+ * ## 版本
22
+ * 每个成员的 `schemaVersion` **从登记表派生**({@link factsSchemaVersion}):首发那一版 = 1,此后每个登记了 `breaking` 的版本 +1。不另写常量 ——
23
+ * 登记一条破坏性形变就抬了版,「改了形忘了抬版」只剩「改了形没登记」一种,门对着已发 tag 抓它。
24
+ * 读方义务:用**同一个包里**那份 Schema 校验;不认识的 `schemaVersion` 整份拒读;同一版本内的未知键忽略。
25
+ */
26
+ import { TENANT_SEPARATION_WORDS } from "@sema-agent/settings-schema/execution-lanes";
27
+ /** 包内目录(npm 子路径前缀 `@sema-agent/server/deploy/facts/`)。 */
28
+ export declare const DEPLOY_FACTS_DIR = "deploy/facts";
29
+ /** 成员闭集。加一个成员 = 这里加一个词 + 生成器给它数据与 Schema + 登记表一条 `introduced`(缺任一处 ⇒ 编译错或生成抛)。 */
30
+ export declare const DEPLOY_FACTS_MEMBERS: readonly ["lanes", "sandbox-rbac", "sealed-key"];
31
+ export type DeployFactsMember = (typeof DEPLOY_FACTS_MEMBERS)[number];
32
+ /** 形变登记表的文件名(与成员同目录;不是成员,没有自己的 Schema)。 */
33
+ export declare const DEPLOY_FACTS_CHANGES_FILE = "CHANGES.json";
34
+ /** 方言 = JSON Schema 2020-12 的一个闭子集;根上的 `$schema` 恒为它。 */
35
+ export declare const FACTS_SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
36
+ /**
37
+ * 方言的节点形(类型就是方言:多写一个关键字 = 编译错;`scripts/deploy-facts-gate.ts` 在 JSON 面再判一次,拿到的是入库文件与已发 tag 上的文件)。
38
+ * · 标量:`string`(可带 `enum` 闭集或 `const`)/ `integer`(可带 `const`)/ `boolean`;
39
+ * · 对象:`properties` + `required`(⊆ properties)+ `additionalProperties: false`(恒关:未登记的键不许出现);
40
+ * · 数组:`items`(必有)+ 可选 `minItems`;标量元素可声明 `uniqueItems: true`,对象元素可声明 `x-uniqueKey`(这几个属性的值组合在数组里唯一;
41
+ * 成员必须是元素的必有属性、且是标量或标量数组 —— 对象成员里加可选属性按上面的判法是加性,却会让旧读方算出的唯一性失真;
42
+ * 标准校验器把它当注解忽略,本仓的校验器执行它)。
43
+ * · JSON 键一律只认自有的(`toString` / `constructor` / `__proto__` 这类原型链上的名字不算「在」)。
44
+ * · `description` 任何节点都可带,差异判法不看它(值含义的变化走人工登记)。
45
+ */
46
+ export type FactsScalarSchema = {
47
+ readonly type: "string";
48
+ readonly enum?: readonly string[];
49
+ readonly const?: string;
50
+ readonly description?: string;
51
+ } | {
52
+ readonly type: "integer";
53
+ readonly const?: number;
54
+ readonly description?: string;
55
+ } | {
56
+ readonly type: "boolean";
57
+ readonly description?: string;
58
+ };
59
+ export interface FactsObjectSchema {
60
+ readonly type: "object";
61
+ readonly properties: {
62
+ readonly [key: string]: FactsNodeSchema;
63
+ };
64
+ readonly required: readonly string[];
65
+ readonly additionalProperties: false;
66
+ readonly description?: string;
67
+ }
68
+ export interface FactsArraySchema {
69
+ readonly type: "array";
70
+ readonly items: FactsNodeSchema;
71
+ readonly minItems?: number;
72
+ readonly uniqueItems?: true;
73
+ readonly "x-uniqueKey"?: readonly string[];
74
+ readonly description?: string;
75
+ }
76
+ export type FactsNodeSchema = FactsScalarSchema | FactsObjectSchema | FactsArraySchema;
77
+ /**
78
+ * 每种节点允许的关键字(运行期闭集;`scripts/deploy-facts-gate.ts` 的方言判读它,对入库文件与已发 tag 上的文件都判)。
79
+ * `satisfies` 让这张表只列类型里有的键;类型里多出来而表里没列的键,生成器在渲 Schema 时当场抛「方言外的关键字」。根节点另多一个 `$schema`。
80
+ */
81
+ export declare const FACTS_SCHEMA_KEYWORDS: {
82
+ readonly string: readonly ["type", "enum", "const", "description"];
83
+ readonly integer: readonly ["type", "const", "description"];
84
+ readonly boolean: readonly ["type", "description"];
85
+ readonly object: readonly ["type", "properties", "required", "additionalProperties", "description"];
86
+ readonly array: readonly ["type", "items", "minItems", "uniqueItems", "x-uniqueKey", "description"];
87
+ };
88
+ /** 根:一个对象节点 + `$schema`;`schemaVersion` 必有且形恒为 `{ type: "integer", const: <版本> }`(门把这一处当版本通道,不当形变)。 */
89
+ export interface FactsRootSchema extends FactsObjectSchema {
90
+ readonly $schema: typeof FACTS_SCHEMA_DIALECT;
91
+ readonly properties: {
92
+ readonly schemaVersion: {
93
+ readonly type: "integer";
94
+ readonly const: number;
95
+ readonly description?: string;
96
+ };
97
+ readonly [key: string]: FactsNodeSchema;
98
+ };
99
+ }
100
+ export declare const FACTS_SCHEMA_CHANGE_KINDS: readonly ["introduced", "additive", "breaking"];
101
+ export type FactsSchemaChangeKind = (typeof FACTS_SCHEMA_CHANGE_KINDS)[number];
102
+ /**
103
+ * 一条形变登记。`pointer` = 实例路径:`""` 是整份,`/lanes/[]/isolation` 是 `lanes` 数组每一行的 `isolation`(`[]` = 数组元素)。
104
+ * `version` = 这条形变随哪个 server 版本发出;已发版本的条目只读(门:基线 tag 上的每一条在本树里原样还在)。
105
+ */
106
+ export interface FactsSchemaChange {
107
+ readonly version: string;
108
+ readonly file: DeployFactsMember;
109
+ readonly kind: FactsSchemaChangeKind;
110
+ readonly pointer: string;
111
+ readonly why: string;
112
+ }
113
+ /**
114
+ * 形变登记表(只追加;生成器把它写成随包 `CHANGES.json` 与 README 的变更节)。
115
+ * 新条目的 `version` 写下一个要发的 server 版本;发车链在版本号抬起后核「本版新登记的条目都是这个版本」。
116
+ */
117
+ export declare const FACTS_SCHEMA_CHANGES: readonly FactsSchemaChange[];
118
+ /**
119
+ * 成员当前的 `schemaVersion`:登记表里恰一条 `introduced`(那一版 = 1),此后每个登记了 `breaking` 的**不同**版本 +1
120
+ * (同一版本里登记几条破坏性形变都只抬一次;首发那一版里的 `breaking` 不算 —— 那时还没有发出去的形)。
121
+ * 登记表不合这个形(零条 / 多条 `introduced`)⇒ 抛:版本号无从派生,不猜。
122
+ */
123
+ export declare function factsSchemaVersion(member: DeployFactsMember, changes?: readonly FactsSchemaChange[]): number;
124
+ /** 隔离位闭集:手跑在不在 OS 级隔离边界里(执行环境能力块的 `isolation` 位;安装器旧车道表的 `isolation` 列也读这两个词)。 */
125
+ export declare const LANE_ISOLATION_WORDS: readonly ["supported", "unsupported"];
126
+ export type LaneIsolationWord = (typeof LANE_ISOLATION_WORDS)[number];
127
+ /** `lanes.json` 的一行(行序 = settings-schema 车道词序)。 */
128
+ export interface LaneFactsRow {
129
+ readonly lane: string;
130
+ readonly tenantSeparation: (typeof TENANT_SEPARATION_WORDS)[number];
131
+ readonly isolation: LaneIsolationWord;
132
+ readonly requiredEnv: readonly string[];
133
+ readonly requiredSecretEnv: readonly string[];
134
+ }
135
+ export declare const LANE_FACTS_SCHEMA: FactsRootSchema;
136
+ /** 钥匙保管目录对安装器的要求(闭集;每个词的意思写在 Schema 的 `description` 里)。 */
137
+ export declare const SEALED_KEY_REQUIREMENTS: readonly ["persist-across-restart", "shared-by-all-replicas", "writable", "whole-directory"];
138
+ export type SealedKeyRequirement = (typeof SEALED_KEY_REQUIREMENTS)[number];
139
+ /** 保管目录路径形的闭集:只收绝对路径(相对路径起服拒)。 */
140
+ export declare const SEALED_KEY_DIR_PATH_FORMS: readonly ["absolute"];
141
+ /**
142
+ * `sealed-key.json` 的内容:安装契约要求**显式设一个绝对路径的 `SEALED_KEY_DIR`**,安装器据此挂卷。
143
+ * 没设它时引擎回落到数据根下的 `sealed-key/`(数据根自身还有一条回落链)—— 那是引擎内部行为,安装器不依赖它,所以不在这份事实里。
144
+ */
145
+ export declare const SEALED_KEY_FACTS: {
146
+ readonly schemaVersion: number;
147
+ readonly dirEnv: "SEALED_KEY_DIR";
148
+ readonly dirPath: "absolute";
149
+ readonly subdirs: readonly ["checkpoint-ctx-keys"];
150
+ readonly dirMode: string;
151
+ readonly fileMode: string;
152
+ readonly requirements: readonly ["persist-across-restart", "shared-by-all-replicas", "writable", "whole-directory"];
153
+ };
154
+ export declare const SEALED_KEY_FACTS_SCHEMA: FactsRootSchema;
155
+ //# sourceMappingURL=deploy-facts.d.ts.map