@sema-agent/server 7.132.0 → 7.133.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 (402) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +174 -55
  5. package/deploy/sema-up/README.md +19 -1
  6. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
  7. package/deploy/sema-up/chart/templates/server.yaml +5 -2
  8. package/deploy/sema-up/stack/compose.yaml +3 -0
  9. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  10. package/dist/adoption/plan.d.ts +3 -2
  11. package/dist/adoption/plan.js +7 -5
  12. package/dist/adoption/runner.js +3 -10
  13. package/dist/adoption/sql.d.ts +3 -2
  14. package/dist/adoption/sql.js +3 -5
  15. package/dist/adoption/wire.d.ts +4 -1
  16. package/dist/adoption/wire.js +1 -0
  17. package/dist/approval-ask-audit-store.d.ts +31 -13
  18. package/dist/approval-ask-audit-store.js +272 -74
  19. package/dist/approval-ask-machine.d.ts +15 -0
  20. package/dist/approval-ask-machine.js +6 -0
  21. package/dist/approval-ask-retention.d.ts +136 -0
  22. package/dist/approval-ask-retention.js +102 -0
  23. package/dist/approval-card.d.ts +79 -19
  24. package/dist/approval-card.js +44 -13
  25. package/dist/approval-deny-reasons.d.ts +1 -1
  26. package/dist/approval.d.ts +9 -0
  27. package/dist/approval.js +24 -3
  28. package/dist/audit.d.ts +27 -10
  29. package/dist/audit.js +12 -16
  30. package/dist/bake-runner/main.js +3 -2
  31. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  32. package/dist/boot/execution-env.js +9 -7
  33. package/dist/boot/execution-lane.js +11 -0
  34. package/dist/boot/leader.js +2 -0
  35. package/dist/boot/memory-boundary.js +2 -2
  36. package/dist/boot/memory-consolidation.d.ts +5 -4
  37. package/dist/boot/memory-consolidation.js +7 -6
  38. package/dist/boot/org-delivery.d.ts +28 -0
  39. package/dist/boot/org-delivery.js +20 -0
  40. package/dist/boot/reapers.d.ts +3 -0
  41. package/dist/boot/reapers.js +21 -1
  42. package/dist/boot/resolve-spec.d.ts +3 -0
  43. package/dist/boot/resolve-spec.js +60 -81
  44. package/dist/boot/runner-deps.js +1 -0
  45. package/dist/boot/session-faces.d.ts +1 -0
  46. package/dist/boot/session-faces.js +4 -2
  47. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  48. package/dist/boot/stage-06-runners.d.ts +2 -0
  49. package/dist/boot/stage-06-runners.js +6 -3
  50. package/dist/boot/stage-07-capability-layer.d.ts +2 -0
  51. package/dist/boot/stage-07-capability-layer.js +24 -3
  52. package/dist/boot/stage-08-reapers.d.ts +2 -0
  53. package/dist/boot/stage-08-reapers.js +2 -2
  54. package/dist/boot/stage-09-leader.d.ts +3 -0
  55. package/dist/boot/stage-10-http-server.d.ts +3 -0
  56. package/dist/boot/stage-10-http-server.js +5 -6
  57. package/dist/boot/stores.js +2 -2
  58. package/dist/boot/web-admin.d.ts +4 -0
  59. package/dist/boot/web-admin.js +151 -63
  60. package/dist/boot/workflow-orchestration.d.ts +2 -0
  61. package/dist/boot/workflow-orchestration.js +2 -1
  62. package/dist/brain.js +8 -3
  63. package/dist/breaker-key.d.ts +6 -0
  64. package/dist/breaker-key.js +29 -0
  65. package/dist/caller-text-echo.d.ts +9 -6
  66. package/dist/caller-text-echo.js +8 -11
  67. package/dist/capabilities/center-plugins.d.ts +7 -0
  68. package/dist/capabilities/center-plugins.js +1 -1
  69. package/dist/capabilities/composite-members.d.ts +1 -1
  70. package/dist/capabilities/composite-members.js +1 -1
  71. package/dist/capabilities/execution-lane.js +2 -2
  72. package/dist/capabilities/hands-lane.d.ts +21 -0
  73. package/dist/capabilities/hands-lane.js +10 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -4
  75. package/dist/capabilities/mcp-probe.js +27 -4
  76. package/dist/capabilities/scenarios.d.ts +63 -7
  77. package/dist/capabilities/scenarios.js +39 -7
  78. package/dist/capability-facts.d.ts +34 -4
  79. package/dist/capability-facts.js +28 -2
  80. package/dist/center-config-tier.d.ts +69 -0
  81. package/dist/center-config-tier.js +42 -0
  82. package/dist/checkpoint-identity.d.ts +16 -0
  83. package/dist/checkpoint-identity.js +19 -0
  84. package/dist/config-catalog.d.ts +17 -10
  85. package/dist/config-catalog.js +43 -28
  86. package/dist/config-d-migration.d.ts +3 -1
  87. package/dist/config-d-migration.js +2 -2
  88. package/dist/config-dir-trust.d.ts +114 -0
  89. package/dist/config-dir-trust.js +388 -0
  90. package/dist/config-invariants.d.ts +18 -5
  91. package/dist/config-invariants.js +35 -3
  92. package/dist/config-provider.d.ts +6 -1
  93. package/dist/config-provider.js +6 -2
  94. package/dist/config-types.d.ts +71 -14
  95. package/dist/config-types.js +8 -0
  96. package/dist/config.d.ts +13 -0
  97. package/dist/config.js +121 -59
  98. package/dist/delegated-session-owner.d.ts +185 -0
  99. package/dist/delegated-session-owner.js +119 -0
  100. package/dist/device-protocol.d.ts +5 -3
  101. package/dist/device-protocol.js +1 -1
  102. package/dist/device-ws-hub.js +21 -2
  103. package/dist/device-ws-protocol.d.ts +70 -6
  104. package/dist/device-ws-protocol.js +50 -23
  105. package/dist/elicitation.js +3 -2
  106. package/dist/entry-problems.d.ts +34 -0
  107. package/dist/entry-problems.js +14 -0
  108. package/dist/execution-lane-caps.d.ts +49 -10
  109. package/dist/execution-lane-caps.js +43 -4
  110. package/dist/field-conflict.d.ts +43 -0
  111. package/dist/field-conflict.js +20 -0
  112. package/dist/fleet/fleet-bus.d.ts +80 -6
  113. package/dist/fleet/fleet-bus.js +41 -9
  114. package/dist/hooks/classic-stations.d.ts +10 -5
  115. package/dist/hooks/classic-stations.js +4 -4
  116. package/dist/hooks/command-spawn.d.ts +57 -0
  117. package/dist/hooks/command-spawn.js +139 -0
  118. package/dist/hooks/hook-llm.js +2 -2
  119. package/dist/hooks/hook-runner.d.ts +127 -25
  120. package/dist/hooks/hook-runner.js +668 -287
  121. package/dist/hooks/hook-source.d.ts +44 -0
  122. package/dist/hooks/hook-source.js +40 -0
  123. package/dist/http/active-run-conflict.d.ts +5 -13
  124. package/dist/http/active-run-conflict.js +17 -27
  125. package/dist/http/admission.js +103 -60
  126. package/dist/http/approval-sweeps.js +55 -18
  127. package/dist/http/caller-trust.d.ts +77 -0
  128. package/dist/http/caller-trust.js +143 -0
  129. package/dist/http/checkpoint-ctx.d.ts +16 -16
  130. package/dist/http/checkpoint-ctx.js +13 -10
  131. package/dist/http/claimed-run.d.ts +4 -3
  132. package/dist/http/device-placement.d.ts +2 -4
  133. package/dist/http/device-placement.js +2 -1
  134. package/dist/http/dispatch.js +10 -4
  135. package/dist/http/durable-run-leg.d.ts +4 -32
  136. package/dist/http/durable-run-leg.js +34 -10
  137. package/dist/http/owner-access.d.ts +56 -0
  138. package/dist/http/owner-access.js +42 -0
  139. package/dist/http/principal-gate.d.ts +48 -23
  140. package/dist/http/principal-gate.js +39 -12
  141. package/dist/http/readiness.d.ts +11 -5
  142. package/dist/http/readiness.js +10 -3
  143. package/dist/http/request-guards.d.ts +16 -23
  144. package/dist/http/request-guards.js +30 -15
  145. package/dist/http/resume-ctx-read.d.ts +2 -5
  146. package/dist/http/resume-ctx-read.js +7 -4
  147. package/dist/http/resume-legs.d.ts +3 -4
  148. package/dist/http/resume-legs.js +126 -69
  149. package/dist/http/retired-service-deps.d.ts +43 -0
  150. package/dist/http/retired-service-deps.js +18 -0
  151. package/dist/http/route-ctx.d.ts +44 -28
  152. package/dist/http/route-ctx.js +4 -0
  153. package/dist/http/route-table.js +2 -0
  154. package/dist/http/routes/a2a-serve.js +3 -4
  155. package/dist/http/routes/admin-config-refresh.js +1 -1
  156. package/dist/http/routes/admin-drain.js +1 -1
  157. package/dist/http/routes/admin-memory-optout.js +5 -1
  158. package/dist/http/routes/adoption.js +2 -9
  159. package/dist/http/routes/approvals-assistant.js +49 -48
  160. package/dist/http/routes/background.js +3 -2
  161. package/dist/http/routes/capabilities.js +20 -4
  162. package/dist/http/routes/config-catalog.d.ts +3 -3
  163. package/dist/http/routes/config-catalog.js +1 -1
  164. package/dist/http/routes/devices.js +3 -17
  165. package/dist/http/routes/diagnostics.js +5 -1
  166. package/dist/http/routes/images.js +6 -7
  167. package/dist/http/routes/leader.js +1 -8
  168. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  169. package/dist/http/routes/mcp-reconnect.js +3 -2
  170. package/dist/http/routes/memory-bundle.js +1 -1
  171. package/dist/http/routes/memory-compliance.js +1 -1
  172. package/dist/http/routes/memory-consolidation.js +1 -1
  173. package/dist/http/routes/memory-origin.js +1 -1
  174. package/dist/http/routes/memory-policy.d.ts +1 -1
  175. package/dist/http/routes/memory-policy.js +3 -2
  176. package/dist/http/routes/notify-wake.js +8 -21
  177. package/dist/http/routes/observability.js +2 -2
  178. package/dist/http/routes/principal-inbox.d.ts +39 -0
  179. package/dist/http/routes/principal-inbox.js +76 -0
  180. package/dist/http/routes/retention-ops.js +2 -9
  181. package/dist/http/routes/rules.js +5 -18
  182. package/dist/http/routes/runs.d.ts +5 -0
  183. package/dist/http/routes/runs.js +33 -106
  184. package/dist/http/routes/session-sync.js +15 -28
  185. package/dist/http/routes/sessions.js +30 -40
  186. package/dist/http/routes/side-query.js +6 -4
  187. package/dist/http/routes/tasks.js +50 -14
  188. package/dist/http/routes/workflows.d.ts +351 -0
  189. package/dist/http/routes/workflows.js +153 -119
  190. package/dist/http/send.d.ts +24 -3
  191. package/dist/http/send.js +14 -2
  192. package/dist/http/server.d.ts +17 -18
  193. package/dist/http/server.js +15 -13
  194. package/dist/http/stored-body-replay.js +17 -4
  195. package/dist/http/submit-ctx.js +4 -3
  196. package/dist/http/submit-replay.d.ts +4 -3
  197. package/dist/http/submit-replay.js +5 -4
  198. package/dist/http/wire-types.d.ts +10 -7
  199. package/dist/index.d.ts +1 -1
  200. package/dist/index.js +0 -1
  201. package/dist/lane-home-probe.d.ts +78 -9
  202. package/dist/lane-home-probe.js +78 -12
  203. package/dist/leader/endpoint.d.ts +4 -1
  204. package/dist/leader/endpoint.js +11 -10
  205. package/dist/limit-refusal.d.ts +17 -5
  206. package/dist/limit-refusal.js +4 -1
  207. package/dist/mcp-assertion-header.d.ts +31 -10
  208. package/dist/mcp-assertion-header.js +10 -3
  209. package/dist/mcp-tool-faces.js +1 -3
  210. package/dist/memory-project-layer.d.ts +37 -0
  211. package/dist/memory-project-layer.js +46 -0
  212. package/dist/memory-scope.d.ts +23 -16
  213. package/dist/memory-scope.js +24 -8
  214. package/dist/memory-sync-client.d.ts +27 -13
  215. package/dist/memory-sync-client.js +107 -18
  216. package/dist/model-entry-refusal.d.ts +9 -1
  217. package/dist/model-entry-refusal.js +6 -1
  218. package/dist/model-plane-face.d.ts +51 -0
  219. package/dist/model-plane-face.js +24 -0
  220. package/dist/model-provider.d.ts +5 -0
  221. package/dist/model-provider.js +4 -2
  222. package/dist/model-route-endpoint.d.ts +8 -11
  223. package/dist/model-route-endpoint.js +4 -7
  224. package/dist/model-route-env.d.ts +22 -0
  225. package/dist/model-route-env.js +2 -0
  226. package/dist/model-route-gap.d.ts +60 -30
  227. package/dist/model-route-gap.js +21 -15
  228. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  229. package/dist/observability/corrupt-read-seat.js +9 -0
  230. package/dist/observability/err-text.d.ts +6 -0
  231. package/dist/observability/err-text.js +18 -4
  232. package/dist/observability/fail-open.d.ts +35 -9
  233. package/dist/observability/fail-open.js +35 -9
  234. package/dist/observability/metrics.js +1 -0
  235. package/dist/observability/prompt-manifest.d.ts +3 -17
  236. package/dist/observability/prompt-manifest.js +45 -42
  237. package/dist/observability/tool-trace.js +9 -9
  238. package/dist/operator-ask.d.ts +10 -0
  239. package/dist/operator-ask.js +3 -0
  240. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  241. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  242. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  243. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  244. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  245. package/dist/orchestration/workflow-notify-journal.js +27 -34
  246. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  247. package/dist/orchestration/workflow-park-decision.js +118 -0
  248. package/dist/org-delivery-gate.d.ts +81 -0
  249. package/dist/org-delivery-gate.js +59 -0
  250. package/dist/panel-tool-names.d.ts +23 -0
  251. package/dist/panel-tool-names.js +8 -0
  252. package/dist/parked-decide.d.ts +39 -6
  253. package/dist/parked-decide.js +98 -51
  254. package/dist/parked-revive-surface.d.ts +9 -2
  255. package/dist/parked-revive-surface.js +11 -8
  256. package/dist/permission-rule-list.d.ts +1 -1
  257. package/dist/permission-rule-list.js +2 -2
  258. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  259. package/dist/plugins/approval-ask-store-file.js +21 -0
  260. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  261. package/dist/plugins/approval-ask-store-memory.js +34 -2
  262. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  263. package/dist/plugins/approval-ask-store-sql.js +37 -1
  264. package/dist/plugins/blob-backend.d.ts +38 -25
  265. package/dist/plugins/blob-backend.js +29 -19
  266. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  267. package/dist/plugins/breaker-state-sql.js +4 -4
  268. package/dist/plugins/caching-session-store.d.ts +3 -0
  269. package/dist/plugins/caching-session-store.js +3 -0
  270. package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
  271. package/dist/plugins/checkpoint-store-sql.js +20 -2
  272. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  273. package/dist/plugins/file-history-store-sql.js +3 -1
  274. package/dist/plugins/file-run-store.d.ts +5 -13
  275. package/dist/plugins/file-run-store.js +9 -0
  276. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  277. package/dist/plugins/fork-routing-session-store.js +12 -1
  278. package/dist/plugins/host-platform.d.ts +2 -0
  279. package/dist/plugins/host-platform.js +2 -1
  280. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  281. package/dist/plugins/local-checkpoint-store.js +6 -1
  282. package/dist/plugins/local-session-store.d.ts +1 -1
  283. package/dist/plugins/local-session-window.d.ts +39 -0
  284. package/dist/plugins/local-session-window.js +54 -0
  285. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  286. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  287. package/dist/plugins/mailbox-store-sql.js +77 -52
  288. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  289. package/dist/plugins/memory-run-store.d.ts +5 -13
  290. package/dist/plugins/memory-run-store.js +8 -0
  291. package/dist/plugins/one-time-migrations.d.ts +110 -5
  292. package/dist/plugins/one-time-migrations.js +320 -8
  293. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  294. package/dist/plugins/org-delivery-quota-store.js +228 -0
  295. package/dist/plugins/pg-pool.js +39 -7
  296. package/dist/plugins/pg-session-storage.d.ts +17 -4
  297. package/dist/plugins/pg-session-storage.js +29 -6
  298. package/dist/plugins/remote-env-adb.d.ts +6 -12
  299. package/dist/plugins/remote-env-adb.js +12 -2
  300. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  301. package/dist/plugins/remote-env-k8s.js +23 -5
  302. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  303. package/dist/plugins/remote-env-local-docker.js +12 -9
  304. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  305. package/dist/plugins/remote-env-ssh.js +17 -11
  306. package/dist/plugins/run-store-sql.d.ts +16 -14
  307. package/dist/plugins/run-store-sql.js +22 -2
  308. package/dist/plugins/schema-indexes.js +2 -0
  309. package/dist/plugins/send-user-file.js +2 -2
  310. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  311. package/dist/plugins/session-epoch-anchor.js +2 -3
  312. package/dist/plugins/session-store.d.ts +18 -8
  313. package/dist/plugins/session-store.js +15 -4
  314. package/dist/plugins/sql-driver.d.ts +74 -11
  315. package/dist/plugins/sql-driver.js +210 -12
  316. package/dist/plugins/sql-errors.d.ts +23 -0
  317. package/dist/plugins/sql-errors.js +21 -0
  318. package/dist/plugins/store-backend.d.ts +36 -1
  319. package/dist/plugins/store-backend.js +40 -14
  320. package/dist/plugins/store-contracts.d.ts +42 -0
  321. package/dist/plugins/store-contracts.js +1 -0
  322. package/dist/plugins/tidb-pool.d.ts +6 -1
  323. package/dist/plugins/tidb-pool.js +44 -10
  324. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  325. package/dist/plugins/tidb-session-storage.js +2 -2
  326. package/dist/plugins/tidb-session-store.d.ts +24 -4
  327. package/dist/plugins/tidb-session-store.js +28 -4
  328. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  329. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  330. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  331. package/dist/plugins/workflow-run-store-sql.js +50 -9
  332. package/dist/posture-source.d.ts +18 -10
  333. package/dist/posture-source.js +4 -1
  334. package/dist/project-identity.d.ts +45 -6
  335. package/dist/project-identity.js +162 -8
  336. package/dist/project-layer-key.d.ts +28 -0
  337. package/dist/project-layer-key.js +29 -0
  338. package/dist/question.js +3 -2
  339. package/dist/read-deny-entry.d.ts +25 -0
  340. package/dist/read-deny-entry.js +12 -0
  341. package/dist/read-face-posture.d.ts +37 -11
  342. package/dist/read-face-posture.js +32 -3
  343. package/dist/request-key-closure.d.ts +7 -0
  344. package/dist/request-key-closure.js +9 -1
  345. package/dist/request-value-closure.d.ts +5 -0
  346. package/dist/request-value-closure.js +11 -3
  347. package/dist/rule-entry-list.d.ts +26 -2
  348. package/dist/rule-entry-list.js +72 -12
  349. package/dist/rules-consent.js +3 -4
  350. package/dist/run-acceptance.d.ts +19 -3
  351. package/dist/run-acceptance.js +13 -1
  352. package/dist/run-local.js +36 -6
  353. package/dist/runs.d.ts +10 -9
  354. package/dist/runs.js +21 -3
  355. package/dist/runtime-caps-resolver.d.ts +16 -6
  356. package/dist/runtime-caps-resolver.js +18 -5
  357. package/dist/sandbox-pkg-source.d.ts +19 -1
  358. package/dist/sandbox-pkg-source.js +29 -7
  359. package/dist/security.d.ts +87 -9
  360. package/dist/security.js +52 -9
  361. package/dist/session-error-wire.d.ts +19 -2
  362. package/dist/session-error-wire.js +5 -1
  363. package/dist/session-titled-frame.d.ts +33 -0
  364. package/dist/session-titled-frame.js +4 -0
  365. package/dist/session-titler.d.ts +9 -1
  366. package/dist/session-titler.js +15 -4
  367. package/dist/spec-fields.js +21 -2
  368. package/dist/sql-engine-posture.d.ts +3 -1
  369. package/dist/task-cwd.d.ts +1 -1
  370. package/dist/task-mcp.d.ts +3 -3
  371. package/dist/task-mcp.js +7 -66
  372. package/dist/task-settings.d.ts +89 -88
  373. package/dist/task-settings.js +71 -63
  374. package/dist/text-bidi.d.ts +0 -4
  375. package/dist/text-bidi.js +1 -3
  376. package/dist/tighten-only-seats.d.ts +150 -0
  377. package/dist/tighten-only-seats.js +196 -0
  378. package/dist/tool-approval.d.ts +303 -87
  379. package/dist/tool-approval.js +623 -239
  380. package/dist/trace/core-keyset-guard.d.ts +104 -22
  381. package/dist/trace/exit-seat.d.ts +28 -0
  382. package/dist/trace/exit-seat.js +76 -0
  383. package/dist/trace/ledger-events.d.ts +3 -2
  384. package/dist/trace/project.d.ts +80 -12
  385. package/dist/trace/project.js +41 -28
  386. package/dist/trace/projection-table.d.ts +100 -0
  387. package/dist/trace/projection-table.js +130 -0
  388. package/dist/trace/redact.d.ts +54 -0
  389. package/dist/trace/redact.js +778 -152
  390. package/dist/trace/self-minted-wire.d.ts +345 -1
  391. package/dist/trace/self-minted-wire.js +117 -1
  392. package/dist/trace/wire-projection-faces.d.ts +298 -2
  393. package/dist/trace/wire-projection-faces.js +154 -13
  394. package/dist/url-refusal.js +2 -0
  395. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  396. package/dist/web-admin-client/apply-effective.js +56 -5
  397. package/dist/web-admin-client/facade.d.ts +1 -1
  398. package/dist/web-admin-client/facade.js +1 -1
  399. package/dist/web-admin-client/read-face.js +5 -9
  400. package/dist/web-admin-client/skills-mcp.js +4 -5
  401. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  402. package/package.json +7 -3
package/MIGRATION.md CHANGED
@@ -7,6 +7,272 @@
7
7
  > ⚠️ 完整清单在仓库根 `CHANGELOG.md`——它**不随 npm tarball 出包**(本文件随包)。看完整迁移窗的
8
8
  > 权威姿势是源码 tag diff:`git diff v<旧>..v<新>`(每版都推 `v<版本>` tag);npm 包页也镜像 CHANGELOG。
9
9
 
10
+ ## 7.133.0 —— `SANDBOX_PKG_SOURCE=custom` 的包源 / 镜像地址带 userinfo 起服拒启(安全) · 删包根导出 `judgeModelRouteGap`(BREAKING;壳 / 包改读 `GET /v1/models` 的 `modelPlane`) · 审批帧一条腿一个帧族(BREAKING,wire;消费方按 `approvalFrameFamilies` 分派) · 坏 JSON 体统一答 `400 request.invalid_json`、读体超限统一答 `413`(BREAKING,wire 码 / 状态码变更;此前多数口答 `request.rejected`,一批口把超限折成 `400 request.invalid_json`) · device 车道四根数值旋钮越界起服拒启、协议修订号抬到 2(结局码集随修订号) · acceptEdits 的免问写域改为引擎的写根(行为变更;沙箱车道上不再等同 `default`) · 审批列表面同族、`approvalId` = 行的键、已决卡再应答回放首决(BREAKING,wire 值变更) · 委派子代会话的属主随委派树写入、无主的委派子代行不对具名主体放行、SQL 后端存量子代行每次起服回填(安全) · 嵌入方 `ServiceKnobDeps.snapshotBlobSqlCap` 读口退役(BREAKING;零别名;要固定帽设 `SNAPSHOT_BLOB_SQL_MAX_BYTES`) · 子代转录读法 = 同一会话读面 + 终态帧 `transcriptId`、会话视图体顶层加性键 `agent`(消费方读法) · 没声明 `REMOTE_EXEC_HOME_DIR` 的 k8s / local-docker / ssh / adb 车道自己实测执行环境的家目录(行为变更;声明仍胜;起服 warn `execution_lane_home_undeclared` 只留给 device) · SQL 后端 workflow 续跑日志的属主 scope 搬进新表 `workflow_journal_owner`、`workflow_journal` 起服一次性按新主键重建(持久数据;🔴 先停旧副本再起新;收编回执腿名随表改) · workflow 子代的审批决定落盘:宿主会话的每一跑都带着它、同一决定重投回同一张回执(行为变更;SQL 后端起服多建一张表、整队一次切;SQL 后端配 `WORKFLOW_RUN_STORE=file|memory` 且开自编排起服拒) · 审批账本有了保留窗:结了且挂靠的东西都已终局的问安静超过 30 天就整问删掉(行为变更;要永久保留设 `APPROVAL_ASK_RETENTION_MS=0`,且要在升级后的第一次清扫之前) · 多租部署上请求 `settings.permissions.allow` 与按名点用的自带技能 `allowedTools` 按调用方信任档受理(安全,行为变更;低角色 / 不带角色的登录令牌带非空的 ⇒ `400`,能力位 `settings.permissions.callerTrust`) · 本地配置源 `config.d` 读之前判目录信任:别人改得动就拒启(安全;升级前自查权限;新旋钮 `CONFIG_LOCAL_OWNER_UID`) · 单用户记忆项目层换键形 `userrepo:<属主>/<档>.<摘要>`(带主体、跨设备;开记忆同步的部署项目层也同步;先升中心;存量项目层第一次在该项目跑任务时自动折进新键) · SQL 后端断路器键换成路由身份摘要、写新表 `breaker_state`,退役表 `circuit_breaker` 起服删掉(持久数据;无需动手) · `settings.hooks` 的 `source` / `plugin` / `args` 被读(不带且不引用插件变量零动作;托管组独立车道、跑不成即折 ask;exec 形不再被剥参数;引用不在场的插件变量的命令起不来) · 名单为空的单用户部署:审批队列不再把每个调用方当运维,要当自己的运维写一行 `OPERATOR_SINGLE_USER=true`(行为变更) · 隔离型车道(e2b / k8s / local-docker)的读面缺省 `READ_FACE` 缺席时从 `roots` 变 `open`(行为变更;把宿主目录或共享卷挂进沙箱的部署升级前写 `READ_FACE=roots`) · center 的 `allowBypassPermissions` / `allowAutoMode` 两键开始生效:组织关掉的模式由引擎折回 `default`(安全;行为变更) · 模式缺席的请求也问 `Workflow`(行为变更;要清掉这一问用 `settings.permissions.allow:["Workflow"]`) · 中心凭证换人:server 自己降到「无中心配置」档、当场拉取,`/health` 多一键 `centerIdentityNotice`(行为变更;没有 env 模型的部署在换人窗口里没有可派发模型) · 嵌入方:`StoreBackend.orgDeliveryQuota()` / `StoreBackend.checkpointReadView()` 必选(BREAKING,类型面;`orgDeliveryQuota()` 的返回型从包根导出,读口按 `StoreBackend` 成员型读) · SQL 后端收件箱里身份键过不了判官的存量行起服删掉(持久数据;无需动手)
11
+
12
+ 1. **`SANDBOX_PKG_SOURCE=custom` 的六只显式地址不得带 userinfo,带的起服拒**(安全):`SEMA_APT_MIRROR` / `SEMA_PIP_INDEX` / `SEMA_UV_INDEX` / `SEMA_UV_PY_MIRROR` /
13
+ `SEMA_NPM_REGISTRY` / `SEMA_NODE_MIRROR` 这六只地址原样写进沙箱(e2b VM / k8s pod)的环境,模型驱动的 Bash 里 `env` 读得到 —— `https://user:pass@mirror/…`
14
+ 把部署的包源凭据交给了模型。7.132.x 及以前起服无告警、凭据照交;现在起服失败,拒句点名那只 env 名,只回显 `scheme://host[:port]`(不含用户名与口令),并写出两条出路。
15
+ 无 scheme 的 `令牌:口令@host:端口` 这类不透明形、`file://` 与无 scheme 的 `host:port`、值里带反斜杠的形(`https://用户\:口令@host/…`:URL 标准把 `\` 读成 `/`,判官因此读不出 userinfo,pip 一类却读得出)
16
+ 也一并拒(这个座位只收层级式 http(s) 地址,且读法要唯一)。**只在 `SANDBOX_PKG_SOURCE=custom` 时判**
17
+ (`global` / `cn` / `none` 不注入这六只);请求面没有包源地址键。**升级前做**:
18
+ - 带凭据的地址:① 把地址改成不带凭据的形,凭据走包管理器自己的通道 —— 沙箱名单旋钮 `E2B_SANDBOX_ENV` / `K8S_SANDBOX_ENV` 点名一个令牌变量(点名即承担:沙箱里所有进程含模型都读得到),
19
+ 或把**按主机记凭据**的文件烤进镜像(npm 的 `.npmrc` 里 `//主机/:_authToken=…`、pip / uv / curl 的 `.netrc`;**别**把凭据写进 `pip.conf` 的 `index-url` ——
20
+ 注入的 `PIP_INDEX_URL` 环境变量比配置文件优先,会把它盖掉);② 源本身不需要认证就去掉 userinfo。
21
+ - `file://` / 无 scheme 地址:改成 `http(s)://host[:port]/…`。
22
+ `E2B_SANDBOX_ENV` / `K8S_SANDBOX_ENV` 点名放行的变量值不受这条影响(照旧原样交出,部署方显式承担);**例外**:名单点名的恰是这六只 `SEMA_*` 之一、
23
+ 且 profile 为 `custom` 时,读口照判环境里的值(带 userinfo 的 `SEMA_NPM_REGISTRY` 写进名单也一样起服拒)。
24
+ 2. **嵌入方(BREAKING;零别名):包根不再导出 `judgeModelRouteGap`,连同型 `ModelRouteGapReading` / `ModelRouteGapOptions`;`ModelRouteGap` 型收成缺口两词(`"endpoint_missing"` | `"lane_credential_missing"`,`"none"` 退役)。** 删即删,零别名、零过渡。
25
+ 它是 env 腿的纯判官 —— 只答「没有目录在管时,这份 env 交给引擎起不起得来」;起服的路由判官自 7.131.0 起判的是**将要服务的那张表**(目录被采纳时判目录表,env 的 `MODEL_ID` 不参与),所以它答的是起服已不再问的问题。
26
+ **谁受伤**:`import { judgeModelRouteGap } from "@sema-agent/server"` 的代码(tsc 红;已编译的 ESM 在模块加载期抛 `SyntaxError … does not provide an export named 'judgeModelRouteGap'`,命名空间导入则取到 `undefined`);对 `ModelRouteGap` 写了 `"none"` 臂的穷举 switch(该臂不再属于这个型)。
27
+ **出路二选一**:
28
+ ① 想知道**一台在跑的引擎**服务哪张模型表、目录采纳了没有、起服判官怎么说:读 `GET /v1/models` 的顶层 `modelPlane`(`servedTable` / `catalog` / 条件键 `refusalCode` + `gap`;键恒在场,见 USAGE 的模型目录段与契约 §A.1d)。
29
+ 这条是读面,**只在引擎起来之后可答** —— 起服之前没有「将要服务的表」可判,也就没有起服前的预判口(壳在引擎起来之前仍只能自己预测;引擎起来后以这一格为准,不再自判);
30
+ ② 自建装配(`loadConfig()` + 自己的配置源应用 + `createHttpServer`):在**自己的**目录应用之后调包根的 `judgeServedModelRoute(config, { envTableIsPlaceholder })`,返回 `{ code, gap, reason }` 或 `undefined`(通过)。
31
+ `GET /v1/models` 是加性改动(新键追加在应答最末),按顶层键集精确比对该体的消费方多读到一个键;零动作升级。
32
+ 3. **审批帧一条腿一个帧族(BREAKING,wire)**:`GET /v1/capabilities` 的 `streamApproval` 为真的 worker 上,工具审批只发呈卡族 ——
33
+ `approval_request`(开卡)/ `approval_complete`(单卡消卡,新帧)/ `approval_revoke`(批级撤卡);`tool_approval` / `tool_approval_complete` 不再发(bg / resume 腿账本里也没有)。
34
+ 为假的 worker 只发旧族(不变)。**消费方(壳 / SDK / 读账本的客户端)要做**:
35
+ - 按 `capabilities.approvalFrameFamilies`(闭集词数组,`("tool_approval" | "approval_request")[]`,至多一员)分派帧族,不嗅 server 版本:含 `approval_request` 时渲它,
36
+ 按 `approval_complete` 消单张卡(`outcome` / `cause` / `parked` 与旧族闭合帧同义同值)、按 `approval_revoke` 批撤;含 `tool_approval` 时走旧族;空数组 = 这台 worker 不呈审批卡。
37
+ `streamApproval` 词义不变(= 呈卡族可用),照旧可读;但 7.131.x / 7.132.0 上 `streamApproval:true` 的腿是两族并发、7.133.0 起是单族,同一个词的帧族含义随版本变,
38
+ 所以**不要再拿它反推帧族**。读不到 `approvalFrameFamilies` 键 = 7.132.x 及以前的 worker:保持旧读法(为真的腿两族并发,按 `approvalId` 去重);两族去重只在读得到该键的 worker 上才可以去掉。
39
+ - 此前只从 `tool_approval` 读的十位(`mandated` / `mandate` / `origin` / `boundGrantDigest` / `boundGrants` / `classifierNoRuling` / `boundGrantAbsence` / `approvalCard` /
40
+ `readRootCandidate` / `probeReason`)改读 `approval_request` 顶层,同名同值;只在活铸的帧上,断连重放帧上缺席(与旧帧一样)。`requiresRealApproval` 读 `card.risk.requiresRealApproval`。
41
+ - 应答口不变(`POST /v1/tool-approvals/:id/respond` 用呈卡帧的 `approvalId`;`POST /v1/tasks/:taskId/asks/:askId/decision` 用 `askId`)。
42
+ - 一时还不能消费呈卡族的接入方:该 worker 显式 `STREAM_APPROVAL_ENABLED=false`(呈卡协议整体不上场,`streamApproval` 读作假,`approvalFrameFamilies` 读作 `["tool_approval"]`,只发旧族)。
43
+ 运维:日志 `approver_unavailable` 的 `arm` 词 `unreached_no_row` 改名 `no_row_no_presenter`,按旧词过滤的告警改词。
44
+ 4. **请求体不是合法 JSON ⇒ 恒答 `400 request.invalid_json`(体带 `reason:"not_json"`);读体撞帽 ⇒ 恒答 `413 request.payload_too_large`(BREAKING,wire 码 / 状态码变更)。** 全仓只有一只请求体读取器,它此前抛的是无码的 `HttpError(400)`:
45
+ 没有自己 catch 的口(提交口 `POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`、steer / interrupt / compact 与各决定口、规则 / 记忆 / 能力探测 / 排空等管理口 …)的坏 JSON 体表面是
46
+ `request.rejected`(状态派生的粗码);另有一批口(leader 提交、设备、保留、领养、会话策略 `PUT`、同步 push / plan、workflow steer)在本地 catch 里自铸 `request.invalid_json`,并把读取器的
47
+ **413 一并折成这个 400**(一份 9 MiB 的合法 JSON 被报「JSON 非法」);`notify` / `wake` / 权限规则三口则在本地 catch 里把坏 JSON **和** 413 都说成 `400 request.body_shape`(句子 `body must be JSON: …` / `body must be valid JSON`)。现在读取器铸这个码(句子 `invalid JSON body` 不变),本地铸点全部删除,各口同一个体
48
+ `{ error, errorCode: "request.invalid_json", reason: "not_json" }`;超 8 MiB 在所有口答 `413`,体带 `field:"body"` / `reason:"too_large"` / `cap`(没有 `count`:体没读完,量不出送来多少)。
49
+ `POST /v1/runs/:id/compact` 收到合法 JSON 的非对象体,码不变、体多 `reason:"not_object"`。
50
+ **谁受伤**:① 按 `errorCode === "request.rejected"` 识别「坏 JSON」的客户端(这一形现在是 `request.invalid_json`;`request.rejected` 回到它的本义 —— 无自带码的 400),或在 `notify` / `wake` / 权限规则三口上按 `request.body_shape` 识别坏 JSON 的客户端(现在也是 `request.invalid_json`;`request.body_shape` 只剩「JSON 合法、形不对」);
51
+ ② 在 leader / 设备 / 保留 / 领养 / 会话策略 / 同步 / workflow steer / `notify` / `wake` / 权限规则这批口上把超限体当 `400` 处理的客户端(现在是 `413`)。
52
+ **出路**:坏 JSON 按 `errorCode === "request.invalid_json"`(想区分「不是 JSON」与「不是对象」读 `reason`)判;体超限按 `413` / `request.payload_too_large` + `field` / `reason` / `cap` 判。状态码对前一类不变(400),只有后一批口的超限状态码变了(400 → 413)。
53
+ 5. **`REMOTE_EXEC=device`:四根数值旋钮越界起服拒启;协议修订号抬到 2(结局码集随修订号)**:
54
+ - **升级前检查部署 env**:`DEVICE_RECONNECT_GRACE_MS` ∈ `[0, 2147483647]`、`DEVICE_DELIVERY_TIMEOUT_MS` ∈ `[0, 2147483647]`、`DEVICE_EXEC_TIMEOUT_MS` ∈ `[1, 2147483647]`、
55
+ `DEVICE_MAX_INFLIGHT_PER_DEVICE` ≥ 1,且都必须是规范十进制整数串(无符号 / 前导零 / 小数点 / 指数 / 十六进制 / 空白 / 单位;此前收任何有限数:分数 / 负数 / `0` 的在途上限 / `04` / `1e3` / `0x10` 都起得来,原样下发给 executor)。越界或奇形 ⇒ 起服拒启,
56
+ 拒句点名旋钮与合法域;去掉旋钮即回缺省(120000 / 10000 / 1800000 / 4)。未设与空串(compose `${X:-}` 透传)不变。
57
+ - **嵌入方**:`createDeviceWsHub` 的 `heartbeatIntervalMs`(≥ 1)/ `maxInflightPerDevice`(≥ 1)/ `reconnectGraceMs` / `cancelGraceMs` / `chunkGapTimeoutMs` / `execGraceMs`(都 `[0, 2147483647]`)
58
+ 越界时创建汇聚端即抛(此前原样用);config 的 `remoteExec`(device 臂)里的 `reconnectGraceMs` / `maxInflightPerDevice` 经装配进同一道检查。`deliveryTimeoutMs` / `execTimeoutMs` 的界只在 env 解析处判。
59
+ - **executor(cli / 第三方)**:`challenge.protocolVersion` 与 `GET /v1/capabilities` 的 `deviceExecutor.protocolVersion` 现为 `2`;hello 的 `protocolVersion` 取「自己实现的最高修订号与 challenge 的较小者」,
60
+ 只发该修订号的 `errorCode` 词(修订号 2 起含 `liveness_no_output`;`@sema-agent/server/device-protocol` 的 `deviceOutcomeErrorCodesAt(revision)` 给集合,表见随包 `docs/DEVICE-EXECUTOR-PROTOCOL.md` §2.1);
61
+ 受理窗 `[1, 2]`,不升级的老 executor 照连。helloAck 的数值位恒在界(协议文档 §1.5):读到越界值 ⇒ 当协议违例关连接,不读成缺省。
62
+ 6. **acceptEdits 的免问写域改为引擎的写根;沙箱车道上 acceptEdits 不再等同 `default`**(行为变更):本服务自己给 acceptEdits 装的那只写门(免问域只认会话工作目录)删除,
63
+ acceptEdits 能免问写哪里只由引擎答 —— 写根(任务根 + 请求的 `additionalDirectories`)内的写免问,写根外照问。变化落在三处:host 车道写 `additionalDirectories` 不再出卡;
64
+ host 车道没登记工作目录时任务根内的写不再出卡;沙箱车道(e2b / k8s / ssh / adb / local-docker)上任务根内的写不再出卡(此前与 `default` 一样每次都问)。
65
+ **要保留「每次写都问」的部署做**:设 `APPROVAL_REQUIRE=Write,Edit,NotebookEdit`(人写的 ask 规则,任何模式都放不掉、会话放行照样可用;名单门要耐久审批在场 —— `DURABLE_APPROVAL=true` + 有检查点面的后端),或让请求方改发 `permissionMode: "default"`。
66
+ 写根外的写照问(不变);请求与部署的 `deny` / `ask` 规则、`SENSITIVE_WRITE_PATTERNS` 守卫集不受影响。
67
+ 7. **审批的列表面与身份同律(BREAKING,wire 值变更;`streamApproval` 为真的 worker)**:
68
+ - `GET /v1/approvals` 的 `livePending[].frame` 与 `/v1/approvals/stream` 的 `live_pending` 帧里的 `frame` 改成 `approval_request` 帧(卡内事实在 `card`,卡外事实在帧顶层);
69
+ **从这一格读旧族键(`frame.args` / `frame.message` / `frame.ruleOffers` / `frame.inputHasBidi` ……)的消费方改读 `frame.card.*`**,按 `frame.type` 判别(旧族 worker 上照旧是 `tool_approval`)。
70
+ - `approvalId` = ask 行的键 `askId`(64 位十六进制串,不再是 uuid;本就不透明,把它当 uuid 解析的代码要改)。同一只 ask 列表一行。
71
+ - 对一只已决的卡再应答(重试 / 别处已决 / 本副本的残留登记 CAS 输)从 `404 tool_approval.not_pending` 改为 **`200 idempotent:true` 回放首决**(按回体的 `decision` 渲);
72
+ 停驻卡在别的副本 / 重启之后按 Yes 照样受理。把「再应答 = 404」当作「卡已消失」信号的消费方改读回体。
73
+ 运维:计数 `server.approval.park-tombstone-global-cap-refused` 改名 `server.approval.park-redemption-cap-refused`(按旧名的看板改名)。
74
+ 8. **委派子代的会话只对发起它的主体可读:无主的委派子代行不对具名主体放行,SQL 后端每次起服回填存量子代行的属主(安全)**:7.132.x 及以前,`DB_BACKEND=mysql` / `pg`
75
+ 为委派子代建的会话行没有属主,而会话面对无主行放行 —— 拿到子代会话 id(子代帧上的 `transcriptId`)的任何主体都读得到整段子代转录。本版起写下那一行的那一笔写入
76
+ **铸行那一刻委派树根会话的属主**(判断时读到的;判断之后根会话被删、同 id 重新登记不改变写进去的值);**属主为空的委派子代行只对 fleet 调用方放行**
77
+ (出示 service 凭据、不带主体头的调用方;dev-open 照旧),任何具名主体、没有 service 凭据的无身份调用方答 `404 not_found.session`(与不存在同体)——
78
+ fork / 删除对 `default` 主的存量无主会话互认、审批豁免的列表 / 撤销、外部 notify 对这些行同样不放行;**存量行每次起服回填**(窗内):
79
+ - 根会话的行在 ⇒ 写它的属主(根会话无主 ⇒ 子代仍无主,不写);根行已不在 ⇒ 写**它记录的**父会话的;两者都已不在 ⇒ 写一只任何调用方都不可能匹配的 `_orphan:<会话 id>`(它下面的子代继承同一只);
80
+ - 起服读数行多三键 `placedSessionOwnersInherited` / `placedSessionOwnersOrphaned` / `placedSessionOwnersRemaining`;孤行非零另打一行 warn `placed_session_owners_orphaned`(点名条数,两种成因分开说)。
81
+ 每次起服**扫一趟**、按原文条件写,写成的第二次起服不再命中;`placedSessionOwnersRemaining` = 这一趟判不出的行(它读到的父会话本身还是一只待回填的子代行),读数行因此是 warn,
82
+ **不拒启**:它们只对 fleet 调用方放行,之后的起服(或它们下一次停驻)按同一条律补上 —— 一次起服至少再定下一层,层层待回填的链要多起几次,读数逐次变小。
83
+ 滚动升级里旧副本在窗内新建的无主子代行同样由之后的起服补上。
84
+ 扫到会话住客记号为空的子代行 ⇒ 起服拒(与全仓「读到空住客记号」同一条律)。窗 = 本版发布日 + 30 天,之后的 minor 删回填码 —— **至少起一次本版**再越过它升级。
85
+ **升级前做**:`DB_BACKEND=local` 且带身份(中心鉴权桥 / 主体头)的部署,先把停驻待批的子代审批处理完 —— 升级前停驻的子代在宿主店里的那一行无主,升级后被批准、
86
+ 复活后再次需要审批时属主对不上,停驻被否决、那一只子代以失败收尾。**升级后看**:`placed_session_owners_orphaned` 那一行 —— 被写成 `_orphan:` 的子代转录只有 fleet-wide / operator 面读得到;要让某位主体读,
87
+ 在会话店里把那一行的 `owner` 改成该主体(`session_meta.owner`);`placedSessionOwnersRemaining` 非零 ⇒ 再起,直到它为 0(或等那些子代下一次停驻)。**拿另一位主体的身份读子代转录的集成**:读面现在答 `404 not_found.session`
88
+ (与不存在同体),改用发起子代的主体读;根会话本就无主的子代转录(无身份调用方的委派树)只有 fleet 调用方读得到 —— 没配 service 凭据、又不是 dev-open 的部署上,
89
+ 给它配 service 凭据(或身份来源)再读。
90
+ `_orphan:` 进保留主体前缀:身份来源报出以它开头的主体 ⇒ `400 principal_reserved`(哪位租户的主体名恰以 `_orphan:` 开头,升级后它的请求被拒,先给它换名)。
91
+ `DB_BACKEND=local`:不涉及回填(子代住私店);停驻时拷进宿主店的子代行本版起带委派树根会话的属主(这一处只按根判:拷进去那一刻根会话已不在 ⇒ `_orphan:`),升级前拷进去的那些仍无主
92
+ (local 后端不记委派树,不补;它们再次停驻时按上面「升级前做」那一形被否决)。local 后端的子代转录行是普通的有主会话行
93
+ (属主的会话列表里列得出、能 `PATCH`、能经 `/sync` 整段换装);「不进列表 / `PATCH` 404 / 换装被拒」只对 SQL 后端的子代行成立。
94
+ 9. **嵌入方(自建 `ServiceDeps` 的进程):`snapshotBlobSqlCap` 读口退役(BREAKING;零别名)**:包根导出型 `ServiceKnobDeps` 少一个座 —— 7.132.0 的 `snapshotBlobSqlCap`(`() => { capBytes, source } | undefined`,7.131.x 数字键 `snapshotBlobSqlCapBytes` 的换形,见 7.132.0 节第 59 条)
95
+ 删了。原因:SQL 快照 blob 的帽依赖语句上限 `max_allowed_packet`,它是**连接的会话值**,只有将要执行写入的那条连接自己说得准;HTTP 面手里没有那条连接,它的前置判读的是池级读数,
96
+ 与店的判决会在库调墙后的过渡窗口里分歧。现在 `PUT /v1/sessions/:id/sync/blobs/:hash` 的 `413 blob_too_large_for_sql` 来自店在写入连接上的判决(码、状态与体上的 `wallSource` 不变,句子仍是 7.132.0 的三形)。
97
+ **谁受伤**:① 传了 `snapshotBlobSqlCap` 的 TypeScript 嵌入方(tsc 红);② JS 嵌入方 / 类型之外的装配照传 ⇒ **起服拒**(`createHttpServer` 装配期;起服拒句点名键、退役版本与出路,退役的座不静默忽略;7.132.0 退的 `snapshotBlobSqlCapBytes` / `sqlEngineFacts` 两个旧键同一张表同一只判官,放在 `knobs` 组里的同样拒;值是 `undefined` 不算传);
98
+ ③ 自建 `fileHistoryStore`(不是本仓的 `TiDBFileHistoryStore` / `PgFileHistoryStore`)又靠这个读口拿 413 的:读口没了 ⇒ 超帽的 blob 回到店的既有失败面(`putBlob` 的 `ok:false` ⇒ 502,对端会重试)。
99
+ **出路**:要固定帽 ⇒ 设 `SNAPSHOT_BLOB_SQL_MAX_BYTES`(店的显式旋钮,两方言都生效;机读位 `wallSource: "operator"`);自建店 ⇒ 让 `putBlob` 超帽时交回
100
+ `{ ok: false, error: { code: "blob_too_large_for_sql", message, wallSource } }`(`wallSource` ∈ `"operator"` | `"reported"` | `"assumed"`),路由据此答 413 并原样转出 `message` 与 `wallSource`;
101
+ `message` 可以直接用包根导出的 `BlobTooLargeError` 的句子。`sqlEngine`(引擎读口)座不变 —— 提交受理口的墙仍读它(SQL 后端在场 ⇒ 必填,7.132.0 节第 61 条的要求不变)。
102
+ 10. **子代转录的读法(消费方;加性,无需升级动作)**:终端侧链投影方按 fleet 帧(`bg_notification` 终态帧,或 `task` 行)上的 `transcriptId` 读子代整段 —— **只有一只读口,同一会话读面**,没有 `/v1/subagents/…` 一类的端点:
103
+ - **读**:用**发起委派的那位主体**调 `GET /v1/sessions/<transcriptId>`(视图;未压缩过的子代 `messages[0]` 的用户消息带委派 prompt,压缩过的子代视图是压缩后的当前窗;子代跑过的工具是 assistant 消息里的
104
+ `toolCall` 段 + 同 `toolCallId` 的 `toolResult` 行)与 `GET /v1/sessions/<transcriptId>/sync/entries`(整段存档逐条,含停驻那一拍的占位 `toolResult` 与复活后的真结果);视图口上别的主体读到
105
+ `404 not_found.session`,与不存在的 id 同体(`/sync/*` 对带 service 凭据的调用方另说,见最后一条)。
106
+ - **子代是哪只**:视图体顶层新 additive 键 `agent: { id?, parentSessionId?, rootSessionId? }` —— `id` 与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 同一个串。**键缺席**有三种成因,一律按「这台 server 没有存」读,
107
+ 回落 fleet 行 / `GET /v1/agents/roster` 的 `handle`:老 server(≤ 7.132.x,没有此键)· 普通会话 · local 后端(不存委派元组)。不要把缺席读成「不是子代」。
108
+ - **范围**:SQL 后端上只有**后台**委派子代有会话元组(会话是宿主店里的 placed 行);同步委派的子代转录不落宿主店,没有元组。
109
+ - **local 后端的两处差别(如实)**:不停驻直接收尾的子代,转录一直住私有短 TTL 店,视图与 `/sync/entries` 都读不到(404,发起它的主体也一样)—— 要读它的整段,等 local 声明 placements 或改用 SQL 后端;
110
+ 撞审批门停驻的子代,拷进宿主店之后读得到(视图 200、无 `agent` 键);拷贝落下之前(待批卡先于拷贝可见的那一小段)属主读也是 404,稍后重读即 200。
111
+ - **带 service 凭据的调用方**:视图口按它的主体头判(没带主体头 ⇒ 404);`/sync/*` 把带凭据的调用方读成 fleet-wide,任何主体头都读得到 —— 与会话视图是两只判据,现状如此,不在本条。
112
+ sdk 的会话视图类型目前没有 `agent` 字段(待 sdk 同步补可选键);自己按白名单解析会话视图体的消费方放行这一个键。
113
+ 11. **没声明 `REMOTE_EXEC_HOME_DIR` 的 k8s / local-docker / ssh / adb 车道:执行环境开起来那一拍自己读一次 `$HOME`、填引擎的家目录座(行为变更;k8s 部署升级前核一遍声明)**:此前这四条车道不声明家目录就恒不知道它,
114
+ 引擎的家锚拒读行放不下,每一次泄内容的递归读(`grep -r` / `rg` / `git grep` / `tar c`)在全 shell 面恒问人、只读面直接拒。现在取值律是:**声明在场 ⇒ 声明(原样);否则 ⇒ 车道建环境时实测的 `$HOME`(绝对路径才收);实测也缺席 ⇒ 座缺席(与此前一致)**。
115
+ 声明在场时:local-docker / ssh 的行为一个字没变(本来就把声明与 `$HOME` 对证);**k8s 现在也对证**(同一只判官、同一句拒;**行为变更**:此前照单全收)—— `REMOTE_EXEC_HOME_DIR` 与 pod 里的 `$HOME` 不一致(去掉尾斜杠后逐字比)、或 `$HOME` 读不出绝对路径时,那只 pod 不开(`connect_failed`,拒句点名两个值与改法),
116
+ adb 仍照单全收。**升级前对 k8s 部署核一遍**:在镜像里跑 `printf %s "$HOME"`,与声明值比;对不上的按拒句改声明(或让镜像以声明的用户运行)。**谁受影响**:① 此前为了消掉起服 warn 而手填了 `REMOTE_EXEC_HOME_DIR` 的部署 —— 不必改,声明仍胜;想让车道自己测就删掉它,**但**用了 `~/` 形权限规则的部署必须保留声明:
117
+ `~/` 形规则的下单门与规则基仍只认声明(提交任务那一刻执行环境还没开),没声明 ⇒ 照旧 `422`;② 按起服行 `execution_lane_home_undeclared` 配了告警的运维 —— 这一行现在只在 device 车道起服时响;k8s / local-docker / ssh / adb 没声明时起服不再响,
118
+ 改成**某只环境实测缺席时**响同一只事件码(字段仍是 `provider` + `note`,note 点名读到了什么;同一部署同一句只响一次),把告警条件从「起服出现」改成「运行期出现」;③ 没声明的部署上引擎对这四条车道的家锚拒读行落位变了
119
+ (由「没有家目录时在任何位置按路径段判」落到实测的家目录下,并另锚引擎宿主的账户家、每条 run 的落位多一次经该车道 `canonicalPath` 的账户家探针,上限 2 s —— 引擎对「声明了家」的远端车道的既有口径,见部署前置文档(仓库 docs 目录下 DEPLOY-PREREQS)该节;本版未在真集群上实测)。
120
+ **做法**:k8s 部署核声明与镜像用户的 `$HOME`(上一段);其余无需动手;想看到实测值是否生效,看运行期是否出现 `execution_lane_home_undeclared`(出现 = 那只环境的 `$HOME` 读不出绝对路径:修环境的 `HOME`,adb 上也可以声明;k8s / local-docker / ssh 上声明替代不了一个读不出的 `$HOME`,会被拒)。
121
+ 12. **SQL 后端(`DB_BACKEND=mysql` / `pg`):workflow 续跑日志(journal)的属主 scope 搬进新表 `workflow_journal_owner`,`workflow_journal` 起服一次性按新主键重建(持久数据;🔴 先停旧副本再起新)**:
122
+ 7.132.x 及以前 scope 是 journal **每一行**上的一列,读面按它判、写面不判(别的 scope 能往一条 run 里写)。本版起一条 run 的属主 scope 只记在 `workflow_journal_owner` 一行(主键 `run_id`,
123
+ 这条 run 的第一次 append 认领,带认领时铸的令牌 `incarnation`);journal 行改带写下它的那只记录的令牌,主键 `(run_id, incarnation, ordinal)`,店的写面与读面都经属主记录判;
124
+ 别的 scope 的 append 被拒(`workflow journal: runId <id> already recorded under a different scope — refusing the append; nothing was written`),什么都不写。
125
+ - **自动(起服,一次性)**:`workflow_journal` 上 scope 列在场 ⇒ ① 每条 run 回填一行属主(scope = 该 run 最小序数那一行的;属主行的回收时钟 = 该 run 最晚一行的时刻)② 照新形建暂存表
126
+ `workflow_journal_m24`,按主键分批(每批的结果字节有界、各自提交)搬与属主同 scope 的行(带属主令牌)③ 原子换名(旧表改名 `workflow_journal_m24_old` 后删掉)—— scope ≠ 属主的行(旧写面放进别人 run 里的写)不搬,
127
+ 写它们的 scope 续跑时那几步改为活跑。起服读数行 `one_time_migrations_applied` 多三键:`workflowJournalScopeColumn: "moved"`(第二次起是 `current`)/
128
+ `workflowJournalOwnersBackfilled` / `workflowJournalForeignScopeRowsRemoved`;丢了行另有一行 warn `workflow_journal_foreign_scope_rows_removed`(条数)。换名之前任何一步被打断,旧表原样、
129
+ 下一次起服从头重来(残留的暂存表删掉重建,属主只补缺的);库里看到 `workflow_journal_m24` / `workflow_journal_m24_old` 而服务没在起动 = 上一次迁移被打断,起一次服就收掉。
130
+ - **升级顺序**:**先停 7.132.x 副本,再起本版** —— 换名之后,仍在跑的旧副本的 journal 读写点名不存在的列而失败(那一刻在跑的 workflow 那一步失败;旧二进制起服被列集对账拒启);
131
+ 复制与换名之间旧副本写进旧表的行随旧表删掉(那几步续跑时活跑)。
132
+ - **直接查这张表的运维 SQL**:`SELECT … FROM workflow_journal WHERE run_id = ? AND scope = ?` 改成 `SELECT … FROM workflow_journal JOIN workflow_journal_owner USING (run_id, incarnation) WHERE run_id = ? AND scope = ?`;
133
+ 按 scope 列 run 的改查 `workflow_journal_owner`(一行一条 run)。
134
+ - **收编(form b)回执**:`legs[].store` 的 `workflow_journal#scope` 换成 `workflow_journal_owner#scope`(腿标识 = 表名#列名);按旧名对账的消费方改读新名,改绑语义不变(与 run 行同事务)。
135
+ - **窗**:本版发布日 + 30 天,之后的 minor 删迁移码 —— **至少起一次本版**再越过它升级;跳过本版直接升的库(`workflow_journal` 上仍有 scope 列、没有 `incarnation` 列)被起服列集对账拒启(`config.schema_mismatch`,点名两列)。
136
+ - `DB_BACKEND=local`:不涉及(journal 是引擎的文件店,一条 run 的属主就是它的 journal 文件首行,一直只记在一处、一直拒别的 scope 的写)。
137
+
138
+ 13. **workflow 子代的审批决定落盘(行为变更;SQL 后端起服多建一张表;SQL 后端配 `WORKFLOW_RUN_STORE=file|memory` 且开自编排起服拒)**:决一张 workflow 子代卡,投递那一跑开跑之前决定写进部署的店,宿主会话之后的每一跑都带着它,直到引擎用掉它或卡到期。
139
+ - 🔴 **要动手的一种部署**:`DB_BACKEND=mysql` / `pg` + `SELF_ORCHESTRATION_ENABLED` + `WORKFLOW_RUN_STORE=file` 或 `memory` ⇒ 本版**起服拒**,读完配置即拒、在一次性迁移之前(那一次起服不动库,
140
+ 改完配置直接再起):决定行写在会话认领的同一个原子步骤里,认领在库里,决定行就得在同一个库里,而库里的决定行随库里的 workflow 记录收割 —— workflow 记录不在库里时没有一只店两头都满足。
141
+ 出路二选一:去掉 `WORKFLOW_RUN_STORE`(缺省 `auto` = 有 SQL 用 SQL,workflow 记录进同一只库),或关掉自编排(`SELF_ORCHESTRATION_ENABLED=false`)。这一形本来只在单机上通(park 指针按箱存,多副本上 `/decide` 路由不到)。
142
+ 嵌入方:`runStore` 与 `workflowParkDecisions` 从同一只 store backend 取(`run()` / `workflowParkDecisions()`,两只都无参、恒交同一只);决定店绑的不是 `runStore` 这一只、漏了这一座、
143
+ 或没装 workflow park 车道却给了决定店 ⇒ 起服拒。local 后端的账本由后端自己放:`<数据根>/workflows/workflow-park-decisions/decisions.jsonl`;`WORKFLOW_RUN_STORE=memory` ⇒ 纯内存,重启即失。
144
+ - **建表**:`DB_BACKEND=mysql` / `pg` 起服时由中央建表语句建 `workflow_park_decision`(加法 DDL,不改写任何存量行);local 车道是数据根下 `workflows/workflow-park-decisions/decisions.jsonl`。无需动手。
145
+ - **消费方**:同一决定重投,在投递的那一跑结束之前回同一张回执(不再起一跑),结束之后再投递一次;另一个决定在宿主会话有一跑在跑时答既有的 `409 conflict.session_active_run`,
146
+ 没有时受理并取代前一个。投递被拒(会话忙 / 配额 / 会话的续跑输入已被回收)时拒体与此前相同,什么都没有记下。决定没落成(部署的店写不进,或投递那一跑在落盘那一拍已不占着宿主会话 ——
147
+ 它的心跳停满 `REAP_RUN_STALE_SEC` 被收走)⇒ `500`,那一跑不开,重投即可;续上宿主停驻(wake)那一形里引擎已认领掉那张停驻,重投改在宿主会话上新起一跑 ——
148
+ 宿主会话空闲超过 `REAP_RUN_STALE_SEC` 时那一形答既有的 `409 conflict.resume_context_unavailable`(去续跑那条 workflow run)。
149
+ 取消落在落盘进行中、落盘随后成功:wake 那一形答那一跑的取消终局;新起一跑那一形答照常的 200 受理回执,那一跑开跑后最多 30 秒被叫停。没有新的错误码。
150
+ - **运维**:fail-open 计数 `server.workflow-park-index.sync-failed` 退役(按它配的告警可删);park 指针写失败现在表现为那次 workflow run 记录写失败(引擎的 run 日志一行),不再是「记录照写、指针缺」。
151
+ 新计数 `server.workflow-park-decision.card-unreadable`:某一跑开跑时读不出一条已受理决定的那张卡 ⇒ 这一跑不带它(下一跑照带)。
152
+ 新计数 `server.workflow-park-decision.store-unreadable`:开跑时决定店读不出(local 账本中间有一行读不出 / SQL 这个会话某一行决定体坏)⇒ 这一跑不带这个会话已受理的决定,照常起跑。
153
+ local 车道决定账本中间有一行读不出 ⇒ 决 workflow 子代卡被拒(`workflow_park_decisions_corrupt_read`),直到有人处理那只文件;起跑不受牵连(不带账本里的决定)。移开它再重启是安全的(其中已受理的决定对应的卡仍待批,可再决)。
154
+ - **SQL 多副本整队一次切**:混跑窗里 7.132.x 副本不读决定行(在它上面起的宿主跑不带已受理的决定,与升级前同),也不写(在它上面受理的决定只活在那一跑里)。先停光 7.132.x 再起本版即无此窗。
155
+ - **回滚到 7.132.x**:表留着无害(旧版不读它);回滚后已受理、未用掉的决定不再随宿主跑走 —— 回到升级前的行为(卡仍待批,重新决即可)。
156
+ 14. **审批账本有了保留窗:结了的问安静超过 `APPROVAL_ASK_RETENTION_MS`(缺省 30 天)就从三本账里整问删掉(行为变更)**:此前 SQL 车道的 `approval_ask` / `approval_batch` 两张表、
157
+ local 车道的问账 `approval-asks/asks.jsonl` 与审计账 `approval-ask-audit/ledger.jsonl` 都只增不删。现在维护 tick 首拍即清扫一次、之后每小时至多一次:终态且不是 provisional 的问行、
158
+ 问走光了的批行、以及审计账里不再欠起服收敛答案的问,最后一次动静早于 `now − APPROVAL_ASK_RETENTION_MS` 的整问删掉;没结的问(`STREAM_PENDING` / `PARKING`、活卡、批了但腿还没闭)多老都不删,
159
+ 发起它的 run、宿主会话或发问那条腿的会话还挂着在跑 / 停驻的 run、后台子代或待决 checkpoint 的问也不删(每次清扫先从 run 账、后台子代账与 checkpoint 店列出这些东西);
160
+ 审计账留下的行逐字节不变。起服日志一行 `approval_ask_retention`(生效窗或关),真删了东西时一行 `approval_ask_retention_swept`(带各账删掉的数)。**谁受影响**:① 把审批账本当永久取证记录的部署;
161
+ ② run 结束超过窗之后才对它的卡作答的客户端:决断口与流内审批口答 404(此前回放首决 / 答 409、410);③ local 部署删过问行之后再降级到
162
+ 不认问账动词 `reapSettledAsks` / `reapEmptyBatches` 的旧版本,local 问账起服拒启(拒句点名出路)。**做法**:要永久保留 ⇒ 升级时同时设 `APPROVAL_ASK_RETENTION_MS=0`(首拍即扫,事后再设已经删掉的回不来);
163
+ 要别的窗 ⇒ 设毫秒数(正值低于 1 天钳到 1 天并在启动告警里点名;负值 / 非整数拒启);其余部署零动作。
164
+ 15. **多租部署(`REQUIRE_PRINCIPAL=true`):请求体 `settings.permissions.allow` 按调用方的信任档受理(安全;行为变更)**:档只由这次请求验过的凭据推 —— 部署的 service 凭据 ⇒ `global`;
165
+ 中心登录令牌在活动 scope 里的角色 ≥ 治理写角色(settings-schema `domainWriteRole("governance")`,今天 `editor`)⇒ `global`;角色更低 / 令牌不带角色 / 直连门 principal 令牌 / 没有验过的凭据 ⇒ `project`。
166
+ `allow` 要 `global`(settings-schema 成员阶梯),所以 `project` 档的调用方带非空 `allow`、或用 `userInvokedSkills` 按名点用带 `allowedTools` 的自带技能(不出 `Skill` 卡,同一成员的孪生)⇒ `400 request.field_invalid`(`detail.problems[].reason: "below_trust_floor"`、`detail.callerTrust`);`deny` / `ask` 照收。
167
+ 单用户 turnkey 与持 service 凭据的前端零变化。**谁要动手**:让 scope 里 `viewer`(或拿不带角色的令牌)直连提交、又靠请求体 `allow` 免问的部署 —— 三选一:scope 管理员把这些成员抬到 `editor` 或以上;
168
+ 把规则放进运维的 `APPROVAL_GRANT`(部署级);或让这些调用方去掉 `allow`、开跑时答卡(点用的技能从 `userInvokedSkills` 拿掉,模型仍可在 `Skill` 卡后激活它)。**壳 / 客户端**:提交前读 `GET /v1/capabilities` 的 `settings.permissions.callerTrust`(按调用方;缺席 = 老 server,
169
+ 不按档受理),把契约 floor 高于它的成员留在本地同意出口、不上 wire;收到上面这只 400 时按 `detail.problems` 逐条提示,不解析句子。升级前已受理、仍在停驻的任务照旧续跑。
170
+
171
+ 16. **本地配置源(HTTP 服务设了 `CONFIG_PROVIDER=local`;`run-local` 与壳起的本机引擎恒是):`config.d` 读之前判目录信任,别人改得动就拒启(安全;升级前自查一遍)**:
172
+ 从 `/` 走到 `config.d`、再到读者会读的每一份文档(链接照跟),路径上每一级的属主只能是本服务的用户、root 或 `CONFIG_LOCAL_OWNER_UID` 声明的那一个 uid,且不得组 / 他人可写
173
+ (属主可信的粘滞目录如 `/tmp` 除外 —— 但要读的一项缺在这样的开放目录里同样拒,别人能先建出来);文档必须是常规文件且 ≤ 16 MiB;链接合计 ≤ 40 跳、不得指向 procfs 一类内核对象。
174
+ 7.132.x 及以前不判。配置根直接放在 `/tmp` 下的,先把根与 `config.d` 建好(属于服务用户),否则起服拒。升级前在服务用户下跑一遍(`<根>` = `CONFIG_LOCAL_DIR`,没设则 `AGENT_DATA_DIR`,再没设则 `~/.ai-agent`):
175
+ ```sh
176
+ find "<根>/config.d" \( -perm -g+w -o -perm -o+w \) ! -type l -print # 有输出 ⇒ 对每一行 chmod go-w
177
+ find "<根>/config.d" ! -user "$(id -u)" ! -user 0 -print # 有输出 ⇒ chown,或设 CONFIG_LOCAL_OWNER_UID=<那个 uid>
178
+ d="<根>/config.d"; while [ "$d" != / ]; do ls -ld "$d"; d=$(dirname "$d"); done # 每一级:属主是你或 root,且无 g/o 写位(粘滞目录 t 除外)
179
+ ```
180
+ Debian / Ubuntu 的用户私有组 + umask 002 会建出 0775 目录 —— 本版起即拒启,`chmod go-w` 即可。userns-remap 容器 bind-mount 的配置在容器里常呈现为 uid 65534:设 `CONFIG_LOCAL_OWNER_UID=65534`
181
+ 或在镜像 / initContainer 里改属主;rootless 容器里宿主用户映射为容器 root,零动作;k8s ConfigMap 卷挂成 `config.d`(或挂在它上面一级)零动作 ——
182
+ kubelet 把卷根建成 0777,判官认这一形:卷根下只有 kubelet 的链接农场(`..data` / `..<时间戳>/` / `<键> -> ..data/<键>`)、属主 root、它是一只只读挂载的 kubelet ConfigMap 卷
183
+ (本进程 `/proc/self/mountinfo` 里那只挂载带 `ro`、来源是 kubelet 的 configMap 卷目录),且来源没有经可写挂载露在本服务的挂载命名空间里(露出来 ⇒ 拒,拒句点名那条路径与那只挂载;
184
+ hostPath 挂了节点目录的 pod 即此形 —— 撤掉拒句点名的那只可写挂载:别把节点根 / kubelet 数据目录或它的任何祖先可写挂进 pod,配置用 `subPath` 或不挂那个祖先;别去放宽节点上 kubelet 目录的权限;
185
+ 只读挂载盖住的露出不算,但祖先的只读挂载不递归 —— 它下面单独挂进来的可写文件系统照样露出、照样拒);认它时每个进程一行 fail-open 告警(`server.config-dir-trust.kubelet-volume-node-side-unverifiable`:来源在节点那一侧的目录本服务看不见),不是错误。这条认臂取决于容器里 `/proc/self/mountinfo` 那一行的形,**未在真集群实测**;读到的形与上面所述不符 ⇒ 该部署照旧起服拒(失效关闭,不会静默放行)。
186
+ `defaultMode` 别给组 / 他人写位(那会让 `..<时间戳>/` 里的文档可写 ⇒ 拒)。
187
+ **Secret / projected / downwardAPI 卷**(内存介质,mountinfo 里认不出来源)、把卷挂成可写、往卷根里另放文件、或把一只普通目录只读 bind 进来的形都不认,照拒 —— 改用 `subPath` 逐文件挂或烤进镜像;
188
+ 挂了 `fsGroup` 的 emptyDir 是组可写的 ⇒ 拒,改用 ConfigMap 或在 initContainer 里 `chmod go-w`。
189
+ 拒的样子:起服 fatal 标题带 `[config.dir_untrusted]`(`run-local` 退 2),句子点名那一个路径、实测值与改法;起服之后才变坏的 ⇒ 每一拍 `web_admin_refresh_failed` 带同一句,已应用的配置不动。
190
+ Windows 上属主与模式位不可判:只判结构,另有一次 fail-open 告警(`server.config-dir-trust.win32-owner-mode-unverifiable`),零动作。中心配置源(舰队形)不读 `config.d`,零动作。回滚:零动作(旧版不判)。
191
+ 17. **单用户记忆的项目层换键形,开了记忆同步的部署项目层也同步了(键值变、形不变;先升中心)**:项目层键从 `repo:<24 hex>`(本机项目根路径的哈希,不带主体)换成
192
+ `userrepo:<属主段>/<档>.<24 hex>` —— 属主 = 全局层(`MEMORY_SCOPE`,run-local 是 `--user`,缺省 `local`)的属主(`user:<P>` 取 P,其余取名字本身);档 `r` = 仓库 `origin` 远端
193
+ URL 归一后的哈希(同一仓在不同机器、不同写法克隆都是同一把键),`p` = 没有 origin(或 origin 是本地路径)时的项目根路径哈希(只在本机稳定)。**升级做法**:
194
+ - **先升中心再升客户端**:旧中心对 `userrepo:` 键答 404,新客户端会在每轮同步对那一层打一行 warn `memory_sync_layer_failed`(同步层本身照常);
195
+ - **只在本机用记忆、不开同步**:无需动手。存量 `repo:` 层的条目在**该项目第一次跑任务时**自动折进新键(日志 info `memory_project_layer_folded`);**窗约 30 天**,窗关之后的版本不再折 ——
196
+ 窗内一次都没打开过的项目,旧层留在库里但不再进任何读列表。想全部带过来:窗内在每个项目里跑一次任务;
197
+ - **开了记忆同步**:同步层与全局层同属主(例 `MEMORY_SCOPE=user:alice` 不设 `MEMORY_SYNC_SCOPE`,或两者都写 `user:alice`)⇒ 项目层不再让位,随同步推拉;启动通知 `memory_project_scope_yields_to_sync`
198
+ 不再出现。缺省 `MEMORY_SCOPE=local` + `MEMORY_SYNC_SCOPE=user:<你>` 的部署仍让位、仍什么都不同步(与此前同),通知改成一句并点名出路:把 `MEMORY_SCOPE` 设成同步层那把 user 键
199
+ (代价如实:换全局层名字之后,原 `local` 全局层与它名下的项目层不在读列表里 —— 与此前改 `MEMORY_SCOPE` 同一种代价,盘上数据不删)。同步腿的旧游标文件 `sync-cursor-<peer>.json`
200
+ 第一轮自动收编(info `memory_sync_cursor_adopted`),此后每层一只 `sync-cursors/<peer>/<scope 摘要>.json`;
201
+ - **起服拒**:`MEMORY_SCOPE` / `MEMORY_SYNC_SCOPE` / run-local `--user` 写成 `userrepo:…` 或 `repo:…` 键 ⇒ 拒(项目层由本服务按任务派生,不能被点名);属主编码超过 64 字符 ⇒ 拒。
202
+ 这样写过的部署改成一把 `user:<主体>` 键或一个普通名字;
203
+ - **中心侧**:`POST /v1/memory/sync/:scope` 与 `GET /v1/memory/export` 放行主体**自己的**项目层(属主段 = 已验主体),别人的照旧 404(与其余拒绝同体);`/v1/adoption` 改名时项目层键的属主段一并改写
204
+ (SQL 文本变,双库都已覆盖);
205
+ - **仓搬家 / 改 origin**:`r` 档键随远端变;先 `git init` 用着、之后才加 origin 的项目,`p` 档条目在加了 origin 之后第一次跑任务时自动折进 `r` 档(常设,不随窗删);反方向(删掉 origin)不折。
206
+ 18. **SQL 后端(`DB_BACKEND=mysql` / `pg`)开了 `MODEL_CIRCUIT_BREAKER`:断路器键换形,写新表 `breaker_state`,退役表 `circuit_breaker` 起服删掉(持久数据;无需动手)**:
207
+ 键从 `<provider>:<模型>@<网关根原串>` 换成 `<provider>:<模型>@<路由身份摘要,24 hex>`(键里不再有 URL;原串会把网关根 query 里的凭据带进共享库)。
208
+ 新一代键写新表 `breaker_state`(起服由中央建表语句建,加法 DDL);一次性迁移把退役表 `circuit_breaker` 整只删掉(不按键形挑行 —— 旧形是开放串,任何认当前形的判据都有一种带凭据的旧行长得像它;
209
+ 启动读数 `retiredBreakerTablesDropped`),新表里的状态它一位不碰,第二次起服起零动作。升级后每条路由的断路器在新表里从关闭态开始计数(旧键没有读者,不做改写)。
210
+ 升级序与第 12 条同一个:先停光 ≤7.132.x 副本,再起本版。没停光时还在跑的旧副本写旧表会失败(建议性写穿,吞掉;旧副本连续 3 次失败打一行 warn `breaker_writethrough_degraded`,
211
+ `counter_flush_fail_streak{table="circuit_breaker"}` 升高),退回各自进程内的断路器;对着已迁移的库重启的旧副本先按旧 DDL 建回一只空的旧表、随即起服拒(`config.schema_mismatch`),
212
+ 那只空表下一次本版起服再删。新副本这只量表的 `table` 标签是 `breaker_state`(按 `table="circuit_breaker"` 配的告警改标签)。
213
+ 按 `circuit open for …` 文本里的 URL 认路由的告警规则,改读启动日志 `listening` 行 `brain.circuitBreakerRoutes` 的「摘要 → 路由展示串」对照表。
214
+ 19. **`settings.hooks`:组上的 `source`、command 条目上的 `plugin` / `args` 被读了;托管组跑在独立车道上(壳 / 嵌入方:不带这三只键、命令里也不引用 `${CLAUDE_PLUGIN_ROOT}` / `${CLAUDE_PLUGIN_DATA}` 的请求零动作)**:
215
+ 三只键此前被契约分类器静默剥掉,现在本服务在同一坐标上读,形错 ⇒ `400 request.field_invalid`(`detail.reason: "wire_key_invalid"`,`detail.key` 点名那只键)。
216
+ - **不带 `source`**:缺席 = 非托管;没有托管组时执行路径与 7.132.0 同一条,判词的读法有两处变了:① 工具输入超载荷上限(`tool_input` 超 262 144 字,hook 只拿到截断标记)时,
217
+ 非托管 `PreToolUse` hook 给的 `allow` / `updatedInput` 不再作数(同组别的条目与引擎门照常裁决 —— 同组另有可信放行 ⇒ 照放行,没有 ⇒ 由引擎门裁决,default 档上是问人;每次一行 warn `hook_verdict_not_honored` + 一帧 `hook_notice` / `hook_verdict_untrusted{lane:"unmanaged"}` 点名那一条,帧不断言这次调用怎么收场);
218
+ ② 同一组里前一条改写、后一条交回与输入同值的 `updatedInput` ⇒ 执行前一条的改写(此前后一条的回显把它盖回原输入)。判据只看载荷是否被截断、不看 hook 读了什么 —— 按工具名放行的 hook 遇到超大输入也一样不作数;这类调用要免问,写审批规则(`settings.permissions.allow` / 部署的放行规则),不靠 hook 的放行。要让组织策略的 hook 守得住,壳在见到能力位 `taskSettings.managedHookGroups` 之后给托管组标
219
+ `source: "managedPolicy"`(托管设置启用的插件标 `managedPlugin:<name>`):托管组在非托管之后、于最终输入上跑,跑不成 ⇒ `hook_notice` 第三族 `hook_managed_unrun`,判词不可信 ⇒ 第四族 `hook_verdict_untrusted{lane:"managed"}`,两种都让 `PreToolUse` 在没有否决时折 `ask`
220
+ (消费端按 `kind` 分派、未知 kind 别崩);托管车道多一只 120 s 的事件墙钟(只门新条目起跑),两车道共用引擎的 handler 预算 `HOOKS_TIMEOUT_MS`。
221
+ 托管 PreToolUse hook 匹配上的超大工具输入(`tool_input` 超载荷上限,hook 只拿到截断标记)在没有否决时变成问人。
222
+ - **exec 形 `args`**:此前被剥掉、只剩可执行名以 shell 形去跑;现在按 exec 形跑(不过 shell)。存量体里有 `args` 的续跑腿同样改按 exec 形跑 —— 这正是写的人的本意;若某条曾「碰巧能跑」只因参数丢了,改写那一条。
223
+ - **命令里引用 `${CLAUDE_PLUGIN_ROOT}` / `${CLAUDE_PLUGIN_DATA}` 而条目没带对应的 `plugin` / `dataDir`、同请求的 `settings.env` 也没给这个变量的非空值**:此前展开成空串照跑,现在这一条起不来(`spawn_failed`;托管组上即没跑成)。
224
+ 设置文件里抄来的插件 hook 删掉这一引用,或改由壳带 `plugin` 投(见能力位 `taskSettings.pluginHooks`)。请求 `settings.env` 给了同名变量的(非空)不在此列 —— 那一形有值,照常起跑(shell 形由 shell 展开、exec 形替成它),靠这条 env 给根的守卫 hook 行为不变。exec 形的替换一趟完成:替进去的值里若带别的占位字面,原样留着不再换(参照实现按序逐名替换,前一个名的值里的字面占位会被排在后面的名再换一次)。不带花括号的 `$CLAUDE_PLUGIN_ROOT` 不在判据里。与参照实现的差:参照实现的 hook 环境同样含 `settings.env`,仍按条目是否带插件上下文一律拒;本服务多读一层请求 `settings.env`,是为了 7.132.0 下靠它给根、确实有值能跑的配置继续能跑。
225
+ - **`plugin.options`** 只放非敏感值(请求体随任务落库,本服务不做 `${user_config.*}` 替换);带敏感选项的插件 hook 留在壳侧执行。
226
+ 20. **名单为空的单用户部署:审批队列不再把每个调用方当运维 —— 要当自己的运维写一行 `OPERATOR_SINGLE_USER=true`(行为变更)**:「谁是运维」只剩一条读法,空的 `OPERATOR_PRINCIPALS` 在每个运维面上都是
227
+ 「没有人是」。此前审批四个读面(`GET /v1/approvals`、`GET /v1/approvals/stream`、`GET /v1/assistant/inbox`、`GET /v1/assistant/tasks`)在名单为空时把每个调用方当运维(看全部主体的待批、`?owner=` 生效);
228
+ 升级后同一台部署上,带主体的调用方只看到自己的待批、不带主体的调用方只看到匿名卡(不带主体提交的任务停下的那几张 —— 正是决断口对它开放的那几张;主体名下的卡它看不到)、`?owner=` 不生效。起服时这一形打一行 warn `operator_undeclared_single_user`。**升级做法**(只对 `REQUIRE_PRINCIPAL` 未开、
229
+ `OPERATOR_PRINCIPALS` 为空的部署):
230
+ - 想保留修前的审批视图 ⇒ 加一行 `OPERATOR_SINGLE_USER=true`。它的意思是「这台单用户部署的每个调用方都是运维」,对全部运维面生效(审批队列之外,记忆运维口、配置目录、身份收编、排空这些此前在名单为空时答 `501` 的口也一并打开);
231
+ 没配服务凭据(`SERVICE_AUTH_TOKEN` 等)的部署上,能连上端口的都是运维 —— 要收窄先配凭据;
232
+ - 只想让某几个主体当运维 ⇒ 写 `OPERATOR_PRINCIPALS=<主体,…>`(二者只能选一,同时写起服拒);
233
+ - 不需要跨主体的审批视图(例:壳只发自己的主体、只看自己的待批)⇒ 无需动手。
234
+ `OPERATOR_SINGLE_USER=true` 与 `REQUIRE_PRINCIPAL=true` 同在也起服拒(多租部署用名单)。声明之后不带主体的调用方是运维、但没有身份可记:记「谁改的」的写面
235
+ (`PUT /v1/admin/memory-optout[/:principal]`)要带主体,否则 `401 auth.principal_required`。
236
+ 21. **隔离型车道(`e2b` / `k8s` / `local-docker`)上 `READ_FACE` 缺席时,读面缺省从 `roots` 变 `open`(行为变更;把宿主目录或共享卷挂进沙箱的部署升级前写 `READ_FACE=roots`)**:此前 `READ_FACE` 缺席时的缺省只按部署形分两种 ——
237
+ 单用户 ⇒ `open`,多租户 ⇒ 不铸、引擎默认 `roots`。现在车道契约行显式声明读面缺省:隔离型三车道 `open`,`host` / `ssh` / `adb` / `device` 一个字节不变;读的是**最终生效的车道**
238
+ (`config.d/remote-exec.json` 换车道之后按最终车道重派)。`READ_FACE` 显式值(env 或中心发布)永远胜,原样不动;单用户沙箱部署读面本来就是 `open`,只有 `GET /v1/diagnostics/wiring` 的 `readFace.source` 从 `posture` 变 `lane`。
239
+ **谁受影响**:把宿主目录(`hostPath` / bind mount)或共享卷挂进沙箱的多租部署 —— 那些宿主文件在 `roots` 面上本有强制问,`open` 面零问可读;读 `readFace.source` 的消费方(web-admin、运维脚本)要按开集处理新词 `lane`
240
+ (来源闭集五词,优先序 `env` > `center` > `lane` > `posture` > `engine-default`)。**谁受益**:团队沙箱上要 `auto` 连续干活的部署(不用再靠 web-admin 向导往 env 写 `READ_FACE=open` 那一行,向导里这一行随本版退为冗余)。
241
+ **做法**:要保留 `roots` ⇒ 升级前写 `READ_FACE=roots`(显式值恒赢);要放开读面又不想让那些挂载可读 ⇒ 给那些路径加读拒行 `READ_DENY_PATTERNS`(`open` 面上读拒表照样拦);升级后看诊断面的 `readFace.source: "lane"`(指路句带挂载告诫)
242
+ 与 boot 期 info 行 `config_knob_posture_derived`;没挂宿主目录的隔离型车道部署无需动手。
243
+ 22. **center 的 `runtimeCaps.allowBypassPermissions` / `allowAutoMode` 两键开始生效:组织关掉的模式由引擎折回 `default`(安全;行为变更)**:center 下发的 per-principal entitlement 里这两键此前被服务端丢掉 —— 组织在 web-admin 里关了 bypass,
244
+ 这个人提交 `permissionMode:"bypassPermissions"` 照样跑在 bypass 下;关 auto 只有 `runtimeCaps.autoMode:false` 一键管用。现在 `allowBypassPermissions:false` ⇒ 引擎的 bypass 拒位,`allowAutoMode:false` ⇒ 与 `autoMode:false` 同一只 auto 拒位
245
+ (两键任一为 `false` 即拒,另一键的 `true` 不覆盖;`true` / 缺席 = 不拒)。被拒的请求**不是 4xx**:受理照常,这条腿跑在 `default`,流上一帧 `engine_notice` `config.permission_mode_unavailable`(`detail.by:"operator_deny"`),
246
+ 实际模式见 `wiring_manifest.permissionMode`;两键的值不是布尔 ⇒ 这个 principal 的放大面整份 fail-closed;center 取数硬失败的降级项也多拒 bypass(降级窗最长约 10 秒,之后整份重抓)。
247
+ **谁受影响**:在 web-admin 里把这两键设成 `false` 的组织下请求 bypass / auto 的人 —— run 改跑 `default`(写会问);center 故障窗里请求 bypass 的 run 同样折回。已知残余:能力位 `taskWriteFaceOpen` 是部署级的,
248
+ 看不到 per-principal 的 bypass 拒,被拒的人读到的仍可能是 `true` ⇒ 壳读回执 / 通告,不要读能力位。**做法**:组织其实想让人用这两个模式 ⇒ 在 web-admin 把键改回 `true` 或删掉(升级前先看这两键现在设的是什么:此前设了不生效,升级后即生效);其余部署无需动手。
249
+ 23. **模式缺席的请求也问 `Workflow`(行为变更)**:本服务给动态工作流(`Workflow` 工具)的那一问由 settings 折叠按模式装,此前请求没带模式词(也没带 `settings.permissions.defaultMode`)时不装 ——
250
+ 引擎把缺席读成 `default`、写照问,而工作流不问。现在这条 run 挂得出 `Workflow`(请求开了自编排 `selfOrchestration: true`,部署也开着;单用户部署缺省开)就装这一问,不看模式:`default` / `auto` / `plan` / `acceptEdits` / 缺席 ⇒ 问
251
+ (`auto` 再交分类器),`dontAsk` ⇒ 由模式拒,`bypassPermissions` ⇒ 放行并披露(`tool_end.gate.disposition.released`,每个 run 每个(模式, 类)一条通告 `permission.ask_released_by_mode`;此前 bypass 下这一问根本不装,调用不经记录直接放行)。
252
+ **谁受影响**:开了自编排而不带模式词的调用方 —— 调 `Workflow` 时多一张卡;有活体审批席的部署上是一张卡,没有人可问(无审批席又无停驻,或同步请求无人附着又没开停驻)时这次调用被拒、写进转录;
253
+ 按通告条数断言的消费方(bypass 下调过 `Workflow` 的 run 多一条)。**做法**:不想被问 ⇒ 请求的 `settings.permissions.allow: ["Workflow"]`(引擎的 allow 层清得掉这一问),或对这一问点「本会话不再询问」;显式发模式词只改处置、不免问(`default` / `plan` / `acceptEdits` / `auto` 仍问,
254
+ `bypassPermissions` 放行并披露,`dontAsk` 由模式拒);不开自编排的调用方无需动手。
255
+ 24. **中心凭证换人:server 自己降到「无中心配置」档、当场拉取、通告两态(行为变更;`/health` 新增一键 `centerIdentityNotice`)**:此前同机换账号(凭据文件被改写成另一个人)之后,在用的中心配置仍是上一个人的,直到下一个 60 s 拍拉成;
256
+ 现在引擎读凭据文件时判出凭证身份与在用中心配置的身份不是同一个人 ⇒ server 把在用的中心配置降到「无中心配置」档(模型目录 / 缺省模型 / 限额 / 审批名单 / autonomy / 读面 / 中心提示词层等热面回 env 底,`GET /v1/models` 立刻是 env 的那一张),
257
+ 当场发起一次拉取,并铸通告 `center_identity_demoted`;新身份的候选落地后通告 `center_identity_landed`。拉取成功之前**不回退**到上一个人的任何东西(两个例外:降档没能降到底的组 —— 例如 env 的审批名单在这台部署上无处可服务 —— 活值仍是上一个人下发的,`centerIdentityNotice.retained` 点名这些组;降档自己失败,即 Runner 拒收 env 表 ⇒ 这一拍整体失败、不采用新身份的候选、不铸通告,按定时拍 / 下一次凭证读重试);拉取失败 ⇒ 停在降档档、通告停在 `demoted`、下一拍再拉。
258
+ **谁受影响**:① 依赖「新身份的候选到达前,上一个人的配置继续跑」的部署 —— 现在换人到新配置落地之间跑在 env 底上(在飞的 run 照旧,新任务用 env 模型 / env 限额),**没有 env 模型(`MODEL_ID` 缺席)的部署在这个窗口里没有可派发的模型**,
259
+ 中心不可达时窗口就是不可达多久;② 令牌里取不出 `sub` 的用户 JWT(身份是令牌自身摘要)—— 每次续期读成「换人」、降档 + 重拉一次(中心签发的 JWT 恒带 `sub`,不受影响);③ 读 `/health.configAppliedVersion` 的编排器 —— 降档那一代记为 version 0;
260
+ ④ 按 `config_env_set_but_ineffective` 配告警的运维 —— 降档后新身份第一份目录落地时这一行会再响一次。**不在射程内**:技能 / MCP 服务器表 / A2A / 场景仍是启动时那个人的,直到重启(`/health` 照旧据差异报 `restartRequired`)。
261
+ **做法**:没有开关、不留旧读法;按部署事实配上 `MODEL_ID`,让降档窗口里仍有模型可用;壳按 `/health.centerIdentityNotice` 的 `code` 转述「现在用的是基础配置」/「新账号的配置已换上」,`retained` 非空时那几组不适用这句冻结句,读 `retained`;不再靠重启引擎补偿;其余部署无需动手。
262
+ 25. **嵌入方(自建 `StoreBackend`、不走 `createStoreBackend` 的进程):`StoreBackend.orgDeliveryQuota()` 与 `StoreBackend.checkpointReadView()` 是必选成员(BREAKING,类型面;零别名)**:跨主体投递门的配额店(三张小时窗计数表的那一只店)
263
+ 挂在后端上,`StoreBackend` 多一个必选方法 `orgDeliveryQuota(): OrgDeliveryQuotaStore` —— 自建后端 tsc 红即通知。返回型 `OrgDeliveryQuotaStore`(`admitAttempt(fromScope, policy)` / `take(fromScope, toScope, policy)`,
264
+ 店读不出 / 写不进 ⇒ 抛,绝不当成放行)与参数型 `OrgDeliveryQuotaPolicy` 自本版从包根导出;经 `createStoreBackend()` 带起后端的嵌入方与部署零动作(SQL 后端起服自建三张配额表)。
265
+ 同一类:`StoreBackend.checkpointReadView()` 也是必选成员(BREAKING,类型面;零别名)—— 待决 checkpoint 的只读读口(审批账本留存读它列「还有哪些会话停驻着」,它不牵动任何别的店),返回型 `ReturnType<StoreBackend["checkpointReadView"]>`(只有 `listPendingSessionIds()`)。
266
+ 有 checkpoint 店的自建后端交与 `checkpoint()` 同一只店的读法;没有 checkpoint 店的自建后端交一只恒空读口 `() => ({ listPendingSessionIds: async () => [] })`。此前它是可选成员,漏实现在留存清扫里读成「没有停驻」(删除方向),现在是 tsc 红即通知;经 `createStoreBackend()` 带起后端的嵌入方零动作。
267
+ 26. **SQL 后端(`DB_BACKEND=mysql` / `pg`):收件箱里身份键过不了判官的存量行,起服一次性删掉(持久数据;无需动手)**:收件箱(跨会话信箱与 principal 收件箱)的键本版只有一只判官
268
+ (良构 Unicode、不含控制字符、UTF-8 ≤ 190 字节、scope 非空),判官拒的键没有箱 —— 每一只入口对它答「箱不在」,会话删除的打标 / 丢箱两步也不再碰它。7.132.x 及以前的
269
+ PostgreSQL 部署收下过主体 / 会话 handle 里带控制字符(HTAB 等)的箱(可信主体头与 JWT `sub` 都不拦这类串),那样的箱升级后谁都够不着。
270
+ - **自动(起服,窗内每次)**:三张收件箱表(`mailbox` / `mailbox_message` / `mailbox_tombstone`)里键过不了判官的行删掉,一只键整箱删(与会话删除丢箱同三句);
271
+ 条数进起动日志行 `one_time_migrations_applied` 的 `mailboxRejectedKeyRowsRemoved`(删了行时这一行是 warn,键一只都不进日志);第二次起服起是 0。
272
+ - **想先留底**:升级前自行导出收件箱表里键会被拒的行(含控制字符 / 含孤立代理 / UTF-8 超 190 字节 / 空 scope,两方言同判);迁移只删这些行、只在首次起服删一次。
273
+ - **不在这一步里**:MySQL 协议部署上主体带孤立代理、升级前写下的箱 —— 驱动早已把孤立代理换成 U+FFFD,库里的键与字面带 U+FFFD 的那只主体的键是同一串,判官收它,迁移不删。
274
+ - 回滚到 ≤7.132.x:零动作(删掉的行在本版下谁都够不着)。`DB_BACKEND=local`:不涉及(local 用引擎自己的文件信箱)。
275
+
10
276
  ## 7.132.0 —— 引擎 7.52.0 → 7.53.0 提货:升级前停驻的子代腿 / Skill 卡在认领前被拒(先排空:随包两条新判据)· `settings.hooks` 换成引擎的扩展注册链(`wiring_manifest.hooks[]` → `mods[]`、`HOOKS_TIMEOUT_MS` 新读法)· 执行车道静默切断换码 `liveness_no_output` · 凭据按值也扣 · 一枚运维通告码退役 · 清单 `prompt_assembled` 换成 v3、`prompt_constitution_total` 下线 · `settings.hooks` 的 matcher 编不过任一事件 400、受理总额度 `budget_exceeded` · 技能 frontmatter 读不了拒载、空正文条目不装 · 标题腿 fail-open 标签按成因族分 · 投递腿不再重投提交时的图 · k8s 车道加固(两处新的起服拒)· 请求体 `mcpServers` 列表级坏形整份 400、沙箱车道的受理拒各带机读码 · 升级前停驻问答的起服一次性迁移 · 宿主 CLI 与 `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 的凭据边界、`REMOTE_EXEC_HOME_DIR` 与实测家目录对证、中心鉴权桥的身份边界(安全)· 受理面拒句与拒体机读位 · 引擎收紧的会话规则与工具清单(放行侧近似名开跑前拒、规则名文法拒、存量会话规则行读不出即拒一切)· 递归读只按点名的根判(放宽;起服点名非锚定读拒行) · 子代工具清单近似名与存量会话规则孪生行的同步腿 200 + failed 改 400(码不变) · 一次性迁移 M17 遇读不出的 deny 行不改写、不盖戳 · 更正 7.131.0 第 8 条对请求体规则表的陈述(新拒的只有大小写孪生;文字更正) · 引擎 7.53.0:hook / 标题腿的 per-model 凭据绑首个发出的主机 · 请求体 `a2aPeers[].toolAxes` 与 MCP env / headers 两处收紧 · 任务流新帧 `compaction_started` 与几处随引擎变的 wire 值 · 中心提示层只有一种 wire 形 `{ schemaVersion: 2, artifact }`(web-admin 与本服务同窗升级,先中心后服务)· 场景名进 `promptBinding` · 品牌行由部署座 overlay 承载 · 「无持久记忆」披露由引擎渲染(委派子代不再带)· LKG 信封 5 · `Artifact(action:<词>)` 是规则(放行侧放宽)· 嵌入方 `snapshotBlobSqlCapBytes` → 读口 `snapshotBlobSqlCap { capBytes, source }`、`sqlEngineFacts` → `sqlEngine { dialect, facts }`(SQL 后端在场必填、值形起服判)(BREAKING)· `READ_DENY_BUILTIN_EXCLUDE` 写 `.npmrc` / `.pypirc` 起服拒
11
277
 
12
278
  1. **升级前先排空:7.131.x 停驻的子代腿与 Skill 卡,升级后续跑可能在认领前被拒**(零 DDL;卡留 pending,行留停驻)。引擎 7.52.0 在认领前按规范拼写读停驻行记下的工具名清单:
package/README.md CHANGED
@@ -106,7 +106,7 @@ MODEL_GATEWAY_BASEURL=https://api.deepseek.com MODEL_ID=deepseek-v4-flash \
106
106
  MODEL_API_KEY=<your-key> SERVICE_AUTH_TOKEN=<pick-one> \
107
107
  node node_modules/@sema-agent/server/dist/main.js # → :8090
108
108
 
109
- # B) container (zero local deps, anonymous pull)
109
+ # B) container (zero local deps, anonymous pull; ⚠ image publishing is paused — see "Image publishing paused" below)
110
110
  docker run -p 8090:8090 \
111
111
  -e MODEL_GATEWAY_BASEURL=https://api.deepseek.com -e MODEL_ID=deepseek-v4-flash \
112
112
  -e MODEL_API_KEY=<your-key> -e SERVICE_AUTH_TOKEN=<pick-one> \
@@ -127,6 +127,7 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
127
127
  - **Distribution coordinates**: npm = [`@sema-agent/server`](https://www.npmjs.com/package/@sema-agent/server)
128
128
  (public on npmjs) · images = `ghcr.io/sema-agent/sema-server` + `docker.io/claybobby/sema-server`
129
129
  (both public; `:latest` rolling, `:<sha>` pinned).
130
+ - **Image publishing paused**: Container images have been paused since 7.128.0; the npm package is the only release artifact; resumption will be announced separately.
130
131
  - **Library embedding** (package root, e.g. `createHttpServer` + your own `StoreBackend`): after
131
132
  `loadConfig()`, call `composeExecutionLane(config, ctx)` — the HTTP service and `run-local` both do. Since
132
133
  7.104.0 the execution-lane start refusals (`LEADER_ENABLED` on the host lane, a multi-tenant posture on a
@@ -135,12 +136,9 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
135
136
  Build-time tools (e.g. a catalog editor) read two allowlists from the package root instead of hand-copying them: `RETIRED_ENVS` (the retired-env
136
137
  tombstones) and, since 7.110.0, `CATALOG_ENTRY_HEADER_LANES` / `CATALOG_ENTRY_HEADER_NAMES` (+ type `CatalogEntryHeaderName`) — the closed allowlist of
137
138
  model-catalog entry `headers` and the API line that reads each name. Both are frozen, the very objects the server judges with.
138
- A shell or package that must know **before the engine starts** whether the model route would stop it imports `judgeModelRouteGap(env)`
139
- (pure; takes an env snapshot) from the package root: `{ gap: "endpoint_missing" | "lane_credential_missing" | "none" }`, plus `code` and the
140
- refusal sentence `reason` when there is a gap. It answers for the **env leg** — "with no catalog in charge, does this env start?" — and is the
141
- very judgment the start-up makes on the env model table, not a copy of it, so the reading and the refusal sentence are the same by construction.
142
- When a catalog is adopted the start-up judges the catalog table instead (env `MODEL_ID` does not serve), so a shell that predicts the refusal must
143
- know whether a catalog is coming. `none` says the route gap is absent, not that the engine will start (other invariants refuse with their own codes).
139
+ A shell that must know which model table a running engine serves, whether the catalog was adopted, and what the start-up route judge says, reads
140
+ `modelPlane` on `GET /v1/models` (`{ servedTable: "env" | "catalog", catalog: "absent" | "adopted" | "refused", refusalCode?, gap? }`) — it asks the server
141
+ instead of predicting, because the judge's inputs are facts of the serving process. It is answerable only once the engine is up; there is no pre-start probe.
144
142
  The start-up's own route judge runs **after** the catalog is applied, not in `loadConfig()`: a hand-built assembly calls `judgeServedModelRoute(config, { envTableIsPlaceholder })`
145
143
  (package root) once after its own config-source apply, like `composeExecutionLane`.
146
144
  - **Bundled binaries**: the package ships two `bin` entries — `run-local` (single-machine local
@@ -181,7 +179,8 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
181
179
  - **Sandbox package sources**: default = official upstreams (pypi/npmjs/crates.io/…). For
182
180
  deployments in mainland China set `SANDBOX_PKG_SOURCE=cn` (tuna/npmmirror/rsproxy/aliyun
183
181
  mirrors); for custom mirrors use `SANDBOX_PKG_SOURCE=custom` plus explicit
184
- `SEMA_*_MIRROR/INDEX/REGISTRY` URLs.
182
+ `SEMA_*_MIRROR/INDEX/REGISTRY` URLs. Those URLs land in the sandbox environment, where the model
183
+ can read them, so a URL carrying `user:pass@` is refused at startup — keep credentials out of the URL.
185
184
 
186
185
  ## Configuration
187
186
 
@@ -199,7 +198,7 @@ The server is configured entirely through environment variables. The most import
199
198
  | `SESSION_BACKEND` | `memory`* | `memory` / `mysql` (durable session center) / `auto`. *Defaults to durable when `DB_BACKEND` is explicitly `mysql`/`pg`. (`tidb` is a RETIRED public name — setting it refuses to boot; since 7.57.0 `GET /v1/config/catalog` also echoes the public word `mysql` instead of the internal `tidb` label) |
200
199
  | `REMOTE_EXEC` | unset | Sandbox execution lane: `host` / `local-docker` / `e2b` / `k8s` / `ssh` / `adb`; unset = in-process stub (with `CONFIG_PROVIDER=local` the default becomes `host`). Naming a lane without its required env (e.g. `e2b` without `E2B_API_KEY`) or an unrecognized value **refuses to start** — no silent downgrade to the host/in-process lane (fail-closed). Under `CONFIG_PROVIDER=local` a `config.d/remote-exec.json` **wins over** this env (deliberate: the file is the single-machine source of truth). Since 7.57.0 that preemption is **loud** — `remote_exec_lane_preempted_by_file` names the preempted lane, the effective one, and whether it is an **isolation downgrade** (an isolated lane replaced by a non-isolated one); a file naming a not-yet-wired isolated lane (`e2b`/`k8s`/`ssh`/`adb`) leaves the env lane in force and says so |
201
200
  | `SSH_HOST_FINGERPRINT` / `SSH_KNOWN_HOSTS` | unset | **SSH lane host-key verification** (`REMOTE_EXEC=ssh` only). `SSH_HOST_FINGERPRINT` = the host key's SHA256 base64 fingerprint (`SHA256:` prefix and `=` padding both optional); `SSH_KNOWN_HOSTS` = a path to a `known_hosts` file, matched literally on `host` / `[host]:port`. **Either one present ⇒ strict verification, a mismatch REFUSES the connection** (the error carries both fingerprints plus an `ssh-keyscan` line); both set ⇒ both must pass. **Both unset ⇒ a loud per-connection warning (`ssh_host_key_unverified`, man-in-the-middle risk) and the connection proceeds** — the deliberate posture for the batch-deploy lane, registered as a P-DEBT fail-open (`docs/FAIL-OPEN-CENSUS.md`). A malformed fingerprint or an unreadable `known_hosts` path **refuses to start**. Not supported in `known_hosts`, on purpose: hashed (`\|1\|…`) lines, wildcard patterns, `@cert-authority` — all skipped, so a host whose only entries are those is REFUSED (`@revoked` is honored and wins over any plain line, whatever the order) |
202
- | `HOOKS_TIMEOUT_MS` | unset (600000) | Time budget of each handler of the request `settings.hooks` registration (one event's run of the request's hook entries). Unset = 600000 ms — the bound this server runs hook processes under (one command's own timeout caps at 600 s); the engine's default for an extension (10 s) is not used. `0` is honored as written (a zero budget). The server's own two observer registrations (deny meter, tool trace) do not read it. A non-integer, negative, or above-`setTimeout`-ceiling (2147483647) value **refuses to start** |
201
+ | `HOOKS_TIMEOUT_MS` | unset (600000) | Time budget of each handler of the request `settings.hooks` registration (one event's run of the request's hook entries). Unset = 600000 ms — this is the engine's `budgetMs` for the registration (each handler's own time, one event's run of the request's hook entries); when the budget is spent, or the task is cancelled, the command hooks still running in that handler are stopped (SIGTERM, a short grace, then SIGKILL) — they no longer run on to their own `timeout`; the engine's default for an extension (10 s) is not used. `0` is honored as written (a zero budget). The server's own two observer registrations (deny meter, tool trace) do not read it. A non-integer, negative, or above-`setTimeout`-ceiling (2147483647) value **refuses to start** |
203
202
  | `CONFIG_PROVIDER` | unset | Config source: `local` (file-backed `config.d/`, single machine) / `remote` (registry control plane). Closed set, matched exactly (7.104.0+): any other value (wrong case, surrounding spaces) refuses to boot; empty = unset |
204
203
  | `DEFAULT_SCENARIO` | `code` | Default scenario when the request body names none; must be a scenario this deployment has (boot refuses otherwise) |
205
204
  | `SANDBOX_PKG_SOURCE` | `global` | Package sources inside sandboxes: `global` (official upstreams) / `cn` (China mirrors) / `custom` / `none` |
package/README.zh-CN.md CHANGED
@@ -95,7 +95,7 @@ MODEL_GATEWAY_BASEURL=https://api.deepseek.com MODEL_ID=deepseek-v4-flash \
95
95
  MODEL_API_KEY=<你的-key> SERVICE_AUTH_TOKEN=<自定> \
96
96
  node node_modules/@sema-agent/server/dist/main.js # → :8090
97
97
 
98
- # B) 容器(零依赖,匿名可拉)
98
+ # B) 容器(零依赖,匿名可拉;⚠️ 镜像已暂停发布,见下方「镜像暂停发布」)
99
99
  docker run -p 8090:8090 \
100
100
  -e MODEL_GATEWAY_BASEURL=https://api.deepseek.com -e MODEL_ID=deepseek-v4-flash \
101
101
  -e MODEL_API_KEY=<你的-key> -e SERVICE_AUTH_TOKEN=<自定> \
@@ -110,16 +110,16 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
110
110
  - **分发坐标**:npm = [`@sema-agent/server`](https://www.npmjs.com/package/@sema-agent/server)
111
111
  (npmjs 公开)· 镜像 = `ghcr.io/sema-agent/sema-server` + `docker.io/claybobby/sema-server`
112
112
  (均 public,`:latest` 滚动 / `:<sha>` 钉版)。
113
+ - **镜像暂停发布**:容器镜像自 7.128.0 起暂停发布,npm 包是唯一发布件;恢复另行通告。
113
114
  - **作为库嵌入**(包根导出,如 `createHttpServer` + 自建 `StoreBackend`):`loadConfig()` 之后调
114
115
  `composeExecutionLane(config, ctx)` —— HTTP 服务与 `run-local` 都这么做。7.104.0 起执行车道的几条拒启(host 车道上开
115
116
  `LEADER_ENABLED`、多租户姿态落在共享车道、device 车道缺耐久店)判在这一步,不在 `loadConfig()` 里;
116
117
  `assertExecutionLaneInvariants(config)` 是同一份判据,不做 `config.d/remote-exec.json` 覆写。
117
118
  构建期工具(如目录编辑页)从包根取两张表、不手抄:`RETIRED_ENVS`(退役 env 墓碑)与 7.110.0 起的 `CATALOG_ENTRY_HEADER_LANES` /
118
119
  `CATALOG_ENTRY_HEADER_NAMES`(+ 型 `CatalogEntryHeaderName`)—— 模型目录条目 `headers` 的闭集白名单及读每个名字的线路。两者都冻结,就是服务端自己判据用的那一只。
119
- 壳 / 包要在**引擎起来之前**知道模型路由会不会让它起不来,从包根调 `judgeModelRouteGap(env)`(纯函数,吃一份 env 快照):
120
- `{ gap: "endpoint_missing" | "lane_credential_missing" | "none" }`,有缺口时另带 `code` 与拒启句 `reason`。它答的是 **env 腿** ——「没有目录在管时,这份 env 起不起得来」——
121
- 就是起服对 env 模型表做的那一判(不是它的副本),所以读数与拒启句同源。目录被采纳时起服判的是目录表(env `MODEL_ID` 不服务),
122
- 壳要预判拒启得自己知道有没有目录要来。`none` 只说路由缺口不在,不担保起得来(别的不变量各自带码拒启)。
120
+ 壳要知道一台在跑的引擎服务的是哪张模型表、目录采纳了没有、起服路由判官怎么说,读 `GET /v1/models` 的 `modelPlane`
121
+ (`{ servedTable: "env" | "catalog", catalog: "absent" | "adopted" | "refused", refusalCode?, gap? }`)—— 问 server,不猜:判官的输入是服务进程的事实。
122
+ 只在引擎起来之后可答,没有起服前的预判口。
123
123
  起服自己的路由判官在**目录应用之后**判,不在 `loadConfig()` 里:自建装配在自己的配置源应用之后调一次包根的 `judgeServedModelRoute(config, { envTableIsPlaceholder })`(与 `composeExecutionLane` 同形)。
124
124
  - **随包二进制**:包内带两个 `bin` —— `run-local`(单机本地 runner)与
125
125
  `sema-up`(部署引导脚本)。
@@ -150,6 +150,7 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
150
150
  - **沙箱装包源**:缺省 = 官方源(pypi/npmjs/crates.io/…)。中国大陆部署配
151
151
  `SANDBOX_PKG_SOURCE=cn` 切国内镜像源(tuna/npmmirror/rsproxy/aliyun),自定义源用
152
152
  `SANDBOX_PKG_SOURCE=custom` + `SEMA_*_MIRROR/INDEX/REGISTRY` 显式 URL。
153
+ 这些 URL 会进沙箱环境(模型读得到):带 `user:pass@` 的地址起服即拒,凭据不要写进 URL。
153
154
 
154
155
  ## 配置
155
156
 
@@ -167,7 +168,7 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
167
168
  | `SESSION_BACKEND` | `memory`* | `memory` / `mysql`(durable 会话中心)/ `auto`。*显式 `DB_BACKEND=mysql/pg` 时默认转 durable。(`tidb` 是**退役公名**,设了拒启;7.57.0 起 `GET /v1/config/catalog` 的回显也归一成公名 `mysql`,不再吐内部标签 `tidb`) |
168
169
  | `REMOTE_EXEC` | 未设 | 沙箱执行通道:`host` / `local-docker` / `e2b` / `k8s` / `ssh` / `adb`;未设 = 进程内 stub(`CONFIG_PROVIDER=local` 时缺省转 `host`)。点名了通道但必需 env 不全(如 `e2b` 缺 `E2B_API_KEY`)或值不在闭集内 ⇒ **启动即拒**——不再静默降级到 host/进程内通道(fail-closed)。`CONFIG_PROVIDER=local` 下 `config.d/remote-exec.json` **压过**本 env(刻意:单机形的真源是那份文件);7.57.0 起这次抢占**响亮**——`remote_exec_lane_preempted_by_file` 点名被抢占的 lane、最终生效的 lane,以及它是不是一次**隔离降级**(隔离 lane 被换成不隔离的);文件点了尚未接线的隔离 lane(`e2b`/`k8s`/`ssh`/`adb`)时 env 腿照旧生效并说明 |
169
170
  | `SSH_HOST_FINGERPRINT` / `SSH_KNOWN_HOSTS` | 未设 | **SSH 通道主机密钥校验**(仅 `REMOTE_EXEC=ssh`)。前者 = 主机公钥的 SHA256 base64 指纹(`SHA256:` 前缀与 `=` 填充都可选);后者 = `known_hosts` 文件路径,按 `host` / `[host]:port` **逐字**匹配行。**任一在场 ⇒ 严格校验,不符即拒连**(拒因带两半指纹 + `ssh-keyscan` 取指纹指路一行);两只同时在场 ⇒ 合取(都要过)。**两只全缺席 ⇒ 每连接一条响亮 warn(`ssh_host_key_unverified`,中间人风险)后照常连** —— 批量部署通道的既定姿态,已登记为 P-DEBT fail-open(`docs/FAIL-OPEN-CENSUS.md`)。指纹拼错 / `known_hosts` 路径读不到 ⇒ **启动即拒**。`known_hosts` 里**刻意不支持**:hashed(`\|1\|…`)行、通配符 pattern、`@cert-authority` —— 一律跳过,于是只有这些条目的主机会被**拒连**(`@revoked` 照常生效,且无论写在哪一行都优先于普通匹配行) |
170
- | `HOOKS_TIMEOUT_MS` | 未设(600000) | 请求 `settings.hooks` 那张扩展注册**每个 handler** 的时间预算(一个事件跑一遍本请求的钩子条目)。未设 = 600000 ms —— 本服务跑钩子子进程的界(单条命令自己的超时上限即 600 s);不用引擎给扩展的缺省(10 s)。`0` **按字面生效**(零预算)。本服务自己的两张观察注册(拒绝计量 / 工具追踪)不读它。非整数 / 负数 / 超 `setTimeout` 上限(2147483647)⇒ **启动即拒** |
171
+ | `HOOKS_TIMEOUT_MS` | 未设(600000) | 请求 `settings.hooks` 那张扩展注册**每个 handler** 的时间预算(一个事件跑一遍本请求的钩子条目)。未设 = 600000 ms —— 这是引擎对这张注册的 `budgetMs`(每个 handler 自己的时间:一个事件跑一遍本请求的钩子条目);预算到、或任务被取消,这个 handler 里还在跑的命令钩子会被叫停(SIGTERM → 短宽限 → SIGKILL),不再跑到自己的 `timeout`;不用引擎给扩展的缺省(10 s)。`0` **按字面生效**(零预算)。本服务自己的两张观察注册(拒绝计量 / 工具追踪)不读它。非整数 / 负数 / 超 `setTimeout` 上限(2147483647)⇒ **启动即拒** |
171
172
  | `CONFIG_PROVIDER` | 未设 | 配置来源:`local`(单机文件 `config.d/`)/ `remote`(registry 控制面)。闭集、逐字比较(7.104.0 起):其余任何值(大小写不同、带首尾空白)拒启;空串 = 未设 |
172
173
  | `DEFAULT_SCENARIO` | `code` | 请求体未指定场景时的缺省场景;必须是本部署在册的场景名,否则拒启 |
173
174
  | `SANDBOX_PKG_SOURCE` | `global` | 沙箱内装包源:`global`(官方源)/ `cn`(国内镜像)/ `custom` / `none` |